Auto merge of #99925 - JohnTitor:rollup-4bt9ou3, r=JohnTitor
Rollup of 8 pull requests Successful merges: - #99227 (Fix thumbv4t-none-eabi frame pointer setting) - #99518 (Let-else: break out scopes when a let-else pattern fails to match) - #99671 (Suggest dereferencing index when trying to use a reference of usize as index) - #99831 (Add Fuchsia platform support documentation) - #99881 (fix ICE when computing codegen_fn_attrs on closure with non-fn parent) - #99888 (Streamline lint checking) - #99891 (Adjust an expr span to account for macros) - #99904 (Cleanup html whitespace) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
8f68c43ca6
36 changed files with 629 additions and 190 deletions
|
@ -15,7 +15,7 @@
|
|||
|
||||
use crate::ast::*;
|
||||
|
||||
use rustc_span::symbol::{Ident, Symbol};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::Span;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
|
@ -109,12 +109,7 @@ pub enum LifetimeCtxt {
|
|||
/// to monitor future changes to `Visitor` in case a new method with a
|
||||
/// new default implementation gets introduced.)
|
||||
pub trait Visitor<'ast>: Sized {
|
||||
fn visit_name(&mut self, _span: Span, _name: Symbol) {
|
||||
// Nothing to do.
|
||||
}
|
||||
fn visit_ident(&mut self, ident: Ident) {
|
||||
walk_ident(self, ident);
|
||||
}
|
||||
fn visit_ident(&mut self, _ident: Ident) {}
|
||||
fn visit_foreign_item(&mut self, i: &'ast ForeignItem) {
|
||||
walk_foreign_item(self, i)
|
||||
}
|
||||
|
@ -267,10 +262,6 @@ macro_rules! walk_list {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn walk_ident<'a, V: Visitor<'a>>(visitor: &mut V, ident: Ident) {
|
||||
visitor.visit_name(ident.span, ident.name);
|
||||
}
|
||||
|
||||
pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) {
|
||||
walk_list!(visitor, visit_item, &krate.items);
|
||||
walk_list!(visitor, visit_attribute, &krate.attrs);
|
||||
|
@ -315,11 +306,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
|
|||
visitor.visit_vis(&item.vis);
|
||||
visitor.visit_ident(item.ident);
|
||||
match item.kind {
|
||||
ItemKind::ExternCrate(orig_name) => {
|
||||
if let Some(orig_name) = orig_name {
|
||||
visitor.visit_name(item.span, orig_name);
|
||||
}
|
||||
}
|
||||
ItemKind::ExternCrate(_) => {}
|
||||
ItemKind::Use(ref use_tree) => visitor.visit_use_tree(use_tree, item.id, false),
|
||||
ItemKind::Static(ref typ, _, ref expr) | ItemKind::Const(_, ref typ, ref expr) => {
|
||||
visitor.visit_ty(typ);
|
||||
|
|
|
@ -16,9 +16,8 @@ impl NodeCounter {
|
|||
}
|
||||
|
||||
impl<'ast> Visitor<'ast> for NodeCounter {
|
||||
fn visit_ident(&mut self, ident: Ident) {
|
||||
fn visit_ident(&mut self, _ident: Ident) {
|
||||
self.count += 1;
|
||||
walk_ident(self, ident);
|
||||
}
|
||||
fn visit_foreign_item(&mut self, i: &ForeignItem) {
|
||||
self.count += 1;
|
||||
|
|
|
@ -90,9 +90,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
|
||||
fn visit_foreign_item(&mut self, it: &'a ast::ForeignItem) {
|
||||
self.with_lint_attrs(it.id, &it.attrs, |cx| {
|
||||
run_early_pass!(cx, check_foreign_item, it);
|
||||
ast_visit::walk_foreign_item(cx, it);
|
||||
run_early_pass!(cx, check_foreign_item_post, it);
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -104,7 +102,6 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
}
|
||||
|
||||
fn visit_anon_const(&mut self, c: &'a ast::AnonConst) {
|
||||
run_early_pass!(self, check_anon_const, c);
|
||||
self.check_id(c.id);
|
||||
ast_visit::walk_anon_const(self, c);
|
||||
}
|
||||
|
@ -154,22 +151,17 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
self.check_id(closure_id);
|
||||
}
|
||||
}
|
||||
|
||||
run_early_pass!(self, check_fn_post, fk, span, id);
|
||||
}
|
||||
|
||||
fn visit_variant_data(&mut self, s: &'a ast::VariantData) {
|
||||
run_early_pass!(self, check_struct_def, s);
|
||||
if let Some(ctor_hir_id) = s.ctor_id() {
|
||||
self.check_id(ctor_hir_id);
|
||||
}
|
||||
ast_visit::walk_struct_def(self, s);
|
||||
run_early_pass!(self, check_struct_def_post, s);
|
||||
}
|
||||
|
||||
fn visit_field_def(&mut self, s: &'a ast::FieldDef) {
|
||||
self.with_lint_attrs(s.id, &s.attrs, |cx| {
|
||||
run_early_pass!(cx, check_field_def, s);
|
||||
ast_visit::walk_field_def(cx, s);
|
||||
})
|
||||
}
|
||||
|
@ -178,7 +170,6 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
self.with_lint_attrs(v.id, &v.attrs, |cx| {
|
||||
run_early_pass!(cx, check_variant, v);
|
||||
ast_visit::walk_variant(cx, v);
|
||||
run_early_pass!(cx, check_variant_post, v);
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -203,7 +194,6 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
run_early_pass!(self, check_block, b);
|
||||
self.check_id(b.id);
|
||||
ast_visit::walk_block(self, b);
|
||||
run_early_pass!(self, check_block_post, b);
|
||||
}
|
||||
|
||||
fn visit_arm(&mut self, a: &'a ast::Arm) {
|
||||
|
@ -214,8 +204,6 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
}
|
||||
|
||||
fn visit_expr_post(&mut self, e: &'a ast::Expr) {
|
||||
run_early_pass!(self, check_expr_post, e);
|
||||
|
||||
// Explicitly check for lints associated with 'closure_id', since
|
||||
// it does not have a corresponding AST node
|
||||
match e.kind {
|
||||
|
@ -242,7 +230,6 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
}
|
||||
|
||||
fn visit_where_predicate(&mut self, p: &'a ast::WherePredicate) {
|
||||
run_early_pass!(self, check_where_predicate, p);
|
||||
ast_visit::walk_where_predicate(self, p);
|
||||
}
|
||||
|
||||
|
@ -256,23 +243,19 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
ast_visit::AssocCtxt::Trait => {
|
||||
run_early_pass!(cx, check_trait_item, item);
|
||||
ast_visit::walk_assoc_item(cx, item, ctxt);
|
||||
run_early_pass!(cx, check_trait_item_post, item);
|
||||
}
|
||||
ast_visit::AssocCtxt::Impl => {
|
||||
run_early_pass!(cx, check_impl_item, item);
|
||||
ast_visit::walk_assoc_item(cx, item, ctxt);
|
||||
run_early_pass!(cx, check_impl_item_post, item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_lifetime(&mut self, lt: &'a ast::Lifetime, _: ast_visit::LifetimeCtxt) {
|
||||
run_early_pass!(self, check_lifetime, lt);
|
||||
self.check_id(lt.id);
|
||||
}
|
||||
|
||||
fn visit_path(&mut self, p: &'a ast::Path, id: ast::NodeId) {
|
||||
run_early_pass!(self, check_path, p, id);
|
||||
self.check_id(id);
|
||||
ast_visit::walk_path(self, p);
|
||||
}
|
||||
|
|
|
@ -81,7 +81,6 @@ impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> {
|
|||
fn process_mod(&mut self, m: &'tcx hir::Mod<'tcx>, s: Span, n: hir::HirId) {
|
||||
lint_callback!(self, check_mod, m, s, n);
|
||||
hir_visit::walk_mod(self, m, n);
|
||||
lint_callback!(self, check_mod_post, m, s, n);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,7 +117,6 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
|
|||
|
||||
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
|
||||
self.with_lint_attrs(param.hir_id, |cx| {
|
||||
lint_callback!(cx, check_param, param);
|
||||
hir_visit::walk_param(cx, param);
|
||||
});
|
||||
}
|
||||
|
@ -151,7 +149,6 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
|
|||
cx.with_param_env(it.hir_id(), |cx| {
|
||||
lint_callback!(cx, check_foreign_item, it);
|
||||
hir_visit::walk_foreign_item(cx, it);
|
||||
lint_callback!(cx, check_foreign_item_post, it);
|
||||
});
|
||||
})
|
||||
}
|
||||
|
@ -193,7 +190,6 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
|
|||
let body = self.context.tcx.hir().body(body_id);
|
||||
lint_callback!(self, check_fn, fk, decl, body, span, id);
|
||||
hir_visit::walk_fn(self, fk, decl, body_id, span, id);
|
||||
lint_callback!(self, check_fn_post, fk, decl, body, span, id);
|
||||
self.context.enclosing_body = old_enclosing_body;
|
||||
self.context.cached_typeck_results.set(old_cached_typeck_results);
|
||||
}
|
||||
|
@ -208,7 +204,6 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
|
|||
) {
|
||||
lint_callback!(self, check_struct_def, s);
|
||||
hir_visit::walk_struct_def(self, s);
|
||||
lint_callback!(self, check_struct_def_post, s);
|
||||
}
|
||||
|
||||
fn visit_field_def(&mut self, s: &'tcx hir::FieldDef<'tcx>) {
|
||||
|
@ -227,7 +222,6 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
|
|||
self.with_lint_attrs(v.id, |cx| {
|
||||
lint_callback!(cx, check_variant, v);
|
||||
hir_visit::walk_variant(cx, v, g, item_id);
|
||||
lint_callback!(cx, check_variant_post, v);
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -237,14 +231,9 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
|
|||
}
|
||||
|
||||
fn visit_infer(&mut self, inf: &'tcx hir::InferArg) {
|
||||
lint_callback!(self, check_infer, inf);
|
||||
hir_visit::walk_inf(self, inf);
|
||||
}
|
||||
|
||||
fn visit_name(&mut self, sp: Span, name: Symbol) {
|
||||
lint_callback!(self, check_name, sp, name);
|
||||
}
|
||||
|
||||
fn visit_mod(&mut self, m: &'tcx hir::Mod<'tcx>, s: Span, n: hir::HirId) {
|
||||
if !self.context.only_module {
|
||||
self.process_mod(m, s, n);
|
||||
|
@ -280,7 +269,6 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
|
|||
}
|
||||
|
||||
fn visit_where_predicate(&mut self, p: &'tcx hir::WherePredicate<'tcx>) {
|
||||
lint_callback!(self, check_where_predicate, p);
|
||||
hir_visit::walk_where_predicate(self, p);
|
||||
}
|
||||
|
||||
|
@ -300,7 +288,6 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
|
|||
cx.with_param_env(trait_item.hir_id(), |cx| {
|
||||
lint_callback!(cx, check_trait_item, trait_item);
|
||||
hir_visit::walk_trait_item(cx, trait_item);
|
||||
lint_callback!(cx, check_trait_item_post, trait_item);
|
||||
});
|
||||
});
|
||||
self.context.generics = generics;
|
||||
|
@ -320,7 +307,6 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
|
|||
}
|
||||
|
||||
fn visit_lifetime(&mut self, lt: &'tcx hir::Lifetime) {
|
||||
lint_callback!(self, check_lifetime, lt);
|
||||
hir_visit::walk_lifetime(self, lt);
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ use rustc_middle::ty::TyCtxt;
|
|||
use rustc_session::lint::builtin::{
|
||||
BARE_TRAIT_OBJECTS, ELIDED_LIFETIMES_IN_PATHS, EXPLICIT_OUTLIVES_REQUIREMENTS,
|
||||
};
|
||||
use rustc_span::symbol::{Ident, Symbol};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::Span;
|
||||
|
||||
use array_into_iter::ArrayIntoIter;
|
||||
|
|
|
@ -5,23 +5,19 @@ use rustc_data_structures::sync;
|
|||
use rustc_hir as hir;
|
||||
use rustc_session::lint::builtin::HardwiredLints;
|
||||
use rustc_session::lint::LintPass;
|
||||
use rustc_span::symbol::{Ident, Symbol};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::Span;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! late_lint_methods {
|
||||
($macro:path, $args:tt, [$hir:tt]) => (
|
||||
$macro!($args, [$hir], [
|
||||
fn check_param(a: &$hir hir::Param<$hir>);
|
||||
fn check_body(a: &$hir hir::Body<$hir>);
|
||||
fn check_body_post(a: &$hir hir::Body<$hir>);
|
||||
fn check_name(a: Span, b: Symbol);
|
||||
fn check_crate();
|
||||
fn check_crate_post();
|
||||
fn check_mod(a: &$hir hir::Mod<$hir>, b: Span, c: hir::HirId);
|
||||
fn check_mod_post(a: &$hir hir::Mod<$hir>, b: Span, c: hir::HirId);
|
||||
fn check_foreign_item(a: &$hir hir::ForeignItem<$hir>);
|
||||
fn check_foreign_item_post(a: &$hir hir::ForeignItem<$hir>);
|
||||
fn check_item(a: &$hir hir::Item<$hir>);
|
||||
fn check_item_post(a: &$hir hir::Item<$hir>);
|
||||
fn check_local(a: &$hir hir::Local<$hir>);
|
||||
|
@ -33,11 +29,8 @@ macro_rules! late_lint_methods {
|
|||
fn check_expr(a: &$hir hir::Expr<$hir>);
|
||||
fn check_expr_post(a: &$hir hir::Expr<$hir>);
|
||||
fn check_ty(a: &$hir hir::Ty<$hir>);
|
||||
fn check_infer(a: &$hir hir::InferArg);
|
||||
fn check_generic_arg(a: &$hir hir::GenericArg<$hir>);
|
||||
fn check_generic_param(a: &$hir hir::GenericParam<$hir>);
|
||||
fn check_generics(a: &$hir hir::Generics<$hir>);
|
||||
fn check_where_predicate(a: &$hir hir::WherePredicate<$hir>);
|
||||
fn check_poly_trait_ref(a: &$hir hir::PolyTraitRef<$hir>, b: hir::TraitBoundModifier);
|
||||
fn check_fn(
|
||||
a: rustc_hir::intravisit::FnKind<$hir>,
|
||||
|
@ -45,23 +38,12 @@ macro_rules! late_lint_methods {
|
|||
c: &$hir hir::Body<$hir>,
|
||||
d: Span,
|
||||
e: hir::HirId);
|
||||
fn check_fn_post(
|
||||
a: rustc_hir::intravisit::FnKind<$hir>,
|
||||
b: &$hir hir::FnDecl<$hir>,
|
||||
c: &$hir hir::Body<$hir>,
|
||||
d: Span,
|
||||
e: hir::HirId
|
||||
);
|
||||
fn check_trait_item(a: &$hir hir::TraitItem<$hir>);
|
||||
fn check_trait_item_post(a: &$hir hir::TraitItem<$hir>);
|
||||
fn check_impl_item(a: &$hir hir::ImplItem<$hir>);
|
||||
fn check_impl_item_post(a: &$hir hir::ImplItem<$hir>);
|
||||
fn check_struct_def(a: &$hir hir::VariantData<$hir>);
|
||||
fn check_struct_def_post(a: &$hir hir::VariantData<$hir>);
|
||||
fn check_field_def(a: &$hir hir::FieldDef<$hir>);
|
||||
fn check_variant(a: &$hir hir::Variant<$hir>);
|
||||
fn check_variant_post(a: &$hir hir::Variant<$hir>);
|
||||
fn check_lifetime(a: &$hir hir::Lifetime);
|
||||
fn check_path(a: &$hir hir::Path<$hir>, b: hir::HirId);
|
||||
fn check_attribute(a: &$hir ast::Attribute);
|
||||
|
||||
|
@ -161,44 +143,25 @@ macro_rules! early_lint_methods {
|
|||
fn check_ident(a: Ident);
|
||||
fn check_crate(a: &ast::Crate);
|
||||
fn check_crate_post(a: &ast::Crate);
|
||||
fn check_foreign_item(a: &ast::ForeignItem);
|
||||
fn check_foreign_item_post(a: &ast::ForeignItem);
|
||||
fn check_item(a: &ast::Item);
|
||||
fn check_item_post(a: &ast::Item);
|
||||
fn check_local(a: &ast::Local);
|
||||
fn check_block(a: &ast::Block);
|
||||
fn check_block_post(a: &ast::Block);
|
||||
fn check_stmt(a: &ast::Stmt);
|
||||
fn check_arm(a: &ast::Arm);
|
||||
fn check_pat(a: &ast::Pat);
|
||||
fn check_anon_const(a: &ast::AnonConst);
|
||||
fn check_pat_post(a: &ast::Pat);
|
||||
fn check_expr(a: &ast::Expr);
|
||||
fn check_expr_post(a: &ast::Expr);
|
||||
fn check_ty(a: &ast::Ty);
|
||||
fn check_generic_arg(a: &ast::GenericArg);
|
||||
fn check_generic_param(a: &ast::GenericParam);
|
||||
fn check_generics(a: &ast::Generics);
|
||||
fn check_where_predicate(a: &ast::WherePredicate);
|
||||
fn check_poly_trait_ref(a: &ast::PolyTraitRef,
|
||||
b: &ast::TraitBoundModifier);
|
||||
fn check_fn(a: rustc_ast::visit::FnKind<'_>, c: Span, d_: ast::NodeId);
|
||||
fn check_fn_post(
|
||||
a: rustc_ast::visit::FnKind<'_>,
|
||||
c: Span,
|
||||
d: ast::NodeId
|
||||
);
|
||||
fn check_trait_item(a: &ast::AssocItem);
|
||||
fn check_trait_item_post(a: &ast::AssocItem);
|
||||
fn check_impl_item(a: &ast::AssocItem);
|
||||
fn check_impl_item_post(a: &ast::AssocItem);
|
||||
fn check_struct_def(a: &ast::VariantData);
|
||||
fn check_struct_def_post(a: &ast::VariantData);
|
||||
fn check_field_def(a: &ast::FieldDef);
|
||||
fn check_variant(a: &ast::Variant);
|
||||
fn check_variant_post(a: &ast::Variant);
|
||||
fn check_lifetime(a: &ast::Lifetime);
|
||||
fn check_path(a: &ast::Path, b: ast::NodeId);
|
||||
fn check_attribute(a: &ast::Attribute);
|
||||
fn check_mac_def(a: &ast::MacroDef, b: ast::NodeId);
|
||||
fn check_mac(a: &ast::MacCall);
|
||||
|
|
|
@ -132,6 +132,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
initializer_span,
|
||||
else_block,
|
||||
visibility_scope,
|
||||
*remainder_scope,
|
||||
remainder_span,
|
||||
pattern,
|
||||
)
|
||||
|
|
|
@ -2282,49 +2282,55 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
initializer_span: Span,
|
||||
else_block: &Block,
|
||||
visibility_scope: Option<SourceScope>,
|
||||
remainder_scope: region::Scope,
|
||||
remainder_span: Span,
|
||||
pattern: &Pat<'tcx>,
|
||||
) -> BlockAnd<()> {
|
||||
let scrutinee = unpack!(block = self.lower_scrutinee(block, init, initializer_span));
|
||||
let pat = Pat { ty: init.ty, span: else_block.span, kind: Box::new(PatKind::Wild) };
|
||||
let mut wildcard = Candidate::new(scrutinee.clone(), &pat, false);
|
||||
self.declare_bindings(
|
||||
visibility_scope,
|
||||
remainder_span,
|
||||
pattern,
|
||||
ArmHasGuard(false),
|
||||
Some((None, initializer_span)),
|
||||
);
|
||||
let mut candidate = Candidate::new(scrutinee.clone(), pattern, false);
|
||||
let fake_borrow_temps = self.lower_match_tree(
|
||||
block,
|
||||
initializer_span,
|
||||
pattern.span,
|
||||
false,
|
||||
&mut [&mut candidate, &mut wildcard],
|
||||
);
|
||||
// This block is for the matching case
|
||||
let matching = self.bind_pattern(
|
||||
self.source_info(pattern.span),
|
||||
candidate,
|
||||
None,
|
||||
&fake_borrow_temps,
|
||||
initializer_span,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
// This block is for the failure case
|
||||
let failure = self.bind_pattern(
|
||||
self.source_info(else_block.span),
|
||||
wildcard,
|
||||
None,
|
||||
&fake_borrow_temps,
|
||||
initializer_span,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let (matching, failure) = self.in_if_then_scope(remainder_scope, |this| {
|
||||
let scrutinee = unpack!(block = this.lower_scrutinee(block, init, initializer_span));
|
||||
let pat = Pat { ty: init.ty, span: else_block.span, kind: Box::new(PatKind::Wild) };
|
||||
let mut wildcard = Candidate::new(scrutinee.clone(), &pat, false);
|
||||
this.declare_bindings(
|
||||
visibility_scope,
|
||||
remainder_span,
|
||||
pattern,
|
||||
ArmHasGuard(false),
|
||||
Some((None, initializer_span)),
|
||||
);
|
||||
let mut candidate = Candidate::new(scrutinee.clone(), pattern, false);
|
||||
let fake_borrow_temps = this.lower_match_tree(
|
||||
block,
|
||||
initializer_span,
|
||||
pattern.span,
|
||||
false,
|
||||
&mut [&mut candidate, &mut wildcard],
|
||||
);
|
||||
// This block is for the matching case
|
||||
let matching = this.bind_pattern(
|
||||
this.source_info(pattern.span),
|
||||
candidate,
|
||||
None,
|
||||
&fake_borrow_temps,
|
||||
initializer_span,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
// This block is for the failure case
|
||||
let failure = this.bind_pattern(
|
||||
this.source_info(else_block.span),
|
||||
wildcard,
|
||||
None,
|
||||
&fake_borrow_temps,
|
||||
initializer_span,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
this.break_for_else(failure, remainder_scope, this.source_info(initializer_span));
|
||||
matching.unit()
|
||||
});
|
||||
|
||||
// This place is not really used because this destination place
|
||||
// should never be used to take values at the end of the failure
|
||||
// block.
|
||||
|
|
|
@ -690,7 +690,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}
|
||||
drops.add_entry(block, drop_idx);
|
||||
|
||||
// `build_drop_tree` doesn't have access to our source_info, so we
|
||||
// `build_drop_trees` doesn't have access to our source_info, so we
|
||||
// create a dummy terminator now. `TerminatorKind::Resume` is used
|
||||
// because MIR type checking will panic if it hasn't been overwritten.
|
||||
self.cfg.terminate(block, source_info, TerminatorKind::Resume);
|
||||
|
@ -722,7 +722,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}
|
||||
drops.add_entry(block, drop_idx);
|
||||
|
||||
// `build_drop_tree` doesn't have access to our source_info, so we
|
||||
// `build_drop_trees` doesn't have access to our source_info, so we
|
||||
// create a dummy terminator now. `TerminatorKind::Resume` is used
|
||||
// because MIR type checking will panic if it hasn't been overwritten.
|
||||
self.cfg.terminate(block, source_info, TerminatorKind::Resume);
|
||||
|
|
|
@ -4,11 +4,21 @@
|
|||
//!
|
||||
//! Please ping @Lokathor if changes are needed.
|
||||
//!
|
||||
//! This target profile assumes that you have the ARM binutils in your path (specifically the linker, `arm-none-eabi-ld`). They can be obtained for free for all major OSes from the ARM developer's website, and they may also be available in your system's package manager. Unfortunately, the standard linker that Rust uses (`lld`) only supports as far back as `ARMv5TE`, so we must use the GNU `ld` linker.
|
||||
//! This target profile assumes that you have the ARM binutils in your path
|
||||
//! (specifically the linker, `arm-none-eabi-ld`). They can be obtained for free
|
||||
//! for all major OSes from the ARM developer's website, and they may also be
|
||||
//! available in your system's package manager. Unfortunately, the standard
|
||||
//! linker that Rust uses (`lld`) only supports as far back as `ARMv5TE`, so we
|
||||
//! must use the GNU `ld` linker.
|
||||
//!
|
||||
//! **Important:** This target profile **does not** specify a linker script. You just get the default link script when you build a binary for this target. The default link script is very likely wrong, so you should use `-Clink-arg=-Tmy_script.ld` to override that with a correct linker script.
|
||||
//! **Important:** This target profile **does not** specify a linker script. You
|
||||
//! just get the default link script when you build a binary for this target.
|
||||
//! The default link script is very likely wrong, so you should use
|
||||
//! `-Clink-arg=-Tmy_script.ld` to override that with a correct linker script.
|
||||
|
||||
use crate::spec::{cvs, LinkerFlavor, Target, TargetOptions};
|
||||
use crate::spec::{
|
||||
cvs, FramePointer, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions,
|
||||
};
|
||||
|
||||
pub fn target() -> Target {
|
||||
Target {
|
||||
|
@ -39,6 +49,14 @@ pub fn target() -> Target {
|
|||
// minimum extra features, these cannot be disabled via -C
|
||||
features: "+soft-float,+strict-align".into(),
|
||||
|
||||
panic_strategy: PanicStrategy::Abort,
|
||||
relocation_model: RelocModel::Static,
|
||||
// suggested from thumb_base, rust-lang/rust#44993.
|
||||
emit_debug_gdb_scripts: false,
|
||||
// suggested from thumb_base, with no-os gcc/clang use 8-bit enums
|
||||
c_enum_min_bits: 8,
|
||||
frame_pointer: FramePointer::MayOmit,
|
||||
|
||||
main_needs_argc_argv: false,
|
||||
|
||||
// don't have atomic compare-and-swap
|
||||
|
|
|
@ -531,6 +531,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
self.suggest_floating_point_literal(&obligation, &mut err, &trait_ref);
|
||||
self.suggest_dereferencing_index(&obligation, &mut err, trait_predicate);
|
||||
let mut suggested =
|
||||
self.suggest_dereferences(&obligation, &mut err, trait_predicate);
|
||||
suggested |= self.suggest_fn_call(&obligation, &mut err, trait_predicate);
|
||||
|
|
|
@ -320,6 +320,13 @@ pub trait InferCtxtExt<'tcx> {
|
|||
err: &mut Diagnostic,
|
||||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
);
|
||||
|
||||
fn suggest_dereferencing_index(
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
err: &mut Diagnostic,
|
||||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
);
|
||||
}
|
||||
|
||||
fn predicate_constraint(generics: &hir::Generics<'_>, pred: String) -> (Span, String) {
|
||||
|
@ -2895,6 +2902,27 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn suggest_dereferencing_index(
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
err: &mut Diagnostic,
|
||||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
) {
|
||||
if let ObligationCauseCode::ImplDerivedObligation(_) = obligation.cause.code()
|
||||
&& self.tcx.is_diagnostic_item(sym::SliceIndex, trait_pred.skip_binder().trait_ref.def_id)
|
||||
&& let ty::Slice(_) = trait_pred.skip_binder().trait_ref.substs.type_at(1).kind()
|
||||
&& let ty::Ref(_, inner_ty, _) = trait_pred.skip_binder().self_ty().kind()
|
||||
&& let ty::Uint(ty::UintTy::Usize) = inner_ty.kind()
|
||||
{
|
||||
err.span_suggestion_verbose(
|
||||
obligation.cause.span.shrink_to_lo(),
|
||||
"dereference this index",
|
||||
'*',
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Collect all the returned expressions within the input expression.
|
||||
|
|
|
@ -39,8 +39,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let scrut_diverges = self.diverges.replace(Diverges::Maybe);
|
||||
|
||||
// #55810: Type check patterns first so we get types for all bindings.
|
||||
let scrut_span = scrut.span.find_ancestor_inside(expr.span).unwrap_or(scrut.span);
|
||||
for arm in arms {
|
||||
self.check_pat_top(&arm.pat, scrutinee_ty, Some(scrut.span), true);
|
||||
self.check_pat_top(&arm.pat, scrutinee_ty, Some(scrut_span), true);
|
||||
}
|
||||
|
||||
// Now typecheck the blocks.
|
||||
|
|
|
@ -2648,6 +2648,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
Some((index_ty, element_ty)) => {
|
||||
// two-phase not needed because index_ty is never mutable
|
||||
self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No);
|
||||
self.select_obligations_where_possible(false, |errors| {
|
||||
self.point_at_index_if_possible(errors, idx.span)
|
||||
});
|
||||
element_ty
|
||||
}
|
||||
None => {
|
||||
|
@ -2691,6 +2694,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn point_at_index_if_possible(
|
||||
&self,
|
||||
errors: &mut Vec<traits::FulfillmentError<'tcx>>,
|
||||
span: Span,
|
||||
) {
|
||||
for error in errors {
|
||||
match error.obligation.predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Trait(predicate)
|
||||
if self.tcx.is_diagnostic_item(sym::SliceIndex, predicate.trait_ref.def_id) => {
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
error.obligation.cause.span = span;
|
||||
}
|
||||
}
|
||||
|
||||
fn check_expr_yield(
|
||||
&self,
|
||||
value: &'tcx hir::Expr<'tcx>,
|
||||
|
|
|
@ -1234,7 +1234,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Does the expected pattern type originate from an expression and what is the span?
|
||||
let (origin_expr, ty_span) = match (decl.ty, decl.init) {
|
||||
(Some(ty), _) => (false, Some(ty.span)), // Bias towards the explicit user type.
|
||||
(_, Some(init)) => (true, Some(init.span)), // No explicit type; so use the scrutinee.
|
||||
(_, Some(init)) => {
|
||||
(true, Some(init.span.find_ancestor_inside(decl.span).unwrap_or(init.span)))
|
||||
} // No explicit type; so use the scrutinee.
|
||||
_ => (false, None), // We have `let $pat;`, so the expected type is unconstrained.
|
||||
};
|
||||
|
||||
|
|
|
@ -3165,9 +3165,11 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
|
|||
// #73631: closures inherit `#[target_feature]` annotations
|
||||
if tcx.features().target_feature_11 && tcx.is_closure(did.to_def_id()) {
|
||||
let owner_id = tcx.parent(did.to_def_id());
|
||||
codegen_fn_attrs
|
||||
.target_features
|
||||
.extend(tcx.codegen_fn_attrs(owner_id).target_features.iter().copied())
|
||||
if tcx.def_kind(owner_id).has_codegen_attrs() {
|
||||
codegen_fn_attrs
|
||||
.target_features
|
||||
.extend(tcx.codegen_fn_attrs(owner_id).target_features.iter().copied());
|
||||
}
|
||||
}
|
||||
|
||||
// If a function uses #[target_feature] it can't be inlined into general
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
- [armv6k-nintendo-3ds](platform-support/armv6k-nintendo-3ds.md)
|
||||
- [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md)
|
||||
- [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md)
|
||||
- [\*-fuchsia](platform-support/fuchsia.md)
|
||||
- [\*-kmc-solid_\*](platform-support/kmc-solid.md)
|
||||
- [m68k-unknown-linux-gnu](platform-support/m68k-unknown-linux-gnu.md)
|
||||
- [mips64-openwrt-linux-musl](platform-support/mips64-openwrt-linux-musl.md)
|
||||
|
|
295
src/doc/rustc/src/platform-support/fuchsia.md
Normal file
295
src/doc/rustc/src/platform-support/fuchsia.md
Normal file
|
@ -0,0 +1,295 @@
|
|||
# `aarch64-fuchsia` and `x86_64-fuchsia`
|
||||
|
||||
**Tier: 2**
|
||||
|
||||
[Fuchsia] is a modern open source operating system that's simple, secure,
|
||||
updatable, and performant.
|
||||
|
||||
[Fuchsia]: https://fuchsia.dev/
|
||||
|
||||
## Target maintainers
|
||||
|
||||
The [Fuchsia team]:
|
||||
|
||||
[Fuchsia team]: https://team-api.infra.rust-lang.org/v1/teams/fuchsia.json
|
||||
|
||||
- Tyler Mandry ([@tmandry](https://github.com/tmandry))
|
||||
- Dan Johnson ([@computerdruid](https://github.com/computerdruid))
|
||||
- David Koloski ([@djkoloski](https://github.com/djkoloski))
|
||||
- Andrew Pollack ([@andrewpollack](https://github.com/andrewpollack))
|
||||
- Joseph Ryan ([@P1n3appl3](https://github.com/P1n3appl3))
|
||||
|
||||
As the team evolves over time, the specific members listed here may differ from
|
||||
the members reported by the API. The API should be considered to be
|
||||
authoritative if this occurs. Instead of pinging individual members, use
|
||||
`@rustbot ping fuchsia` to contact the team on GitHub.
|
||||
|
||||
## Requirements
|
||||
|
||||
This target is cross-compiled from a host environment. Development may be done
|
||||
from the [source tree] or using the Fuchsia SDK.
|
||||
|
||||
[source tree]: https://fuchsia.dev/fuchsia-src/get-started/learn/build
|
||||
|
||||
Fuchsia targets support std and follow the `sysv64` calling convention on
|
||||
x86_64. Fuchsia binaries use the ELF file format.
|
||||
|
||||
## Building the target
|
||||
|
||||
Before building Rust for Fuchsia, you'll need a clang toolchain that supports
|
||||
Fuchsia as well. A recent version (14+) of clang should be sufficient to compile
|
||||
Rust for Fuchsia.
|
||||
|
||||
You'll also need a recent copy of the [Fuchsia SDK], which provides the tools
|
||||
and binaries required to build and link programs for Fuchsia.
|
||||
|
||||
[Fuchsia SDK]: https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core
|
||||
|
||||
x86-64 and AArch64 Fuchsia targets can be enabled using the following
|
||||
configuration.
|
||||
|
||||
In `config.toml`, add:
|
||||
|
||||
```toml
|
||||
[build]
|
||||
target = ["<host_platform>", "aarch64-fuchsia", "x86_64-fuchsia"]
|
||||
|
||||
[target.x86_64-fuchsia]
|
||||
llvm-libunwind = "in-tree"
|
||||
|
||||
[target.aarch64-fuchsia]
|
||||
llvm-libunwind = "in-tree"
|
||||
```
|
||||
|
||||
Additionally, the following environment variables must be configured (for
|
||||
example, using a script like `config-env.sh`):
|
||||
|
||||
```sh
|
||||
# Configure this environment variable to be the path to the downloaded SDK
|
||||
export SDK_PATH="<SDK path goes here>"
|
||||
|
||||
export CFLAGS_aarch64_fuchsia="--target=aarch64-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -I${SDK_PATH}/pkg/fdio/include"
|
||||
export CXXFLAGS_aarch64_fuchsia="--target=aarch64-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -I${SDK_PATH}/pkg/fdio/include"
|
||||
export LDFLAGS_aarch64_fuchsia="--target=aarch64-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -L${SDK_PATH}/arch/arm64/lib"
|
||||
export CARGO_TARGET_AARCH64_FUCHSIA_RUSTFLAGS="-C link-arg=--sysroot=${SDK_PATH}/arch/arm64/sysroot -Lnative=${SDK_PATH}/arch/arm64/sysroot/lib -Lnative=${SDK_PATH}/arch/arm64/lib"
|
||||
export CFLAGS_x86_64_fuchsia="--target=x86_64-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -I${SDK_PATH}/pkg/fdio/include"
|
||||
export CXXFLAGS_x86_64_fuchsia="--target=x86_64-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -I${SDK_PATH}/pkg/fdio/include"
|
||||
export LDFLAGS_x86_64_fuchsia="--target=x86_64-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -L${SDK_PATH}/arch/x64/lib"
|
||||
export CARGO_TARGET_X86_64_FUCHSIA_RUSTFLAGS="-C link-arg=--sysroot=${SDK_PATH}/arch/x64/sysroot -Lnative=${SDK_PATH}/arch/x64/sysroot/lib -Lnative=${SDK_PATH}/arch/x64/lib"
|
||||
```
|
||||
|
||||
These can be run together in a shell environment by executing
|
||||
`(source config-env.sh && ./x.py install)`.
|
||||
|
||||
## Building Rust programs
|
||||
|
||||
After compiling Rust binaries, you'll need to build a component, package it, and
|
||||
serve it to a Fuchsia device or emulator. All of this can be done using the
|
||||
Fuchsia SDK.
|
||||
|
||||
As an example, we'll compile and run this simple program on a Fuchsia emulator:
|
||||
|
||||
**`hello_fuchsia.rs`**
|
||||
```rust
|
||||
fn main() {
|
||||
println!("Hello Fuchsia!");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
assert_eq!(2 + 2, 4);
|
||||
}
|
||||
```
|
||||
|
||||
Create a new file named `hello_fuchsia.rs` and fill out its contents with that
|
||||
code.
|
||||
|
||||
### Create a package
|
||||
|
||||
On Fuchsia, a package is the unit of distribution for software. We'll need to
|
||||
create a new package directory where we will place files like our finished
|
||||
binary and any data it may need. The working directory will have this layout:
|
||||
|
||||
```txt
|
||||
hello_fuchsia.rs
|
||||
hello_fuchsia.cml
|
||||
package
|
||||
┣━ bin
|
||||
┃ ┗━ hello_fuchsia
|
||||
┣━ meta
|
||||
┃ ┣━ package
|
||||
┃ ┗━ hello_fuchsia.cm
|
||||
┗━ hello_fuchsia.manifest
|
||||
```
|
||||
|
||||
Make the `package`, `package/bin`, and `package/meta` directories and create the
|
||||
following files inside:
|
||||
|
||||
**`package/meta/package`**
|
||||
```json
|
||||
{"name":"hello_fuchsia","version":0}
|
||||
```
|
||||
|
||||
The `package` file describes our package's name and version number. Every
|
||||
package must contain one.
|
||||
|
||||
**`package/hello_fuchsia.manifest`**
|
||||
```txt
|
||||
bin/hello_fuchsia=package/bin/hello_fuchsia
|
||||
lib/ld.so.1=<SDK_PATH>/arch/x64/sysroot/dist/lib/ld.so.1
|
||||
lib/libfdio.so=<SDK_PATH>/arch/x64/dist/libfdio.so
|
||||
meta/package=package/meta/package
|
||||
meta/hello_fuchsia.cm=package/meta/hello_fuchsia.cm
|
||||
```
|
||||
|
||||
*Note: Relative manifest paths are resolved starting from the working directory
|
||||
of `pm`. Make sure to fill out `<SDK_PATH>` with the path to the downloaded
|
||||
SDK.*
|
||||
|
||||
The `.manifest` file will be used to describe the contents of the package by
|
||||
relating their location when installed to their location on the file system. You
|
||||
can use this to make a package pull files from other places, but for this
|
||||
example we'll just be placing everything in the `package` directory.
|
||||
|
||||
### Compiling a binary
|
||||
|
||||
Using your freshly compiled `rustc`, you can compile a binary for Fuchsia using
|
||||
the following options:
|
||||
|
||||
* `--target x86_64-fuchsia`/`--target aarch64-fuchsia`: Targets the Fuchsia
|
||||
platform of your choice
|
||||
* `-Lnative ${SDK_PATH}/arch/${ARCH}/lib`: Link against Fuchsia libraries from
|
||||
the SDK
|
||||
* `-Lnative ${SDK_PATH}/arch/${ARCH}/sysroot/lib`: Link against Fuchsia kernel
|
||||
libraries from the SDK
|
||||
|
||||
Putting it all together:
|
||||
|
||||
```sh
|
||||
# Configure these for the Fuchsia target of your choice
|
||||
TARGET_ARCH="<x86_64-fuchsia|aarch64-fuchsia>"
|
||||
ARCH="<x64|aarch64>"
|
||||
|
||||
rustc --target ${TARGET_ARCH} -Lnative=${SDK_PATH}/arch/${ARCH}/lib -Lnative=${SDK_PATH}/arch/${ARCH}/sysroot/lib -o package/bin/hello_fuchsia hello_fuchsia.rs
|
||||
```
|
||||
|
||||
### Bulding a component
|
||||
|
||||
On Fuchsia, components require a component manifest written in Fuchia's markup
|
||||
language called CML. The Fuchsia devsite contains an [overview of CML] and a
|
||||
[reference for the file format]. Here's a basic one that can run our single binary:
|
||||
|
||||
[overview of CML]: https://fuchsia.dev/fuchsia-src/concepts/components/v2/component_manifests
|
||||
[reference for the file format]: https://fuchsia.dev/reference/cml
|
||||
|
||||
**`hello_fuchsia.cml`**
|
||||
```txt
|
||||
{
|
||||
include: [ "syslog/client.shard.cml" ],
|
||||
program: {
|
||||
runner: "elf",
|
||||
binary: "bin/hello_fuchsia",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Now we can compile that CML into a component manifest:
|
||||
|
||||
```sh
|
||||
${SDK_PATH}/tools/${ARCH}/cmc compile hello_fuchsia.cml --includepath ${SDK_PATH}/pkg -o package/meta/hello_fuchsia.cm
|
||||
```
|
||||
|
||||
`--includepath` tells the compiler where to look for `include`s from our CML.
|
||||
In our case, we're only using `syslog/client.shard.cml`.
|
||||
|
||||
### Building and publishing a package
|
||||
|
||||
Next, we'll build our package as defined by our manifest:
|
||||
|
||||
```sh
|
||||
${SDK_PATH}/tools/${ARCH}/pm -o hello_fuchsia -m package/hello_fuchsia.manifest build -output-package-manifest hello_fuchsia_manifest
|
||||
```
|
||||
|
||||
This will produce `hello_fuchsia_manifest` which is a package manifest we can
|
||||
publish directly to a repository. We can set up that repository with:
|
||||
|
||||
```sh
|
||||
${SDK_PATH}/tools/${ARCH}/pm newrepo -repo repo
|
||||
```
|
||||
|
||||
And then publish our new package to that repository with:
|
||||
|
||||
```sh
|
||||
${SDK_PATH}/tools/${ARCH}/pm publish -repo repo -lp -f <(echo "hello_fuchsia_manifest")
|
||||
```
|
||||
|
||||
Then we can add it to `ffx`'s package server as `hello-fuchsia` using:
|
||||
|
||||
```sh
|
||||
${SDK_PATH}/tools/${ARCH}/ffx repository add-from-pm repo -r hello-fuchsia
|
||||
```
|
||||
|
||||
### Starting the emulator
|
||||
|
||||
Start a Fuchsia emulator in a new terminal using:
|
||||
|
||||
```sh
|
||||
${SDK_PATH}/tools/${ARCH}/ffx product-bundle get workstation_eng.qemu-${ARCH}
|
||||
${SDK_PATH}/tools/${ARCH}/ffx emu start workstation_eng.qemu-${ARCH} --headless
|
||||
```
|
||||
|
||||
Then, once the emulator has been started:
|
||||
|
||||
```sh
|
||||
${SDK_PATH}/tools/${ARCH}/ffx target repository register
|
||||
```
|
||||
|
||||
And watch the logs from the emulator in a separate terminal:
|
||||
|
||||
```sh
|
||||
${SDK_PATH}/tools/${ARCH}/ffx log --since now
|
||||
```
|
||||
|
||||
Finally, run the component:
|
||||
|
||||
```sh
|
||||
${SDK_PATH}/tools/${ARCH}/ffx component run fuchsia-pkg://hello-fuchsia/hello_fuchsia#meta/hello_fuchsia.cm
|
||||
```
|
||||
|
||||
On reruns of the component, the `--recreate` argument may also need to be
|
||||
passed.
|
||||
|
||||
## Testing
|
||||
|
||||
### Running unit tests
|
||||
|
||||
Tests can be run in the same way as a regular binary, simply by passing `--test`
|
||||
to the `rustc` invocation and then repackaging and rerunning. The test harness
|
||||
will run the applicable unit tests.
|
||||
|
||||
Often when testing, you may want to pass additional command line arguments to
|
||||
your binary. Additional arguments can be set in the component manifest:
|
||||
|
||||
**`hello_fuchsia.cml`**
|
||||
```txt
|
||||
{
|
||||
include: [ "syslog/client.shard.cml" ],
|
||||
program: {
|
||||
runner: "elf",
|
||||
binary: "bin/hello_fuchsia",
|
||||
args: ["it_works"],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
This will pass the argument `it_works` to the binary, filtering the tests to
|
||||
only those tests that match the pattern. There are many more configuration
|
||||
options available in CML including environment variables. More documentation is
|
||||
available on the [Fuchsia devsite](https://fuchsia.dev/reference/cml).
|
||||
|
||||
### Running the compiler test suite
|
||||
|
||||
Running the Rust test suite on Fuchsia is [not currently supported], but work is
|
||||
underway to enable it.
|
||||
|
||||
[not currently supported]: https://fxbug.dev/105393
|
|
@ -311,7 +311,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
|
|||
w,
|
||||
"<h2 id=\"{id}\" class=\"small-section-header\">\
|
||||
<a href=\"#{id}\">{name}</a>\
|
||||
</h2>\n{}",
|
||||
</h2>{}",
|
||||
ITEM_TABLE_OPEN,
|
||||
id = cx.derive_id(my_section.id().to_owned()),
|
||||
name = my_section.name(),
|
||||
|
@ -415,10 +415,10 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
|
|||
write!(
|
||||
w,
|
||||
"<div class=\"item-left {stab}{add}module-item\">\
|
||||
<a class=\"{class}\" href=\"{href}\" title=\"{title}\">{name}</a>\
|
||||
{visibility_emoji}\
|
||||
{unsafety_flag}\
|
||||
{stab_tags}\
|
||||
<a class=\"{class}\" href=\"{href}\" title=\"{title}\">{name}</a>\
|
||||
{visibility_emoji}\
|
||||
{unsafety_flag}\
|
||||
{stab_tags}\
|
||||
</div>\
|
||||
<div class=\"item-right docblock-short\">{docs}</div>",
|
||||
name = myitem.name.unwrap(),
|
||||
|
@ -1126,7 +1126,8 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
|
|||
write!(
|
||||
w,
|
||||
"<h2 id=\"fields\" class=\"fields small-section-header\">\
|
||||
Fields<a href=\"#fields\" class=\"anchor\"></a></h2>"
|
||||
Fields<a href=\"#fields\" class=\"anchor\"></a>\
|
||||
</h2>"
|
||||
);
|
||||
for (field, ty) in fields {
|
||||
let name = field.name.expect("union field name");
|
||||
|
@ -1238,7 +1239,8 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
|
|||
write!(
|
||||
w,
|
||||
"<h2 id=\"variants\" class=\"variants small-section-header\">\
|
||||
Variants{}<a href=\"#variants\" class=\"anchor\"></a></h2>",
|
||||
Variants{}<a href=\"#variants\" class=\"anchor\"></a>\
|
||||
</h2>",
|
||||
document_non_exhaustive_header(it)
|
||||
);
|
||||
document_non_exhaustive(w, it);
|
||||
|
@ -1294,9 +1296,9 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
|
|||
w,
|
||||
"<div class=\"sub-variant-field\">\
|
||||
<span id=\"{id}\" class=\"variant small-section-header\">\
|
||||
<a href=\"#{id}\" class=\"anchor field\"></a>\
|
||||
<code>{f}: {t}</code>\
|
||||
</span>",
|
||||
<a href=\"#{id}\" class=\"anchor field\"></a>\
|
||||
<code>{f}: {t}</code>\
|
||||
</span>",
|
||||
id = id,
|
||||
f = field.name.unwrap(),
|
||||
t = ty.print(cx)
|
||||
|
|
|
@ -82,10 +82,10 @@
|
|||
{%- else -%}
|
||||
<img class="rust-logo" src="{{static_root_path|safe}}rust-logo{{page.resource_suffix}}.svg" alt="logo"> {#- -#}
|
||||
{%- endif -%}
|
||||
</div>
|
||||
</div> {#- -#}
|
||||
</a> {#- -#}
|
||||
<h2 class="location"></h2>
|
||||
</nav>
|
||||
<h2 class="location"></h2> {#- -#}
|
||||
</nav> {#- -#}
|
||||
<nav class="sidebar"> {#- -#}
|
||||
<a class="sidebar-logo" href="{{page.root_path|safe}}{{krate_with_trailing_slash|safe}}index.html"> {#- -#}
|
||||
<div class="logo-container"> {#- -#}
|
||||
|
@ -94,7 +94,7 @@
|
|||
{%- else -%}
|
||||
<img class="rust-logo" src="{{static_root_path|safe}}rust-logo{{page.resource_suffix}}.svg" alt="logo"> {#- -#}
|
||||
{%- endif -%}
|
||||
</div>
|
||||
</div> {#- -#}
|
||||
</a> {#- -#}
|
||||
{{- sidebar|safe -}}
|
||||
</nav> {#- -#}
|
||||
|
@ -122,12 +122,12 @@
|
|||
<div id="help-button" title="help" tabindex="-1"> {#- -#}
|
||||
<button type="button">?</button> {#- -#}
|
||||
</div> {#- -#}
|
||||
<div id="settings-menu" tabindex="-1">
|
||||
<div id="settings-menu" tabindex="-1"> {#- -#}
|
||||
<a href="{{page.root_path|safe}}settings.html" title="settings"> {#- -#}
|
||||
<img width="22" height="22" alt="Change settings" {# -#}
|
||||
src="{{static_root_path|safe}}wheel{{page.resource_suffix}}.svg"> {#- -#}
|
||||
</a> {#- -#}
|
||||
</div>
|
||||
</div> {#- -#}
|
||||
</div> {#- -#}
|
||||
</form> {#- -#}
|
||||
</nav> {#- -#}
|
||||
|
@ -143,6 +143,6 @@
|
|||
data-resource-suffix="{{page.resource_suffix}}" {# -#}
|
||||
data-rustdoc-version="{{rustdoc_version}}" {# -#}
|
||||
> {#- -#}
|
||||
</div>
|
||||
</div> {#- -#}
|
||||
</body> {#- -#}
|
||||
</html> {#- -#}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div class="main-heading">
|
||||
<div class="main-heading"> {#- -#}
|
||||
<h1 class="fqn"> {#- -#}
|
||||
<span class="in-band"> {#- -#}
|
||||
{{-typ-}}
|
||||
|
@ -27,4 +27,4 @@
|
|||
[<span class="inner">−</span>] {#- -#}
|
||||
</a> {#- -#}
|
||||
</span> {#- -#}
|
||||
</div>
|
||||
</div> {#- -#}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error[E0277]: the type `[{integer}]` cannot be indexed by `i32`
|
||||
--> $DIR/index-help.rs:3:5
|
||||
--> $DIR/index-help.rs:3:7
|
||||
|
|
||||
LL | x[0i32];
|
||||
| ^^^^^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
| ^^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
|
|
||||
= help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32`
|
||||
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error[E0277]: the type `[{integer}]` cannot be indexed by `u8`
|
||||
--> $DIR/indexing-requires-a-uint.rs:6:5
|
||||
--> $DIR/indexing-requires-a-uint.rs:6:9
|
||||
|
|
||||
LL | [0][0u8];
|
||||
| ^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
| ^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
|
|
||||
= help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8`
|
||||
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
|
||||
|
|
|
@ -1,78 +1,78 @@
|
|||
error[E0277]: the type `[isize]` cannot be indexed by `u8`
|
||||
--> $DIR/integral-indexing.rs:6:5
|
||||
--> $DIR/integral-indexing.rs:6:7
|
||||
|
|
||||
LL | v[3u8];
|
||||
| ^^^^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
| ^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
|
|
||||
= help: the trait `SliceIndex<[isize]>` is not implemented for `u8`
|
||||
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
|
||||
= note: required because of the requirements on the impl of `Index<u8>` for `Vec<isize>`
|
||||
|
||||
error[E0277]: the type `[isize]` cannot be indexed by `i8`
|
||||
--> $DIR/integral-indexing.rs:7:5
|
||||
--> $DIR/integral-indexing.rs:7:7
|
||||
|
|
||||
LL | v[3i8];
|
||||
| ^^^^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
| ^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
|
|
||||
= help: the trait `SliceIndex<[isize]>` is not implemented for `i8`
|
||||
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
|
||||
= note: required because of the requirements on the impl of `Index<i8>` for `Vec<isize>`
|
||||
|
||||
error[E0277]: the type `[isize]` cannot be indexed by `u32`
|
||||
--> $DIR/integral-indexing.rs:8:5
|
||||
--> $DIR/integral-indexing.rs:8:7
|
||||
|
|
||||
LL | v[3u32];
|
||||
| ^^^^^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
| ^^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
|
|
||||
= help: the trait `SliceIndex<[isize]>` is not implemented for `u32`
|
||||
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
|
||||
= note: required because of the requirements on the impl of `Index<u32>` for `Vec<isize>`
|
||||
|
||||
error[E0277]: the type `[isize]` cannot be indexed by `i32`
|
||||
--> $DIR/integral-indexing.rs:9:5
|
||||
--> $DIR/integral-indexing.rs:9:7
|
||||
|
|
||||
LL | v[3i32];
|
||||
| ^^^^^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
| ^^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
|
|
||||
= help: the trait `SliceIndex<[isize]>` is not implemented for `i32`
|
||||
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
|
||||
= note: required because of the requirements on the impl of `Index<i32>` for `Vec<isize>`
|
||||
|
||||
error[E0277]: the type `[u8]` cannot be indexed by `u8`
|
||||
--> $DIR/integral-indexing.rs:12:5
|
||||
--> $DIR/integral-indexing.rs:12:18
|
||||
|
|
||||
LL | s.as_bytes()[3u8];
|
||||
| ^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
| ^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
|
|
||||
= help: the trait `SliceIndex<[u8]>` is not implemented for `u8`
|
||||
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
|
||||
= note: required because of the requirements on the impl of `Index<u8>` for `[u8]`
|
||||
|
||||
error[E0277]: the type `[u8]` cannot be indexed by `i8`
|
||||
--> $DIR/integral-indexing.rs:13:5
|
||||
--> $DIR/integral-indexing.rs:13:18
|
||||
|
|
||||
LL | s.as_bytes()[3i8];
|
||||
| ^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
| ^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
|
|
||||
= help: the trait `SliceIndex<[u8]>` is not implemented for `i8`
|
||||
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
|
||||
= note: required because of the requirements on the impl of `Index<i8>` for `[u8]`
|
||||
|
||||
error[E0277]: the type `[u8]` cannot be indexed by `u32`
|
||||
--> $DIR/integral-indexing.rs:14:5
|
||||
--> $DIR/integral-indexing.rs:14:18
|
||||
|
|
||||
LL | s.as_bytes()[3u32];
|
||||
| ^^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
| ^^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
|
|
||||
= help: the trait `SliceIndex<[u8]>` is not implemented for `u32`
|
||||
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
|
||||
= note: required because of the requirements on the impl of `Index<u32>` for `[u8]`
|
||||
|
||||
error[E0277]: the type `[u8]` cannot be indexed by `i32`
|
||||
--> $DIR/integral-indexing.rs:15:5
|
||||
--> $DIR/integral-indexing.rs:15:18
|
||||
|
|
||||
LL | s.as_bytes()[3i32];
|
||||
| ^^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
| ^^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
|
|
||||
= help: the trait `SliceIndex<[u8]>` is not implemented for `i32`
|
||||
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
|
||||
|
|
26
src/test/ui/let-else/let-else-temp-borrowck.rs
Normal file
26
src/test/ui/let-else/let-else-temp-borrowck.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
// run-pass
|
||||
//
|
||||
// from issue #93951, where borrowck complained the temporary that `foo(&x)` was stored in was to
|
||||
// be dropped sometime after `x` was. It then suggested adding a semicolon that was already there.
|
||||
|
||||
#![feature(let_else)]
|
||||
use std::fmt::Debug;
|
||||
|
||||
fn foo<'a>(x: &'a str) -> Result<impl Debug + 'a, ()> {
|
||||
Ok(x)
|
||||
}
|
||||
|
||||
fn let_else() {
|
||||
let x = String::from("Hey");
|
||||
let Ok(_) = foo(&x) else { return };
|
||||
}
|
||||
|
||||
fn if_let() {
|
||||
let x = String::from("Hey");
|
||||
let _ = if let Ok(s) = foo(&x) { s } else { return };
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let_else();
|
||||
if_let();
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
// run-pass
|
||||
#![feature(let_else)]
|
||||
|
||||
use std::fmt::Display;
|
||||
use std::rc::Rc;
|
||||
use std::sync::atomic::{AtomicU8, Ordering};
|
||||
|
||||
static TRACKER: AtomicU8 = AtomicU8::new(0);
|
||||
|
@ -17,9 +19,70 @@ impl Drop for Droppy {
|
|||
}
|
||||
}
|
||||
|
||||
fn foo<'a>(x: &'a str) -> Result<impl Display + 'a, ()> {
|
||||
Ok(x)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(TRACKER.load(Ordering::Acquire), 0);
|
||||
let 0 = Droppy::default().inner else { return };
|
||||
assert_eq!(TRACKER.load(Ordering::Acquire), 1);
|
||||
println!("Should have dropped 👆");
|
||||
|
||||
{
|
||||
// cf. https://github.com/rust-lang/rust/pull/99518#issuecomment-1191520030
|
||||
struct Foo<'a>(&'a mut u32);
|
||||
|
||||
impl<'a> Drop for Foo<'a> {
|
||||
fn drop(&mut self) {
|
||||
*self.0 = 0;
|
||||
}
|
||||
}
|
||||
let mut foo = 0;
|
||||
let Foo(0) = Foo(&mut foo) else {
|
||||
*&mut foo = 1;
|
||||
todo!()
|
||||
};
|
||||
}
|
||||
{
|
||||
let x = String::from("Hey");
|
||||
|
||||
let Ok(s) = foo(&x) else { panic!() };
|
||||
assert_eq!(s.to_string(), x);
|
||||
}
|
||||
{
|
||||
// test let-else drops temps after statement
|
||||
let rc = Rc::new(0);
|
||||
let 0 = *rc.clone() else { unreachable!() };
|
||||
Rc::try_unwrap(rc).unwrap();
|
||||
}
|
||||
{
|
||||
let mut rc = Rc::new(0);
|
||||
let mut i = 0;
|
||||
loop {
|
||||
if i > 3 {
|
||||
break;
|
||||
}
|
||||
let 1 = *rc.clone() else {
|
||||
if let Ok(v) = Rc::try_unwrap(rc) {
|
||||
rc = Rc::new(v);
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
i += 1;
|
||||
continue
|
||||
};
|
||||
}
|
||||
}
|
||||
{
|
||||
// test let-else drops temps before else block
|
||||
// NOTE: this test has to be the last block in the `main`
|
||||
// body.
|
||||
let rc = Rc::new(0);
|
||||
let 1 = *rc.clone() else {
|
||||
Rc::try_unwrap(rc).unwrap();
|
||||
return;
|
||||
};
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
error[E0277]: the type `[i32]` cannot be indexed by `i32`
|
||||
--> $DIR/slice-index.rs:8:5
|
||||
--> $DIR/slice-index.rs:8:7
|
||||
|
|
||||
LL | x[1i32];
|
||||
| ^^^^^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
| ^^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
|
|
||||
= help: the trait `SliceIndex<[i32]>` is not implemented for `i32`
|
||||
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
|
||||
= note: required because of the requirements on the impl of `Index<i32>` for `[i32]`
|
||||
|
||||
error[E0277]: the type `[i32]` cannot be indexed by `RangeTo<i32>`
|
||||
--> $DIR/slice-index.rs:9:5
|
||||
--> $DIR/slice-index.rs:9:7
|
||||
|
|
||||
LL | x[..1i32];
|
||||
| ^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
| ^^^^^^ slice indices are of type `usize` or ranges of `usize`
|
||||
|
|
||||
= help: the trait `SliceIndex<[i32]>` is not implemented for `RangeTo<i32>`
|
||||
= help: the following other types implement trait `SliceIndex<T>`:
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
// check-pass
|
||||
|
||||
#![feature(target_feature_11)]
|
||||
|
||||
struct S<T>(T)
|
||||
where
|
||||
[T; (|| {}, 1).1]: Copy;
|
||||
|
||||
fn main() {}
|
|
@ -1,8 +1,8 @@
|
|||
error[E0277]: the type `str` cannot be indexed by `{integer}`
|
||||
--> $DIR/str-idx.rs:3:17
|
||||
--> $DIR/str-idx.rs:3:19
|
||||
|
|
||||
LL | let _: u8 = s[4];
|
||||
| ^^^^ string indices are ranges of `usize`
|
||||
| ^ string indices are ranges of `usize`
|
||||
|
|
||||
= help: the trait `SliceIndex<str>` is not implemented for `{integer}`
|
||||
= note: you can use `.chars().nth()` or `.bytes().nth()`
|
||||
|
@ -47,10 +47,10 @@ LL | pub const unsafe fn get_unchecked<I: ~const SliceIndex<str>>(&self, i:
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl str>::get_unchecked`
|
||||
|
||||
error[E0277]: the type `str` cannot be indexed by `char`
|
||||
--> $DIR/str-idx.rs:6:17
|
||||
--> $DIR/str-idx.rs:6:19
|
||||
|
|
||||
LL | let _: u8 = s['c'];
|
||||
| ^^^^^^ string indices are ranges of `usize`
|
||||
| ^^^ string indices are ranges of `usize`
|
||||
|
|
||||
= help: the trait `SliceIndex<str>` is not implemented for `char`
|
||||
= note: required because of the requirements on the impl of `Index<char>` for `str`
|
||||
|
|
|
@ -25,10 +25,10 @@ LL | s[1..2] = bot();
|
|||
= note: the left-hand-side of an assignment must have a statically known size
|
||||
|
||||
error[E0277]: the type `str` cannot be indexed by `usize`
|
||||
--> $DIR/str-mut-idx.rs:7:5
|
||||
--> $DIR/str-mut-idx.rs:7:7
|
||||
|
|
||||
LL | s[1usize] = bot();
|
||||
| ^^^^^^^^^ string indices are ranges of `usize`
|
||||
| ^^^^^^ string indices are ranges of `usize`
|
||||
|
|
||||
= help: the trait `SliceIndex<str>` is not implemented for `usize`
|
||||
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
|
||||
|
@ -71,10 +71,10 @@ LL | pub const unsafe fn get_unchecked_mut<I: ~const SliceIndex<str>>(
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl str>::get_unchecked_mut`
|
||||
|
||||
error[E0277]: the type `str` cannot be indexed by `char`
|
||||
--> $DIR/str-mut-idx.rs:13:5
|
||||
--> $DIR/str-mut-idx.rs:13:7
|
||||
|
|
||||
LL | s['c'];
|
||||
| ^^^^^^ string indices are ranges of `usize`
|
||||
| ^^^ string indices are ranges of `usize`
|
||||
|
|
||||
= help: the trait `SliceIndex<str>` is not implemented for `char`
|
||||
= note: required because of the requirements on the impl of `Index<char>` for `str`
|
||||
|
|
|
@ -24,4 +24,8 @@ fn main() {
|
|||
//~^ ERROR: expected an array or slice
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let [..] = vec![1, 2, 3][..];
|
||||
//~^ ERROR: expected an array or slice
|
||||
//~| HELP: consider slicing here
|
||||
}
|
||||
|
|
|
@ -24,4 +24,8 @@ fn main() {
|
|||
//~^ ERROR: expected an array or slice
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let [..] = vec![1, 2, 3];
|
||||
//~^ ERROR: expected an array or slice
|
||||
//~| HELP: consider slicing here
|
||||
}
|
||||
|
|
|
@ -31,6 +31,14 @@ LL |
|
|||
LL | [5] => {}
|
||||
| ^^^ pattern cannot match with input type `Vec<_>`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error[E0529]: expected an array or slice, found `Vec<{integer}>`
|
||||
--> $DIR/pattern-slice-vec.rs:28:9
|
||||
|
|
||||
LL | let [..] = vec![1, 2, 3];
|
||||
| ^^^^ ------------- help: consider slicing here: `vec![1, 2, 3][..]`
|
||||
| |
|
||||
| pattern cannot match with input type `Vec<{integer}>`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0529`.
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
// run-rustfix
|
||||
#![allow(unused_variables)]
|
||||
|
||||
fn main() {
|
||||
let i: &usize = &1;
|
||||
let one_item_please: i32 = [1, 2, 3][*i]; //~ ERROR the type `[{integer}]` cannot be indexed by `&usize`
|
||||
}
|
7
src/test/ui/suggestions/suggest-dereferencing-index.rs
Normal file
7
src/test/ui/suggestions/suggest-dereferencing-index.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
// run-rustfix
|
||||
#![allow(unused_variables)]
|
||||
|
||||
fn main() {
|
||||
let i: &usize = &1;
|
||||
let one_item_please: i32 = [1, 2, 3][i]; //~ ERROR the type `[{integer}]` cannot be indexed by `&usize`
|
||||
}
|
17
src/test/ui/suggestions/suggest-dereferencing-index.stderr
Normal file
17
src/test/ui/suggestions/suggest-dereferencing-index.stderr
Normal file
|
@ -0,0 +1,17 @@
|
|||
error[E0277]: the type `[{integer}]` cannot be indexed by `&usize`
|
||||
--> $DIR/suggest-dereferencing-index.rs:6:42
|
||||
|
|
||||
LL | let one_item_please: i32 = [1, 2, 3][i];
|
||||
| ^ slice indices are of type `usize` or ranges of `usize`
|
||||
|
|
||||
= help: the trait `SliceIndex<[{integer}]>` is not implemented for `&usize`
|
||||
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
|
||||
= note: required because of the requirements on the impl of `Index<&usize>` for `[{integer}]`
|
||||
help: dereference this index
|
||||
|
|
||||
LL | let one_item_please: i32 = [1, 2, 3][*i];
|
||||
| +
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
Loading…
Add table
Reference in a new issue