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:
bors 2022-07-30 00:26:22 +00:00
commit 8f68c43ca6
36 changed files with 629 additions and 190 deletions

View file

@ -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);

View file

@ -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;

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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;

View file

@ -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);

View file

@ -132,6 +132,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
initializer_span,
else_block,
visibility_scope,
*remainder_scope,
remainder_span,
pattern,
)

View file

@ -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.

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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.

View file

@ -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.

View file

@ -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>,

View file

@ -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.
};

View file

@ -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

View file

@ -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)

View 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

View file

@ -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}:&nbsp;{t}</code>\
</span>",
<a href=\"#{id}\" class=\"anchor field\"></a>\
<code>{f}:&nbsp;{t}</code>\
</span>",
id = id,
f = field.name.unwrap(),
t = ty.print(cx)

View file

@ -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> {#- -#}

View file

@ -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">&#x2212;</span>] {#- -#}
</a> {#- -#}
</span> {#- -#}
</div>
</div> {#- -#}

View file

@ -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`

View file

@ -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`

View file

@ -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`

View 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();
}

View file

@ -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!();
}
}

View file

@ -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>`:

View file

@ -0,0 +1,9 @@
// check-pass
#![feature(target_feature_11)]
struct S<T>(T)
where
[T; (|| {}, 1).1]: Copy;
fn main() {}

View file

@ -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`

View file

@ -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`

View file

@ -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
}

View file

@ -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
}

View file

@ -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`.

View 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`
}

View 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`
}

View 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`.