diff options
| author | Oli Scherer <github35764891676564198441@oli-obk.de> | 2024-12-15 05:35:37 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-12-15 05:35:37 +0000 |
| commit | e999c48404b492659f90993e9fdd2544c675abce (patch) | |
| tree | 57e9863e82b35af828fb9ea01e1067f656f8cf26 | |
| parent | d5322f75df7ec605bbcca5d9ec329e32bb696f69 (diff) | |
| parent | 581989d1c6de8ece197b1317e3093203d3203d66 (diff) | |
| download | rust-e999c48404b492659f90993e9fdd2544c675abce.tar.gz rust-e999c48404b492659f90993e9fdd2544c675abce.zip | |
Merge pull request #4095 from rust-lang/rustup-2024-12-15
Automatic Rustup
669 files changed, 7061 insertions, 4608 deletions
diff --git a/Cargo.lock b/Cargo.lock index 38b009bfc70..923d4017c0c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3507,7 +3507,6 @@ dependencies = [ "cc", "either", "itertools", - "jobserver", "libc", "object 0.36.5", "pathdiff", diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 650525a2f52..f0099fa8adc 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1382,6 +1382,7 @@ impl Expr { | ExprKind::Tup(_) | ExprKind::Type(..) | ExprKind::Underscore + | ExprKind::UnsafeBinderCast(..) | ExprKind::While(..) | ExprKind::Err(_) | ExprKind::Dummy => ExprPrecedence::Unambiguous, @@ -1509,7 +1510,13 @@ pub enum ExprKind { /// `'label: for await? pat in iter { block }` /// /// This is desugared to a combination of `loop` and `match` expressions. - ForLoop { pat: P<Pat>, iter: P<Expr>, body: P<Block>, label: Option<Label>, kind: ForLoopKind }, + ForLoop { + pat: P<Pat>, + iter: P<Expr>, + body: P<Block>, + label: Option<Label>, + kind: ForLoopKind, + }, /// Conditionless loop (can be exited with `break`, `continue`, or `return`). /// /// `'label: loop { block }` @@ -1614,6 +1621,8 @@ pub enum ExprKind { /// A `format_args!()` expression. FormatArgs(P<FormatArgs>), + UnsafeBinderCast(UnsafeBinderCastKind, P<Expr>, Option<P<Ty>>), + /// Placeholder for an expression that wasn't syntactically well formed in some way. Err(ErrorGuaranteed), @@ -1652,6 +1661,16 @@ impl GenBlockKind { } } +/// Whether we're unwrapping or wrapping an unsafe binder +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Encodable, Decodable, HashStable_Generic)] +pub enum UnsafeBinderCastKind { + // e.g. `&i32` -> `unsafe<'a> &'a i32` + Wrap, + // e.g. `unsafe<'a> &'a i32` -> `&i32` + Unwrap, +} + /// The explicit `Self` type in a "qualified path". The actual /// path, including the trait and the associated item, is stored /// separately. `position` represents the index of the associated @@ -2223,6 +2242,12 @@ pub struct BareFnTy { pub decl_span: Span, } +#[derive(Clone, Encodable, Decodable, Debug)] +pub struct UnsafeBinderTy { + pub generic_params: ThinVec<GenericParam>, + pub inner_ty: P<Ty>, +} + /// The various kinds of type recognized by the compiler. // // Adding a new variant? Please update `test_ty` in `tests/ui/macros/stringify.rs`. @@ -2242,6 +2267,8 @@ pub enum TyKind { PinnedRef(Option<Lifetime>, MutTy), /// A bare function (e.g., `fn(usize) -> bool`). BareFn(P<BareFnTy>), + /// An unsafe existential lifetime binder (e.g., `unsafe<'a> &'a ()`). + UnsafeBinder(P<UnsafeBinderTy>), /// The never type (`!`). Never, /// A tuple (`(A, B, C, D,...)`). @@ -2877,7 +2904,7 @@ pub enum ModKind { /// or with definition outlined to a separate file `mod foo;` and already loaded from it. /// The inner span is from the first token past `{` to the last token until `}`, /// or from the first to the last token in the loaded file. - Loaded(ThinVec<P<Item>>, Inline, ModSpans), + Loaded(ThinVec<P<Item>>, Inline, ModSpans, Result<(), ErrorGuaranteed>), /// Module with definition outlined to a separate file `mod foo;` but not yet loaded from it. Unloaded, } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 2c09059fe19..b44e2d9cace 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -558,6 +558,11 @@ pub fn walk_ty<T: MutVisitor>(vis: &mut T, ty: &mut P<Ty>) { vis.visit_fn_decl(decl); vis.visit_span(decl_span); } + TyKind::UnsafeBinder(binder) => { + let UnsafeBinderTy { generic_params, inner_ty } = binder.deref_mut(); + generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); + vis.visit_ty(inner_ty); + } TyKind::Tup(tys) => visit_thin_vec(tys, |ty| vis.visit_ty(ty)), TyKind::Paren(ty) => vis.visit_ty(ty), TyKind::Pat(ty, pat) => { @@ -1212,7 +1217,12 @@ impl WalkItemKind for ItemKind { ItemKind::Mod(safety, mod_kind) => { visit_safety(vis, safety); match mod_kind { - ModKind::Loaded(items, _inline, ModSpans { inner_span, inject_use_span }) => { + ModKind::Loaded( + items, + _inline, + ModSpans { inner_span, inject_use_span }, + _, + ) => { items.flat_map_in_place(|item| vis.flat_map_item(item)); vis.visit_span(inner_span); vis.visit_span(inject_use_span); @@ -1775,6 +1785,12 @@ pub fn walk_expr<T: MutVisitor>(vis: &mut T, Expr { kind, id, span, attrs, token ExprKind::TryBlock(body) => vis.visit_block(body), ExprKind::Lit(_token) => {} ExprKind::IncludedBytes(_bytes) => {} + ExprKind::UnsafeBinderCast(_kind, expr, ty) => { + vis.visit_expr(expr); + if let Some(ty) = ty { + vis.visit_ty(ty); + } + } ExprKind::Err(_guar) => {} ExprKind::Dummy => {} } diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs index ae1ca36a3ba..64f2a98b8a6 100644 --- a/compiler/rustc_ast/src/util/classify.rs +++ b/compiler/rustc_ast/src/util/classify.rs @@ -152,6 +152,7 @@ pub fn leading_labeled_expr(mut expr: &ast::Expr) -> bool { | Underscore | Yeet(..) | Yield(..) + | UnsafeBinderCast(..) | Err(..) | Dummy => return false, } @@ -232,6 +233,7 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> { | Paren(_) | Try(_) | Yeet(None) + | UnsafeBinderCast(..) | Err(_) | Dummy => break None, } @@ -253,6 +255,10 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> { ty = &mut_ty.ty; } + ast::TyKind::UnsafeBinder(binder) => { + ty = &binder.inner_ty; + } + ast::TyKind::BareFn(fn_ty) => match &fn_ty.decl.output { ast::FnRetTy::Default(_) => break None, ast::FnRetTy::Ty(ret) => ty = ret, diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index a7f7c37693a..22db4438e31 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -380,7 +380,7 @@ impl WalkItemKind for ItemKind { try_visit!(visitor.visit_fn(kind, span, id)); } ItemKind::Mod(_unsafety, mod_kind) => match mod_kind { - ModKind::Loaded(items, _inline, _inner_span) => { + ModKind::Loaded(items, _inline, _inner_span, _) => { walk_list!(visitor, visit_item, items); } ModKind::Unloaded => {} @@ -522,6 +522,10 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result { walk_list!(visitor, visit_generic_param, generic_params); try_visit!(visitor.visit_fn_decl(decl)); } + TyKind::UnsafeBinder(binder) => { + walk_list!(visitor, visit_generic_param, &binder.generic_params); + try_visit!(visitor.visit_ty(&binder.inner_ty)); + } TyKind::Path(maybe_qself, path) => { try_visit!(visitor.visit_qself(maybe_qself)); try_visit!(visitor.visit_path(path, *id)); @@ -1226,6 +1230,10 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V ExprKind::TryBlock(body) => try_visit!(visitor.visit_block(body)), ExprKind::Lit(_token) => {} ExprKind::IncludedBytes(_bytes) => {} + ExprKind::UnsafeBinderCast(_kind, expr, ty) => { + try_visit!(visitor.visit_expr(expr)); + visit_opt!(visitor, visit_ty, ty); + } ExprKind::Err(_guar) => {} ExprKind::Dummy => {} } diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 20d3ce65fac..88ce6f80e10 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -1,5 +1,6 @@ use rustc_ast::{Block, BlockCheckMode, Local, LocalKind, Stmt, StmtKind}; use rustc_hir as hir; +use rustc_span::sym; use smallvec::SmallVec; use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext}; @@ -82,11 +83,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { (self.arena.alloc_from_iter(stmts), expr) } + /// Return an `ImplTraitContext` that allows impl trait in bindings if + /// the feature gate is enabled, or issues a feature error if it is not. + fn impl_trait_in_bindings_ctxt(&self, position: ImplTraitPosition) -> ImplTraitContext { + if self.tcx.features().impl_trait_in_bindings() { + ImplTraitContext::InBinding + } else { + ImplTraitContext::FeatureGated(position, sym::impl_trait_in_bindings) + } + } + fn lower_local(&mut self, l: &Local) -> &'hir hir::LetStmt<'hir> { - let ty = l - .ty - .as_ref() - .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Variable))); + // Let statements are allowed to have impl trait in bindings. + let ty = l.ty.as_ref().map(|t| { + self.lower_ty(t, self.impl_trait_in_bindings_ctxt(ImplTraitPosition::Variable)) + }); let init = l.kind.init().map(|init| self.lower_expr(init)); let hir_id = self.lower_node_id(l.id); let pat = self.lower_pat(&l.pat); diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 2ad0ff3200e..32905806343 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -379,6 +379,14 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()), ExprKind::Err(guar) => hir::ExprKind::Err(*guar), + ExprKind::UnsafeBinderCast(kind, expr, ty) => hir::ExprKind::UnsafeBinderCast( + *kind, + self.lower_expr(expr), + ty.as_ref().map(|ty| { + self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Cast)) + }), + ), + ExprKind::Dummy => { span_bug!(e.span, "lowered ExprKind::Dummy") } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 7d6c41992eb..d63131eacb5 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -238,7 +238,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }) } ItemKind::Mod(_, mod_kind) => match mod_kind { - ModKind::Loaded(items, _, spans) => { + ModKind::Loaded(items, _, spans, _) => { hir::ItemKind::Mod(self.lower_mod(items, spans)) } ModKind::Unloaded => panic!("`mod` items should have been loaded by now"), diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index bac3f974cca..e4600b0f636 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -260,6 +260,13 @@ enum ImplTraitContext { /// equivalent to a new opaque type like `type T = impl Debug; fn foo() -> T`. /// OpaqueTy { origin: hir::OpaqueTyOrigin<LocalDefId> }, + + /// Treat `impl Trait` as a "trait ascription", which is like a type + /// variable but that also enforces that a set of trait goals hold. + /// + /// This is useful to guide inference for unnameable types. + InBinding, + /// `impl Trait` is unstably accepted in this position. FeatureGated(ImplTraitPosition, Symbol), /// `impl Trait` is not accepted in this position. @@ -1228,6 +1235,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { param_names: self.lower_fn_params_to_names(&f.decl), })) } + TyKind::UnsafeBinder(f) => { + let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params); + hir::TyKind::UnsafeBinder(self.arena.alloc(hir::UnsafeBinderTy { + generic_params, + inner_ty: self.lower_ty(&f.inner_ty, itctx), + })) + } TyKind::Never => hir::TyKind::Never, TyKind::Tup(tys) => hir::TyKind::Tup( self.arena.alloc_from_iter(tys.iter().map(|ty| self.lower_ty_direct(ty, itctx))), @@ -1320,6 +1334,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } path } + ImplTraitContext::InBinding => { + hir::TyKind::TraitAscription(self.lower_param_bounds(bounds, itctx)) + } ImplTraitContext::FeatureGated(position, feature) => { let guar = self .tcx diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 64e91c91e2c..290c2e52970 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1029,7 +1029,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.dcx().emit_err(errors::UnsafeItem { span, kind: "module" }); } // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584). - if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) + if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _, _)) && !attr::contains_name(&item.attrs, sym::path) { self.check_mod_file_item_asciionly(item.ident); diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 61a710517ea..c10b3296497 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -560,6 +560,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(return_type_notation, "return type notation is experimental"); gate_all!(pin_ergonomics, "pinned reference syntax is experimental"); gate_all!(unsafe_fields, "`unsafe` fields are experimental"); + gate_all!(unsafe_binders, "unsafe binder types are experimental"); if !visitor.features.never_patterns() { if let Some(spans) = spans.get(&sym::never_patterns) { diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 49e4a559e73..04ffa2cffe3 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1198,6 +1198,14 @@ impl<'a> State<'a> { ast::TyKind::BareFn(f) => { self.print_ty_fn(f.ext, f.safety, &f.decl, None, &f.generic_params); } + ast::TyKind::UnsafeBinder(f) => { + self.ibox(INDENT_UNIT); + self.word("unsafe"); + self.print_generic_params(&f.generic_params); + self.nbsp(); + self.print_type(&f.inner_ty); + self.end(); + } ast::TyKind::Path(None, path) => { self.print_path(path, false, 0); } diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index c239cb249c3..dce76fb1e77 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -772,6 +772,25 @@ impl<'a> State<'a> { self.word_nbsp("try"); self.print_block_with_attrs(blk, attrs) } + ast::ExprKind::UnsafeBinderCast(kind, expr, ty) => { + self.word("builtin # "); + match kind { + ast::UnsafeBinderCastKind::Wrap => self.word("wrap_binder"), + ast::UnsafeBinderCastKind::Unwrap => self.word("unwrap_binder"), + } + self.popen(); + self.ibox(0); + self.print_expr(expr, FixupContext::default()); + + if let Some(ty) = ty { + self.word(","); + self.space(); + self.print_type(ty); + } + + self.end(); + self.pclose(); + } ast::ExprKind::Err(_) => { self.popen(); self.word("/*ERROR*/"); diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index 16b3d901956..ff838fbbb88 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -34,6 +34,25 @@ pub struct BorrowSet<'tcx> { pub(crate) locals_state_at_exit: LocalsStateAtExit, } +// These methods are public to support borrowck consumers. +impl<'tcx> BorrowSet<'tcx> { + pub fn location_map(&self) -> &FxIndexMap<Location, BorrowData<'tcx>> { + &self.location_map + } + + pub fn activation_map(&self) -> &FxIndexMap<Location, Vec<BorrowIndex>> { + &self.activation_map + } + + pub fn local_map(&self) -> &FxIndexMap<mir::Local, FxIndexSet<BorrowIndex>> { + &self.local_map + } + + pub fn locals_state_at_exit(&self) -> &LocalsStateAtExit { + &self.locals_state_at_exit + } +} + impl<'tcx> Index<BorrowIndex> for BorrowSet<'tcx> { type Output = BorrowData<'tcx>; @@ -45,7 +64,7 @@ impl<'tcx> Index<BorrowIndex> for BorrowSet<'tcx> { /// Location where a two-phase borrow is activated, if a borrow /// is in fact a two-phase borrow. #[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub(crate) enum TwoPhaseActivation { +pub enum TwoPhaseActivation { NotTwoPhase, NotActivated, ActivatedAt(Location), @@ -68,6 +87,33 @@ pub struct BorrowData<'tcx> { pub(crate) assigned_place: mir::Place<'tcx>, } +// These methods are public to support borrowck consumers. +impl<'tcx> BorrowData<'tcx> { + pub fn reserve_location(&self) -> Location { + self.reserve_location + } + + pub fn activation_location(&self) -> TwoPhaseActivation { + self.activation_location + } + + pub fn kind(&self) -> mir::BorrowKind { + self.kind + } + + pub fn region(&self) -> RegionVid { + self.region + } + + pub fn borrowed_place(&self) -> mir::Place<'tcx> { + self.borrowed_place + } + + pub fn assigned_place(&self) -> mir::Place<'tcx> { + self.assigned_place + } +} + impl<'tcx> fmt::Display for BorrowData<'tcx> { fn fmt(&self, w: &mut fmt::Formatter<'_>) -> fmt::Result { let kind = match self.kind { @@ -120,7 +166,7 @@ impl LocalsStateAtExit { } impl<'tcx> BorrowSet<'tcx> { - pub(crate) fn build( + pub fn build( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, locals_are_invalidated_at_exit: bool, diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index 7ace38c3e85..74de766ba23 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -5,15 +5,15 @@ use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::{Body, Promoted}; use rustc_middle::ty::TyCtxt; +pub use super::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation}; pub use super::constraints::OutlivesConstraint; pub use super::dataflow::{BorrowIndex, Borrows, calculate_borrows_out_of_scope_at_location}; -pub use super::facts::{AllFacts as PoloniusInput, RustcFacts}; +pub use super::facts::{AllFacts as PoloniusInput, PoloniusRegionVid, RustcFacts}; pub use super::location::{LocationTable, RichLocation}; pub use super::nll::PoloniusOutput; pub use super::place_ext::PlaceExt; pub use super::places_conflict::{PlaceConflictBias, places_conflict}; pub use super::region_infer::RegionInferenceContext; -use crate::borrow_set::BorrowSet; /// Options determining the output behavior of [`get_body_with_borrowck_facts`]. /// diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 452038bc328..dc4eab766c9 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -8,7 +8,10 @@ use rustc_middle::mir::{ }; use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_mir_dataflow::fmt::DebugWithContext; -use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces}; +use rustc_mir_dataflow::impls::{ + EverInitializedPlaces, EverInitializedPlacesDomain, MaybeUninitializedPlaces, + MaybeUninitializedPlacesDomain, +}; use rustc_mir_dataflow::{Analysis, GenKill, JoinSemiLattice, SwitchIntEdgeEffects}; use tracing::debug; @@ -24,7 +27,7 @@ pub(crate) struct Borrowck<'a, 'tcx> { } impl<'a, 'tcx> Analysis<'tcx> for Borrowck<'a, 'tcx> { - type Domain = BorrowckDomain<'a, 'tcx>; + type Domain = BorrowckDomain; const NAME: &'static str = "borrowck"; @@ -41,48 +44,48 @@ impl<'a, 'tcx> Analysis<'tcx> for Borrowck<'a, 'tcx> { unreachable!(); } - fn apply_before_statement_effect( + fn apply_early_statement_effect( &mut self, state: &mut Self::Domain, stmt: &mir::Statement<'tcx>, loc: Location, ) { - self.borrows.apply_before_statement_effect(&mut state.borrows, stmt, loc); - self.uninits.apply_before_statement_effect(&mut state.uninits, stmt, loc); - self.ever_inits.apply_before_statement_effect(&mut state.ever_inits, stmt, loc); + self.borrows.apply_early_statement_effect(&mut state.borrows, stmt, loc); + self.uninits.apply_early_statement_effect(&mut state.uninits, stmt, loc); + self.ever_inits.apply_early_statement_effect(&mut state.ever_inits, stmt, loc); } - fn apply_statement_effect( + fn apply_primary_statement_effect( &mut self, state: &mut Self::Domain, stmt: &mir::Statement<'tcx>, loc: Location, ) { - self.borrows.apply_statement_effect(&mut state.borrows, stmt, loc); - self.uninits.apply_statement_effect(&mut state.uninits, stmt, loc); - self.ever_inits.apply_statement_effect(&mut state.ever_inits, stmt, loc); + self.borrows.apply_primary_statement_effect(&mut state.borrows, stmt, loc); + self.uninits.apply_primary_statement_effect(&mut state.uninits, stmt, loc); + self.ever_inits.apply_primary_statement_effect(&mut state.ever_inits, stmt, loc); } - fn apply_before_terminator_effect( + fn apply_early_terminator_effect( &mut self, state: &mut Self::Domain, term: &mir::Terminator<'tcx>, loc: Location, ) { - self.borrows.apply_before_terminator_effect(&mut state.borrows, term, loc); - self.uninits.apply_before_terminator_effect(&mut state.uninits, term, loc); - self.ever_inits.apply_before_terminator_effect(&mut state.ever_inits, term, loc); + self.borrows.apply_early_terminator_effect(&mut state.borrows, term, loc); + self.uninits.apply_early_terminator_effect(&mut state.uninits, term, loc); + self.ever_inits.apply_early_terminator_effect(&mut state.ever_inits, term, loc); } - fn apply_terminator_effect<'mir>( + fn apply_primary_terminator_effect<'mir>( &mut self, state: &mut Self::Domain, term: &'mir mir::Terminator<'tcx>, loc: Location, ) -> TerminatorEdges<'mir, 'tcx> { - self.borrows.apply_terminator_effect(&mut state.borrows, term, loc); - self.uninits.apply_terminator_effect(&mut state.uninits, term, loc); - self.ever_inits.apply_terminator_effect(&mut state.ever_inits, term, loc); + self.borrows.apply_primary_terminator_effect(&mut state.borrows, term, loc); + self.uninits.apply_primary_terminator_effect(&mut state.uninits, term, loc); + self.ever_inits.apply_primary_terminator_effect(&mut state.ever_inits, term, loc); // This return value doesn't matter. It's only used by `iterate_to_fixpoint`, which this // analysis doesn't use. @@ -110,14 +113,14 @@ impl<'a, 'tcx> Analysis<'tcx> for Borrowck<'a, 'tcx> { } } -impl JoinSemiLattice for BorrowckDomain<'_, '_> { +impl JoinSemiLattice for BorrowckDomain { fn join(&mut self, _other: &Self) -> bool { // This is only reachable from `iterate_to_fixpoint`, which this analysis doesn't use. unreachable!(); } } -impl<'tcx, C> DebugWithContext<C> for BorrowckDomain<'_, 'tcx> +impl<'tcx, C> DebugWithContext<C> for BorrowckDomain where C: rustc_mir_dataflow::move_paths::HasMoveData<'tcx>, { @@ -160,10 +163,10 @@ where /// The transient state of the dataflow analyses used by the borrow checker. #[derive(Clone, Debug, PartialEq, Eq)] -pub(crate) struct BorrowckDomain<'a, 'tcx> { - pub(crate) borrows: <Borrows<'a, 'tcx> as Analysis<'tcx>>::Domain, - pub(crate) uninits: <MaybeUninitializedPlaces<'a, 'tcx> as Analysis<'tcx>>::Domain, - pub(crate) ever_inits: <EverInitializedPlaces<'a, 'tcx> as Analysis<'tcx>>::Domain, +pub(crate) struct BorrowckDomain { + pub(crate) borrows: BorrowsDomain, + pub(crate) uninits: MaybeUninitializedPlacesDomain, + pub(crate) ever_inits: EverInitializedPlacesDomain, } rustc_index::newtype_index! { @@ -503,7 +506,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { /// That means they went out of a nonlexical scope fn kill_loans_out_of_scope_at_location( &self, - trans: &mut <Self as Analysis<'tcx>>::Domain, + state: &mut <Self as Analysis<'tcx>>::Domain, location: Location, ) { // NOTE: The state associated with a given `location` @@ -518,14 +521,14 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { // region, then setting that gen-bit will override any // potential kill introduced here. if let Some(indices) = self.borrows_out_of_scope_at_location.get(&location) { - trans.kill_all(indices.iter().copied()); + state.kill_all(indices.iter().copied()); } } /// Kill any borrows that conflict with `place`. fn kill_borrows_on_place( &self, - trans: &mut <Self as Analysis<'tcx>>::Domain, + state: &mut <Self as Analysis<'tcx>>::Domain, place: Place<'tcx>, ) { debug!("kill_borrows_on_place: place={:?}", place); @@ -543,7 +546,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { // `places_conflict` for every borrow. if place.projection.is_empty() { if !self.body.local_decls[place.local].is_ref_to_static() { - trans.kill_all(other_borrows_of_local); + state.kill_all(other_borrows_of_local); } return; } @@ -562,10 +565,12 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { ) }); - trans.kill_all(definitely_conflicting_borrows); + state.kill_all(definitely_conflicting_borrows); } } +type BorrowsDomain = BitSet<BorrowIndex>; + /// Forward dataflow computation of the set of borrows that are in scope at a particular location. /// - we gen the introduced loans /// - we kill loans on locals going out of (regular) scope @@ -574,7 +579,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { /// - we also kill loans of conflicting places when overwriting a shared path: e.g. borrows of /// `a.b.c` when `a` is overwritten. impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> { - type Domain = BitSet<BorrowIndex>; + type Domain = BorrowsDomain; const NAME: &'static str = "borrows"; @@ -588,18 +593,18 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> { // function execution, so this method has no effect. } - fn apply_before_statement_effect( + fn apply_early_statement_effect( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, _statement: &mir::Statement<'tcx>, location: Location, ) { - self.kill_loans_out_of_scope_at_location(trans, location); + self.kill_loans_out_of_scope_at_location(state, location); } - fn apply_statement_effect( + fn apply_primary_statement_effect( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, stmt: &mir::Statement<'tcx>, location: Location, ) { @@ -617,18 +622,18 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> { panic!("could not find BorrowIndex for location {location:?}"); }); - trans.gen_(index); + state.gen_(index); } // Make sure there are no remaining borrows for variables // that are assigned over. - self.kill_borrows_on_place(trans, *lhs); + self.kill_borrows_on_place(state, *lhs); } mir::StatementKind::StorageDead(local) => { // Make sure there are no remaining borrows for locals that // are gone out of scope. - self.kill_borrows_on_place(trans, Place::from(*local)); + self.kill_borrows_on_place(state, Place::from(*local)); } mir::StatementKind::FakeRead(..) @@ -646,18 +651,18 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> { } } - fn apply_before_terminator_effect( + fn apply_early_terminator_effect( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, _terminator: &mir::Terminator<'tcx>, location: Location, ) { - self.kill_loans_out_of_scope_at_location(trans, location); + self.kill_loans_out_of_scope_at_location(state, location); } - fn apply_terminator_effect<'mir>( + fn apply_primary_terminator_effect<'mir>( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, terminator: &'mir mir::Terminator<'tcx>, _location: Location, ) -> TerminatorEdges<'mir, 'tcx> { @@ -666,7 +671,7 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> { if let mir::InlineAsmOperand::Out { place: Some(place), .. } | mir::InlineAsmOperand::InOut { out_place: Some(place), .. } = *op { - self.kill_borrows_on_place(trans, place); + self.kill_borrows_on_place(state, place); } } } diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index c5ebf3c547e..4fb7b22f289 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1100,12 +1100,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } let decl_span = local_decl.source_info.span; - let label = match *local_decl.local_info() { + let amp_mut_sugg = match *local_decl.local_info() { LocalInfo::User(mir::BindingForm::ImplicitSelf(_)) => { let suggestion = suggest_ampmut_self(self.infcx.tcx, decl_span); let additional = local_trait.map(|span| (span, suggest_ampmut_self(self.infcx.tcx, span))); - Some((true, decl_span, suggestion, additional)) + Some(AmpMutSugg { has_sugg: true, span: decl_span, suggestion, additional }) } LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm { @@ -1150,7 +1150,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { None } None => { - let (has_sugg, decl_span, sugg) = if name != kw::SelfLower { + if name != kw::SelfLower { suggest_ampmut( self.infcx.tcx, local_decl.ty, @@ -1165,7 +1165,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { .. })) => { let sugg = suggest_ampmut_self(self.infcx.tcx, decl_span); - (true, decl_span, sugg) + Some(AmpMutSugg { + has_sugg: true, + span: decl_span, + suggestion: sugg, + additional: None, + }) } // explicit self (eg `self: &'a Self`) _ => suggest_ampmut( @@ -1176,8 +1181,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { opt_ty_info, ), } - }; - Some((has_sugg, decl_span, sugg, None)) + } } } } @@ -1187,15 +1191,24 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { .. })) => { let pattern_span: Span = local_decl.source_info.span; - suggest_ref_mut(self.infcx.tcx, pattern_span) - .map(|span| (true, span, "mut ".to_owned(), None)) + suggest_ref_mut(self.infcx.tcx, pattern_span).map(|span| AmpMutSugg { + has_sugg: true, + span, + suggestion: "mut ".to_owned(), + additional: None, + }) } _ => unreachable!(), }; - match label { - Some((true, err_help_span, suggested_code, additional)) => { + match amp_mut_sugg { + Some(AmpMutSugg { + has_sugg: true, + span: err_help_span, + suggestion: suggested_code, + additional, + }) => { let mut sugg = vec![(err_help_span, suggested_code)]; if let Some(s) = additional { sugg.push(s); @@ -1217,7 +1230,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ); } } - Some((false, err_label_span, message, _)) => { + Some(AmpMutSugg { + has_sugg: false, span: err_label_span, suggestion: message, .. + }) => { let def_id = self.body.source.def_id(); let hir_id = if let Some(local_def_id) = def_id.as_local() && let Some(body) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id) @@ -1422,6 +1437,13 @@ fn suggest_ampmut_self<'tcx>(tcx: TyCtxt<'tcx>, span: Span) -> String { } } +struct AmpMutSugg { + has_sugg: bool, + span: Span, + suggestion: String, + additional: Option<(Span, String)>, +} + // When we want to suggest a user change a local variable to be a `&mut`, there // are three potential "obvious" things to highlight: // @@ -1443,7 +1465,7 @@ fn suggest_ampmut<'tcx>( decl_span: Span, opt_assignment_rhs_span: Option<Span>, opt_ty_info: Option<Span>, -) -> (bool, Span, String) { +) -> Option<AmpMutSugg> { // if there is a RHS and it starts with a `&` from it, then check if it is // mutable, and if not, put suggest putting `mut ` to make it mutable. // we don't have to worry about lifetime annotations here because they are @@ -1456,6 +1478,11 @@ fn suggest_ampmut<'tcx>( && let Ok(src) = tcx.sess.source_map().span_to_snippet(assignment_rhs_span) && let Some(stripped) = src.strip_prefix('&') { + let is_raw_ref = stripped.trim_start().starts_with("raw "); + // We don't support raw refs yet + if is_raw_ref { + return None; + } let is_mut = if let Some(rest) = stripped.trim_start().strip_prefix("mut") { match rest.chars().next() { // e.g. `&mut x` @@ -1479,7 +1506,12 @@ fn suggest_ampmut<'tcx>( // FIXME(Ezrashaw): returning is bad because we still might want to // update the annotated type, see #106857. - return (true, span, "mut ".to_owned()); + return Some(AmpMutSugg { + has_sugg: true, + span, + suggestion: "mut ".to_owned(), + additional: None, + }); } } @@ -1504,18 +1536,23 @@ fn suggest_ampmut<'tcx>( && let Some(ws_pos) = src.find(char::is_whitespace) { let span = span.with_lo(span.lo() + BytePos(ws_pos as u32)).shrink_to_lo(); - (true, span, " mut".to_owned()) + Some(AmpMutSugg { has_sugg: true, span, suggestion: " mut".to_owned(), additional: None }) // if there is already a binding, we modify it to be `mut` } else if binding_exists { // shrink the span to just after the `&` in `&variable` let span = span.with_lo(span.lo() + BytePos(1)).shrink_to_lo(); - (true, span, "mut ".to_owned()) + Some(AmpMutSugg { has_sugg: true, span, suggestion: "mut ".to_owned(), additional: None }) } else { // otherwise, suggest that the user annotates the binding; we provide the // type of the local. let ty = decl_ty.builtin_deref(true).unwrap(); - (false, span, format!("{}mut {}", if decl_ty.is_ref() { "&" } else { "*" }, ty)) + Some(AmpMutSugg { + has_sugg: false, + span, + suggestion: format!("{}mut {}", if decl_ty.is_ref() { "&" } else { "*" }, ty), + additional: None, + }) } } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index d7db92da18f..18b7984e90d 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -43,7 +43,7 @@ use rustc_mir_dataflow::impls::{ use rustc_mir_dataflow::move_paths::{ InitIndex, InitLocation, LookupResult, MoveData, MoveOutIndex, MovePathIndex, }; -use rustc_mir_dataflow::{Analysis, EntrySets, Results, ResultsVisitor, visit_results}; +use rustc_mir_dataflow::{Analysis, EntryStates, Results, ResultsVisitor, visit_results}; use rustc_session::lint::builtin::UNUSED_MUT; use rustc_span::{Span, Symbol}; use smallvec::SmallVec; @@ -426,14 +426,14 @@ fn get_flow_results<'a, 'tcx>( ever_inits: ever_inits.analysis, }; - assert_eq!(borrows.entry_sets.len(), uninits.entry_sets.len()); - assert_eq!(borrows.entry_sets.len(), ever_inits.entry_sets.len()); - let entry_sets: EntrySets<'_, Borrowck<'_, '_>> = - itertools::izip!(borrows.entry_sets, uninits.entry_sets, ever_inits.entry_sets) + assert_eq!(borrows.entry_states.len(), uninits.entry_states.len()); + assert_eq!(borrows.entry_states.len(), ever_inits.entry_states.len()); + let entry_states: EntryStates<'_, Borrowck<'_, '_>> = + itertools::izip!(borrows.entry_states, uninits.entry_states, ever_inits.entry_states) .map(|(borrows, uninits, ever_inits)| BorrowckDomain { borrows, uninits, ever_inits }) .collect(); - Results { analysis, entry_sets } + Results { analysis, entry_states } } pub(crate) struct BorrowckInferCtxt<'tcx> { @@ -600,10 +600,10 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> { // 3. assignments do not affect things loaned out as immutable // 4. moves do not affect things loaned out in any way impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a, '_, 'tcx> { - fn visit_statement_before_primary_effect( + fn visit_after_early_statement_effect( &mut self, _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>, - state: &BorrowckDomain<'a, 'tcx>, + state: &BorrowckDomain, stmt: &'a Statement<'tcx>, location: Location, ) { @@ -674,10 +674,10 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt< } } - fn visit_terminator_before_primary_effect( + fn visit_after_early_terminator_effect( &mut self, _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>, - state: &BorrowckDomain<'a, 'tcx>, + state: &BorrowckDomain, term: &'a Terminator<'tcx>, loc: Location, ) { @@ -787,10 +787,10 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt< } } - fn visit_terminator_after_primary_effect( + fn visit_after_primary_terminator_effect( &mut self, _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>, - state: &BorrowckDomain<'a, 'tcx>, + state: &BorrowckDomain, term: &'a Terminator<'tcx>, loc: Location, ) { @@ -983,7 +983,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { place_span: (Place<'tcx>, Span), kind: (AccessDepth, ReadOrWrite), is_local_mutation_allowed: LocalMutationIsAllowed, - state: &BorrowckDomain<'a, 'tcx>, + state: &BorrowckDomain, ) { let (sd, rw) = kind; @@ -1032,7 +1032,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { place_span: (Place<'tcx>, Span), sd: AccessDepth, rw: ReadOrWrite, - state: &BorrowckDomain<'a, 'tcx>, + state: &BorrowckDomain, ) -> bool { let mut error_reported = false; @@ -1172,7 +1172,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { location: Location, place_span: (Place<'tcx>, Span), kind: AccessDepth, - state: &BorrowckDomain<'a, 'tcx>, + state: &BorrowckDomain, ) { // Write of P[i] or *P requires P init'd. self.check_if_assigned_path_is_moved(location, place_span, state); @@ -1190,7 +1190,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { &mut self, location: Location, (rvalue, span): (&'a Rvalue<'tcx>, Span), - state: &BorrowckDomain<'a, 'tcx>, + state: &BorrowckDomain, ) { match rvalue { &Rvalue::Ref(_ /*rgn*/, bk, place) => { @@ -1448,7 +1448,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { &mut self, location: Location, (operand, span): (&'a Operand<'tcx>, Span), - state: &BorrowckDomain<'a, 'tcx>, + state: &BorrowckDomain, ) { match *operand { Operand::Copy(place) => { @@ -1568,12 +1568,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { } } - fn check_activations( - &mut self, - location: Location, - span: Span, - state: &BorrowckDomain<'a, 'tcx>, - ) { + fn check_activations(&mut self, location: Location, span: Span, state: &BorrowckDomain) { // Two-phase borrow support: For each activation that is newly // generated at this statement, check if it interferes with // another borrow. @@ -1731,7 +1726,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { location: Location, desired_action: InitializationRequiringAction, place_span: (PlaceRef<'tcx>, Span), - state: &BorrowckDomain<'a, 'tcx>, + state: &BorrowckDomain, ) { let maybe_uninits = &state.uninits; @@ -1836,7 +1831,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { location: Location, desired_action: InitializationRequiringAction, place_span: (PlaceRef<'tcx>, Span), - state: &BorrowckDomain<'a, 'tcx>, + state: &BorrowckDomain, ) { let maybe_uninits = &state.uninits; @@ -1935,7 +1930,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { &mut self, location: Location, (place, span): (Place<'tcx>, Span), - state: &BorrowckDomain<'a, 'tcx>, + state: &BorrowckDomain, ) { debug!("check_if_assigned_path_is_moved place: {:?}", place); @@ -2001,7 +1996,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { location: Location, base: PlaceRef<'tcx>, span: Span, - state: &BorrowckDomain<'a, 'tcx>, + state: &BorrowckDomain, ) { // rust-lang/rust#21232: Until Rust allows reads from the // initialized parts of partially initialized structs, we @@ -2092,7 +2087,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { (place, span): (Place<'tcx>, Span), kind: ReadOrWrite, is_local_mutation_allowed: LocalMutationIsAllowed, - state: &BorrowckDomain<'a, 'tcx>, + state: &BorrowckDomain, location: Location, ) -> bool { debug!( @@ -2206,18 +2201,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { } } - fn is_local_ever_initialized( - &self, - local: Local, - state: &BorrowckDomain<'a, 'tcx>, - ) -> Option<InitIndex> { + fn is_local_ever_initialized(&self, local: Local, state: &BorrowckDomain) -> Option<InitIndex> { let mpi = self.move_data.rev_lookup.find_local(local)?; let ii = &self.move_data.init_path_map[mpi]; ii.into_iter().find(|&&index| state.ever_inits.contains(index)).copied() } /// Adds the place into the used mutable variables set - fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, state: &BorrowckDomain<'a, 'tcx>) { + fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, state: &BorrowckDomain) { match root_place { RootPlace { place_local: local, place_projection: [], is_local_mutation_allowed } => { // If the local may have been initialized, and it is now currently being diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 585d0eabf5b..3903c45fda5 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -275,7 +275,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { user_ty: ty::UserType<'tcx>, span: Span, ) { - let ty::UserType::Ty(user_ty) = user_ty else { bug!() }; + let ty::UserTypeKind::Ty(user_ty) = user_ty.kind else { bug!() }; // A fast path for a common case with closure input/output types. if let ty::Infer(_) = user_ty.kind() { diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index bbe2b55d8c4..1f2ec168f03 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -110,7 +110,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ) { self.ascribe_user_type_skip_wf( arg_decl.ty, - ty::UserType::Ty(user_ty), + ty::UserType::new(ty::UserTypeKind::Ty(user_ty)), arg_decl.source_info.span, ); } @@ -119,7 +119,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let output_decl = &body.local_decls[RETURN_PLACE]; self.ascribe_user_type_skip_wf( output_decl.ty, - ty::UserType::Ty(user_provided_sig.output()), + ty::UserType::new(ty::UserTypeKind::Ty(user_provided_sig.output())), output_decl.source_info.span, ); } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 89e683b8ae3..90d327b0ad2 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -31,7 +31,7 @@ use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{ self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt, Dynamic, GenericArgsRef, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserArgs, - UserType, UserTypeAnnotationIndex, + UserTypeAnnotationIndex, }; use rustc_middle::{bug, span_bug}; use rustc_mir_dataflow::ResultsCursor; @@ -370,7 +370,10 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } else { self.cx.ascribe_user_type( constant.const_.ty(), - UserType::TypeOf(uv.def, UserArgs { args: uv.args, user_self_ty: None }), + ty::UserType::new(ty::UserTypeKind::TypeOf(uv.def, UserArgs { + args: uv.args, + user_self_ty: None, + })), locations.span(self.cx.body), ); } @@ -991,9 +994,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { for user_annotation in self.user_type_annotations { let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation; let annotation = self.instantiate_canonical(span, user_ty); - if let ty::UserType::TypeOf(def, args) = annotation + if let ty::UserTypeKind::TypeOf(def, args) = annotation.kind && let DefKind::InlineConst = tcx.def_kind(def) { + assert!(annotation.bounds.is_empty()); self.check_inline_const(inferred_ty, def.expect_local(), args, span); } else { self.ascribe_user_type(inferred_ty, annotation, span); diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index 70fa4d00c0f..eb07975d8af 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -323,7 +323,8 @@ impl<'cx, 'a> Context<'cx, 'a> { | ExprKind::While(_, _, _) | ExprKind::Yeet(_) | ExprKind::Become(_) - | ExprKind::Yield(_) => {} + | ExprKind::Yield(_) + | ExprKind::UnsafeBinderCast(..) => {} } } diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index b2048c534a4..e7ff65e08f9 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -141,8 +141,10 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { // We don't want to recurse into anything other than mods, since // mods or tests inside of functions will break things - if let ast::ItemKind::Mod(_, ModKind::Loaded(.., ast::ModSpans { inner_span: span, .. })) = - item.kind + if let ast::ItemKind::Mod( + _, + ModKind::Loaded(.., ast::ModSpans { inner_span: span, .. }, _), + ) = item.kind { let prev_tests = mem::take(&mut self.tests); walk_item_kind( diff --git a/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs b/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs index 2093b49ff31..b5a81fc11d5 100644 --- a/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs +++ b/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs @@ -1,8 +1,7 @@ use std::sync::{Arc, Condvar, Mutex}; -use jobserver::HelperThread; +use rustc_data_structures::jobserver::{self, HelperThread}; use rustc_errors::DiagCtxtHandle; -use rustc_session::Session; // FIXME don't panic when a worker thread panics @@ -14,14 +13,13 @@ pub(super) struct ConcurrencyLimiter { } impl ConcurrencyLimiter { - pub(super) fn new(sess: &Session, pending_jobs: usize) -> Self { + pub(super) fn new(pending_jobs: usize) -> Self { let state = Arc::new(Mutex::new(state::ConcurrencyLimiterState::new(pending_jobs))); let available_token_condvar = Arc::new(Condvar::new()); let state_helper = state.clone(); let available_token_condvar_helper = available_token_condvar.clone(); - let helper_thread = sess - .jobserver + let helper_thread = jobserver::client() .clone() .into_helper_thread(move |token| { let mut state = state_helper.lock().unwrap(); @@ -113,7 +111,7 @@ impl Drop for ConcurrencyLimiterToken { } mod state { - use jobserver::Acquired; + use rustc_data_structures::jobserver::Acquired; #[derive(Debug)] pub(super) struct ConcurrencyLimiterState { diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 5bbcfc2cda7..4fc30b69123 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -679,7 +679,7 @@ pub(crate) fn run_aot( metadata_module: None, metadata, crate_info: CrateInfo::new(tcx, target_cpu), - concurrency_limiter: ConcurrencyLimiter::new(tcx.sess, 0), + concurrency_limiter: ConcurrencyLimiter::new(0), }); }; @@ -711,7 +711,7 @@ pub(crate) fn run_aot( CguReuse::PreLto | CguReuse::PostLto => false, }); - let concurrency_limiter = IntoDynSyncSend(ConcurrencyLimiter::new(tcx.sess, todo_cgus.len())); + let concurrency_limiter = IntoDynSyncSend(ConcurrencyLimiter::new(todo_cgus.len())); let modules = tcx.sess.time("codegen mono items", || { let mut modules: Vec<_> = par_map(todo_cgus, |(_, cgu)| { diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs index d68948966ea..4be4291021d 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs @@ -287,12 +287,7 @@ fn dep_symbol_lookup_fn( let mut dylib_paths = Vec::new(); - let data = &crate_info - .dependency_formats - .iter() - .find(|(crate_type, _data)| *crate_type == rustc_session::config::CrateType::Executable) - .unwrap() - .1; + let data = &crate_info.dependency_formats[&rustc_session::config::CrateType::Executable].1; // `used_crates` is in reverse postorder in terms of dependencies. Reverse the order here to // get a postorder which ensures that all dependencies of a dylib are loaded before the dylib // itself. This helps the dynamic linker to find dylibs not in the regular dynamic library diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 9f552b3feb9..c38ef82e5b8 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -12,7 +12,6 @@ #![warn(unused_lifetimes)] // tidy-alphabetical-end -extern crate jobserver; #[macro_use] extern crate rustc_middle; extern crate rustc_abi; @@ -175,7 +174,11 @@ impl CodegenBackend for CraneliftCodegenBackend { } } - fn target_features(&self, sess: &Session, _allow_unstable: bool) -> Vec<rustc_span::Symbol> { + fn target_features_cfg( + &self, + sess: &Session, + _allow_unstable: bool, + ) -> Vec<rustc_span::Symbol> { // FIXME return the actually used target features. this is necessary for #[cfg(target_feature)] if sess.target.arch == "x86_64" && sess.target.os != "none" { // x86_64 mandates SSE2 support diff --git a/compiler/rustc_codegen_gcc/messages.ftl b/compiler/rustc_codegen_gcc/messages.ftl index 26ddc5732dd..85fa17a6ba5 100644 --- a/compiler/rustc_codegen_gcc/messages.ftl +++ b/compiler/rustc_codegen_gcc/messages.ftl @@ -9,7 +9,7 @@ codegen_gcc_lto_not_supported = LTO is not supported. You may get a linker error. codegen_gcc_forbidden_ctarget_feature = - target feature `{$feature}` cannot be toggled with `-Ctarget-feature` + target feature `{$feature}` cannot be toggled with `-Ctarget-feature`: {$reason} codegen_gcc_unwinding_inline_asm = GCC backend does not support unwinding from inline asm diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index 7a586b5b04c..56849cc8610 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -28,6 +28,7 @@ pub(crate) struct UnstableCTargetFeature<'a> { #[diag(codegen_gcc_forbidden_ctarget_feature)] pub(crate) struct ForbiddenCTargetFeature<'a> { pub feature: &'a str, + pub reason: &'a str, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs index 65279c9495a..88e5eefd7a1 100644 --- a/compiler/rustc_codegen_gcc/src/gcc_util.rs +++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs @@ -5,7 +5,7 @@ use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable; use rustc_data_structures::fx::FxHashMap; use rustc_middle::bug; use rustc_session::Session; -use rustc_target::target_features::{RUSTC_SPECIFIC_FEATURES, Stability}; +use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES; use smallvec::{SmallVec, smallvec}; use crate::errors::{ @@ -94,13 +94,17 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri }; sess.dcx().emit_warn(unknown_feature); } - Some((_, Stability::Stable, _)) => {} - Some((_, Stability::Unstable(_), _)) => { - // An unstable feature. Warn about using it. - sess.dcx().emit_warn(UnstableCTargetFeature { feature }); - } - Some((_, Stability::Forbidden { .. }, _)) => { - sess.dcx().emit_err(ForbiddenCTargetFeature { feature }); + Some((_, stability, _)) => { + if let Err(reason) = + stability.compute_toggleability(&sess.target).allow_toggle() + { + sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, reason }); + } else if stability.requires_nightly().is_some() { + // An unstable feature. Warn about using it. (It makes little sense + // to hard-error here since we just warn about fully unknown + // features above). + sess.dcx().emit_warn(UnstableCTargetFeature { feature }); + } } } diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 452e92bffa2..764e84be1fe 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -260,8 +260,8 @@ impl CodegenBackend for GccCodegenBackend { .join(sess) } - fn target_features(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> { - target_features(sess, allow_unstable, &self.target_info) + fn target_features_cfg(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> { + target_features_cfg(sess, allow_unstable, &self.target_info) } } @@ -472,7 +472,8 @@ fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel { } } -pub fn target_features( +/// Returns the features that should be set in `cfg(target_feature)`. +fn target_features_cfg( sess: &Session, allow_unstable: bool, target_info: &LockedTargetInfo, @@ -481,9 +482,9 @@ pub fn target_features( sess.target .rust_target_features() .iter() - .filter(|(_, gate, _)| gate.is_supported()) + .filter(|(_, gate, _)| gate.in_cfg()) .filter_map(|&(feature, gate, _)| { - if sess.is_nightly_build() || allow_unstable || gate.is_stable() { + if sess.is_nightly_build() || allow_unstable || gate.requires_nightly().is_none() { Some(feature) } else { None diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index a573a37beb3..4f2af732527 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -75,10 +75,10 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { // Encode all filenames referenced by coverage mappings in this CGU. let filenames_buffer = global_file_table.make_filenames_buffer(tcx); - - let filenames_size = filenames_buffer.len(); - let filenames_val = cx.const_bytes(&filenames_buffer); - let filenames_ref = llvm_cov::hash_bytes(&filenames_buffer); + // The `llvm-cov` tool uses this hash to associate each covfun record with + // its corresponding filenames table, since the final binary will typically + // contain multiple covmap records from different compilation units. + let filenames_hash = llvm_cov::hash_bytes(&filenames_buffer); let mut unused_function_names = Vec::new(); @@ -101,7 +101,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { for covfun in &covfun_records { unused_function_names.extend(covfun.mangled_function_name_if_unused()); - covfun::generate_covfun_record(cx, filenames_ref, covfun) + covfun::generate_covfun_record(cx, filenames_hash, covfun) } // For unused functions, we need to take their mangled names and store them @@ -126,7 +126,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { // Generate the coverage map header, which contains the filenames used by // this CGU's coverage mappings, and store it in a well-known global. // (This is skipped if we returned early due to having no covfun records.) - generate_covmap_record(cx, covmap_version, filenames_size, filenames_val); + generate_covmap_record(cx, covmap_version, &filenames_buffer); } /// Maps "global" (per-CGU) file ID numbers to their underlying filenames. @@ -225,38 +225,35 @@ fn span_file_name(tcx: TyCtxt<'_>, span: Span) -> Symbol { /// Generates the contents of the covmap record for this CGU, which mostly /// consists of a header and a list of filenames. The record is then stored /// as a global variable in the `__llvm_covmap` section. -fn generate_covmap_record<'ll>( - cx: &CodegenCx<'ll, '_>, - version: u32, - filenames_size: usize, - filenames_val: &'ll llvm::Value, -) { - debug!("cov map: filenames_size = {}, 0-based version = {}", filenames_size, version); - - // Create the coverage data header (Note, fields 0 and 2 are now always zero, - // as of `llvm::coverage::CovMapVersion::Version4`.) - let zero_was_n_records_val = cx.const_u32(0); - let filenames_size_val = cx.const_u32(filenames_size as u32); - let zero_was_coverage_size_val = cx.const_u32(0); - let version_val = cx.const_u32(version); - let cov_data_header_val = cx.const_struct( - &[zero_was_n_records_val, filenames_size_val, zero_was_coverage_size_val, version_val], - /*packed=*/ false, +fn generate_covmap_record<'ll>(cx: &CodegenCx<'ll, '_>, version: u32, filenames_buffer: &[u8]) { + // A covmap record consists of four target-endian u32 values, followed by + // the encoded filenames table. Two of the header fields are unused in + // modern versions of the LLVM coverage mapping format, and are always 0. + // <https://llvm.org/docs/CoverageMappingFormat.html#llvm-ir-representation> + // See also `src/llvm-project/clang/lib/CodeGen/CoverageMappingGen.cpp`. + let covmap_header = cx.const_struct( + &[ + cx.const_u32(0), // (unused) + cx.const_u32(filenames_buffer.len() as u32), + cx.const_u32(0), // (unused) + cx.const_u32(version), + ], + /* packed */ false, ); - - // Create the complete LLVM coverage data value to add to the LLVM IR - let covmap_data = - cx.const_struct(&[cov_data_header_val, filenames_val], /*packed=*/ false); - - let llglobal = llvm::add_global(cx.llmod, cx.val_ty(covmap_data), &llvm_cov::covmap_var_name()); - llvm::set_initializer(llglobal, covmap_data); - llvm::set_global_constant(llglobal, true); - llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage); - llvm::set_section(llglobal, &llvm_cov::covmap_section_name(cx.llmod)); + let covmap_record = cx + .const_struct(&[covmap_header, cx.const_bytes(filenames_buffer)], /* packed */ false); + + let covmap_global = + llvm::add_global(cx.llmod, cx.val_ty(covmap_record), &llvm_cov::covmap_var_name()); + llvm::set_initializer(covmap_global, covmap_record); + llvm::set_global_constant(covmap_global, true); + llvm::set_linkage(covmap_global, llvm::Linkage::PrivateLinkage); + llvm::set_section(covmap_global, &llvm_cov::covmap_section_name(cx.llmod)); // LLVM's coverage mapping format specifies 8-byte alignment for items in this section. // <https://llvm.org/docs/CoverageMappingFormat.html> - llvm::set_alignment(llglobal, Align::EIGHT); - cx.add_used_global(llglobal); + llvm::set_alignment(covmap_global, Align::EIGHT); + + cx.add_used_global(covmap_global); } /// Each CGU will normally only emit coverage metadata for the functions that it actually generates. diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs index 530e6827f55..33e7a0f2f20 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs @@ -136,7 +136,7 @@ fn fill_region_tables<'tcx>( /// as a global variable in the `__llvm_covfun` section. pub(crate) fn generate_covfun_record<'tcx>( cx: &CodegenCx<'_, 'tcx>, - filenames_ref: u64, + filenames_hash: u64, covfun: &CovfunRecord<'tcx>, ) { let &CovfunRecord { @@ -155,46 +155,45 @@ pub(crate) fn generate_covfun_record<'tcx>( regions, ); - // Concatenate the encoded coverage mappings - let coverage_mapping_size = coverage_mapping_buffer.len(); - let coverage_mapping_val = cx.const_bytes(&coverage_mapping_buffer); - + // A covfun record consists of four target-endian integers, followed by the + // encoded mapping data in bytes. Note that the length field is 32 bits. + // <https://llvm.org/docs/CoverageMappingFormat.html#llvm-ir-representation> + // See also `src/llvm-project/clang/lib/CodeGen/CoverageMappingGen.cpp` and + // `COVMAP_V3` in `src/llvm-project/llvm/include/llvm/ProfileData/InstrProfData.inc`. let func_name_hash = llvm_cov::hash_bytes(mangled_function_name.as_bytes()); - let func_name_hash_val = cx.const_u64(func_name_hash); - let coverage_mapping_size_val = cx.const_u32(coverage_mapping_size as u32); - let source_hash_val = cx.const_u64(source_hash); - let filenames_ref_val = cx.const_u64(filenames_ref); - let func_record_val = cx.const_struct( + let covfun_record = cx.const_struct( &[ - func_name_hash_val, - coverage_mapping_size_val, - source_hash_val, - filenames_ref_val, - coverage_mapping_val, + cx.const_u64(func_name_hash), + cx.const_u32(coverage_mapping_buffer.len() as u32), + cx.const_u64(source_hash), + cx.const_u64(filenames_hash), + cx.const_bytes(&coverage_mapping_buffer), ], - /*packed=*/ true, + // This struct needs to be packed, so that the 32-bit length field + // doesn't have unexpected padding. + true, ); // Choose a variable name to hold this function's covfun data. // Functions that are used have a suffix ("u") to distinguish them from // unused copies of the same function (from different CGUs), so that if a // linker sees both it won't discard the used copy's data. - let func_record_var_name = - CString::new(format!("__covrec_{:X}{}", func_name_hash, if is_used { "u" } else { "" })) - .unwrap(); - debug!("function record var name: {:?}", func_record_var_name); - - let llglobal = llvm::add_global(cx.llmod, cx.val_ty(func_record_val), &func_record_var_name); - llvm::set_initializer(llglobal, func_record_val); - llvm::set_global_constant(llglobal, true); - llvm::set_linkage(llglobal, llvm::Linkage::LinkOnceODRLinkage); - llvm::set_visibility(llglobal, llvm::Visibility::Hidden); - llvm::set_section(llglobal, cx.covfun_section_name()); + let u = if is_used { "u" } else { "" }; + let covfun_var_name = CString::new(format!("__covrec_{func_name_hash:X}{u}")).unwrap(); + debug!("function record var name: {covfun_var_name:?}"); + + let covfun_global = llvm::add_global(cx.llmod, cx.val_ty(covfun_record), &covfun_var_name); + llvm::set_initializer(covfun_global, covfun_record); + llvm::set_global_constant(covfun_global, true); + llvm::set_linkage(covfun_global, llvm::Linkage::LinkOnceODRLinkage); + llvm::set_visibility(covfun_global, llvm::Visibility::Hidden); + llvm::set_section(covfun_global, cx.covfun_section_name()); // LLVM's coverage mapping format specifies 8-byte alignment for items in this section. // <https://llvm.org/docs/CoverageMappingFormat.html> - llvm::set_alignment(llglobal, Align::EIGHT); + llvm::set_alignment(covfun_global, Align::EIGHT); if cx.target_spec().supports_comdat() { - llvm::set_comdat(cx.llmod, llglobal, &func_record_var_name); + llvm::set_comdat(cx.llmod, covfun_global, &covfun_var_name); } - cx.add_used_global(llglobal); + + cx.add_used_global(covfun_global); } diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 5235891a18d..af8562db054 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -27,7 +27,7 @@ use std::mem::ManuallyDrop; use back::owned_target_machine::OwnedTargetMachine; use back::write::{create_informational_target_machine, create_target_machine}; use errors::ParseTargetMachineConfig; -pub use llvm_util::target_features; +pub use llvm_util::target_features_cfg; use rustc_ast::expand::allocator::AllocatorKind; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule}; use rustc_codegen_ssa::back::write::{ @@ -330,8 +330,8 @@ impl CodegenBackend for LlvmCodegenBackend { llvm_util::print_version(); } - fn target_features(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> { - target_features(sess, allow_unstable) + fn target_features_cfg(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> { + target_features_cfg(sess, allow_unstable) } fn codegen_crate<'tcx>( diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 07eb89e6041..bfec7d708cf 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -17,7 +17,7 @@ use rustc_session::Session; use rustc_session::config::{PrintKind, PrintRequest}; use rustc_span::symbol::Symbol; use rustc_target::spec::{MergeFunctions, PanicStrategy, SmallDataThresholdSupport}; -use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES, Stability}; +use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES}; use crate::back::write::create_informational_target_machine; use crate::errors::{ @@ -300,7 +300,7 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea /// Must express features in the way Rust understands them. /// /// We do not have to worry about RUSTC_SPECIFIC_FEATURES here, those are handled outside codegen. -pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> { +pub fn target_features_cfg(sess: &Session, allow_unstable: bool) -> Vec<Symbol> { let mut features: FxHashSet<Symbol> = Default::default(); // Add base features for the target. @@ -316,7 +316,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> { sess.target .rust_target_features() .iter() - .filter(|(_, gate, _)| gate.is_supported()) + .filter(|(_, gate, _)| gate.in_cfg()) .filter(|(feature, _, _)| { // skip checking special features, as LLVM may not understand them if RUSTC_SPECIAL_FEATURES.contains(feature) { @@ -372,9 +372,9 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> { sess.target .rust_target_features() .iter() - .filter(|(_, gate, _)| gate.is_supported()) + .filter(|(_, gate, _)| gate.in_cfg()) .filter_map(|&(feature, gate, _)| { - if sess.is_nightly_build() || allow_unstable || gate.is_stable() { + if sess.is_nightly_build() || allow_unstable || gate.requires_nightly().is_none() { Some(feature) } else { None @@ -493,7 +493,7 @@ fn print_target_features(sess: &Session, tm: &llvm::TargetMachine, out: &mut Str .rust_target_features() .iter() .filter_map(|(feature, gate, _implied)| { - if !gate.is_supported() { + if !gate.in_cfg() { // Only list (experimentally) supported features. return None; } @@ -716,13 +716,17 @@ pub(crate) fn global_llvm_features( }; sess.dcx().emit_warn(unknown_feature); } - Some((_, Stability::Stable, _)) => {} - Some((_, Stability::Unstable(_), _)) => { - // An unstable feature. Warn about using it. - sess.dcx().emit_warn(UnstableCTargetFeature { feature }); - } - Some((_, Stability::Forbidden { reason }, _)) => { - sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, reason }); + Some((_, stability, _)) => { + if let Err(reason) = + stability.compute_toggleability(&sess.target).allow_toggle() + { + sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, reason }); + } else if stability.requires_nightly().is_some() { + // An unstable feature. Warn about using it. It makes little sense + // to hard-error here since we just warn about fully unknown + // features above. + sess.dcx().emit_warn(UnstableCTargetFeature { feature }); + } } } diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index c81e36dfc8d..450a95ae20c 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -11,7 +11,6 @@ bitflags = "2.4.1" cc = "1.1.23" either = "1.5.0" itertools = "0.12" -jobserver = "0.1.28" pathdiff = "0.2.0" regex = "1.4" rustc_abi = { path = "../rustc_abi" } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index b030ea3f6df..cfd40a575b1 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -236,7 +236,13 @@ pub fn each_linked_rlib( ) -> Result<(), errors::LinkRlibError> { let crates = info.used_crates.iter(); - let fmts = if crate_type.is_none() { + let fmts = if let Some(crate_type) = crate_type { + let Some(fmts) = info.dependency_formats.get(&crate_type) else { + return Err(errors::LinkRlibError::MissingFormat); + }; + + fmts + } else { for combination in info.dependency_formats.iter().combinations(2) { let (ty1, list1) = &combination[0]; let (ty2, list2) = &combination[1]; @@ -252,18 +258,7 @@ pub fn each_linked_rlib( if info.dependency_formats.is_empty() { return Err(errors::LinkRlibError::MissingFormat); } - &info.dependency_formats[0].1 - } else { - let fmts = info - .dependency_formats - .iter() - .find_map(|&(ty, ref list)| if Some(ty) == crate_type { Some(list) } else { None }); - - let Some(fmts) = fmts else { - return Err(errors::LinkRlibError::MissingFormat); - }; - - fmts + info.dependency_formats.first().unwrap().1 }; for &cnum in crates { @@ -624,8 +619,7 @@ fn link_staticlib( let fmts = codegen_results .crate_info .dependency_formats - .iter() - .find_map(|&(ty, ref list)| if ty == CrateType::Staticlib { Some(list) } else { None }) + .get(&CrateType::Staticlib) .expect("no dependency formats for staticlib"); let mut all_rust_dylibs = vec![]; @@ -2355,11 +2349,10 @@ fn linker_with_args( // they are used within inlined functions or instantiated generic functions. We do this *after* // handling the raw-dylib symbols in the current crate to make sure that those are chosen first // by the linker. - let (_, dependency_linkage) = codegen_results + let dependency_linkage = codegen_results .crate_info .dependency_formats - .iter() - .find(|(ty, _)| *ty == crate_type) + .get(&crate_type) .expect("failed to find crate type in dependency format list"); // We sort the libraries below @@ -2738,11 +2731,10 @@ fn add_upstream_rust_crates( // Linking to a rlib involves just passing it to the linker (the linker // will slurp up the object files inside), and linking to a dynamic library // involves just passing the right -l flag. - let (_, data) = codegen_results + let data = codegen_results .crate_info .dependency_formats - .iter() - .find(|(ty, _)| *ty == crate_type) + .get(&crate_type) .expect("failed to find crate type in dependency format list"); if sess.target.is_like_aix { diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 4c5eb98e890..301b22f2be4 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1749,7 +1749,7 @@ fn for_each_exported_symbols_include_dep<'tcx>( } let formats = tcx.dependency_formats(()); - let deps = formats.iter().find_map(|(t, list)| (*t == crate_type).then_some(list)).unwrap(); + let deps = &formats[&crate_type]; for (index, dep_format) in deps.iter().enumerate() { let cnum = CrateNum::new(index + 1); diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 501f7517919..683defcafee 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -6,9 +6,9 @@ use std::sync::Arc; use std::sync::mpsc::{Receiver, Sender, channel}; use std::{fs, io, mem, str, thread}; -use jobserver::{Acquired, Client}; use rustc_ast::attr; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; +use rustc_data_structures::jobserver::{self, Acquired}; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard}; use rustc_errors::emitter::Emitter; @@ -456,7 +456,6 @@ pub(crate) fn start_async_codegen<B: ExtraBackendMethods>( metadata_module: Option<CompiledModule>, ) -> OngoingCodegen<B> { let (coordinator_send, coordinator_receive) = channel(); - let sess = tcx.sess; let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID); let no_builtins = attr::contains_name(crate_attrs, sym::no_builtins); @@ -477,7 +476,6 @@ pub(crate) fn start_async_codegen<B: ExtraBackendMethods>( shared_emitter, codegen_worker_send, coordinator_receive, - sess.jobserver.clone(), Arc::new(regular_config), Arc::new(metadata_config), Arc::new(allocator_config), @@ -1093,7 +1091,6 @@ fn start_executing_work<B: ExtraBackendMethods>( shared_emitter: SharedEmitter, codegen_worker_send: Sender<CguMessage>, coordinator_receive: Receiver<Box<dyn Any + Send>>, - jobserver: Client, regular_config: Arc<ModuleConfig>, metadata_config: Arc<ModuleConfig>, allocator_config: Arc<ModuleConfig>, @@ -1145,7 +1142,7 @@ fn start_executing_work<B: ExtraBackendMethods>( // get tokens on `coordinator_receive` which will // get managed in the main loop below. let coordinator_send2 = coordinator_send.clone(); - let helper = jobserver + let helper = jobserver::client() .into_helper_thread(move |token| { drop(coordinator_send2.send(Box::new(Message::Token::<B>(token)))); }) diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index eee7cc75400..fa600ec7166 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -11,7 +11,7 @@ use rustc_middle::ty::TyCtxt; use rustc_session::parse::feature_err; use rustc_span::Span; use rustc_span::symbol::{Symbol, sym}; -use rustc_target::target_features::{self, Stability}; +use rustc_target::target_features; use crate::errors; @@ -20,7 +20,7 @@ use crate::errors; pub(crate) fn from_target_feature_attr( tcx: TyCtxt<'_>, attr: &ast::Attribute, - rust_target_features: &UnordMap<String, target_features::Stability>, + rust_target_features: &UnordMap<String, target_features::StabilityComputed>, target_features: &mut Vec<TargetFeature>, ) { let Some(list) = attr.meta_item_list() else { return }; @@ -63,32 +63,24 @@ pub(crate) fn from_target_feature_attr( return None; }; - // Only allow target features whose feature gates have been enabled. - let allowed = match stability { - Stability::Forbidden { .. } => false, - Stability::Stable => true, - Stability::Unstable(name) => rust_features.enabled(*name), - }; - if !allowed { - match stability { - Stability::Stable => unreachable!(), - &Stability::Unstable(lang_feature_name) => { - feature_err( - &tcx.sess, - lang_feature_name, - item.span(), - format!("the target feature `{feature}` is currently unstable"), - ) - .emit(); - } - Stability::Forbidden { reason } => { - tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr { - span: item.span(), - feature, - reason, - }); - } - } + // Only allow target features whose feature gates have been enabled + // and which are permitted to be toggled. + if let Err(reason) = stability.allow_toggle() { + tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr { + span: item.span(), + feature, + reason, + }); + } else if let Some(nightly_feature) = stability.requires_nightly() + && !rust_features.enabled(nightly_feature) + { + feature_err( + &tcx.sess, + nightly_feature, + item.span(), + format!("the target feature `{feature}` is currently unstable"), + ) + .emit(); } Some(Symbol::intern(feature)) })); @@ -156,18 +148,19 @@ pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { rust_target_features: |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); + let target = &tcx.sess.target; if tcx.sess.opts.actually_rustdoc { // rustdoc needs to be able to document functions that use all the features, so // whitelist them all rustc_target::target_features::all_rust_features() - .map(|(a, b)| (a.to_string(), b)) + .map(|(a, b)| (a.to_string(), b.compute_toggleability(target))) .collect() } else { tcx.sess .target .rust_target_features() .iter() - .map(|&(a, b, _)| (a.to_string(), b)) + .map(|&(a, b, _)| (a.to_string(), b.compute_toggleability(target))) .collect() } }, diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 5b4a51fc301..4b17db2c49e 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -45,7 +45,9 @@ pub trait CodegenBackend { fn print(&self, _req: &PrintRequest, _out: &mut String, _sess: &Session) {} - fn target_features(&self, _sess: &Session, _allow_unstable: bool) -> Vec<Symbol> { + /// Returns the features that should be set in `cfg(target_features)`. + /// RUSTC_SPECIFIC_FEATURES should be skipped here, those are handled outside codegen. + fn target_features_cfg(&self, _sess: &Session, _allow_unstable: bool) -> Vec<Symbol> { vec![] } diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 916929b6c0b..16610ebfca2 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -573,12 +573,27 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { ) => {} Rvalue::ShallowInitBox(_, _) => {} - Rvalue::UnaryOp(_, operand) => { + Rvalue::UnaryOp(op, operand) => { let ty = operand.ty(self.body, self.tcx); - if is_int_bool_float_or_char(ty) { - // Int, bool, float, and char operations are fine. - } else { - span_bug!(self.span, "non-primitive type in `Rvalue::UnaryOp`: {:?}", ty); + match op { + UnOp::Not | UnOp::Neg => { + if is_int_bool_float_or_char(ty) { + // Int, bool, float, and char operations are fine. + } else { + span_bug!( + self.span, + "non-primitive type in `Rvalue::UnaryOp{op:?}`: {ty:?}", + ); + } + } + UnOp::PtrMetadata => { + if !ty.is_ref() && !ty.is_unsafe_ptr() { + span_bug!( + self.span, + "non-pointer type in `Rvalue::UnaryOp({op:?})`: {ty:?}", + ); + } + } } } diff --git a/compiler/rustc_const_eval/src/check_consts/resolver.rs b/compiler/rustc_const_eval/src/check_consts/resolver.rs index 0f9a460ca1b..763c37a41af 100644 --- a/compiler/rustc_const_eval/src/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/check_consts/resolver.rs @@ -329,7 +329,7 @@ where self.transfer_function(state).initialize_state(); } - fn apply_statement_effect( + fn apply_primary_statement_effect( &mut self, state: &mut Self::Domain, statement: &mir::Statement<'tcx>, @@ -338,7 +338,7 @@ where self.transfer_function(state).visit_statement(statement, location); } - fn apply_terminator_effect<'mir>( + fn apply_primary_terminator_effect<'mir>( &mut self, state: &mut Self::Domain, terminator: &'mir mir::Terminator<'tcx>, diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index beff0cd99fc..f5396c62433 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -4,27 +4,29 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; -pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { +fn parent_impl_constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness { let parent_id = tcx.local_parent(def_id); - matches!(tcx.def_kind(parent_id), DefKind::Impl { .. }) - && tcx.constness(parent_id) == hir::Constness::Const + if matches!(tcx.def_kind(parent_id), DefKind::Impl { .. }) + && let Some(header) = tcx.impl_trait_header(parent_id) + { + header.constness + } else { + hir::Constness::NotConst + } } -/// Checks whether an item is considered to be `const`. If it is a constructor, anonymous const, -/// const block, const item or associated const, it is const. If it is a trait impl/function, +/// Checks whether an item is considered to be `const`. If it is a constructor, it is const. +/// If it is an assoc method or function, /// return if it has a `const` modifier. If it is an intrinsic, report whether said intrinsic -/// has a `rustc_const_{un,}stable` attribute. Otherwise, return `Constness::NotConst`. +/// has a `rustc_const_{un,}stable` attribute. Otherwise, panic. fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness { let node = tcx.hir_node_by_def_id(def_id); match node { - hir::Node::Ctor(_) - | hir::Node::AnonConst(_) - | hir::Node::ConstBlock(_) + hir::Node::Ctor(hir::VariantData::Tuple(..)) | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => { hir::Constness::Const } - hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.constness, hir::Node::ForeignItem(_) => { // Foreign items cannot be evaluated at compile-time. hir::Constness::NotConst @@ -38,10 +40,12 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness { // If the function itself is not annotated with `const`, it may still be a `const fn` // if it resides in a const trait impl. - let is_const = is_parent_const_impl_raw(tcx, def_id); - if is_const { hir::Constness::Const } else { hir::Constness::NotConst } + parent_impl_constness(tcx, def_id) } else { - hir::Constness::NotConst + tcx.dcx().span_bug( + tcx.def_span(def_id), + format!("should not be requesting the constness of items that can't be const: {node:#?}: {:?}", tcx.def_kind(def_id)) + ) } } } diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 56325eaa1be..23683851799 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -249,10 +249,9 @@ impl<'tcx> CompileTimeInterpCx<'tcx> { } else if self.tcx.is_lang_item(def_id, LangItem::PanicFmt) { // For panic_fmt, call const_panic_fmt instead. let const_def_id = self.tcx.require_lang_item(LangItem::ConstPanicFmt, None); - // FIXME(@lcnr): why does this use an empty env if we've got a `param_env` right here. let new_instance = ty::Instance::expect_resolve( *self.tcx, - ty::TypingEnv::fully_monomorphized(), + self.typing_env(), const_def_id, instance.args, self.cur_span(), diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index a180d5da941..9ac2a024ccf 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -540,10 +540,14 @@ pub trait Machine<'tcx>: Sized { interp_ok(ReturnAction::Normal) } - /// Called immediately after an "immediate" local variable is read + /// Called immediately after an "immediate" local variable is read in a given frame /// (i.e., this is called for reads that do not end up accessing addressable memory). #[inline(always)] - fn after_local_read(_ecx: &InterpCx<'tcx, Self>, _local: mir::Local) -> InterpResult<'tcx> { + fn after_local_read( + _ecx: &InterpCx<'tcx, Self>, + _frame: &Frame<'tcx, Self::Provenance, Self::FrameExtra>, + _local: mir::Local, + ) -> InterpResult<'tcx> { interp_ok(()) } diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 0157e6c2125..b861ffb6110 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -15,9 +15,9 @@ use rustc_middle::{bug, mir, span_bug, ty}; use tracing::trace; use super::{ - CtfeProvenance, InterpCx, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, OffsetMode, - PlaceTy, Pointer, Projectable, Provenance, Scalar, alloc_range, err_ub, from_known_layout, - interp_ok, mir_assign_valid_types, throw_ub, + CtfeProvenance, Frame, InterpCx, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, + OffsetMode, PlaceTy, Pointer, Projectable, Provenance, Scalar, alloc_range, err_ub, + from_known_layout, interp_ok, mir_assign_valid_types, throw_ub, }; /// An `Immediate` represents a single immediate self-contained Rust value. @@ -297,6 +297,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { #[inline] pub fn from_bool(b: bool, tcx: TyCtxt<'tcx>) -> Self { + // Can use any typing env, since `bool` is always monomorphic. let layout = tcx .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(tcx.types.bool)) .unwrap(); @@ -305,17 +306,18 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { #[inline] pub fn from_ordering(c: std::cmp::Ordering, tcx: TyCtxt<'tcx>) -> Self { + // Can use any typing env, since `Ordering` is always monomorphic. let ty = tcx.ty_ordering_enum(None); let layout = tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)).unwrap(); Self::from_scalar(Scalar::from_i8(c as i8), layout) } - pub fn from_pair(a: Self, b: Self, tcx: TyCtxt<'tcx>) -> Self { - let layout = tcx + pub fn from_pair(a: Self, b: Self, cx: &(impl HasTypingEnv<'tcx> + HasTyCtxt<'tcx>)) -> Self { + let layout = cx + .tcx() .layout_of( - ty::TypingEnv::fully_monomorphized() - .as_query_input(Ty::new_tup(tcx, &[a.layout.ty, b.layout.ty])), + cx.typing_env().as_query_input(Ty::new_tup(cx.tcx(), &[a.layout.ty, b.layout.ty])), ) .unwrap(); Self::from_scalar_pair(a.to_scalar(), b.to_scalar(), layout) @@ -706,23 +708,32 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { interp_ok(str) } - /// Read from a local of the current frame. + /// Read from a local of the current frame. Convenience method for [`InterpCx::local_at_frame_to_op`]. + pub fn local_to_op( + &self, + local: mir::Local, + layout: Option<TyAndLayout<'tcx>>, + ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { + self.local_at_frame_to_op(self.frame(), local, layout) + } + + /// Read from a local of a given frame. /// Will not access memory, instead an indirect `Operand` is returned. /// - /// This is public because it is used by [priroda](https://github.com/oli-obk/priroda) to get an - /// OpTy from a local. - pub fn local_to_op( + /// This is public because it is used by [Aquascope](https://github.com/cognitive-engineering-lab/aquascope/) + /// to get an OpTy from a local. + pub fn local_at_frame_to_op( &self, + frame: &Frame<'tcx, M::Provenance, M::FrameExtra>, local: mir::Local, layout: Option<TyAndLayout<'tcx>>, ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { - let frame = self.frame(); let layout = self.layout_of_local(frame, local, layout)?; let op = *frame.locals[local].access()?; if matches!(op, Operand::Immediate(_)) { assert!(!layout.is_unsized()); } - M::after_local_read(self, local)?; + M::after_local_read(self, frame, local)?; interp_ok(OpTy { op, layout }) } diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index 1fa5dcbd24f..8b7b78c7129 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -222,7 +222,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let res = ImmTy::from_scalar_int(result, left.layout); return interp_ok(if with_overflow { let overflow = ImmTy::from_bool(overflow, *self.tcx); - ImmTy::from_pair(res, overflow, *self.tcx) + ImmTy::from_pair(res, overflow, self) } else { res }); @@ -279,7 +279,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let res = ImmTy::from_scalar_int(result, left.layout); if with_overflow { let overflow = ImmTy::from_bool(overflow, *self.tcx); - ImmTy::from_pair(res, overflow, *self.tcx) + ImmTy::from_pair(res, overflow, self) } else { res } diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs index a9ebf386617..6512675530a 100644 --- a/compiler/rustc_const_eval/src/interpret/stack.rs +++ b/compiler/rustc_const_eval/src/interpret/stack.rs @@ -584,8 +584,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { interp_ok(()) } + /// This is public because it is used by [Aquascope](https://github.com/cognitive-engineering-lab/aquascope/) + /// to analyze all the locals in a stack frame. #[inline(always)] - pub(super) fn layout_of_local( + pub fn layout_of_local( &self, frame: &Frame<'tcx, M::Provenance, M::FrameExtra>, local: mir::Local, diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index b61865be667..a26c2eca107 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -9,6 +9,7 @@ use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::{self, Instance, Ty}; use rustc_middle::{bug, mir, span_bug}; use rustc_span::source_map::Spanned; +use rustc_span::{DesugaringKind, Span}; use rustc_target::callconv::FnAbi; use tracing::{info, instrument, trace}; @@ -80,7 +81,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { use rustc_middle::mir::StatementKind::*; match &stmt.kind { - Assign(box (place, rvalue)) => self.eval_rvalue_into_place(rvalue, *place)?, + Assign(box (place, rvalue)) => { + self.eval_rvalue_into_place(rvalue, *place, stmt.source_info.span)? + } SetDiscriminant { place, variant_index } => { let dest = self.eval_place(**place)?; @@ -159,6 +162,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { &mut self, rvalue: &mir::Rvalue<'tcx>, place: mir::Place<'tcx>, + span: Span, ) -> InterpResult<'tcx> { let dest = self.eval_place(place)?; // FIXME: ensure some kind of non-aliasing between LHS and RHS? @@ -250,8 +254,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let src = self.eval_place(place)?; let place = self.force_allocation(&src)?; let mut val = ImmTy::from_immediate(place.to_ref(self), dest.layout); - if !place_base_raw { + if !place_base_raw + && span.desugaring_kind() != Some(DesugaringKind::IndexBoundsCheckReborrow) + { // If this was not already raw, it needs retagging. + // As a special hack, we exclude the desugared `PtrMetadata(&raw const *_n)` + // from indexing. (Really we should not do any retag on `&raw` but that does not + // currently work with Stacked Borrows.) val = M::retag_ptr_value(self, mir::RetagKind::Raw, &val)?; } self.write_immediate(*val, &dest)?; diff --git a/compiler/rustc_data_structures/src/jobserver.rs b/compiler/rustc_data_structures/src/jobserver.rs index d09f7efc8ff..1204f2d692d 100644 --- a/compiler/rustc_data_structures/src/jobserver.rs +++ b/compiler/rustc_data_structures/src/jobserver.rs @@ -1,6 +1,6 @@ use std::sync::{LazyLock, OnceLock}; -pub use jobserver_crate::Client; +pub use jobserver_crate::{Acquired, Client, HelperThread}; use jobserver_crate::{FromEnv, FromEnvErrorKind}; // We can only call `from_env_ext` once per process diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 2e01c385a66..b80736f41ad 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -45,7 +45,7 @@ use rustc_errors::registry::Registry; use rustc_errors::{ColorConfig, DiagCtxt, ErrCode, FatalError, PResult, markdown}; use rustc_feature::find_gated_cfg; use rustc_interface::util::{self, get_codegen_backend}; -use rustc_interface::{Linker, Queries, interface, passes}; +use rustc_interface::{Linker, interface, passes}; use rustc_lint::unerased_lint_store; use rustc_metadata::creader::MetadataLoader; use rustc_metadata::locator; @@ -158,13 +158,10 @@ pub trait Callbacks { /// Called after parsing the crate root. Submodules are not yet parsed when /// this callback is called. Return value instructs the compiler whether to /// continue the compilation afterwards (defaults to `Compilation::Continue`) - #[deprecated = "This callback will likely be removed or stop giving access \ - to the TyCtxt in the future. Use either the after_expansion \ - or the after_analysis callback instead."] - fn after_crate_root_parsing<'tcx>( + fn after_crate_root_parsing( &mut self, _compiler: &interface::Compiler, - _queries: &'tcx Queries<'tcx>, + _queries: &ast::Crate, ) -> Compilation { Compilation::Continue } @@ -173,7 +170,7 @@ pub trait Callbacks { fn after_expansion<'tcx>( &mut self, _compiler: &interface::Compiler, - _queries: &'tcx Queries<'tcx>, + _tcx: TyCtxt<'tcx>, ) -> Compilation { Compilation::Continue } @@ -350,6 +347,8 @@ fn run_compiler( callbacks.config(&mut config); + let registered_lints = config.register_lints.is_some(); + interface::run_compiler(config, |compiler| { let sess = &compiler.sess; let codegen_backend = &*compiler.codegen_backend; @@ -365,7 +364,7 @@ fn run_compiler( // `--help`/`-Zhelp`/`-Chelp`. This is the earliest it can run, because // it must happen after lints are registered, during session creation. if sess.opts.describe_lints { - describe_lints(sess); + describe_lints(sess, registered_lints); return early_exit(); } @@ -416,8 +415,9 @@ fn run_compiler( return early_exit(); } - #[allow(deprecated)] - if callbacks.after_crate_root_parsing(compiler, queries) == Compilation::Stop { + if callbacks.after_crate_root_parsing(compiler, &*queries.parse().borrow()) + == Compilation::Stop + { return early_exit(); } @@ -425,18 +425,18 @@ fn run_compiler( return early_exit(); } - // Make sure name resolution and macro expansion is run. - queries.global_ctxt().enter(|tcx| tcx.resolver_for_lowering()); + queries.global_ctxt().enter(|tcx| { + // Make sure name resolution and macro expansion is run. + let _ = tcx.resolver_for_lowering(); - if let Some(metrics_dir) = &sess.opts.unstable_opts.metrics_dir { - queries.global_ctxt().enter(|tcxt| dump_feature_usage_metrics(tcxt, metrics_dir)); - } + if let Some(metrics_dir) = &sess.opts.unstable_opts.metrics_dir { + dump_feature_usage_metrics(tcx, metrics_dir); + } - if callbacks.after_expansion(compiler, queries) == Compilation::Stop { - return early_exit(); - } + if callbacks.after_expansion(compiler, tcx) == Compilation::Stop { + return early_exit(); + } - queries.global_ctxt().enter(|tcx| { passes::write_dep_info(tcx); if sess.opts.output_types.contains_key(&OutputType::DepInfo) @@ -982,7 +982,7 @@ the command line flag directly. } /// Write to stdout lint command options, together with a list of all available lints -pub fn describe_lints(sess: &Session) { +pub fn describe_lints(sess: &Session, registered_lints: bool) { safe_println!( " Available lint options: @@ -1086,7 +1086,7 @@ Available lint options: print_lint_groups(builtin_groups, true); - match (sess.registered_lints, loaded.len(), loaded_groups.len()) { + match (registered_lints, loaded.len(), loaded_groups.len()) { (false, 0, _) | (false, _, 0) => { safe_println!("Lint tools like Clippy can load additional lints and lint groups."); } diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 1b6c6edcc61..ac2f91cdeb3 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -3048,11 +3048,19 @@ impl FileWithAnnotatedLines { // working correctly. let middle = min(ann.line_start + 4, ann.line_end); // We'll show up to 4 lines past the beginning of the multispan start. - // We will *not* include the tail of lines that are only whitespace. + // We will *not* include the tail of lines that are only whitespace, a comment or + // a bare delimiter. + let filter = |s: &str| { + let s = s.trim(); + // Consider comments as empty, but don't consider docstrings to be empty. + !(s.starts_with("//") && !(s.starts_with("///") || s.starts_with("//!"))) + // Consider lines with nothing but whitespace, a single delimiter as empty. + && !["", "{", "}", "(", ")", "[", "]"].contains(&s) + }; let until = (ann.line_start..middle) .rev() .filter_map(|line| file.get_line(line - 1).map(|s| (line + 1, s))) - .find(|(_, s)| !s.trim().is_empty()) + .find(|(_, s)| filter(s)) .map(|(line, _)| line) .unwrap_or(ann.line_start); for line in ann.line_start + 1..until { @@ -3060,7 +3068,8 @@ impl FileWithAnnotatedLines { add_annotation_to_file(&mut output, Lrc::clone(&file), line, ann.as_line()); } let line_end = ann.line_end - 1; - if middle < line_end { + let end_is_empty = file.get_line(line_end - 1).map_or(false, |s| !filter(&s)); + if middle < line_end && !end_is_empty { add_annotation_to_file(&mut output, Lrc::clone(&file), line_end, ann.as_line()); } } else { diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 6a6496f9827..690e080fbfc 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -723,7 +723,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { item_inner.kind, ItemKind::Mod( _, - ModKind::Unloaded | ModKind::Loaded(_, Inline::No, _), + ModKind::Unloaded | ModKind::Loaded(_, Inline::No, _, _), ) ) => { @@ -889,7 +889,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { fn visit_item(&mut self, item: &'ast ast::Item) { match &item.kind { ItemKind::Mod(_, mod_kind) - if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) => + if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _, _)) => { feature_err( self.sess, @@ -1195,7 +1195,7 @@ impl InvocationCollectorNode for P<ast::Item> { let ecx = &mut collector.cx; let (file_path, dir_path, dir_ownership) = match mod_kind { - ModKind::Loaded(_, inline, _) => { + ModKind::Loaded(_, inline, _, _) => { // Inline `mod foo { ... }`, but we still need to push directories. let (dir_path, dir_ownership) = mod_dir_path( ecx.sess, @@ -1217,15 +1217,21 @@ impl InvocationCollectorNode for P<ast::Item> { ModKind::Unloaded => { // We have an outline `mod foo;` so we need to parse the file. let old_attrs_len = attrs.len(); - let ParsedExternalMod { items, spans, file_path, dir_path, dir_ownership } = - parse_external_mod( - ecx.sess, - ident, - span, - &ecx.current_expansion.module, - ecx.current_expansion.dir_ownership, - &mut attrs, - ); + let ParsedExternalMod { + items, + spans, + file_path, + dir_path, + dir_ownership, + had_parse_error, + } = parse_external_mod( + ecx.sess, + ident, + span, + &ecx.current_expansion.module, + ecx.current_expansion.dir_ownership, + &mut attrs, + ); if let Some(lint_store) = ecx.lint_store { lint_store.pre_expansion_lint( @@ -1239,7 +1245,7 @@ impl InvocationCollectorNode for P<ast::Item> { ); } - *mod_kind = ModKind::Loaded(items, Inline::No, spans); + *mod_kind = ModKind::Loaded(items, Inline::No, spans, had_parse_error); node.attrs = attrs; if node.attrs.len() > old_attrs_len { // If we loaded an out-of-line module and added some inner attributes, diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index 614f52bbd28..85ea42e78ad 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -37,6 +37,7 @@ pub(crate) struct ParsedExternalMod { pub file_path: PathBuf, pub dir_path: PathBuf, pub dir_ownership: DirOwnership, + pub had_parse_error: Result<(), ErrorGuaranteed>, } pub enum ModError<'a> { @@ -74,14 +75,17 @@ pub(crate) fn parse_external_mod( attrs.extend(inner_attrs); (items, inner_span, mp.file_path) }; + // (1) ...instead, we return a dummy module. - let (items, spans, file_path) = - result.map_err(|err| err.report(sess, span)).unwrap_or_default(); + let ((items, spans, file_path), had_parse_error) = match result { + Err(err) => (Default::default(), Err(err.report(sess, span))), + Ok(result) => (result, Ok(())), + }; // Extract the directory path for submodules of the module. let dir_path = file_path.parent().unwrap_or(&file_path).to_owned(); - ParsedExternalMod { items, spans, file_path, dir_path, dir_ownership } + ParsedExternalMod { items, spans, file_path, dir_path, dir_ownership, had_parse_error } } pub(crate) fn mod_dir_path( diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 8b4f441dafe..e25840ba5fc 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -126,9 +126,6 @@ declare_features! ( better implied higher-ranked implied bounds support" ) ), - /// Allows `impl Trait` in bindings (`let`, `const`, `static`). - (removed, impl_trait_in_bindings, "1.55.0", Some(63065), - Some("the implementation was not maintainable, the feature may get reintroduced once the current refactorings are done")), (removed, import_shadowing, "1.0.0", None, None), /// Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`). (removed, in_band_lifetimes, "1.23.0", Some(44524), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 3c9115be7f5..45c63b03fe9 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -342,6 +342,7 @@ declare_features! ( (unstable, sse4a_target_feature, "1.27.0", Some(44839)), (unstable, tbm_target_feature, "1.27.0", Some(44839)), (unstable, wasm_target_feature, "1.30.0", Some(44839)), + (unstable, x87_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)), // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way. // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! @@ -516,6 +517,8 @@ declare_features! ( (unstable, if_let_guard, "1.47.0", Some(51114)), /// Allows `impl Trait` to be used inside associated types (RFC 2515). (unstable, impl_trait_in_assoc_type, "1.70.0", Some(63063)), + /// Allows `impl Trait` in bindings (`let`). + (unstable, impl_trait_in_bindings, "1.64.0", Some(63065)), /// Allows `impl Trait` as output type in `Fn` traits in return position of functions. (unstable, impl_trait_in_fn_trait_return, "1.64.0", Some(99697)), /// Allows associated types in inherent impls. @@ -635,6 +638,8 @@ declare_features! ( /// Allows creation of instances of a struct by moving fields that have /// not changed from prior instances of the same struct (RFC #2528) (unstable, type_changing_struct_update, "1.58.0", Some(86555)), + /// Allows using `unsafe<'a> &'a T` unsafe binder types. + (incomplete, unsafe_binders, "CURRENT_RUSTC_VERSION", Some(130516)), /// Allows declaring fields `unsafe`. (incomplete, unsafe_fields, "CURRENT_RUSTC_VERSION", Some(132922)), /// Allows const generic parameters to be defined with types that diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 4800a479ff4..2e795d84559 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -8,7 +8,7 @@ use rustc_ast::{ }; pub use rustc_ast::{ BinOp, BinOpKind, BindingMode, BorrowKind, BoundConstness, BoundPolarity, ByRef, CaptureBy, - ImplPolarity, IsAuto, Movability, Mutability, UnOp, + ImplPolarity, IsAuto, Movability, Mutability, UnOp, UnsafeBinderCastKind, }; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::sorted_map::SortedMap; @@ -1740,6 +1740,7 @@ impl Expr<'_> { | ExprKind::Struct(..) | ExprKind::Tup(_) | ExprKind::Type(..) + | ExprKind::UnsafeBinderCast(..) | ExprKind::Err(_) => ExprPrecedence::Unambiguous, ExprKind::DropTemps(ref expr, ..) => expr.precedence(), @@ -1769,6 +1770,9 @@ impl Expr<'_> { // https://github.com/rust-lang/rfcs/blob/master/text/0803-type-ascription.md#type-ascription-and-temporaries ExprKind::Type(ref e, _) => e.is_place_expr(allow_projections_from), + // Unsafe binder cast preserves place-ness of the sub-expression. + ExprKind::UnsafeBinderCast(_, e, _) => e.is_place_expr(allow_projections_from), + ExprKind::Unary(UnOp::Deref, _) => true, ExprKind::Field(ref base, _) | ExprKind::Index(ref base, _, _) => { @@ -1850,7 +1854,8 @@ impl Expr<'_> { | ExprKind::Field(base, _) | ExprKind::Index(base, _, _) | ExprKind::AddrOf(.., base) - | ExprKind::Cast(base, _) => { + | ExprKind::Cast(base, _) + | ExprKind::UnsafeBinderCast(_, base, _) => { // This isn't exactly true for `Index` and all `Unary`, but we are using this // method exclusively for diagnostics and there's a *cultural* pressure against // them being used only for its side-effects. @@ -2020,6 +2025,22 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool { } } +/// Checks if the specified expression needs parentheses for prefix +/// or postfix suggestions to be valid. +/// For example, `a + b` requires parentheses to suggest `&(a + b)`, +/// but just `a` does not. +/// Similarly, `(a + b).c()` also requires parentheses. +/// This should not be used for other types of suggestions. +pub fn expr_needs_parens(expr: &Expr<'_>) -> bool { + match expr.kind { + // parenthesize if needed (Issue #46756) + ExprKind::Cast(_, _) | ExprKind::Binary(_, _, _) => true, + // parenthesize borrows of range literals (Issue #54505) + _ if is_range_literal(expr) => true, + _ => false, + } +} + #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum ExprKind<'hir> { /// Allow anonymous constants from an inline `const` block @@ -2144,6 +2165,10 @@ pub enum ExprKind<'hir> { /// A suspension point for coroutines (i.e., `yield <expr>`). Yield(&'hir Expr<'hir>, YieldSource), + /// Operators which can be used to interconvert `unsafe` binder types. + /// e.g. `unsafe<'a> &'a i32` <=> `&i32`. + UnsafeBinderCast(UnsafeBinderCastKind, &'hir Expr<'hir>, Option<&'hir Ty<'hir>>), + /// A placeholder for an expression that wasn't syntactically well formed in some way. Err(rustc_span::ErrorGuaranteed), } @@ -2781,6 +2806,12 @@ pub struct BareFnTy<'hir> { } #[derive(Debug, Clone, Copy, HashStable_Generic)] +pub struct UnsafeBinderTy<'hir> { + pub generic_params: &'hir [GenericParam<'hir>], + pub inner_ty: &'hir Ty<'hir>, +} + +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct OpaqueTy<'hir> { pub hir_id: HirId, pub def_id: LocalDefId, @@ -2878,6 +2909,8 @@ pub enum TyKind<'hir> { Ref(&'hir Lifetime, MutTy<'hir>), /// A bare function (e.g., `fn(usize) -> bool`). BareFn(&'hir BareFnTy<'hir>), + /// An unsafe binder type (e.g. `unsafe<'a> Foo<'a>`). + UnsafeBinder(&'hir UnsafeBinderTy<'hir>), /// The never type (`!`). Never, /// A tuple (`(A, B, C, D, ...)`). @@ -2889,6 +2922,8 @@ pub enum TyKind<'hir> { Path(QPath<'hir>), /// An opaque type definition itself. This is only used for `impl Trait`. OpaqueDef(&'hir OpaqueTy<'hir>), + /// A trait ascription type, which is `impl Trait` within a local binding. + TraitAscription(GenericBounds<'hir>), /// A trait object type `Bound1 + Bound2 + Bound3` /// where `Bound` is a trait or a lifetime. TraitObject(&'hir [PolyTraitRef<'hir>], &'hir Lifetime, TraitObjectSyntax), @@ -4042,9 +4077,7 @@ impl<'hir> Node<'hir> { _ => None, }, Node::TraitItem(ti) => match ti.kind { - TraitItemKind::Fn(ref sig, TraitFn::Provided(_)) => { - Some(FnKind::Method(ti.ident, sig)) - } + TraitItemKind::Fn(ref sig, _) => Some(FnKind::Method(ti.ident, sig)), _ => None, }, Node::ImplItem(ii) => match ii.kind { diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 8dbfefffee4..6d481f7536a 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -857,6 +857,10 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) ExprKind::Yield(ref subexpression, _) => { try_visit!(visitor.visit_expr(subexpression)); } + ExprKind::UnsafeBinderCast(_kind, expr, ty) => { + try_visit!(visitor.visit_expr(expr)); + visit_opt!(visitor, visit_ty, ty); + } ExprKind::Lit(_) | ExprKind::Err(_) => {} } V::Result::output() @@ -886,12 +890,19 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul walk_list!(visitor, visit_generic_param, function_declaration.generic_params); try_visit!(visitor.visit_fn_decl(function_declaration.decl)); } + TyKind::UnsafeBinder(ref unsafe_binder) => { + walk_list!(visitor, visit_generic_param, unsafe_binder.generic_params); + try_visit!(visitor.visit_ty(unsafe_binder.inner_ty)); + } TyKind::Path(ref qpath) => { try_visit!(visitor.visit_qpath(qpath, typ.hir_id, typ.span)); } TyKind::OpaqueDef(opaque) => { try_visit!(visitor.visit_opaque_ty(opaque)); } + TyKind::TraitAscription(bounds) => { + walk_list!(visitor, visit_param_bound, bounds); + } TyKind::Array(ref ty, ref length) => { try_visit!(visitor.visit_ty(ty)); try_visit!(visitor.visit_const_arg(length)); diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 25feb95d5df..0c3ed9b5c60 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -246,6 +246,18 @@ hir_analysis_invalid_receiver_ty = invalid `self` parameter type: `{$receiver_ty hir_analysis_invalid_receiver_ty_help = consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` +hir_analysis_invalid_receiver_ty_help_no_arbitrary_self_types = + consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) + +hir_analysis_invalid_receiver_ty_help_nonnull_note = + `NonNull` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `NonNull` in a newtype wrapper for which you implement `Receiver` + +hir_analysis_invalid_receiver_ty_help_weak_note = + `Weak` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `Weak` in a newtype wrapper for which you implement `Receiver` + +hir_analysis_invalid_receiver_ty_no_arbitrary_self_types = invalid `self` parameter type: `{$receiver_ty}` + .note = type of `self` must be `Self` or a type that dereferences to it + hir_analysis_invalid_union_field = field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union .note = union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 57264d0bd2a..95ad8225f61 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -44,6 +44,7 @@ use {rustc_ast as ast, rustc_hir as hir}; use crate::autoderef::Autoderef; use crate::collect::CollectItemTypesVisitor; use crate::constrained_generic_params::{Parameter, identify_constrained_generic_params}; +use crate::errors::InvalidReceiverTyHint; use crate::{errors, fluent_generated as fluent}; pub(super) struct WfCheckingCtxt<'a, 'tcx> { @@ -1748,8 +1749,25 @@ fn check_method_receiver<'tcx>( // Report error; would not have worked with `arbitrary_self_types[_pointers]`. { match receiver_validity_err { + ReceiverValidityError::DoesNotDeref if arbitrary_self_types_level.is_some() => { + let hint = match receiver_ty + .builtin_deref(false) + .unwrap_or(receiver_ty) + .ty_adt_def() + .and_then(|adt_def| tcx.get_diagnostic_name(adt_def.did())) + { + Some(sym::RcWeak | sym::ArcWeak) => Some(InvalidReceiverTyHint::Weak), + Some(sym::NonNull) => Some(InvalidReceiverTyHint::NonNull), + _ => None, + }; + + tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty, hint }) + } ReceiverValidityError::DoesNotDeref => { - tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty }) + tcx.dcx().emit_err(errors::InvalidReceiverTyNoArbitrarySelfTypes { + span, + receiver_ty, + }) } ReceiverValidityError::MethodGenericParamUsed => { tcx.dcx().emit_err(errors::InvalidGenericReceiverTy { span, receiver_ty }) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 96d2714252a..8c9da78a659 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -29,7 +29,7 @@ use rustc_errors::{ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor, walk_generics}; -use rustc_hir::{self as hir, GenericParamKind, Node}; +use rustc_hir::{self as hir, GenericParamKind, HirId, Node}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::hir::nested_filter; @@ -201,12 +201,13 @@ pub(crate) fn placeholder_type_error_diag<'cx, 'tcx>( placeholder_types.iter().map(|sp| (*sp, (*type_name).to_string())).collect(); if let Some(generics) = generics { - if let Some(arg) = params.iter().find(|arg| { - matches!(arg.name, hir::ParamName::Plain(Ident { name: kw::Underscore, .. })) + if let Some(span) = params.iter().find_map(|arg| match arg.name { + hir::ParamName::Plain(Ident { name: kw::Underscore, span }) => Some(span), + _ => None, }) { // Account for `_` already present in cases like `struct S<_>(_);` and suggest // `struct S<T>(T);` instead of `struct S<_, T>(T);`. - sugg.push((arg.span, (*type_name).to_string())); + sugg.push((span, (*type_name).to_string())); } else if let Some(span) = generics.span_for_param_suggestion() { // Account for bounds, we want `fn foo<T: E, K>(_: K)` not `fn foo<T, K: E>(_: K)`. sugg.push((span, format!(", {type_name}"))); @@ -436,6 +437,15 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { ty::Const::new_error_with_message(self.tcx(), span, "bad placeholder constant") } + fn register_trait_ascription_bounds( + &self, + _: Vec<(ty::Clause<'tcx>, Span)>, + _: HirId, + span: Span, + ) { + self.dcx().span_delayed_bug(span, "trait ascription type not allowed here"); + } + fn probe_ty_param_bounds( &self, span: Span, @@ -1330,7 +1340,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn .. }) | Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), .. }) => { - infer_return_ty_for_fn_sig(sig, generics, def_id, &icx) + lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id) } ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => { @@ -1347,7 +1357,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn None, ) } else { - infer_return_ty_for_fn_sig(sig, generics, def_id, &icx) + lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id) } } @@ -1397,99 +1407,108 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn ty::EarlyBinder::bind(output) } -fn infer_return_ty_for_fn_sig<'tcx>( - sig: &hir::FnSig<'tcx>, - generics: &hir::Generics<'_>, +fn lower_fn_sig_recovering_infer_ret_ty<'tcx>( + icx: &ItemCtxt<'tcx>, + sig: &'tcx hir::FnSig<'tcx>, + generics: &'tcx hir::Generics<'tcx>, def_id: LocalDefId, +) -> ty::PolyFnSig<'tcx> { + if let Some(infer_ret_ty) = sig.decl.output.get_infer_ret_ty() { + return recover_infer_ret_ty(icx, infer_ret_ty, generics, def_id); + } + + icx.lowerer().lower_fn_ty( + icx.tcx().local_def_id_to_hir_id(def_id), + sig.header.safety, + sig.header.abi, + sig.decl, + Some(generics), + None, + ) +} + +fn recover_infer_ret_ty<'tcx>( icx: &ItemCtxt<'tcx>, + infer_ret_ty: &'tcx hir::Ty<'tcx>, + generics: &'tcx hir::Generics<'tcx>, + def_id: LocalDefId, ) -> ty::PolyFnSig<'tcx> { let tcx = icx.tcx; let hir_id = tcx.local_def_id_to_hir_id(def_id); - match sig.decl.output.get_infer_ret_ty() { - Some(ty) => { - let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id]; - // Typeck doesn't expect erased regions to be returned from `type_of`. - // This is a heuristic approach. If the scope has region parameters, - // we should change fn_sig's lifetime from `ReErased` to `ReError`, - // otherwise to `ReStatic`. - let has_region_params = generics.params.iter().any(|param| match param.kind { - GenericParamKind::Lifetime { .. } => true, - _ => false, - }); - let fn_sig = fold_regions(tcx, fn_sig, |r, _| match *r { - ty::ReErased => { - if has_region_params { - ty::Region::new_error_with_message( - tcx, - DUMMY_SP, - "erased region is not allowed here in return type", - ) - } else { - tcx.lifetimes.re_static - } - } - _ => r, - }); + let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id]; - let mut visitor = HirPlaceholderCollector::default(); - visitor.visit_ty(ty); - - let mut diag = bad_placeholder(icx.lowerer(), visitor.0, "return type"); - let ret_ty = fn_sig.output(); - // Don't leak types into signatures unless they're nameable! - // For example, if a function returns itself, we don't want that - // recursive function definition to leak out into the fn sig. - let mut recovered_ret_ty = None; - - if let Some(suggestable_ret_ty) = ret_ty.make_suggestable(tcx, false, None) { - diag.span_suggestion( - ty.span, - "replace with the correct return type", - suggestable_ret_ty, - Applicability::MachineApplicable, - ); - recovered_ret_ty = Some(suggestable_ret_ty); - } else if let Some(sugg) = suggest_impl_trait( - &tcx.infer_ctxt().build(TypingMode::non_body_analysis()), - tcx.param_env(def_id), - ret_ty, - ) { - diag.span_suggestion( - ty.span, - "replace with an appropriate return type", - sugg, - Applicability::MachineApplicable, - ); - } else if ret_ty.is_closure() { - diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound"); - } - // Also note how `Fn` traits work just in case! - if ret_ty.is_closure() { - diag.note( - "for more information on `Fn` traits and closure types, see \ - https://doc.rust-lang.org/book/ch13-01-closures.html", - ); + // Typeck doesn't expect erased regions to be returned from `type_of`. + // This is a heuristic approach. If the scope has region parameters, + // we should change fn_sig's lifetime from `ReErased` to `ReError`, + // otherwise to `ReStatic`. + let has_region_params = generics.params.iter().any(|param| match param.kind { + GenericParamKind::Lifetime { .. } => true, + _ => false, + }); + let fn_sig = fold_regions(tcx, fn_sig, |r, _| match *r { + ty::ReErased => { + if has_region_params { + ty::Region::new_error_with_message( + tcx, + DUMMY_SP, + "erased region is not allowed here in return type", + ) + } else { + tcx.lifetimes.re_static } - - let guar = diag.emit(); - ty::Binder::dummy(tcx.mk_fn_sig( - fn_sig.inputs().iter().copied(), - recovered_ret_ty.unwrap_or_else(|| Ty::new_error(tcx, guar)), - fn_sig.c_variadic, - fn_sig.safety, - fn_sig.abi, - )) } - None => icx.lowerer().lower_fn_ty( - hir_id, - sig.header.safety, - sig.header.abi, - sig.decl, - Some(generics), - None, - ), + _ => r, + }); + + let mut visitor = HirPlaceholderCollector::default(); + visitor.visit_ty(infer_ret_ty); + + let mut diag = bad_placeholder(icx.lowerer(), visitor.0, "return type"); + let ret_ty = fn_sig.output(); + + // Don't leak types into signatures unless they're nameable! + // For example, if a function returns itself, we don't want that + // recursive function definition to leak out into the fn sig. + let mut recovered_ret_ty = None; + if let Some(suggestable_ret_ty) = ret_ty.make_suggestable(tcx, false, None) { + diag.span_suggestion( + infer_ret_ty.span, + "replace with the correct return type", + suggestable_ret_ty, + Applicability::MachineApplicable, + ); + recovered_ret_ty = Some(suggestable_ret_ty); + } else if let Some(sugg) = suggest_impl_trait( + &tcx.infer_ctxt().build(TypingMode::non_body_analysis()), + tcx.param_env(def_id), + ret_ty, + ) { + diag.span_suggestion( + infer_ret_ty.span, + "replace with an appropriate return type", + sugg, + Applicability::MachineApplicable, + ); + } else if ret_ty.is_closure() { + diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound"); } + + // Also note how `Fn` traits work just in case! + if ret_ty.is_closure() { + diag.note( + "for more information on `Fn` traits and closure types, see \ + https://doc.rust-lang.org/book/ch13-01-closures.html", + ); + } + let guar = diag.emit(); + ty::Binder::dummy(tcx.mk_fn_sig( + fn_sig.inputs().iter().copied(), + recovered_ret_ty.unwrap_or_else(|| Ty::new_error(tcx, guar)), + fn_sig.c_variadic, + fn_sig.safety, + fn_sig.abi, + )) } pub fn suggest_impl_trait<'tcx>( @@ -1611,7 +1630,7 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTrai impl_.of_trait.as_ref().map(|ast_trait_ref| { let selfty = tcx.type_of(def_id).instantiate_identity(); - check_impl_constness(tcx, tcx.is_const_trait_impl(def_id.to_def_id()), ast_trait_ref); + check_impl_constness(tcx, impl_.constness, ast_trait_ref); let trait_ref = icx.lowerer().lower_impl_trait_ref(ast_trait_ref, selfty); @@ -1619,22 +1638,23 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTrai trait_ref: ty::EarlyBinder::bind(trait_ref), safety: impl_.safety, polarity: polarity_of_impl(tcx, def_id, impl_, item.span), + constness: impl_.constness, } }) } fn check_impl_constness( tcx: TyCtxt<'_>, - is_const: bool, + constness: hir::Constness, hir_trait_ref: &hir::TraitRef<'_>, -) -> Option<ErrorGuaranteed> { - if !is_const { - return None; +) { + if let hir::Constness::NotConst = constness { + return; } - let trait_def_id = hir_trait_ref.trait_def_id()?; + let Some(trait_def_id) = hir_trait_ref.trait_def_id() else { return }; if tcx.is_const_trait(trait_def_id) { - return None; + return; } let trait_name = tcx.item_name(trait_def_id).to_string(); @@ -1650,14 +1670,14 @@ fn check_impl_constness( ), (false, _) | (_, false) => (None, ""), }; - Some(tcx.dcx().emit_err(errors::ConstImplForNonConstTrait { + tcx.dcx().emit_err(errors::ConstImplForNonConstTrait { trait_ref_span: hir_trait_ref.path.span, trait_name, local_trait_span, suggestion_pre, marking: (), adding: (), - })) + }); } fn polarity_of_impl( diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 1d9114b0ef3..f52d4f42eca 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -470,6 +470,12 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S self.outer_index.shift_out(1); res } + hir::TyKind::UnsafeBinder(_) => { + self.outer_index.shift_in(1); + let res = intravisit::walk_ty(self, ty); + self.outer_index.shift_out(1); + res + } _ => intravisit::walk_ty(self, ty), } } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 74f381d2661..0f797bcdae4 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -781,6 +781,36 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { intravisit::walk_ty(this, ty); }); } + hir::TyKind::UnsafeBinder(binder) => { + let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) = + binder + .generic_params + .iter() + .enumerate() + .map(|(late_bound_idx, param)| { + ( + (param.def_id, ResolvedArg::late(late_bound_idx as u32, param)), + late_arg_as_bound_arg(self.tcx, param), + ) + }) + .unzip(); + + deny_non_region_late_bound(self.tcx, &mut bound_vars, "function pointer types"); + + self.record_late_bound_vars(ty.hir_id, binders); + let scope = Scope::Binder { + hir_id: ty.hir_id, + bound_vars, + s: self.scope, + scope_type: BinderScopeType::Normal, + where_bound_origin: None, + }; + self.with(scope, |this| { + // a bare fn has no bounds, so everything + // contained within is scoped within its binder. + intravisit::walk_ty(this, ty); + }); + } hir::TyKind::TraitObject(bounds, lifetime, _) => { debug!(?bounds, ?lifetime, "TraitObject"); let scope = Scope::TraitRefBoundary { s: self.scope }; @@ -822,6 +852,21 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { }; self.with(scope, |this| this.visit_ty(mt.ty)); } + hir::TyKind::TraitAscription(bounds) => { + let scope = Scope::TraitRefBoundary { s: self.scope }; + self.with(scope, |this| { + let scope = Scope::LateBoundary { + s: this.scope, + what: "`impl Trait` in binding", + deny_late_regions: true, + }; + this.with(scope, |this| { + for bound in bounds { + this.visit_param_bound(bound); + } + }) + }); + } _ => intravisit::walk_ty(self, ty), } } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 7f62ccc91f0..d46f60b16f5 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1655,6 +1655,24 @@ pub(crate) struct NonConstRange { pub span: Span, } +#[derive(Subdiagnostic)] +pub(crate) enum InvalidReceiverTyHint { + #[note(hir_analysis_invalid_receiver_ty_help_weak_note)] + Weak, + #[note(hir_analysis_invalid_receiver_ty_help_nonnull_note)] + NonNull, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_invalid_receiver_ty_no_arbitrary_self_types, code = E0307)] +#[note] +#[help(hir_analysis_invalid_receiver_ty_help_no_arbitrary_self_types)] +pub(crate) struct InvalidReceiverTyNoArbitrarySelfTypes<'tcx> { + #[primary_span] + pub span: Span, + pub receiver_ty: Ty<'tcx>, +} + #[derive(Diagnostic)] #[diag(hir_analysis_invalid_receiver_ty, code = E0307)] #[note] @@ -1663,6 +1681,8 @@ pub(crate) struct InvalidReceiverTy<'tcx> { #[primary_span] pub span: Span, pub receiver_ty: Ty<'tcx>, + #[subdiagnostic] + pub hint: Option<InvalidReceiverTyHint>, } #[derive(Diagnostic)] diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index d3c86989440..71a5727ed6c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -1,9 +1,8 @@ -use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; +use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::DefId; use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS; use rustc_middle::span_bug; use rustc_middle::ty::fold::BottomUpFolder; @@ -11,7 +10,7 @@ use rustc_middle::ty::{ self, DynKind, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast, }; -use rustc_span::{ErrorGuaranteed, Span}; +use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility; use rustc_trait_selection::traits::{self, hir_ty_lowering_dyn_compatibility_violations}; use rustc_type_ir::elaborate::ClauseWithSupertraitSpan; @@ -128,8 +127,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - let mut associated_types: FxIndexMap<Span, FxIndexSet<DefId>> = FxIndexMap::default(); + let mut needed_associated_types = FxIndexSet::default(); + let principal_span = regular_traits.first().map_or(DUMMY_SP, |info| info.bottom().1); let regular_traits_refs_spans = trait_bounds .into_iter() .filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id())); @@ -145,13 +145,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let bound_predicate = pred.kind(); match bound_predicate.skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { - let pred = bound_predicate.rebind(pred); - associated_types.entry(original_span).or_default().extend( - tcx.associated_items(pred.def_id()) + // FIXME(negative_bounds): Handle this correctly... + let trait_ref = + tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref)); + needed_associated_types.extend( + tcx.associated_items(trait_ref.def_id()) .in_definition_order() .filter(|item| item.kind == ty::AssocKind::Type) .filter(|item| !item.is_impl_trait_in_trait()) - .map(|item| item.def_id), + // If the associated type has a `where Self: Sized` bound, + // we do not need to constrain the associated type. + .filter(|item| !tcx.generics_require_sized_self(item.def_id)) + .map(|item| (item.def_id, trait_ref)), ); } ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => { @@ -201,26 +206,25 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // So every `Projection` clause is an `Assoc = Foo` bound. `associated_types` contains all associated // types's `DefId`, so the following loop removes all the `DefIds` of the associated types that have a // corresponding `Projection` clause - for def_ids in associated_types.values_mut() { - for (projection_bound, span) in &projection_bounds { - let def_id = projection_bound.item_def_id(); - def_ids.swap_remove(&def_id); - if tcx.generics_require_sized_self(def_id) { - tcx.emit_node_span_lint( - UNUSED_ASSOCIATED_TYPE_BOUNDS, - hir_id, - *span, - crate::errors::UnusedAssociatedTypeBounds { span: *span }, - ); - } + for (projection_bound, span) in &projection_bounds { + let def_id = projection_bound.item_def_id(); + let trait_ref = tcx.anonymize_bound_vars( + projection_bound.map_bound(|p| p.projection_term.trait_ref(tcx)), + ); + needed_associated_types.swap_remove(&(def_id, trait_ref)); + if tcx.generics_require_sized_self(def_id) { + tcx.emit_node_span_lint( + UNUSED_ASSOCIATED_TYPE_BOUNDS, + hir_id, + *span, + crate::errors::UnusedAssociatedTypeBounds { span: *span }, + ); } - // If the associated type has a `where Self: Sized` bound, we do not need to constrain the associated - // type in the `dyn Trait`. - def_ids.retain(|def_id| !tcx.generics_require_sized_self(def_id)); } if let Err(guar) = self.check_for_required_assoc_tys( - associated_types, + principal_span, + needed_associated_types, potential_assoc_types, hir_trait_bounds, ) { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 2e227ead14a..00c1f9b332b 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -9,7 +9,6 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_middle::bug; -use rustc_middle::query::Key; use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _}; use rustc_middle::ty::{ self, AdtDef, Binder, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeVisitableExt, @@ -722,51 +721,42 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// emit a generic note suggesting using a `where` clause to constraint instead. pub(crate) fn check_for_required_assoc_tys( &self, - associated_types: FxIndexMap<Span, FxIndexSet<DefId>>, + principal_span: Span, + missing_assoc_types: FxIndexSet<(DefId, ty::PolyTraitRef<'tcx>)>, potential_assoc_types: Vec<usize>, trait_bounds: &[hir::PolyTraitRef<'_>], ) -> Result<(), ErrorGuaranteed> { - if associated_types.values().all(|v| v.is_empty()) { + if missing_assoc_types.is_empty() { return Ok(()); } let tcx = self.tcx(); - // FIXME: Marked `mut` so that we can replace the spans further below with a more - // appropriate one, but this should be handled earlier in the span assignment. - let associated_types: FxIndexMap<Span, Vec<_>> = associated_types + // FIXME: This logic needs some more care w.r.t handling of conflicts + let missing_assoc_types: Vec<_> = missing_assoc_types .into_iter() - .map(|(span, def_ids)| { - (span, def_ids.into_iter().map(|did| tcx.associated_item(did)).collect()) - }) + .map(|(def_id, trait_ref)| (tcx.associated_item(def_id), trait_ref)) .collect(); - let mut names: FxIndexMap<String, Vec<Symbol>> = Default::default(); + let mut names: FxIndexMap<_, Vec<Symbol>> = Default::default(); let mut names_len = 0; // Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and // `issue-22560.rs`. - let mut trait_bound_spans: Vec<Span> = vec![]; let mut dyn_compatibility_violations = Ok(()); - for (span, items) in &associated_types { - if !items.is_empty() { - trait_bound_spans.push(*span); - } - for assoc_item in items { - let trait_def_id = assoc_item.container_id(tcx); - names.entry(tcx.def_path_str(trait_def_id)).or_default().push(assoc_item.name); - names_len += 1; - - let violations = - dyn_compatibility_violations_for_assoc_item(tcx, trait_def_id, *assoc_item); - if !violations.is_empty() { - dyn_compatibility_violations = Err(report_dyn_incompatibility( - tcx, - *span, - None, - trait_def_id, - &violations, - ) - .emit()); - } + for (assoc_item, trait_ref) in &missing_assoc_types { + names.entry(trait_ref).or_default().push(assoc_item.name); + names_len += 1; + + let violations = + dyn_compatibility_violations_for_assoc_item(tcx, trait_ref.def_id(), *assoc_item); + if !violations.is_empty() { + dyn_compatibility_violations = Err(report_dyn_incompatibility( + tcx, + principal_span, + None, + trait_ref.def_id(), + &violations, + ) + .emit()); } } @@ -814,6 +804,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .into_iter() .map(|(trait_, mut assocs)| { assocs.sort(); + let trait_ = trait_.print_trait_sugared(); format!("{} in `{trait_}`", match &assocs[..] { [] => String::new(), [only] => format!("`{only}`"), @@ -827,10 +818,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { names.sort(); let names = names.join(", "); - trait_bound_spans.sort(); let mut err = struct_span_code_err!( self.dcx(), - trait_bound_spans, + principal_span, E0191, "the value of the associated type{} {} must be specified", pluralize!(names_len), @@ -840,81 +830,83 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut types_count = 0; let mut where_constraints = vec![]; let mut already_has_generics_args_suggestion = false; - for (span, assoc_items) in &associated_types { - let mut names: UnordMap<_, usize> = Default::default(); - for item in assoc_items { - types_count += 1; - *names.entry(item.name).or_insert(0) += 1; - } - let mut dupes = false; - let mut shadows = false; - for item in assoc_items { - let prefix = if names[&item.name] > 1 { - let trait_def_id = item.container_id(tcx); - dupes = true; - format!("{}::", tcx.def_path_str(trait_def_id)) - } else if bound_names.get(&item.name).is_some_and(|x| x != &item) { - let trait_def_id = item.container_id(tcx); - shadows = true; - format!("{}::", tcx.def_path_str(trait_def_id)) - } else { - String::new() - }; - let mut is_shadowed = false; - - if let Some(assoc_item) = bound_names.get(&item.name) - && assoc_item != &item - { - is_shadowed = true; + let mut names: UnordMap<_, usize> = Default::default(); + for (item, _) in &missing_assoc_types { + types_count += 1; + *names.entry(item.name).or_insert(0) += 1; + } + let mut dupes = false; + let mut shadows = false; + for (item, trait_ref) in &missing_assoc_types { + let prefix = if names[&item.name] > 1 { + let trait_def_id = trait_ref.def_id(); + dupes = true; + format!("{}::", tcx.def_path_str(trait_def_id)) + } else if bound_names.get(&item.name).is_some_and(|x| *x != item) { + let trait_def_id = trait_ref.def_id(); + shadows = true; + format!("{}::", tcx.def_path_str(trait_def_id)) + } else { + String::new() + }; - let rename_message = - if assoc_item.def_id.is_local() { ", consider renaming it" } else { "" }; - err.span_label( - tcx.def_span(assoc_item.def_id), - format!("`{}{}` shadowed here{}", prefix, item.name, rename_message), - ); - } + let mut is_shadowed = false; - let rename_message = if is_shadowed { ", consider renaming it" } else { "" }; + if let Some(assoc_item) = bound_names.get(&item.name) + && *assoc_item != item + { + is_shadowed = true; - if let Some(sp) = tcx.hir().span_if_local(item.def_id) { - err.span_label( - sp, - format!("`{}{}` defined here{}", prefix, item.name, rename_message), - ); - } + let rename_message = + if assoc_item.def_id.is_local() { ", consider renaming it" } else { "" }; + err.span_label( + tcx.def_span(assoc_item.def_id), + format!("`{}{}` shadowed here{}", prefix, item.name, rename_message), + ); } - if potential_assoc_types.len() == assoc_items.len() { - // When the amount of missing associated types equals the number of - // extra type arguments present. A suggesting to replace the generic args with - // associated types is already emitted. - already_has_generics_args_suggestion = true; - } else if let (Ok(snippet), false, false) = - (tcx.sess.source_map().span_to_snippet(*span), dupes, shadows) - { - let types: Vec<_> = - assoc_items.iter().map(|item| format!("{} = Type", item.name)).collect(); - let code = if snippet.ends_with('>') { - // The user wrote `Trait<'a>` or similar and we don't have a type we can - // suggest, but at least we can clue them to the correct syntax - // `Trait<'a, Item = Type>` while accounting for the `<'a>` in the - // suggestion. - format!("{}, {}>", &snippet[..snippet.len() - 1], types.join(", ")) - } else if in_expr_or_pat { - // The user wrote `Iterator`, so we don't have a type we can suggest, but at - // least we can clue them to the correct syntax `Iterator::<Item = Type>`. - format!("{}::<{}>", snippet, types.join(", ")) - } else { - // The user wrote `Iterator`, so we don't have a type we can suggest, but at - // least we can clue them to the correct syntax `Iterator<Item = Type>`. - format!("{}<{}>", snippet, types.join(", ")) - }; - suggestions.push((*span, code)); - } else if dupes { - where_constraints.push(*span); + + let rename_message = if is_shadowed { ", consider renaming it" } else { "" }; + + if let Some(sp) = tcx.hir().span_if_local(item.def_id) { + err.span_label( + sp, + format!("`{}{}` defined here{}", prefix, item.name, rename_message), + ); } } + if potential_assoc_types.len() == missing_assoc_types.len() { + // When the amount of missing associated types equals the number of + // extra type arguments present. A suggesting to replace the generic args with + // associated types is already emitted. + already_has_generics_args_suggestion = true; + } else if let (Ok(snippet), false, false) = + (tcx.sess.source_map().span_to_snippet(principal_span), dupes, shadows) + { + let types: Vec<_> = missing_assoc_types + .iter() + .map(|(item, _)| format!("{} = Type", item.name)) + .collect(); + let code = if snippet.ends_with('>') { + // The user wrote `Trait<'a>` or similar and we don't have a type we can + // suggest, but at least we can clue them to the correct syntax + // `Trait<'a, Item = Type>` while accounting for the `<'a>` in the + // suggestion. + format!("{}, {}>", &snippet[..snippet.len() - 1], types.join(", ")) + } else if in_expr_or_pat { + // The user wrote `Iterator`, so we don't have a type we can suggest, but at + // least we can clue them to the correct syntax `Iterator::<Item = Type>`. + format!("{}::<{}>", snippet, types.join(", ")) + } else { + // The user wrote `Iterator`, so we don't have a type we can suggest, but at + // least we can clue them to the correct syntax `Iterator<Item = Type>`. + format!("{}<{}>", snippet, types.join(", ")) + }; + suggestions.push((principal_span, code)); + } else if dupes { + where_constraints.push(principal_span); + } + let where_msg = "consider introducing a new type parameter, adding `where` constraints \ using the fully-qualified path to the associated types"; if !where_constraints.is_empty() && suggestions.is_empty() { @@ -925,32 +917,29 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } if suggestions.len() != 1 || already_has_generics_args_suggestion { // We don't need this label if there's an inline suggestion, show otherwise. - for (span, assoc_items) in &associated_types { - let mut names: FxIndexMap<_, usize> = FxIndexMap::default(); - for item in assoc_items { - types_count += 1; - *names.entry(item.name).or_insert(0) += 1; - } - let mut label = vec![]; - for item in assoc_items { - let postfix = if names[&item.name] > 1 { - let trait_def_id = item.container_id(tcx); - format!(" (from trait `{}`)", tcx.def_path_str(trait_def_id)) - } else { - String::new() - }; - label.push(format!("`{}`{}", item.name, postfix)); - } - if !label.is_empty() { - err.span_label( - *span, - format!( - "associated type{} {} must be specified", - pluralize!(label.len()), - label.join(", "), - ), - ); - } + let mut names: FxIndexMap<_, usize> = FxIndexMap::default(); + for (item, _) in &missing_assoc_types { + types_count += 1; + *names.entry(item.name).or_insert(0) += 1; + } + let mut label = vec![]; + for (item, trait_ref) in &missing_assoc_types { + let postfix = if names[&item.name] > 1 { + format!(" (from trait `{}`)", trait_ref.print_trait_sugared()) + } else { + String::new() + }; + label.push(format!("`{}`{}", item.name, postfix)); + } + if !label.is_empty() { + err.span_label( + principal_span, + format!( + "associated type{} {} must be specified", + pluralize!(label.len()), + label.join(", "), + ), + ); } } suggestions.sort_by_key(|&(span, _)| span); @@ -1007,8 +996,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { )), .. }) = node - && let Some(ty_def_id) = qself_ty.ty_def_id() - && let [inherent_impl] = tcx.inherent_impls(ty_def_id) + && let Some(adt_def) = qself_ty.ty_adt_def() + && let [inherent_impl] = tcx.inherent_impls(adt_def.did()) && let name = format!("{ident2}_{ident3}") && let Some(ty::AssocItem { kind: ty::AssocKind::Fn, .. }) = tcx .associated_items(inherent_impl) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 7683c87168b..a357ade0294 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -123,6 +123,13 @@ pub trait HirTyLowerer<'tcx> { /// Returns the const to use when a const is omitted. fn ct_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx>; + fn register_trait_ascription_bounds( + &self, + bounds: Vec<(ty::Clause<'tcx>, Span)>, + hir_id: HirId, + span: Span, + ); + /// Probe bounds in scope where the bounded type coincides with the given type parameter. /// /// Rephrased, this returns bounds of the form `T: Trait`, where `T` is a type parameter @@ -2312,6 +2319,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.lower_fn_ty(hir_ty.hir_id, bf.safety, bf.abi, bf.decl, None, Some(hir_ty)), ) } + hir::TyKind::UnsafeBinder(_binder) => { + let guar = self + .dcx() + .struct_span_err(hir_ty.span, "unsafe binders are not yet implemented") + .emit(); + Ty::new_error(tcx, guar) + } hir::TyKind::TraitObject(bounds, lifetime, repr) => { if let Some(guar) = self.prohibit_or_lint_bare_trait_object_ty(hir_ty) { // Don't continue with type analysis if the `dyn` keyword is missing @@ -2368,6 +2382,25 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.lower_opaque_ty(opaque_ty.def_id, in_trait) } + hir::TyKind::TraitAscription(hir_bounds) => { + // Impl trait in bindings lower as an infer var with additional + // set of type bounds. + let self_ty = self.ty_infer(None, hir_ty.span); + let mut bounds = Bounds::default(); + self.lower_bounds( + self_ty, + hir_bounds.iter(), + &mut bounds, + ty::List::empty(), + PredicateFilter::All, + ); + self.register_trait_ascription_bounds( + bounds.clauses().collect(), + hir_ty.hir_id, + hir_ty.span, + ); + self_ty + } // If we encounter a type relative path with RTN generics, then it must have // *not* gone through `lower_ty_maybe_return_type_notation`, and therefore // it's certainly in an illegal position. diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 20ba9ae2632..8dd8a5c98ef 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -288,7 +288,13 @@ impl<'a> State<'a> { hir::TyKind::BareFn(f) => { self.print_ty_fn(f.abi, f.safety, f.decl, None, f.generic_params, f.param_names); } + hir::TyKind::UnsafeBinder(unsafe_binder) => { + self.print_unsafe_binder(unsafe_binder); + } hir::TyKind::OpaqueDef(..) => self.word("/*impl Trait*/"), + hir::TyKind::TraitAscription(bounds) => { + self.print_bounds("impl", bounds); + } hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false), hir::TyKind::TraitObject(bounds, lifetime, syntax) => { if syntax == ast::TraitObjectSyntax::Dyn { @@ -339,6 +345,15 @@ impl<'a> State<'a> { self.end() } + fn print_unsafe_binder(&mut self, unsafe_binder: &hir::UnsafeBinderTy<'_>) { + self.ibox(INDENT_UNIT); + self.word("unsafe"); + self.print_generic_params(unsafe_binder.generic_params); + self.nbsp(); + self.print_type(unsafe_binder.inner_ty); + self.end(); + } + fn print_foreign_item(&mut self, item: &hir::ForeignItem<'_>) { self.hardbreak_if_not_bol(); self.maybe_print_comment(item.span.lo()); @@ -1530,6 +1545,19 @@ impl<'a> State<'a> { self.word(")"); } + hir::ExprKind::UnsafeBinderCast(kind, expr, ty) => { + match kind { + hir::UnsafeBinderCastKind::Wrap => self.word("wrap_binder!("), + hir::UnsafeBinderCastKind::Unwrap => self.word("unwrap_binder!("), + } + self.print_expr(expr); + if let Some(ty) = ty { + self.word(","); + self.space(); + self.print_type(ty); + } + self.word(")"); + } hir::ExprKind::Yield(expr, _) => { self.word_space("yield"); self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 56903865277..66978399efb 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -72,12 +72,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.try_structurally_resolve_type(expr.span, ty).is_never() && self.expr_guaranteed_to_constitute_read_for_never(expr) { - if let Some(_) = self.typeck_results.borrow().adjustments().get(expr.hir_id) { + if let Some(adjustments) = self.typeck_results.borrow().adjustments().get(expr.hir_id) { let reported = self.dcx().span_delayed_bug( expr.span, "expression with never type wound up being adjusted", ); - return Ty::new_error(self.tcx(), reported); + + return if let [Adjustment { kind: Adjust::NeverToAny, target }] = &adjustments[..] { + target.to_owned() + } else { + Ty::new_error(self.tcx(), reported) + }; } let adj_ty = self.next_ty_var(expr.span); @@ -329,6 +334,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Assignment does call `drop_in_place`, though, but its safety // requirements are not the same. ExprKind::AddrOf(..) | hir::ExprKind::Field(..) => false, + + // Place-preserving expressions only constitute reads if their + // parent expression constitutes a read. + ExprKind::Type(..) | ExprKind::UnsafeBinderCast(..) => { + self.expr_guaranteed_to_constitute_read_for_never(expr) + } + ExprKind::Assign(lhs, _, _) => { // Only the LHS does not constitute a read expr.hir_id != lhs.hir_id @@ -353,7 +365,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | ExprKind::Binary(_, _, _) | ExprKind::Unary(_, _) | ExprKind::Cast(_, _) - | ExprKind::Type(_, _) | ExprKind::DropTemps(_) | ExprKind::If(_, _, _) | ExprKind::Closure(_) @@ -564,7 +575,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_expr_index(base, idx, expr, brackets_span) } ExprKind::Yield(value, _) => self.check_expr_yield(value, expr), - hir::ExprKind::Err(guar) => Ty::new_error(tcx, guar), + ExprKind::UnsafeBinderCast(kind, expr, ty) => { + self.check_expr_unsafe_binder_cast(kind, expr, ty, expected) + } + ExprKind::Err(guar) => Ty::new_error(tcx, guar), } } @@ -1634,6 +1648,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + fn check_expr_unsafe_binder_cast( + &self, + _kind: hir::UnsafeBinderCastKind, + expr: &'tcx hir::Expr<'tcx>, + _hir_ty: Option<&'tcx hir::Ty<'tcx>>, + _expected: Expectation<'tcx>, + ) -> Ty<'tcx> { + let guar = + self.dcx().struct_span_err(expr.span, "unsafe binders are not yet implemented").emit(); + Ty::new_error(self.tcx, guar) + } + fn check_expr_array( &self, args: &'tcx [hir::Expr<'tcx>], diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 27ec2e9e0d4..ecbae6ac72f 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -341,6 +341,10 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx self.walk_expr(subexpr)?; } + hir::ExprKind::UnsafeBinderCast(_, subexpr, _) => { + self.walk_expr(subexpr)?; + } + hir::ExprKind::Unary(hir::UnOp::Deref, base) => { // *base self.walk_expr(base)?; @@ -1360,7 +1364,10 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx self.cat_res(expr.hir_id, expr.span, expr_ty, res) } + // both type ascription and unsafe binder casts don't affect + // the place-ness of the subexpression. hir::ExprKind::Type(e, _) => self.cat_expr(e), + hir::ExprKind::UnsafeBinderCast(_, e, _) => self.cat_expr(e), hir::ExprKind::AddrOf(..) | hir::ExprKind::Call(..) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 863be3bdcb2..0dacfc9b7bf 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -4,11 +4,11 @@ use std::slice; use rustc_abi::FieldIdx; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey}; -use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; +use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; -use rustc_hir::{ExprKind, GenericArg, HirId, Node, QPath}; +use rustc_hir::{self as hir, ExprKind, GenericArg, HirId, Node, QPath, intravisit}; use rustc_hir_analysis::hir_ty_lowering::errors::GenericsArgsErrExtend; use rustc_hir_analysis::hir_ty_lowering::generics::{ check_generic_arg_count_for_call, lower_generic_args, @@ -25,7 +25,7 @@ use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; use rustc_middle::ty::{ self, AdtKind, CanonicalUserType, GenericArgKind, GenericArgsRef, GenericParamDefKind, - IsIdentity, Ty, TyCtxt, UserArgs, UserSelfTy, UserType, + IsIdentity, Ty, TyCtxt, UserArgs, UserSelfTy, }; use rustc_middle::{bug, span_bug}; use rustc_session::lint; @@ -216,11 +216,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("fcx {}", self.tag()); if Self::can_contain_user_lifetime_bounds((args, user_self_ty)) { - let canonicalized = - self.canonicalize_user_type_annotation(UserType::TypeOf(def_id, UserArgs { - args, - user_self_ty, - })); + let canonicalized = self.canonicalize_user_type_annotation(ty::UserType::new( + ty::UserTypeKind::TypeOf(def_id, UserArgs { args, user_self_ty }), + )); debug!(?canonicalized); self.write_user_type_annotation(hir_id, canonicalized); } @@ -462,13 +460,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { LoweredTy::from_raw(self, hir_ty.span, ty) } + /// Walk a `hir_ty` and collect any clauses that may have come from a type + /// within the `hir_ty`. These clauses will be canonicalized with a user type + /// annotation so that we can enforce these bounds in borrowck, too. + pub(crate) fn collect_impl_trait_clauses_from_hir_ty( + &self, + hir_ty: &'tcx hir::Ty<'tcx>, + ) -> ty::Clauses<'tcx> { + struct CollectClauses<'a, 'tcx> { + clauses: Vec<ty::Clause<'tcx>>, + fcx: &'a FnCtxt<'a, 'tcx>, + } + + impl<'tcx> intravisit::Visitor<'tcx> for CollectClauses<'_, 'tcx> { + fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { + if let Some(clauses) = self.fcx.trait_ascriptions.borrow().get(&ty.hir_id.local_id) + { + self.clauses.extend(clauses.iter().cloned()); + } + intravisit::walk_ty(self, ty) + } + } + + let mut clauses = CollectClauses { clauses: vec![], fcx: self }; + clauses.visit_ty(hir_ty); + self.tcx.mk_clauses(&clauses.clauses) + } + #[instrument(level = "debug", skip_all)] - pub(crate) fn lower_ty_saving_user_provided_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { + pub(crate) fn lower_ty_saving_user_provided_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> Ty<'tcx> { let ty = self.lower_ty(hir_ty); debug!(?ty); if Self::can_contain_user_lifetime_bounds(ty.raw) { - let c_ty = self.canonicalize_response(UserType::Ty(ty.raw)); + let c_ty = self.canonicalize_response(ty::UserType::new(ty::UserTypeKind::Ty(ty.raw))); debug!(?c_ty); self.typeck_results.borrow_mut().user_provided_types_mut().insert(hir_ty.hir_id, c_ty); } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index aacdcf027b6..b9011e89f04 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -10,10 +10,11 @@ use std::ops::Deref; use hir::def_id::CRATE_DEF_ID; use rustc_errors::DiagCtxtHandle; -use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::{self as hir, HirId, ItemLocalMap}; use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, RegionInferReason}; use rustc_infer::infer; +use rustc_infer::traits::Obligation; use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt}; use rustc_session::Session; use rustc_span::symbol::Ident; @@ -114,6 +115,12 @@ pub(crate) struct FnCtxt<'a, 'tcx> { pub(super) diverging_fallback_behavior: DivergingFallbackBehavior, pub(super) diverging_block_behavior: DivergingBlockBehavior, + + /// Clauses that we lowered as part of the `impl_trait_in_bindings` feature. + /// + /// These are stored here so we may collect them when canonicalizing user + /// type ascriptions later. + pub(super) trait_ascriptions: RefCell<ItemLocalMap<Vec<ty::Clause<'tcx>>>>, } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -141,6 +148,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fallback_has_occurred: Cell::new(false), diverging_fallback_behavior, diverging_block_behavior, + trait_ascriptions: Default::default(), } } @@ -252,6 +260,30 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { } } + fn register_trait_ascription_bounds( + &self, + bounds: Vec<(ty::Clause<'tcx>, Span)>, + hir_id: HirId, + _span: Span, + ) { + for (clause, span) in bounds { + if clause.has_escaping_bound_vars() { + self.dcx().span_delayed_bug(span, "clause should have no escaping bound vars"); + continue; + } + + self.trait_ascriptions.borrow_mut().entry(hir_id.local_id).or_default().push(clause); + + let clause = self.normalize(span, clause); + self.register_predicate(Obligation::new( + self.tcx, + self.misc(span), + self.param_env, + clause, + )); + } + } + fn probe_ty_param_bounds( &self, _: Span, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index ddcd90a2a9d..21b1768ae6f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -10,7 +10,7 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::lang_items::LangItem; use rustc_hir::{ Arm, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId, - Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicateKind, + Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicateKind, expr_needs_parens, }; use rustc_hir_analysis::collect::suggest_impl_trait; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; @@ -35,7 +35,6 @@ use tracing::{debug, instrument}; use super::FnCtxt; use crate::fn_ctxt::rustc_span::BytePos; -use crate::hir::is_range_literal; use crate::method::probe; use crate::method::probe::{IsSuggestion, Mode, ProbeScope}; use crate::{errors, fluent_generated as fluent}; @@ -2648,7 +2647,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let make_sugg = |expr: &Expr<'_>, span: Span, sugg: &str| { - if self.needs_parentheses(expr) { + if expr_needs_parens(expr) { ( vec![ (span.shrink_to_lo(), format!("{prefix}{sugg}(")), @@ -2861,7 +2860,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return None; } - if self.needs_parentheses(expr) { + if expr_needs_parens(expr) { return Some(( vec![ (span, format!("{suggestion}(")), @@ -2902,16 +2901,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } - fn needs_parentheses(&self, expr: &hir::Expr<'_>) -> bool { - match expr.kind { - // parenthesize if needed (Issue #46756) - hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true, - // parenthesize borrows of range literals (Issue #54505) - _ if is_range_literal(expr) => true, - _ => false, - } - } - pub(crate) fn suggest_cast( &self, err: &mut Diag<'_>, diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index f427b0b805e..48fd5f1f982 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -2,7 +2,7 @@ use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{HirId, PatKind}; use rustc_infer::traits::ObligationCauseCode; -use rustc_middle::ty::{Ty, UserType}; +use rustc_middle::ty::{self, Ty}; use rustc_span::Span; use rustc_span::def_id::LocalDefId; use tracing::debug; @@ -92,7 +92,12 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> { Some(ref ty) => { let o_ty = self.fcx.lower_ty(ty); - let c_ty = self.fcx.infcx.canonicalize_user_type_annotation(UserType::Ty(o_ty.raw)); + let c_ty = self.fcx.infcx.canonicalize_user_type_annotation( + ty::UserType::new_with_bounds( + ty::UserTypeKind::Ty(o_ty.raw), + self.fcx.collect_impl_trait_clauses_from_hir_ty(ty), + ), + ); debug!("visit_local: ty.hir_id={:?} o_ty={:?} c_ty={:?}", ty.hir_id, o_ty, c_ty); self.fcx .typeck_results diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index b31ee1a55d6..ef431c852e9 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -17,7 +17,6 @@ use rustc_middle::ty::adjustment::{ use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{ self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, UserArgs, - UserType, }; use rustc_middle::{bug, span_bug}; use rustc_span::{DUMMY_SP, Span}; @@ -491,9 +490,8 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { user_self_ty: None, // not relevant here }; - self.fcx.canonicalize_user_type_annotation(UserType::TypeOf( - pick.item.def_id, - user_args, + self.fcx.canonicalize_user_type_annotation(ty::UserType::new( + ty::UserTypeKind::TypeOf(pick.item.def_id, user_args), )) }); diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 2a8ed26aa2b..e7726845652 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -10,8 +10,12 @@ use rustc_errors::{ }; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::pat_util::EnumerateAndAdjustIterator; -use rustc_hir::{self as hir, BindingMode, ByRef, HirId, LangItem, Mutability, Pat, PatKind}; +use rustc_hir::{ + self as hir, BindingMode, ByRef, ExprKind, HirId, LangItem, Mutability, Pat, PatKind, + expr_needs_parens, +}; use rustc_infer::infer; +use rustc_middle::traits::PatternOriginExpr; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_middle::{bug, span_bug}; use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; @@ -94,10 +98,32 @@ struct PatInfo<'a, 'tcx> { impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn pattern_cause(&self, ti: &TopInfo<'tcx>, cause_span: Span) -> ObligationCause<'tcx> { + // If origin_expr exists, then expected represents the type of origin_expr. + // If span also exists, then span == origin_expr.span (although it doesn't need to exist). + // In that case, we can peel away references from both and treat them + // as the same. + let origin_expr_info = ti.origin_expr.map(|mut cur_expr| { + let mut count = 0; + + // cur_ty may have more layers of references than cur_expr. + // We can only make suggestions about cur_expr, however, so we'll + // use that as our condition for stopping. + while let ExprKind::AddrOf(.., inner) = &cur_expr.kind { + cur_expr = inner; + count += 1; + } + + PatternOriginExpr { + peeled_span: cur_expr.span, + peeled_count: count, + peeled_prefix_suggestion_parentheses: expr_needs_parens(cur_expr), + } + }); + let code = ObligationCauseCode::Pattern { span: ti.span, root_ty: ti.expected, - origin_expr: ti.origin_expr.is_some(), + origin_expr: origin_expr_info, }; self.cause(cause_span, code) } diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index e17a68c8692..6f1e3a0cf8c 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -476,7 +476,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { for (local_id, c_ty) in sorted_user_provided_types { let hir_id = HirId { owner: common_hir_owner, local_id }; - if let ty::UserType::TypeOf(_, user_args) = c_ty.value { + if let ty::UserTypeKind::TypeOf(_, user_args) = c_ty.value.kind { // This is a unit-testing mechanism. let span = self.tcx().hir().span(hir_id); // We need to buffer the errors in order to guarantee a consistent diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 07ae24ee6d3..91f190c6a28 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -371,7 +371,6 @@ pub(crate) fn initialize_checked_jobserver(early_dcx: &EarlyDiagCtxt) { // JUSTIFICATION: before session exists, only config #[allow(rustc::bad_opt_access)] -#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R { trace!("run_compiler"); @@ -425,7 +424,11 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se config.opts.unstable_opts.translate_directionality_markers, ) { Ok(bundle) => bundle, - Err(e) => early_dcx.early_fatal(format!("failed to load fluent bundle: {e}")), + Err(e) => { + // We can't translate anything if we failed to load translations + #[allow(rustc::untranslatable_diagnostic)] + early_dcx.early_fatal(format!("failed to load fluent bundle: {e}")) + } }; let mut locale_resources = config.locale_resources; @@ -479,7 +482,6 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints()); if let Some(register_lints) = config.register_lints.as_deref() { register_lints(&sess, &mut lint_store); - sess.registered_lints = true; } sess.lint_store = Some(Lrc::new(lint_store)); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 62f35333015..430bc7db077 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1125,6 +1125,18 @@ pub(crate) fn start_codegen<'tcx>( } } + // This must run after monomorphization so that all generic types + // have been instantiated. + if tcx.sess.opts.unstable_opts.print_type_sizes { + tcx.sess.code_stats.print_type_sizes(); + } + + if tcx.sess.opts.unstable_opts.print_vtable_sizes { + let crate_name = tcx.crate_name(LOCAL_CRATE); + + tcx.sess.code_stats.print_vtable_sizes(crate_name); + } + codegen } diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 7e3a1332630..bb2ad3b3dd0 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -127,18 +127,6 @@ impl Linker { ) -> Linker { let ongoing_codegen = passes::start_codegen(codegen_backend, tcx); - // This must run after monomorphization so that all generic types - // have been instantiated. - if tcx.sess.opts.unstable_opts.print_type_sizes { - tcx.sess.code_stats.print_type_sizes(); - } - - if tcx.sess.opts.unstable_opts.print_vtable_sizes { - let crate_name = tcx.crate_name(LOCAL_CRATE); - - tcx.sess.code_stats.print_vtable_sizes(crate_name); - } - Linker { dep_graph: tcx.dep_graph.clone(), output_filenames: Arc::clone(tcx.output_filenames(())), diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index d3213b1263c..2af25bfd3aa 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -35,10 +35,10 @@ pub type MakeBackendFn = fn() -> Box<dyn CodegenBackend>; pub fn add_configuration(cfg: &mut Cfg, sess: &mut Session, codegen_backend: &dyn CodegenBackend) { let tf = sym::target_feature; - let unstable_target_features = codegen_backend.target_features(sess, true); + let unstable_target_features = codegen_backend.target_features_cfg(sess, true); sess.unstable_target_features.extend(unstable_target_features.iter().cloned()); - let target_features = codegen_backend.target_features(sess, false); + let target_features = codegen_backend.target_features_cfg(sess, false); sess.target_features.extend(target_features.iter().cloned()); cfg.extend(target_features.into_iter().map(|feat| (tf, Some(feat)))); diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 49e6b763590..01d9ac20fae 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -806,10 +806,14 @@ lint_unexpected_cfg_add_build_rs_println = or consider adding `{$build_rs_printl lint_unexpected_cfg_add_cargo_feature = consider using a Cargo feature instead lint_unexpected_cfg_add_cargo_toml_lint_cfg = or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:{$cargo_toml_lint_cfg} lint_unexpected_cfg_add_cmdline_arg = to expect this configuration use `{$cmdline_arg}` +lint_unexpected_cfg_cargo_update = the {$macro_kind} `{$macro_name}` may come from an old version of it's defining crate, try updating your dependencies with `cargo update` + lint_unexpected_cfg_define_features = consider defining some features in `Cargo.toml` lint_unexpected_cfg_doc_cargo = see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration lint_unexpected_cfg_doc_rustc = see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration +lint_unexpected_cfg_from_external_macro_origin = using a cfg inside a {$macro_kind} will use the cfgs from the destination crate and not the ones from the defining crate +lint_unexpected_cfg_from_external_macro_refer = try refering to `{$macro_name}` crate for guidance on how handle this unexpected cfg lint_unexpected_cfg_name = unexpected `cfg` condition name: `{$name}` lint_unexpected_cfg_name_expected_names = expected names are: {$possibilities}{$and_more -> [0] {""} diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 093cc16fb4c..3543784bc72 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -3038,7 +3038,7 @@ impl EarlyLintPass for SpecialModuleName { for item in &krate.items { if let ast::ItemKind::Mod( _, - ast::ModKind::Unloaded | ast::ModKind::Loaded(_, ast::Inline::No, _), + ast::ModKind::Unloaded | ast::ModKind::Loaded(_, ast::Inline::No, _, _), ) = item.kind { if item.attrs.iter().any(|a| a.has_name(sym::path)) { diff --git a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs index 16994846545..63a722f6067 100644 --- a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs +++ b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs @@ -1,9 +1,10 @@ +use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::bug; use rustc_session::Session; use rustc_session::config::ExpectedValues; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::symbol::Ident; -use rustc_span::{Span, Symbol, sym}; +use rustc_span::{ExpnKind, Span, Symbol, sym}; use crate::lints; @@ -60,6 +61,35 @@ fn cargo_help_sub( } } +fn rustc_macro_help(span: Span) -> Option<lints::UnexpectedCfgRustcMacroHelp> { + let oexpn = span.ctxt().outer_expn_data(); + if let Some(def_id) = oexpn.macro_def_id + && let ExpnKind::Macro(macro_kind, macro_name) = oexpn.kind + && def_id.krate != LOCAL_CRATE + { + Some(lints::UnexpectedCfgRustcMacroHelp { macro_kind: macro_kind.descr(), macro_name }) + } else { + None + } +} + +fn cargo_macro_help(span: Span) -> Option<lints::UnexpectedCfgCargoMacroHelp> { + let oexpn = span.ctxt().outer_expn_data(); + if let Some(def_id) = oexpn.macro_def_id + && let ExpnKind::Macro(macro_kind, macro_name) = oexpn.kind + && def_id.krate != LOCAL_CRATE + { + Some(lints::UnexpectedCfgCargoMacroHelp { + macro_kind: macro_kind.descr(), + macro_name, + // FIXME: Get access to a `TyCtxt` from an `EarlyContext` + // crate_name: cx.tcx.crate_name(def_id.krate), + }) + } else { + None + } +} + pub(super) fn unexpected_cfg_name( sess: &Session, (name, name_span): (Symbol, Span), @@ -85,6 +115,7 @@ pub(super) fn unexpected_cfg_name( }; let is_from_cargo = rustc_session::utils::was_invoked_from_cargo(); + let is_from_external_macro = rustc_middle::lint::in_external_macro(sess, name_span); let mut is_feature_cfg = name == sym::feature; let code_sugg = if is_feature_cfg && is_from_cargo { @@ -185,12 +216,21 @@ pub(super) fn unexpected_cfg_name( }; let invocation_help = if is_from_cargo { - let sub = if !is_feature_cfg { Some(cargo_help_sub(sess, &inst)) } else { None }; - lints::unexpected_cfg_name::InvocationHelp::Cargo { sub } + let help = if !is_feature_cfg && !is_from_external_macro { + Some(cargo_help_sub(sess, &inst)) + } else { + None + }; + lints::unexpected_cfg_name::InvocationHelp::Cargo { + help, + macro_help: cargo_macro_help(name_span), + } } else { - lints::unexpected_cfg_name::InvocationHelp::Rustc(lints::UnexpectedCfgRustcHelp::new( - &inst(EscapeQuotes::No), - )) + let help = lints::UnexpectedCfgRustcHelp::new(&inst(EscapeQuotes::No)); + lints::unexpected_cfg_name::InvocationHelp::Rustc { + help, + macro_help: rustc_macro_help(name_span), + } }; lints::UnexpectedCfgName { code_sugg, invocation_help, name } @@ -216,7 +256,9 @@ pub(super) fn unexpected_cfg_value( .copied() .flatten() .collect(); + let is_from_cargo = rustc_session::utils::was_invoked_from_cargo(); + let is_from_external_macro = rustc_middle::lint::in_external_macro(sess, name_span); // Show the full list if all possible values for a given name, but don't do it // for names as the possibilities could be very long @@ -284,25 +326,31 @@ pub(super) fn unexpected_cfg_value( }; let invocation_help = if is_from_cargo { - let help = if name == sym::feature { + let help = if name == sym::feature && !is_from_external_macro { if let Some((value, _value_span)) = value { Some(lints::unexpected_cfg_value::CargoHelp::AddFeature { value }) } else { Some(lints::unexpected_cfg_value::CargoHelp::DefineFeatures) } - } else if can_suggest_adding_value { + } else if can_suggest_adding_value && !is_from_external_macro { Some(lints::unexpected_cfg_value::CargoHelp::Other(cargo_help_sub(sess, &inst))) } else { None }; - lints::unexpected_cfg_value::InvocationHelp::Cargo(help) + lints::unexpected_cfg_value::InvocationHelp::Cargo { + help, + macro_help: cargo_macro_help(name_span), + } } else { let help = if can_suggest_adding_value { Some(lints::UnexpectedCfgRustcHelp::new(&inst(EscapeQuotes::No))) } else { None }; - lints::unexpected_cfg_value::InvocationHelp::Rustc(help) + lints::unexpected_cfg_value::InvocationHelp::Rustc { + help, + macro_help: rustc_macro_help(name_span), + } }; lints::UnexpectedCfgValue { diff --git a/compiler/rustc_lint/src/dangling.rs b/compiler/rustc_lint/src/dangling.rs index 7e298a9a63c..10769b57a76 100644 --- a/compiler/rustc_lint/src/dangling.rs +++ b/compiler/rustc_lint/src/dangling.rs @@ -192,6 +192,8 @@ fn is_temporary_rvalue(expr: &Expr<'_>) -> bool { | ExprKind::DropTemps(..) | ExprKind::Let(..) => false, + ExprKind::UnsafeBinderCast(..) => false, + // Not applicable ExprKind::Type(..) | ExprKind::Err(..) => false, } diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index 2db229ed133..1402129195f 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -422,6 +422,7 @@ impl<'tcx, 'a> Visitor<'tcx> for FindSignificantDropper<'tcx, 'a> { hir::ExprKind::Unary(_, expr) | hir::ExprKind::Cast(expr, _) | hir::ExprKind::Type(expr, _) + | hir::ExprKind::UnsafeBinderCast(_, expr, _) | hir::ExprKind::Yield(expr, _) | hir::ExprKind::AddrOf(_, _, expr) | hir::ExprKind::Match(expr, _, _) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 20822f23bf1..5da9f6d2053 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2172,6 +2172,25 @@ impl UnexpectedCfgRustcHelp { } } +#[derive(Subdiagnostic)] +#[note(lint_unexpected_cfg_from_external_macro_origin)] +#[help(lint_unexpected_cfg_from_external_macro_refer)] +pub(crate) struct UnexpectedCfgRustcMacroHelp { + pub macro_kind: &'static str, + pub macro_name: Symbol, +} + +#[derive(Subdiagnostic)] +#[note(lint_unexpected_cfg_from_external_macro_origin)] +#[help(lint_unexpected_cfg_from_external_macro_refer)] +#[help(lint_unexpected_cfg_cargo_update)] +pub(crate) struct UnexpectedCfgCargoMacroHelp { + pub macro_kind: &'static str, + pub macro_name: Symbol, + // FIXME: Figure out a way to get the crate name + // crate_name: String, +} + #[derive(LintDiagnostic)] #[diag(lint_unexpected_cfg_name)] pub(crate) struct UnexpectedCfgName { @@ -2276,10 +2295,17 @@ pub(crate) mod unexpected_cfg_name { #[note(lint_unexpected_cfg_doc_cargo)] Cargo { #[subdiagnostic] - sub: Option<super::UnexpectedCfgCargoHelp>, + macro_help: Option<super::UnexpectedCfgCargoMacroHelp>, + #[subdiagnostic] + help: Option<super::UnexpectedCfgCargoHelp>, }, #[note(lint_unexpected_cfg_doc_rustc)] - Rustc(#[subdiagnostic] super::UnexpectedCfgRustcHelp), + Rustc { + #[subdiagnostic] + macro_help: Option<super::UnexpectedCfgRustcMacroHelp>, + #[subdiagnostic] + help: super::UnexpectedCfgRustcHelp, + }, } } @@ -2382,9 +2408,19 @@ pub(crate) mod unexpected_cfg_value { #[derive(Subdiagnostic)] pub(crate) enum InvocationHelp { #[note(lint_unexpected_cfg_doc_cargo)] - Cargo(#[subdiagnostic] Option<CargoHelp>), + Cargo { + #[subdiagnostic] + help: Option<CargoHelp>, + #[subdiagnostic] + macro_help: Option<super::UnexpectedCfgCargoMacroHelp>, + }, #[note(lint_unexpected_cfg_doc_rustc)] - Rustc(#[subdiagnostic] Option<super::UnexpectedCfgRustcHelp>), + Rustc { + #[subdiagnostic] + help: Option<super::UnexpectedCfgRustcHelp>, + #[subdiagnostic] + macro_help: Option<super::UnexpectedCfgRustcMacroHelp>, + }, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index 641d1d8e798..e8de0acb7c9 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -77,7 +77,7 @@ pub(crate) fn calculate(tcx: TyCtxt<'_>) -> Dependencies { verify_ok(tcx, &linkage); (ty, linkage) }) - .collect::<Vec<_>>() + .collect() } fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 5c80d24f502..df5b06c6d16 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1264,12 +1264,7 @@ fn should_encode_fn_sig(def_kind: DefKind) -> bool { fn should_encode_constness(def_kind: DefKind) -> bool { match def_kind { - DefKind::Fn - | DefKind::AssocFn - | DefKind::Closure - | DefKind::Impl { of_trait: true } - | DefKind::Variant - | DefKind::Ctor(..) => true, + DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Ctor(_, CtorKind::Fn) => true, DefKind::Struct | DefKind::Union @@ -1281,7 +1276,7 @@ fn should_encode_constness(def_kind: DefKind) -> bool { | DefKind::Static { .. } | DefKind::TyAlias | DefKind::OpaqueTy - | DefKind::Impl { of_trait: false } + | DefKind::Impl { .. } | DefKind::ForeignTy | DefKind::ConstParam | DefKind::InlineConst @@ -1296,6 +1291,8 @@ fn should_encode_constness(def_kind: DefKind) -> bool { | DefKind::LifetimeParam | DefKind::GlobalAsm | DefKind::ExternCrate + | DefKind::Ctor(_, CtorKind::Const) + | DefKind::Variant | DefKind::SyntheticCoroutineBody => false, } } @@ -2164,10 +2161,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_dylib_dependency_formats(&mut self) -> LazyArray<Option<LinkagePreference>> { empty_proc_macro!(self); let formats = self.tcx.dependency_formats(()); - for (ty, arr) in formats.iter() { - if *ty != CrateType::Dylib { - continue; - } + if let Some(arr) = formats.get(&CrateType::Dylib) { return self.lazy_array(arr.iter().map(|slot| match *slot { Linkage::NotLinked | Linkage::IncludedFromDylib => None, diff --git a/compiler/rustc_middle/src/middle/dependency_format.rs b/compiler/rustc_middle/src/middle/dependency_format.rs index a3aff9a1101..e3b40b64157 100644 --- a/compiler/rustc_middle/src/middle/dependency_format.rs +++ b/compiler/rustc_middle/src/middle/dependency_format.rs @@ -7,6 +7,7 @@ // FIXME: move this file to rustc_metadata::dependency_format, but // this will introduce circular dependency between rustc_metadata and rustc_middle +use rustc_data_structures::fx::FxIndexMap; use rustc_macros::{Decodable, Encodable, HashStable}; use rustc_session::config::CrateType; @@ -18,7 +19,7 @@ pub type DependencyList = Vec<Linkage>; /// A mapping of all required dependencies for a particular flavor of output. /// /// This is local to the tcx, and is generally relevant to one session. -pub type Dependencies = Vec<(CrateType, DependencyList)>; +pub type Dependencies = FxIndexMap<CrateType, DependencyList>; #[derive(Copy, Clone, PartialEq, Debug, HashStable, Encodable, Decodable)] pub enum Linkage { diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index 52009422d98..d8a39191920 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -467,6 +467,9 @@ impl<'tcx> Const<'tcx> { let const_val = tcx.valtree_to_const_val((ty, valtree)); Self::Val(const_val, ty) } + ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) => { + Self::Unevaluated(UnevaluatedConst { def, args, promoted: None }, ty) + } _ => Self::Ty(ty, c), } } diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 1f50b67cb50..266dc7ad2b3 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -294,10 +294,22 @@ pub enum Linkage { Common, } +/// Specifies the symbol visibility with regards to dynamic linking. +/// +/// Visibility doesn't have any effect when linkage is internal. +/// +/// DSO means dynamic shared object, that is a dynamically linked executable or dylib. #[derive(Copy, Clone, PartialEq, Debug, HashStable)] pub enum Visibility { + /// Export the symbol from the DSO and apply overrides of the symbol by outside DSOs to within + /// the DSO if the object file format supports this. Default, + /// Hide the symbol outside of the defining DSO even when external linkage is used to export it + /// from the object file. Hidden, + /// Export the symbol from the DSO, but don't apply overrides of the symbol by outside DSOs to + /// within the DSO. Equivalent to default visibility with object file formats that don't support + /// overriding exported symbols by another DSO. Protected, } diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index 970dc72e1ff..66fec2dd0f7 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -41,7 +41,8 @@ pub trait Key: Sized { None } - fn ty_def_id(&self) -> Option<DefId> { + /// Used to detect when ADT def ids are used as keys in a cycle for better error reporting. + fn def_id_for_ty_in_cycle(&self) -> Option<DefId> { None } } @@ -423,7 +424,7 @@ impl<'tcx> Key for Ty<'tcx> { DUMMY_SP } - fn ty_def_id(&self) -> Option<DefId> { + fn def_id_for_ty_in_cycle(&self) -> Option<DefId> { match *self.kind() { ty::Adt(adt, _) => Some(adt.did()), ty::Coroutine(def_id, ..) => Some(def_id), @@ -471,8 +472,8 @@ impl<'tcx, T: Key> Key for ty::PseudoCanonicalInput<'tcx, T> { self.value.default_span(tcx) } - fn ty_def_id(&self) -> Option<DefId> { - self.value.ty_def_id() + fn def_id_for_ty_in_cycle(&self) -> Option<DefId> { + self.value.def_id_for_ty_in_cycle() } } @@ -593,7 +594,7 @@ impl<'tcx> Key for (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx> DUMMY_SP } - fn ty_def_id(&self) -> Option<DefId> { + fn def_id_for_ty_in_cycle(&self) -> Option<DefId> { match self.1.value.kind() { ty::Adt(adt, _) => Some(adt.did()), _ => None, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index fc3d690a8a9..cc4e31294bd 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -746,7 +746,10 @@ rustc_queries! { desc { |tcx| "computing drop-check constraints for `{}`", tcx.def_path_str(key) } } - /// Returns `true` if this is a const fn / const impl. + /// Returns the constness of function-like things (tuple struct/variant constructors, functions, + /// methods) + /// + /// Will ICE if used on things that are always const or never const. /// /// **Do not call this function manually.** It is only meant to cache the base data for the /// higher-level functions. Consider using `is_const_fn` or `is_const_trait_impl` instead. @@ -2230,7 +2233,7 @@ rustc_queries! { } /// Returns the Rust target features for the current target. These are not always the same as LLVM target features! - query rust_target_features(_: CrateNum) -> &'tcx UnordMap<String, rustc_target::target_features::Stability> { + query rust_target_features(_: CrateNum) -> &'tcx UnordMap<String, rustc_target::target_features::StabilityComputed> { arena_cache eval_always desc { "looking up Rust target features" } diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index c8675660e0f..3337f7ceee7 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -44,16 +44,16 @@ pub struct DynamicQuery<'tcx, C: QueryCache> { pub format_value: fn(&C::Value) -> String, } -pub struct QuerySystemFns<'tcx> { +pub struct QuerySystemFns { pub engine: QueryEngine, pub local_providers: Providers, pub extern_providers: ExternProviders, - pub encode_query_results: fn( + pub encode_query_results: for<'tcx> fn( tcx: TyCtxt<'tcx>, encoder: &mut CacheEncoder<'_, 'tcx>, query_result_index: &mut EncodedDepNodeIndex, ), - pub try_mark_green: fn(tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool, + pub try_mark_green: for<'tcx> fn(tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool, } pub struct QuerySystem<'tcx> { @@ -68,7 +68,7 @@ pub struct QuerySystem<'tcx> { /// This is `None` if we are not incremental compilation mode pub on_disk_cache: Option<OnDiskCache>, - pub fns: QuerySystemFns<'tcx>, + pub fns: QuerySystemFns, pub jobs: AtomicU64, } @@ -323,7 +323,7 @@ macro_rules! define_callbacks { // Increase this limit if necessary, but do try to keep the size low if possible #[cfg(target_pointer_width = "64")] const _: () = { - if mem::size_of::<Key<'static>>() > 80 { + if mem::size_of::<Key<'static>>() > 88 { panic!("{}", concat!( "the query `", stringify!($name), diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 0a77c3bc42f..8c434265d27 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -316,8 +316,8 @@ pub enum ObligationCauseCode<'tcx> { span: Option<Span>, /// The root expected type induced by a scrutinee or type expression. root_ty: Ty<'tcx>, - /// Whether the `Span` came from an expression or a type expression. - origin_expr: bool, + /// Information about the `Span`, if it came from an expression, otherwise `None`. + origin_expr: Option<PatternOriginExpr>, }, /// Computing common supertype in an if expression @@ -530,6 +530,25 @@ pub struct MatchExpressionArmCause<'tcx> { pub tail_defines_return_position_impl_trait: Option<LocalDefId>, } +/// Information about the origin expression of a pattern, relevant to diagnostics. +/// Fields here refer to the scrutinee of a pattern. +/// If the scrutinee isn't given in the diagnostic, then this won't exist. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)] +pub struct PatternOriginExpr { + /// A span representing the scrutinee expression, with all leading references + /// peeled from the expression. + /// Only references in the expression are peeled - if the expression refers to a variable + /// whose type is a reference, then that reference is kept because it wasn't created + /// in the expression. + pub peeled_span: Span, + /// The number of references that were peeled to produce `peeled_span`. + pub peeled_count: usize, + /// Does the peeled expression need to be wrapped in parentheses for + /// a prefix suggestion (i.e., dereference) to be valid. + pub peeled_prefix_suggestion_parentheses: bool, +} + #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)] pub struct IfExpressionCause<'tcx> { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 2841470d248..db1a479f580 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -3141,7 +3141,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Whether the trait impl is marked const. This does not consider stability or feature gates. pub fn is_const_trait_impl(self, def_id: DefId) -> bool { self.def_kind(def_id) == DefKind::Impl { of_trait: true } - && self.constness(def_id) == hir::Constness::Const + && self.impl_trait_header(def_id).unwrap().constness == hir::Constness::Const } pub fn intrinsic(self, def_id: impl IntoQueryParam<DefId> + Copy) -> Option<ty::IntrinsicDef> { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 80b11892a42..e47b0cf0b3b 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -95,7 +95,7 @@ pub use self::sty::{ pub use self::trait_def::TraitDef; pub use self::typeck_results::{ CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, IsIdentity, - TypeckResults, UserType, UserTypeAnnotationIndex, + TypeckResults, UserType, UserTypeAnnotationIndex, UserTypeKind, }; pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason}; @@ -254,6 +254,7 @@ pub struct ImplTraitHeader<'tcx> { pub trait_ref: ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>, pub polarity: ImplPolarity, pub safety: hir::Safety, + pub constness: hir::Constness, } #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)] @@ -2005,17 +2006,25 @@ impl<'tcx> TyCtxt<'tcx> { let def_id: DefId = def_id.into(); match self.def_kind(def_id) { DefKind::Impl { of_trait: true } => { - self.constness(def_id) == hir::Constness::Const - && self.is_const_trait( - self.trait_id_of_impl(def_id) - .expect("expected trait for trait implementation"), - ) + let header = self.impl_trait_header(def_id).unwrap(); + header.constness == hir::Constness::Const + && self.is_const_trait(header.trait_ref.skip_binder().def_id) } DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) => { self.constness(def_id) == hir::Constness::Const } DefKind::Trait => self.is_const_trait(def_id), - DefKind::AssocTy | DefKind::AssocFn => { + DefKind::AssocTy => { + let parent_def_id = self.parent(def_id); + match self.def_kind(parent_def_id) { + DefKind::Impl { of_trait: false } => false, + DefKind::Impl { of_trait: true } | DefKind::Trait => { + self.is_conditionally_const(parent_def_id) + } + _ => bug!("unexpected parent item of associated type: {parent_def_id:?}"), + } + } + DefKind::AssocFn => { let parent_def_id = self.parent(def_id); match self.def_kind(parent_def_id) { DefKind::Impl { of_trait: false } => { @@ -2024,7 +2033,7 @@ impl<'tcx> TyCtxt<'tcx> { DefKind::Impl { of_trait: true } | DefKind::Trait => { self.is_conditionally_const(parent_def_id) } - _ => bug!("unexpected parent item of associated item: {parent_def_id:?}"), + _ => bug!("unexpected parent item of associated fn: {parent_def_id:?}"), } } DefKind::OpaqueTy => match self.opaque_ty_origin(def_id) { diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 8cba5f33278..551c113aa59 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -700,12 +700,31 @@ pub struct CanonicalUserTypeAnnotation<'tcx> { /// Canonical user type annotation. pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>; +#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)] +#[derive(Eq, Hash, HashStable, TypeFoldable, TypeVisitable)] +pub struct UserType<'tcx> { + pub kind: UserTypeKind<'tcx>, + pub bounds: ty::Clauses<'tcx>, +} + +impl<'tcx> UserType<'tcx> { + pub fn new(kind: UserTypeKind<'tcx>) -> UserType<'tcx> { + UserType { kind, bounds: ty::ListWithCachedTypeInfo::empty() } + } + + /// A user type annotation with additional bounds that need to be enforced. + /// These bounds are lowered from `impl Trait` in bindings. + pub fn new_with_bounds(kind: UserTypeKind<'tcx>, bounds: ty::Clauses<'tcx>) -> UserType<'tcx> { + UserType { kind, bounds } + } +} + /// A user-given type annotation attached to a constant. These arise /// from constants that are named via paths, like `Foo::<A>::new` and /// so forth. #[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)] #[derive(Eq, Hash, HashStable, TypeFoldable, TypeVisitable)] -pub enum UserType<'tcx> { +pub enum UserTypeKind<'tcx> { Ty(Ty<'tcx>), /// The canonical type is the result of `type_of(def_id)` with the @@ -721,9 +740,13 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> { /// Returns `true` if this represents the generic parameters of the form `[?0, ?1, ?2]`, /// i.e., each thing is mapped to a canonical variable with the same index. fn is_identity(&self) -> bool { - match self.value { - UserType::Ty(_) => false, - UserType::TypeOf(_, user_args) => { + if !self.value.bounds.is_empty() { + return false; + } + + match self.value.kind { + UserTypeKind::Ty(_) => false, + UserTypeKind::TypeOf(_, user_args) => { if user_args.user_self_ty.is_some() { return false; } @@ -765,6 +788,18 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> { impl<'tcx> std::fmt::Display for UserType<'tcx> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if self.bounds.is_empty() { + self.kind.fmt(f) + } else { + self.kind.fmt(f)?; + write!(f, " + ")?; + std::fmt::Debug::fmt(&self.bounds, f) + } + } +} + +impl<'tcx> std::fmt::Display for UserTypeKind<'tcx> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Ty(arg0) => { ty::print::with_no_trimmed_paths!(write!(f, "Ty({})", arg0)) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index b9a45ea3c2c..fda9898ed56 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -389,7 +389,7 @@ impl<'tcx> TyCtxt<'tcx> { .delay_as_bug(); } - dtor_candidate = Some((*item_id, self.constness(impl_did))); + dtor_candidate = Some((*item_id, self.impl_trait_header(impl_did).unwrap().constness)); }); let (did, constness) = dtor_candidate?; diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index 48d744a9ef6..390909bb0ab 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -100,7 +100,7 @@ impl<'tcx> Value<TyCtxt<'tcx>> for Representability { } for info in &cycle_error.cycle { if info.query.dep_kind == dep_kinds::representability_adt_ty - && let Some(def_id) = info.query.ty_def_id + && let Some(def_id) = info.query.def_id_for_ty_in_cycle && let Some(def_id) = def_id.as_local() && !item_and_field_ids.iter().any(|&(id, _)| id == def_id) { @@ -182,7 +182,7 @@ impl<'tcx, T> Value<TyCtxt<'tcx>> for Result<T, &'_ ty::layout::LayoutError<'_>> &cycle_error.cycle, |cycle| { if cycle[0].query.dep_kind == dep_kinds::layout_of - && let Some(def_id) = cycle[0].query.ty_def_id + && let Some(def_id) = cycle[0].query.def_id_for_ty_in_cycle && let Some(def_id) = def_id.as_local() && let def_kind = tcx.def_kind(def_id) && matches!(def_kind, DefKind::Closure) @@ -209,7 +209,7 @@ impl<'tcx, T> Value<TyCtxt<'tcx>> for Result<T, &'_ ty::layout::LayoutError<'_>> if frame.query.dep_kind != dep_kinds::layout_of { continue; } - let Some(frame_def_id) = frame.query.ty_def_id else { + let Some(frame_def_id) = frame.query.def_id_for_ty_in_cycle else { continue; }; let Some(frame_coroutine_kind) = tcx.coroutine_kind(frame_def_id) else { diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index 6ce88cdc39d..70a74910a68 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -11,7 +11,7 @@ use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty::{self, AdtDef, CanonicalUserTypeAnnotation, Ty, Variance}; use rustc_middle::{bug, span_bug}; -use rustc_span::Span; +use rustc_span::{DesugaringKind, Span}; use tracing::{debug, instrument, trace}; use crate::build::ForGuard::{OutsideGuard, RefWithinGuard}; @@ -630,6 +630,80 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block.and(base_place.index(idx)) } + /// Given a place that's either an array or a slice, returns an operand + /// with the length of the array/slice. + /// + /// For arrays it'll be `Operand::Constant` with the actual length; + /// For slices it'll be `Operand::Move` of a local using `PtrMetadata`. + fn len_of_slice_or_array( + &mut self, + block: BasicBlock, + place: Place<'tcx>, + span: Span, + source_info: SourceInfo, + ) -> Operand<'tcx> { + let place_ty = place.ty(&self.local_decls, self.tcx).ty; + let usize_ty = self.tcx.types.usize; + + match place_ty.kind() { + ty::Array(_elem_ty, len_const) => { + // We know how long an array is, so just use that as a constant + // directly -- no locals needed. We do need one statement so + // that borrow- and initialization-checking consider it used, + // though. FIXME: Do we really *need* to count this as a use? + // Could partial array tracking work off something else instead? + self.cfg.push_fake_read(block, source_info, FakeReadCause::ForIndex, place); + let const_ = Const::from_ty_const(*len_const, usize_ty, self.tcx); + Operand::Constant(Box::new(ConstOperand { span, user_ty: None, const_ })) + } + ty::Slice(_elem_ty) => { + let ptr_or_ref = if let [PlaceElem::Deref] = place.projection[..] + && let local_ty = self.local_decls[place.local].ty + && local_ty.is_trivially_pure_clone_copy() + { + // It's extremely common that we have something that can be + // directly passed to `PtrMetadata`, so avoid an unnecessary + // temporary and statement in those cases. Note that we can + // only do that for `Copy` types -- not `&mut [_]` -- because + // the MIR we're building here needs to pass NLL later. + Operand::Copy(Place::from(place.local)) + } else { + let len_span = self.tcx.with_stable_hashing_context(|hcx| { + let span = source_info.span; + span.mark_with_reason( + None, + DesugaringKind::IndexBoundsCheckReborrow, + span.edition(), + hcx, + ) + }); + let ptr_ty = Ty::new_imm_ptr(self.tcx, place_ty); + let slice_ptr = self.temp(ptr_ty, span); + self.cfg.push_assign( + block, + SourceInfo { span: len_span, ..source_info }, + slice_ptr, + Rvalue::RawPtr(Mutability::Not, place), + ); + Operand::Move(slice_ptr) + }; + + let len = self.temp(usize_ty, span); + self.cfg.push_assign( + block, + source_info, + len, + Rvalue::UnaryOp(UnOp::PtrMetadata, ptr_or_ref), + ); + + Operand::Move(len) + } + _ => { + span_bug!(span, "len called on place of type {place_ty:?}") + } + } + } + fn bounds_check( &mut self, block: BasicBlock, @@ -638,25 +712,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr_span: Span, source_info: SourceInfo, ) -> BasicBlock { - let usize_ty = self.tcx.types.usize; - let bool_ty = self.tcx.types.bool; - // bounds check: - let len = self.temp(usize_ty, expr_span); - let lt = self.temp(bool_ty, expr_span); + let slice = slice.to_place(self); // len = len(slice) - self.cfg.push_assign(block, source_info, len, Rvalue::Len(slice.to_place(self))); + let len = self.len_of_slice_or_array(block, slice, expr_span, source_info); + // lt = idx < len + let bool_ty = self.tcx.types.bool; + let lt = self.temp(bool_ty, expr_span); self.cfg.push_assign( block, source_info, lt, Rvalue::BinaryOp( BinOp::Lt, - Box::new((Operand::Copy(Place::from(index)), Operand::Copy(len))), + Box::new((Operand::Copy(Place::from(index)), len.to_copy())), ), ); - let msg = BoundsCheck { len: Operand::Move(len), index: Operand::Copy(Place::from(index)) }; + let msg = BoundsCheck { len, index: Operand::Copy(Place::from(index)) }; + // assert!(lt, "...") self.assert(block, Operand::Move(lt), true, msg, expr_span) } diff --git a/compiler/rustc_mir_build/src/build/matches/match_pair.rs b/compiler/rustc_mir_build/src/build/matches/match_pair.rs index 2815b390375..33fbd7b1a3f 100644 --- a/compiler/rustc_mir_build/src/build/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/build/matches/match_pair.rs @@ -176,9 +176,8 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> { ty: cx.infcx.next_ty_var(span), }) .args; - let user_ty = cx.infcx.canonicalize_user_type_annotation(ty::UserType::TypeOf( - def_id, - ty::UserArgs { args, user_self_ty: None }, + let user_ty = cx.infcx.canonicalize_user_type_annotation(ty::UserType::new( + ty::UserTypeKind::TypeOf(def_id, ty::UserArgs { args, user_self_ty: None }), )); let annotation = ty::CanonicalUserTypeAnnotation { inferred_ty: pattern.ty, diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index d75f01dfba0..6770e562d50 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -15,7 +15,6 @@ use rustc_middle::ty::adjustment::{ }; use rustc_middle::ty::{ self, AdtKind, GenericArgs, InlineConstArgs, InlineConstArgsParts, ScalarInt, Ty, UpvarArgs, - UserType, }; use rustc_middle::{bug, span_bug}; use rustc_span::{Span, sym}; @@ -443,7 +442,9 @@ impl<'tcx> Cx<'tcx> { let user_provided_types = self.typeck_results().user_provided_types(); let user_ty = user_provided_types.get(fun.hir_id).copied().map(|mut u_ty| { - if let UserType::TypeOf(ref mut did, _) = &mut u_ty.value { + if let ty::UserTypeKind::TypeOf(ref mut did, _) = + &mut u_ty.value.kind + { *did = adt_def.did(); } Box::new(u_ty) @@ -915,6 +916,11 @@ impl<'tcx> Cx<'tcx> { } } } + + hir::ExprKind::UnsafeBinderCast(_kind, _source, _ty) => { + unreachable!("unsafe binders are not yet implemented") + } + hir::ExprKind::DropTemps(source) => ExprKind::Use { source: self.mirror_expr(source) }, hir::ExprKind::Array(fields) => ExprKind::Array { fields: self.mirror_exprs(fields) }, hir::ExprKind::Tup(fields) => ExprKind::Tuple { fields: self.mirror_exprs(fields) }, diff --git a/compiler/rustc_mir_build/src/thir/util.rs b/compiler/rustc_mir_build/src/thir/util.rs index 53a2a0852eb..ed7c7e40993 100644 --- a/compiler/rustc_mir_build/src/thir/util.rs +++ b/compiler/rustc_mir_build/src/thir/util.rs @@ -1,6 +1,6 @@ use rustc_hir as hir; use rustc_middle::bug; -use rustc_middle::ty::{self, CanonicalUserType, TyCtxt, UserType}; +use rustc_middle::ty::{self, CanonicalUserType, TyCtxt}; use tracing::debug; pub(crate) trait UserAnnotatedTyHelpers<'tcx> { @@ -21,7 +21,7 @@ pub(crate) trait UserAnnotatedTyHelpers<'tcx> { let ty = self.typeck_results().node_type(hir_id); match ty.kind() { ty::Adt(adt_def, ..) => { - if let UserType::TypeOf(ref mut did, _) = &mut user_ty.value { + if let ty::UserTypeKind::TypeOf(ref mut did, _) = &mut user_ty.value.kind { *did = adt_def.did(); } Some(user_ty) diff --git a/compiler/rustc_mir_dataflow/src/framework/cursor.rs b/compiler/rustc_mir_dataflow/src/framework/cursor.rs index 4a9bcdaddb3..89ff93d9943 100644 --- a/compiler/rustc_mir_dataflow/src/framework/cursor.rs +++ b/compiler/rustc_mir_dataflow/src/framework/cursor.rs @@ -179,15 +179,15 @@ where /// Advances the cursor to hold the dataflow state at `target` before its "primary" effect is /// applied. /// - /// The "before" effect at the target location *will be* applied. + /// The "early" effect at the target location *will be* applied. pub fn seek_before_primary_effect(&mut self, target: Location) { - self.seek_after(target, Effect::Before) + self.seek_after(target, Effect::Early) } /// Advances the cursor to hold the dataflow state at `target` after its "primary" effect is /// applied. /// - /// The "before" effect at the target location will be applied as well. + /// The "early" effect at the target location will be applied as well. pub fn seek_after_primary_effect(&mut self, target: Location) { self.seek_after(target, Effect::Primary) } @@ -222,12 +222,12 @@ where #[rustfmt::skip] let next_effect = if A::Direction::IS_FORWARD { self.pos.curr_effect_index.map_or_else( - || Effect::Before.at_index(0), + || Effect::Early.at_index(0), EffectIndex::next_in_forward_order, ) } else { self.pos.curr_effect_index.map_or_else( - || Effect::Before.at_index(block_data.statements.len()), + || Effect::Early.at_index(block_data.statements.len()), EffectIndex::next_in_backward_order, ) }; diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 566a6b09b2b..9d943ebe327 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -66,12 +66,12 @@ impl Direction for Backward { { let terminator = block_data.terminator(); let location = Location { block, statement_index: block_data.statements.len() }; - analysis.apply_before_terminator_effect(state, terminator, location); - analysis.apply_terminator_effect(state, terminator, location); + analysis.apply_early_terminator_effect(state, terminator, location); + analysis.apply_primary_terminator_effect(state, terminator, location); for (statement_index, statement) in block_data.statements.iter().enumerate().rev() { let location = Location { block, statement_index }; - analysis.apply_before_statement_effect(state, statement, location); - analysis.apply_statement_effect(state, statement, location); + analysis.apply_early_statement_effect(state, statement, location); + analysis.apply_primary_statement_effect(state, statement, location); } let exit_state = state; @@ -159,14 +159,14 @@ impl Direction for Backward { let location = Location { block, statement_index: from.statement_index }; let terminator = block_data.terminator(); - if from.effect == Effect::Before { - analysis.apply_before_terminator_effect(state, terminator, location); - if to == Effect::Before.at_index(terminator_index) { + if from.effect == Effect::Early { + analysis.apply_early_terminator_effect(state, terminator, location); + if to == Effect::Early.at_index(terminator_index) { return; } } - analysis.apply_terminator_effect(state, terminator, location); + analysis.apply_primary_terminator_effect(state, terminator, location); if to == Effect::Primary.at_index(terminator_index) { return; } @@ -180,7 +180,7 @@ impl Direction for Backward { let location = Location { block, statement_index: from.statement_index }; let statement = &block_data.statements[from.statement_index]; - analysis.apply_statement_effect(state, statement, location); + analysis.apply_primary_statement_effect(state, statement, location); if to == Effect::Primary.at_index(from.statement_index) { return; } @@ -188,7 +188,7 @@ impl Direction for Backward { from.statement_index - 1 } - Effect::Before => from.statement_index, + Effect::Early => from.statement_index, }; // Handle all statements between `first_unapplied_idx` and `to.statement_index`. @@ -196,21 +196,21 @@ impl Direction for Backward { for statement_index in (to.statement_index..next_effect).rev().map(|i| i + 1) { let location = Location { block, statement_index }; let statement = &block_data.statements[statement_index]; - analysis.apply_before_statement_effect(state, statement, location); - analysis.apply_statement_effect(state, statement, location); + analysis.apply_early_statement_effect(state, statement, location); + analysis.apply_primary_statement_effect(state, statement, location); } // Handle the statement at `to`. let location = Location { block, statement_index: to.statement_index }; let statement = &block_data.statements[to.statement_index]; - analysis.apply_before_statement_effect(state, statement, location); + analysis.apply_early_statement_effect(state, statement, location); - if to.effect == Effect::Before { + if to.effect == Effect::Early { return; } - analysis.apply_statement_effect(state, statement, location); + analysis.apply_primary_statement_effect(state, statement, location); } fn visit_results_in_block<'mir, 'tcx, A>( @@ -228,17 +228,17 @@ impl Direction for Backward { let loc = Location { block, statement_index: block_data.statements.len() }; let term = block_data.terminator(); - results.analysis.apply_before_terminator_effect(state, term, loc); - vis.visit_terminator_before_primary_effect(results, state, term, loc); - results.analysis.apply_terminator_effect(state, term, loc); - vis.visit_terminator_after_primary_effect(results, state, term, loc); + results.analysis.apply_early_terminator_effect(state, term, loc); + vis.visit_after_early_terminator_effect(results, state, term, loc); + results.analysis.apply_primary_terminator_effect(state, term, loc); + vis.visit_after_primary_terminator_effect(results, state, term, loc); for (statement_index, stmt) in block_data.statements.iter().enumerate().rev() { let loc = Location { block, statement_index }; - results.analysis.apply_before_statement_effect(state, stmt, loc); - vis.visit_statement_before_primary_effect(results, state, stmt, loc); - results.analysis.apply_statement_effect(state, stmt, loc); - vis.visit_statement_after_primary_effect(results, state, stmt, loc); + results.analysis.apply_early_statement_effect(state, stmt, loc); + vis.visit_after_early_statement_effect(results, state, stmt, loc); + results.analysis.apply_primary_statement_effect(state, stmt, loc); + vis.visit_after_primary_statement_effect(results, state, stmt, loc); } vis.visit_block_start(state); @@ -294,13 +294,13 @@ impl Direction for Forward { { for (statement_index, statement) in block_data.statements.iter().enumerate() { let location = Location { block, statement_index }; - analysis.apply_before_statement_effect(state, statement, location); - analysis.apply_statement_effect(state, statement, location); + analysis.apply_early_statement_effect(state, statement, location); + analysis.apply_primary_statement_effect(state, statement, location); } let terminator = block_data.terminator(); let location = Location { block, statement_index: block_data.statements.len() }; - analysis.apply_before_terminator_effect(state, terminator, location); - let edges = analysis.apply_terminator_effect(state, terminator, location); + analysis.apply_early_terminator_effect(state, terminator, location); + let edges = analysis.apply_primary_terminator_effect(state, terminator, location); let exit_state = state; match edges { @@ -368,21 +368,21 @@ impl Direction for Forward { // after effect, do so now and start the loop below from the next statement. let first_unapplied_index = match from.effect { - Effect::Before => from.statement_index, + Effect::Early => from.statement_index, Effect::Primary if from.statement_index == terminator_index => { debug_assert_eq!(from, to); let location = Location { block, statement_index: terminator_index }; let terminator = block_data.terminator(); - analysis.apply_terminator_effect(state, terminator, location); + analysis.apply_primary_terminator_effect(state, terminator, location); return; } Effect::Primary => { let location = Location { block, statement_index: from.statement_index }; let statement = &block_data.statements[from.statement_index]; - analysis.apply_statement_effect(state, statement, location); + analysis.apply_primary_statement_effect(state, statement, location); // If we only needed to apply the after effect of the statement at `idx`, we are // done. @@ -399,8 +399,8 @@ impl Direction for Forward { for statement_index in first_unapplied_index..to.statement_index { let location = Location { block, statement_index }; let statement = &block_data.statements[statement_index]; - analysis.apply_before_statement_effect(state, statement, location); - analysis.apply_statement_effect(state, statement, location); + analysis.apply_early_statement_effect(state, statement, location); + analysis.apply_primary_statement_effect(state, statement, location); } // Handle the statement or terminator at `to`. @@ -408,17 +408,17 @@ impl Direction for Forward { let location = Location { block, statement_index: to.statement_index }; if to.statement_index == terminator_index { let terminator = block_data.terminator(); - analysis.apply_before_terminator_effect(state, terminator, location); + analysis.apply_early_terminator_effect(state, terminator, location); if to.effect == Effect::Primary { - analysis.apply_terminator_effect(state, terminator, location); + analysis.apply_primary_terminator_effect(state, terminator, location); } } else { let statement = &block_data.statements[to.statement_index]; - analysis.apply_before_statement_effect(state, statement, location); + analysis.apply_early_statement_effect(state, statement, location); if to.effect == Effect::Primary { - analysis.apply_statement_effect(state, statement, location); + analysis.apply_primary_statement_effect(state, statement, location); } } } @@ -438,18 +438,18 @@ impl Direction for Forward { for (statement_index, stmt) in block_data.statements.iter().enumerate() { let loc = Location { block, statement_index }; - results.analysis.apply_before_statement_effect(state, stmt, loc); - vis.visit_statement_before_primary_effect(results, state, stmt, loc); - results.analysis.apply_statement_effect(state, stmt, loc); - vis.visit_statement_after_primary_effect(results, state, stmt, loc); + results.analysis.apply_early_statement_effect(state, stmt, loc); + vis.visit_after_early_statement_effect(results, state, stmt, loc); + results.analysis.apply_primary_statement_effect(state, stmt, loc); + vis.visit_after_primary_statement_effect(results, state, stmt, loc); } let loc = Location { block, statement_index: block_data.statements.len() }; let term = block_data.terminator(); - results.analysis.apply_before_terminator_effect(state, term, loc); - vis.visit_terminator_before_primary_effect(results, state, term, loc); - results.analysis.apply_terminator_effect(state, term, loc); - vis.visit_terminator_after_primary_effect(results, state, term, loc); + results.analysis.apply_early_terminator_effect(state, term, loc); + vis.visit_after_early_terminator_effect(results, state, term, loc); + results.analysis.apply_primary_terminator_effect(state, term, loc); + vis.visit_after_primary_terminator_effect(results, state, term, loc); vis.visit_block_end(state); } diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index f844e8fbe03..5b2b128e035 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -724,7 +724,7 @@ where } } - fn visit_statement_before_primary_effect( + fn visit_after_early_statement_effect( &mut self, results: &mut Results<'tcx, A>, state: &A::Domain, @@ -737,7 +737,7 @@ where } } - fn visit_statement_after_primary_effect( + fn visit_after_primary_statement_effect( &mut self, results: &mut Results<'tcx, A>, state: &A::Domain, @@ -748,7 +748,7 @@ where self.prev_state.clone_from(state) } - fn visit_terminator_before_primary_effect( + fn visit_after_early_terminator_effect( &mut self, results: &mut Results<'tcx, A>, state: &A::Domain, @@ -761,7 +761,7 @@ where } } - fn visit_terminator_after_primary_effect( + fn visit_after_primary_terminator_effect( &mut self, results: &mut Results<'tcx, A>, state: &A::Domain, diff --git a/compiler/rustc_mir_dataflow/src/framework/lattice.rs b/compiler/rustc_mir_dataflow/src/framework/lattice.rs index e063eaf74bd..cb8159ce37b 100644 --- a/compiler/rustc_mir_dataflow/src/framework/lattice.rs +++ b/compiler/rustc_mir_dataflow/src/framework/lattice.rs @@ -38,10 +38,8 @@ //! [Hasse diagram]: https://en.wikipedia.org/wiki/Hasse_diagram //! [poset]: https://en.wikipedia.org/wiki/Partially_ordered_set -use std::iter; - +use rustc_index::Idx; use rustc_index::bit_set::{BitSet, MixedBitSet}; -use rustc_index::{Idx, IndexVec}; use crate::framework::BitSetExt; @@ -70,53 +68,6 @@ pub trait HasTop { const TOP: Self; } -/// A `bool` is a "two-point" lattice with `true` as the top element and `false` as the bottom: -/// -/// ```text -/// true -/// | -/// false -/// ``` -impl JoinSemiLattice for bool { - fn join(&mut self, other: &Self) -> bool { - if let (false, true) = (*self, *other) { - *self = true; - return true; - } - - false - } -} - -impl HasBottom for bool { - const BOTTOM: Self = false; - - fn is_bottom(&self) -> bool { - !self - } -} - -impl HasTop for bool { - const TOP: Self = true; -} - -/// A tuple (or list) of lattices is itself a lattice whose least upper bound is the concatenation -/// of the least upper bounds of each element of the tuple (or list). -/// -/// In other words: -/// (A₀, A₁, ..., Aₙ) ∨ (B₀, B₁, ..., Bₙ) = (A₀∨B₀, A₁∨B₁, ..., Aₙ∨Bₙ) -impl<I: Idx, T: JoinSemiLattice> JoinSemiLattice for IndexVec<I, T> { - fn join(&mut self, other: &Self) -> bool { - assert_eq!(self.len(), other.len()); - - let mut changed = false; - for (a, b) in iter::zip(self, other) { - changed |= a.join(b); - } - changed - } -} - /// A `BitSet` represents the lattice formed by the powerset of all possible values of /// the index type `T` ordered by inclusion. Equivalently, it is a tuple of "two-point" lattices, /// one for each possible value of `T`. @@ -197,18 +148,6 @@ impl<T> MaybeReachable<T> { } } -impl<T> HasBottom for MaybeReachable<T> { - const BOTTOM: Self = MaybeReachable::Unreachable; - - fn is_bottom(&self) -> bool { - matches!(self, Self::Unreachable) - } -} - -impl<T: HasTop> HasTop for MaybeReachable<T> { - const TOP: Self = MaybeReachable::Reachable(T::TOP); -} - impl<S> MaybeReachable<S> { /// Return whether the current state contains the given element. If the state is unreachable, /// it does no contain anything. diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index 7f5a68e884e..41df5fae0de 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -56,7 +56,7 @@ mod visitor; pub use self::cursor::ResultsCursor; pub use self::direction::{Backward, Direction, Forward}; pub use self::lattice::{JoinSemiLattice, MaybeReachable}; -pub use self::results::{EntrySets, Results}; +pub use self::results::{EntryStates, Results}; pub use self::visitor::{ResultsVisitor, visit_results}; /// Analysis domains are all bitsets of various kinds. This trait holds @@ -122,8 +122,23 @@ pub trait Analysis<'tcx> { // `resume`). It's not obvious how to handle `yield` points in coroutines, however. fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut Self::Domain); + /// Updates the current dataflow state with an "early" effect, i.e. one + /// that occurs immediately before the given statement. + /// + /// This method is useful if the consumer of the results of this analysis only needs to observe + /// *part* of the effect of a statement (e.g. for two-phase borrows). As a general rule, + /// analyses should not implement this without also implementing + /// `apply_primary_statement_effect`. + fn apply_early_statement_effect( + &mut self, + _state: &mut Self::Domain, + _statement: &mir::Statement<'tcx>, + _location: Location, + ) { + } + /// Updates the current dataflow state with the effect of evaluating a statement. - fn apply_statement_effect( + fn apply_primary_statement_effect( &mut self, state: &mut Self::Domain, statement: &mir::Statement<'tcx>, @@ -131,15 +146,16 @@ pub trait Analysis<'tcx> { ); /// Updates the current dataflow state with an effect that occurs immediately *before* the - /// given statement. + /// given terminator. /// - /// This method is useful if the consumer of the results of this analysis only needs to observe - /// *part* of the effect of a statement (e.g. for two-phase borrows). As a general rule, - /// analyses should not implement this without also implementing `apply_statement_effect`. - fn apply_before_statement_effect( + /// This method is useful if the consumer of the results of this analysis needs only to observe + /// *part* of the effect of a terminator (e.g. for two-phase borrows). As a general rule, + /// analyses should not implement this without also implementing + /// `apply_primary_terminator_effect`. + fn apply_early_terminator_effect( &mut self, _state: &mut Self::Domain, - _statement: &mir::Statement<'tcx>, + _terminator: &mir::Terminator<'tcx>, _location: Location, ) { } @@ -150,7 +166,7 @@ pub trait Analysis<'tcx> { /// in this function. That should go in `apply_call_return_effect`. For example, in the /// `InitializedPlaces` analyses, the return place for a function call is not marked as /// initialized here. - fn apply_terminator_effect<'mir>( + fn apply_primary_terminator_effect<'mir>( &mut self, _state: &mut Self::Domain, terminator: &'mir mir::Terminator<'tcx>, @@ -159,27 +175,13 @@ pub trait Analysis<'tcx> { terminator.edges() } - /// Updates the current dataflow state with an effect that occurs immediately *before* the - /// given terminator. - /// - /// This method is useful if the consumer of the results of this analysis needs only to observe - /// *part* of the effect of a terminator (e.g. for two-phase borrows). As a general rule, - /// analyses should not implement this without also implementing `apply_terminator_effect`. - fn apply_before_terminator_effect( - &mut self, - _state: &mut Self::Domain, - _terminator: &mir::Terminator<'tcx>, - _location: Location, - ) { - } - /* Edge-specific effects */ /// Updates the current dataflow state with the effect of a successful return from a `Call` /// terminator. /// - /// This is separate from `apply_terminator_effect` to properly track state across unwind - /// edges. + /// This is separate from `apply_primary_terminator_effect` to properly track state across + /// unwind edges. fn apply_call_return_effect( &mut self, _state: &mut Self::Domain, @@ -234,11 +236,12 @@ pub trait Analysis<'tcx> { Self: Sized, Self::Domain: DebugWithContext<Self>, { - let mut entry_sets = + let mut entry_states = IndexVec::from_fn_n(|_| self.bottom_value(body), body.basic_blocks.len()); - self.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]); + self.initialize_start_block(body, &mut entry_states[mir::START_BLOCK]); - if Self::Direction::IS_BACKWARD && entry_sets[mir::START_BLOCK] != self.bottom_value(body) { + if Self::Direction::IS_BACKWARD && entry_states[mir::START_BLOCK] != self.bottom_value(body) + { bug!("`initialize_start_block` is not yet supported for backward dataflow analyses"); } @@ -262,9 +265,9 @@ pub trait Analysis<'tcx> { let mut state = self.bottom_value(body); while let Some(bb) = dirty_queue.pop() { // Set the state to the entry state of the block. - // This is equivalent to `state = entry_sets[bb].clone()`, + // This is equivalent to `state = entry_states[bb].clone()`, // but it saves an allocation, thus improving compile times. - state.clone_from(&entry_sets[bb]); + state.clone_from(&entry_states[bb]); Self::Direction::apply_effects_in_block( &mut self, @@ -273,7 +276,7 @@ pub trait Analysis<'tcx> { bb, &body[bb], |target: BasicBlock, state: &Self::Domain| { - let set_changed = entry_sets[target].join(state); + let set_changed = entry_states[target].join(state); if set_changed { dirty_queue.insert(target); } @@ -281,7 +284,7 @@ pub trait Analysis<'tcx> { ); } - let mut results = Results { analysis: self, entry_sets }; + let mut results = Results { analysis: self, entry_states }; if tcx.sess.opts.unstable_opts.dump_mir_dataflow { let res = write_graphviz_results(tcx, body, &mut results, pass_name); @@ -358,11 +361,10 @@ impl<T, S: GenKill<T>> GenKill<T> for MaybeReachable<S> { // NOTE: DO NOT CHANGE VARIANT ORDER. The derived `Ord` impls rely on the current order. #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] enum Effect { - /// The "before" effect (e.g., `apply_before_statement_effect`) for a statement (or - /// terminator). - Before, + /// The "early" effect (e.g., `apply_early_statement_effect`) for a statement/terminator. + Early, - /// The "primary" effect (e.g., `apply_statement_effect`) for a statement (or terminator). + /// The "primary" effect (e.g., `apply_primary_statement_effect`) for a statement/terminator. Primary, } @@ -381,15 +383,15 @@ pub struct EffectIndex { impl EffectIndex { fn next_in_forward_order(self) -> Self { match self.effect { - Effect::Before => Effect::Primary.at_index(self.statement_index), - Effect::Primary => Effect::Before.at_index(self.statement_index + 1), + Effect::Early => Effect::Primary.at_index(self.statement_index), + Effect::Primary => Effect::Early.at_index(self.statement_index + 1), } } fn next_in_backward_order(self) -> Self { match self.effect { - Effect::Before => Effect::Primary.at_index(self.statement_index), - Effect::Primary => Effect::Before.at_index(self.statement_index - 1), + Effect::Early => Effect::Primary.at_index(self.statement_index), + Effect::Primary => Effect::Early.at_index(self.statement_index - 1), } } diff --git a/compiler/rustc_mir_dataflow/src/framework/results.rs b/compiler/rustc_mir_dataflow/src/framework/results.rs index a7dbd99b8ab..8e2c3afddb3 100644 --- a/compiler/rustc_mir_dataflow/src/framework/results.rs +++ b/compiler/rustc_mir_dataflow/src/framework/results.rs @@ -6,7 +6,7 @@ use rustc_middle::mir::{BasicBlock, Body, traversal}; use super::{Analysis, ResultsCursor, ResultsVisitor, visit_results}; use crate::framework::cursor::ResultsHandle; -pub type EntrySets<'tcx, A> = IndexVec<BasicBlock, <A as Analysis<'tcx>>::Domain>; +pub type EntryStates<'tcx, A> = IndexVec<BasicBlock, <A as Analysis<'tcx>>::Domain>; /// A dataflow analysis that has converged to fixpoint. It only holds the domain values at the /// entry of each basic block. Domain values in other parts of the block are recomputed on the fly @@ -17,7 +17,7 @@ where A: Analysis<'tcx>, { pub analysis: A, - pub entry_sets: EntrySets<'tcx, A>, + pub entry_states: EntryStates<'tcx, A>, } impl<'tcx, A> Results<'tcx, A> @@ -40,7 +40,7 @@ where /// Gets the dataflow state for the given block. pub fn entry_set_for_block(&self, block: BasicBlock) -> &A::Domain { - &self.entry_sets[block] + &self.entry_states[block] } pub fn visit_with<'mir>( diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs index 14fb6dfb50c..8e7d4ab0fa3 100644 --- a/compiler/rustc_mir_dataflow/src/framework/tests.rs +++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs @@ -73,7 +73,7 @@ fn mock_body<'tcx>() -> mir::Body<'tcx> { /// /// The `102` in the block's entry set is derived from the basic block index and ensures that the /// expected state is unique across all basic blocks. Remember, it is generated by -/// `mock_entry_sets`, not from actually running `MockAnalysis` to fixpoint. +/// `mock_entry_states`, not from actually running `MockAnalysis` to fixpoint. struct MockAnalysis<'tcx, D> { body: &'tcx mir::Body<'tcx>, dir: PhantomData<D>, @@ -90,7 +90,7 @@ impl<D: Direction> MockAnalysis<'_, D> { ret } - fn mock_entry_sets(&self) -> IndexVec<BasicBlock, BitSet<usize>> { + fn mock_entry_states(&self) -> IndexVec<BasicBlock, BitSet<usize>> { let empty = self.bottom_value(self.body); let mut ret = IndexVec::from_elem(empty, &self.body.basic_blocks); @@ -104,7 +104,7 @@ impl<D: Direction> MockAnalysis<'_, D> { /// Returns the index that should be added to the dataflow state at the given target. fn effect(&self, loc: EffectIndex) -> usize { let idx = match loc.effect { - Effect::Before => loc.statement_index * 2, + Effect::Early => loc.statement_index * 2, Effect::Primary => loc.statement_index * 2 + 1, }; @@ -128,14 +128,14 @@ impl<D: Direction> MockAnalysis<'_, D> { let target = match target { SeekTarget::BlockEntry { .. } => return ret, - SeekTarget::Before(loc) => Effect::Before.at_index(loc.statement_index), + SeekTarget::Early(loc) => Effect::Early.at_index(loc.statement_index), SeekTarget::After(loc) => Effect::Primary.at_index(loc.statement_index), }; let mut pos = if D::IS_FORWARD { - Effect::Before.at_index(0) + Effect::Early.at_index(0) } else { - Effect::Before.at_index(self.body[block].statements.len()) + Effect::Early.at_index(self.body[block].statements.len()) }; loop { @@ -168,52 +168,52 @@ impl<'tcx, D: Direction> Analysis<'tcx> for MockAnalysis<'tcx, D> { unimplemented!("This is never called since `MockAnalysis` is never iterated to fixpoint"); } - fn apply_statement_effect( + fn apply_early_statement_effect( &mut self, state: &mut Self::Domain, _statement: &mir::Statement<'tcx>, location: Location, ) { - let idx = self.effect(Effect::Primary.at_index(location.statement_index)); + let idx = self.effect(Effect::Early.at_index(location.statement_index)); assert!(state.insert(idx)); } - fn apply_before_statement_effect( + fn apply_primary_statement_effect( &mut self, state: &mut Self::Domain, _statement: &mir::Statement<'tcx>, location: Location, ) { - let idx = self.effect(Effect::Before.at_index(location.statement_index)); + let idx = self.effect(Effect::Primary.at_index(location.statement_index)); assert!(state.insert(idx)); } - fn apply_terminator_effect<'mir>( + fn apply_early_terminator_effect( &mut self, state: &mut Self::Domain, - terminator: &'mir mir::Terminator<'tcx>, + _terminator: &mir::Terminator<'tcx>, location: Location, - ) -> TerminatorEdges<'mir, 'tcx> { - let idx = self.effect(Effect::Primary.at_index(location.statement_index)); + ) { + let idx = self.effect(Effect::Early.at_index(location.statement_index)); assert!(state.insert(idx)); - terminator.edges() } - fn apply_before_terminator_effect( + fn apply_primary_terminator_effect<'mir>( &mut self, state: &mut Self::Domain, - _terminator: &mir::Terminator<'tcx>, + terminator: &'mir mir::Terminator<'tcx>, location: Location, - ) { - let idx = self.effect(Effect::Before.at_index(location.statement_index)); + ) -> TerminatorEdges<'mir, 'tcx> { + let idx = self.effect(Effect::Primary.at_index(location.statement_index)); assert!(state.insert(idx)); + terminator.edges() } } #[derive(Clone, Copy, Debug, PartialEq, Eq)] enum SeekTarget { BlockEntry(BasicBlock), - Before(Location), + Early(Location), After(Location), } @@ -223,7 +223,7 @@ impl SeekTarget { match *self { BlockEntry(block) => block, - Before(loc) | After(loc) => loc.block, + Early(loc) | After(loc) => loc.block, } } @@ -235,7 +235,7 @@ impl SeekTarget { .map(move |(i, kind)| { let loc = Location { block, statement_index: i }; match kind { - 0 => SeekTarget::Before(loc), + 0 => SeekTarget::Early(loc), 1 => SeekTarget::After(loc), _ => unreachable!(), } @@ -249,7 +249,7 @@ fn test_cursor<D: Direction>(analysis: MockAnalysis<'_, D>) { let body = analysis.body; let mut cursor = - Results { entry_sets: analysis.mock_entry_sets(), analysis }.into_results_cursor(body); + Results { entry_states: analysis.mock_entry_states(), analysis }.into_results_cursor(body); cursor.allow_unreachable(); @@ -262,7 +262,7 @@ fn test_cursor<D: Direction>(analysis: MockAnalysis<'_, D>) { match targ { BlockEntry(block) => cursor.seek_to_block_entry(block), - Before(loc) => cursor.seek_before_primary_effect(loc), + Early(loc) => cursor.seek_before_primary_effect(loc), After(loc) => cursor.seek_after_primary_effect(loc), } diff --git a/compiler/rustc_mir_dataflow/src/framework/visitor.rs b/compiler/rustc_mir_dataflow/src/framework/visitor.rs index bde41974d47..d18e9fa33f0 100644 --- a/compiler/rustc_mir_dataflow/src/framework/visitor.rs +++ b/compiler/rustc_mir_dataflow/src/framework/visitor.rs @@ -35,9 +35,9 @@ where { fn visit_block_start(&mut self, _state: &A::Domain) {} - /// Called with the `before_statement_effect` of the given statement applied to `state` but not - /// its `statement_effect`. - fn visit_statement_before_primary_effect( + /// // njn: grep for "before", "primary", etc. + /// Called after the "early" effect of the given statement is applied to `state`. + fn visit_after_early_statement_effect( &mut self, _results: &mut Results<'tcx, A>, _state: &A::Domain, @@ -46,9 +46,8 @@ where ) { } - /// Called with both the `before_statement_effect` and the `statement_effect` of the given - /// statement applied to `state`. - fn visit_statement_after_primary_effect( + /// Called after the "primary" effect of the given statement is applied to `state`. + fn visit_after_primary_statement_effect( &mut self, _results: &mut Results<'tcx, A>, _state: &A::Domain, @@ -57,9 +56,8 @@ where ) { } - /// Called with the `before_terminator_effect` of the given terminator applied to `state` but - /// not its `terminator_effect`. - fn visit_terminator_before_primary_effect( + /// Called after the "early" effect of the given terminator is applied to `state`. + fn visit_after_early_terminator_effect( &mut self, _results: &mut Results<'tcx, A>, _state: &A::Domain, @@ -68,11 +66,10 @@ where ) { } - /// Called with both the `before_terminator_effect` and the `terminator_effect` of the given - /// terminator applied to `state`. + /// Called after the "primary" effect of the given terminator is applied to `state`. /// /// The `call_return_effect` (if one exists) will *not* be applied to `state`. - fn visit_terminator_after_primary_effect( + fn visit_after_primary_terminator_effect( &mut self, _results: &mut Results<'tcx, A>, _state: &A::Domain, diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index cec654cac72..568d8a5acaf 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -33,22 +33,22 @@ impl<'tcx> Analysis<'tcx> for MaybeBorrowedLocals { // No locals are aliased on function entry } - fn apply_statement_effect( + fn apply_primary_statement_effect( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, statement: &Statement<'tcx>, location: Location, ) { - Self::transfer_function(trans).visit_statement(statement, location); + Self::transfer_function(state).visit_statement(statement, location); } - fn apply_terminator_effect<'mir>( + fn apply_primary_terminator_effect<'mir>( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, terminator: &'mir Terminator<'tcx>, location: Location, ) -> TerminatorEdges<'mir, 'tcx> { - Self::transfer_function(trans).visit_terminator(terminator, location); + Self::transfer_function(state).visit_terminator(terminator, location); terminator.edges() } } diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index 91677657602..fb02408e17d 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -70,7 +70,7 @@ impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> { pub fn is_unwind_dead( &self, place: mir::Place<'tcx>, - state: &MaybeReachable<MixedBitSet<MovePathIndex>>, + state: &<Self as Analysis<'tcx>>::Domain, ) -> bool { if let LookupResult::Exact(path) = self.move_data().rev_lookup.find(place.as_ref()) { let mut maybe_live = false; @@ -218,26 +218,26 @@ impl<'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'_, 'tcx> { impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> { fn update_bits( - trans: &mut <Self as Analysis<'tcx>>::Domain, + state: &mut <Self as Analysis<'tcx>>::Domain, path: MovePathIndex, - state: DropFlagState, + dfstate: DropFlagState, ) { - match state { - DropFlagState::Absent => trans.kill(path), - DropFlagState::Present => trans.gen_(path), + match dfstate { + DropFlagState::Absent => state.kill(path), + DropFlagState::Present => state.gen_(path), } } } impl<'tcx> MaybeUninitializedPlaces<'_, 'tcx> { fn update_bits( - trans: &mut <Self as Analysis<'tcx>>::Domain, + state: &mut <Self as Analysis<'tcx>>::Domain, path: MovePathIndex, - state: DropFlagState, + dfstate: DropFlagState, ) { - match state { - DropFlagState::Absent => trans.gen_(path), - DropFlagState::Present => trans.kill(path), + match dfstate { + DropFlagState::Absent => state.gen_(path), + DropFlagState::Present => state.kill(path), } } } @@ -263,14 +263,14 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { }); } - fn apply_statement_effect( + fn apply_primary_statement_effect( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, statement: &mir::Statement<'tcx>, location: Location, ) { drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| { - Self::update_bits(trans, path, s) + Self::update_bits(state, path, s) }); // Mark all places as "maybe init" if they are mutably borrowed. See #90752. @@ -282,12 +282,12 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { && let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref()) { on_all_children_bits(self.move_data(), mpi, |child| { - trans.gen_(child); + state.gen_(child); }) } } - fn apply_terminator_effect<'mir>( + fn apply_primary_terminator_effect<'mir>( &mut self, state: &mut Self::Domain, terminator: &'mir mir::Terminator<'tcx>, @@ -309,7 +309,7 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { fn apply_call_return_effect( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, _block: mir::BasicBlock, return_places: CallReturnPlaces<'_, 'tcx>, ) { @@ -320,7 +320,7 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { self.move_data(), self.move_data().rev_lookup.find(place.as_ref()), |mpi| { - trans.gen_(mpi); + state.gen_(mpi); }, ); }); @@ -345,7 +345,7 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { }; let mut discriminants = enum_def.discriminants(self.tcx); - edge_effects.apply(|trans, edge| { + edge_effects.apply(|state, edge| { let Some(value) = edge.value else { return; }; @@ -363,25 +363,27 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { self.move_data(), enum_place, variant, - |mpi| trans.kill(mpi), + |mpi| state.kill(mpi), ); }); } } +/// There can be many more `MovePathIndex` than there are locals in a MIR body. +/// We use a mixed bitset to avoid paying too high a memory footprint. +pub type MaybeUninitializedPlacesDomain = MixedBitSet<MovePathIndex>; + impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { - /// There can be many more `MovePathIndex` than there are locals in a MIR body. - /// We use a mixed bitset to avoid paying too high a memory footprint. - type Domain = MixedBitSet<MovePathIndex>; + type Domain = MaybeUninitializedPlacesDomain; const NAME: &'static str = "maybe_uninit"; fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain { - // bottom = initialized (start_block_effect counters this at outset) + // bottom = initialized (`initialize_start_block` overwrites this on first entry) MixedBitSet::new_empty(self.move_data().move_paths.len()) } - // sets on_entry bits for Arg places + // sets state bits for Arg places fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) { // set all bits to 1 (uninit) before gathering counter-evidence state.insert_all(); @@ -392,28 +394,28 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { }); } - fn apply_statement_effect( + fn apply_primary_statement_effect( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, _statement: &mir::Statement<'tcx>, location: Location, ) { drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| { - Self::update_bits(trans, path, s) + Self::update_bits(state, path, s) }); // Unlike in `MaybeInitializedPlaces` above, we don't need to change the state when a // mutable borrow occurs. Places cannot become uninitialized through a mutable reference. } - fn apply_terminator_effect<'mir>( + fn apply_primary_terminator_effect<'mir>( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, terminator: &'mir mir::Terminator<'tcx>, location: Location, ) -> TerminatorEdges<'mir, 'tcx> { drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| { - Self::update_bits(trans, path, s) + Self::update_bits(state, path, s) }); if self.skip_unreachable_unwind.contains(location.block) { let mir::TerminatorKind::Drop { target, unwind, .. } = terminator.kind else { bug!() }; @@ -426,7 +428,7 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { fn apply_call_return_effect( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, _block: mir::BasicBlock, return_places: CallReturnPlaces<'_, 'tcx>, ) { @@ -437,7 +439,7 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { self.move_data(), self.move_data().rev_lookup.find(place.as_ref()), |mpi| { - trans.kill(mpi); + state.kill(mpi); }, ); }); @@ -466,7 +468,7 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { }; let mut discriminants = enum_def.discriminants(self.tcx); - edge_effects.apply(|trans, edge| { + edge_effects.apply(|state, edge| { let Some(value) = edge.value else { return; }; @@ -484,16 +486,18 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { self.move_data(), enum_place, variant, - |mpi| trans.gen_(mpi), + |mpi| state.gen_(mpi), ); }); } } +/// There can be many more `InitIndex` than there are locals in a MIR body. +/// We use a mixed bitset to avoid paying too high a memory footprint. +pub type EverInitializedPlacesDomain = MixedBitSet<InitIndex>; + impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { - /// There can be many more `InitIndex` than there are locals in a MIR body. - /// We use a mixed bitset to avoid paying too high a memory footprint. - type Domain = MixedBitSet<InitIndex>; + type Domain = EverInitializedPlacesDomain; const NAME: &'static str = "ever_init"; @@ -508,10 +512,10 @@ impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { } } - #[instrument(skip(self, trans), level = "debug")] - fn apply_statement_effect( + #[instrument(skip(self, state), level = "debug")] + fn apply_primary_statement_effect( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, stmt: &mir::Statement<'tcx>, location: Location, ) { @@ -521,7 +525,7 @@ impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { let rev_lookup = &move_data.rev_lookup; debug!("initializes move_indexes {:?}", init_loc_map[location]); - trans.gen_all(init_loc_map[location].iter().copied()); + state.gen_all(init_loc_map[location].iter().copied()); if let mir::StatementKind::StorageDead(local) = stmt.kind { // End inits for StorageDead, so that an immutable variable can @@ -531,15 +535,15 @@ impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { "clears the ever initialized status of {:?}", init_path_map[move_path_index] ); - trans.kill_all(init_path_map[move_path_index].iter().copied()); + state.kill_all(init_path_map[move_path_index].iter().copied()); } } } - #[instrument(skip(self, trans, terminator), level = "debug")] - fn apply_terminator_effect<'mir>( + #[instrument(skip(self, state, terminator), level = "debug")] + fn apply_primary_terminator_effect<'mir>( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, terminator: &'mir mir::Terminator<'tcx>, location: Location, ) -> TerminatorEdges<'mir, 'tcx> { @@ -548,7 +552,7 @@ impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { let init_loc_map = &move_data.init_loc_map; debug!(?term); debug!("initializes move_indexes {:?}", init_loc_map[location]); - trans.gen_all( + state.gen_all( init_loc_map[location] .iter() .filter(|init_index| { @@ -561,7 +565,7 @@ impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { fn apply_call_return_effect( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, block: mir::BasicBlock, _return_places: CallReturnPlaces<'_, 'tcx>, ) { @@ -570,7 +574,7 @@ impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { let call_loc = self.body.terminator_loc(block); for init_index in &init_loc_map[call_loc] { - trans.gen_(*init_index); + state.gen_(*init_index); } } } diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index fd7254a0210..b2050a6adf9 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -40,33 +40,33 @@ impl<'tcx> Analysis<'tcx> for MaybeLiveLocals { // No variables are live until we observe a use } - fn apply_statement_effect( + fn apply_primary_statement_effect( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, statement: &mir::Statement<'tcx>, location: Location, ) { - TransferFunction(trans).visit_statement(statement, location); + TransferFunction(state).visit_statement(statement, location); } - fn apply_terminator_effect<'mir>( + fn apply_primary_terminator_effect<'mir>( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, terminator: &'mir mir::Terminator<'tcx>, location: Location, ) -> TerminatorEdges<'mir, 'tcx> { - TransferFunction(trans).visit_terminator(terminator, location); + TransferFunction(state).visit_terminator(terminator, location); terminator.edges() } fn apply_call_return_effect( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, _block: mir::BasicBlock, return_places: CallReturnPlaces<'_, 'tcx>, ) { if let CallReturnPlaces::Yield(resume_place) = return_places { - YieldResumeEffect(trans).visit_place( + YieldResumeEffect(state).visit_place( &resume_place, PlaceContext::MutatingUse(MutatingUseContext::Yield), Location::START, @@ -74,7 +74,7 @@ impl<'tcx> Analysis<'tcx> for MaybeLiveLocals { } else { return_places.for_each(|place| { if let Some(local) = place.as_local() { - trans.kill(local); + state.kill(local); } }); } @@ -137,10 +137,10 @@ enum DefUse { } impl DefUse { - fn apply(trans: &mut BitSet<Local>, place: Place<'_>, context: PlaceContext) { + fn apply(state: &mut BitSet<Local>, place: Place<'_>, context: PlaceContext) { match DefUse::for_place(place, context) { - Some(DefUse::Def) => trans.kill(place.local), - Some(DefUse::Use) => trans.gen_(place.local), + Some(DefUse::Def) => state.kill(place.local), + Some(DefUse::Use) => state.gen_(place.local), None => {} } } @@ -232,9 +232,9 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> { // No variables are live until we observe a use } - fn apply_statement_effect( + fn apply_primary_statement_effect( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, statement: &mir::Statement<'tcx>, location: Location, ) { @@ -258,34 +258,34 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> { }; if let Some(destination) = destination { if !destination.is_indirect() - && !trans.contains(destination.local) + && !state.contains(destination.local) && !self.always_live.contains(destination.local) { // This store is dead return; } } - TransferFunction(trans).visit_statement(statement, location); + TransferFunction(state).visit_statement(statement, location); } - fn apply_terminator_effect<'mir>( + fn apply_primary_terminator_effect<'mir>( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, terminator: &'mir mir::Terminator<'tcx>, location: Location, ) -> TerminatorEdges<'mir, 'tcx> { - TransferFunction(trans).visit_terminator(terminator, location); + TransferFunction(state).visit_terminator(terminator, location); terminator.edges() } fn apply_call_return_effect( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, _block: mir::BasicBlock, return_places: CallReturnPlaces<'_, 'tcx>, ) { if let CallReturnPlaces::Yield(resume_place) = return_places { - YieldResumeEffect(trans).visit_place( + YieldResumeEffect(state).visit_place( &resume_place, PlaceContext::MutatingUse(MutatingUseContext::Yield), Location::START, @@ -293,7 +293,7 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> { } else { return_places.for_each(|place| { if let Some(local) = place.as_local() { - trans.remove(local); + state.remove(local); } }); } diff --git a/compiler/rustc_mir_dataflow/src/impls/mod.rs b/compiler/rustc_mir_dataflow/src/impls/mod.rs index d69a8019c8d..3f29b819a6d 100644 --- a/compiler/rustc_mir_dataflow/src/impls/mod.rs +++ b/compiler/rustc_mir_dataflow/src/impls/mod.rs @@ -5,7 +5,8 @@ mod storage_liveness; pub use self::borrowed_locals::{MaybeBorrowedLocals, borrowed_locals}; pub use self::initialized::{ - EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces, + EverInitializedPlaces, EverInitializedPlacesDomain, MaybeInitializedPlaces, + MaybeUninitializedPlaces, MaybeUninitializedPlacesDomain, }; pub use self::liveness::{ MaybeLiveLocals, MaybeTransitiveLiveLocals, TransferFunction as LivenessTransferFunction, diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index 1aae06d79d3..65b480d3a5e 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -44,23 +44,23 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeStorageLive<'a> { BitSet::new_empty(body.local_decls.len()) } - fn initialize_start_block(&self, body: &Body<'tcx>, on_entry: &mut Self::Domain) { - on_entry.union(&*self.always_live_locals); + fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) { + state.union(&*self.always_live_locals); for arg in body.args_iter() { - on_entry.insert(arg); + state.insert(arg); } } - fn apply_statement_effect( + fn apply_primary_statement_effect( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, stmt: &Statement<'tcx>, _: Location, ) { match stmt.kind { - StatementKind::StorageLive(l) => trans.gen_(l), - StatementKind::StorageDead(l) => trans.kill(l), + StatementKind::StorageLive(l) => state.gen_(l), + StatementKind::StorageDead(l) => state.kill(l), _ => (), } } @@ -86,25 +86,25 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeStorageDead<'a> { BitSet::new_empty(body.local_decls.len()) } - fn initialize_start_block(&self, body: &Body<'tcx>, on_entry: &mut Self::Domain) { + fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) { assert_eq!(body.local_decls.len(), self.always_live_locals.domain_size()); // Do not iterate on return place and args, as they are trivially always live. for local in body.vars_and_temps_iter() { if !self.always_live_locals.contains(local) { - on_entry.insert(local); + state.insert(local); } } } - fn apply_statement_effect( + fn apply_primary_statement_effect( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, stmt: &Statement<'tcx>, _: Location, ) { match stmt.kind { - StatementKind::StorageLive(l) => trans.kill(l), - StatementKind::StorageDead(l) => trans.gen_(l), + StatementKind::StorageLive(l) => state.kill(l), + StatementKind::StorageDead(l) => state.gen_(l), _ => (), } } @@ -134,31 +134,31 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { BitSet::new_empty(body.local_decls.len()) } - fn initialize_start_block(&self, body: &Body<'tcx>, on_entry: &mut Self::Domain) { + fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) { // The resume argument is live on function entry (we don't care about // the `self` argument) for arg in body.args_iter().skip(1) { - on_entry.insert(arg); + state.insert(arg); } } - fn apply_before_statement_effect( + fn apply_early_statement_effect( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, stmt: &Statement<'tcx>, loc: Location, ) { // If a place is borrowed in a statement, it needs storage for that statement. - MaybeBorrowedLocals::transfer_function(trans).visit_statement(stmt, loc); + MaybeBorrowedLocals::transfer_function(state).visit_statement(stmt, loc); match &stmt.kind { - StatementKind::StorageDead(l) => trans.kill(*l), + StatementKind::StorageDead(l) => state.kill(*l), // If a place is assigned to in a statement, it needs storage for that statement. StatementKind::Assign(box (place, _)) | StatementKind::SetDiscriminant { box place, .. } | StatementKind::Deinit(box place) => { - trans.gen_(place.local); + state.gen_(place.local); } // Nothing to do for these. Match exhaustively so this fails to compile when new @@ -176,29 +176,29 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { } } - fn apply_statement_effect( + fn apply_primary_statement_effect( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, _: &Statement<'tcx>, loc: Location, ) { // If we move from a place then it only stops needing storage *after* // that statement. - self.check_for_move(trans, loc); + self.check_for_move(state, loc); } - fn apply_before_terminator_effect( + fn apply_early_terminator_effect( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, terminator: &Terminator<'tcx>, loc: Location, ) { // If a place is borrowed in a terminator, it needs storage for that terminator. - MaybeBorrowedLocals::transfer_function(trans).visit_terminator(terminator, loc); + MaybeBorrowedLocals::transfer_function(state).visit_terminator(terminator, loc); match &terminator.kind { TerminatorKind::Call { destination, .. } => { - trans.gen_(destination.local); + state.gen_(destination.local); } // Note that we do *not* gen the `resume_arg` of `Yield` terminators. The reason for @@ -213,7 +213,7 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { InlineAsmOperand::Out { place, .. } | InlineAsmOperand::InOut { out_place: place, .. } => { if let Some(place) = place { - trans.gen_(place.local); + state.gen_(place.local); } } InlineAsmOperand::In { .. } @@ -242,9 +242,9 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { } } - fn apply_terminator_effect<'t>( + fn apply_primary_terminator_effect<'t>( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, terminator: &'t Terminator<'tcx>, loc: Location, ) -> TerminatorEdges<'t, 'tcx> { @@ -254,12 +254,12 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { // Since `propagate_call_unwind` doesn't exist, we have to kill the // destination here, and then gen it again in `call_return_effect`. TerminatorKind::Call { destination, .. } => { - trans.kill(destination.local); + state.kill(destination.local); } // The same applies to InlineAsm outputs. TerminatorKind::InlineAsm { ref operands, .. } => { - CallReturnPlaces::InlineAsm(operands).for_each(|place| trans.kill(place.local)); + CallReturnPlaces::InlineAsm(operands).for_each(|place| state.kill(place.local)); } // Nothing to do for these. Match exhaustively so this fails to compile when new @@ -279,32 +279,32 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { | TerminatorKind::Unreachable => {} } - self.check_for_move(trans, loc); + self.check_for_move(state, loc); terminator.edges() } fn apply_call_return_effect( &mut self, - trans: &mut Self::Domain, + state: &mut Self::Domain, _block: BasicBlock, return_places: CallReturnPlaces<'_, 'tcx>, ) { - return_places.for_each(|place| trans.gen_(place.local)); + return_places.for_each(|place| state.gen_(place.local)); } } impl<'tcx> MaybeRequiresStorage<'_, 'tcx> { /// Kill locals that are fully moved and have not been borrowed. - fn check_for_move(&mut self, trans: &mut <Self as Analysis<'tcx>>::Domain, loc: Location) { + fn check_for_move(&mut self, state: &mut <Self as Analysis<'tcx>>::Domain, loc: Location) { let body = self.borrowed_locals.body(); - let mut visitor = MoveVisitor { trans, borrowed_locals: &mut self.borrowed_locals }; + let mut visitor = MoveVisitor { state, borrowed_locals: &mut self.borrowed_locals }; visitor.visit_location(body, loc); } } struct MoveVisitor<'a, 'mir, 'tcx> { borrowed_locals: &'a mut BorrowedLocalsResults<'mir, 'tcx>, - trans: &'a mut BitSet<Local>, + state: &'a mut BitSet<Local>, } impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, 'tcx> { @@ -312,7 +312,7 @@ impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, 'tcx> { if PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) == context { self.borrowed_locals.seek_before_primary_effect(loc); if !self.borrowed_locals.get().contains(local) { - self.trans.kill(local); + self.state.kill(local); } } } diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 2248972cecc..85255db5d9a 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -18,7 +18,7 @@ pub use self::drop_flag_effects::{ move_path_children_matching, on_all_children_bits, on_lookup_result_bits, }; pub use self::framework::{ - Analysis, Backward, Direction, EntrySets, Forward, GenKill, JoinSemiLattice, MaybeReachable, + Analysis, Backward, Direction, EntryStates, Forward, GenKill, JoinSemiLattice, MaybeReachable, Results, ResultsCursor, ResultsVisitor, SwitchIntEdgeEffects, fmt, graphviz, lattice, visit_results, }; diff --git a/compiler/rustc_mir_dataflow/src/points.rs b/compiler/rustc_mir_dataflow/src/points.rs index 10f1e009855..74209da876a 100644 --- a/compiler/rustc_mir_dataflow/src/points.rs +++ b/compiler/rustc_mir_dataflow/src/points.rs @@ -125,7 +125,7 @@ where A: Analysis<'tcx, Domain = BitSet<N>>, N: Idx, { - fn visit_statement_after_primary_effect( + fn visit_after_primary_statement_effect( &mut self, _results: &mut Results<'tcx, A>, state: &A::Domain, @@ -139,7 +139,7 @@ where }); } - fn visit_terminator_after_primary_effect( + fn visit_after_primary_terminator_effect( &mut self, _results: &mut Results<'tcx, A>, state: &A::Domain, diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index 34ef8afdde3..85cf8ca2104 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -1,6 +1,5 @@ use rustc_ast::MetaItem; use rustc_hir::def_id::DefId; -use rustc_index::bit_set::BitSet; use rustc_middle::mir::{self, Body, Local, Location}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; @@ -254,7 +253,7 @@ impl<'tcx> RustcPeekAt<'tcx> for MaybeLiveLocals { &self, tcx: TyCtxt<'tcx>, place: mir::Place<'tcx>, - state: &BitSet<Local>, + state: &Self::Domain, call: PeekCall, ) { info!(?place, "peek_at"); diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index ed8678de1eb..9328870c7ae 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -67,7 +67,7 @@ impl<V: Clone> Clone for StateData<V> { } } -impl<V: JoinSemiLattice + Clone + HasBottom> JoinSemiLattice for StateData<V> { +impl<V: JoinSemiLattice + Clone> JoinSemiLattice for StateData<V> { fn join(&mut self, other: &Self) -> bool { let mut changed = false; #[allow(rustc::potential_query_instability)] @@ -342,7 +342,7 @@ impl<V: Clone + HasBottom> State<V> { } } -impl<V: JoinSemiLattice + Clone + HasBottom> JoinSemiLattice for State<V> { +impl<V: JoinSemiLattice + Clone> JoinSemiLattice for State<V> { fn join(&mut self, other: &Self) -> bool { match (&mut *self, other) { (_, State::Unreachable) => false, diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 858752a3f01..31d5245fb5c 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -878,7 +878,7 @@ struct StorageConflictVisitor<'a, 'tcx> { impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, MaybeRequiresStorage<'a, 'tcx>> for StorageConflictVisitor<'a, 'tcx> { - fn visit_statement_before_primary_effect( + fn visit_after_early_statement_effect( &mut self, _results: &mut Results<'tcx, MaybeRequiresStorage<'a, 'tcx>>, state: &BitSet<Local>, @@ -888,7 +888,7 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, MaybeRequiresStorage<'a, 'tcx>> self.apply_state(state, loc); } - fn visit_terminator_before_primary_effect( + fn visit_after_early_terminator_effect( &mut self, _results: &mut Results<'tcx, MaybeRequiresStorage<'a, 'tcx>>, state: &BitSet<Local>, diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index b94c925b1db..711cf2edc46 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -106,7 +106,7 @@ impl<'tcx> Analysis<'tcx> for ConstAnalysis<'_, 'tcx> { } } - fn apply_statement_effect( + fn apply_primary_statement_effect( &mut self, state: &mut Self::Domain, statement: &Statement<'tcx>, @@ -117,7 +117,7 @@ impl<'tcx> Analysis<'tcx> for ConstAnalysis<'_, 'tcx> { } } - fn apply_terminator_effect<'mir>( + fn apply_primary_terminator_effect<'mir>( &mut self, state: &mut Self::Domain, terminator: &'mir Terminator<'tcx>, @@ -224,7 +224,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { } /// The effect of a successful function call return should not be - /// applied here, see [`Analysis::apply_terminator_effect`]. + /// applied here, see [`Analysis::apply_primary_terminator_effect`]. fn handle_terminator<'mir>( &self, terminator: &'mir Terminator<'tcx>, @@ -954,7 +954,7 @@ fn try_write_constant<'tcx>( impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, ConstAnalysis<'_, 'tcx>> for Collector<'_, 'tcx> { #[instrument(level = "trace", skip(self, results, statement))] - fn visit_statement_before_primary_effect( + fn visit_after_early_statement_effect( &mut self, results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>, state: &State<FlatSet<Scalar>>, @@ -976,7 +976,7 @@ impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, ConstAnalysis<'_, 'tcx>> for Collect } #[instrument(level = "trace", skip(self, results, statement))] - fn visit_statement_after_primary_effect( + fn visit_after_primary_statement_effect( &mut self, results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>, state: &State<FlatSet<Scalar>>, @@ -1001,7 +1001,7 @@ impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, ConstAnalysis<'_, 'tcx>> for Collect } } - fn visit_terminator_before_primary_effect( + fn visit_after_early_terminator_effect( &mut self, results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>, state: &State<FlatSet<Scalar>>, diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 0c0f3b61977..3ebc9113725 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -127,7 +127,7 @@ impl InitializationData<'_, '_> { self.uninits.seek_before_primary_effect(loc); } - fn maybe_live_dead(&self, path: MovePathIndex) -> (bool, bool) { + fn maybe_init_uninit(&self, path: MovePathIndex) -> (bool, bool) { (self.inits.get().contains(path), self.uninits.get().contains(path)) } } @@ -153,23 +153,23 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for ElaborateDropsCtxt<'a, 'tcx> { #[instrument(level = "debug", skip(self), ret)] fn drop_style(&self, path: Self::Path, mode: DropFlagMode) -> DropStyle { - let ((maybe_live, maybe_dead), multipart) = match mode { - DropFlagMode::Shallow => (self.init_data.maybe_live_dead(path), false), + let ((maybe_init, maybe_uninit), multipart) = match mode { + DropFlagMode::Shallow => (self.init_data.maybe_init_uninit(path), false), DropFlagMode::Deep => { - let mut some_live = false; - let mut some_dead = false; + let mut some_maybe_init = false; + let mut some_maybe_uninit = false; let mut children_count = 0; on_all_children_bits(self.move_data(), path, |child| { - let (live, dead) = self.init_data.maybe_live_dead(child); - debug!("elaborate_drop: state({:?}) = {:?}", child, (live, dead)); - some_live |= live; - some_dead |= dead; + let (maybe_init, maybe_uninit) = self.init_data.maybe_init_uninit(child); + debug!("elaborate_drop: state({:?}) = {:?}", child, (maybe_init, maybe_uninit)); + some_maybe_init |= maybe_init; + some_maybe_uninit |= maybe_uninit; children_count += 1; }); - ((some_live, some_dead), children_count != 1) + ((some_maybe_init, some_maybe_uninit), children_count != 1) } }; - match (maybe_live, maybe_dead, multipart) { + match (maybe_init, maybe_uninit, multipart) { (false, _, _) => DropStyle::Dead, (true, false, _) => DropStyle::Static, (true, true, false) => DropStyle::Conditional, @@ -283,15 +283,15 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { LookupResult::Exact(path) => { self.init_data.seek_before(self.body.terminator_loc(bb)); on_all_children_bits(self.move_data(), path, |child| { - let (maybe_live, maybe_dead) = self.init_data.maybe_live_dead(child); + let (maybe_init, maybe_uninit) = self.init_data.maybe_init_uninit(child); debug!( "collect_drop_flags: collecting {:?} from {:?}@{:?} - {:?}", child, place, path, - (maybe_live, maybe_dead) + (maybe_init, maybe_uninit) ); - if maybe_live && maybe_dead { + if maybe_init && maybe_uninit { self.create_drop_flag(child, terminator.source_info.span) } }); @@ -303,8 +303,8 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { } self.init_data.seek_before(self.body.terminator_loc(bb)); - let (_maybe_live, maybe_dead) = self.init_data.maybe_live_dead(parent); - if maybe_dead { + let (_maybe_init, maybe_uninit) = self.init_data.maybe_init_uninit(parent); + if maybe_uninit { self.tcx.dcx().span_delayed_bug( terminator.source_info.span, format!( diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index a6ba2f32d32..adc3374df2e 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -47,7 +47,6 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { } ctx.simplify_bool_cmp(rvalue); ctx.simplify_ref_deref(rvalue); - ctx.simplify_len(rvalue); ctx.simplify_ptr_aggregate(rvalue); ctx.simplify_cast(rvalue); } @@ -132,18 +131,6 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { } } - /// Transform `Len([_; N])` ==> `N`. - fn simplify_len(&self, rvalue: &mut Rvalue<'tcx>) { - if let Rvalue::Len(ref place) = *rvalue { - let place_ty = place.ty(self.local_decls, self.tcx).ty; - if let ty::Array(_, len) = *place_ty.kind() { - let const_ = Const::from_ty_const(len, self.tcx.types.usize, self.tcx); - let constant = ConstOperand { span: DUMMY_SP, const_, user_ty: None }; - *rvalue = Rvalue::Use(Operand::Constant(Box::new(constant))); - } - } - } - /// Transform `Aggregate(RawPtr, [p, ()])` ==> `Cast(PtrToPtr, p)`. fn simplify_ptr_aggregate(&self, rvalue: &mut Rvalue<'tcx>) { if let Rvalue::Aggregate(box AggregateKind::RawPtr(pointee_ty, mutability), fields) = rvalue diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index f0fcb44603b..5c090bf7cad 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -189,6 +189,7 @@ declare_passes! { mod simplify_comparison_integral : SimplifyComparisonIntegral; mod single_use_consts : SingleUseConsts; mod sroa : ScalarReplacementOfAggregates; + mod strip_debuginfo : StripDebugInfo; mod unreachable_enum_branching : UnreachableEnumBranching; mod unreachable_prop : UnreachablePropagation; mod validate : Validator; @@ -699,6 +700,8 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &o1(simplify_branches::SimplifyConstCondition::Final), &o1(remove_noop_landing_pads::RemoveNoopLandingPads), &o1(simplify::SimplifyCfg::Final), + // After the last SimplifyCfg, because this wants one-block functions. + &strip_debuginfo::StripDebugInfo, ©_prop::CopyProp, &dead_store_elimination::DeadStoreElimination::Final, &nrvo::RenameReturnPlace, diff --git a/compiler/rustc_mir_transform/src/strip_debuginfo.rs b/compiler/rustc_mir_transform/src/strip_debuginfo.rs new file mode 100644 index 00000000000..438c75726bb --- /dev/null +++ b/compiler/rustc_mir_transform/src/strip_debuginfo.rs @@ -0,0 +1,34 @@ +use rustc_middle::mir::*; +use rustc_middle::ty::TyCtxt; +use rustc_session::config::MirStripDebugInfo; + +/// Conditionally remove some of the VarDebugInfo in MIR. +/// +/// In particular, stripping non-parameter debug info for tiny, primitive-like +/// methods in core saves work later, and nobody ever wanted to use it anyway. +pub(super) struct StripDebugInfo; + +impl<'tcx> crate::MirPass<'tcx> for StripDebugInfo { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.opts.unstable_opts.mir_strip_debuginfo != MirStripDebugInfo::None + } + + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + match tcx.sess.opts.unstable_opts.mir_strip_debuginfo { + MirStripDebugInfo::None => return, + MirStripDebugInfo::AllLocals => {} + MirStripDebugInfo::LocalsInTinyFunctions + if let TerminatorKind::Return { .. } = + body.basic_blocks[START_BLOCK].terminator().kind => {} + MirStripDebugInfo::LocalsInTinyFunctions => return, + } + + body.var_debug_info.retain(|vdi| { + matches!( + vdi.value, + VarDebugInfoContents::Place(place) + if place.local.as_usize() <= body.arg_count && place.local != RETURN_PLACE, + ) + }); + } +} diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 404fbb6b839..bce015046e1 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -1115,14 +1115,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ); } UnOp::PtrMetadata => { - if !matches!(self.body.phase, MirPhase::Runtime(_)) { - // It would probably be fine to support this in earlier phases, but at - // the time of writing it's only ever introduced from intrinsic - // lowering or other runtime-phase optimization passes, so earlier - // things can just `bug!` on it. - self.fail(location, "PtrMetadata should be in runtime MIR only"); - } - check_kinds!( a, "Cannot PtrMetadata non-pointer non-reference type {:?}", diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 2426eb81678..443ddfc94ec 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -69,24 +69,30 @@ pub(crate) fn lex_token_trees<'psess, 'src>( token: Token::dummy(), diag_info: TokenTreeDiagInfo::default(), }; - let (_open_spacing, stream, res) = lexer.lex_token_trees(/* is_delimited */ false); - let unmatched_delims = lexer.diag_info.unmatched_delims; - - if res.is_ok() && unmatched_delims.is_empty() { - Ok(stream) - } else { - // Return error if there are unmatched delimiters or unclosed delimiters. - // We emit delimiter mismatch errors first, then emit the unclosing delimiter mismatch - // because the delimiter mismatch is more likely to be the root cause of error - let mut buffer: Vec<_> = unmatched_delims - .into_iter() - .filter_map(|unmatched_delim| make_unclosed_delims_error(unmatched_delim, psess)) - .collect(); - if let Err(errs) = res { - // Add unclosing delimiter or diff marker errors - buffer.extend(errs); + let res = lexer.lex_token_trees(/* is_delimited */ false); + + let mut unmatched_delims: Vec<_> = lexer + .diag_info + .unmatched_delims + .into_iter() + .filter_map(|unmatched_delim| make_unclosed_delims_error(unmatched_delim, psess)) + .collect(); + + match res { + Ok((_open_spacing, stream)) => { + if unmatched_delims.is_empty() { + Ok(stream) + } else { + // Return error if there are unmatched delimiters or unclosed delimiters. + Err(unmatched_delims) + } + } + Err(errs) => { + // We emit delimiter mismatch errors first, then emit the unclosing delimiter mismatch + // because the delimiter mismatch is more likely to be the root cause of error + unmatched_delims.extend(errs); + Err(unmatched_delims) } - Err(buffer) } } diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index ee38f16d4ec..b3f83a32024 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -1,12 +1,10 @@ use rustc_ast::token::{self, Delimiter, Token}; use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; use rustc_ast_pretty::pprust::token_to_string; -use rustc_errors::{Applicability, Diag}; -use rustc_span::symbol::kw; +use rustc_errors::Diag; use super::diagnostics::{report_suspicious_mismatch_block, same_indentation_level}; use super::{Lexer, UnmatchedDelim}; -use crate::Parser; impl<'psess, 'src> Lexer<'psess, 'src> { // Lex into a token stream. The `Spacing` in the result is that of the @@ -14,7 +12,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { pub(super) fn lex_token_trees( &mut self, is_delimited: bool, - ) -> (Spacing, TokenStream, Result<(), Vec<Diag<'psess>>>) { + ) -> Result<(Spacing, TokenStream), Vec<Diag<'psess>>> { // Move past the opening delimiter. let open_spacing = self.bump_minimal(); @@ -27,25 +25,25 @@ impl<'psess, 'src> Lexer<'psess, 'src> { debug_assert!(!matches!(delim, Delimiter::Invisible(_))); buf.push(match self.lex_token_tree_open_delim(delim) { Ok(val) => val, - Err(errs) => return (open_spacing, TokenStream::new(buf), Err(errs)), + Err(errs) => return Err(errs), }) } token::CloseDelim(delim) => { // Invisible delimiters cannot occur here because `TokenTreesReader` parses // code directly from strings, with no macro expansion involved. debug_assert!(!matches!(delim, Delimiter::Invisible(_))); - return ( - open_spacing, - TokenStream::new(buf), - if is_delimited { Ok(()) } else { Err(vec![self.close_delim_err(delim)]) }, - ); + return if is_delimited { + Ok((open_spacing, TokenStream::new(buf))) + } else { + Err(vec![self.close_delim_err(delim)]) + }; } token::Eof => { - return ( - open_spacing, - TokenStream::new(buf), - if is_delimited { Err(vec![self.eof_err()]) } else { Ok(()) }, - ); + return if is_delimited { + Err(vec![self.eof_err()]) + } else { + Ok((open_spacing, TokenStream::new(buf))) + }; } _ => { // Get the next normal token. @@ -107,10 +105,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { // Lex the token trees within the delimiters. // We stop at any delimiter so we can try to recover if the user // uses an incorrect delimiter. - let (open_spacing, tts, res) = self.lex_token_trees(/* is_delimited */ true); - if let Err(errs) = res { - return Err(self.unclosed_delim_err(tts, errs)); - } + let (open_spacing, tts) = self.lex_token_trees(/* is_delimited */ true)?; // Expand to cover the entire delimited token tree. let delim_span = DelimSpan::from_pair(pre_span, self.token.span); @@ -247,67 +242,6 @@ impl<'psess, 'src> Lexer<'psess, 'src> { this_spacing } - fn unclosed_delim_err( - &mut self, - tts: TokenStream, - mut errs: Vec<Diag<'psess>>, - ) -> Vec<Diag<'psess>> { - // If there are unclosed delims, see if there are diff markers and if so, point them - // out instead of complaining about the unclosed delims. - let mut parser = Parser::new(self.psess, tts, None); - let mut diff_errs = vec![]; - // Suggest removing a `{` we think appears in an `if`/`while` condition. - // We want to suggest removing a `{` only if we think we're in an `if`/`while` condition, - // but we have no way of tracking this in the lexer itself, so we piggyback on the parser. - let mut in_cond = false; - while parser.token != token::Eof { - if let Err(diff_err) = parser.err_vcs_conflict_marker() { - diff_errs.push(diff_err); - } else if parser.is_keyword_ahead(0, &[kw::If, kw::While]) { - in_cond = true; - } else if matches!( - parser.token.kind, - token::CloseDelim(Delimiter::Brace) | token::FatArrow - ) { - // End of the `if`/`while` body, or the end of a `match` guard. - in_cond = false; - } else if in_cond && parser.token == token::OpenDelim(Delimiter::Brace) { - // Store the `&&` and `let` to use their spans later when creating the diagnostic - let maybe_andand = parser.look_ahead(1, |t| t.clone()); - let maybe_let = parser.look_ahead(2, |t| t.clone()); - if maybe_andand == token::OpenDelim(Delimiter::Brace) { - // This might be the beginning of the `if`/`while` body (i.e., the end of the - // condition). - in_cond = false; - } else if maybe_andand == token::AndAnd && maybe_let.is_keyword(kw::Let) { - let mut err = parser.dcx().struct_span_err( - parser.token.span, - "found a `{` in the middle of a let-chain", - ); - err.span_suggestion( - parser.token.span, - "consider removing this brace to parse the `let` as part of the same chain", - "", - Applicability::MachineApplicable, - ); - err.span_label( - maybe_andand.span.to(maybe_let.span), - "you might have meant to continue the let-chain here", - ); - errs.push(err); - } - } - parser.bump(); - } - if !diff_errs.is_empty() { - for err in errs { - err.cancel(); - } - return diff_errs; - } - errs - } - fn close_delim_err(&mut self, delim: Delimiter) -> Diag<'psess> { // An unexpected closing delimiter (i.e., there is no matching opening delimiter). let token_str = token_to_string(&self.token); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 44f42e5fbf2..a2136399b0c 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -15,7 +15,7 @@ use rustc_ast::visit::{Visitor, walk_expr}; use rustc_ast::{ self as ast, AnonConst, Arm, AttrStyle, AttrVec, BinOp, BinOpKind, BlockCheckMode, CaptureBy, ClosureBinder, DUMMY_NODE_ID, Expr, ExprField, ExprKind, FnDecl, FnRetTy, Label, MacCall, - MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind, UnOp, + MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind, }; use rustc_ast_pretty::pprust; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -1931,6 +1931,12 @@ impl<'a> Parser<'a> { Ok(match ident.name { sym::offset_of => Some(this.parse_expr_offset_of(lo)?), sym::type_ascribe => Some(this.parse_expr_type_ascribe(lo)?), + sym::wrap_binder => { + Some(this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Wrap)?) + } + sym::unwrap_binder => { + Some(this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Unwrap)?) + } _ => None, }) }) @@ -2006,6 +2012,17 @@ impl<'a> Parser<'a> { Ok(self.mk_expr(span, ExprKind::Type(expr, ty))) } + pub(crate) fn parse_expr_unsafe_binder_cast( + &mut self, + lo: Span, + kind: UnsafeBinderCastKind, + ) -> PResult<'a, P<Expr>> { + let expr = self.parse_expr()?; + let ty = if self.eat(&TokenKind::Comma) { Some(self.parse_ty()?) } else { None }; + let span = lo.to(self.token.span); + Ok(self.mk_expr(span, ExprKind::UnsafeBinderCast(kind, expr, ty))) + } + /// Returns a string literal if the next token is a string literal. /// In case of error returns `Some(lit)` if the next token is a literal with a wrong kind, /// and returns `None` if the next token is not literal at all. @@ -4016,7 +4033,9 @@ impl MutVisitor for CondChecker<'_> { mut_visit::walk_expr(self, e); self.forbid_let_reason = forbid_let_reason; } - ExprKind::Cast(ref mut op, _) | ExprKind::Type(ref mut op, _) => { + ExprKind::Cast(ref mut op, _) + | ExprKind::Type(ref mut op, _) + | ExprKind::UnsafeBinderCast(_, ref mut op, _) => { let forbid_let_reason = self.forbid_let_reason; self.forbid_let_reason = Some(OtherForbidden); self.visit_expr(op); diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 58b4bf8980b..e27fc963eb9 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -45,7 +45,7 @@ impl<'a> Parser<'a> { let (inner_attrs, items, inner_span) = self.parse_mod(&token::CloseDelim(Delimiter::Brace))?; attrs.extend(inner_attrs); - ModKind::Loaded(items, Inline::Yes, inner_span) + ModKind::Loaded(items, Inline::Yes, inner_span, Ok(())) }; Ok((id, ItemKind::Mod(safety, mod_kind))) } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 8cff23c2e32..f696074e66a 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -5,7 +5,7 @@ use rustc_ast::{ self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty, - TyKind, + TyKind, UnsafeBinderTy, }; use rustc_errors::{Applicability, PResult}; use rustc_span::symbol::{Ident, kw, sym}; @@ -348,6 +348,10 @@ impl<'a> Parser<'a> { TyKind::Err(guar) } } + } else if self.check_keyword(kw::Unsafe) + && self.look_ahead(1, |tok| matches!(tok.kind, token::Lt)) + { + self.parse_unsafe_binder_ty()? } else { let msg = format!("expected type, found {}", super::token_descr(&self.token)); let mut err = self.dcx().struct_span_err(lo, msg); @@ -369,6 +373,19 @@ impl<'a> Parser<'a> { if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) } } + fn parse_unsafe_binder_ty(&mut self) -> PResult<'a, TyKind> { + let lo = self.token.span; + assert!(self.eat_keyword(kw::Unsafe)); + self.expect_lt()?; + let generic_params = self.parse_generic_params()?; + self.expect_gt()?; + let inner_ty = self.parse_ty()?; + let span = lo.to(self.prev_token.span); + self.psess.gated_spans.gate(sym::unsafe_binders, span); + + Ok(TyKind::UnsafeBinder(P(UnsafeBinderTy { generic_params, inner_ty }))) + } + /// Parses either: /// - `(TYPE)`, a parenthesized type. /// - `(TYPE,)`, a tuple with a single field of type TYPE. diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index 76edb51c0bc..7ccbc7bdc57 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -315,9 +315,40 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { fn visit_expr(&mut self, e: &'v hir::Expr<'v>) { record_variants!((self, e, e.kind, Some(e.hir_id), hir, Expr, ExprKind), [ - ConstBlock, Array, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, DropTemps, - Let, If, Loop, Match, Closure, Block, Assign, AssignOp, Field, Index, Path, AddrOf, - Break, Continue, Ret, Become, InlineAsm, OffsetOf, Struct, Repeat, Yield, Err + ConstBlock, + Array, + Call, + MethodCall, + Tup, + Binary, + Unary, + Lit, + Cast, + Type, + DropTemps, + Let, + If, + Loop, + Match, + Closure, + Block, + Assign, + AssignOp, + Field, + Index, + Path, + AddrOf, + Break, + Continue, + Ret, + Become, + InlineAsm, + OffsetOf, + Struct, + Repeat, + Yield, + UnsafeBinderCast, + Err ]); hir_visit::walk_expr(self, e) } @@ -335,10 +366,12 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { Ptr, Ref, BareFn, + UnsafeBinder, Never, Tup, Path, OpaqueDef, + TraitAscription, TraitObject, Typeof, Infer, @@ -571,7 +604,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { If, While, ForLoop, Loop, Match, Closure, Block, Await, TryBlock, Assign, AssignOp, Field, Index, Range, Underscore, Path, AddrOf, Break, Continue, Ret, InlineAsm, FormatArgs, OffsetOf, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet, - Become, IncludedBytes, Gen, Err, Dummy + Become, IncludedBytes, Gen, UnsafeBinderCast, Err, Dummy ] ); ast_visit::walk_expr(self, e) @@ -585,6 +618,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { Ref, PinnedRef, BareFn, + UnsafeBinder, Never, Tup, Path, diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 09cbb648f9b..034f7308c4a 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -447,6 +447,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> { | hir::ExprKind::InlineAsm(..) | hir::ExprKind::OffsetOf(..) | hir::ExprKind::Type(..) + | hir::ExprKind::UnsafeBinderCast(..) | hir::ExprKind::Err(_) | hir::ExprKind::Path(hir::QPath::TypeRelative(..)) | hir::ExprKind::Path(hir::QPath::LangItem(..)) => {} @@ -1051,6 +1052,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprKind::AddrOf(_, _, ref e) | hir::ExprKind::Cast(ref e, _) | hir::ExprKind::Type(ref e, _) + | hir::ExprKind::UnsafeBinderCast(_, ref e, _) | hir::ExprKind::DropTemps(ref e) | hir::ExprKind::Unary(_, ref e) | hir::ExprKind::Repeat(ref e, _) => self.propagate_through_expr(e, succ), @@ -1443,6 +1445,7 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) { | hir::ExprKind::Path(_) | hir::ExprKind::Yield(..) | hir::ExprKind::Type(..) + | hir::ExprKind::UnsafeBinderCast(..) | hir::ExprKind::Err(_) => {} } } diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs index b2f8d7dadff..766a9e1bdad 100644 --- a/compiler/rustc_passes/src/naked_functions.rs +++ b/compiler/rustc_passes/src/naked_functions.rs @@ -186,6 +186,7 @@ impl CheckInlineAssembly { | ExprKind::Lit(..) | ExprKind::Cast(..) | ExprKind::Type(..) + | ExprKind::UnsafeBinderCast(..) | ExprKind::Loop(..) | ExprKind::Match(..) | ExprKind::If(..) diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index f72f656b2f8..1b12af62ea5 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -349,9 +349,9 @@ pub(crate) fn create_query_frame< hasher.finish::<Hash64>() }) }; - let ty_def_id = key.ty_def_id(); + let def_id_for_ty_in_cycle = key.def_id_for_ty_in_cycle(); - QueryStackFrame::new(description, span, def_id, def_kind, kind, ty_def_id, hash) + QueryStackFrame::new(description, span, def_id, def_kind, kind, def_id_for_ty_in_cycle, hash) } pub(crate) fn encode_query_results<'a, 'tcx, Q>( diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index b81386f06ec..82c51193a19 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -33,7 +33,7 @@ pub struct QueryStackFrame { pub def_id: Option<DefId>, pub def_kind: Option<DefKind>, /// A def-id that is extracted from a `Ty` in a query key - pub ty_def_id: Option<DefId>, + pub def_id_for_ty_in_cycle: Option<DefId>, pub dep_kind: DepKind, /// This hash is used to deterministically pick /// a query to remove cycles in the parallel compiler. @@ -48,10 +48,10 @@ impl QueryStackFrame { def_id: Option<DefId>, def_kind: Option<DefKind>, dep_kind: DepKind, - ty_def_id: Option<DefId>, + def_id_for_ty_in_cycle: Option<DefId>, hash: impl FnOnce() -> Hash64, ) -> Self { - Self { description, span, def_id, def_kind, ty_def_id, dep_kind, hash: hash() } + Self { description, span, def_id, def_kind, def_id_for_ty_in_cycle, dep_kind, hash: hash() } } // FIXME(eddyb) Get more valid `Span`s on queries. diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 293cee500bb..924b8afa329 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -770,7 +770,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { ); } - ItemKind::Mod(..) => { + ItemKind::Mod(.., ref mod_kind) => { let module = self.r.new_module( Some(parent), ModuleKind::Def(def_kind, def_id, ident.name), @@ -781,6 +781,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { ); self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion)); + if let ast::ModKind::Loaded(_, _, _, Err(_)) = mod_kind { + self.r.mods_with_parse_errors.insert(def_id); + } + // Descend into the module. self.parent_scope.module = module; } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 4c76617a391..368eb3c26c7 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -3056,7 +3056,7 @@ impl<'tcx> visit::Visitor<'tcx> for UsePlacementFinder { fn visit_item(&mut self, item: &'tcx ast::Item) { if self.target_module == item.id { - if let ItemKind::Mod(_, ModKind::Loaded(items, _inline, mod_spans)) = &item.kind { + if let ItemKind::Mod(_, ModKind::Loaded(items, _inline, mod_spans, _)) = &item.kind { let inject = mod_spans.inject_use_span; if is_span_suitable_for_use_injection(inject) { self.first_legal_span = Some(inject); diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 466e190028a..5906a682f3e 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -1428,6 +1428,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ignore_import: Option<Import<'ra>>, ) -> PathResult<'ra> { let mut module = None; + let mut module_had_parse_errors = false; let mut allow_super = true; let mut second_binding = None; @@ -1471,9 +1472,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { continue; } } - return PathResult::failed(ident, false, finalize.is_some(), module, || { - ("there are too many leading `super` keywords".to_string(), None) - }); + return PathResult::failed( + ident, + false, + finalize.is_some(), + module_had_parse_errors, + module, + || ("there are too many leading `super` keywords".to_string(), None), + ); } if segment_idx == 0 { if name == kw::SelfLower { @@ -1511,19 +1517,26 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Report special messages for path segment keywords in wrong positions. if ident.is_path_segment_keyword() && segment_idx != 0 { - return PathResult::failed(ident, false, finalize.is_some(), module, || { - let name_str = if name == kw::PathRoot { - "crate root".to_string() - } else { - format!("`{name}`") - }; - let label = if segment_idx == 1 && path[0].ident.name == kw::PathRoot { - format!("global paths cannot start with {name_str}") - } else { - format!("{name_str} in paths can only be used in start position") - }; - (label, None) - }); + return PathResult::failed( + ident, + false, + finalize.is_some(), + module_had_parse_errors, + module, + || { + let name_str = if name == kw::PathRoot { + "crate root".to_string() + } else { + format!("`{name}`") + }; + let label = if segment_idx == 1 && path[0].ident.name == kw::PathRoot { + format!("global paths cannot start with {name_str}") + } else { + format!("{name_str} in paths can only be used in start position") + }; + (label, None) + }, + ); } let binding = if let Some(module) = module { @@ -1589,6 +1602,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(res); if let Some(next_module) = binding.module() { + if self.mods_with_parse_errors.contains(&next_module.def_id()) { + module_had_parse_errors = true; + } module = Some(ModuleOrUniformRoot::Module(next_module)); record_segment_res(self, res); } else if res == Res::ToolMod && !is_last && opt_ns.is_some() { @@ -1614,6 +1630,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ident, is_last, finalize.is_some(), + module_had_parse_errors, module, || { let label = format!( @@ -1637,19 +1654,26 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - return PathResult::failed(ident, is_last, finalize.is_some(), module, || { - self.report_path_resolution_error( - path, - opt_ns, - parent_scope, - ribs, - ignore_binding, - ignore_import, - module, - segment_idx, - ident, - ) - }); + return PathResult::failed( + ident, + is_last, + finalize.is_some(), + module_had_parse_errors, + module, + || { + self.report_path_resolution_error( + path, + opt_ns, + parent_scope, + ribs, + ignore_binding, + ignore_import, + module, + segment_idx, + ident, + ) + }, + ); } } } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 51fbcb8ebb8..2ed3f4d2c4f 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -670,9 +670,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn throw_unresolved_import_error( &mut self, - errors: Vec<(Import<'_>, UnresolvedImportError)>, + mut errors: Vec<(Import<'_>, UnresolvedImportError)>, glob_error: bool, ) { + errors.retain(|(_import, err)| match err.module { + // Skip `use` errors for `use foo::Bar;` if `foo.rs` has unrecovered parse errors. + Some(def_id) if self.mods_with_parse_errors.contains(&def_id) => false, + _ => true, + }); if errors.is_empty() { return; } @@ -898,6 +903,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { label, suggestion, module, + error_implied_by_parse_error: _, } => { if no_ambiguity { assert!(import.imported_module.get().is_none()); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 789d74876f7..bde11428d40 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -887,6 +887,28 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r }, ) } + TyKind::UnsafeBinder(unsafe_binder) => { + // FIXME(unsafe_binder): Better span + let span = ty.span; + self.with_generic_param_rib( + &unsafe_binder.generic_params, + RibKind::Normal, + LifetimeRibKind::Generics { + binder: ty.id, + kind: LifetimeBinderKind::BareFnType, + span, + }, + |this| { + this.visit_generic_params(&unsafe_binder.generic_params, false); + this.with_lifetime_rib( + // We don't allow anonymous `unsafe &'_ ()` binders, + // although I guess we could. + LifetimeRibKind::AnonymousReportError, + |this| this.visit_ty(&unsafe_binder.inner_ty), + ); + }, + ) + } TyKind::Array(element_ty, length) => { self.visit_ty(element_ty); self.resolve_anon_const(length, AnonConstKind::ConstArg(IsRepeatExpr::No)); @@ -4395,6 +4417,12 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { PathResult::Module(ModuleOrUniformRoot::Module(module)) if !module.is_normal() => { PartialRes::new(module.res().unwrap()) } + // A part of this path references a `mod` that had a parse error. To avoid resolution + // errors for each reference to that module, we don't emit an error for them until the + // `mod` is fixed. this can have a significant cascade effect. + PathResult::Failed { error_implied_by_parse_error: true, .. } => { + PartialRes::new(Res::Err) + } // In `a(::assoc_item)*` `a` cannot be a module. If `a` does resolve to a module we // don't report an error right away, but try to fallback to a primitive type. // So, we are still able to successfully resolve something like @@ -4443,6 +4471,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { suggestion, module, segment_name, + error_implied_by_parse_error: _, } => { return Err(respan(span, ResolutionError::FailedToResolve { segment: Some(segment_name), diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index ca4adce37ce..94adfcd3b91 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -450,6 +450,7 @@ enum PathResult<'ra> { module: Option<ModuleOrUniformRoot<'ra>>, /// The segment name of target segment_name: Symbol, + error_implied_by_parse_error: bool, }, } @@ -458,6 +459,7 @@ impl<'ra> PathResult<'ra> { ident: Ident, is_error_from_last_segment: bool, finalize: bool, + error_implied_by_parse_error: bool, module: Option<ModuleOrUniformRoot<'ra>>, label_and_suggestion: impl FnOnce() -> (String, Option<Suggestion>), ) -> PathResult<'ra> { @@ -470,6 +472,7 @@ impl<'ra> PathResult<'ra> { suggestion, is_error_from_last_segment, module, + error_implied_by_parse_error, } } } @@ -1198,6 +1201,8 @@ pub struct Resolver<'ra, 'tcx> { /// This is the `Span` where an `extern crate foo;` suggestion would be inserted, if `foo` /// could be a crate that wasn't imported. For diagnostics use only. current_crate_outer_attr_insert_span: Span, + + mods_with_parse_errors: FxHashSet<DefId>, } /// This provides memory for the rest of the crate. The `'ra` lifetime that is @@ -1543,6 +1548,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { impl_unexpanded_invocations: Default::default(), impl_binding_keys: Default::default(), current_crate_outer_attr_insert_span, + mods_with_parse_errors: Default::default(), }; let root_parent_scope = ParentScope::module(graph_root, &resolver); diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 0b4d0e04c29..669a9c2428f 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -166,7 +166,7 @@ fn soft_custom_inner_attributes_gate(path: &ast::Path, invoc: &Invocation) -> bo [seg1, seg2] if seg1.ident.name == sym::rustfmt && seg2.ident.name == sym::skip => { if let InvocationKind::Attr { item, .. } = &invoc.kind { if let Annotatable::Item(item) = item { - if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, _)) = item.kind { + if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, _, _)) = item.kind { return true; } } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index cb6d539cdf9..936c2ca87d6 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -472,6 +472,13 @@ impl ToString for DebugInfoCompression { } } +#[derive(Clone, Copy, Debug, PartialEq, Hash)] +pub enum MirStripDebugInfo { + None, + LocalsInTinyFunctions, + AllLocals, +} + /// Split debug-information is enabled by `-C split-debuginfo`, this enum is only used if split /// debug-information is enabled (in either `Packed` or `Unpacked` modes), and the platform /// uses DWARF for debug-information. @@ -2900,10 +2907,10 @@ pub(crate) mod dep_tracking { BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CoverageOptions, CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug, FunctionReturn, InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail, - LtoCli, NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, - PatchableFunctionEntry, Polonius, RemapPathScopeComponents, ResolveDocLinks, - SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, - WasiExecModel, + LtoCli, MirStripDebugInfo, NextSolverConfig, OomStrategy, OptLevel, OutFileName, + OutputType, OutputTypes, PatchableFunctionEntry, Polonius, RemapPathScopeComponents, + ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, + SymbolManglingVersion, WasiExecModel, }; use crate::lint; use crate::utils::NativeLib; @@ -2971,6 +2978,7 @@ pub(crate) mod dep_tracking { LtoCli, DebugInfo, DebugInfoCompression, + MirStripDebugInfo, CollapseMacroDebuginfo, UnstableFeatures, NativeLib, diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs index 99d9d5b7665..43cf1324edd 100644 --- a/compiler/rustc_session/src/config/cfg.rs +++ b/compiler/rustc_session/src/config/cfg.rs @@ -371,7 +371,7 @@ impl CheckCfg { ins!(sym::target_feature, empty_values).extend( rustc_target::target_features::all_rust_features() - .filter(|(_, s)| s.is_supported()) + .filter(|(_, s)| s.in_cfg()) .map(|(f, _s)| f) .chain(rustc_target::target_features::RUSTC_SPECIFIC_FEATURES.iter().cloned()) .map(Symbol::intern), diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index b01d9e5e8e3..3873a203bd3 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -391,6 +391,8 @@ mod desc { pub(crate) const parse_cfprotection: &str = "`none`|`no`|`n` (default), `branch`, `return`, or `full`|`yes`|`y` (equivalent to `branch` and `return`)"; pub(crate) const parse_debuginfo: &str = "either an integer (0, 1, 2), `none`, `line-directives-only`, `line-tables-only`, `limited`, or `full`"; pub(crate) const parse_debuginfo_compression: &str = "one of `none`, `zlib`, or `zstd`"; + pub(crate) const parse_mir_strip_debuginfo: &str = + "one of `none`, `locals-in-tiny-functions`, or `all-locals`"; pub(crate) const parse_collapse_macro_debuginfo: &str = "one of `no`, `external`, or `yes`"; pub(crate) const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`"; pub(crate) const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of(); @@ -925,6 +927,16 @@ pub mod parse { true } + pub(crate) fn parse_mir_strip_debuginfo(slot: &mut MirStripDebugInfo, v: Option<&str>) -> bool { + match v { + Some("none") => *slot = MirStripDebugInfo::None, + Some("locals-in-tiny-functions") => *slot = MirStripDebugInfo::LocalsInTinyFunctions, + Some("all-locals") => *slot = MirStripDebugInfo::AllLocals, + _ => return false, + }; + true + } + pub(crate) fn parse_linker_flavor(slot: &mut Option<LinkerFlavorCli>, v: Option<&str>) -> bool { match v.and_then(LinkerFlavorCli::from_str) { Some(lf) => *slot = Some(lf), @@ -1893,6 +1905,8 @@ options! { #[rustc_lint_opt_deny_field_access("use `Session::mir_opt_level` instead of this field")] mir_opt_level: Option<usize> = (None, parse_opt_number, [TRACKED], "MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"), + mir_strip_debuginfo: MirStripDebugInfo = (MirStripDebugInfo::None, parse_mir_strip_debuginfo, [TRACKED], + "Whether to remove some of the MIR debug info from methods. Default: None"), move_size_limit: Option<usize> = (None, parse_opt_number, [TRACKED], "the size at which the `large_assignments` lint starts to be emitted"), mutable_noalias: bool = (true, parse_bool, [TRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 993d111466b..9f6106f9cfb 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -8,7 +8,6 @@ use std::{env, fmt, io}; use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; -use rustc_data_structures::jobserver::{self, Client}; use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef}; use rustc_data_structures::sync::{ DynSend, DynSync, Lock, Lrc, MappedReadGuard, ReadGuard, RwLock, @@ -154,16 +153,9 @@ pub struct Session { /// Data about code being compiled, gathered during compilation. pub code_stats: CodeStats, - /// Loaded up early on in the initialization of this `Session` to avoid - /// false positives about a job server in our environment. - pub jobserver: Client, - /// This only ever stores a `LintStore` but we don't want a dependency on that type here. pub lint_store: Option<Lrc<dyn LintStoreMarker>>, - /// Should be set if any lints are registered in `lint_store`. - pub registered_lints: bool, - /// Cap lint level specified by a driver specifically. pub driver_lint_caps: FxHashMap<lint::LintId, lint::Level>, @@ -1072,9 +1064,7 @@ pub fn build_session( incr_comp_session: RwLock::new(IncrCompSession::NotInitialized), prof, code_stats: Default::default(), - jobserver: jobserver::client(), lint_store: None, - registered_lints: false, driver_lint_caps, ctfe_backtrace, miri_unleashed_features: Lock::new(Default::default()), diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index dec2a77619b..c465367b6b9 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -141,6 +141,10 @@ impl RustcInternal for RigidTy { RigidTy::Coroutine(def, args, _mov) => { rustc_ty::TyKind::Coroutine(def.0.internal(tables, tcx), args.internal(tables, tcx)) } + RigidTy::CoroutineClosure(def, args) => rustc_ty::TyKind::CoroutineClosure( + def.0.internal(tables, tcx), + args.internal(tables, tcx), + ), RigidTy::CoroutineWitness(def, args) => rustc_ty::TyKind::CoroutineWitness( def.0.internal(tables, tcx), args.internal(tables, tcx), diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 614c9169d66..64d241067a8 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -107,6 +107,10 @@ impl<'tcx> Tables<'tcx> { stable_mir::ty::CoroutineDef(self.create_def_id(did)) } + pub fn coroutine_closure_def(&mut self, did: DefId) -> stable_mir::ty::CoroutineClosureDef { + stable_mir::ty::CoroutineClosureDef(self.create_def_id(did)) + } + pub fn alias_def(&mut self, did: DefId) -> stable_mir::ty::AliasDef { stable_mir::ty::AliasDef(self.create_def_id(did)) } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index fcdf8703b14..a5a17b4b573 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -565,8 +565,11 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> { tables.tcx.coroutine_movability(*def_id).stable(tables), ) } - mir::AggregateKind::CoroutineClosure(..) => { - todo!("FIXME(async_closures): Lower these to SMIR") + mir::AggregateKind::CoroutineClosure(def_id, generic_args) => { + stable_mir::mir::AggregateKind::CoroutineClosure( + tables.coroutine_closure_def(*def_id), + generic_args.stable(tables), + ) } mir::AggregateKind::RawPtr(ty, mutability) => { stable_mir::mir::AggregateKind::RawPtr(ty.stable(tables), mutability.stable(tables)) diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index a5826137181..3cdae437b7d 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -1163,6 +1163,9 @@ pub enum DesugaringKind { WhileLoop, /// `async Fn()` bound modifier BoundModifier, + /// Marks a `&raw const *_1` needed as part of getting the length of a mutable + /// slice for the bounds check, so that MIRI's retag handling can recognize it. + IndexBoundsCheckReborrow, } impl DesugaringKind { @@ -1179,6 +1182,7 @@ impl DesugaringKind { DesugaringKind::ForLoop => "`for` loop", DesugaringKind::WhileLoop => "`while` loop", DesugaringKind::BoundModifier => "trait bound modifier", + DesugaringKind::IndexBoundsCheckReborrow => "slice indexing", } } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 9b499c71603..e3708896ba9 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2105,6 +2105,7 @@ symbols! { unreachable_macro, unrestricted_attribute_tokens, unsafe_attributes, + unsafe_binders, unsafe_block_in_unsafe_fn, unsafe_cell, unsafe_cell_raw_get, @@ -2128,6 +2129,7 @@ symbols! { unwind_attributes, unwind_safe_trait, unwrap, + unwrap_binder, unwrap_or, use_extern_macros, use_nested_groups, @@ -2186,6 +2188,7 @@ symbols! { windows, windows_subsystem, with_negative_coherence, + wrap_binder, wrapping_add, wrapping_div, wrapping_mul, @@ -2201,6 +2204,7 @@ symbols! { writeln_macro, x86_amx_intrinsics, x87_reg, + x87_target_feature, xer, xmm_reg, xop_target_feature, diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 59ccd6dff85..0d6d8488a23 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -2,7 +2,7 @@ use std::fmt::{self, Write}; use std::mem::{self, discriminant}; use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher}; -use rustc_hir::def_id::CrateNum; +use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; use rustc_middle::bug; use rustc_middle::ty::print::{PrettyPrinter, Print, PrintError, Printer}; @@ -378,6 +378,33 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> { Ok(()) } } + + fn print_impl_path( + &mut self, + impl_def_id: DefId, + args: &'tcx [GenericArg<'tcx>], + mut self_ty: Ty<'tcx>, + mut impl_trait_ref: Option<ty::TraitRef<'tcx>>, + ) -> Result<(), PrintError> { + let mut typing_env = ty::TypingEnv::post_analysis(self.tcx, impl_def_id); + if !args.is_empty() { + typing_env.param_env = + ty::EarlyBinder::bind(typing_env.param_env).instantiate(self.tcx, args); + } + + match &mut impl_trait_ref { + Some(impl_trait_ref) => { + assert_eq!(impl_trait_ref.self_ty(), self_ty); + *impl_trait_ref = self.tcx.normalize_erasing_regions(typing_env, *impl_trait_ref); + self_ty = impl_trait_ref.self_ty(); + } + None => { + self_ty = self.tcx.normalize_erasing_regions(typing_env, self_ty); + } + } + + self.default_print_impl_path(impl_def_id, args, self_ty, impl_trait_ref) + } } impl<'tcx> PrettyPrinter<'tcx> for SymbolPrinter<'tcx> { diff --git a/compiler/rustc_target/src/callconv/powerpc64.rs b/compiler/rustc_target/src/callconv/powerpc64.rs index 71e533b8cc5..3a71592cbe0 100644 --- a/compiler/rustc_target/src/callconv/powerpc64.rs +++ b/compiler/rustc_target/src/callconv/powerpc64.rs @@ -99,7 +99,7 @@ where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, { - let abi = if cx.target_spec().env == "musl" { + let abi = if cx.target_spec().env == "musl" || cx.target_spec().os == "freebsd" { ELFv2 } else if cx.target_spec().os == "aix" { AIX diff --git a/compiler/rustc_target/src/spec/base/linux_musl.rs b/compiler/rustc_target/src/spec/base/linux_musl.rs index e020bb85238..1a854fe362d 100644 --- a/compiler/rustc_target/src/spec/base/linux_musl.rs +++ b/compiler/rustc_target/src/spec/base/linux_musl.rs @@ -8,8 +8,5 @@ pub(crate) fn opts() -> TargetOptions { base.post_link_objects_self_contained = crt_objects::post_musl_self_contained(); base.link_self_contained = LinkSelfContainedDefault::InferredForMusl; - // These targets statically link libc by default - base.crt_static_default = true; - base } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 210d67fa1aa..7d308c6c662 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2603,6 +2603,18 @@ impl TargetOptions { .collect(); } } + + pub(crate) fn has_feature(&self, search_feature: &str) -> bool { + self.features.split(',').any(|f| { + if let Some(f) = f.strip_prefix('+') + && f == search_feature + { + true + } else { + false + } + }) + } } impl Default for TargetOptions { diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs index bb65048a56d..4fefdfa5c5e 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs @@ -12,6 +12,9 @@ pub(crate) fn target() -> Target { | SanitizerSet::MEMORY | SanitizerSet::THREAD; + // FIXME(compiler-team#422): musl targets should be dynamically linked by default. + base.crt_static_default = true; + Target { llvm_target: "aarch64-unknown-linux-musl".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs index b96d8455a5b..416bb5432fd 100644 --- a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs +++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs @@ -22,6 +22,8 @@ pub(crate) fn target() -> Target { features: "+strict-align,+v6".into(), max_atomic_width: Some(64), mcount: "\u{1}mcount".into(), + // FIXME(compiler-team#422): musl targets should be dynamically linked by default. + crt_static_default: true, ..base::linux_musl::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs index 3418a7090d3..909eb78f698 100644 --- a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs +++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs @@ -22,6 +22,8 @@ pub(crate) fn target() -> Target { features: "+strict-align,+v6,+vfp2,-d32".into(), max_atomic_width: Some(64), mcount: "\u{1}mcount".into(), + // FIXME(compiler-team#422): musl targets should be dynamically linked by default. + crt_static_default: true, ..base::linux_musl::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs index 1bcd090b9f2..5e3ad42e5a4 100644 --- a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs @@ -23,6 +23,8 @@ pub(crate) fn target() -> Target { max_atomic_width: Some(32), mcount: "\u{1}mcount".into(), has_thumb_interworking: true, + // FIXME(compiler-team#422): musl targets should be dynamically linked by default. + crt_static_default: true, ..base::linux_musl::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs index 16923497325..843adcfc711 100644 --- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs @@ -26,6 +26,8 @@ pub(crate) fn target() -> Target { features: "+v7,+thumb2,+soft-float,-neon".into(), max_atomic_width: Some(64), mcount: "\u{1}mcount".into(), + // FIXME(compiler-team#422): musl targets should be dynamically linked by default. + crt_static_default: true, ..base::linux_musl::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs index 5adfa0bc2f8..e0630817bc3 100644 --- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs @@ -25,6 +25,8 @@ pub(crate) fn target() -> Target { features: "+v7,+vfp3,-d32,+thumb2,-neon".into(), max_atomic_width: Some(64), mcount: "\u{1}mcount".into(), + // FIXME(compiler-team#422): musl targets should be dynamically linked by default. + crt_static_default: true, ..base::linux_musl::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs index 623422a89ea..8ad93496f3a 100644 --- a/compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs @@ -4,5 +4,7 @@ pub(crate) fn target() -> Target { let mut base = super::i686_unknown_linux_musl::target(); base.cpu = "pentium".into(); base.llvm_target = "i586-unknown-linux-musl".into(); + // FIXME(compiler-team#422): musl targets should be dynamically linked by default. + base.crt_static_default = true; base } diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs index b805b80b85b..6ba87c732b7 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs @@ -6,6 +6,8 @@ pub(crate) fn target() -> Target { base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-Wl,-melf_i386"]); base.stack_probes = StackProbeType::Inline; + // FIXME(compiler-team#422): musl targets should be dynamically linked by default. + base.crt_static_default = true; // The unwinder used by i686-unknown-linux-musl, the LLVM libunwind // implementation, apparently relies on frame pointers existing... somehow. diff --git a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs index cc288e042d9..bddcc457498 100644 --- a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs @@ -8,7 +8,6 @@ pub(crate) fn target() -> Target { base.cpu = "mips64r2".into(); base.features = "+mips64r2,+soft-float".into(); base.max_atomic_width = Some(64); - base.crt_static_default = false; Target { // LLVM doesn't recognize "muslabi64" yet. diff --git a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs index 69af2da1100..32f5c79d653 100644 --- a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs @@ -22,6 +22,8 @@ pub(crate) fn target() -> Target { abi: "abi64".into(), endian: Endian::Big, mcount: "_mcount".into(), + // FIXME(compiler-team#422): musl targets should be dynamically linked by default. + crt_static_default: true, ..base }, } diff --git a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs index 4f50e8b7033..5e7c37fd46c 100644 --- a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs @@ -5,6 +5,8 @@ pub(crate) fn target() -> Target { base.cpu = "mips64r2".into(); base.features = "+mips64r2".into(); base.max_atomic_width = Some(64); + // FIXME(compiler-team#422): musl targets should be dynamically linked by default. + base.crt_static_default = true; Target { // LLVM doesn't recognize "muslabi64" yet. llvm_target: "mips64el-unknown-linux-musl".into(), diff --git a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs index b283b3b1ef7..5076ae345a9 100644 --- a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs @@ -6,7 +6,6 @@ pub(crate) fn target() -> Target { base.cpu = "mips32r2".into(); base.features = "+mips32r2,+soft-float".into(); base.max_atomic_width = Some(32); - base.crt_static_default = false; Target { llvm_target: "mips-unknown-linux-musl".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs index 744396aa1ba..339b32b6339 100644 --- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs @@ -5,7 +5,6 @@ pub(crate) fn target() -> Target { base.cpu = "mips32r2".into(); base.features = "+mips32r2,+soft-float".into(); base.max_atomic_width = Some(32); - base.crt_static_default = false; Target { llvm_target: "mipsel-unknown-linux-musl".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs index 68a3718035c..4ccb3ee4664 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs @@ -11,7 +11,7 @@ pub(crate) fn target() -> Target { Target { llvm_target: "powerpc64-unknown-freebsd".into(), metadata: crate::spec::TargetMetadata { - description: Some("PPC64 FreeBSD (ELFv1 and ELFv2)".into()), + description: Some("PPC64 FreeBSD (ELFv2)".into()), tier: Some(3), host_tools: Some(true), std: Some(true), diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs index a964f417799..a54b17c87a7 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs @@ -7,6 +7,8 @@ pub(crate) fn target() -> Target { base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); base.stack_probes = StackProbeType::Inline; + // FIXME(compiler-team#422): musl targets should be dynamically linked by default. + base.crt_static_default = true; Target { llvm_target: "powerpc64-unknown-linux-musl".into(), diff --git a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs index 04fe5f9af33..952a00c52a2 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs @@ -6,6 +6,8 @@ pub(crate) fn target() -> Target { base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); base.stack_probes = StackProbeType::Inline; + // FIXME(compiler-team#422): musl targets should be dynamically linked by default. + base.crt_static_default = true; Target { llvm_target: "powerpc64le-unknown-linux-musl".into(), diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs index 5372a83e29a..0cd0ea96ad3 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs @@ -6,6 +6,8 @@ pub(crate) fn target() -> Target { base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]); base.max_atomic_width = Some(32); base.stack_probes = StackProbeType::Inline; + // FIXME(compiler-team#422): musl targets should be dynamically linked by default. + base.crt_static_default = true; Target { llvm_target: "powerpc-unknown-linux-musl".into(), diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs index 2305db81c5e..b86c3c2e8e0 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs @@ -6,6 +6,8 @@ pub(crate) fn target() -> Target { base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-mspe"]); base.max_atomic_width = Some(32); base.stack_probes = StackProbeType::Inline; + // FIXME(compiler-team#422): musl targets should be dynamically linked by default. + base.crt_static_default = true; Target { llvm_target: "powerpc-unknown-linux-muslspe".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs index 08871d9d72b..a07429bb0c5 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs @@ -23,6 +23,8 @@ pub(crate) fn target() -> Target { llvm_abiname: "ilp32d".into(), max_atomic_width: Some(32), supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), + // FIXME(compiler-team#422): musl targets should be dynamically linked by default. + crt_static_default: true, ..base::linux_musl::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs index 397c202ec1a..0a4cc3b8be6 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs @@ -21,7 +21,6 @@ pub(crate) fn target() -> Target { llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), - crt_static_default: false, ..base::linux_musl::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs index 7a78004927b..fbe8c48eca7 100644 --- a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs @@ -12,6 +12,8 @@ pub(crate) fn target() -> Target { base.stack_probes = StackProbeType::Inline; base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::MEMORY | SanitizerSet::THREAD; + // FIXME(compiler-team#422): musl targets should be dynamically linked by default. + base.crt_static_default = true; Target { llvm_target: "s390x-unknown-linux-musl".into(), diff --git a/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs b/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs index fdc9628f78e..770da60da9e 100644 --- a/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs +++ b/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs @@ -13,7 +13,7 @@ pub(crate) fn target() -> Target { Target { llvm_target: "sparcv9-sun-solaris".into(), metadata: crate::spec::TargetMetadata { - description: Some("SPARC Solaris 11, illumos".into()), + description: Some("SPARC Solaris 11.4".into()), tier: Some(2), host_tools: Some(false), std: Some(true), diff --git a/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs index 2f539f4f600..a0852b4611e 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs @@ -29,6 +29,8 @@ pub(crate) fn target() -> Target { features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".into(), max_atomic_width: Some(64), mcount: "\u{1}mcount".into(), + // FIXME(compiler-team#422): musl targets should be dynamically linked by default. + crt_static_default: true, ..base::linux_musl::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs index 28dd3c426c7..843568a4792 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs @@ -13,7 +13,7 @@ pub(crate) fn target() -> Target { Target { llvm_target: "x86_64-pc-solaris".into(), metadata: crate::spec::TargetMetadata { - description: Some("64-bit Solaris 11, illumos".into()), + description: Some("64-bit Solaris 11.4".into()), tier: Some(2), host_tools: Some(false), std: Some(true), diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs index 8be0f335db9..8dcdc5be8a9 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs @@ -14,6 +14,8 @@ pub(crate) fn target() -> Target { | SanitizerSet::MEMORY | SanitizerSet::THREAD; base.supports_xray = true; + // FIXME(compiler-team#422): musl targets should be dynamically linked by default. + base.crt_static_default = true; Target { llvm_target: "x86_64-unknown-linux-musl".into(), diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index c89045c93e3..29d3f826a15 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -5,6 +5,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_span::symbol::{Symbol, sym}; +use crate::spec::Target; + /// Features that control behaviour of rustc, rather than the codegen. /// These exist globally and are not in the target-specific lists below. pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"]; @@ -15,45 +17,115 @@ pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"]; pub const RUSTC_SPECIAL_FEATURES: &[&str] = &["backchain"]; /// Stability information for target features. +/// `Toggleability` is the type storing whether (un)stable features can be toggled: +/// this is initially a function since it can depend on `Target`, but for stable hashing +/// it needs to be something hashable to we have to make the type generic. #[derive(Debug, Clone, Copy)] -pub enum Stability { +pub enum Stability<Toggleability> { /// This target feature is stable, it can be used in `#[target_feature]` and /// `#[cfg(target_feature)]`. - Stable, - /// This target feature is unstable; using it in `#[target_feature]` or `#[cfg(target_feature)]` - /// requires enabling the given nightly feature. - Unstable(Symbol), - /// This feature can not be set via `-Ctarget-feature` or `#[target_feature]`, it can only be set in the basic - /// target definition. Used in particular for features that change the floating-point ABI. + Stable { + /// When enabling/disabling the feature via `-Ctarget-feature` or `#[target_feature]`, + /// determine if that is allowed. + allow_toggle: Toggleability, + }, + /// This target feature is unstable. It is only present in `#[cfg(target_feature)]` on + /// nightly and using it in `#[target_feature]` requires enabling the given nightly feature. + Unstable { + /// This must be a *language* feature, or else rustc will ICE when reporting a missing + /// feature gate! + nightly_feature: Symbol, + /// See `Stable::allow_toggle` comment above. + allow_toggle: Toggleability, + }, + /// This feature can not be set via `-Ctarget-feature` or `#[target_feature]`, it can only be + /// set in the basic target definition. It is never set in `cfg(target_feature)`. Used in + /// particular for features that change the floating-point ABI. Forbidden { reason: &'static str }, } -use Stability::*; -impl<CTX> HashStable<CTX> for Stability { +/// `Stability` where `allow_toggle` has not been computed yet. +/// Returns `Ok` if the toggle is allowed, `Err` with an explanation of not. +pub type StabilityUncomputed = Stability<fn(&Target) -> Result<(), &'static str>>; +/// `Stability` where `allow_toggle` has already been computed. +pub type StabilityComputed = Stability<Result<(), &'static str>>; + +impl<CTX, Toggleability: HashStable<CTX>> HashStable<CTX> for Stability<Toggleability> { #[inline] fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { std::mem::discriminant(self).hash_stable(hcx, hasher); match self { - Stable => {} - Unstable(sym) => { - sym.hash_stable(hcx, hasher); + Stability::Stable { allow_toggle } => { + allow_toggle.hash_stable(hcx, hasher); + } + Stability::Unstable { nightly_feature, allow_toggle } => { + nightly_feature.hash_stable(hcx, hasher); + allow_toggle.hash_stable(hcx, hasher); } - Forbidden { .. } => {} + Stability::Forbidden { reason } => { + reason.hash_stable(hcx, hasher); + } + } + } +} + +impl<Toggleability> Stability<Toggleability> { + /// Returns whether the feature can be used in `cfg(target_feature)` ever. + /// (It might still be nightly-only even if this returns `true`, so make sure to also check + /// `requires_nightly`.) + pub fn in_cfg(self) -> bool { + !matches!(self, Stability::Forbidden { .. }) + } + + /// Returns the nightly feature that is required to toggle this target feature via + /// `#[target_feature]`/`-Ctarget-feature` or to test it via `cfg(target_feature)`. + /// (For `cfg` we only care whether the feature is nightly or not, we don't require + /// the feature gate to actually be enabled when using a nightly compiler.) + /// + /// Before calling this, ensure the feature is even permitted for this use: + /// - for `#[target_feature]`/`-Ctarget-feature`, check `allow_toggle()` + /// - for `cfg(target_feature)`, check `in_cfg` + pub fn requires_nightly(self) -> Option<Symbol> { + match self { + Stability::Unstable { nightly_feature, .. } => Some(nightly_feature), + Stability::Stable { .. } => None, + Stability::Forbidden { .. } => panic!("forbidden features should not reach this far"), } } } -impl Stability { - pub fn is_stable(self) -> bool { - matches!(self, Stable) +impl StabilityUncomputed { + pub fn compute_toggleability(self, target: &Target) -> StabilityComputed { + use Stability::*; + match self { + Stable { allow_toggle } => Stable { allow_toggle: allow_toggle(target) }, + Unstable { nightly_feature, allow_toggle } => { + Unstable { nightly_feature, allow_toggle: allow_toggle(target) } + } + Forbidden { reason } => Forbidden { reason }, + } } +} - /// Forbidden features are not supported. - pub fn is_supported(self) -> bool { - !matches!(self, Forbidden { .. }) +impl StabilityComputed { + /// Returns whether the feature may be toggled via `#[target_feature]` or `-Ctarget-feature`. + /// (It might still be nightly-only even if this returns `true`, so make sure to also check + /// `requires_nightly`.) + pub fn allow_toggle(self) -> Result<(), &'static str> { + match self { + Stability::Stable { allow_toggle } => allow_toggle, + Stability::Unstable { allow_toggle, .. } => allow_toggle, + Stability::Forbidden { reason } => Err(reason), + } } } +// Constructors for the list below, defaulting to "always allow toggle". +const STABLE: StabilityUncomputed = Stability::Stable { allow_toggle: |_target| Ok(()) }; +const fn unstable(nightly_feature: Symbol) -> StabilityUncomputed { + Stability::Unstable { nightly_feature, allow_toggle: |_target| Ok(()) } +} + // Here we list target features that rustc "understands": they can be used in `#[target_feature]` // and `#[cfg(target_feature)]`. They also do not trigger any warnings when used with // `-Ctarget-feature`. @@ -99,181 +171,196 @@ impl Stability { // Both of these are also applied transitively. type ImpliedFeatures = &'static [&'static str]; -const ARM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const ARM_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[ // tidy-alphabetical-start - ("aclass", Unstable(sym::arm_target_feature), &[]), - ("aes", Unstable(sym::arm_target_feature), &["neon"]), - ("crc", Unstable(sym::arm_target_feature), &[]), - ("d32", Unstable(sym::arm_target_feature), &[]), - ("dotprod", Unstable(sym::arm_target_feature), &["neon"]), - ("dsp", Unstable(sym::arm_target_feature), &[]), - ("fp-armv8", Unstable(sym::arm_target_feature), &["vfp4"]), - ("i8mm", Unstable(sym::arm_target_feature), &["neon"]), - ("mclass", Unstable(sym::arm_target_feature), &[]), - ("neon", Unstable(sym::arm_target_feature), &["vfp3"]), - ("rclass", Unstable(sym::arm_target_feature), &[]), - ("sha2", Unstable(sym::arm_target_feature), &["neon"]), - ("soft-float", Forbidden { reason: "unsound because it changes float ABI" }, &[]), + ("aclass", unstable(sym::arm_target_feature), &[]), + ("aes", unstable(sym::arm_target_feature), &["neon"]), + ("crc", unstable(sym::arm_target_feature), &[]), + ("d32", unstable(sym::arm_target_feature), &[]), + ("dotprod", unstable(sym::arm_target_feature), &["neon"]), + ("dsp", unstable(sym::arm_target_feature), &[]), + ("fp-armv8", unstable(sym::arm_target_feature), &["vfp4"]), + ( + "fpregs", + Stability::Unstable { + nightly_feature: sym::arm_target_feature, + allow_toggle: |target: &Target| { + // Only allow toggling this if the target has `soft-float` set. With `soft-float`, + // `fpregs` isn't needed so changing it cannot affect the ABI. + if target.has_feature("soft-float") { + Ok(()) + } else { + Err("unsound on hard-float targets because it changes float ABI") + } + }, + }, + &[], + ), + ("i8mm", unstable(sym::arm_target_feature), &["neon"]), + ("mclass", unstable(sym::arm_target_feature), &[]), + ("neon", unstable(sym::arm_target_feature), &["vfp3"]), + ("rclass", unstable(sym::arm_target_feature), &[]), + ("sha2", unstable(sym::arm_target_feature), &["neon"]), + ("soft-float", Stability::Forbidden { reason: "unsound because it changes float ABI" }, &[]), // This is needed for inline assembly, but shouldn't be stabilized as-is // since it should be enabled per-function using #[instruction_set], not // #[target_feature]. - ("thumb-mode", Unstable(sym::arm_target_feature), &[]), - ("thumb2", Unstable(sym::arm_target_feature), &[]), - ("trustzone", Unstable(sym::arm_target_feature), &[]), - ("v5te", Unstable(sym::arm_target_feature), &[]), - ("v6", Unstable(sym::arm_target_feature), &["v5te"]), - ("v6k", Unstable(sym::arm_target_feature), &["v6"]), - ("v6t2", Unstable(sym::arm_target_feature), &["v6k", "thumb2"]), - ("v7", Unstable(sym::arm_target_feature), &["v6t2"]), - ("v8", Unstable(sym::arm_target_feature), &["v7"]), - ("vfp2", Unstable(sym::arm_target_feature), &[]), - ("vfp3", Unstable(sym::arm_target_feature), &["vfp2", "d32"]), - ("vfp4", Unstable(sym::arm_target_feature), &["vfp3"]), - ("virtualization", Unstable(sym::arm_target_feature), &[]), + ("thumb-mode", unstable(sym::arm_target_feature), &[]), + ("thumb2", unstable(sym::arm_target_feature), &[]), + ("trustzone", unstable(sym::arm_target_feature), &[]), + ("v5te", unstable(sym::arm_target_feature), &[]), + ("v6", unstable(sym::arm_target_feature), &["v5te"]), + ("v6k", unstable(sym::arm_target_feature), &["v6"]), + ("v6t2", unstable(sym::arm_target_feature), &["v6k", "thumb2"]), + ("v7", unstable(sym::arm_target_feature), &["v6t2"]), + ("v8", unstable(sym::arm_target_feature), &["v7"]), + ("vfp2", unstable(sym::arm_target_feature), &[]), + ("vfp3", unstable(sym::arm_target_feature), &["vfp2", "d32"]), + ("vfp4", unstable(sym::arm_target_feature), &["vfp3"]), + ("virtualization", unstable(sym::arm_target_feature), &[]), // tidy-alphabetical-end - // FIXME: need to also forbid turning off `fpregs` on hardfloat targets ]; -const AARCH64_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const AARCH64_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[ // tidy-alphabetical-start // FEAT_AES & FEAT_PMULL - ("aes", Stable, &["neon"]), + ("aes", STABLE, &["neon"]), // FEAT_BF16 - ("bf16", Stable, &[]), + ("bf16", STABLE, &[]), // FEAT_BTI - ("bti", Stable, &[]), + ("bti", STABLE, &[]), // FEAT_CRC - ("crc", Stable, &[]), + ("crc", STABLE, &[]), // FEAT_CSSC - ("cssc", Unstable(sym::aarch64_unstable_target_feature), &[]), + ("cssc", unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_DIT - ("dit", Stable, &[]), + ("dit", STABLE, &[]), // FEAT_DotProd - ("dotprod", Stable, &["neon"]), + ("dotprod", STABLE, &["neon"]), // FEAT_DPB - ("dpb", Stable, &[]), + ("dpb", STABLE, &[]), // FEAT_DPB2 - ("dpb2", Stable, &["dpb"]), + ("dpb2", STABLE, &["dpb"]), // FEAT_ECV - ("ecv", Unstable(sym::aarch64_unstable_target_feature), &[]), + ("ecv", unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_F32MM - ("f32mm", Stable, &["sve"]), + ("f32mm", STABLE, &["sve"]), // FEAT_F64MM - ("f64mm", Stable, &["sve"]), + ("f64mm", STABLE, &["sve"]), // FEAT_FAMINMAX - ("faminmax", Unstable(sym::aarch64_unstable_target_feature), &[]), + ("faminmax", unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_FCMA - ("fcma", Stable, &["neon"]), + ("fcma", STABLE, &["neon"]), // FEAT_FHM - ("fhm", Stable, &["fp16"]), + ("fhm", STABLE, &["fp16"]), // FEAT_FLAGM - ("flagm", Stable, &[]), + ("flagm", STABLE, &[]), // FEAT_FLAGM2 - ("flagm2", Unstable(sym::aarch64_unstable_target_feature), &[]), + ("flagm2", unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_FP16 // Rust ties FP and Neon: https://github.com/rust-lang/rust/pull/91608 - ("fp16", Stable, &["neon"]), + ("fp16", STABLE, &["neon"]), // FEAT_FP8 - ("fp8", Unstable(sym::aarch64_unstable_target_feature), &["faminmax", "lut", "bf16"]), + ("fp8", unstable(sym::aarch64_unstable_target_feature), &["faminmax", "lut", "bf16"]), // FEAT_FP8DOT2 - ("fp8dot2", Unstable(sym::aarch64_unstable_target_feature), &["fp8dot4"]), + ("fp8dot2", unstable(sym::aarch64_unstable_target_feature), &["fp8dot4"]), // FEAT_FP8DOT4 - ("fp8dot4", Unstable(sym::aarch64_unstable_target_feature), &["fp8fma"]), + ("fp8dot4", unstable(sym::aarch64_unstable_target_feature), &["fp8fma"]), // FEAT_FP8FMA - ("fp8fma", Unstable(sym::aarch64_unstable_target_feature), &["fp8"]), + ("fp8fma", unstable(sym::aarch64_unstable_target_feature), &["fp8"]), // FEAT_FRINTTS - ("frintts", Stable, &[]), + ("frintts", STABLE, &[]), // FEAT_HBC - ("hbc", Unstable(sym::aarch64_unstable_target_feature), &[]), + ("hbc", unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_I8MM - ("i8mm", Stable, &[]), + ("i8mm", STABLE, &[]), // FEAT_JSCVT // Rust ties FP and Neon: https://github.com/rust-lang/rust/pull/91608 - ("jsconv", Stable, &["neon"]), + ("jsconv", STABLE, &["neon"]), // FEAT_LOR - ("lor", Stable, &[]), + ("lor", STABLE, &[]), // FEAT_LSE - ("lse", Stable, &[]), + ("lse", STABLE, &[]), // FEAT_LSE128 - ("lse128", Unstable(sym::aarch64_unstable_target_feature), &["lse"]), + ("lse128", unstable(sym::aarch64_unstable_target_feature), &["lse"]), // FEAT_LSE2 - ("lse2", Unstable(sym::aarch64_unstable_target_feature), &[]), + ("lse2", unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_LUT - ("lut", Unstable(sym::aarch64_unstable_target_feature), &[]), + ("lut", unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_MOPS - ("mops", Unstable(sym::aarch64_unstable_target_feature), &[]), + ("mops", unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_MTE & FEAT_MTE2 - ("mte", Stable, &[]), + ("mte", STABLE, &[]), // FEAT_AdvSimd & FEAT_FP - ("neon", Stable, &[]), + ("neon", STABLE, &[]), // FEAT_PAUTH (address authentication) - ("paca", Stable, &[]), + ("paca", STABLE, &[]), // FEAT_PAUTH (generic authentication) - ("pacg", Stable, &[]), + ("pacg", STABLE, &[]), // FEAT_PAN - ("pan", Stable, &[]), + ("pan", STABLE, &[]), // FEAT_PAuth_LR - ("pauth-lr", Unstable(sym::aarch64_unstable_target_feature), &[]), + ("pauth-lr", unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_PMUv3 - ("pmuv3", Stable, &[]), + ("pmuv3", STABLE, &[]), // FEAT_RNG - ("rand", Stable, &[]), + ("rand", STABLE, &[]), // FEAT_RAS & FEAT_RASv1p1 - ("ras", Stable, &[]), + ("ras", STABLE, &[]), // FEAT_LRCPC - ("rcpc", Stable, &[]), + ("rcpc", STABLE, &[]), // FEAT_LRCPC2 - ("rcpc2", Stable, &["rcpc"]), + ("rcpc2", STABLE, &["rcpc"]), // FEAT_LRCPC3 - ("rcpc3", Unstable(sym::aarch64_unstable_target_feature), &["rcpc2"]), + ("rcpc3", unstable(sym::aarch64_unstable_target_feature), &["rcpc2"]), // FEAT_RDM - ("rdm", Stable, &["neon"]), + ("rdm", STABLE, &["neon"]), // This is needed for inline assembly, but shouldn't be stabilized as-is // since it should be enabled globally using -Zfixed-x18, not // #[target_feature]. // Note that cfg(target_feature = "reserve-x18") is currently not set for // targets that reserve x18 by default. - ("reserve-x18", Unstable(sym::aarch64_unstable_target_feature), &[]), + ("reserve-x18", unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_SB - ("sb", Stable, &[]), + ("sb", STABLE, &[]), // FEAT_SHA1 & FEAT_SHA256 - ("sha2", Stable, &["neon"]), + ("sha2", STABLE, &["neon"]), // FEAT_SHA512 & FEAT_SHA3 - ("sha3", Stable, &["sha2"]), + ("sha3", STABLE, &["sha2"]), // FEAT_SM3 & FEAT_SM4 - ("sm4", Stable, &["neon"]), + ("sm4", STABLE, &["neon"]), // FEAT_SME - ("sme", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]), + ("sme", unstable(sym::aarch64_unstable_target_feature), &["bf16"]), // FEAT_SME_B16B16 - ("sme-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16", "sme2", "sve-b16b16"]), + ("sme-b16b16", unstable(sym::aarch64_unstable_target_feature), &["bf16", "sme2", "sve-b16b16"]), // FEAT_SME_F16F16 - ("sme-f16f16", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]), + ("sme-f16f16", unstable(sym::aarch64_unstable_target_feature), &["sme2"]), // FEAT_SME_F64F64 - ("sme-f64f64", Unstable(sym::aarch64_unstable_target_feature), &["sme"]), + ("sme-f64f64", unstable(sym::aarch64_unstable_target_feature), &["sme"]), // FEAT_SME_F8F16 - ("sme-f8f16", Unstable(sym::aarch64_unstable_target_feature), &["sme-f8f32"]), + ("sme-f8f16", unstable(sym::aarch64_unstable_target_feature), &["sme-f8f32"]), // FEAT_SME_F8F32 - ("sme-f8f32", Unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]), + ("sme-f8f32", unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]), // FEAT_SME_FA64 - ("sme-fa64", Unstable(sym::aarch64_unstable_target_feature), &["sme", "sve2"]), + ("sme-fa64", unstable(sym::aarch64_unstable_target_feature), &["sme", "sve2"]), // FEAT_SME_I16I64 - ("sme-i16i64", Unstable(sym::aarch64_unstable_target_feature), &["sme"]), + ("sme-i16i64", unstable(sym::aarch64_unstable_target_feature), &["sme"]), // FEAT_SME_LUTv2 - ("sme-lutv2", Unstable(sym::aarch64_unstable_target_feature), &[]), + ("sme-lutv2", unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_SME2 - ("sme2", Unstable(sym::aarch64_unstable_target_feature), &["sme"]), + ("sme2", unstable(sym::aarch64_unstable_target_feature), &["sme"]), // FEAT_SME2p1 - ("sme2p1", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]), + ("sme2p1", unstable(sym::aarch64_unstable_target_feature), &["sme2"]), // FEAT_SPE - ("spe", Stable, &[]), + ("spe", STABLE, &[]), // FEAT_SSBS & FEAT_SSBS2 - ("ssbs", Stable, &[]), + ("ssbs", STABLE, &[]), // FEAT_SSVE_FP8FDOT2 - ("ssve-fp8dot2", Unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8dot4"]), + ("ssve-fp8dot2", unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8dot4"]), // FEAT_SSVE_FP8FDOT4 - ("ssve-fp8dot4", Unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8fma"]), + ("ssve-fp8dot4", unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8fma"]), // FEAT_SSVE_FP8FMA - ("ssve-fp8fma", Unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]), + ("ssve-fp8fma", unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]), // FEAT_SVE // It was decided that SVE requires Neon: https://github.com/rust-lang/rust/pull/91608 // @@ -281,46 +368,46 @@ const AARCH64_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // exist together: https://developer.arm.com/documentation/102340/0100/New-features-in-SVE2 // // "For backwards compatibility, Neon and VFP are required in the latest architectures." - ("sve", Stable, &["neon"]), + ("sve", STABLE, &["neon"]), // FEAT_SVE_B16B16 (SVE or SME Z-targeting instructions) - ("sve-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]), + ("sve-b16b16", unstable(sym::aarch64_unstable_target_feature), &["bf16"]), // FEAT_SVE2 - ("sve2", Stable, &["sve"]), + ("sve2", STABLE, &["sve"]), // FEAT_SVE_AES & FEAT_SVE_PMULL128 - ("sve2-aes", Stable, &["sve2", "aes"]), + ("sve2-aes", STABLE, &["sve2", "aes"]), // FEAT_SVE2_BitPerm - ("sve2-bitperm", Stable, &["sve2"]), + ("sve2-bitperm", STABLE, &["sve2"]), // FEAT_SVE2_SHA3 - ("sve2-sha3", Stable, &["sve2", "sha3"]), + ("sve2-sha3", STABLE, &["sve2", "sha3"]), // FEAT_SVE2_SM4 - ("sve2-sm4", Stable, &["sve2", "sm4"]), + ("sve2-sm4", STABLE, &["sve2", "sm4"]), // FEAT_SVE2p1 - ("sve2p1", Unstable(sym::aarch64_unstable_target_feature), &["sve2"]), + ("sve2p1", unstable(sym::aarch64_unstable_target_feature), &["sve2"]), // FEAT_TME - ("tme", Stable, &[]), - ("v8.1a", Unstable(sym::aarch64_ver_target_feature), &[ + ("tme", STABLE, &[]), + ("v8.1a", unstable(sym::aarch64_ver_target_feature), &[ "crc", "lse", "rdm", "pan", "lor", "vh", ]), - ("v8.2a", Unstable(sym::aarch64_ver_target_feature), &["v8.1a", "ras", "dpb"]), - ("v8.3a", Unstable(sym::aarch64_ver_target_feature), &[ + ("v8.2a", unstable(sym::aarch64_ver_target_feature), &["v8.1a", "ras", "dpb"]), + ("v8.3a", unstable(sym::aarch64_ver_target_feature), &[ "v8.2a", "rcpc", "paca", "pacg", "jsconv", ]), - ("v8.4a", Unstable(sym::aarch64_ver_target_feature), &["v8.3a", "dotprod", "dit", "flagm"]), - ("v8.5a", Unstable(sym::aarch64_ver_target_feature), &["v8.4a", "ssbs", "sb", "dpb2", "bti"]), - ("v8.6a", Unstable(sym::aarch64_ver_target_feature), &["v8.5a", "bf16", "i8mm"]), - ("v8.7a", Unstable(sym::aarch64_ver_target_feature), &["v8.6a", "wfxt"]), - ("v8.8a", Unstable(sym::aarch64_ver_target_feature), &["v8.7a", "hbc", "mops"]), - ("v8.9a", Unstable(sym::aarch64_ver_target_feature), &["v8.8a", "cssc"]), - ("v9.1a", Unstable(sym::aarch64_ver_target_feature), &["v9a", "v8.6a"]), - ("v9.2a", Unstable(sym::aarch64_ver_target_feature), &["v9.1a", "v8.7a"]), - ("v9.3a", Unstable(sym::aarch64_ver_target_feature), &["v9.2a", "v8.8a"]), - ("v9.4a", Unstable(sym::aarch64_ver_target_feature), &["v9.3a", "v8.9a"]), - ("v9.5a", Unstable(sym::aarch64_ver_target_feature), &["v9.4a"]), - ("v9a", Unstable(sym::aarch64_ver_target_feature), &["v8.5a", "sve2"]), + ("v8.4a", unstable(sym::aarch64_ver_target_feature), &["v8.3a", "dotprod", "dit", "flagm"]), + ("v8.5a", unstable(sym::aarch64_ver_target_feature), &["v8.4a", "ssbs", "sb", "dpb2", "bti"]), + ("v8.6a", unstable(sym::aarch64_ver_target_feature), &["v8.5a", "bf16", "i8mm"]), + ("v8.7a", unstable(sym::aarch64_ver_target_feature), &["v8.6a", "wfxt"]), + ("v8.8a", unstable(sym::aarch64_ver_target_feature), &["v8.7a", "hbc", "mops"]), + ("v8.9a", unstable(sym::aarch64_ver_target_feature), &["v8.8a", "cssc"]), + ("v9.1a", unstable(sym::aarch64_ver_target_feature), &["v9a", "v8.6a"]), + ("v9.2a", unstable(sym::aarch64_ver_target_feature), &["v9.1a", "v8.7a"]), + ("v9.3a", unstable(sym::aarch64_ver_target_feature), &["v9.2a", "v8.8a"]), + ("v9.4a", unstable(sym::aarch64_ver_target_feature), &["v9.3a", "v8.9a"]), + ("v9.5a", unstable(sym::aarch64_ver_target_feature), &["v9.4a"]), + ("v9a", unstable(sym::aarch64_ver_target_feature), &["v8.5a", "sve2"]), // FEAT_VHE - ("vh", Stable, &[]), + ("vh", STABLE, &[]), // FEAT_WFxT - ("wfxt", Unstable(sym::aarch64_unstable_target_feature), &[]), + ("wfxt", unstable(sym::aarch64_unstable_target_feature), &[]), // tidy-alphabetical-end ]; @@ -328,241 +415,256 @@ const AARCH64_TIED_FEATURES: &[&[&str]] = &[ &["paca", "pacg"], // Together these represent `pauth` in LLVM ]; -const X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const X86_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[ // tidy-alphabetical-start - ("adx", Stable, &[]), - ("aes", Stable, &["sse2"]), - ("amx-bf16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), - ("amx-complex", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), - ("amx-fp16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), - ("amx-int8", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), - ("amx-tile", Unstable(sym::x86_amx_intrinsics), &[]), - ("avx", Stable, &["sse4.2"]), - ("avx2", Stable, &["avx"]), - ("avx512bf16", Unstable(sym::avx512_target_feature), &["avx512bw"]), - ("avx512bitalg", Unstable(sym::avx512_target_feature), &["avx512bw"]), - ("avx512bw", Unstable(sym::avx512_target_feature), &["avx512f"]), - ("avx512cd", Unstable(sym::avx512_target_feature), &["avx512f"]), - ("avx512dq", Unstable(sym::avx512_target_feature), &["avx512f"]), - ("avx512f", Unstable(sym::avx512_target_feature), &["avx2", "fma", "f16c"]), - ("avx512fp16", Unstable(sym::avx512_target_feature), &["avx512bw", "avx512vl", "avx512dq"]), - ("avx512ifma", Unstable(sym::avx512_target_feature), &["avx512f"]), - ("avx512vbmi", Unstable(sym::avx512_target_feature), &["avx512bw"]), - ("avx512vbmi2", Unstable(sym::avx512_target_feature), &["avx512bw"]), - ("avx512vl", Unstable(sym::avx512_target_feature), &["avx512f"]), - ("avx512vnni", Unstable(sym::avx512_target_feature), &["avx512f"]), - ("avx512vp2intersect", Unstable(sym::avx512_target_feature), &["avx512f"]), - ("avx512vpopcntdq", Unstable(sym::avx512_target_feature), &["avx512f"]), - ("avxifma", Unstable(sym::avx512_target_feature), &["avx2"]), - ("avxneconvert", Unstable(sym::avx512_target_feature), &["avx2"]), - ("avxvnni", Unstable(sym::avx512_target_feature), &["avx2"]), - ("avxvnniint16", Unstable(sym::avx512_target_feature), &["avx2"]), - ("avxvnniint8", Unstable(sym::avx512_target_feature), &["avx2"]), - ("bmi1", Stable, &[]), - ("bmi2", Stable, &[]), - ("cmpxchg16b", Stable, &[]), - ("ermsb", Unstable(sym::ermsb_target_feature), &[]), - ("f16c", Stable, &["avx"]), - ("fma", Stable, &["avx"]), - ("fxsr", Stable, &[]), - ("gfni", Unstable(sym::avx512_target_feature), &["sse2"]), - ("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]), - ("lzcnt", Stable, &[]), - ("movbe", Stable, &[]), - ("pclmulqdq", Stable, &["sse2"]), - ("popcnt", Stable, &[]), - ("prfchw", Unstable(sym::prfchw_target_feature), &[]), - ("rdrand", Stable, &[]), - ("rdseed", Stable, &[]), - ("rtm", Unstable(sym::rtm_target_feature), &[]), - ("sha", Stable, &["sse2"]), - ("sha512", Unstable(sym::sha512_sm_x86), &["avx2"]), - ("sm3", Unstable(sym::sha512_sm_x86), &["avx"]), - ("sm4", Unstable(sym::sha512_sm_x86), &["avx2"]), - ("soft-float", Forbidden { reason: "unsound because it changes float ABI" }, &[]), - ("sse", Stable, &[]), - ("sse2", Stable, &["sse"]), - ("sse3", Stable, &["sse2"]), - ("sse4.1", Stable, &["ssse3"]), - ("sse4.2", Stable, &["sse4.1"]), - ("sse4a", Unstable(sym::sse4a_target_feature), &["sse3"]), - ("ssse3", Stable, &["sse3"]), - ("tbm", Unstable(sym::tbm_target_feature), &[]), - ("vaes", Unstable(sym::avx512_target_feature), &["avx2", "aes"]), - ("vpclmulqdq", Unstable(sym::avx512_target_feature), &["avx", "pclmulqdq"]), - ("xop", Unstable(sym::xop_target_feature), &[/*"fma4", */ "avx", "sse4a"]), - ("xsave", Stable, &[]), - ("xsavec", Stable, &["xsave"]), - ("xsaveopt", Stable, &["xsave"]), - ("xsaves", Stable, &["xsave"]), + ("adx", STABLE, &[]), + ("aes", STABLE, &["sse2"]), + ("amx-bf16", unstable(sym::x86_amx_intrinsics), &["amx-tile"]), + ("amx-complex", unstable(sym::x86_amx_intrinsics), &["amx-tile"]), + ("amx-fp16", unstable(sym::x86_amx_intrinsics), &["amx-tile"]), + ("amx-int8", unstable(sym::x86_amx_intrinsics), &["amx-tile"]), + ("amx-tile", unstable(sym::x86_amx_intrinsics), &[]), + ("avx", STABLE, &["sse4.2"]), + ("avx2", STABLE, &["avx"]), + ("avx512bf16", unstable(sym::avx512_target_feature), &["avx512bw"]), + ("avx512bitalg", unstable(sym::avx512_target_feature), &["avx512bw"]), + ("avx512bw", unstable(sym::avx512_target_feature), &["avx512f"]), + ("avx512cd", unstable(sym::avx512_target_feature), &["avx512f"]), + ("avx512dq", unstable(sym::avx512_target_feature), &["avx512f"]), + ("avx512f", unstable(sym::avx512_target_feature), &["avx2", "fma", "f16c"]), + ("avx512fp16", unstable(sym::avx512_target_feature), &["avx512bw", "avx512vl", "avx512dq"]), + ("avx512ifma", unstable(sym::avx512_target_feature), &["avx512f"]), + ("avx512vbmi", unstable(sym::avx512_target_feature), &["avx512bw"]), + ("avx512vbmi2", unstable(sym::avx512_target_feature), &["avx512bw"]), + ("avx512vl", unstable(sym::avx512_target_feature), &["avx512f"]), + ("avx512vnni", unstable(sym::avx512_target_feature), &["avx512f"]), + ("avx512vp2intersect", unstable(sym::avx512_target_feature), &["avx512f"]), + ("avx512vpopcntdq", unstable(sym::avx512_target_feature), &["avx512f"]), + ("avxifma", unstable(sym::avx512_target_feature), &["avx2"]), + ("avxneconvert", unstable(sym::avx512_target_feature), &["avx2"]), + ("avxvnni", unstable(sym::avx512_target_feature), &["avx2"]), + ("avxvnniint16", unstable(sym::avx512_target_feature), &["avx2"]), + ("avxvnniint8", unstable(sym::avx512_target_feature), &["avx2"]), + ("bmi1", STABLE, &[]), + ("bmi2", STABLE, &[]), + ("cmpxchg16b", STABLE, &[]), + ("ermsb", unstable(sym::ermsb_target_feature), &[]), + ("f16c", STABLE, &["avx"]), + ("fma", STABLE, &["avx"]), + ("fxsr", STABLE, &[]), + ("gfni", unstable(sym::avx512_target_feature), &["sse2"]), + ("lahfsahf", unstable(sym::lahfsahf_target_feature), &[]), + ("lzcnt", STABLE, &[]), + ("movbe", STABLE, &[]), + ("pclmulqdq", STABLE, &["sse2"]), + ("popcnt", STABLE, &[]), + ("prfchw", unstable(sym::prfchw_target_feature), &[]), + ("rdrand", STABLE, &[]), + ("rdseed", STABLE, &[]), + ("rtm", unstable(sym::rtm_target_feature), &[]), + ("sha", STABLE, &["sse2"]), + ("sha512", unstable(sym::sha512_sm_x86), &["avx2"]), + ("sm3", unstable(sym::sha512_sm_x86), &["avx"]), + ("sm4", unstable(sym::sha512_sm_x86), &["avx2"]), + ("soft-float", Stability::Forbidden { reason: "unsound because it changes float ABI" }, &[]), + ("sse", STABLE, &[]), + ("sse2", STABLE, &["sse"]), + ("sse3", STABLE, &["sse2"]), + ("sse4.1", STABLE, &["ssse3"]), + ("sse4.2", STABLE, &["sse4.1"]), + ("sse4a", unstable(sym::sse4a_target_feature), &["sse3"]), + ("ssse3", STABLE, &["sse3"]), + ("tbm", unstable(sym::tbm_target_feature), &[]), + ("vaes", unstable(sym::avx512_target_feature), &["avx2", "aes"]), + ("vpclmulqdq", unstable(sym::avx512_target_feature), &["avx", "pclmulqdq"]), + ( + "x87", + Stability::Unstable { + nightly_feature: sym::x87_target_feature, + allow_toggle: |target: &Target| { + // Only allow toggling this if the target has `soft-float` set. With `soft-float`, + // `fpregs` isn't needed so changing it cannot affect the ABI. + if target.has_feature("soft-float") { + Ok(()) + } else { + Err("unsound on hard-float targets because it changes float ABI") + } + }, + }, + &[], + ), + ("xop", unstable(sym::xop_target_feature), &[/*"fma4", */ "avx", "sse4a"]), + ("xsave", STABLE, &[]), + ("xsavec", STABLE, &["xsave"]), + ("xsaveopt", STABLE, &["xsave"]), + ("xsaves", STABLE, &["xsave"]), // tidy-alphabetical-end - // FIXME: need to also forbid turning off `x87` on hardfloat targets ]; -const HEXAGON_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const HEXAGON_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[ // tidy-alphabetical-start - ("hvx", Unstable(sym::hexagon_target_feature), &[]), - ("hvx-length128b", Unstable(sym::hexagon_target_feature), &["hvx"]), + ("hvx", unstable(sym::hexagon_target_feature), &[]), + ("hvx-length128b", unstable(sym::hexagon_target_feature), &["hvx"]), // tidy-alphabetical-end ]; -const POWERPC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const POWERPC_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[ // tidy-alphabetical-start - ("altivec", Unstable(sym::powerpc_target_feature), &[]), - ("partword-atomics", Unstable(sym::powerpc_target_feature), &[]), - ("power10-vector", Unstable(sym::powerpc_target_feature), &["power9-vector"]), - ("power8-altivec", Unstable(sym::powerpc_target_feature), &["altivec"]), - ("power8-crypto", Unstable(sym::powerpc_target_feature), &["power8-altivec"]), - ("power8-vector", Unstable(sym::powerpc_target_feature), &["vsx", "power8-altivec"]), - ("power9-altivec", Unstable(sym::powerpc_target_feature), &["power8-altivec"]), - ("power9-vector", Unstable(sym::powerpc_target_feature), &["power8-vector", "power9-altivec"]), - ("quadword-atomics", Unstable(sym::powerpc_target_feature), &[]), - ("vsx", Unstable(sym::powerpc_target_feature), &["altivec"]), + ("altivec", unstable(sym::powerpc_target_feature), &[]), + ("partword-atomics", unstable(sym::powerpc_target_feature), &[]), + ("power10-vector", unstable(sym::powerpc_target_feature), &["power9-vector"]), + ("power8-altivec", unstable(sym::powerpc_target_feature), &["altivec"]), + ("power8-crypto", unstable(sym::powerpc_target_feature), &["power8-altivec"]), + ("power8-vector", unstable(sym::powerpc_target_feature), &["vsx", "power8-altivec"]), + ("power9-altivec", unstable(sym::powerpc_target_feature), &["power8-altivec"]), + ("power9-vector", unstable(sym::powerpc_target_feature), &["power8-vector", "power9-altivec"]), + ("quadword-atomics", unstable(sym::powerpc_target_feature), &[]), + ("vsx", unstable(sym::powerpc_target_feature), &["altivec"]), // tidy-alphabetical-end ]; -const MIPS_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const MIPS_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[ // tidy-alphabetical-start - ("fp64", Unstable(sym::mips_target_feature), &[]), - ("msa", Unstable(sym::mips_target_feature), &[]), - ("virt", Unstable(sym::mips_target_feature), &[]), + ("fp64", unstable(sym::mips_target_feature), &[]), + ("msa", unstable(sym::mips_target_feature), &[]), + ("virt", unstable(sym::mips_target_feature), &[]), // tidy-alphabetical-end ]; -const RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const RISCV_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[ // tidy-alphabetical-start - ("a", Stable, &["zaamo", "zalrsc"]), - ("c", Stable, &[]), - ("d", Unstable(sym::riscv_target_feature), &["f"]), - ("e", Unstable(sym::riscv_target_feature), &[]), - ("f", Unstable(sym::riscv_target_feature), &[]), - ("m", Stable, &[]), - ("relax", Unstable(sym::riscv_target_feature), &[]), - ("unaligned-scalar-mem", Unstable(sym::riscv_target_feature), &[]), - ("v", Unstable(sym::riscv_target_feature), &[]), - ("zaamo", Unstable(sym::riscv_target_feature), &[]), - ("zabha", Unstable(sym::riscv_target_feature), &["zaamo"]), - ("zalrsc", Unstable(sym::riscv_target_feature), &[]), - ("zba", Stable, &[]), - ("zbb", Stable, &[]), - ("zbc", Stable, &[]), - ("zbkb", Stable, &[]), - ("zbkc", Stable, &[]), - ("zbkx", Stable, &[]), - ("zbs", Stable, &[]), - ("zdinx", Unstable(sym::riscv_target_feature), &["zfinx"]), - ("zfh", Unstable(sym::riscv_target_feature), &["zfhmin"]), - ("zfhmin", Unstable(sym::riscv_target_feature), &["f"]), - ("zfinx", Unstable(sym::riscv_target_feature), &[]), - ("zhinx", Unstable(sym::riscv_target_feature), &["zhinxmin"]), - ("zhinxmin", Unstable(sym::riscv_target_feature), &["zfinx"]), - ("zk", Stable, &["zkn", "zkr", "zkt"]), - ("zkn", Stable, &["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"]), - ("zknd", Stable, &[]), - ("zkne", Stable, &[]), - ("zknh", Stable, &[]), - ("zkr", Stable, &[]), - ("zks", Stable, &["zbkb", "zbkc", "zbkx", "zksed", "zksh"]), - ("zksed", Stable, &[]), - ("zksh", Stable, &[]), - ("zkt", Stable, &[]), + ("a", STABLE, &["zaamo", "zalrsc"]), + ("c", STABLE, &[]), + ("d", unstable(sym::riscv_target_feature), &["f"]), + ("e", unstable(sym::riscv_target_feature), &[]), + ("f", unstable(sym::riscv_target_feature), &[]), + ("m", STABLE, &[]), + ("relax", unstable(sym::riscv_target_feature), &[]), + ("unaligned-scalar-mem", unstable(sym::riscv_target_feature), &[]), + ("v", unstable(sym::riscv_target_feature), &[]), + ("zaamo", unstable(sym::riscv_target_feature), &[]), + ("zabha", unstable(sym::riscv_target_feature), &["zaamo"]), + ("zalrsc", unstable(sym::riscv_target_feature), &[]), + ("zba", STABLE, &[]), + ("zbb", STABLE, &[]), + ("zbc", STABLE, &[]), + ("zbkb", STABLE, &[]), + ("zbkc", STABLE, &[]), + ("zbkx", STABLE, &[]), + ("zbs", STABLE, &[]), + ("zdinx", unstable(sym::riscv_target_feature), &["zfinx"]), + ("zfh", unstable(sym::riscv_target_feature), &["zfhmin"]), + ("zfhmin", unstable(sym::riscv_target_feature), &["f"]), + ("zfinx", unstable(sym::riscv_target_feature), &[]), + ("zhinx", unstable(sym::riscv_target_feature), &["zhinxmin"]), + ("zhinxmin", unstable(sym::riscv_target_feature), &["zfinx"]), + ("zk", STABLE, &["zkn", "zkr", "zkt"]), + ("zkn", STABLE, &["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"]), + ("zknd", STABLE, &[]), + ("zkne", STABLE, &[]), + ("zknh", STABLE, &[]), + ("zkr", STABLE, &[]), + ("zks", STABLE, &["zbkb", "zbkc", "zbkx", "zksed", "zksh"]), + ("zksed", STABLE, &[]), + ("zksh", STABLE, &[]), + ("zkt", STABLE, &[]), // tidy-alphabetical-end ]; -const WASM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const WASM_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[ // tidy-alphabetical-start - ("atomics", Unstable(sym::wasm_target_feature), &[]), - ("bulk-memory", Stable, &[]), - ("exception-handling", Unstable(sym::wasm_target_feature), &[]), - ("extended-const", Stable, &[]), - ("multivalue", Stable, &[]), - ("mutable-globals", Stable, &[]), - ("nontrapping-fptoint", Stable, &[]), - ("reference-types", Stable, &[]), - ("relaxed-simd", Stable, &["simd128"]), - ("sign-ext", Stable, &[]), - ("simd128", Stable, &[]), - ("tail-call", Stable, &[]), - ("wide-arithmetic", Unstable(sym::wasm_target_feature), &[]), + ("atomics", unstable(sym::wasm_target_feature), &[]), + ("bulk-memory", STABLE, &[]), + ("exception-handling", unstable(sym::wasm_target_feature), &[]), + ("extended-const", STABLE, &[]), + ("multivalue", STABLE, &[]), + ("mutable-globals", STABLE, &[]), + ("nontrapping-fptoint", STABLE, &[]), + ("reference-types", STABLE, &[]), + ("relaxed-simd", STABLE, &["simd128"]), + ("sign-ext", STABLE, &[]), + ("simd128", STABLE, &[]), + ("tail-call", STABLE, &[]), + ("wide-arithmetic", unstable(sym::wasm_target_feature), &[]), // tidy-alphabetical-end ]; -const BPF_FEATURES: &[(&str, Stability, ImpliedFeatures)] = - &[("alu32", Unstable(sym::bpf_target_feature), &[])]; +const BPF_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = + &[("alu32", unstable(sym::bpf_target_feature), &[])]; -const CSKY_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const CSKY_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[ // tidy-alphabetical-start - ("10e60", Unstable(sym::csky_target_feature), &["7e10"]), - ("2e3", Unstable(sym::csky_target_feature), &["e2"]), - ("3e3r1", Unstable(sym::csky_target_feature), &[]), - ("3e3r2", Unstable(sym::csky_target_feature), &["3e3r1", "doloop"]), - ("3e3r3", Unstable(sym::csky_target_feature), &["doloop"]), - ("3e7", Unstable(sym::csky_target_feature), &["2e3"]), - ("7e10", Unstable(sym::csky_target_feature), &["3e7"]), - ("cache", Unstable(sym::csky_target_feature), &[]), - ("doloop", Unstable(sym::csky_target_feature), &[]), - ("dsp1e2", Unstable(sym::csky_target_feature), &[]), - ("dspe60", Unstable(sym::csky_target_feature), &[]), - ("e1", Unstable(sym::csky_target_feature), &["elrw"]), - ("e2", Unstable(sym::csky_target_feature), &["e2"]), - ("edsp", Unstable(sym::csky_target_feature), &[]), - ("elrw", Unstable(sym::csky_target_feature), &[]), - ("float1e2", Unstable(sym::csky_target_feature), &[]), - ("float1e3", Unstable(sym::csky_target_feature), &[]), - ("float3e4", Unstable(sym::csky_target_feature), &[]), - ("float7e60", Unstable(sym::csky_target_feature), &[]), - ("floate1", Unstable(sym::csky_target_feature), &[]), - ("hard-tp", Unstable(sym::csky_target_feature), &[]), - ("high-registers", Unstable(sym::csky_target_feature), &[]), - ("hwdiv", Unstable(sym::csky_target_feature), &[]), - ("mp", Unstable(sym::csky_target_feature), &["2e3"]), - ("mp1e2", Unstable(sym::csky_target_feature), &["3e7"]), - ("nvic", Unstable(sym::csky_target_feature), &[]), - ("trust", Unstable(sym::csky_target_feature), &[]), - ("vdsp2e60f", Unstable(sym::csky_target_feature), &[]), - ("vdspv1", Unstable(sym::csky_target_feature), &[]), - ("vdspv2", Unstable(sym::csky_target_feature), &[]), + ("10e60", unstable(sym::csky_target_feature), &["7e10"]), + ("2e3", unstable(sym::csky_target_feature), &["e2"]), + ("3e3r1", unstable(sym::csky_target_feature), &[]), + ("3e3r2", unstable(sym::csky_target_feature), &["3e3r1", "doloop"]), + ("3e3r3", unstable(sym::csky_target_feature), &["doloop"]), + ("3e7", unstable(sym::csky_target_feature), &["2e3"]), + ("7e10", unstable(sym::csky_target_feature), &["3e7"]), + ("cache", unstable(sym::csky_target_feature), &[]), + ("doloop", unstable(sym::csky_target_feature), &[]), + ("dsp1e2", unstable(sym::csky_target_feature), &[]), + ("dspe60", unstable(sym::csky_target_feature), &[]), + ("e1", unstable(sym::csky_target_feature), &["elrw"]), + ("e2", unstable(sym::csky_target_feature), &["e2"]), + ("edsp", unstable(sym::csky_target_feature), &[]), + ("elrw", unstable(sym::csky_target_feature), &[]), + ("float1e2", unstable(sym::csky_target_feature), &[]), + ("float1e3", unstable(sym::csky_target_feature), &[]), + ("float3e4", unstable(sym::csky_target_feature), &[]), + ("float7e60", unstable(sym::csky_target_feature), &[]), + ("floate1", unstable(sym::csky_target_feature), &[]), + ("hard-tp", unstable(sym::csky_target_feature), &[]), + ("high-registers", unstable(sym::csky_target_feature), &[]), + ("hwdiv", unstable(sym::csky_target_feature), &[]), + ("mp", unstable(sym::csky_target_feature), &["2e3"]), + ("mp1e2", unstable(sym::csky_target_feature), &["3e7"]), + ("nvic", unstable(sym::csky_target_feature), &[]), + ("trust", unstable(sym::csky_target_feature), &[]), + ("vdsp2e60f", unstable(sym::csky_target_feature), &[]), + ("vdspv1", unstable(sym::csky_target_feature), &[]), + ("vdspv2", unstable(sym::csky_target_feature), &[]), // tidy-alphabetical-end //fpu // tidy-alphabetical-start - ("fdivdu", Unstable(sym::csky_target_feature), &[]), - ("fpuv2_df", Unstable(sym::csky_target_feature), &[]), - ("fpuv2_sf", Unstable(sym::csky_target_feature), &[]), - ("fpuv3_df", Unstable(sym::csky_target_feature), &[]), - ("fpuv3_hf", Unstable(sym::csky_target_feature), &[]), - ("fpuv3_hi", Unstable(sym::csky_target_feature), &[]), - ("fpuv3_sf", Unstable(sym::csky_target_feature), &[]), - ("hard-float", Unstable(sym::csky_target_feature), &[]), - ("hard-float-abi", Unstable(sym::csky_target_feature), &[]), + ("fdivdu", unstable(sym::csky_target_feature), &[]), + ("fpuv2_df", unstable(sym::csky_target_feature), &[]), + ("fpuv2_sf", unstable(sym::csky_target_feature), &[]), + ("fpuv3_df", unstable(sym::csky_target_feature), &[]), + ("fpuv3_hf", unstable(sym::csky_target_feature), &[]), + ("fpuv3_hi", unstable(sym::csky_target_feature), &[]), + ("fpuv3_sf", unstable(sym::csky_target_feature), &[]), + ("hard-float", unstable(sym::csky_target_feature), &[]), + ("hard-float-abi", unstable(sym::csky_target_feature), &[]), // tidy-alphabetical-end ]; -const LOONGARCH_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const LOONGARCH_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[ // tidy-alphabetical-start - ("d", Unstable(sym::loongarch_target_feature), &["f"]), - ("f", Unstable(sym::loongarch_target_feature), &[]), - ("frecipe", Unstable(sym::loongarch_target_feature), &[]), - ("lasx", Unstable(sym::loongarch_target_feature), &["lsx"]), - ("lbt", Unstable(sym::loongarch_target_feature), &[]), - ("lsx", Unstable(sym::loongarch_target_feature), &["d"]), - ("lvz", Unstable(sym::loongarch_target_feature), &[]), - ("relax", Unstable(sym::loongarch_target_feature), &[]), - ("ual", Unstable(sym::loongarch_target_feature), &[]), + ("d", unstable(sym::loongarch_target_feature), &["f"]), + ("f", unstable(sym::loongarch_target_feature), &[]), + ("frecipe", unstable(sym::loongarch_target_feature), &[]), + ("lasx", unstable(sym::loongarch_target_feature), &["lsx"]), + ("lbt", unstable(sym::loongarch_target_feature), &[]), + ("lsx", unstable(sym::loongarch_target_feature), &["d"]), + ("lvz", unstable(sym::loongarch_target_feature), &[]), + ("relax", unstable(sym::loongarch_target_feature), &[]), + ("ual", unstable(sym::loongarch_target_feature), &[]), // tidy-alphabetical-end ]; -const IBMZ_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const IBMZ_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[ // tidy-alphabetical-start - ("backchain", Unstable(sym::s390x_target_feature), &[]), - ("vector", Unstable(sym::s390x_target_feature), &[]), + ("backchain", unstable(sym::s390x_target_feature), &[]), + ("vector", unstable(sym::s390x_target_feature), &[]), // tidy-alphabetical-end ]; -const SPARC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const SPARC_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[ // tidy-alphabetical-start - ("leoncasa", Unstable(sym::sparc_target_feature), &[]), - ("v8plus", Unstable(sym::sparc_target_feature), &[]), - ("v9", Unstable(sym::sparc_target_feature), &[]), + ("leoncasa", unstable(sym::sparc_target_feature), &[]), + ("v8plus", unstable(sym::sparc_target_feature), &[]), + ("v9", unstable(sym::sparc_target_feature), &[]), // tidy-alphabetical-end ]; @@ -570,7 +672,7 @@ const SPARC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ /// primitives may be documented. /// /// IMPORTANT: If you're adding another feature list above, make sure to add it to this iterator! -pub fn all_rust_features() -> impl Iterator<Item = (&'static str, Stability)> { +pub fn all_rust_features() -> impl Iterator<Item = (&'static str, StabilityUncomputed)> { std::iter::empty() .chain(ARM_FEATURES.iter()) .chain(AARCH64_FEATURES.iter()) @@ -614,8 +716,10 @@ const CSKY_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[( const LOONGARCH_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "lsx"), (256, "lasx")]; -impl super::spec::Target { - pub fn rust_target_features(&self) -> &'static [(&'static str, Stability, ImpliedFeatures)] { +impl Target { + pub fn rust_target_features( + &self, + ) -> &'static [(&'static str, StabilityUncomputed, ImpliedFeatures)] { match &*self.arch { "arm" => ARM_FEATURES, "aarch64" | "arm64ec" => AARCH64_FEATURES, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index f856a8d7abb..5a62a4c3bd5 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -63,10 +63,11 @@ use rustc_hir::{self as hir}; use rustc_macros::extension; use rustc_middle::bug; use rustc_middle::dep_graph::DepContext; +use rustc_middle::traits::PatternOriginExpr; use rustc_middle::ty::error::{ExpectedFound, TypeError, TypeErrorToStringExt}; use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, with_forced_trimmed_paths}; use rustc_middle::ty::{ - self, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, + self, List, ParamEnv, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, }; use rustc_span::def_id::LOCAL_CRATE; @@ -77,7 +78,7 @@ use crate::error_reporting::TypeErrCtxt; use crate::errors::{ObligationCauseFailureCode, TypeErrorAdditionalDiags}; use crate::infer; use crate::infer::relate::{self, RelateResult, TypeRelation}; -use crate::infer::{InferCtxt, TypeTrace, ValuePairs}; +use crate::infer::{InferCtxt, InferCtxtExt as _, TypeTrace, ValuePairs}; use crate::solve::deeply_normalize_for_diagnostics; use crate::traits::{ IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode, @@ -433,15 +434,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { cause: &ObligationCause<'tcx>, exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>, terr: TypeError<'tcx>, + param_env: Option<ParamEnv<'tcx>>, ) { match *cause.code() { - ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => { - let ty = self.resolve_vars_if_possible(root_ty); - if !matches!(ty.kind(), ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_))) - { + ObligationCauseCode::Pattern { + origin_expr: Some(origin_expr), + span: Some(span), + root_ty, + } => { + let expected_ty = self.resolve_vars_if_possible(root_ty); + if !matches!( + expected_ty.kind(), + ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_)) + ) { // don't show type `_` if span.desugaring_kind() == Some(DesugaringKind::ForLoop) - && let ty::Adt(def, args) = ty.kind() + && let ty::Adt(def, args) = expected_ty.kind() && Some(def.did()) == self.tcx.get_diagnostic_item(sym::Option) { err.span_label( @@ -449,22 +457,48 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { format!("this is an iterator with items of type `{}`", args.type_at(0)), ); } else { - err.span_label(span, format!("this expression has type `{ty}`")); + err.span_label(span, format!("this expression has type `{expected_ty}`")); } } if let Some(ty::error::ExpectedFound { found, .. }) = exp_found - && ty.boxed_ty() == Some(found) - && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) + && let Ok(mut peeled_snippet) = + self.tcx.sess.source_map().span_to_snippet(origin_expr.peeled_span) { - err.span_suggestion( - span, - "consider dereferencing the boxed value", - format!("*{snippet}"), - Applicability::MachineApplicable, - ); + // Parentheses are needed for cases like as casts. + // We use the peeled_span for deref suggestions. + // It's also safe to use for box, since box only triggers if there + // wasn't a reference to begin with. + if origin_expr.peeled_prefix_suggestion_parentheses { + peeled_snippet = format!("({peeled_snippet})"); + } + + // Try giving a box suggestion first, as it is a special case of the + // deref suggestion. + if expected_ty.boxed_ty() == Some(found) { + err.span_suggestion_verbose( + span, + "consider dereferencing the boxed value", + format!("*{peeled_snippet}"), + Applicability::MachineApplicable, + ); + } else if let Some(param_env) = param_env + && let Some(prefix) = self.should_deref_suggestion_on_mismatch( + param_env, + found, + expected_ty, + origin_expr, + ) + { + err.span_suggestion_verbose( + span, + "consider dereferencing to access the inner value using the Deref trait", + format!("{prefix}{peeled_snippet}"), + Applicability::MaybeIncorrect, + ); + } } } - ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => { + ObligationCauseCode::Pattern { origin_expr: None, span: Some(span), .. } => { err.span_label(span, "expected due to this"); } ObligationCauseCode::BlockTailExpression( @@ -618,6 +652,45 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } + /// Determines whether deref_to == <deref_from as Deref>::Target, and if so, + /// returns a prefix that should be added to deref_from as a suggestion. + fn should_deref_suggestion_on_mismatch( + &self, + param_env: ParamEnv<'tcx>, + deref_to: Ty<'tcx>, + deref_from: Ty<'tcx>, + origin_expr: PatternOriginExpr, + ) -> Option<String> { + // origin_expr contains stripped away versions of our expression. + // We'll want to use that to avoid suggesting things like *&x. + // However, the type that we have access to hasn't been stripped away, + // so we need to ignore the first n dereferences, where n is the number + // that's been stripped away in origin_expr. + + // Find a way to autoderef from deref_from to deref_to. + let Some((num_derefs, (after_deref_ty, _))) = (self.autoderef_steps)(deref_from) + .into_iter() + .enumerate() + .find(|(_, (ty, _))| self.infcx.can_eq(param_env, *ty, deref_to)) + else { + return None; + }; + + if num_derefs <= origin_expr.peeled_count { + return None; + } + + let deref_part = "*".repeat(num_derefs - origin_expr.peeled_count); + + // If the user used a reference in the original expression, they probably + // want the suggestion to still give a reference. + if deref_from.is_ref() && !after_deref_ty.is_ref() { + Some(format!("&{deref_part}")) + } else { + Some(deref_part) + } + } + /// Given that `other_ty` is the same as a type argument for `name` in `sub`, populate `value` /// highlighting `name` and every type argument that isn't at `pos` (which is `other_ty`), and /// populate `other_value` with `other_ty`. @@ -1406,8 +1479,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { Variable(ty::error::ExpectedFound<Ty<'a>>), Fixed(&'static str), } - let (expected_found, exp_found, is_simple_error, values) = match values { - None => (None, Mismatch::Fixed("type"), false, None), + let (expected_found, exp_found, is_simple_error, values, param_env) = match values { + None => (None, Mismatch::Fixed("type"), false, None, None), Some(ty::ParamEnvAnd { param_env, value: values }) => { let mut values = self.resolve_vars_if_possible(values); if self.next_trait_solver() { @@ -1459,7 +1532,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { diag.downgrade_to_delayed_bug(); return; }; - (Some(vals), exp_found, is_simple_error, Some(values)) + (Some(vals), exp_found, is_simple_error, Some(values), Some(param_env)) } }; @@ -1791,7 +1864,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // It reads better to have the error origin as the final // thing. - self.note_error_origin(diag, cause, exp_found, terr); + self.note_error_origin(diag, cause, exp_found, terr, param_env); debug!(?diag); } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs index fc2d0ba36f0..08775df5ac9 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs @@ -210,7 +210,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { (Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code() { ObligationCauseCode::Pattern { span: Some(then_span), origin_expr, .. } => { - origin_expr.then_some(ConsiderAddingAwait::FutureSugg { + origin_expr.is_some().then_some(ConsiderAddingAwait::FutureSugg { span: then_span.shrink_to_hi(), }) } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 94682f501a8..cc8941b9224 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -20,7 +20,8 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{ - CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node, is_range_literal, + CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node, expr_needs_parens, + is_range_literal, }; use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk}; use rustc_middle::hir::map; @@ -1391,13 +1392,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let Some(expr) = expr_finder.result else { return false; }; - let needs_parens = match expr.kind { - // parenthesize if needed (Issue #46756) - hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true, - // parenthesize borrows of range literals (Issue #54505) - _ if is_range_literal(expr) => true, - _ => false, - }; + let needs_parens = expr_needs_parens(expr); let span = if needs_parens { span } else { span.shrink_to_lo() }; let suggestions = if !needs_parens { diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index 07fb2efb7fe..b17a489a857 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -128,7 +128,9 @@ fn evaluate_host_effect_from_selection_candiate<'tcx>( Err(_) => Err(EvaluationFailure::NoSolution), Ok(Some(source)) => match source { ImplSource::UserDefined(impl_) => { - if tcx.constness(impl_.impl_def_id) != hir::Constness::Const { + if tcx.impl_trait_header(impl_.impl_def_id).unwrap().constness + != hir::Constness::Const + { return Err(EvaluationFailure::NoSolution); } diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs index dc3f5544613..254dee794f1 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs @@ -3,7 +3,7 @@ use rustc_infer::traits::Obligation; use rustc_middle::traits::query::NoSolution; pub use rustc_middle::traits::query::type_op::AscribeUserType; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; -use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, UserArgs, UserSelfTy, UserType}; +use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, UserArgs, UserSelfTy, UserTypeKind}; use rustc_span::{DUMMY_SP, Span}; use tracing::{debug, instrument}; @@ -46,12 +46,18 @@ pub fn type_op_ascribe_user_type_with_span<'tcx>( let (param_env, AscribeUserType { mir_ty, user_ty }) = key.into_parts(); debug!("type_op_ascribe_user_type: mir_ty={:?} user_ty={:?}", mir_ty, user_ty); let span = span.unwrap_or(DUMMY_SP); - match user_ty { - UserType::Ty(user_ty) => relate_mir_and_user_ty(ocx, param_env, span, mir_ty, user_ty)?, - UserType::TypeOf(def_id, user_args) => { + match user_ty.kind { + UserTypeKind::Ty(user_ty) => relate_mir_and_user_ty(ocx, param_env, span, mir_ty, user_ty)?, + UserTypeKind::TypeOf(def_id, user_args) => { relate_mir_and_user_args(ocx, param_env, span, mir_ty, def_id, user_args)? } }; + + // Enforce any bounds that come from impl trait in bindings. + ocx.register_obligations(user_ty.bounds.iter().map(|clause| { + Obligation::new(ocx.infcx.tcx, ObligationCause::dummy_with_span(span), param_env, clause) + })); + Ok(()) } diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index f96487cc53c..dfd090b3956 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -5,8 +5,8 @@ use serde::Serialize; use crate::compiler_interface::with; use crate::mir::pretty::function_body; use crate::ty::{ - AdtDef, ClosureDef, CoroutineDef, GenericArgs, MirConst, Movability, Region, RigidTy, Ty, - TyConst, TyKind, VariantIdx, + AdtDef, ClosureDef, CoroutineClosureDef, CoroutineDef, GenericArgs, MirConst, Movability, + Region, RigidTy, Ty, TyConst, TyKind, VariantIdx, }; use crate::{Error, Opaque, Span, Symbol}; @@ -617,6 +617,9 @@ impl Rvalue { AggregateKind::Coroutine(def, ref args, mov) => { Ok(Ty::new_coroutine(def, args.clone(), mov)) } + AggregateKind::CoroutineClosure(def, ref args) => { + Ok(Ty::new_coroutine_closure(def, args.clone())) + } AggregateKind::RawPtr(ty, mutability) => Ok(Ty::new_ptr(ty, mutability)), }, Rvalue::ShallowInitBox(_, ty) => Ok(Ty::new_box(*ty)), @@ -633,6 +636,7 @@ pub enum AggregateKind { Closure(ClosureDef, GenericArgs), // FIXME(stable_mir): Movability here is redundant Coroutine(CoroutineDef, GenericArgs, Movability), + CoroutineClosure(CoroutineClosureDef, GenericArgs), RawPtr(Ty, Mutability), } diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs index 01a50d46b2d..93ed32e258a 100644 --- a/compiler/stable_mir/src/mir/pretty.rs +++ b/compiler/stable_mir/src/mir/pretty.rs @@ -410,6 +410,10 @@ fn pretty_aggregate<W: Write>( write!(writer, "{{coroutine@{}}}(", def.span().diagnostic())?; ")" } + AggregateKind::CoroutineClosure(def, _) => { + write!(writer, "{{coroutine-closure@{}}}(", def.span().diagnostic())?; + ")" + } AggregateKind::RawPtr(ty, mutability) => { write!( writer, diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index 9ce72f155f9..d7eb435e13f 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -63,6 +63,11 @@ impl Ty { Ty::from_rigid_kind(RigidTy::Coroutine(def, args, mov)) } + /// Create a new closure type. + pub fn new_coroutine_closure(def: CoroutineClosureDef, args: GenericArgs) -> Ty { + Ty::from_rigid_kind(RigidTy::CoroutineClosure(def, args)) + } + /// Create a new box type that represents `Box<T>`, for the given inner type `T`. pub fn new_box(inner_ty: Ty) -> Ty { with(|cx| cx.new_box_ty(inner_ty)) @@ -550,6 +555,7 @@ pub enum RigidTy { Closure(ClosureDef, GenericArgs), // FIXME(stable_mir): Movability here is redundant Coroutine(CoroutineDef, GenericArgs, Movability), + CoroutineClosure(CoroutineClosureDef, GenericArgs), Dynamic(Vec<Binder<ExistentialPredicate>>, Region, DynKind), Never, Tuple(Vec<Ty>), @@ -742,6 +748,11 @@ crate_def! { crate_def! { #[derive(Serialize)] + pub CoroutineClosureDef; +} + +crate_def! { + #[derive(Serialize)] pub ParamDef; } diff --git a/compiler/stable_mir/src/visitor.rs b/compiler/stable_mir/src/visitor.rs index 48260285408..3533ed2e851 100644 --- a/compiler/stable_mir/src/visitor.rs +++ b/compiler/stable_mir/src/visitor.rs @@ -168,6 +168,7 @@ impl Visitable for RigidTy { | RigidTy::Closure(_, args) | RigidTy::Coroutine(_, args, _) | RigidTy::CoroutineWitness(_, args) + | RigidTy::CoroutineClosure(_, args) | RigidTy::FnDef(_, args) => args.visit(visitor), RigidTy::FnPtr(sig) => sig.visit(visitor), RigidTy::Dynamic(pred, r, _) => { diff --git a/library/core/src/error.rs b/library/core/src/error.rs index 91549f49f9f..9dbea57fa1f 100644 --- a/library/core/src/error.rs +++ b/library/core/src/error.rs @@ -2,7 +2,7 @@ #![stable(feature = "error_in_core", since = "1.81.0")] use crate::any::TypeId; -use crate::fmt::{Debug, Display, Formatter, Result}; +use crate::fmt::{self, Debug, Display, Formatter}; /// `Error` is a trait representing the basic expectations for error values, /// i.e., values of type `E` in [`Result<T, E>`]. @@ -857,7 +857,7 @@ impl<'a> Request<'a> { #[unstable(feature = "error_generic_member_access", issue = "99301")] impl<'a> Debug for Request<'a> { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("Request").finish_non_exhaustive() } } diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs index af6f0da88de..94341a4da66 100644 --- a/library/core/src/fmt/rt.rs +++ b/library/core/src/fmt/rt.rs @@ -19,7 +19,7 @@ pub struct Placeholder { } impl Placeholder { - #[inline(always)] + #[inline] pub const fn new( position: usize, fill: char, @@ -95,7 +95,7 @@ pub struct Argument<'a> { #[rustc_diagnostic_item = "ArgumentMethods"] impl Argument<'_> { - #[inline(always)] + #[inline] fn new<'a, T>(x: &'a T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'a> { Argument { // INVARIANT: this creates an `ArgumentType<'a>` from a `&'a T` and @@ -109,47 +109,47 @@ impl Argument<'_> { } } - #[inline(always)] + #[inline] pub fn new_display<T: Display>(x: &T) -> Argument<'_> { Self::new(x, Display::fmt) } - #[inline(always)] + #[inline] pub fn new_debug<T: Debug>(x: &T) -> Argument<'_> { Self::new(x, Debug::fmt) } - #[inline(always)] + #[inline] pub fn new_debug_noop<T: Debug>(x: &T) -> Argument<'_> { Self::new(x, |_, _| Ok(())) } - #[inline(always)] + #[inline] pub fn new_octal<T: Octal>(x: &T) -> Argument<'_> { Self::new(x, Octal::fmt) } - #[inline(always)] + #[inline] pub fn new_lower_hex<T: LowerHex>(x: &T) -> Argument<'_> { Self::new(x, LowerHex::fmt) } - #[inline(always)] + #[inline] pub fn new_upper_hex<T: UpperHex>(x: &T) -> Argument<'_> { Self::new(x, UpperHex::fmt) } - #[inline(always)] + #[inline] pub fn new_pointer<T: Pointer>(x: &T) -> Argument<'_> { Self::new(x, Pointer::fmt) } - #[inline(always)] + #[inline] pub fn new_binary<T: Binary>(x: &T) -> Argument<'_> { Self::new(x, Binary::fmt) } - #[inline(always)] + #[inline] pub fn new_lower_exp<T: LowerExp>(x: &T) -> Argument<'_> { Self::new(x, LowerExp::fmt) } - #[inline(always)] + #[inline] pub fn new_upper_exp<T: UpperExp>(x: &T) -> Argument<'_> { Self::new(x, UpperExp::fmt) } - #[inline(always)] + #[inline] pub fn from_usize(x: &usize) -> Argument<'_> { Argument { ty: ArgumentType::Count(*x) } } @@ -164,7 +164,7 @@ impl Argument<'_> { // it here is an explicit CFI violation. #[allow(inline_no_sanitize)] #[no_sanitize(cfi, kcfi)] - #[inline(always)] + #[inline] pub(super) unsafe fn fmt(&self, f: &mut Formatter<'_>) -> Result { match self.ty { // SAFETY: @@ -180,7 +180,7 @@ impl Argument<'_> { } } - #[inline(always)] + #[inline] pub(super) fn as_usize(&self) -> Option<usize> { match self.ty { ArgumentType::Count(count) => Some(count), @@ -198,7 +198,7 @@ impl Argument<'_> { /// let f = format_args!("{}", "a"); /// println!("{f}"); /// ``` - #[inline(always)] + #[inline] pub fn none() -> [Self; 0] { [] } @@ -215,7 +215,7 @@ pub struct UnsafeArg { impl UnsafeArg { /// See documentation where `UnsafeArg` is required to know when it is safe to /// create and use `UnsafeArg`. - #[inline(always)] + #[inline] pub unsafe fn new() -> Self { Self { _private: () } } diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index c59e4414d37..9c054b99a27 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -310,6 +310,8 @@ pub fn spin_loop() { /// behavior in the calling code. This property makes `black_box` useful for writing code in which /// certain optimizations are not desired, such as benchmarks. /// +/// <div class="warning"> +/// /// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The /// extent to which it can block optimisations may vary depending upon the platform and code-gen /// backend used. Programs cannot rely on `black_box` for *correctness*, beyond it behaving as the @@ -317,6 +319,8 @@ pub fn spin_loop() { /// This also means that this function does not offer any guarantees for cryptographic or security /// purposes. /// +/// </div> +/// /// [`std::convert::identity`]: crate::convert::identity /// /// # When is this useful? @@ -357,7 +361,7 @@ pub fn spin_loop() { /// ``` /// use std::hint::black_box; /// -/// // Same `contains` function +/// // Same `contains` function. /// fn contains(haystack: &[&str], needle: &str) -> bool { /// haystack.iter().any(|x| x == &needle) /// } @@ -366,8 +370,13 @@ pub fn spin_loop() { /// let haystack = vec!["abc", "def", "ghi", "jkl", "mno"]; /// let needle = "ghi"; /// for _ in 0..10 { -/// // Adjust our benchmark loop contents -/// black_box(contains(black_box(&haystack), black_box(needle))); +/// // Force the compiler to run `contains`, even though it is a pure function whose +/// // results are unused. +/// black_box(contains( +/// // Prevent the compiler from making assumptions about the input. +/// black_box(&haystack), +/// black_box(needle), +/// )); /// } /// } /// ``` @@ -382,6 +391,83 @@ pub fn spin_loop() { /// /// This makes our benchmark much more realistic to how the function would actually be used, where /// arguments are usually not known at compile time and the result is used in some way. +/// +/// # How to use this +/// +/// In practice, `black_box` serves two purposes: +/// +/// 1. It prevents the compiler from making optimizations related to the value returned by `black_box` +/// 2. It forces the value passed to `black_box` to be calculated, even if the return value of `black_box` is unused +/// +/// ``` +/// use std::hint::black_box; +/// +/// let zero = 0; +/// let five = 5; +/// +/// // The compiler will see this and remove the `* five` call, because it knows that multiplying +/// // any integer by 0 will result in 0. +/// let c = zero * five; +/// +/// // Adding `black_box` here disables the compiler's ability to reason about the first operand in the multiplication. +/// // It is forced to assume that it can be any possible number, so it cannot remove the `* five` +/// // operation. +/// let c = black_box(zero) * five; +/// ``` +/// +/// While most cases will not be as clear-cut as the above example, it still illustrates how +/// `black_box` can be used. When benchmarking a function, you usually want to wrap its inputs in +/// `black_box` so the compiler cannot make optimizations that would be unrealistic in real-life +/// use. +/// +/// ``` +/// use std::hint::black_box; +/// +/// // This is a simple function that increments its input by 1. Note that it is pure, meaning it +/// // has no side-effects. This function has no effect if its result is unused. (An example of a +/// // function *with* side-effects is `println!()`.) +/// fn increment(x: u8) -> u8 { +/// x + 1 +/// } +/// +/// // Here, we call `increment` but discard its result. The compiler, seeing this and knowing that +/// // `increment` is pure, will eliminate this function call entirely. This may not be desired, +/// // though, especially if we're trying to track how much time `increment` takes to execute. +/// let _ = increment(black_box(5)); +/// +/// // Here, we force `increment` to be executed. This is because the compiler treats `black_box` +/// // as if it has side-effects, and thus must compute its input. +/// let _ = black_box(increment(black_box(5))); +/// ``` +/// +/// There may be additional situations where you want to wrap the result of a function in +/// `black_box` to force its execution. This is situational though, and may not have any effect +/// (such as when the function returns a zero-sized type such as [`()` unit][unit]). +/// +/// Note that `black_box` has no effect on how its input is treated, only its output. As such, +/// expressions passed to `black_box` may still be optimized: +/// +/// ``` +/// use std::hint::black_box; +/// +/// // The compiler sees this... +/// let y = black_box(5 * 10); +/// +/// // ...as this. As such, it will likely simplify `5 * 10` to just `50`. +/// let _0 = 5 * 10; +/// let y = black_box(_0); +/// ``` +/// +/// In the above example, the `5 * 10` expression is considered distinct from the `black_box` call, +/// and thus is still optimized by the compiler. You can prevent this by moving the multiplication +/// operation outside of `black_box`: +/// +/// ``` +/// use std::hint::black_box; +/// +/// // No assumptions can be made about either operand, so the multiplication is not optimized out. +/// let y = black_box(5) * black_box(10); +/// ``` #[inline] #[stable(feature = "bench_black_box", since = "1.66.0")] #[rustc_const_unstable(feature = "const_black_box", issue = "none")] diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index c3c7288e389..8ab1c26f95e 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -493,15 +493,64 @@ impl Extend<()> for () { } macro_rules! spec_tuple_impl { - ( ($ty_name:ident, $var_name:ident, $extend_ty_name: ident, $trait_name:ident, $default_fn_name:ident, $cnt:tt), ) => { - spec_tuple_impl!($trait_name, $default_fn_name, #[doc(fake_variadic)] #[doc = "This trait is implemented for tuples up to twelve items long. The `impl`s for 1- and 3- through 12-ary tuples were stabilized after 2-tuples, in RUSTC_CURRENT_VERSION."] => ($ty_name, $var_name, $extend_ty_name, $cnt),); + ( + ( + $ty_name:ident, $var_name:ident, $extend_ty_name: ident, + $trait_name:ident, $default_fn_name:ident, $cnt:tt + ), + ) => { + spec_tuple_impl!( + $trait_name, + $default_fn_name, + #[doc(fake_variadic)] + #[doc = "This trait is implemented for tuples up to twelve items long. The `impl`s for \ + 1- and 3- through 12-ary tuples were stabilized after 2-tuples, in \ + CURRENT_RUSTC_VERSION."] + => ($ty_name, $var_name, $extend_ty_name, $cnt), + ); }; - ( ($ty_name:ident, $var_name:ident, $extend_ty_name: ident, $trait_name:ident, $default_fn_name:ident, $cnt:tt), $(($ty_names:ident, $var_names:ident, $extend_ty_names:ident, $trait_names:ident, $default_fn_names:ident, $cnts:tt),)*) => { - - spec_tuple_impl!($(($ty_names, $var_names, $extend_ty_names, $trait_names, $default_fn_names, $cnts),)*); - spec_tuple_impl!($trait_name, $default_fn_name, #[doc(hidden)] => ($ty_name, $var_name, $extend_ty_name, $cnt), $(($ty_names, $var_names, $extend_ty_names, $cnts),)*); + ( + ( + $ty_name:ident, $var_name:ident, $extend_ty_name: ident, + $trait_name:ident, $default_fn_name:ident, $cnt:tt + ), + $( + ( + $ty_names:ident, $var_names:ident, $extend_ty_names:ident, + $trait_names:ident, $default_fn_names:ident, $cnts:tt + ), + )* + ) => { + spec_tuple_impl!( + $( + ( + $ty_names, $var_names, $extend_ty_names, + $trait_names, $default_fn_names, $cnts + ), + )* + ); + spec_tuple_impl!( + $trait_name, + $default_fn_name, + #[doc(hidden)] + => ( + $ty_name, $var_name, $extend_ty_name, $cnt + ), + $( + ( + $ty_names, $var_names, $extend_ty_names, $cnts + ), + )* + ); }; - ($trait_name:ident, $default_fn_name:ident, #[$meta:meta] $(#[$doctext:meta])? => $(($ty_names:ident, $var_names:ident, $extend_ty_names:ident, $cnts:tt),)*) => { + ( + $trait_name:ident, $default_fn_name:ident, #[$meta:meta] + $(#[$doctext:meta])? => $( + ( + $ty_names:ident, $var_names:ident, $extend_ty_names:ident, $cnts:tt + ), + )* + ) => { #[$meta] $(#[$doctext])? #[stable(feature = "extend_for_tuple", since = "1.56.0")] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index fde6887c5ab..d45cb01910f 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -354,6 +354,8 @@ pub mod random; pub mod range; pub mod result; pub mod sync; +#[unstable(feature = "unsafe_binders", issue = "130516")] +pub mod unsafe_binder; pub mod fmt; pub mod hash; diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index bc4c4e168a3..51ab2054b3b 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -200,7 +200,7 @@ //! //! But it *is* still sound to: //! -//! * Create a pointer without provenance from just an address (see [`ptr::dangling`]). Such a +//! * Create a pointer without provenance from just an address (see [`without_provenance`]). Such a //! pointer cannot be used for memory accesses (except for zero-sized accesses). This can still be //! useful for sentinel values like `null` *or* to represent a tagged pointer that will never be //! dereferenceable. In general, it is always sound for an integer to pretend to be a pointer "for @@ -314,8 +314,8 @@ //! } //! ``` //! -//! (Yes, if you've been using AtomicUsize for pointers in concurrent datastructures, you should -//! be using AtomicPtr instead. If that messes up the way you atomically manipulate pointers, +//! (Yes, if you've been using [`AtomicUsize`] for pointers in concurrent datastructures, you should +//! be using [`AtomicPtr`] instead. If that messes up the way you atomically manipulate pointers, //! we would like to know why, and what needs to be done to fix it.) //! //! Situations where a valid pointer *must* be created from just an address, such as baremetal code @@ -381,7 +381,8 @@ //! [`with_addr`]: pointer::with_addr //! [`map_addr`]: pointer::map_addr //! [`addr`]: pointer::addr -//! [`ptr::dangling`]: core::ptr::dangling +//! [`AtomicUsize`]: crate::sync::atomic::AtomicUsize +//! [`AtomicPtr`]: crate::sync::atomic::AtomicPtr //! [`expose_provenance`]: pointer::expose_provenance //! [`with_exposed_provenance`]: with_exposed_provenance //! [Miri]: https://github.com/rust-lang/miri diff --git a/library/core/src/unsafe_binder.rs b/library/core/src/unsafe_binder.rs new file mode 100644 index 00000000000..98f53e07d9d --- /dev/null +++ b/library/core/src/unsafe_binder.rs @@ -0,0 +1,25 @@ +//! Operators used to turn types into unsafe binders and back. + +/// Unwrap an unsafe binder into its underlying type. +#[allow_internal_unstable(builtin_syntax)] +#[unstable(feature = "unsafe_binders", issue = "130516")] +pub macro unwrap_binder { + ($expr:expr) => { + builtin # unwrap_binder ( $expr ) + }, + ($expr:expr ; $ty:ty) => { + builtin # unwrap_binder ( $expr, $ty ) + }, +} + +/// Wrap a type into an unsafe binder. +#[allow_internal_unstable(builtin_syntax)] +#[unstable(feature = "unsafe_binders", issue = "130516")] +pub macro wrap_binder { + ($expr:expr) => { + builtin # wrap_binder ( $expr ) + }, + ($expr:expr ; $ty:ty) => { + builtin # wrap_binder ( $expr, $ty ) + }, +} diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 047f5b0c4c5..1cbf51463ea 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -544,6 +544,8 @@ pub use core::u64; #[stable(feature = "i128", since = "1.26.0")] #[allow(deprecated, deprecated_in_future)] pub use core::u128; +#[unstable(feature = "unsafe_binders", issue = "130516")] +pub use core::unsafe_binder; #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated, deprecated_in_future)] pub use core::usize; diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 5b277a982ee..35e920ab344 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -2327,7 +2327,9 @@ impl Path { // FIXME: Allow Redox prefixes self.has_root() || has_redox_scheme(self.as_u8_slice()) } else { - self.has_root() && (cfg!(any(unix, target_os = "wasi")) || self.prefix().is_some()) + self.has_root() + && (cfg!(any(unix, target_os = "hermit", target_os = "wasi")) + || self.prefix().is_some()) } } diff --git a/library/std/src/pipe.rs b/library/std/src/pipe.rs index 891032e94a6..06f3fd9fdff 100644 --- a/library/std/src/pipe.rs +++ b/library/std/src/pipe.rs @@ -1,20 +1,66 @@ -//! Module for anonymous pipe +//! A cross-platform anonymous pipe. //! -//! ``` -//! #![feature(anonymous_pipe)] +//! This module provides support for anonymous OS pipes, like [pipe] on Linux or [CreatePipe] on +//! Windows. +//! +//! # Behavior +//! +//! A pipe is a synchronous, unidirectional data channel between two or more processes, like an +//! interprocess [`mpsc`](crate::sync::mpsc) provided by the OS. In particular: +//! +//! * A read on a [`PipeReader`] blocks until the pipe is non-empty. +//! * A write on a [`PipeWriter`] blocks when the pipe is full. +//! * When all copies of a [`PipeWriter`] are closed, a read on the corresponding [`PipeReader`] +//! returns EOF. +//! * [`PipeReader`] can be shared, but only one process will consume the data in the pipe. +//! +//! # Capacity +//! +//! Pipe capacity is platform dependent. To quote the Linux [man page]: +//! +//! > Different implementations have different limits for the pipe capacity. Applications should +//! > not rely on a particular capacity: an application should be designed so that a reading process +//! > consumes data as soon as it is available, so that a writing process does not remain blocked. //! +//! # Examples +//! +//! ```no_run +//! #![feature(anonymous_pipe)] //! # #[cfg(miri)] fn main() {} //! # #[cfg(not(miri))] //! # fn main() -> std::io::Result<()> { -//! let (reader, writer) = std::pipe::pipe()?; +//! # use std::process::Command; +//! # use std::io::{Read, Write}; +//! let (ping_rx, mut ping_tx) = std::pipe::pipe()?; +//! let (mut pong_rx, pong_tx) = std::pipe::pipe()?; +//! +//! // Spawn a process that echoes its input. +//! let mut echo_server = Command::new("cat").stdin(ping_rx).stdout(pong_tx).spawn()?; +//! +//! ping_tx.write_all(b"hello")?; +//! // Close to unblock echo_server's reader. +//! drop(ping_tx); +//! +//! let mut buf = String::new(); +//! // Block until echo_server's writer is closed. +//! pong_rx.read_to_string(&mut buf)?; +//! assert_eq!(&buf, "hello"); +//! +//! echo_server.wait()?; //! # Ok(()) //! # } //! ``` - +//! [pipe]: https://man7.org/linux/man-pages/man2/pipe.2.html +//! [CreatePipe]: https://learn.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-createpipe +//! [man page]: https://man7.org/linux/man-pages/man7/pipe.7.html use crate::io; use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner}; /// Create anonymous pipe that is close-on-exec and blocking. +/// +/// # Examples +/// +/// See the [module-level](crate::pipe) documentation for examples. #[unstable(feature = "anonymous_pipe", issue = "127154")] #[inline] pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> { @@ -33,6 +79,58 @@ pub struct PipeWriter(pub(crate) AnonPipe); impl PipeReader { /// Create a new [`PipeReader`] instance that shares the same underlying file description. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(anonymous_pipe)] + /// # #[cfg(miri)] fn main() {} + /// # #[cfg(not(miri))] + /// # fn main() -> std::io::Result<()> { + /// # use std::fs; + /// # use std::io::Write; + /// # use std::process::Command; + /// const NUM_SLOT: u8 = 2; + /// const NUM_PROC: u8 = 5; + /// const OUTPUT: &str = "work.txt"; + /// + /// let mut jobs = vec![]; + /// let (reader, mut writer) = std::pipe::pipe()?; + /// + /// // Write NUM_SLOT characters the the pipe. + /// writer.write_all(&[b'|'; NUM_SLOT as usize])?; + /// + /// // Spawn several processes that read a character from the pipe, do some work, then + /// // write back to the pipe. When the pipe is empty, the processes block, so only + /// // NUM_SLOT processes can be working at any given time. + /// for _ in 0..NUM_PROC { + /// jobs.push( + /// Command::new("bash") + /// .args(["-c", + /// &format!( + /// "read -n 1\n\ + /// echo -n 'x' >> '{OUTPUT}'\n\ + /// echo -n '|'", + /// ), + /// ]) + /// .stdin(reader.try_clone()?) + /// .stdout(writer.try_clone()?) + /// .spawn()?, + /// ); + /// } + /// + /// // Wait for all jobs to finish. + /// for mut job in jobs { + /// job.wait()?; + /// } + /// + /// // Check our work and clean up. + /// let xs = fs::read_to_string(OUTPUT)?; + /// fs::remove_file(OUTPUT)?; + /// assert_eq!(xs, "x".repeat(NUM_PROC.into())); + /// # Ok(()) + /// # } + /// ``` #[unstable(feature = "anonymous_pipe", issue = "127154")] pub fn try_clone(&self) -> io::Result<Self> { self.0.try_clone().map(Self) @@ -41,6 +139,38 @@ impl PipeReader { impl PipeWriter { /// Create a new [`PipeWriter`] instance that shares the same underlying file description. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(anonymous_pipe)] + /// # #[cfg(miri)] fn main() {} + /// # #[cfg(not(miri))] + /// # fn main() -> std::io::Result<()> { + /// # use std::process::Command; + /// # use std::io::Read; + /// let (mut reader, writer) = std::pipe::pipe()?; + /// + /// // Spawn a process that writes to stdout and stderr. + /// let mut peer = Command::new("bash") + /// .args([ + /// "-c", + /// "echo -n foo\n\ + /// echo -n bar >&2" + /// ]) + /// .stdout(writer.try_clone()?) + /// .stderr(writer) + /// .spawn()?; + /// + /// // Read and check the result. + /// let mut msg = String::new(); + /// reader.read_to_string(&mut msg)?; + /// assert_eq!(&msg, "foobar"); + /// + /// peer.wait()?; + /// # Ok(()) + /// # } + /// ``` #[unstable(feature = "anonymous_pipe", issue = "127154")] pub fn try_clone(&self) -> io::Result<Self> { self.0.try_clone().map(Self) diff --git a/library/std/src/sys/pal/hermit/fs.rs b/library/std/src/sys/pal/hermit/fs.rs index 11862a07608..88fc4068719 100644 --- a/library/std/src/sys/pal/hermit/fs.rs +++ b/library/std/src/sys/pal/hermit/fs.rs @@ -3,7 +3,7 @@ use super::hermit_abi::{ self, DT_DIR, DT_LNK, DT_REG, DT_UNKNOWN, O_APPEND, O_CREAT, O_DIRECTORY, O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY, S_IFDIR, S_IFLNK, S_IFMT, S_IFREG, dirent64, stat as stat_struct, }; -use crate::ffi::{CStr, OsStr, OsString}; +use crate::ffi::{CStr, OsStr, OsString, c_char}; use crate::io::{self, BorrowedCursor, Error, ErrorKind, IoSlice, IoSliceMut, SeekFrom}; use crate::os::hermit::ffi::OsStringExt; use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; @@ -204,7 +204,7 @@ impl Iterator for ReadDir { // the size of dirent64. The file name is always a C string and terminated by `\0`. // Consequently, we are able to ignore the last byte. let name_bytes = - unsafe { CStr::from_ptr(&dir.d_name as *const _ as *const i8).to_bytes() }; + unsafe { CStr::from_ptr(&dir.d_name as *const _ as *const c_char).to_bytes() }; let entry = DirEntry { root: self.inner.root.clone(), ino: dir.d_ino, @@ -445,7 +445,7 @@ impl DirBuilder { pub fn mkdir(&self, path: &Path) -> io::Result<()> { run_path_with_cstr(path, &|path| { - cvt(unsafe { hermit_abi::mkdir(path.as_ptr(), self.mode.into()) }).map(|_| ()) + cvt(unsafe { hermit_abi::mkdir(path.as_ptr().cast(), self.mode.into()) }).map(|_| ()) }) } diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index f03fca60344..d833c9d632c 100644 --- a/library/std/src/sys/pal/hermit/mod.rs +++ b/library/std/src/sys/pal/hermit/mod.rs @@ -85,7 +85,7 @@ pub unsafe extern "C" fn runtime_entry( } // initialize environment - os::init_environment(env as *const *const i8); + os::init_environment(env); let result = unsafe { main(argc as isize, argv) }; diff --git a/library/std/src/sys/pal/hermit/os.rs b/library/std/src/sys/pal/hermit/os.rs index f8ea80afa43..791cdb1e57e 100644 --- a/library/std/src/sys/pal/hermit/os.rs +++ b/library/std/src/sys/pal/hermit/os.rs @@ -3,7 +3,7 @@ use core::slice::memchr; use super::hermit_abi; use crate::collections::HashMap; use crate::error::Error as StdError; -use crate::ffi::{CStr, OsStr, OsString}; +use crate::ffi::{CStr, OsStr, OsString, c_char}; use crate::marker::PhantomData; use crate::os::hermit::ffi::OsStringExt; use crate::path::{self, PathBuf}; @@ -70,7 +70,7 @@ pub fn current_exe() -> io::Result<PathBuf> { static ENV: Mutex<Option<HashMap<OsString, OsString>>> = Mutex::new(None); -pub fn init_environment(env: *const *const i8) { +pub fn init_environment(env: *const *const c_char) { let mut guard = ENV.lock().unwrap(); let map = guard.insert(HashMap::new()); diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 0cacd6e4f37..928023bd60b 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1892,12 +1892,6 @@ impl Step for Assemble { }); } - let lld_install = if builder.config.lld_enabled { - Some(builder.ensure(llvm::Lld { target: target_compiler.host })) - } else { - None - }; - let stage = target_compiler.stage; let host = target_compiler.host; let (host_info, dir_name) = if build_compiler.host == host { @@ -1958,22 +1952,11 @@ impl Step for Assemble { copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler); - if let Some(lld_install) = lld_install { - let src_exe = exe("lld", target_compiler.host); - let dst_exe = exe("rust-lld", target_compiler.host); - builder.copy_link(&lld_install.join("bin").join(src_exe), &libdir_bin.join(dst_exe)); - let self_contained_lld_dir = libdir_bin.join("gcc-ld"); - t!(fs::create_dir_all(&self_contained_lld_dir)); - let lld_wrapper_exe = builder.ensure(crate::core::build_steps::tool::LldWrapper { - compiler: build_compiler, - target: target_compiler.host, + if builder.config.lld_enabled { + builder.ensure(crate::core::build_steps::tool::LldWrapper { + build_compiler, + target_compiler, }); - for name in crate::LLD_FILE_NAMES { - builder.copy_link( - &lld_wrapper_exe, - &self_contained_lld_dir.join(exe(name, target_compiler.host)), - ); - } } if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled { diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 0c739115165..89b2d73f74a 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -471,7 +471,7 @@ impl Step for Rustc { } } - { + if builder.config.llvm_enabled(compiler.host) && builder.config.llvm_tools_enabled { let src_dir = builder.sysroot_target_bindir(compiler, host); let llvm_objcopy = exe("llvm-objcopy", compiler.host); let rust_objcopy = exe("rust-objcopy", compiler.host); diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 3cfbef27f87..04f1e10f493 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -1,8 +1,8 @@ use std::path::PathBuf; use std::{env, fs}; -use crate::core::build_steps::compile; use crate::core::build_steps::toolstate::ToolState; +use crate::core::build_steps::{compile, llvm}; use crate::core::builder; use crate::core::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step}; use crate::core::config::TargetSelection; @@ -722,21 +722,27 @@ impl Step for Cargo { #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct LldWrapper { - pub compiler: Compiler, - pub target: TargetSelection, + pub build_compiler: Compiler, + pub target_compiler: Compiler, } impl Step for LldWrapper { - type Output = PathBuf; + type Output = (); fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.never() } - fn run(self, builder: &Builder<'_>) -> PathBuf { - builder.ensure(ToolBuild { - compiler: self.compiler, - target: self.target, + fn run(self, builder: &Builder<'_>) { + if builder.config.dry_run() { + return; + } + + let target = self.target_compiler.host; + + let executable = builder.ensure(ToolBuild { + compiler: self.build_compiler, + target, tool: "lld-wrapper", mode: Mode::ToolStd, path: "src/tools/lld-wrapper", @@ -744,7 +750,22 @@ impl Step for LldWrapper { extra_features: Vec::new(), allow_features: "", cargo_args: Vec::new(), - }) + }); + + let libdir_bin = builder.sysroot_target_bindir(self.target_compiler, target); + t!(fs::create_dir_all(&libdir_bin)); + + let lld_install = builder.ensure(llvm::Lld { target }); + let src_exe = exe("lld", target); + let dst_exe = exe("rust-lld", target); + + builder.copy_link(&lld_install.join("bin").join(src_exe), &libdir_bin.join(dst_exe)); + let self_contained_lld_dir = libdir_bin.join("gcc-ld"); + t!(fs::create_dir_all(&self_contained_lld_dir)); + + for name in crate::LLD_FILE_NAMES { + builder.copy_link(&executable, &self_contained_lld_dir.join(exe(name, target))); + } } } diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 6e848628e5c..96d3162a8c5 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -1203,6 +1203,11 @@ impl Builder<'_> { // even if we're not going to output debuginfo for the crate we're currently building, // so that it'll be available when downstream consumers of std try to use it. rustflags.arg("-Zinline-mir-preserve-debug"); + + // FIXME: always pass this after the next `#[cfg(bootstrap)]` update. + if compiler.stage != 0 { + rustflags.arg("-Zmir_strip_debuginfo=locals-in-tiny-functions"); + } } Cargo { diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index c6800aedca9..22d361ff091 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1320,7 +1320,31 @@ impl Config { // Set flags. config.paths = std::mem::take(&mut flags.paths); - config.skip = flags.skip.into_iter().chain(flags.exclude).collect(); + config.skip = flags + .skip + .into_iter() + .chain(flags.exclude) + .map(|p| { + let p = if cfg!(windows) { + PathBuf::from(p.to_str().unwrap().replace('/', "\\")) + } else { + p + }; + + // Jump to top-level project path to support passing paths + // from sub directories. + let top_level_path = config.src.join(&p); + if !config.src.join(&top_level_path).exists() { + eprintln!("WARNING: '{}' does not exist.", top_level_path.display()); + } + + // Never return top-level path here as it would break `--skip` + // logic on rustc's internal test framework which is utilized + // by compiletest. + p + }) + .collect(); + config.include_default_paths = flags.include_default_paths; config.rustc_error_format = flags.rustc_error_format; config.json_output = flags.json_output; diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs index 0df00469452..4aec554b432 100644 --- a/src/bootstrap/src/utils/cc_detect.rs +++ b/src/bootstrap/src/utils/cc_detect.rs @@ -44,6 +44,16 @@ fn cc2ar(cc: &Path, target: TargetSelection) -> Option<PathBuf> { Some(PathBuf::from("ar")) } else if target.contains("vxworks") { Some(PathBuf::from("wr-ar")) + } else if target.contains("-nto-") { + if target.starts_with("i586") { + Some(PathBuf::from("ntox86-ar")) + } else if target.starts_with("aarch64") { + Some(PathBuf::from("ntoaarch64-ar")) + } else if target.starts_with("x86_64") { + Some(PathBuf::from("ntox86_64-ar")) + } else { + panic!("Unknown architecture, cannot determine archiver for Neutrino QNX"); + } } else if target.contains("android") || target.contains("-wasi") { Some(cc.parent().unwrap().join(PathBuf::from("llvm-ar"))) } else { diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index c40de76abbf..03ec77f507e 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -90,9 +90,9 @@ RUN /tmp/build-solaris-toolchain.sh sparcv9 sparcv9 solaris-sparc sun COPY host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh /tmp/ RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh -RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-23/wasi-sdk-23.0-x86_64-linux.tar.gz | \ +RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.tar.gz | \ tar -xz -ENV WASI_SDK_PATH=/tmp/wasi-sdk-23.0-x86_64-linux +ENV WASI_SDK_PATH=/tmp/wasi-sdk-25.0-x86_64-linux COPY scripts/freebsd-toolchain.sh /tmp/ RUN /tmp/freebsd-toolchain.sh i686 diff --git a/src/ci/docker/host-x86_64/test-various/Dockerfile b/src/ci/docker/host-x86_64/test-various/Dockerfile index c2f5a87b123..8d2e45ae497 100644 --- a/src/ci/docker/host-x86_64/test-various/Dockerfile +++ b/src/ci/docker/host-x86_64/test-various/Dockerfile @@ -40,9 +40,9 @@ WORKDIR / COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-23/wasi-sdk-23.0-x86_64-linux.tar.gz | \ +RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.tar.gz | \ tar -xz -ENV WASI_SDK_PATH=/wasi-sdk-23.0-x86_64-linux +ENV WASI_SDK_PATH=/wasi-sdk-25.0-x86_64-linux ENV RUST_CONFIGURE_ARGS \ --musl-root-x86_64=/usr/local/x86_64-linux-musl \ diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index f3d8a4edd6c..2341d25ff09 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -75,6 +75,7 @@ - [s390x-unknown-linux-gnu](platform-support/s390x-unknown-linux-gnu.md) - [s390x-unknown-linux-musl](platform-support/s390x-unknown-linux-musl.md) - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md) + - [sparcv9-sun-solaris](platform-support/solaris.md) - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md) - [\*-nto-qnx-\*](platform-support/nto-qnx.md) - [*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md) @@ -93,6 +94,7 @@ - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md) - [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md) - [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md) + - [x86_64-pc-solaris](platform-support/solaris.md) - [x86_64-unknown-linux-none.md](platform-support/x86_64-unknown-linux-none.md) - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md) - [xtensa-\*-none-elf](platform-support/xtensa.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 3b82d123276..c4efe27efc2 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -180,7 +180,7 @@ target | std | notes `riscv64gc-unknown-none-elf` | * | Bare RISC-V (RV64IMAFDC ISA) `riscv64imac-unknown-none-elf` | * | Bare RISC-V (RV64IMAC ISA) `sparc64-unknown-linux-gnu` | ✓ | SPARC Linux (kernel 4.4, glibc 2.23) -`sparcv9-sun-solaris` | ✓ | SPARC Solaris 11, illumos +[`sparcv9-sun-solaris`](platform-support/solaris.md) | ✓ | SPARC V9 Solaris 11.4 [`thumbv6m-none-eabi`](platform-support/thumbv6m-none-eabi.md) | * | Bare Armv6-M [`thumbv7em-none-eabi`](platform-support/thumbv7em-none-eabi.md) | * | Bare Armv7E-M [`thumbv7em-none-eabihf`](platform-support/thumbv7em-none-eabi.md) | * | Bare Armv7E-M, hardfloat @@ -201,7 +201,7 @@ target | std | notes [`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX [`x86_64-unknown-fuchsia`](platform-support/fuchsia.md) | ✓ | 64-bit x86 Fuchsia [`x86_64-linux-android`](platform-support/android.md) | ✓ | 64-bit x86 Android -`x86_64-pc-solaris` | ✓ | 64-bit Solaris 11, illumos +[`x86_64-pc-solaris`](platform-support/solaris.md) | ✓ | 64-bit x86 Solaris 11.4 [`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | 64-bit x86 MinGW (Windows 10+), LLVM ABI `x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27) [`x86_64-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | x86_64 OpenHarmony @@ -343,7 +343,7 @@ target | std | host | notes [`powerpc-unknown-openbsd`](platform-support/powerpc-unknown-openbsd.md) | * | | [`powerpc-wrs-vxworks-spe`](platform-support/vxworks.md) | ✓ | | [`powerpc-wrs-vxworks`](platform-support/vxworks.md) | ✓ | | -`powerpc64-unknown-freebsd` | ✓ | ✓ | PPC64 FreeBSD (ELFv1 and ELFv2) +`powerpc64-unknown-freebsd` | ✓ | ✓ | PPC64 FreeBSD (ELFv2) `powerpc64le-unknown-freebsd` | ✓ | ✓ | PPC64LE FreeBSD `powerpc-unknown-freebsd` | ? | | PowerPC FreeBSD `powerpc64-unknown-linux-musl` | ? | | 64-bit PowerPC Linux with musl 1.2.3 diff --git a/src/doc/rustc/src/platform-support/solaris.md b/src/doc/rustc/src/platform-support/solaris.md new file mode 100644 index 00000000000..1e0a241f840 --- /dev/null +++ b/src/doc/rustc/src/platform-support/solaris.md @@ -0,0 +1,32 @@ +# sparcv9-sun-solaris +# x86_64-pc-solaris + +**Tier: 2** + +Rust for Solaris operating system. + +## Target maintainers + +- Petr Sumbera `sumbera@volny.cz`, https://github.com/psumbera + +## Requirements + +Binary built for this target is expected to run on sparcv9 or x86_64, and Solaris 11.4. + +## Testing + +For testing you can download Oracle Solaris 11.4 CBE release from: + + https://www.oracle.com/uk/solaris/solaris11/downloads/solaris-downloads.html + +Solaris CBE release is also available for GitHub CI: + + https://github.com/vmactions/solaris-vm + +Latest Solaris 11.4 SRU can be tested at Compile farm project: + + https://portal.cfarm.net/machines/list/ (cfarm215, cfarm215) + +There are no official Rust binaries for Solaris available for Rustup yet. But you can eventually download unofficial from: + + https://github.com/psumbera/solaris-rust diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 50dfe0a1b56..25f88c8797f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1839,8 +1839,15 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T DynTrait(bounds, lifetime) } TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))), + TyKind::UnsafeBinder(..) => { + unimplemented!("unsafe binders are not supported yet") + } // Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s. - TyKind::Infer | TyKind::Err(_) | TyKind::Typeof(..) | TyKind::InferDelegation(..) => Infer, + TyKind::Infer + | TyKind::Err(_) + | TyKind::Typeof(..) + | TyKind::InferDelegation(..) + | TyKind::TraitAscription(_) => Infer, } } diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 91b31f31ab1..2c26ffa76f6 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -423,6 +423,14 @@ pub(crate) fn build_index( } Some(path) }); + } else if let Some(parent_idx) = item.parent_idx { + let i = <isize as TryInto<usize>>::try_into(parent_idx).unwrap(); + item.path = { + let p = &crate_paths[i].1; + join_with_double_colon(&p[..p.len() - 1]) + }; + item.exact_path = + crate_paths[i].2.as_ref().map(|xp| join_with_double_colon(&xp[..xp.len() - 1])); } // Omit the parent path if it is same to that of the prior item. diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index a384c286039..5d82b8e309a 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -846,11 +846,13 @@ fn main_args( let config = core::create_config(input, options, &render_options, using_internal_features); + let registered_lints = config.register_lints.is_some(); + interface::run_compiler(config, |compiler| { let sess = &compiler.sess; if sess.opts.describe_lints { - rustc_driver::describe_lints(sess); + rustc_driver::describe_lints(sess, registered_lints); return; } diff --git a/src/tools/cargo b/src/tools/cargo -Subproject 20a443231846b81c7b909691ec3f15eb173f2b1 +Subproject 769f622e12db0001431d8ae36d1093fb8727c5d diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index c300f7cd665..e3959903fdd 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -814,11 +814,13 @@ impl TyCoercionStability { | TyKind::Tup(_) | TyKind::Path(_) => Self::Deref, TyKind::OpaqueDef(..) + | TyKind::TraitAscription(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::InferDelegation(..) | TyKind::Err(_) => Self::Reborrow, + TyKind::UnsafeBinder(..) => Self::None, }; } } diff --git a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs index ed27e38ef2d..1dac7b971f9 100644 --- a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs +++ b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs @@ -63,7 +63,7 @@ impl_lint_pass!(DuplicateMod => [DUPLICATE_MOD]); impl EarlyLintPass for DuplicateMod { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, mod_spans)) = &item.kind + if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, mod_spans, _)) = &item.kind && let FileName::Real(real) = cx.sess().source_map().span_to_filename(mod_spans.inner_span) && let Some(local_path) = real.into_local_path() && let Ok(absolute_path) = local_path.canonicalize() diff --git a/src/tools/clippy/clippy_lints/src/excessive_nesting.rs b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs index ffc76366983..dfea40db182 100644 --- a/src/tools/clippy/clippy_lints/src/excessive_nesting.rs +++ b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs @@ -163,7 +163,7 @@ impl Visitor<'_> for NestingVisitor<'_, '_> { } match &item.kind { - ItemKind::Trait(_) | ItemKind::Impl(_) | ItemKind::Mod(.., ModKind::Loaded(_, Inline::Yes, _)) => { + ItemKind::Trait(_) | ItemKind::Impl(_) | ItemKind::Mod(.., ModKind::Loaded(_, Inline::Yes, _, _)) => { self.nest_level += 1; if !self.check_indent(item.span, item.id) { diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs index ed9879de13b..b679fdfadc3 100644 --- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs @@ -156,7 +156,8 @@ fn never_loop_expr<'tcx>( | ExprKind::Field(e, _) | ExprKind::AddrOf(_, _, e) | ExprKind::Repeat(e, _) - | ExprKind::DropTemps(e) => never_loop_expr(cx, e, local_labels, main_loop_id), + | ExprKind::DropTemps(e) + | ExprKind::UnsafeBinderCast(_, e, _) => never_loop_expr(cx, e, local_labels, main_loop_id), ExprKind::Let(let_expr) => never_loop_expr(cx, let_expr.init, local_labels, main_loop_id), ExprKind::Array(es) | ExprKind::Tup(es) => never_loop_expr_all(cx, es.iter(), local_labels, main_loop_id), ExprKind::MethodCall(_, receiver, es, _) => { diff --git a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs index b12f575e81a..0e08e2eb83d 100644 --- a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs +++ b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs @@ -6,8 +6,11 @@ use clippy_utils::source::SpanRangeExt; use clippy_utils::{is_from_proc_macro, path_to_local}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Constness, Expr, ExprKind}; +use rustc_hir::def::DefKind; +use rustc_hir::def_id::DefId; use rustc_lint::{LateContext, LateLintPass, Lint, LintContext}; use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::TyCtxt; use rustc_session::impl_lint_pass; declare_clippy_lint! { @@ -94,6 +97,44 @@ impl ManualFloatMethods { } } +fn is_not_const(tcx: TyCtxt<'_>, def_id: DefId) -> bool { + match tcx.def_kind(def_id) { + DefKind::Mod + | DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::Variant + | DefKind::Trait + | DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::TraitAlias + | DefKind::AssocTy + | DefKind::Macro(..) + | DefKind::Field + | DefKind::LifetimeParam + | DefKind::ExternCrate + | DefKind::Use + | DefKind::ForeignMod + | DefKind::GlobalAsm + | DefKind::Impl { .. } + | DefKind::OpaqueTy + | DefKind::SyntheticCoroutineBody + | DefKind::TyParam => true, + + DefKind::AnonConst + | DefKind::InlineConst + | DefKind::Const + | DefKind::ConstParam + | DefKind::Static { .. } + | DefKind::Ctor(..) + | DefKind::AssocConst => false, + + DefKind::Fn + | DefKind::AssocFn + | DefKind::Closure => tcx.constness(def_id) == Constness::NotConst, + } +} + impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if let ExprKind::Binary(kind, lhs, rhs) = expr.kind @@ -105,7 +146,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods { && exprs.iter_mut().partition_in_place(|i| path_to_local(i).is_some()) == 2 && !in_external_macro(cx.sess(), expr.span) && ( - matches!(cx.tcx.constness(cx.tcx.hir().enclosing_body_owner(expr.hir_id)), Constness::NotConst) + is_not_const(cx.tcx, cx.tcx.hir().enclosing_body_owner(expr.hir_id).into()) || self.msrv.meets(msrvs::CONST_FLOAT_CLASSIFY) ) && let [first, second, const_1, const_2] = exprs diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs index 3de51bc661e..5b9e9e70e47 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -3,13 +3,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::ty::is_copy; use clippy_utils::usage::mutated_variables; use clippy_utils::visitors::{Descend, for_each_expr_without_closures}; -use clippy_utils::{MaybePath, is_res_lang_ctor, is_trait_method, path_res, path_to_local_id}; +use clippy_utils::{is_res_lang_ctor, is_trait_method, path_res, path_to_local_id}; use core::ops::ControlFlow; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::LangItem::{OptionNone, OptionSome}; use rustc_lint::LateContext; -use rustc_middle::query::Key; use rustc_middle::ty; use rustc_span::sym; @@ -44,7 +43,6 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, a if name == "filter_map" && let hir::ExprKind::Call(expr, args) = body.value.kind && is_res_lang_ctor(cx, path_res(cx, expr), OptionSome) - && arg_id.ty_def_id() == args[0].hir_id().ty_def_id() && let hir::ExprKind::Path(_) = args[0].kind { span_lint_and_sugg( diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 311ed427cb9..521bf6a5fed 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -623,6 +623,9 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { kind!("DropTemps({expr})"); self.expr(expr); }, + ExprKind::UnsafeBinderCast(..) => { + unimplemented!("unsafe binders are not implemented yet"); + } } } diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 620a9b56eb5..12074dd16e6 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -379,7 +379,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { (Mod(lu, lmk), Mod(ru, rmk)) => { lu == ru && match (lmk, rmk) { - (ModKind::Loaded(litems, linline, _), ModKind::Loaded(ritems, rinline, _)) => { + (ModKind::Loaded(litems, linline, _, _), ModKind::Loaded(ritems, rinline, _, _)) => { linline == rinline && over(litems, ritems, |l, r| eq_item(l, r, eq_item_kind)) }, (ModKind::Unloaded, ModKind::Unloaded) => true, diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs index 7f0363ac942..b5bb174e737 100644 --- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs +++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs @@ -303,7 +303,8 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS | ExprKind::AddrOf(..) | ExprKind::Repeat(..) | ExprKind::Block(Block { stmts: [], .. }, _) - | ExprKind::OffsetOf(..) => (), + | ExprKind::OffsetOf(..) + | ExprKind::UnsafeBinderCast(..) => (), // Assignment might be to a local defined earlier, so don't eagerly evaluate. // Blocks with multiple statements might be expensive, so don't eagerly evaluate. diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index e318ad8671c..4b604f658b8 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -370,6 +370,10 @@ impl HirEqInterExpr<'_, '_, '_> { && self.eq_expr(l_receiver, r_receiver) && self.eq_exprs(l_args, r_args) }, + (&ExprKind::UnsafeBinderCast(lkind, le, None), &ExprKind::UnsafeBinderCast(rkind, re, None)) => + lkind == rkind && self.eq_expr(le, re), + (&ExprKind::UnsafeBinderCast(lkind, le, Some(lt)), &ExprKind::UnsafeBinderCast(rkind, re, Some(rt))) => + lkind == rkind && self.eq_expr(le, re) && self.eq_ty(lt, rt), (&ExprKind::OffsetOf(l_container, l_fields), &ExprKind::OffsetOf(r_container, r_fields)) => { self.eq_ty(l_container, r_container) && over(l_fields, r_fields, |l, r| l.name == r.name) }, @@ -424,6 +428,7 @@ impl HirEqInterExpr<'_, '_, '_> { | &ExprKind::Type(..) | &ExprKind::Unary(..) | &ExprKind::Yield(..) + | &ExprKind::UnsafeBinderCast(..) // --- Special cases that do not have a positive branch. @@ -1032,6 +1037,13 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { std::mem::discriminant(&lop).hash(&mut self.s); self.hash_expr(le); }, + ExprKind::UnsafeBinderCast(kind, expr, ty) => { + std::mem::discriminant(&kind).hash(&mut self.s); + self.hash_expr(expr); + if let Some(ty) = ty { + self.hash_ty(ty); + } + } ExprKind::Err(_) => {}, } } @@ -1241,11 +1253,15 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { TyKind::Typeof(anon_const) => { self.hash_body(anon_const.body); }, + TyKind::UnsafeBinder(binder) => { + self.hash_ty(binder.inner_ty); + } TyKind::Err(_) | TyKind::Infer | TyKind::Never | TyKind::InferDelegation(..) - | TyKind::OpaqueDef(_) => {}, + | TyKind::OpaqueDef(_) + | TyKind::TraitAscription(_) => {}, } } diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index 25ebe879192..088abd7c479 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -151,7 +151,8 @@ impl<'a> Sugg<'a> { | ExprKind::Become(..) | ExprKind::Struct(..) | ExprKind::Tup(..) - | ExprKind::Err(_) => Sugg::NonParen(get_snippet(expr.span)), + | ExprKind::Err(_) + | ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(get_snippet(expr.span)), ExprKind::DropTemps(inner) => Self::hir_from_snippet(inner, get_snippet), ExprKind::Assign(lhs, rhs, _) => { Sugg::BinOp(AssocOp::Assign, get_snippet(lhs.span), get_snippet(rhs.span)) @@ -226,7 +227,8 @@ impl<'a> Sugg<'a> { | ast::ExprKind::While(..) | ast::ExprKind::Await(..) | ast::ExprKind::Err(_) - | ast::ExprKind::Dummy => Sugg::NonParen(snippet(expr.span)), + | ast::ExprKind::Dummy + | ast::ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(snippet(expr.span)), ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::HalfOpen) => Sugg::BinOp( AssocOp::DotDot, lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)), diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs index 351e619d7b1..ff58c6358ba 100644 --- a/src/tools/clippy/clippy_utils/src/visitors.rs +++ b/src/tools/clippy/clippy_utils/src/visitors.rs @@ -694,6 +694,7 @@ pub fn for_each_unconsumed_temporary<'tcx, B>( | ExprKind::Continue(_) | ExprKind::InlineAsm(_) | ExprKind::OffsetOf(..) + | ExprKind::UnsafeBinderCast(..) | ExprKind::Err(_) => (), } ControlFlow::Continue(()) diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr index 062bf25ea62..ee2868869de 100644 --- a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr @@ -20,7 +20,6 @@ LL | | fn clone_self(&self) -> Self { LL | | Self { LL | | a: true, ... | -LL | | } LL | | } | |_^ | @@ -32,7 +31,6 @@ LL | | fn default() -> Self { LL | | Self { LL | | a: true, ... | -LL | | } LL | | } | |_^ diff --git a/src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.stderr b/src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.stderr index ccdaecdd481..9cf6fc66757 100644 --- a/src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.stderr +++ b/src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.stderr @@ -66,8 +66,7 @@ error: this block is too nested LL | if true { | _________________________^ LL | | if true { -LL | | -LL | | } +... | LL | | } | |_________________^ | diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr index a44c810b135..9677beeb2c2 100644 --- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr +++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr @@ -286,7 +286,6 @@ LL | | if unsafe { true } { LL | | todo!(); LL | | } else { ... | -LL | | } LL | | }; | |______^ | diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr index db5ea5b6289..0eccdd42800 100644 --- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr +++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr @@ -294,7 +294,6 @@ LL | | if unsafe { true } { LL | | todo!(); LL | | } else { ... | -LL | | } LL | | }; | |______^ | diff --git a/src/tools/clippy/tests/ui/async_yields_async.stderr b/src/tools/clippy/tests/ui/async_yields_async.stderr index c900a9d7421..474914299d0 100644 --- a/src/tools/clippy/tests/ui/async_yields_async.stderr +++ b/src/tools/clippy/tests/ui/async_yields_async.stderr @@ -80,7 +80,6 @@ error: an async construct yields a type which is itself awaitable LL | let _m = async || { | _______________________- LL | | println!("I'm bored"); -LL | | // Some more stuff ... | LL | | CustomFutureType | | ^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.stderr b/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.stderr index 2adaecc96d6..d271381adea 100644 --- a/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.stderr +++ b/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.stderr @@ -44,7 +44,6 @@ LL | | if { LL | | if s == "43" { LL | | return Some(43); ... | -LL | | } LL | | }); | |______^ | diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr index 68ebb6ad781..36b17773973 100644 --- a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr +++ b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr @@ -115,8 +115,7 @@ error: all if blocks contain the same code at the end --> tests/ui/branches_sharing_code/shared_at_bottom.rs:183:5 | LL | / x << 2 -LL | | -LL | | +... | LL | | }; | |_____^ | @@ -131,8 +130,7 @@ error: all if blocks contain the same code at the end --> tests/ui/branches_sharing_code/shared_at_bottom.rs:192:5 | LL | / x * 4 -LL | | -LL | | +... | LL | | } | |_____^ | diff --git a/src/tools/clippy/tests/ui/collapsible_else_if.stderr b/src/tools/clippy/tests/ui/collapsible_else_if.stderr index 395c2dcf68d..45566a78bd8 100644 --- a/src/tools/clippy/tests/ui/collapsible_else_if.stderr +++ b/src/tools/clippy/tests/ui/collapsible_else_if.stderr @@ -43,9 +43,7 @@ LL | } else { | ____________^ LL | | if y == "world" { LL | | println!("world") -LL | | } ... | -LL | | } LL | | } | |_____^ | @@ -66,9 +64,7 @@ LL | } else { | ____________^ LL | | if let Some(42) = Some(42) { LL | | println!("world") -LL | | } ... | -LL | | } LL | | } | |_____^ | @@ -89,9 +85,7 @@ LL | } else { | ____________^ LL | | if let Some(42) = Some(42) { LL | | println!("world") -LL | | } ... | -LL | | } LL | | } | |_____^ | @@ -112,9 +106,7 @@ LL | } else { | ____________^ LL | | if x == "hello" { LL | | println!("world") -LL | | } ... | -LL | | } LL | | } | |_____^ | @@ -135,9 +127,7 @@ LL | } else { | ____________^ LL | | if let Some(42) = Some(42) { LL | | println!("world") -LL | | } ... | -LL | | } LL | | } | |_____^ | diff --git a/src/tools/clippy/tests/ui/copy_iterator.stderr b/src/tools/clippy/tests/ui/copy_iterator.stderr index 990b1ce628d..2f6378a85fe 100644 --- a/src/tools/clippy/tests/ui/copy_iterator.stderr +++ b/src/tools/clippy/tests/ui/copy_iterator.stderr @@ -6,7 +6,6 @@ LL | | LL | | LL | | type Item = u8; ... | -LL | | } LL | | } | |_^ | diff --git a/src/tools/clippy/tests/ui/crashes/ice-360.stderr b/src/tools/clippy/tests/ui/crashes/ice-360.stderr index 50b245c65cd..9961eb21485 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-360.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-360.stderr @@ -2,11 +2,7 @@ error: this loop never actually loops --> tests/ui/crashes/ice-360.rs:5:5 | LL | / loop { -LL | | -LL | | -LL | | ... | -LL | | LL | | } | |_____^ | @@ -16,11 +12,7 @@ error: this loop could be written as a `while let` loop --> tests/ui/crashes/ice-360.rs:5:5 | LL | / loop { -LL | | -LL | | -LL | | ... | -LL | | LL | | } | |_____^ help: try: `while let Some(ele) = iter.next() { .. }` | diff --git a/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr b/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr index 7d7922ae8ca..bcc8684f7c2 100644 --- a/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr +++ b/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr @@ -2,8 +2,7 @@ error: this looks like you are trying to swap `a` and `b` --> tests/ui/crate_level_checks/no_std_swap.rs:12:5 | LL | / a = b; -LL | | -LL | | +... | LL | | b = a; | |_________^ help: try: `core::mem::swap(&mut a, &mut b)` | diff --git a/src/tools/clippy/tests/ui/derivable_impls.stderr b/src/tools/clippy/tests/ui/derivable_impls.stderr index c22569145bd..0caea892358 100644 --- a/src/tools/clippy/tests/ui/derivable_impls.stderr +++ b/src/tools/clippy/tests/ui/derivable_impls.stderr @@ -6,7 +6,6 @@ LL | | fn default() -> Self { LL | | Self { LL | | a: false, ... | -LL | | } LL | | } | |_^ | diff --git a/src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr b/src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr index 2852e26680f..c5d5f3d3759 100644 --- a/src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr +++ b/src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr @@ -99,8 +99,7 @@ LL | / /// for OldA LL | | // struct OldA; LL | | LL | | /// Docs -LL | | /// for OldB -LL | | // struct OldB; +... | LL | | | |_^ ... diff --git a/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.stderr b/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.stderr index 75fc23e9e7e..a95306e2fa3 100644 --- a/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.stderr +++ b/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.stderr @@ -103,8 +103,7 @@ error: empty lines after outer attribute --> tests/ui/empty_line_after/outer_attribute.rs:64:1 | LL | / #[allow(unused)] -LL | | -LL | | // This comment is isolated +... | LL | | | |_^ LL | pub fn isolated_comment() {} diff --git a/src/tools/clippy/tests/ui/entry.stderr b/src/tools/clippy/tests/ui/entry.stderr index fb467676606..4b6bd3b4a25 100644 --- a/src/tools/clippy/tests/ui/entry.stderr +++ b/src/tools/clippy/tests/ui/entry.stderr @@ -16,8 +16,7 @@ LL | / if !m.contains_key(&k) { LL | | if true { LL | | m.insert(k, v); LL | | } else { -LL | | m.insert(k, v2); -LL | | } +... | LL | | } | |_____^ | @@ -63,7 +62,6 @@ LL | | if true { LL | | m.insert(k, v); LL | | } else { ... | -LL | | } LL | | } | |_____^ | @@ -154,7 +152,6 @@ LL | | foo(); LL | | match 0 { LL | | 0 if false => { ... | -LL | | } LL | | } | |_____^ | diff --git a/src/tools/clippy/tests/ui/enum_variants.stderr b/src/tools/clippy/tests/ui/enum_variants.stderr index aaac3cbb82d..ecca6c833ac 100644 --- a/src/tools/clippy/tests/ui/enum_variants.stderr +++ b/src/tools/clippy/tests/ui/enum_variants.stderr @@ -13,7 +13,6 @@ error: all variants have the same prefix: `c` LL | / enum Foo { LL | | LL | | cFoo, -LL | | ... | LL | | cBaz, LL | | } @@ -45,9 +44,7 @@ error: all variants have the same prefix: `Food` LL | / enum Food { LL | | LL | | FoodGood, -LL | | ... | -LL | | LL | | } | |_^ | diff --git a/src/tools/clippy/tests/ui/fallible_impl_from.stderr b/src/tools/clippy/tests/ui/fallible_impl_from.stderr index 62496148924..cc3739031b7 100644 --- a/src/tools/clippy/tests/ui/fallible_impl_from.stderr +++ b/src/tools/clippy/tests/ui/fallible_impl_from.stderr @@ -29,7 +29,6 @@ LL | | LL | | fn from(i: usize) -> Invalid { LL | | if i != 42 { ... | -LL | | } LL | | } | |_^ | @@ -49,7 +48,6 @@ LL | | LL | | fn from(s: Option<String>) -> Invalid { LL | | let s = s.unwrap(); ... | -LL | | } LL | | } | |_^ | @@ -76,7 +74,6 @@ LL | | LL | | fn from(s: &'a mut <Box<u32> as ProjStrTrait>::ProjString) -> Invalid { LL | | if s.parse::<u32>().ok().unwrap() != 42 { ... | -LL | | } LL | | } | |_^ | diff --git a/src/tools/clippy/tests/ui/if_same_then_else2.stderr b/src/tools/clippy/tests/ui/if_same_then_else2.stderr index 93507eb2c6f..369d6f66737 100644 --- a/src/tools/clippy/tests/ui/if_same_then_else2.stderr +++ b/src/tools/clippy/tests/ui/if_same_then_else2.stderr @@ -7,7 +7,6 @@ LL | | for _ in &[42] { LL | | let foo: &Option<_> = &Some::<u8>(42); LL | | if foo.is_some() { ... | -LL | | } LL | | } else { | |_____^ | @@ -20,7 +19,6 @@ LL | | for _ in &[42] { LL | | let bar: &Option<_> = &Some::<u8>(42); LL | | if bar.is_some() { ... | -LL | | } LL | | } | |_____^ = note: `-D clippy::if-same-then-else` implied by `-D warnings` diff --git a/src/tools/clippy/tests/ui/infinite_loops.stderr b/src/tools/clippy/tests/ui/infinite_loops.stderr index 7635a7442f4..3b5705d5f21 100644 --- a/src/tools/clippy/tests/ui/infinite_loops.stderr +++ b/src/tools/clippy/tests/ui/infinite_loops.stderr @@ -20,7 +20,6 @@ error: infinite loop detected LL | / loop { LL | | LL | | loop { -LL | | ... | LL | | do_something(); LL | | } @@ -37,9 +36,7 @@ error: infinite loop detected LL | / loop { LL | | LL | | loop { -LL | | -LL | | do_something(); -LL | | } +... | LL | | } | |_________^ | @@ -79,8 +76,7 @@ error: infinite loop detected LL | / loop { LL | | fn inner_fn() -> ! { LL | | std::process::exit(0); -LL | | } -LL | | do_something(); +... | LL | | } | |_____^ | @@ -97,7 +93,6 @@ LL | | LL | | loop { LL | | if cond { ... | -LL | | } LL | | } | |_____^ | @@ -114,7 +109,6 @@ LL | | LL | | 'inner: loop { LL | | loop { ... | -LL | | } LL | | } | |_____^ | @@ -145,7 +139,6 @@ LL | | LL | | 'inner: loop { LL | | loop { ... | -LL | | } LL | | } | |_________^ | @@ -162,7 +155,6 @@ LL | | LL | | match opt { LL | | Some(v) => { ... | -LL | | } LL | | } | |_____^ | @@ -279,7 +271,6 @@ LL | | LL | | 'inner: loop { LL | | loop { ... | -LL | | } LL | | } | |_____^ | diff --git a/src/tools/clippy/tests/ui/into_iter_without_iter.stderr b/src/tools/clippy/tests/ui/into_iter_without_iter.stderr index 533a7f68593..cde1b60c2ab 100644 --- a/src/tools/clippy/tests/ui/into_iter_without_iter.stderr +++ b/src/tools/clippy/tests/ui/into_iter_without_iter.stderr @@ -6,7 +6,6 @@ LL | | LL | | type IntoIter = std::slice::Iter<'a, u8>; LL | | type Item = &'a u8; ... | -LL | | } LL | | } | |_^ | @@ -30,7 +29,6 @@ LL | | LL | | type IntoIter = std::slice::IterMut<'a, u8>; LL | | type Item = &'a mut u8; ... | -LL | | } LL | | } | |_^ | @@ -52,7 +50,6 @@ LL | | LL | | type IntoIter = std::slice::Iter<'a, T>; LL | | type Item = &'a T; ... | -LL | | } LL | | } | |_^ | @@ -74,7 +71,6 @@ LL | | LL | | type IntoIter = std::slice::IterMut<'a, T>; LL | | type Item = &'a mut T; ... | -LL | | } LL | | } | |_^ | @@ -96,7 +92,6 @@ LL | | LL | | type IntoIter = std::slice::IterMut<'a, T>; LL | | type Item = &'a mut T; ... | -LL | | } LL | | } | |_^ | @@ -117,8 +112,7 @@ LL | / impl<'a> IntoIterator for &'a Issue12037 { LL | | type IntoIter = std::slice::Iter<'a, u8>; LL | | type Item = &'a u8; LL | | fn into_iter(self) -> Self::IntoIter { -LL | | todo!() -LL | | } +... | LL | | } | |_________^ ... diff --git a/src/tools/clippy/tests/ui/manual_find.stderr b/src/tools/clippy/tests/ui/manual_find.stderr index eb55a0c11f2..a4e7878a247 100644 --- a/src/tools/clippy/tests/ui/manual_find.stderr +++ b/src/tools/clippy/tests/ui/manual_find.stderr @@ -6,7 +6,6 @@ LL | | LL | | LL | | if s == String::new() { ... | -LL | | } LL | | None | |________^ help: replace with an iterator: `strings.into_iter().find(|s| s == String::new())` | @@ -22,7 +21,6 @@ LL | | LL | | LL | | if s == String::new() { ... | -LL | | } LL | | None | |________^ help: replace with an iterator: `arr.into_iter().map(|(s, _)| s).find(|s| s == String::new())` | diff --git a/src/tools/clippy/tests/ui/manual_find_fixable.stderr b/src/tools/clippy/tests/ui/manual_find_fixable.stderr index c3f48fb9f98..5ed8be1b3ee 100644 --- a/src/tools/clippy/tests/ui/manual_find_fixable.stderr +++ b/src/tools/clippy/tests/ui/manual_find_fixable.stderr @@ -4,8 +4,7 @@ error: manual implementation of `Iterator::find` LL | / for &v in ARRAY { LL | | if v == n { LL | | return Some(v); -LL | | } -LL | | } +... | LL | | None | |________^ help: replace with an iterator: `ARRAY.iter().find(|&&v| v == n).copied()` | @@ -18,8 +17,7 @@ error: manual implementation of `Iterator::find` LL | / for (a, _) in arr { LL | | if a % 2 == 0 { LL | | return Some(a); -LL | | } -LL | | } +... | LL | | None | |________^ help: replace with an iterator: `arr.into_iter().map(|(a, _)| a).find(|&a| a % 2 == 0)` @@ -29,8 +27,7 @@ error: manual implementation of `Iterator::find` LL | / for el in arr { LL | | if el.name.len() == 10 { LL | | return Some(el); -LL | | } -LL | | } +... | LL | | None | |________^ help: replace with an iterator: `arr.into_iter().find(|el| el.name.len() == 10)` | @@ -42,8 +39,7 @@ error: manual implementation of `Iterator::find` LL | / for Tuple(a, _) in arr { LL | | if a >= 3 { LL | | return Some(a); -LL | | } -LL | | } +... | LL | | None | |________^ help: replace with an iterator: `arr.into_iter().map(|Tuple(a, _)| a).find(|&a| a >= 3)` @@ -53,8 +49,7 @@ error: manual implementation of `Iterator::find` LL | / for el in arr { LL | | if el.should_keep() { LL | | return Some(el); -LL | | } -LL | | } +... | LL | | None | |________^ help: replace with an iterator: `arr.into_iter().find(|el| el.should_keep())` | @@ -66,8 +61,7 @@ error: manual implementation of `Iterator::find` LL | / for el in arr { LL | | if f(el) == 20 { LL | | return Some(el); -LL | | } -LL | | } +... | LL | | None | |________^ help: replace with an iterator: `arr.into_iter().find(|&el| f(el) == 20)` @@ -77,8 +71,7 @@ error: manual implementation of `Iterator::find` LL | / for &el in arr.values() { LL | | if f(el) { LL | | return Some(el); -LL | | } -LL | | } +... | LL | | None | |________^ help: replace with an iterator: `arr.values().find(|&&el| f(el)).copied()` @@ -88,8 +81,7 @@ error: manual implementation of `Iterator::find` LL | / for el in arr { LL | | if el.is_true { LL | | return Some(el); -LL | | } -LL | | } +... | LL | | None | |________^ help: replace with an iterator: `arr.into_iter().find(|el| el.is_true)` | @@ -101,8 +93,7 @@ error: manual implementation of `Iterator::find` LL | / for (_, &x) in v { LL | | if x > 10 { LL | | return Some(x); -LL | | } -LL | | } +... | LL | | None | |________^ help: replace with an iterator: `v.into_iter().map(|(_, &x)| x).find(|&x| x > 10)` @@ -112,8 +103,7 @@ error: manual implementation of `Iterator::find` LL | / for &(_, &x) in v { LL | | if x > 10 { LL | | return Some(x); -LL | | } -LL | | } +... | LL | | None | |________^ help: replace with an iterator: `v.iter().map(|&(_, &x)| x).find(|&x| x > 10)` @@ -123,8 +113,7 @@ error: manual implementation of `Iterator::find` LL | / for x in arr { LL | | if x >= 5 { LL | | return Some(x); -LL | | } -LL | | } +... | LL | | return None; | |________________^ help: replace with an iterator: `arr.into_iter().find(|&x| x >= 5)` @@ -134,8 +123,7 @@ error: manual implementation of `Iterator::find` LL | / for x in arr { LL | | if x < 1 { LL | | return Some(x); -LL | | } -LL | | } +... | LL | | None | |____________^ help: replace with an iterator: `arr.into_iter().find(|&x| x < 1)` diff --git a/src/tools/clippy/tests/ui/manual_flatten.stderr b/src/tools/clippy/tests/ui/manual_flatten.stderr index 3b64d9ef859..cf1b0a1c8bb 100644 --- a/src/tools/clippy/tests/ui/manual_flatten.stderr +++ b/src/tools/clippy/tests/ui/manual_flatten.stderr @@ -184,7 +184,6 @@ LL | | LL | | Some(1), LL | | Some(2), ... | -LL | | } LL | | } | |_____^ | diff --git a/src/tools/clippy/tests/ui/manual_let_else.stderr b/src/tools/clippy/tests/ui/manual_let_else.stderr index 55a410982ad..dcd5d456111 100644 --- a/src/tools/clippy/tests/ui/manual_let_else.stderr +++ b/src/tools/clippy/tests/ui/manual_let_else.stderr @@ -148,7 +148,6 @@ LL | | LL | | v_some LL | | } else { ... | -LL | | } LL | | }; | |______^ | @@ -175,7 +174,6 @@ LL | | LL | | v_some LL | | } else { ... | -LL | | } LL | | }; | |______^ | @@ -197,7 +195,6 @@ LL | | LL | | v_some LL | | } else { ... | -LL | | } LL | | }; | |______^ | @@ -306,7 +303,6 @@ LL | | LL | | v_some LL | | } else { ... | -LL | | } LL | | }; | |______^ | diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or.stderr b/src/tools/clippy/tests/ui/manual_unwrap_or.stderr index c93a8952a08..a5a64ecb9a3 100644 --- a/src/tools/clippy/tests/ui/manual_unwrap_or.stderr +++ b/src/tools/clippy/tests/ui/manual_unwrap_or.stderr @@ -36,7 +36,6 @@ LL | | Some(i) => i, LL | | None => { LL | | 42 + 42 ... | -LL | | } LL | | }; | |_____^ | @@ -130,7 +129,6 @@ LL | | Ok(i) => i, LL | | Err(_) => { LL | | 42 + 42 ... | -LL | | } LL | | }; | |_____^ | diff --git a/src/tools/clippy/tests/ui/map_flatten_fixable.stderr b/src/tools/clippy/tests/ui/map_flatten_fixable.stderr index 128c95146aa..095bee52d6d 100644 --- a/src/tools/clippy/tests/ui/map_flatten_fixable.stderr +++ b/src/tools/clippy/tests/ui/map_flatten_fixable.stderr @@ -77,9 +77,6 @@ error: called `map(..).flatten()` on `Option` | LL | .map(|_| { | __________^ -LL | | // we need some newlines -LL | | // so that the span is big enough -LL | | // for a split output of the diagnostic ... | LL | | }) LL | | .flatten(); diff --git a/src/tools/clippy/tests/ui/match_bool.stderr b/src/tools/clippy/tests/ui/match_bool.stderr index 1303e082daf..fb24e67ecee 100644 --- a/src/tools/clippy/tests/ui/match_bool.stderr +++ b/src/tools/clippy/tests/ui/match_bool.stderr @@ -75,9 +75,6 @@ error: you seem to be trying to match on a boolean expression --> tests/ui/match_bool.rs:36:5 | LL | / match test && test { -LL | | -LL | | -LL | | ... | LL | | _ => (), LL | | }; diff --git a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr index 201b977e558..ffe5772ece9 100644 --- a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr +++ b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr @@ -68,8 +68,7 @@ LL | let _ans = match x { | ____________________^ LL | | E::A(_) => { LL | | true -LL | | } -LL | | E::B(_) => true, +... | LL | | _ => false, LL | | }; | |_________^ help: try: `matches!(x, E::A(_) | E::B(_))` diff --git a/src/tools/clippy/tests/ui/missing_doc.stderr b/src/tools/clippy/tests/ui/missing_doc.stderr index 133c76ac9d4..6554eed1610 100644 --- a/src/tools/clippy/tests/ui/missing_doc.stderr +++ b/src/tools/clippy/tests/ui/missing_doc.stderr @@ -72,7 +72,6 @@ LL | | /// dox LL | | pub fn documented() {} LL | | pub fn undocumented1() {} ... | -LL | | } LL | | } | |_^ diff --git a/src/tools/clippy/tests/ui/missing_doc_crate_missing.stderr b/src/tools/clippy/tests/ui/missing_doc_crate_missing.stderr index a421fb986d3..d6a4342c503 100644 --- a/src/tools/clippy/tests/ui/missing_doc_crate_missing.stderr +++ b/src/tools/clippy/tests/ui/missing_doc_crate_missing.stderr @@ -2,9 +2,7 @@ error: missing documentation for the crate --> tests/ui/missing_doc_crate_missing.rs:1:1 | LL | / #![warn(clippy::missing_docs_in_private_items)] -LL | | -LL | | -LL | | +... | LL | | fn main() {} | |____________^ | diff --git a/src/tools/clippy/tests/ui/missing_fields_in_debug.stderr b/src/tools/clippy/tests/ui/missing_fields_in_debug.stderr index 8c1810909dd..5e51194c4b3 100644 --- a/src/tools/clippy/tests/ui/missing_fields_in_debug.stderr +++ b/src/tools/clippy/tests/ui/missing_fields_in_debug.stderr @@ -6,7 +6,6 @@ LL | | LL | | // unused field: hidden LL | | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { ... | -LL | | } LL | | } | |_^ | @@ -28,7 +27,6 @@ LL | | LL | | // unused fields: hidden, hidden2, hidden4 LL | | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { ... | -LL | | } LL | | } | |_^ | @@ -58,7 +56,6 @@ LL | | LL | | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { LL | | let mut f = formatter.debug_struct("MultiExprDebugImpl"); ... | -LL | | } LL | | } | |_^ | diff --git a/src/tools/clippy/tests/ui/needless_for_each_unfixable.stderr b/src/tools/clippy/tests/ui/needless_for_each_unfixable.stderr index 9d3f639efbf..682140a1dfd 100644 --- a/src/tools/clippy/tests/ui/needless_for_each_unfixable.stderr +++ b/src/tools/clippy/tests/ui/needless_for_each_unfixable.stderr @@ -6,7 +6,6 @@ LL | | LL | | LL | | if *v == 10 { ... | -LL | | } LL | | }); | |_______^ | diff --git a/src/tools/clippy/tests/ui/needless_if.stderr b/src/tools/clippy/tests/ui/needless_if.stderr index 9beae596ee3..cbfeb979d2f 100644 --- a/src/tools/clippy/tests/ui/needless_if.stderr +++ b/src/tools/clippy/tests/ui/needless_if.stderr @@ -34,7 +34,6 @@ error: this `if` branch is empty LL | / if { LL | | if let true = true LL | | && true -LL | | { ... | LL | | } && true LL | | {} diff --git a/src/tools/clippy/tests/ui/never_loop.stderr b/src/tools/clippy/tests/ui/never_loop.stderr index 440a2b5aaba..dab3488af10 100644 --- a/src/tools/clippy/tests/ui/never_loop.stderr +++ b/src/tools/clippy/tests/ui/never_loop.stderr @@ -2,9 +2,6 @@ error: this loop never actually loops --> tests/ui/never_loop.rs:12:5 | LL | / loop { -LL | | -LL | | -LL | | // clippy::never_loop ... | LL | | break; LL | | } @@ -75,7 +72,6 @@ LL | | LL | | // never loops LL | | match x { ... | -LL | | } LL | | } | |_____^ | @@ -126,7 +122,6 @@ LL | | LL | | 'b: { LL | | break 'b 'c: { ... | -LL | | } LL | | } | |_____^ diff --git a/src/tools/clippy/tests/ui/option_if_let_else.stderr b/src/tools/clippy/tests/ui/option_if_let_else.stderr index 37ef791edb0..32ff2276323 100644 --- a/src/tools/clippy/tests/ui/option_if_let_else.stderr +++ b/src/tools/clippy/tests/ui/option_if_let_else.stderr @@ -115,8 +115,7 @@ LL | let _ = if let Some(x) = arg { | _____________^ LL | | x LL | | } else { -LL | | // map_or_else must be suggested -LL | | side_effect() +... | LL | | }; | |_____^ help: try: `arg.map_or_else(side_effect, |x| x)` diff --git a/src/tools/clippy/tests/ui/question_mark.stderr b/src/tools/clippy/tests/ui/question_mark.stderr index 0a48c4e80cb..06a8bd0de34 100644 --- a/src/tools/clippy/tests/ui/question_mark.stderr +++ b/src/tools/clippy/tests/ui/question_mark.stderr @@ -183,8 +183,7 @@ error: this block may be rewritten with the `?` operator | LL | / if a.is_none() { LL | | return None; -LL | | // do lint here, the outer `try` is not relevant here -LL | | // https://github.com/rust-lang/rust-clippy/pull/11001#issuecomment-1610636867 +... | LL | | } | |_____________^ help: replace it with: `a?;` diff --git a/src/tools/clippy/tests/ui/significant_drop_tightening.stderr b/src/tools/clippy/tests/ui/significant_drop_tightening.stderr index 2d7da4f394d..7d7e3ac7d0a 100644 --- a/src/tools/clippy/tests/ui/significant_drop_tightening.stderr +++ b/src/tools/clippy/tests/ui/significant_drop_tightening.stderr @@ -5,8 +5,7 @@ LL | pub fn complex_return_triggers_the_lint() -> i32 { | __________________________________________________- LL | | fn foo() -> i32 { LL | | 1 -LL | | } -LL | | let mutex = Mutex::new(1); +... | LL | | let lock = mutex.lock().unwrap(); | | ^^^^ ... | diff --git a/src/tools/clippy/tests/ui/single_match.stderr b/src/tools/clippy/tests/ui/single_match.stderr index 9240b09c50a..dd03737279a 100644 --- a/src/tools/clippy/tests/ui/single_match.stderr +++ b/src/tools/clippy/tests/ui/single_match.stderr @@ -22,10 +22,7 @@ error: you seem to be trying to use `match` for destructuring a single pattern. --> tests/ui/single_match.rs:23:5 | LL | / match x { -LL | | // Note the missing block braces. -LL | | // We suggest `if let Some(y) = x { .. }` because the macro -LL | | // is expanded before we can do anything. -LL | | Some(y) => println!("{:?}", y), +... | LL | | _ => (), LL | | } | |_____^ help: try: `if let Some(y) = x { println!("{:?}", y) }` diff --git a/src/tools/clippy/tests/ui/single_match_else.stderr b/src/tools/clippy/tests/ui/single_match_else.stderr index a2801751a43..aa494520b84 100644 --- a/src/tools/clippy/tests/ui/single_match_else.stderr +++ b/src/tools/clippy/tests/ui/single_match_else.stderr @@ -68,8 +68,7 @@ LL | / match Result::<i32, &Infallible>::Ok(1) { LL | | Ok(a) => println!("${:?}", a), LL | | Err(_) => { LL | | println!("else block"); -LL | | return; -LL | | } +... | LL | | } | |_____^ | @@ -88,8 +87,7 @@ LL | / match Cow::from("moo") { LL | | Cow::Owned(a) => println!("${:?}", a), LL | | Cow::Borrowed(_) => { LL | | println!("else block"); -LL | | return; -LL | | } +... | LL | | } | |_____^ | diff --git a/src/tools/clippy/tests/ui/temporary_assignment.stderr b/src/tools/clippy/tests/ui/temporary_assignment.stderr index 8c284594075..7e6529cb213 100644 --- a/src/tools/clippy/tests/ui/temporary_assignment.stderr +++ b/src/tools/clippy/tests/ui/temporary_assignment.stderr @@ -13,8 +13,7 @@ error: assignment to temporary LL | / MultiStruct { LL | | LL | | structure: Struct { field: 0 }, -LL | | } -LL | | .structure +... | LL | | .field = 1; | |______________^ diff --git a/src/tools/clippy/tests/ui/unit_cmp.stderr b/src/tools/clippy/tests/ui/unit_cmp.stderr index f9473d3be26..9e067edb846 100644 --- a/src/tools/clippy/tests/ui/unit_cmp.stderr +++ b/src/tools/clippy/tests/ui/unit_cmp.stderr @@ -34,7 +34,6 @@ LL | | LL | | { LL | | true; ... | -LL | | } LL | | ); | |_____^ @@ -46,7 +45,6 @@ LL | | LL | | { LL | | true; ... | -LL | | } LL | | ); | |_____^ @@ -58,7 +56,6 @@ LL | | LL | | { LL | | true; ... | -LL | | } LL | | ); | |_____^ @@ -70,7 +67,6 @@ LL | | LL | | { LL | | true; ... | -LL | | } LL | | ); | |_____^ diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr index bcdf65b217e..35a2144c389 100644 --- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr @@ -434,11 +434,7 @@ error: unnecessary closure used to substitute value for `Result::Err` | LL | let _: Result<usize, usize> = res. | ___________________________________^ -LL | | // some lines -LL | | // some lines -LL | | // some lines ... | -LL | | // some lines LL | | or_else(|_| Ok(ext_str.some_field)); | |_______________________________________^ | diff --git a/src/tools/clippy/tests/ui/unnecessary_wraps.stderr b/src/tools/clippy/tests/ui/unnecessary_wraps.stderr index 59986d895b3..b304d4dce6e 100644 --- a/src/tools/clippy/tests/ui/unnecessary_wraps.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_wraps.stderr @@ -6,7 +6,6 @@ LL | | LL | | LL | | if a && b { ... | -LL | | } LL | | } | |_^ | @@ -112,7 +111,6 @@ LL | | LL | | if a && b { LL | | return Some(()); ... | -LL | | } LL | | } | |_^ | @@ -139,7 +137,6 @@ LL | | LL | | if a && b { LL | | return Ok(()); ... | -LL | | } LL | | } | |_^ | diff --git a/src/tools/clippy/tests/ui/unwrap_in_result.stderr b/src/tools/clippy/tests/ui/unwrap_in_result.stderr index 752177aaca5..201d4ae36ae 100644 --- a/src/tools/clippy/tests/ui/unwrap_in_result.stderr +++ b/src/tools/clippy/tests/ui/unwrap_in_result.stderr @@ -6,7 +6,6 @@ LL | | LL | | // checks whether a string represents a number divisible by 3 LL | | let i = i_str.parse::<i32>().unwrap(); ... | -LL | | } LL | | } | |_____^ | diff --git a/src/tools/clippy/tests/ui/vec_init_then_push.stderr b/src/tools/clippy/tests/ui/vec_init_then_push.stderr index 58720c9a181..f35625c9b08 100644 --- a/src/tools/clippy/tests/ui/vec_init_then_push.stderr +++ b/src/tools/clippy/tests/ui/vec_init_then_push.stderr @@ -2,8 +2,7 @@ error: calls to `push` immediately after creation --> tests/ui/vec_init_then_push.rs:5:5 | LL | / let mut def_err: Vec<u32> = Default::default(); -LL | | -LL | | +... | LL | | def_err.push(0); | |____________________^ help: consider using the `vec![]` macro: `let def_err: Vec<u32> = vec![..];` | diff --git a/src/tools/clippy/tests/ui/while_let_loop.stderr b/src/tools/clippy/tests/ui/while_let_loop.stderr index 5212d4fdcc7..10c2311d82f 100644 --- a/src/tools/clippy/tests/ui/while_let_loop.stderr +++ b/src/tools/clippy/tests/ui/while_let_loop.stderr @@ -6,7 +6,6 @@ LL | | LL | | LL | | if let Some(_x) = y { ... | -LL | | } LL | | } | |_____^ help: try: `while let Some(_x) = y { .. }` | @@ -45,7 +44,6 @@ LL | | LL | | let x = match y { LL | | Some(x) => x, ... | -LL | | } LL | | } | |_____^ help: try: `while let Some(x) = y { .. }` diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index ff62667f9b8..68131efa387 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -f4f0fafd0c7849e162eddbc69fa5fe82dbec28c7 +7caf35b2e5401d7740fdc567fdc388059208150b diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 7a85b4a4a6f..ea11093a17a 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -149,10 +149,9 @@ pub fn iter_exported_symbols<'tcx>( let dependency_formats = tcx.dependency_formats(()); // Find the dependencies of the executable we are running. let dependency_format = dependency_formats - .iter() - .find(|(crate_type, _)| *crate_type == CrateType::Executable) + .get(&CrateType::Executable) .expect("interpreting a non-executable crate"); - for cnum in dependency_format.1.iter().enumerate().filter_map(|(num, &linkage)| { + for cnum in dependency_format.iter().enumerate().filter_map(|(num, &linkage)| { // We add 1 to the number because that's what rustc also does everywhere it // calls `CrateNum::new`... #[expect(clippy::arithmetic_side_effects)] diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 7cc22f83a24..ac26feb345c 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1571,8 +1571,12 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { res } - fn after_local_read(ecx: &InterpCx<'tcx, Self>, local: mir::Local) -> InterpResult<'tcx> { - if let Some(data_race) = &ecx.frame().extra.data_race { + fn after_local_read( + ecx: &InterpCx<'tcx, Self>, + frame: &Frame<'tcx, Provenance, FrameExtra<'tcx>>, + local: mir::Local, + ) -> InterpResult<'tcx> { + if let Some(data_race) = &frame.extra.data_race { data_race.local_read(local, &ecx.machine); } interp_ok(()) diff --git a/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.stderr b/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.stderr index 23a9f8f9c28..6540543d8da 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.stderr @@ -24,8 +24,7 @@ note: inside `main` LL | / thread::spawn(|| { LL | | unsafe { LL | | assert_eq!(WaitForSingleObject(MAIN_THREAD, INFINITE), WAIT_OBJECT_0); -LL | | } -LL | | }) +... | LL | | .join() | |___________^ diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr index d9ab782986f..2875a5be285 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr @@ -14,7 +14,6 @@ LL | | let _unit: (); LL | | { LL | | let non_copy = S(42); ... | -LL | | } LL | | } | |_____^ help: <TAG> is this argument diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr index 677952b39da..c699987b796 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr @@ -16,7 +16,6 @@ LL | | let _unit: (); LL | | { LL | | let non_copy = S(42); ... | -LL | | } LL | | } | |_____^ help: the protected tag <TAG> was created here, in the initial state Reserved diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr index efdd6129d74..f20ec00f97b 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr @@ -14,7 +14,6 @@ LL | | let _unit: (); LL | | { LL | | let non_copy = S(42); ... | -LL | | LL | | } | |_____^ help: <TAG> is this argument diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr index 5746ad1e13d..8996c3643db 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr @@ -16,7 +16,6 @@ LL | | let _unit: (); LL | | { LL | | let non_copy = S(42); ... | -LL | | LL | | } | |_____^ help: the protected tag <TAG> was created here, in the initial state Reserved diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.stack.stderr index b009b0901c4..47e5ee48292 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.stack.stderr @@ -14,7 +14,6 @@ LL | | { LL | | let x = 0; LL | | let ptr = &raw mut x; ... | -LL | | } LL | | } | |_____^ help: <TAG> is this argument diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.tree.stderr index 6d2cbe9b7cd..7eb237ca1a7 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.tree.stderr @@ -16,7 +16,6 @@ LL | | { LL | | let x = 0; LL | | let ptr = &raw mut x; ... | -LL | | } LL | | } | |_____^ help: the protected tag <TAG> was created here, in the initial state Reserved diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.stack.stderr index 54f9a7aebd6..813042f06a6 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.stack.stderr @@ -14,7 +14,6 @@ LL | | { LL | | let _x = 0; LL | | let ptr = &raw mut _x; ... | -LL | | } LL | | } | |_____^ help: <TAG> is this argument diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.tree.stderr index 693534be2e0..5090ec06b78 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.tree.stderr @@ -16,7 +16,6 @@ LL | | { LL | | let _x = 0; LL | | let ptr = &raw mut _x; ... | -LL | | } LL | | } | |_____^ help: the protected tag <TAG> was created here, in the initial state Reserved diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.stack.stderr index 520937beaeb..a6a0362a226 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.stack.stderr @@ -14,7 +14,6 @@ LL | | { LL | | let _x = 0; LL | | let ptr = &raw mut _x; ... | -LL | | } LL | | } | |_____^ help: <TAG> is this argument diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.tree.stderr index a879189d0c1..26a54fe8748 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.tree.stderr @@ -16,7 +16,6 @@ LL | | { LL | | let _x = 0; LL | | let ptr = &raw mut _x; ... | -LL | | } LL | | } | |_____^ help: the protected tag <TAG> was created here, in the initial state Reserved diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index 77c9818b66b..16b7e7aa709 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -413,7 +413,8 @@ pub(crate) fn format_expr( ast::ExprKind::FormatArgs(..) | ast::ExprKind::Type(..) | ast::ExprKind::IncludedBytes(..) - | ast::ExprKind::OffsetOf(..) => { + | ast::ExprKind::OffsetOf(..) + | ast::ExprKind::UnsafeBinderCast(..) => { // These don't normally occur in the AST because macros aren't expanded. However, // rustfmt tries to parse macro arguments when formatting macros, so it's not totally // impossible for rustfmt to come across one of these nodes when formatting a file. diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 18932587f1f..c3debc2f4f0 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -3597,7 +3597,7 @@ pub(crate) fn rewrite_extern_crate( pub(crate) fn is_mod_decl(item: &ast::Item) -> bool { !matches!( item.kind, - ast::ItemKind::Mod(_, ast::ModKind::Loaded(_, ast::Inline::Yes, _)) + ast::ItemKind::Mod(_, ast::ModKind::Loaded(_, ast::Inline::Yes, _, _)) ) } diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs index 493b04f16c6..a40ee7f66a9 100644 --- a/src/tools/rustfmt/src/modules.rs +++ b/src/tools/rustfmt/src/modules.rs @@ -316,12 +316,11 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> { self.directory = directory; } match (sub_mod.ast_mod_kind, sub_mod.items) { - (Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _))), _) => { + (Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _, _))), _) => { self.visit_mod_from_ast(items) } - (Some(Cow::Owned(ast::ModKind::Loaded(items, _, _))), _) | (_, Cow::Owned(items)) => { - self.visit_mod_outside_ast(items) - } + (Some(Cow::Owned(ast::ModKind::Loaded(items, _, _, _))), _) + | (_, Cow::Owned(items)) => self.visit_mod_outside_ast(items), (_, _) => Ok(()), } } diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index dd4a788c002..f8b713117f4 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -1016,6 +1016,31 @@ impl Rewrite for ast::Ty { let pat = pat.rewrite_result(context, shape)?; Ok(format!("{ty} is {pat}")) } + ast::TyKind::UnsafeBinder(ref binder) => { + let mut result = String::new(); + if let Some(ref lifetime_str) = + rewrite_bound_params(context, shape, &binder.generic_params) + { + result.push_str("unsafe<"); + result.push_str(lifetime_str); + result.push_str("> "); + } + + let inner_ty_shape = if context.use_block_indent() { + shape + .offset_left(result.len()) + .max_width_error(shape.width, self.span())? + } else { + shape + .visual_indent(result.len()) + .sub_width(result.len()) + .max_width_error(shape.width, self.span())? + }; + + let rewrite = binder.inner_ty.rewrite_result(context, inner_ty_shape)?; + result.push_str(&rewrite); + Ok(result) + } } } } diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs index 0ca34a79491..ba4a4c045f1 100644 --- a/src/tools/rustfmt/src/utils.rs +++ b/src/tools/rustfmt/src/utils.rs @@ -504,6 +504,7 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr | ast::ExprKind::IncludedBytes(..) | ast::ExprKind::InlineAsm(..) | ast::ExprKind::OffsetOf(..) + | ast::ExprKind::UnsafeBinderCast(..) | ast::ExprKind::Let(..) | ast::ExprKind::Path(..) | ast::ExprKind::Range(..) diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index 9b116b620b7..805e13b7803 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -927,7 +927,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let ident_str = rewrite_ident(&self.get_context(), ident).to_owned(); self.push_str(&ident_str); - if let ast::ModKind::Loaded(ref items, ast::Inline::Yes, ref spans) = mod_kind { + if let ast::ModKind::Loaded(ref items, ast::Inline::Yes, ref spans, _) = mod_kind { let ast::ModSpans { inner_span, inject_use_span: _, diff --git a/src/tools/rustfmt/tests/source/unsafe-binders.rs b/src/tools/rustfmt/tests/source/unsafe-binders.rs new file mode 100644 index 00000000000..ccf7c8bb9af --- /dev/null +++ b/src/tools/rustfmt/tests/source/unsafe-binders.rs @@ -0,0 +1,11 @@ +fn foo() -> unsafe<'a> +&'a () {} + +struct Foo { + x: unsafe<'a> +&'a (), +} + +struct Bar(unsafe<'a> &'a ()); + +impl Trait for unsafe<'a> &'a () {} diff --git a/src/tools/rustfmt/tests/target/unsafe-binders.rs b/src/tools/rustfmt/tests/target/unsafe-binders.rs new file mode 100644 index 00000000000..9d308f4a894 --- /dev/null +++ b/src/tools/rustfmt/tests/target/unsafe-binders.rs @@ -0,0 +1,9 @@ +fn foo() -> unsafe<'a> &'a () {} + +struct Foo { + x: unsafe<'a> &'a (), +} + +struct Bar(unsafe<'a> &'a ()); + +impl Trait for unsafe<'a> &'a () {} diff --git a/tests/codegen/mem-replace-big-type.rs b/tests/codegen/mem-replace-big-type.rs index e62adfa0ba6..0b2229ba7d1 100644 --- a/tests/codegen/mem-replace-big-type.rs +++ b/tests/codegen/mem-replace-big-type.rs @@ -25,9 +25,10 @@ pub fn replace_big(dst: &mut Big, src: Big) -> Big { // CHECK-NOT: call void @llvm.memcpy // For a large type, we expect exactly three `memcpy`s -// CHECK-LABEL: define internal void @{{.+}}mem{{.+}}replace{{.+}}sret([56 x i8]) +// CHECK-LABEL: define internal void @{{.+}}mem{{.+}}replace{{.+}}(ptr +// CHECK-SAME: sret([56 x i8]){{.+}}[[RESULT:%.+]], ptr{{.+}}%dest, ptr{{.+}}%src) // CHECK-NOT: call void @llvm.memcpy -// CHECK: call void @llvm.memcpy.{{.+}}(ptr align 8 %result, ptr align 8 %dest, i{{.*}} 56, i1 false) +// CHECK: call void @llvm.memcpy.{{.+}}(ptr align 8 [[RESULT]], ptr align 8 %dest, i{{.*}} 56, i1 false) // CHECK-NOT: call void @llvm.memcpy // CHECK: call void @llvm.memcpy.{{.+}}(ptr align 8 %dest, ptr align 8 %src, i{{.*}} 56, i1 false) // CHECK-NOT: call void @llvm.memcpy diff --git a/tests/crashes/123861.rs b/tests/crashes/123861.rs deleted file mode 100644 index 60245960af0..00000000000 --- a/tests/crashes/123861.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ known-bug: #123861 -//@ needs-rustc-debug-assertions - -struct _; -fn mainIterator<_ = _> {} diff --git a/tests/crashes/132765.rs b/tests/crashes/132765.rs new file mode 100644 index 00000000000..01e8fdaacff --- /dev/null +++ b/tests/crashes/132765.rs @@ -0,0 +1,12 @@ +//@ known-bug: #132765 + +trait LendingIterator { + type Item<'q>; + fn for_each(&self, _f: Box<fn(Self::Item<'_>)>) {} +} + +fn f(_: ()) {} + +fn main() { + LendingIterator::for_each(&(), f); +} diff --git a/tests/crashes/132766.rs b/tests/crashes/132766.rs new file mode 100644 index 00000000000..5f5117d77a5 --- /dev/null +++ b/tests/crashes/132766.rs @@ -0,0 +1,9 @@ +//@ known-bug: #132766 + +trait Trait {} +impl<'a> Trait for () { + fn pass2<'a>() -> impl Trait2 {} +} + +trait Trait2 {} +impl Trait2 for () {} diff --git a/tests/crashes/132882.rs b/tests/crashes/132882.rs new file mode 100644 index 00000000000..6b5e4dba803 --- /dev/null +++ b/tests/crashes/132882.rs @@ -0,0 +1,13 @@ +//@ known-bug: #132882 + +use std::ops::Add; + +pub trait Numoid +where + for<N: Numoid> &'a Self: Add<Self>, +{ +} + +pub fn compute<N: Numoid>(a: N) -> N { + &a + a +} diff --git a/tests/crashes/132981.rs b/tests/crashes/132981.rs new file mode 100644 index 00000000000..8ff4fa36fd0 --- /dev/null +++ b/tests/crashes/132981.rs @@ -0,0 +1,7 @@ +//@ known-bug: #132981 +//@compile-flags: -Clink-dead-code=true --crate-type lib +//@ only-x86_64 +//@ ignore-windows + +#![feature(rust_cold_cc)] +pub extern "rust-cold" fn foo(_: [usize; 3]) {} diff --git a/tests/crashes/133063.rs b/tests/crashes/133063.rs new file mode 100644 index 00000000000..132b5486170 --- /dev/null +++ b/tests/crashes/133063.rs @@ -0,0 +1,8 @@ +//@ known-bug: #133063 + +fn foo(x: !) { + match x { + (! | !) if false => {} + _ => {} + } +} diff --git a/tests/crashes/133066.rs b/tests/crashes/133066.rs new file mode 100644 index 00000000000..732ebb7079f --- /dev/null +++ b/tests/crashes/133066.rs @@ -0,0 +1,12 @@ +//@ known-bug: #133066 +trait Owner { + const C<const N: u32>: u32; +} + +impl Owner for () {;} + +fn take0<const N: u64>(_: impl Owner<C<N> = { N }>) {} + +fn main() { + take0::<f32, >(()); +} diff --git a/tests/crashes/133199.rs b/tests/crashes/133199.rs new file mode 100644 index 00000000000..76535fa83a6 --- /dev/null +++ b/tests/crashes/133199.rs @@ -0,0 +1,11 @@ +//@ known-bug: #133199 +//@ aux-build: aux133199.rs + +extern crate aux133199; + +use aux133199::FixedBitSet; + +fn main() { + FixedBitSet::<7>::new(); + //~^ ERROR +} diff --git a/tests/crashes/133275-1.rs b/tests/crashes/133275-1.rs new file mode 100644 index 00000000000..73c04f5d6e4 --- /dev/null +++ b/tests/crashes/133275-1.rs @@ -0,0 +1,13 @@ +//@ known-bug: #133275 +#![feature(const_trait_impl)] +#![feature(associated_type_defaults)] + +#[const_trait] +trait Foo3<T> +where + Self::Baz: Clone, +{ + type Baz = T; +} + +pub fn main() {} diff --git a/tests/crashes/133275-2.rs b/tests/crashes/133275-2.rs new file mode 100644 index 00000000000..a774b3cdb69 --- /dev/null +++ b/tests/crashes/133275-2.rs @@ -0,0 +1,15 @@ +//@ known-bug: #133275 +#![feature(const_trait_impl)] +#[const_trait] +pub trait Owo<X = <IntEnum as Uwu>::T> {} + +#[const_trait] +trait Foo3<T> +where + Self::Bar: Clone, + Self::Baz: Clone, +{ + type Bar = Vec<Self::Baz>; + type Baz = T; + //~^ ERROR the trait bound `T: Clone` is not satisfied +} diff --git a/tests/crashes/133426.rs b/tests/crashes/133426.rs new file mode 100644 index 00000000000..307a94c0f6c --- /dev/null +++ b/tests/crashes/133426.rs @@ -0,0 +1,12 @@ +//@ known-bug: #133426 + +fn a( + _: impl Iterator< + Item = [(); { + match *todo!() { ! }; + }], + >, +) { +} + +fn b(_: impl Iterator<Item = { match 0 { ! } }>) {} diff --git a/tests/crashes/133597.rs b/tests/crashes/133597.rs new file mode 100644 index 00000000000..f716d5e7bc7 --- /dev/null +++ b/tests/crashes/133597.rs @@ -0,0 +1,11 @@ +//@ known-bug: #133597 + +pub trait Foo2 { + fn boxed<'a: 'a>() -> impl Sized + FnOnce<()>; +} + +impl Foo2 for () {} + + +fn f() -> impl FnOnce<()> { || () } +fn main() { () = f(); } diff --git a/tests/crashes/133639.rs b/tests/crashes/133639.rs new file mode 100644 index 00000000000..d522b0730cf --- /dev/null +++ b/tests/crashes/133639.rs @@ -0,0 +1,33 @@ +//@ known-bug: #133639 + +#![feature(with_negative_coherence)] +#![feature(min_specialization)] +#![feature(generic_const_exprs)] + +#![crate_type = "lib"] +use std::str::FromStr; + +struct a<const b: bool>; + +trait c {} + +impl<const d: u32> FromStr for e<d> +where + a<{ d <= 2 }>: c, +{ + type Err = (); + fn from_str(f: &str) -> Result<Self, Self::Err> { + unimplemented!() + } +} +struct e<const d: u32>; + +impl<const d: u32> FromStr for e<d> +where + a<{ d <= 2 }>: c, +{ + type Err = (); + fn from_str(f: &str) -> Result<Self, Self::Err> { + unimplemented!() + } +} diff --git a/tests/crashes/133808.rs b/tests/crashes/133808.rs new file mode 100644 index 00000000000..9c6a23d1e35 --- /dev/null +++ b/tests/crashes/133808.rs @@ -0,0 +1,15 @@ +//@ known-bug: #133808 + +#![feature(generic_const_exprs, transmutability)] + +mod assert { + use std::mem::TransmuteFrom; + + pub fn is_transmutable<Src, Dst>() + where + Dst: TransmuteFrom<Src>, + { + } +} + +pub fn main() {} diff --git a/tests/crashes/133868.rs b/tests/crashes/133868.rs new file mode 100644 index 00000000000..dc25cb9df28 --- /dev/null +++ b/tests/crashes/133868.rs @@ -0,0 +1,13 @@ +//@ known-bug: #133868 + +trait Foo { + type Assoc; +} + +trait Bar { + fn method() -> impl Sized; +} +impl<T> Bar for T where <T as Foo>::Assoc: Sized +{ + fn method() {} +} diff --git a/tests/crashes/133965.rs b/tests/crashes/133965.rs new file mode 100644 index 00000000000..69f533ccbe9 --- /dev/null +++ b/tests/crashes/133965.rs @@ -0,0 +1,9 @@ +//@ known-bug: #133965 +//@ needs-rustc-debug-assertions + +struct NonGeneric {} + +#[derive(Default)] +struct NonGeneric<'a, const N: usize> {} + +pub fn main() {} diff --git a/tests/crashes/133966.rs b/tests/crashes/133966.rs new file mode 100644 index 00000000000..25a881ae99b --- /dev/null +++ b/tests/crashes/133966.rs @@ -0,0 +1,3 @@ +//@ known-bug: #133966 +pub struct Data([[&'static str]; 5_i32]); +const _: &'static Data = unsafe { &*(&[] as *const Data) }; diff --git a/tests/crashes/134005.rs b/tests/crashes/134005.rs new file mode 100644 index 00000000000..c1f4c758a14 --- /dev/null +++ b/tests/crashes/134005.rs @@ -0,0 +1,5 @@ +//@ known-bug: #134005 + +fn main() { + let _ = [std::ops::Add::add, std::ops::Mul::mul, main as fn(_, &_)]; +} diff --git a/tests/crashes/134061.rs b/tests/crashes/134061.rs new file mode 100644 index 00000000000..e00eb7603fe --- /dev/null +++ b/tests/crashes/134061.rs @@ -0,0 +1,4 @@ +//@ known-bug: #134061 +//@ needs-rustc-debug-assertions + +const x: () = |&'a diff --git a/tests/crashes/134217.rs b/tests/crashes/134217.rs new file mode 100644 index 00000000000..1b14c660e8b --- /dev/null +++ b/tests/crashes/134217.rs @@ -0,0 +1,9 @@ +//@ known-bug: #134217 + +impl<A> std::ops::CoerceUnsized<A> for A {} + +fn main() { + if let _ = true + && true + {} +} diff --git a/tests/crashes/auxiliary/aux133199.rs b/tests/crashes/auxiliary/aux133199.rs new file mode 100644 index 00000000000..40765d92fbf --- /dev/null +++ b/tests/crashes/auxiliary/aux133199.rs @@ -0,0 +1,13 @@ +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +pub struct FixedBitSet<const N: usize>; + +impl<const N: usize> FixedBitSet<N> +where + [u8; N.div_ceil(8)]: Sized, +{ + pub fn new() -> Self { + todo!() + } +} diff --git a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir index a467987e886..8d9176ef301 100644 --- a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir +++ b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir @@ -7,8 +7,7 @@ fn main() -> () { let mut _5: u32; let mut _6: *mut usize; let _7: usize; - let mut _8: usize; - let mut _9: bool; + let mut _8: bool; scope 1 { debug x => _1; let mut _2: usize; @@ -41,9 +40,8 @@ fn main() -> () { StorageDead(_6); StorageLive(_7); _7 = copy _2; - _8 = Len(_1); - _9 = Lt(copy _7, copy _8); - assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb2, unwind unreachable]; + _8 = Lt(copy _7, const 3_usize); + assert(move _8, "index out of bounds: the length is {} but the index is {}", const 3_usize, copy _7) -> [success: bb2, unwind unreachable]; } bb2: { diff --git a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir index bd7365543bd..e1df0e3e2a3 100644 --- a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir +++ b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir @@ -7,8 +7,7 @@ fn main() -> () { let mut _5: u32; let mut _6: *mut usize; let _7: usize; - let mut _8: usize; - let mut _9: bool; + let mut _8: bool; scope 1 { debug x => _1; let mut _2: usize; @@ -41,9 +40,8 @@ fn main() -> () { StorageDead(_6); StorageLive(_7); _7 = copy _2; - _8 = Len(_1); - _9 = Lt(copy _7, copy _8); - assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb2, unwind continue]; + _8 = Lt(copy _7, const 3_usize); + assert(move _8, "index out of bounds: the length is {} but the index is {}", const 3_usize, copy _7) -> [success: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/building/index_array_and_slice.index_array.built.after.mir b/tests/mir-opt/building/index_array_and_slice.index_array.built.after.mir new file mode 100644 index 00000000000..d28a2031013 --- /dev/null +++ b/tests/mir-opt/building/index_array_and_slice.index_array.built.after.mir @@ -0,0 +1,31 @@ +// MIR for `index_array` after built + +fn index_array(_1: &[i32; 7], _2: usize) -> &i32 { + debug array => _1; + debug index => _2; + let mut _0: &i32; + let _3: &i32; + let _4: usize; + let mut _5: bool; + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = copy _2; + FakeRead(ForIndex, (*_1)); + _5 = Lt(copy _4, const 7_usize); + assert(move _5, "index out of bounds: the length is {} but the index is {}", const 7_usize, copy _4) -> [success: bb1, unwind: bb2]; + } + + bb1: { + _3 = &(*_1)[_4]; + _0 = &(*_3); + StorageDead(_4); + StorageDead(_3); + return; + } + + bb2 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/building/index_array_and_slice.index_const_generic_array.built.after.mir b/tests/mir-opt/building/index_array_and_slice.index_const_generic_array.built.after.mir new file mode 100644 index 00000000000..e9627532c38 --- /dev/null +++ b/tests/mir-opt/building/index_array_and_slice.index_const_generic_array.built.after.mir @@ -0,0 +1,31 @@ +// MIR for `index_const_generic_array` after built + +fn index_const_generic_array(_1: &[i32; N], _2: usize) -> &i32 { + debug array => _1; + debug index => _2; + let mut _0: &i32; + let _3: &i32; + let _4: usize; + let mut _5: bool; + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = copy _2; + FakeRead(ForIndex, (*_1)); + _5 = Lt(copy _4, const N); + assert(move _5, "index out of bounds: the length is {} but the index is {}", const N, copy _4) -> [success: bb1, unwind: bb2]; + } + + bb1: { + _3 = &(*_1)[_4]; + _0 = &(*_3); + StorageDead(_4); + StorageDead(_3); + return; + } + + bb2 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/building/index_array_and_slice.index_custom.built.after.mir b/tests/mir-opt/building/index_array_and_slice.index_custom.built.after.mir new file mode 100644 index 00000000000..00f2b7e07d5 --- /dev/null +++ b/tests/mir-opt/building/index_array_and_slice.index_custom.built.after.mir @@ -0,0 +1,34 @@ +// MIR for `index_custom` after built + +fn index_custom(_1: &WithSliceTail, _2: usize) -> &i32 { + debug custom => _1; + debug index => _2; + let mut _0: &i32; + let _3: &i32; + let _4: usize; + let mut _5: *const [i32]; + let mut _6: usize; + let mut _7: bool; + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = copy _2; + _5 = &raw const ((*_1).1: [i32]); + _6 = PtrMetadata(move _5); + _7 = Lt(copy _4, copy _6); + assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _4) -> [success: bb1, unwind: bb2]; + } + + bb1: { + _3 = &((*_1).1: [i32])[_4]; + _0 = &(*_3); + StorageDead(_4); + StorageDead(_3); + return; + } + + bb2 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/building/index_array_and_slice.index_mut_slice.built.after.mir b/tests/mir-opt/building/index_array_and_slice.index_mut_slice.built.after.mir new file mode 100644 index 00000000000..cb0b2f600c8 --- /dev/null +++ b/tests/mir-opt/building/index_array_and_slice.index_mut_slice.built.after.mir @@ -0,0 +1,34 @@ +// MIR for `index_mut_slice` after built + +fn index_mut_slice(_1: &mut [i32], _2: usize) -> &i32 { + debug slice => _1; + debug index => _2; + let mut _0: &i32; + let _3: &i32; + let _4: usize; + let mut _5: *const [i32]; + let mut _6: usize; + let mut _7: bool; + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = copy _2; + _5 = &raw const (*_1); + _6 = PtrMetadata(move _5); + _7 = Lt(copy _4, copy _6); + assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _4) -> [success: bb1, unwind: bb2]; + } + + bb1: { + _3 = &(*_1)[_4]; + _0 = &(*_3); + StorageDead(_4); + StorageDead(_3); + return; + } + + bb2 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/building/index_array_and_slice.index_slice.built.after.mir b/tests/mir-opt/building/index_array_and_slice.index_slice.built.after.mir new file mode 100644 index 00000000000..0911df59049 --- /dev/null +++ b/tests/mir-opt/building/index_array_and_slice.index_slice.built.after.mir @@ -0,0 +1,32 @@ +// MIR for `index_slice` after built + +fn index_slice(_1: &[i32], _2: usize) -> &i32 { + debug slice => _1; + debug index => _2; + let mut _0: &i32; + let _3: &i32; + let _4: usize; + let mut _5: usize; + let mut _6: bool; + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = copy _2; + _5 = PtrMetadata(copy _1); + _6 = Lt(copy _4, copy _5); + assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind: bb2]; + } + + bb1: { + _3 = &(*_1)[_4]; + _0 = &(*_3); + StorageDead(_4); + StorageDead(_3); + return; + } + + bb2 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/building/index_array_and_slice.rs b/tests/mir-opt/building/index_array_and_slice.rs new file mode 100644 index 00000000000..16d0b983132 --- /dev/null +++ b/tests/mir-opt/building/index_array_and_slice.rs @@ -0,0 +1,71 @@ +//@ compile-flags: -C opt-level=0 + +// EMIT_MIR index_array_and_slice.index_array.built.after.mir +fn index_array(array: &[i32; 7], index: usize) -> &i32 { + // CHECK: bb0: + // CHECK: [[LT:_.+]] = Lt(copy _2, const 7_usize); + // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", const 7_usize, copy _2) -> [success: bb1, unwind + + // CHECK: bb1: + // CHECK: _0 = &(*_1)[_2]; + &array[index] +} + +// EMIT_MIR index_array_and_slice.index_const_generic_array.built.after.mir +fn index_const_generic_array<const N: usize>(array: &[i32; N], index: usize) -> &i32 { + // CHECK: bb0: + // CHECK: [[LT:_.+]] = Lt(copy _2, const N); + // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", const N, copy _2) -> [success: bb1, unwind + + // CHECK: bb1: + // CHECK: _0 = &(*_1)[_2]; + &array[index] +} + +// EMIT_MIR index_array_and_slice.index_slice.built.after.mir +fn index_slice(slice: &[i32], index: usize) -> &i32 { + // CHECK: bb0: + // CHECK: [[LEN:_.+]] = PtrMetadata(copy _1); + // CHECK: [[LT:_.+]] = Lt(copy _2, copy [[LEN]]); + // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _2) -> [success: bb1, + + // CHECK: bb1: + // CHECK: _0 = &(*_1)[_2]; + &slice[index] +} + +// EMIT_MIR index_array_and_slice.index_mut_slice.built.after.mir +fn index_mut_slice(slice: &mut [i32], index: usize) -> &i32 { + // While the filecheck here is identical to the above test, the emitted MIR is different. + // This cannot `copy _1` in the *built* MIR, only in the *runtime* MIR. + + // CHECK: bb0: + // CHECK: [[LEN:_.+]] = PtrMetadata(copy _1); + // CHECK: [[LT:_.+]] = Lt(copy _2, copy [[LEN]]); + // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _2) -> [success: bb1, + + // CHECK: bb1: + // CHECK: _0 = &(*_1)[_2]; + &slice[index] +} + +struct WithSliceTail(f64, [i32]); + +// EMIT_MIR index_array_and_slice.index_custom.built.after.mir +fn index_custom(custom: &WithSliceTail, index: usize) -> &i32 { + // CHECK: bb0: + // CHECK: [[PTR:_.+]] = &raw const ((*_1).1: [i32]); + // CHECK: [[LEN:_.+]] = PtrMetadata(move [[PTR]]); + // CHECK: [[LT:_.+]] = Lt(copy _2, copy [[LEN]]); + // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _2) -> [success: bb1, + + // CHECK: bb1: + // CHECK: _0 = &((*_1).1: [i32])[_2]; + &custom.1[index] +} + +fn main() { + index_array(&[1, 2, 3, 4, 5, 6, 7], 3); + index_slice(&[1, 2, 3, 4, 5, 6, 7][..], 3); + _ = index_custom; +} diff --git a/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff index e754af95ce3..3a5a8d00991 100644 --- a/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff @@ -6,8 +6,7 @@ let _1: u32; let mut _2: [u32; 4]; let _3: usize; - let mut _4: usize; - let mut _5: bool; + let mut _4: bool; scope 1 { debug x => _1; } @@ -18,11 +17,9 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); -- _5 = Lt(copy _3, copy _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable]; -+ _4 = const 4_usize; -+ _5 = const true; +- _4 = Lt(copy _3, const 4_usize); +- assert(move _4, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _3) -> [success: bb1, unwind unreachable]; ++ _4 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff index e15a35c7fe9..62d6e6007e5 100644 --- a/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff @@ -6,8 +6,7 @@ let _1: u32; let mut _2: [u32; 4]; let _3: usize; - let mut _4: usize; - let mut _5: bool; + let mut _4: bool; scope 1 { debug x => _1; } @@ -18,11 +17,9 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); -- _5 = Lt(copy _3, copy _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue]; -+ _4 = const 4_usize; -+ _5 = const true; +- _4 = Lt(copy _3, const 4_usize); +- assert(move _4, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _3) -> [success: bb1, unwind continue]; ++ _4 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind continue]; } diff --git a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff index e754af95ce3..3a5a8d00991 100644 --- a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff @@ -6,8 +6,7 @@ let _1: u32; let mut _2: [u32; 4]; let _3: usize; - let mut _4: usize; - let mut _5: bool; + let mut _4: bool; scope 1 { debug x => _1; } @@ -18,11 +17,9 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); -- _5 = Lt(copy _3, copy _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable]; -+ _4 = const 4_usize; -+ _5 = const true; +- _4 = Lt(copy _3, const 4_usize); +- assert(move _4, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _3) -> [success: bb1, unwind unreachable]; ++ _4 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff index e15a35c7fe9..62d6e6007e5 100644 --- a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff @@ -6,8 +6,7 @@ let _1: u32; let mut _2: [u32; 4]; let _3: usize; - let mut _4: usize; - let mut _5: bool; + let mut _4: bool; scope 1 { debug x => _1; } @@ -18,11 +17,9 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); -- _5 = Lt(copy _3, copy _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue]; -+ _4 = const 4_usize; -+ _5 = const true; +- _4 = Lt(copy _3, const 4_usize); +- assert(move _4, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _3) -> [success: bb1, unwind continue]; ++ _4 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind continue]; } diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff index 15d30140367..be42c4d60c8 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff @@ -30,19 +30,22 @@ StorageDead(_2); StorageDead(_3); StorageLive(_5); - StorageLive(_6); +- StorageLive(_6); ++ nop; _6 = const 3_usize; - _7 = Len((*_1)); +- _7 = PtrMetadata(copy _1); - _8 = Lt(copy _6, copy _7); - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable]; -+ _8 = Lt(const 3_usize, copy _7); -+ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> [success: bb1, unwind unreachable]; ++ _7 = const 3_usize; ++ _8 = const false; ++ assert(const false, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 3_usize) -> [success: bb1, unwind unreachable]; } bb1: { - _5 = copy (*_1)[_6]; +- StorageDead(_6); + _5 = copy (*_1)[3 of 4]; - StorageDead(_6); ++ nop; _0 = const (); StorageDead(_5); StorageDead(_1); diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff index dd411d84f9f..b51d0c0845f 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff @@ -30,19 +30,22 @@ StorageDead(_2); StorageDead(_3); StorageLive(_5); - StorageLive(_6); +- StorageLive(_6); ++ nop; _6 = const 3_usize; - _7 = Len((*_1)); +- _7 = PtrMetadata(copy _1); - _8 = Lt(copy _6, copy _7); - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue]; -+ _8 = Lt(const 3_usize, copy _7); -+ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> [success: bb1, unwind continue]; ++ _7 = const 3_usize; ++ _8 = const false; ++ assert(const false, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 3_usize) -> [success: bb1, unwind continue]; } bb1: { - _5 = copy (*_1)[_6]; +- StorageDead(_6); + _5 = copy (*_1)[3 of 4]; - StorageDead(_6); ++ nop; _0 = const (); StorageDead(_5); StorageDead(_1); diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff index 15d30140367..be42c4d60c8 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff @@ -30,19 +30,22 @@ StorageDead(_2); StorageDead(_3); StorageLive(_5); - StorageLive(_6); +- StorageLive(_6); ++ nop; _6 = const 3_usize; - _7 = Len((*_1)); +- _7 = PtrMetadata(copy _1); - _8 = Lt(copy _6, copy _7); - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable]; -+ _8 = Lt(const 3_usize, copy _7); -+ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> [success: bb1, unwind unreachable]; ++ _7 = const 3_usize; ++ _8 = const false; ++ assert(const false, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 3_usize) -> [success: bb1, unwind unreachable]; } bb1: { - _5 = copy (*_1)[_6]; +- StorageDead(_6); + _5 = copy (*_1)[3 of 4]; - StorageDead(_6); ++ nop; _0 = const (); StorageDead(_5); StorageDead(_1); diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff index dd411d84f9f..b51d0c0845f 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff @@ -30,19 +30,22 @@ StorageDead(_2); StorageDead(_3); StorageLive(_5); - StorageLive(_6); +- StorageLive(_6); ++ nop; _6 = const 3_usize; - _7 = Len((*_1)); +- _7 = PtrMetadata(copy _1); - _8 = Lt(copy _6, copy _7); - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue]; -+ _8 = Lt(const 3_usize, copy _7); -+ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> [success: bb1, unwind continue]; ++ _7 = const 3_usize; ++ _8 = const false; ++ assert(const false, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 3_usize) -> [success: bb1, unwind continue]; } bb1: { - _5 = copy (*_1)[_6]; +- StorageDead(_6); + _5 = copy (*_1)[3 of 4]; - StorageDead(_6); ++ nop; _0 = const (); StorageDead(_5); StorageDead(_1); diff --git a/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff index 49ea51deed6..3569998b13f 100644 --- a/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff @@ -6,8 +6,7 @@ let _1: u8; let mut _2: [u8; 5000]; let _3: usize; - let mut _4: usize; - let mut _5: bool; + let mut _4: bool; scope 1 { debug x => _1; } @@ -18,11 +17,9 @@ _2 = [const 0_u8; 5000]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); -- _5 = Lt(copy _3, copy _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable]; -+ _4 = const 5000_usize; -+ _5 = const true; +- _4 = Lt(copy _3, const 5000_usize); +- assert(move _4, "index out of bounds: the length is {} but the index is {}", const 5000_usize, copy _3) -> [success: bb1, unwind unreachable]; ++ _4 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-unwind.diff index 103bfbcaf64..50b31c9ac13 100644 --- a/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-unwind.diff @@ -6,8 +6,7 @@ let _1: u8; let mut _2: [u8; 5000]; let _3: usize; - let mut _4: usize; - let mut _5: bool; + let mut _4: bool; scope 1 { debug x => _1; } @@ -18,11 +17,9 @@ _2 = [const 0_u8; 5000]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); -- _5 = Lt(copy _3, copy _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue]; -+ _4 = const 5000_usize; -+ _5 = const true; +- _4 = Lt(copy _3, const 5000_usize); +- assert(move _4, "index out of bounds: the length is {} but the index is {}", const 5000_usize, copy _3) -> [success: bb1, unwind continue]; ++ _4 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind continue]; } diff --git a/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-abort.diff index 49ea51deed6..3569998b13f 100644 --- a/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-abort.diff @@ -6,8 +6,7 @@ let _1: u8; let mut _2: [u8; 5000]; let _3: usize; - let mut _4: usize; - let mut _5: bool; + let mut _4: bool; scope 1 { debug x => _1; } @@ -18,11 +17,9 @@ _2 = [const 0_u8; 5000]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); -- _5 = Lt(copy _3, copy _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable]; -+ _4 = const 5000_usize; -+ _5 = const true; +- _4 = Lt(copy _3, const 5000_usize); +- assert(move _4, "index out of bounds: the length is {} but the index is {}", const 5000_usize, copy _3) -> [success: bb1, unwind unreachable]; ++ _4 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff index 103bfbcaf64..50b31c9ac13 100644 --- a/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff @@ -6,8 +6,7 @@ let _1: u8; let mut _2: [u8; 5000]; let _3: usize; - let mut _4: usize; - let mut _5: bool; + let mut _4: bool; scope 1 { debug x => _1; } @@ -18,11 +17,9 @@ _2 = [const 0_u8; 5000]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); -- _5 = Lt(copy _3, copy _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue]; -+ _4 = const 5000_usize; -+ _5 = const true; +- _4 = Lt(copy _3, const 5000_usize); +- assert(move _4, "index out of bounds: the length is {} but the index is {}", const 5000_usize, copy _3) -> [success: bb1, unwind continue]; ++ _4 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind continue]; } diff --git a/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff index f7c1c2da01f..a41668b6fa3 100644 --- a/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff @@ -7,8 +7,7 @@ let mut _2: u32; let mut _3: [u32; 8]; let _4: usize; - let mut _5: usize; - let mut _6: bool; + let mut _5: bool; scope 1 { debug x => _1; } @@ -20,11 +19,9 @@ _3 = [const 42_u32; 8]; StorageLive(_4); _4 = const 2_usize; -- _5 = Len(_3); -- _6 = Lt(copy _4, copy _5); -- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind unreachable]; -+ _5 = const 8_usize; -+ _6 = const true; +- _5 = Lt(copy _4, const 8_usize); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", const 8_usize, copy _4) -> [success: bb1, unwind unreachable]; ++ _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-unwind.diff index 436773c8556..2313084b49e 100644 --- a/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-unwind.diff @@ -7,8 +7,7 @@ let mut _2: u32; let mut _3: [u32; 8]; let _4: usize; - let mut _5: usize; - let mut _6: bool; + let mut _5: bool; scope 1 { debug x => _1; } @@ -20,11 +19,9 @@ _3 = [const 42_u32; 8]; StorageLive(_4); _4 = const 2_usize; -- _5 = Len(_3); -- _6 = Lt(copy _4, copy _5); -- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind continue]; -+ _5 = const 8_usize; -+ _6 = const true; +- _5 = Lt(copy _4, const 8_usize); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", const 8_usize, copy _4) -> [success: bb1, unwind continue]; ++ _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind continue]; } diff --git a/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-abort.diff index f7c1c2da01f..a41668b6fa3 100644 --- a/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-abort.diff @@ -7,8 +7,7 @@ let mut _2: u32; let mut _3: [u32; 8]; let _4: usize; - let mut _5: usize; - let mut _6: bool; + let mut _5: bool; scope 1 { debug x => _1; } @@ -20,11 +19,9 @@ _3 = [const 42_u32; 8]; StorageLive(_4); _4 = const 2_usize; -- _5 = Len(_3); -- _6 = Lt(copy _4, copy _5); -- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind unreachable]; -+ _5 = const 8_usize; -+ _6 = const true; +- _5 = Lt(copy _4, const 8_usize); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", const 8_usize, copy _4) -> [success: bb1, unwind unreachable]; ++ _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff index 436773c8556..2313084b49e 100644 --- a/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff @@ -7,8 +7,7 @@ let mut _2: u32; let mut _3: [u32; 8]; let _4: usize; - let mut _5: usize; - let mut _6: bool; + let mut _5: bool; scope 1 { debug x => _1; } @@ -20,11 +19,9 @@ _3 = [const 42_u32; 8]; StorageLive(_4); _4 = const 2_usize; -- _5 = Len(_3); -- _6 = Lt(copy _4, copy _5); -- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind continue]; -+ _5 = const 8_usize; -+ _6 = const true; +- _5 = Lt(copy _4, const 8_usize); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", const 8_usize, copy _4) -> [success: bb1, unwind continue]; ++ _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind continue]; } diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff index 8a8ea5b7e20..0798b303929 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff @@ -30,11 +30,12 @@ StorageDead(_3); StorageLive(_6); _6 = const 1_usize; - _7 = Len((*_2)); +- _7 = PtrMetadata(copy _2); - _8 = Lt(copy _6, copy _7); - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable]; -+ _8 = Lt(const 1_usize, copy _7); -+ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 1_usize) -> [success: bb1, unwind unreachable]; ++ _7 = const 3_usize; ++ _8 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff index f0c844884f6..c0b3d4d3219 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff @@ -30,11 +30,12 @@ StorageDead(_3); StorageLive(_6); _6 = const 1_usize; - _7 = Len((*_2)); +- _7 = PtrMetadata(copy _2); - _8 = Lt(copy _6, copy _7); - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue]; -+ _8 = Lt(const 1_usize, copy _7); -+ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 1_usize) -> [success: bb1, unwind continue]; ++ _7 = const 3_usize; ++ _8 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff index 8a8ea5b7e20..0798b303929 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff @@ -30,11 +30,12 @@ StorageDead(_3); StorageLive(_6); _6 = const 1_usize; - _7 = Len((*_2)); +- _7 = PtrMetadata(copy _2); - _8 = Lt(copy _6, copy _7); - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable]; -+ _8 = Lt(const 1_usize, copy _7); -+ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 1_usize) -> [success: bb1, unwind unreachable]; ++ _7 = const 3_usize; ++ _8 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff index f0c844884f6..c0b3d4d3219 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff @@ -30,11 +30,12 @@ StorageDead(_3); StorageLive(_6); _6 = const 1_usize; - _7 = Len((*_2)); +- _7 = PtrMetadata(copy _2); - _8 = Lt(copy _6, copy _7); - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue]; -+ _8 = Lt(const 1_usize, copy _7); -+ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 1_usize) -> [success: bb1, unwind continue]; ++ _7 = const 3_usize; ++ _8 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff index 6d967257df1..689083dfc1d 100644 --- a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff @@ -18,8 +18,7 @@ let mut _15: !; let mut _17: i32; let _18: usize; - let mut _19: usize; - let mut _20: bool; + let mut _19: bool; scope 1 { debug sum => _1; let _2: [i32; 4]; @@ -92,11 +91,10 @@ StorageLive(_17); - StorageLive(_18); - _18 = copy _16; - _19 = Len(_2); -- _20 = Lt(copy _18, copy _19); -- assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, copy _18) -> [success: bb8, unwind unreachable]; -+ _20 = Lt(copy _16, copy _19); -+ assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, copy _16) -> [success: bb8, unwind unreachable]; +- _19 = Lt(copy _18, const 4_usize); +- assert(move _19, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _18) -> [success: bb8, unwind unreachable]; ++ _19 = Lt(copy _16, const 4_usize); ++ assert(move _19, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _16) -> [success: bb8, unwind unreachable]; } bb7: { diff --git a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff index 3580c87c469..7f768a9f834 100644 --- a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff @@ -18,8 +18,7 @@ let mut _15: !; let mut _17: i32; let _18: usize; - let mut _19: usize; - let mut _20: bool; + let mut _19: bool; scope 1 { debug sum => _1; let _2: [i32; 4]; @@ -92,11 +91,10 @@ StorageLive(_17); - StorageLive(_18); - _18 = copy _16; - _19 = Len(_2); -- _20 = Lt(copy _18, copy _19); -- assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, copy _18) -> [success: bb8, unwind continue]; -+ _20 = Lt(copy _16, copy _19); -+ assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, copy _16) -> [success: bb8, unwind continue]; +- _19 = Lt(copy _18, const 4_usize); +- assert(move _19, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _18) -> [success: bb8, unwind continue]; ++ _19 = Lt(copy _16, const 4_usize); ++ assert(move _19, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _16) -> [success: bb8, unwind continue]; } bb7: { diff --git a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-abort.diff index a46daef435f..0275d7e8a0d 100644 --- a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-abort.diff @@ -6,8 +6,7 @@ let _1: u32; let mut _2: [u32; 4]; let _3: usize; - let mut _4: usize; - let mut _5: bool; + let mut _4: bool; scope 1 { debug x => _1; } @@ -18,11 +17,9 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); -- _5 = Lt(copy _3, copy _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable]; -+ _4 = const 4_usize; -+ _5 = const true; +- _4 = Lt(copy _3, const 4_usize); +- assert(move _4, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _3) -> [success: bb1, unwind unreachable]; ++ _4 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-unwind.diff index 1a4e15b45fa..490ed4b55a1 100644 --- a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-unwind.diff @@ -6,8 +6,7 @@ let _1: u32; let mut _2: [u32; 4]; let _3: usize; - let mut _4: usize; - let mut _5: bool; + let mut _4: bool; scope 1 { debug x => _1; } @@ -18,11 +17,9 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); -- _5 = Lt(copy _3, copy _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue]; -+ _4 = const 4_usize; -+ _5 = const true; +- _4 = Lt(copy _3, const 4_usize); +- assert(move _4, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _3) -> [success: bb1, unwind continue]; ++ _4 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind continue]; } diff --git a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-abort.diff index a46daef435f..0275d7e8a0d 100644 --- a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-abort.diff @@ -6,8 +6,7 @@ let _1: u32; let mut _2: [u32; 4]; let _3: usize; - let mut _4: usize; - let mut _5: bool; + let mut _4: bool; scope 1 { debug x => _1; } @@ -18,11 +17,9 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); -- _5 = Lt(copy _3, copy _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable]; -+ _4 = const 4_usize; -+ _5 = const true; +- _4 = Lt(copy _3, const 4_usize); +- assert(move _4, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _3) -> [success: bb1, unwind unreachable]; ++ _4 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-unwind.diff index 1a4e15b45fa..490ed4b55a1 100644 --- a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-unwind.diff @@ -6,8 +6,7 @@ let _1: u32; let mut _2: [u32; 4]; let _3: usize; - let mut _4: usize; - let mut _5: bool; + let mut _4: bool; scope 1 { debug x => _1; } @@ -18,11 +17,9 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); -- _5 = Lt(copy _3, copy _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue]; -+ _4 = const 4_usize; -+ _5 = const true; +- _4 = Lt(copy _3, const 4_usize); +- assert(move _4, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _3) -> [success: bb1, unwind continue]; ++ _4 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind continue]; } diff --git a/tests/mir-opt/dataflow-const-prop/array_index.rs b/tests/mir-opt/dataflow-const-prop/array_index.rs index e442ef99f79..1aa8dcd28f4 100644 --- a/tests/mir-opt/dataflow-const-prop/array_index.rs +++ b/tests/mir-opt/dataflow-const-prop/array_index.rs @@ -11,9 +11,10 @@ fn main() { // CHECK: [[array_lit]] = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; // CHECK-NOT: {{_.*}} = Len( + // CHECK-NOT: {{_.*}} = PtrMetadata( // CHECK-NOT: {{_.*}} = Lt( // CHECK-NOT: assert(move _ - // CHECK: {{_.*}} = const 4_usize; + // CHECK: {{_.*}} = const 2_usize; // CHECK: {{_.*}} = const true; // CHECK: assert(const true // CHECK: [[x]] = copy [[array_lit]][2 of 3]; diff --git a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-abort.diff index b7ff0b671f7..f0d59ef5923 100644 --- a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-abort.diff @@ -6,8 +6,7 @@ let _1: u8; let mut _2: [u8; 5000]; let _3: usize; - let mut _4: usize; - let mut _5: bool; + let mut _4: bool; scope 1 { debug x => _1; } @@ -18,11 +17,9 @@ _2 = [const 0_u8; 5000]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); -- _5 = Lt(copy _3, copy _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable]; -+ _4 = const 5000_usize; -+ _5 = const true; +- _4 = Lt(copy _3, const 5000_usize); +- assert(move _4, "index out of bounds: the length is {} but the index is {}", const 5000_usize, copy _3) -> [success: bb1, unwind unreachable]; ++ _4 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-unwind.diff index af6e3626142..959c3e75214 100644 --- a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-unwind.diff @@ -6,8 +6,7 @@ let _1: u8; let mut _2: [u8; 5000]; let _3: usize; - let mut _4: usize; - let mut _5: bool; + let mut _4: bool; scope 1 { debug x => _1; } @@ -18,11 +17,9 @@ _2 = [const 0_u8; 5000]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); -- _5 = Lt(copy _3, copy _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue]; -+ _4 = const 5000_usize; -+ _5 = const true; +- _4 = Lt(copy _3, const 5000_usize); +- assert(move _4, "index out of bounds: the length is {} but the index is {}", const 5000_usize, copy _3) -> [success: bb1, unwind continue]; ++ _4 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind continue]; } diff --git a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-abort.diff index b7ff0b671f7..f0d59ef5923 100644 --- a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-abort.diff @@ -6,8 +6,7 @@ let _1: u8; let mut _2: [u8; 5000]; let _3: usize; - let mut _4: usize; - let mut _5: bool; + let mut _4: bool; scope 1 { debug x => _1; } @@ -18,11 +17,9 @@ _2 = [const 0_u8; 5000]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); -- _5 = Lt(copy _3, copy _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable]; -+ _4 = const 5000_usize; -+ _5 = const true; +- _4 = Lt(copy _3, const 5000_usize); +- assert(move _4, "index out of bounds: the length is {} but the index is {}", const 5000_usize, copy _3) -> [success: bb1, unwind unreachable]; ++ _4 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-unwind.diff index af6e3626142..959c3e75214 100644 --- a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-unwind.diff @@ -6,8 +6,7 @@ let _1: u8; let mut _2: [u8; 5000]; let _3: usize; - let mut _4: usize; - let mut _5: bool; + let mut _4: bool; scope 1 { debug x => _1; } @@ -18,11 +17,9 @@ _2 = [const 0_u8; 5000]; StorageLive(_3); _3 = const 2_usize; -- _4 = Len(_2); -- _5 = Lt(copy _3, copy _4); -- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue]; -+ _4 = const 5000_usize; -+ _5 = const true; +- _4 = Lt(copy _3, const 5000_usize); +- assert(move _4, "index out of bounds: the length is {} but the index is {}", const 5000_usize, copy _3) -> [success: bb1, unwind continue]; ++ _4 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind continue]; } diff --git a/tests/mir-opt/dataflow-const-prop/large_array_index.rs b/tests/mir-opt/dataflow-const-prop/large_array_index.rs index e9f2fa2badf..e490cfde247 100644 --- a/tests/mir-opt/dataflow-const-prop/large_array_index.rs +++ b/tests/mir-opt/dataflow-const-prop/large_array_index.rs @@ -10,7 +10,7 @@ fn main() { // CHECK: debug x => [[x:_.*]]; // CHECK: [[array_lit:_.*]] = [const 0_u8; 5000]; - // CHECK: {{_.*}} = const 5000_usize; + // CHECK: {{_.*}} = const 2_usize; // CHECK: {{_.*}} = const true; // CHECK: assert(const true // CHECK: [[x]] = copy [[array_lit]][2 of 3]; diff --git a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-abort.diff index dfa541b1200..618121ea632 100644 --- a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-abort.diff @@ -7,8 +7,7 @@ let mut _2: u32; let mut _3: [u32; 8]; let _4: usize; - let mut _5: usize; - let mut _6: bool; + let mut _5: bool; scope 1 { debug x => _1; } @@ -20,11 +19,9 @@ _3 = [const 42_u32; 8]; StorageLive(_4); _4 = const 2_usize; -- _5 = Len(_3); -- _6 = Lt(copy _4, copy _5); -- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind unreachable]; -+ _5 = const 8_usize; -+ _6 = const true; +- _5 = Lt(copy _4, const 8_usize); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", const 8_usize, copy _4) -> [success: bb1, unwind unreachable]; ++ _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-unwind.diff index 9ede3c5f7ac..1788f58432b 100644 --- a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-unwind.diff @@ -7,8 +7,7 @@ let mut _2: u32; let mut _3: [u32; 8]; let _4: usize; - let mut _5: usize; - let mut _6: bool; + let mut _5: bool; scope 1 { debug x => _1; } @@ -20,11 +19,9 @@ _3 = [const 42_u32; 8]; StorageLive(_4); _4 = const 2_usize; -- _5 = Len(_3); -- _6 = Lt(copy _4, copy _5); -- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind continue]; -+ _5 = const 8_usize; -+ _6 = const true; +- _5 = Lt(copy _4, const 8_usize); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", const 8_usize, copy _4) -> [success: bb1, unwind continue]; ++ _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind continue]; } diff --git a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-abort.diff index dfa541b1200..618121ea632 100644 --- a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-abort.diff @@ -7,8 +7,7 @@ let mut _2: u32; let mut _3: [u32; 8]; let _4: usize; - let mut _5: usize; - let mut _6: bool; + let mut _5: bool; scope 1 { debug x => _1; } @@ -20,11 +19,9 @@ _3 = [const 42_u32; 8]; StorageLive(_4); _4 = const 2_usize; -- _5 = Len(_3); -- _6 = Lt(copy _4, copy _5); -- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind unreachable]; -+ _5 = const 8_usize; -+ _6 = const true; +- _5 = Lt(copy _4, const 8_usize); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", const 8_usize, copy _4) -> [success: bb1, unwind unreachable]; ++ _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-unwind.diff index 9ede3c5f7ac..1788f58432b 100644 --- a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-unwind.diff @@ -7,8 +7,7 @@ let mut _2: u32; let mut _3: [u32; 8]; let _4: usize; - let mut _5: usize; - let mut _6: bool; + let mut _5: bool; scope 1 { debug x => _1; } @@ -20,11 +19,9 @@ _3 = [const 42_u32; 8]; StorageLive(_4); _4 = const 2_usize; -- _5 = Len(_3); -- _6 = Lt(copy _4, copy _5); -- assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind continue]; -+ _5 = const 8_usize; -+ _6 = const true; +- _5 = Lt(copy _4, const 8_usize); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", const 8_usize, copy _4) -> [success: bb1, unwind continue]; ++ _5 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind continue]; } diff --git a/tests/mir-opt/dataflow-const-prop/repeat.rs b/tests/mir-opt/dataflow-const-prop/repeat.rs index 2067aa3d709..1bc2cb82a60 100644 --- a/tests/mir-opt/dataflow-const-prop/repeat.rs +++ b/tests/mir-opt/dataflow-const-prop/repeat.rs @@ -9,8 +9,9 @@ fn main() { // CHECK: [[array_lit:_.*]] = [const 42_u32; 8]; // CHECK-NOT: {{_.*}} = Len( + // CHECK-NOT: {{_.*}} = PtrMetadata( // CHECK-NOT: {{_.*}} = Lt( - // CHECK: {{_.*}} = const 8_usize; + // CHECK: {{_.*}} = const 2_usize; // CHECK: {{_.*}} = const true; // CHECK: assert(const true diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-abort.diff deleted file mode 100644 index e71992316dc..00000000000 --- a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-abort.diff +++ /dev/null @@ -1,77 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); - let _1: u32; - let mut _2: &[u32]; - let mut _3: &[u32; 3]; - let _4: &[u32; 3]; - let _5: [u32; 3]; - let _6: usize; - let mut _7: usize; - let mut _8: bool; - let mut _10: &[u32]; - let _11: usize; - let mut _12: usize; - let mut _13: bool; - let mut _14: &[u32; 3]; - scope 1 { - debug local => _1; - let _9: u32; - scope 2 { - debug constant => _9; - } - } - - bb0: { - StorageLive(_1); - StorageLive(_2); - StorageLive(_3); - StorageLive(_4); - _14 = const main::promoted[0]; - _4 = copy _14; - _3 = copy _4; - _2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast)); - StorageDead(_3); - StorageLive(_6); - _6 = const 1_usize; -- _7 = Len((*_2)); -- _8 = Lt(copy _6, copy _7); -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable]; -+ _7 = const 3_usize; -+ _8 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind unreachable]; - } - - bb1: { -- _1 = copy (*_2)[_6]; -+ _1 = copy (*_2)[1 of 2]; - StorageDead(_6); - StorageDead(_4); - StorageDead(_2); - StorageLive(_9); - StorageLive(_10); - _10 = const main::SLICE; - StorageLive(_11); - _11 = const 1_usize; -- _12 = Len((*_10)); -- _13 = Lt(copy _11, copy _12); -- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind unreachable]; -+ _12 = const 3_usize; -+ _13 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind unreachable]; - } - - bb2: { -- _9 = copy (*_10)[_11]; -+ _9 = copy (*_10)[1 of 2]; - StorageDead(_11); - StorageDead(_10); - _0 = const (); - StorageDead(_9); - StorageDead(_1); - return; - } - } - diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-unwind.diff deleted file mode 100644 index 26de8595768..00000000000 --- a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-unwind.diff +++ /dev/null @@ -1,77 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); - let _1: u32; - let mut _2: &[u32]; - let mut _3: &[u32; 3]; - let _4: &[u32; 3]; - let _5: [u32; 3]; - let _6: usize; - let mut _7: usize; - let mut _8: bool; - let mut _10: &[u32]; - let _11: usize; - let mut _12: usize; - let mut _13: bool; - let mut _14: &[u32; 3]; - scope 1 { - debug local => _1; - let _9: u32; - scope 2 { - debug constant => _9; - } - } - - bb0: { - StorageLive(_1); - StorageLive(_2); - StorageLive(_3); - StorageLive(_4); - _14 = const main::promoted[0]; - _4 = copy _14; - _3 = copy _4; - _2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast)); - StorageDead(_3); - StorageLive(_6); - _6 = const 1_usize; -- _7 = Len((*_2)); -- _8 = Lt(copy _6, copy _7); -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue]; -+ _7 = const 3_usize; -+ _8 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind continue]; - } - - bb1: { -- _1 = copy (*_2)[_6]; -+ _1 = copy (*_2)[1 of 2]; - StorageDead(_6); - StorageDead(_4); - StorageDead(_2); - StorageLive(_9); - StorageLive(_10); - _10 = const main::SLICE; - StorageLive(_11); - _11 = const 1_usize; -- _12 = Len((*_10)); -- _13 = Lt(copy _11, copy _12); -- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind continue]; -+ _12 = const 3_usize; -+ _13 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind continue]; - } - - bb2: { -- _9 = copy (*_10)[_11]; -+ _9 = copy (*_10)[1 of 2]; - StorageDead(_11); - StorageDead(_10); - _0 = const (); - StorageDead(_9); - StorageDead(_1); - return; - } - } - diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-abort.diff deleted file mode 100644 index e71992316dc..00000000000 --- a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-abort.diff +++ /dev/null @@ -1,77 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); - let _1: u32; - let mut _2: &[u32]; - let mut _3: &[u32; 3]; - let _4: &[u32; 3]; - let _5: [u32; 3]; - let _6: usize; - let mut _7: usize; - let mut _8: bool; - let mut _10: &[u32]; - let _11: usize; - let mut _12: usize; - let mut _13: bool; - let mut _14: &[u32; 3]; - scope 1 { - debug local => _1; - let _9: u32; - scope 2 { - debug constant => _9; - } - } - - bb0: { - StorageLive(_1); - StorageLive(_2); - StorageLive(_3); - StorageLive(_4); - _14 = const main::promoted[0]; - _4 = copy _14; - _3 = copy _4; - _2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast)); - StorageDead(_3); - StorageLive(_6); - _6 = const 1_usize; -- _7 = Len((*_2)); -- _8 = Lt(copy _6, copy _7); -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable]; -+ _7 = const 3_usize; -+ _8 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind unreachable]; - } - - bb1: { -- _1 = copy (*_2)[_6]; -+ _1 = copy (*_2)[1 of 2]; - StorageDead(_6); - StorageDead(_4); - StorageDead(_2); - StorageLive(_9); - StorageLive(_10); - _10 = const main::SLICE; - StorageLive(_11); - _11 = const 1_usize; -- _12 = Len((*_10)); -- _13 = Lt(copy _11, copy _12); -- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind unreachable]; -+ _12 = const 3_usize; -+ _13 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind unreachable]; - } - - bb2: { -- _9 = copy (*_10)[_11]; -+ _9 = copy (*_10)[1 of 2]; - StorageDead(_11); - StorageDead(_10); - _0 = const (); - StorageDead(_9); - StorageDead(_1); - return; - } - } - diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-unwind.diff deleted file mode 100644 index 26de8595768..00000000000 --- a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-unwind.diff +++ /dev/null @@ -1,77 +0,0 @@ -- // MIR for `main` before DataflowConstProp -+ // MIR for `main` after DataflowConstProp - - fn main() -> () { - let mut _0: (); - let _1: u32; - let mut _2: &[u32]; - let mut _3: &[u32; 3]; - let _4: &[u32; 3]; - let _5: [u32; 3]; - let _6: usize; - let mut _7: usize; - let mut _8: bool; - let mut _10: &[u32]; - let _11: usize; - let mut _12: usize; - let mut _13: bool; - let mut _14: &[u32; 3]; - scope 1 { - debug local => _1; - let _9: u32; - scope 2 { - debug constant => _9; - } - } - - bb0: { - StorageLive(_1); - StorageLive(_2); - StorageLive(_3); - StorageLive(_4); - _14 = const main::promoted[0]; - _4 = copy _14; - _3 = copy _4; - _2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast)); - StorageDead(_3); - StorageLive(_6); - _6 = const 1_usize; -- _7 = Len((*_2)); -- _8 = Lt(copy _6, copy _7); -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue]; -+ _7 = const 3_usize; -+ _8 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind continue]; - } - - bb1: { -- _1 = copy (*_2)[_6]; -+ _1 = copy (*_2)[1 of 2]; - StorageDead(_6); - StorageDead(_4); - StorageDead(_2); - StorageLive(_9); - StorageLive(_10); - _10 = const main::SLICE; - StorageLive(_11); - _11 = const 1_usize; -- _12 = Len((*_10)); -- _13 = Lt(copy _11, copy _12); -- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind continue]; -+ _12 = const 3_usize; -+ _13 = const true; -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind continue]; - } - - bb2: { -- _9 = copy (*_10)[_11]; -+ _9 = copy (*_10)[1 of 2]; - StorageDead(_11); - StorageDead(_10); - _0 = const (); - StorageDead(_9); - StorageDead(_1); - return; - } - } - diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.rs b/tests/mir-opt/dataflow-const-prop/slice_len.rs deleted file mode 100644 index e0e68f9fde5..00000000000 --- a/tests/mir-opt/dataflow-const-prop/slice_len.rs +++ /dev/null @@ -1,34 +0,0 @@ -// EMIT_MIR_FOR_EACH_PANIC_STRATEGY -//@ test-mir-pass: DataflowConstProp -//@ compile-flags: -Zmir-enable-passes=+InstSimplify-after-simplifycfg -// EMIT_MIR_FOR_EACH_BIT_WIDTH - -// EMIT_MIR slice_len.main.DataflowConstProp.diff - -// CHECK-LABEL: fn main( -fn main() { - // CHECK: debug local => [[local:_.*]]; - // CHECK: debug constant => [[constant:_.*]]; - - // CHECK-NOT: {{_.*}} = Len( - // CHECK-NOT: {{_.*}} = Lt( - // CHECK-NOT: assert(move _ - // CHECK: {{_.*}} = const 3_usize; - // CHECK: {{_.*}} = const true; - // CHECK: assert(const true, - - // CHECK: [[local]] = copy (*{{_.*}})[1 of 2]; - let local = (&[1u32, 2, 3] as &[u32])[1]; - - // CHECK-NOT: {{_.*}} = Len( - // CHECK-NOT: {{_.*}} = Lt( - // CHECK-NOT: assert(move _ - const SLICE: &[u32] = &[1, 2, 3]; - // CHECK: {{_.*}} = const 3_usize; - // CHECK: {{_.*}} = const true; - // CHECK: assert(const true, - - // CHECK-NOT: [[constant]] = {{copy|move}} (*{{_.*}})[_ - // CHECK: [[constant]] = copy (*{{_.*}})[1 of 2]; - let constant = SLICE[1]; -} diff --git a/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-abort.diff b/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-abort.diff index 3f052ee19fd..183b4d2599f 100644 --- a/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-abort.diff @@ -53,7 +53,7 @@ StorageLive(_8); - _8 = copy _2; + _8 = const usize::MAX; - _9 = Len((*_1)); + _9 = PtrMetadata(copy _1); - _10 = Lt(copy _8, copy _9); - assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb3, unwind unreachable]; + _10 = Lt(const usize::MAX, copy _9); @@ -72,7 +72,7 @@ StorageDead(_5); StorageLive(_11); _11 = const 0_usize; - _12 = Len((*_1)); + _12 = PtrMetadata(copy _1); - _13 = Lt(copy _11, copy _12); - assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb5, unwind unreachable]; + _13 = Lt(const 0_usize, copy _12); diff --git a/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-unwind.diff b/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-unwind.diff index 84b738c7804..03e8aa3bd9b 100644 --- a/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-unwind.diff @@ -53,7 +53,7 @@ StorageLive(_8); - _8 = copy _2; + _8 = const usize::MAX; - _9 = Len((*_1)); + _9 = PtrMetadata(copy _1); - _10 = Lt(copy _8, copy _9); - assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb3, unwind continue]; + _10 = Lt(const usize::MAX, copy _9); @@ -72,7 +72,7 @@ StorageDead(_5); StorageLive(_11); _11 = const 0_usize; - _12 = Len((*_1)); + _12 = PtrMetadata(copy _1); - _13 = Lt(copy _11, copy _12); - assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb5, unwind continue]; + _13 = Lt(const 0_usize, copy _12); diff --git a/tests/mir-opt/gvn.dedup_multiple_bounds_checks_lengths.GVN.panic-abort.diff b/tests/mir-opt/gvn.dedup_multiple_bounds_checks_lengths.GVN.panic-abort.diff new file mode 100644 index 00000000000..4b077f580f1 --- /dev/null +++ b/tests/mir-opt/gvn.dedup_multiple_bounds_checks_lengths.GVN.panic-abort.diff @@ -0,0 +1,72 @@ +- // MIR for `dedup_multiple_bounds_checks_lengths` before GVN ++ // MIR for `dedup_multiple_bounds_checks_lengths` after GVN + + fn dedup_multiple_bounds_checks_lengths(_1: &[i32]) -> [i32; 3] { + debug x => _1; + let mut _0: [i32; 3]; + let mut _2: i32; + let _3: usize; + let mut _4: usize; + let mut _5: bool; + let mut _6: i32; + let _7: usize; + let mut _8: usize; + let mut _9: bool; + let mut _10: i32; + let _11: usize; + let mut _12: usize; + let mut _13: bool; + + bb0: { + StorageLive(_2); + StorageLive(_3); + _3 = const 42_usize; + _4 = PtrMetadata(copy _1); +- _5 = Lt(copy _3, copy _4); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable]; ++ _5 = Lt(const 42_usize, copy _4); ++ assert(move _5, "index out of bounds: the length is {} but the index is {}", copy _4, const 42_usize) -> [success: bb1, unwind unreachable]; + } + + bb1: { +- _2 = copy (*_1)[_3]; ++ _2 = copy (*_1)[42 of 43]; + StorageLive(_6); + StorageLive(_7); + _7 = const 13_usize; +- _8 = PtrMetadata(copy _1); +- _9 = Lt(copy _7, copy _8); +- assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb2, unwind unreachable]; ++ _8 = copy _4; ++ _9 = Lt(const 13_usize, copy _4); ++ assert(move _9, "index out of bounds: the length is {} but the index is {}", copy _4, const 13_usize) -> [success: bb2, unwind unreachable]; + } + + bb2: { +- _6 = copy (*_1)[_7]; ++ _6 = copy (*_1)[13 of 14]; + StorageLive(_10); + StorageLive(_11); + _11 = const 7_usize; +- _12 = PtrMetadata(copy _1); +- _13 = Lt(copy _11, copy _12); +- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb3, unwind unreachable]; ++ _12 = copy _4; ++ _13 = Lt(const 7_usize, copy _4); ++ assert(move _13, "index out of bounds: the length is {} but the index is {}", copy _4, const 7_usize) -> [success: bb3, unwind unreachable]; + } + + bb3: { +- _10 = copy (*_1)[_11]; ++ _10 = copy (*_1)[7 of 8]; + _0 = [move _2, move _6, move _10]; + StorageDead(_10); + StorageDead(_6); + StorageDead(_2); + StorageDead(_11); + StorageDead(_7); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/gvn.dedup_multiple_bounds_checks_lengths.GVN.panic-unwind.diff b/tests/mir-opt/gvn.dedup_multiple_bounds_checks_lengths.GVN.panic-unwind.diff new file mode 100644 index 00000000000..87e69d44006 --- /dev/null +++ b/tests/mir-opt/gvn.dedup_multiple_bounds_checks_lengths.GVN.panic-unwind.diff @@ -0,0 +1,72 @@ +- // MIR for `dedup_multiple_bounds_checks_lengths` before GVN ++ // MIR for `dedup_multiple_bounds_checks_lengths` after GVN + + fn dedup_multiple_bounds_checks_lengths(_1: &[i32]) -> [i32; 3] { + debug x => _1; + let mut _0: [i32; 3]; + let mut _2: i32; + let _3: usize; + let mut _4: usize; + let mut _5: bool; + let mut _6: i32; + let _7: usize; + let mut _8: usize; + let mut _9: bool; + let mut _10: i32; + let _11: usize; + let mut _12: usize; + let mut _13: bool; + + bb0: { + StorageLive(_2); + StorageLive(_3); + _3 = const 42_usize; + _4 = PtrMetadata(copy _1); +- _5 = Lt(copy _3, copy _4); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue]; ++ _5 = Lt(const 42_usize, copy _4); ++ assert(move _5, "index out of bounds: the length is {} but the index is {}", copy _4, const 42_usize) -> [success: bb1, unwind continue]; + } + + bb1: { +- _2 = copy (*_1)[_3]; ++ _2 = copy (*_1)[42 of 43]; + StorageLive(_6); + StorageLive(_7); + _7 = const 13_usize; +- _8 = PtrMetadata(copy _1); +- _9 = Lt(copy _7, copy _8); +- assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb2, unwind continue]; ++ _8 = copy _4; ++ _9 = Lt(const 13_usize, copy _4); ++ assert(move _9, "index out of bounds: the length is {} but the index is {}", copy _4, const 13_usize) -> [success: bb2, unwind continue]; + } + + bb2: { +- _6 = copy (*_1)[_7]; ++ _6 = copy (*_1)[13 of 14]; + StorageLive(_10); + StorageLive(_11); + _11 = const 7_usize; +- _12 = PtrMetadata(copy _1); +- _13 = Lt(copy _11, copy _12); +- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb3, unwind continue]; ++ _12 = copy _4; ++ _13 = Lt(const 7_usize, copy _4); ++ assert(move _13, "index out of bounds: the length is {} but the index is {}", copy _4, const 7_usize) -> [success: bb3, unwind continue]; + } + + bb3: { +- _10 = copy (*_1)[_11]; ++ _10 = copy (*_1)[7 of 8]; + _0 = [move _2, move _6, move _10]; + StorageDead(_10); + StorageDead(_6); + StorageDead(_2); + StorageDead(_11); + StorageDead(_7); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff b/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff index d4b22d05f6c..7f44176b756 100644 --- a/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff @@ -10,13 +10,11 @@ let _5: (); let mut _6: T; let _7: usize; - let mut _8: usize; - let mut _9: bool; - let _10: (); - let mut _11: T; - let _12: usize; - let mut _13: usize; - let mut _14: bool; + let mut _8: bool; + let _9: (); + let mut _10: T; + let _11: usize; + let mut _12: bool; scope 1 { debug a => _3; } @@ -32,12 +30,10 @@ StorageLive(_6); StorageLive(_7); _7 = const 0_usize; -- _8 = Len(_3); -- _9 = Lt(copy _7, copy _8); -- assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb1, unwind unreachable]; -+ _8 = const N; -+ _9 = Lt(const 0_usize, const N); -+ assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb1, unwind unreachable]; +- _8 = Lt(copy _7, const N); +- assert(move _8, "index out of bounds: the length is {} but the index is {}", const N, copy _7) -> [success: bb1, unwind unreachable]; ++ _8 = Lt(const 0_usize, const N); ++ assert(move _8, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb1, unwind unreachable]; } bb1: { @@ -51,29 +47,27 @@ StorageDead(_6); StorageDead(_7); StorageDead(_5); + StorageLive(_9); StorageLive(_10); StorageLive(_11); - StorageLive(_12); - _12 = copy _2; -- _13 = Len(_3); -- _14 = Lt(copy _12, copy _13); -- assert(move _14, "index out of bounds: the length is {} but the index is {}", move _13, copy _12) -> [success: bb3, unwind unreachable]; -+ _13 = const N; -+ _14 = Lt(copy _2, const N); -+ assert(move _14, "index out of bounds: the length is {} but the index is {}", const N, copy _2) -> [success: bb3, unwind unreachable]; + _11 = copy _2; +- _12 = Lt(copy _11, const N); +- assert(move _12, "index out of bounds: the length is {} but the index is {}", const N, copy _11) -> [success: bb3, unwind unreachable]; ++ _12 = Lt(copy _2, const N); ++ assert(move _12, "index out of bounds: the length is {} but the index is {}", const N, copy _2) -> [success: bb3, unwind unreachable]; } bb3: { -- _11 = copy _3[_12]; -- _10 = opaque::<T>(move _11) -> [return: bb4, unwind unreachable]; -+ _11 = copy _1; -+ _10 = opaque::<T>(copy _1) -> [return: bb4, unwind unreachable]; +- _10 = copy _3[_11]; +- _9 = opaque::<T>(move _10) -> [return: bb4, unwind unreachable]; ++ _10 = copy _1; ++ _9 = opaque::<T>(copy _1) -> [return: bb4, unwind unreachable]; } bb4: { - StorageDead(_11); - StorageDead(_12); StorageDead(_10); + StorageDead(_11); + StorageDead(_9); _0 = const (); StorageDead(_3); return; diff --git a/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff b/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff index 708c0f92e54..d34882d725f 100644 --- a/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff @@ -10,13 +10,11 @@ let _5: (); let mut _6: T; let _7: usize; - let mut _8: usize; - let mut _9: bool; - let _10: (); - let mut _11: T; - let _12: usize; - let mut _13: usize; - let mut _14: bool; + let mut _8: bool; + let _9: (); + let mut _10: T; + let _11: usize; + let mut _12: bool; scope 1 { debug a => _3; } @@ -32,12 +30,10 @@ StorageLive(_6); StorageLive(_7); _7 = const 0_usize; -- _8 = Len(_3); -- _9 = Lt(copy _7, copy _8); -- assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb1, unwind continue]; -+ _8 = const N; -+ _9 = Lt(const 0_usize, const N); -+ assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb1, unwind continue]; +- _8 = Lt(copy _7, const N); +- assert(move _8, "index out of bounds: the length is {} but the index is {}", const N, copy _7) -> [success: bb1, unwind continue]; ++ _8 = Lt(const 0_usize, const N); ++ assert(move _8, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb1, unwind continue]; } bb1: { @@ -51,29 +47,27 @@ StorageDead(_6); StorageDead(_7); StorageDead(_5); + StorageLive(_9); StorageLive(_10); StorageLive(_11); - StorageLive(_12); - _12 = copy _2; -- _13 = Len(_3); -- _14 = Lt(copy _12, copy _13); -- assert(move _14, "index out of bounds: the length is {} but the index is {}", move _13, copy _12) -> [success: bb3, unwind continue]; -+ _13 = const N; -+ _14 = Lt(copy _2, const N); -+ assert(move _14, "index out of bounds: the length is {} but the index is {}", const N, copy _2) -> [success: bb3, unwind continue]; + _11 = copy _2; +- _12 = Lt(copy _11, const N); +- assert(move _12, "index out of bounds: the length is {} but the index is {}", const N, copy _11) -> [success: bb3, unwind continue]; ++ _12 = Lt(copy _2, const N); ++ assert(move _12, "index out of bounds: the length is {} but the index is {}", const N, copy _2) -> [success: bb3, unwind continue]; } bb3: { -- _11 = copy _3[_12]; -- _10 = opaque::<T>(move _11) -> [return: bb4, unwind continue]; -+ _11 = copy _1; -+ _10 = opaque::<T>(copy _1) -> [return: bb4, unwind continue]; +- _10 = copy _3[_11]; +- _9 = opaque::<T>(move _10) -> [return: bb4, unwind continue]; ++ _10 = copy _1; ++ _9 = opaque::<T>(copy _1) -> [return: bb4, unwind continue]; } bb4: { - StorageDead(_11); - StorageDead(_12); StorageDead(_10); + StorageDead(_11); + StorageDead(_9); _0 = const (); StorageDead(_3); return; diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index 97513248e23..19b58a917f8 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -835,6 +835,25 @@ fn array_len(x: &mut [i32; 42]) -> usize { std::intrinsics::ptr_metadata(x) } +// Check that we only load the length once, rather than all 3 times. +fn dedup_multiple_bounds_checks_lengths(x: &[i32]) -> [i32; 3] { + // CHECK-LABEL: fn dedup_multiple_bounds_checks_lengths + // CHECK: [[LEN:_.+]] = PtrMetadata(copy _1); + // CHECK: Lt(const 42_usize, copy [[LEN]]); + // CHECK: assert{{.+}}copy [[LEN]] + // CHECK: [[A:_.+]] = copy (*_1)[42 of 43]; + // CHECK-NOT: PtrMetadata + // CHECK: Lt(const 13_usize, copy [[LEN]]); + // CHECK: assert{{.+}}copy [[LEN]] + // CHECK: [[B:_.+]] = copy (*_1)[13 of 14]; + // CHECK-NOT: PtrMetadata + // CHECK: Lt(const 7_usize, copy [[LEN]]); + // CHECK: assert{{.+}}copy [[LEN]] + // CHECK: [[C:_.+]] = copy (*_1)[7 of 8]; + // CHECK: _0 = [move [[A]], move [[B]], move [[C]]] + [x[42], x[13], x[7]] +} + #[custom_mir(dialect = "runtime")] fn generic_cast_metadata<T, A: ?Sized, B: ?Sized>(ps: *const [T], pa: *const A, pb: *const B) { // CHECK-LABEL: fn generic_cast_metadata @@ -1012,6 +1031,7 @@ fn identity<T>(x: T) -> T { // EMIT_MIR gvn.casts_before_aggregate_raw_ptr.GVN.diff // EMIT_MIR gvn.manual_slice_mut_len.GVN.diff // EMIT_MIR gvn.array_len.GVN.diff +// EMIT_MIR gvn.dedup_multiple_bounds_checks_lengths.GVN.diff // EMIT_MIR gvn.generic_cast_metadata.GVN.diff // EMIT_MIR gvn.cast_pointer_eq.GVN.diff // EMIT_MIR gvn.cast_pointer_then_transmute.GVN.diff diff --git a/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-abort.diff b/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-abort.diff index 6b6152c1117..1b305e746f5 100644 --- a/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-abort.diff @@ -10,62 +10,60 @@ let mut _6: &i32; let _7: &i32; let _8: usize; - let mut _9: usize; - let mut _10: bool; - let mut _12: *const dyn std::marker::Send; - let _13: &dyn std::marker::Send; - let mut _14: &i32; - let _15: &i32; - let _16: usize; - let mut _17: usize; + let mut _9: bool; + let mut _11: *const dyn std::marker::Send; + let _12: &dyn std::marker::Send; + let mut _13: &i32; + let _14: &i32; + let _15: usize; + let mut _16: bool; + let _17: (); let mut _18: bool; - let _19: (); - let mut _20: bool; + let mut _19: *const dyn std::marker::Send; + let mut _20: *const dyn std::marker::Send; let mut _21: *const dyn std::marker::Send; - let mut _22: *const dyn std::marker::Send; - let mut _23: *const dyn std::marker::Send; - let _24: (); - let mut _25: bool; + let _22: (); + let mut _23: bool; + let mut _24: *const dyn std::marker::Send; + let mut _25: *const dyn std::marker::Send; let mut _26: *const dyn std::marker::Send; - let mut _27: *const dyn std::marker::Send; - let mut _28: *const dyn std::marker::Send; - let _29: (); - let mut _30: bool; + let _27: (); + let mut _28: bool; + let mut _29: *const dyn std::marker::Send; + let mut _30: *const dyn std::marker::Send; let mut _31: *const dyn std::marker::Send; - let mut _32: *const dyn std::marker::Send; - let mut _33: *const dyn std::marker::Send; - let _34: (); - let mut _35: bool; + let _32: (); + let mut _33: bool; + let mut _34: *const dyn std::marker::Send; + let mut _35: *const dyn std::marker::Send; let mut _36: *const dyn std::marker::Send; - let mut _37: *const dyn std::marker::Send; - let mut _38: *const dyn std::marker::Send; - let _39: (); - let mut _40: bool; + let _37: (); + let mut _38: bool; + let mut _39: *const dyn std::marker::Send; + let mut _40: *const dyn std::marker::Send; let mut _41: *const dyn std::marker::Send; - let mut _42: *const dyn std::marker::Send; - let mut _43: *const dyn std::marker::Send; - let _44: (); - let mut _45: bool; + let _42: (); + let mut _43: bool; + let mut _44: *const dyn std::marker::Send; + let mut _45: *const dyn std::marker::Send; let mut _46: *const dyn std::marker::Send; - let mut _47: *const dyn std::marker::Send; - let mut _48: *const dyn std::marker::Send; - let mut _49: &[i32; 2]; + let mut _47: &[i32; 2]; scope 1 { debug slice => _1; let _3: *const dyn std::marker::Send; scope 2 { debug a => _3; - let _11: *const dyn std::marker::Send; + let _10: *const dyn std::marker::Send; scope 3 { - debug b => _11; + debug b => _10; } } } bb0: { StorageLive(_1); - _49 = const wide_ptr_same_provenance::promoted[0]; - _1 = &(*_49); + _47 = const wide_ptr_same_provenance::promoted[0]; + _1 = &(*_47); StorageLive(_3); - StorageLive(_4); + nop; @@ -74,11 +72,9 @@ StorageLive(_7); StorageLive(_8); _8 = const 0_usize; -- _9 = Len((*_1)); -- _10 = Lt(copy _8, copy _9); -- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb1, unwind unreachable]; -+ _9 = const 2_usize; -+ _10 = const true; +- _9 = Lt(copy _8, const 2_usize); +- assert(move _9, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _8) -> [success: bb1, unwind unreachable]; ++ _9 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 2_usize, const 0_usize) -> [success: bb1, unwind unreachable]; } @@ -95,170 +91,168 @@ + nop; StorageDead(_7); StorageDead(_5); - StorageLive(_11); -- StorageLive(_12); + StorageLive(_10); +- StorageLive(_11); + nop; + StorageLive(_12); StorageLive(_13); StorageLive(_14); StorageLive(_15); - StorageLive(_16); - _16 = const 1_usize; -- _17 = Len((*_1)); -- _18 = Lt(copy _16, copy _17); -- assert(move _18, "index out of bounds: the length is {} but the index is {}", move _17, copy _16) -> [success: bb2, unwind unreachable]; -+ _17 = const 2_usize; -+ _18 = const true; + _15 = const 1_usize; +- _16 = Lt(copy _15, const 2_usize); +- assert(move _16, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _15) -> [success: bb2, unwind unreachable]; ++ _16 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 2_usize, const 1_usize) -> [success: bb2, unwind unreachable]; } bb2: { -- _15 = &(*_1)[_16]; -+ _15 = &(*_1)[1 of 2]; - _14 = &(*_15); - _13 = move _14 as &dyn std::marker::Send (PointerCoercion(Unsize, AsCast)); - StorageDead(_14); - _12 = &raw const (*_13); -- _11 = move _12 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); -- StorageDead(_12); -+ _11 = copy _12; -+ nop; - StorageDead(_15); +- _14 = &(*_1)[_15]; ++ _14 = &(*_1)[1 of 2]; + _13 = &(*_14); + _12 = move _13 as &dyn std::marker::Send (PointerCoercion(Unsize, AsCast)); StorageDead(_13); + _11 = &raw const (*_12); +- _10 = move _11 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); +- StorageDead(_11); ++ _10 = copy _11; ++ nop; + StorageDead(_14); + StorageDead(_12); + StorageLive(_17); + StorageLive(_18); StorageLive(_19); +- _19 = copy _3; ++ _19 = copy _4; StorageLive(_20); StorageLive(_21); -- _21 = copy _3; -+ _21 = copy _4; - StorageLive(_22); - StorageLive(_23); -- _23 = copy _11; -- _22 = move _23 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); -+ _23 = copy _12; -+ _22 = copy _12; - StorageDead(_23); -- _20 = Eq(move _21, move _22); -+ _20 = Eq(copy _4, copy _12); - StorageDead(_22); +- _21 = copy _10; +- _20 = move _21 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); ++ _21 = copy _11; ++ _20 = copy _11; StorageDead(_21); - _19 = opaque::<bool>(move _20) -> [return: bb3, unwind unreachable]; +- _18 = Eq(move _19, move _20); ++ _18 = Eq(copy _4, copy _11); + StorageDead(_20); + StorageDead(_19); + _17 = opaque::<bool>(move _18) -> [return: bb3, unwind unreachable]; } bb3: { - StorageDead(_20); - StorageDead(_19); + StorageDead(_18); + StorageDead(_17); + StorageLive(_22); + StorageLive(_23); StorageLive(_24); +- _24 = copy _3; ++ _24 = copy _4; StorageLive(_25); StorageLive(_26); -- _26 = copy _3; -+ _26 = copy _4; - StorageLive(_27); - StorageLive(_28); -- _28 = copy _11; -- _27 = move _28 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); -+ _28 = copy _12; -+ _27 = copy _12; - StorageDead(_28); -- _25 = Ne(move _26, move _27); -+ _25 = Ne(copy _4, copy _12); - StorageDead(_27); +- _26 = copy _10; +- _25 = move _26 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); ++ _26 = copy _11; ++ _25 = copy _11; StorageDead(_26); - _24 = opaque::<bool>(move _25) -> [return: bb4, unwind unreachable]; +- _23 = Ne(move _24, move _25); ++ _23 = Ne(copy _4, copy _11); + StorageDead(_25); + StorageDead(_24); + _22 = opaque::<bool>(move _23) -> [return: bb4, unwind unreachable]; } bb4: { - StorageDead(_25); - StorageDead(_24); + StorageDead(_23); + StorageDead(_22); + StorageLive(_27); + StorageLive(_28); StorageLive(_29); +- _29 = copy _3; ++ _29 = copy _4; StorageLive(_30); StorageLive(_31); -- _31 = copy _3; -+ _31 = copy _4; - StorageLive(_32); - StorageLive(_33); -- _33 = copy _11; -- _32 = move _33 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); -+ _33 = copy _12; -+ _32 = copy _12; - StorageDead(_33); -- _30 = Lt(move _31, move _32); -+ _30 = Lt(copy _4, copy _12); - StorageDead(_32); +- _31 = copy _10; +- _30 = move _31 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); ++ _31 = copy _11; ++ _30 = copy _11; StorageDead(_31); - _29 = opaque::<bool>(move _30) -> [return: bb5, unwind unreachable]; +- _28 = Lt(move _29, move _30); ++ _28 = Lt(copy _4, copy _11); + StorageDead(_30); + StorageDead(_29); + _27 = opaque::<bool>(move _28) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_30); - StorageDead(_29); + StorageDead(_28); + StorageDead(_27); + StorageLive(_32); + StorageLive(_33); StorageLive(_34); +- _34 = copy _3; ++ _34 = copy _4; StorageLive(_35); StorageLive(_36); -- _36 = copy _3; -+ _36 = copy _4; - StorageLive(_37); - StorageLive(_38); -- _38 = copy _11; -- _37 = move _38 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); -+ _38 = copy _12; -+ _37 = copy _12; - StorageDead(_38); -- _35 = Le(move _36, move _37); -+ _35 = Le(copy _4, copy _12); - StorageDead(_37); +- _36 = copy _10; +- _35 = move _36 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); ++ _36 = copy _11; ++ _35 = copy _11; StorageDead(_36); - _34 = opaque::<bool>(move _35) -> [return: bb6, unwind unreachable]; +- _33 = Le(move _34, move _35); ++ _33 = Le(copy _4, copy _11); + StorageDead(_35); + StorageDead(_34); + _32 = opaque::<bool>(move _33) -> [return: bb6, unwind unreachable]; } bb6: { - StorageDead(_35); - StorageDead(_34); + StorageDead(_33); + StorageDead(_32); + StorageLive(_37); + StorageLive(_38); StorageLive(_39); +- _39 = copy _3; ++ _39 = copy _4; StorageLive(_40); StorageLive(_41); -- _41 = copy _3; -+ _41 = copy _4; - StorageLive(_42); - StorageLive(_43); -- _43 = copy _11; -- _42 = move _43 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); -+ _43 = copy _12; -+ _42 = copy _12; - StorageDead(_43); -- _40 = Gt(move _41, move _42); -+ _40 = Gt(copy _4, copy _12); - StorageDead(_42); +- _41 = copy _10; +- _40 = move _41 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); ++ _41 = copy _11; ++ _40 = copy _11; StorageDead(_41); - _39 = opaque::<bool>(move _40) -> [return: bb7, unwind unreachable]; +- _38 = Gt(move _39, move _40); ++ _38 = Gt(copy _4, copy _11); + StorageDead(_40); + StorageDead(_39); + _37 = opaque::<bool>(move _38) -> [return: bb7, unwind unreachable]; } bb7: { - StorageDead(_40); - StorageDead(_39); + StorageDead(_38); + StorageDead(_37); + StorageLive(_42); + StorageLive(_43); StorageLive(_44); +- _44 = copy _3; ++ _44 = copy _4; StorageLive(_45); StorageLive(_46); -- _46 = copy _3; -+ _46 = copy _4; - StorageLive(_47); - StorageLive(_48); -- _48 = copy _11; -- _47 = move _48 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); -+ _48 = copy _12; -+ _47 = copy _12; - StorageDead(_48); -- _45 = Ge(move _46, move _47); -+ _45 = Ge(copy _4, copy _12); - StorageDead(_47); +- _46 = copy _10; +- _45 = move _46 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); ++ _46 = copy _11; ++ _45 = copy _11; StorageDead(_46); - _44 = opaque::<bool>(move _45) -> [return: bb8, unwind unreachable]; +- _43 = Ge(move _44, move _45); ++ _43 = Ge(copy _4, copy _11); + StorageDead(_45); + StorageDead(_44); + _42 = opaque::<bool>(move _43) -> [return: bb8, unwind unreachable]; } bb8: { - StorageDead(_45); - StorageDead(_44); + StorageDead(_43); + StorageDead(_42); _0 = const (); - StorageDead(_16); - StorageDead(_11); + StorageDead(_15); + StorageDead(_10); StorageDead(_8); StorageDead(_3); StorageDead(_1); diff --git a/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-unwind.diff b/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-unwind.diff index 093c1ec6ce3..e418ecf25bd 100644 --- a/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-unwind.diff @@ -10,62 +10,60 @@ let mut _6: &i32; let _7: &i32; let _8: usize; - let mut _9: usize; - let mut _10: bool; - let mut _12: *const dyn std::marker::Send; - let _13: &dyn std::marker::Send; - let mut _14: &i32; - let _15: &i32; - let _16: usize; - let mut _17: usize; + let mut _9: bool; + let mut _11: *const dyn std::marker::Send; + let _12: &dyn std::marker::Send; + let mut _13: &i32; + let _14: &i32; + let _15: usize; + let mut _16: bool; + let _17: (); let mut _18: bool; - let _19: (); - let mut _20: bool; + let mut _19: *const dyn std::marker::Send; + let mut _20: *const dyn std::marker::Send; let mut _21: *const dyn std::marker::Send; - let mut _22: *const dyn std::marker::Send; - let mut _23: *const dyn std::marker::Send; - let _24: (); - let mut _25: bool; + let _22: (); + let mut _23: bool; + let mut _24: *const dyn std::marker::Send; + let mut _25: *const dyn std::marker::Send; let mut _26: *const dyn std::marker::Send; - let mut _27: *const dyn std::marker::Send; - let mut _28: *const dyn std::marker::Send; - let _29: (); - let mut _30: bool; + let _27: (); + let mut _28: bool; + let mut _29: *const dyn std::marker::Send; + let mut _30: *const dyn std::marker::Send; let mut _31: *const dyn std::marker::Send; - let mut _32: *const dyn std::marker::Send; - let mut _33: *const dyn std::marker::Send; - let _34: (); - let mut _35: bool; + let _32: (); + let mut _33: bool; + let mut _34: *const dyn std::marker::Send; + let mut _35: *const dyn std::marker::Send; let mut _36: *const dyn std::marker::Send; - let mut _37: *const dyn std::marker::Send; - let mut _38: *const dyn std::marker::Send; - let _39: (); - let mut _40: bool; + let _37: (); + let mut _38: bool; + let mut _39: *const dyn std::marker::Send; + let mut _40: *const dyn std::marker::Send; let mut _41: *const dyn std::marker::Send; - let mut _42: *const dyn std::marker::Send; - let mut _43: *const dyn std::marker::Send; - let _44: (); - let mut _45: bool; + let _42: (); + let mut _43: bool; + let mut _44: *const dyn std::marker::Send; + let mut _45: *const dyn std::marker::Send; let mut _46: *const dyn std::marker::Send; - let mut _47: *const dyn std::marker::Send; - let mut _48: *const dyn std::marker::Send; - let mut _49: &[i32; 2]; + let mut _47: &[i32; 2]; scope 1 { debug slice => _1; let _3: *const dyn std::marker::Send; scope 2 { debug a => _3; - let _11: *const dyn std::marker::Send; + let _10: *const dyn std::marker::Send; scope 3 { - debug b => _11; + debug b => _10; } } } bb0: { StorageLive(_1); - _49 = const wide_ptr_same_provenance::promoted[0]; - _1 = &(*_49); + _47 = const wide_ptr_same_provenance::promoted[0]; + _1 = &(*_47); StorageLive(_3); - StorageLive(_4); + nop; @@ -74,11 +72,9 @@ StorageLive(_7); StorageLive(_8); _8 = const 0_usize; -- _9 = Len((*_1)); -- _10 = Lt(copy _8, copy _9); -- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb1, unwind continue]; -+ _9 = const 2_usize; -+ _10 = const true; +- _9 = Lt(copy _8, const 2_usize); +- assert(move _9, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _8) -> [success: bb1, unwind continue]; ++ _9 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 2_usize, const 0_usize) -> [success: bb1, unwind continue]; } @@ -95,170 +91,168 @@ + nop; StorageDead(_7); StorageDead(_5); - StorageLive(_11); -- StorageLive(_12); + StorageLive(_10); +- StorageLive(_11); + nop; + StorageLive(_12); StorageLive(_13); StorageLive(_14); StorageLive(_15); - StorageLive(_16); - _16 = const 1_usize; -- _17 = Len((*_1)); -- _18 = Lt(copy _16, copy _17); -- assert(move _18, "index out of bounds: the length is {} but the index is {}", move _17, copy _16) -> [success: bb2, unwind continue]; -+ _17 = const 2_usize; -+ _18 = const true; + _15 = const 1_usize; +- _16 = Lt(copy _15, const 2_usize); +- assert(move _16, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _15) -> [success: bb2, unwind continue]; ++ _16 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 2_usize, const 1_usize) -> [success: bb2, unwind continue]; } bb2: { -- _15 = &(*_1)[_16]; -+ _15 = &(*_1)[1 of 2]; - _14 = &(*_15); - _13 = move _14 as &dyn std::marker::Send (PointerCoercion(Unsize, AsCast)); - StorageDead(_14); - _12 = &raw const (*_13); -- _11 = move _12 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); -- StorageDead(_12); -+ _11 = copy _12; -+ nop; - StorageDead(_15); +- _14 = &(*_1)[_15]; ++ _14 = &(*_1)[1 of 2]; + _13 = &(*_14); + _12 = move _13 as &dyn std::marker::Send (PointerCoercion(Unsize, AsCast)); StorageDead(_13); + _11 = &raw const (*_12); +- _10 = move _11 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); +- StorageDead(_11); ++ _10 = copy _11; ++ nop; + StorageDead(_14); + StorageDead(_12); + StorageLive(_17); + StorageLive(_18); StorageLive(_19); +- _19 = copy _3; ++ _19 = copy _4; StorageLive(_20); StorageLive(_21); -- _21 = copy _3; -+ _21 = copy _4; - StorageLive(_22); - StorageLive(_23); -- _23 = copy _11; -- _22 = move _23 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); -+ _23 = copy _12; -+ _22 = copy _12; - StorageDead(_23); -- _20 = Eq(move _21, move _22); -+ _20 = Eq(copy _4, copy _12); - StorageDead(_22); +- _21 = copy _10; +- _20 = move _21 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); ++ _21 = copy _11; ++ _20 = copy _11; StorageDead(_21); - _19 = opaque::<bool>(move _20) -> [return: bb3, unwind continue]; +- _18 = Eq(move _19, move _20); ++ _18 = Eq(copy _4, copy _11); + StorageDead(_20); + StorageDead(_19); + _17 = opaque::<bool>(move _18) -> [return: bb3, unwind continue]; } bb3: { - StorageDead(_20); - StorageDead(_19); + StorageDead(_18); + StorageDead(_17); + StorageLive(_22); + StorageLive(_23); StorageLive(_24); +- _24 = copy _3; ++ _24 = copy _4; StorageLive(_25); StorageLive(_26); -- _26 = copy _3; -+ _26 = copy _4; - StorageLive(_27); - StorageLive(_28); -- _28 = copy _11; -- _27 = move _28 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); -+ _28 = copy _12; -+ _27 = copy _12; - StorageDead(_28); -- _25 = Ne(move _26, move _27); -+ _25 = Ne(copy _4, copy _12); - StorageDead(_27); +- _26 = copy _10; +- _25 = move _26 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); ++ _26 = copy _11; ++ _25 = copy _11; StorageDead(_26); - _24 = opaque::<bool>(move _25) -> [return: bb4, unwind continue]; +- _23 = Ne(move _24, move _25); ++ _23 = Ne(copy _4, copy _11); + StorageDead(_25); + StorageDead(_24); + _22 = opaque::<bool>(move _23) -> [return: bb4, unwind continue]; } bb4: { - StorageDead(_25); - StorageDead(_24); + StorageDead(_23); + StorageDead(_22); + StorageLive(_27); + StorageLive(_28); StorageLive(_29); +- _29 = copy _3; ++ _29 = copy _4; StorageLive(_30); StorageLive(_31); -- _31 = copy _3; -+ _31 = copy _4; - StorageLive(_32); - StorageLive(_33); -- _33 = copy _11; -- _32 = move _33 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); -+ _33 = copy _12; -+ _32 = copy _12; - StorageDead(_33); -- _30 = Lt(move _31, move _32); -+ _30 = Lt(copy _4, copy _12); - StorageDead(_32); +- _31 = copy _10; +- _30 = move _31 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); ++ _31 = copy _11; ++ _30 = copy _11; StorageDead(_31); - _29 = opaque::<bool>(move _30) -> [return: bb5, unwind continue]; +- _28 = Lt(move _29, move _30); ++ _28 = Lt(copy _4, copy _11); + StorageDead(_30); + StorageDead(_29); + _27 = opaque::<bool>(move _28) -> [return: bb5, unwind continue]; } bb5: { - StorageDead(_30); - StorageDead(_29); + StorageDead(_28); + StorageDead(_27); + StorageLive(_32); + StorageLive(_33); StorageLive(_34); +- _34 = copy _3; ++ _34 = copy _4; StorageLive(_35); StorageLive(_36); -- _36 = copy _3; -+ _36 = copy _4; - StorageLive(_37); - StorageLive(_38); -- _38 = copy _11; -- _37 = move _38 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); -+ _38 = copy _12; -+ _37 = copy _12; - StorageDead(_38); -- _35 = Le(move _36, move _37); -+ _35 = Le(copy _4, copy _12); - StorageDead(_37); +- _36 = copy _10; +- _35 = move _36 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); ++ _36 = copy _11; ++ _35 = copy _11; StorageDead(_36); - _34 = opaque::<bool>(move _35) -> [return: bb6, unwind continue]; +- _33 = Le(move _34, move _35); ++ _33 = Le(copy _4, copy _11); + StorageDead(_35); + StorageDead(_34); + _32 = opaque::<bool>(move _33) -> [return: bb6, unwind continue]; } bb6: { - StorageDead(_35); - StorageDead(_34); + StorageDead(_33); + StorageDead(_32); + StorageLive(_37); + StorageLive(_38); StorageLive(_39); +- _39 = copy _3; ++ _39 = copy _4; StorageLive(_40); StorageLive(_41); -- _41 = copy _3; -+ _41 = copy _4; - StorageLive(_42); - StorageLive(_43); -- _43 = copy _11; -- _42 = move _43 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); -+ _43 = copy _12; -+ _42 = copy _12; - StorageDead(_43); -- _40 = Gt(move _41, move _42); -+ _40 = Gt(copy _4, copy _12); - StorageDead(_42); +- _41 = copy _10; +- _40 = move _41 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); ++ _41 = copy _11; ++ _40 = copy _11; StorageDead(_41); - _39 = opaque::<bool>(move _40) -> [return: bb7, unwind continue]; +- _38 = Gt(move _39, move _40); ++ _38 = Gt(copy _4, copy _11); + StorageDead(_40); + StorageDead(_39); + _37 = opaque::<bool>(move _38) -> [return: bb7, unwind continue]; } bb7: { - StorageDead(_40); - StorageDead(_39); + StorageDead(_38); + StorageDead(_37); + StorageLive(_42); + StorageLive(_43); StorageLive(_44); +- _44 = copy _3; ++ _44 = copy _4; StorageLive(_45); StorageLive(_46); -- _46 = copy _3; -+ _46 = copy _4; - StorageLive(_47); - StorageLive(_48); -- _48 = copy _11; -- _47 = move _48 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); -+ _48 = copy _12; -+ _47 = copy _12; - StorageDead(_48); -- _45 = Ge(move _46, move _47); -+ _45 = Ge(copy _4, copy _12); - StorageDead(_47); +- _46 = copy _10; +- _45 = move _46 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit)); ++ _46 = copy _11; ++ _45 = copy _11; StorageDead(_46); - _44 = opaque::<bool>(move _45) -> [return: bb8, unwind continue]; +- _43 = Ge(move _44, move _45); ++ _43 = Ge(copy _4, copy _11); + StorageDead(_45); + StorageDead(_44); + _42 = opaque::<bool>(move _43) -> [return: bb8, unwind continue]; } bb8: { - StorageDead(_45); - StorageDead(_44); + StorageDead(_43); + StorageDead(_42); _0 = const (); - StorageDead(_16); - StorageDead(_11); + StorageDead(_15); + StorageDead(_10); StorageDead(_8); StorageDead(_3); StorageDead(_1); diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff index 94017f028cc..56d4d50e967 100644 --- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff @@ -16,7 +16,6 @@ + scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new) { + debug pointer => _3; + scope 4 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new_unchecked) { -+ debug pointer => _3; + } + } + scope 5 (inlined g::{closure#0}) { diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff index 858f9ace9b4..751916a00f1 100644 --- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff @@ -16,7 +16,6 @@ + scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new) { + debug pointer => _3; + scope 4 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new_unchecked) { -+ debug pointer => _3; + } + } + scope 5 (inlined g::{closure#0}) { diff --git a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff deleted file mode 100644 index f39df7ffca0..00000000000 --- a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff +++ /dev/null @@ -1,77 +0,0 @@ -- // MIR for `norm2` before InstSimplify-after-simplifycfg -+ // MIR for `norm2` after InstSimplify-after-simplifycfg - - fn norm2(_1: [f32; 2]) -> f32 { - debug x => _1; - let mut _0: f32; - let _2: f32; - let _3: usize; - let mut _4: usize; - let mut _5: bool; - let _7: usize; - let mut _8: usize; - let mut _9: bool; - let mut _10: f32; - let mut _11: f32; - let mut _12: f32; - let mut _13: f32; - let mut _14: f32; - let mut _15: f32; - scope 1 { - debug a => _2; - let _6: f32; - scope 2 { - debug b => _6; - } - } - - bb0: { - StorageLive(_2); - StorageLive(_3); - _3 = const 0_usize; -- _4 = Len(_1); -+ _4 = const 2_usize; - _5 = Lt(copy _3, copy _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable]; - } - - bb1: { - _2 = copy _1[_3]; - StorageDead(_3); - StorageLive(_6); - StorageLive(_7); - _7 = const 1_usize; -- _8 = Len(_1); -+ _8 = const 2_usize; - _9 = Lt(copy _7, copy _8); - assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb2, unwind unreachable]; - } - - bb2: { - _6 = copy _1[_7]; - StorageDead(_7); - StorageLive(_10); - StorageLive(_11); - _11 = copy _2; - StorageLive(_12); - _12 = copy _2; - _10 = Mul(move _11, move _12); - StorageDead(_12); - StorageDead(_11); - StorageLive(_13); - StorageLive(_14); - _14 = copy _6; - StorageLive(_15); - _15 = copy _6; - _13 = Mul(move _14, move _15); - StorageDead(_15); - StorageDead(_14); - _0 = Add(move _10, move _13); - StorageDead(_13); - StorageDead(_10); - StorageDead(_6); - StorageDead(_2); - return; - } - } - diff --git a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff deleted file mode 100644 index 0e7d5653c68..00000000000 --- a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff +++ /dev/null @@ -1,77 +0,0 @@ -- // MIR for `norm2` before InstSimplify-after-simplifycfg -+ // MIR for `norm2` after InstSimplify-after-simplifycfg - - fn norm2(_1: [f32; 2]) -> f32 { - debug x => _1; - let mut _0: f32; - let _2: f32; - let _3: usize; - let mut _4: usize; - let mut _5: bool; - let _7: usize; - let mut _8: usize; - let mut _9: bool; - let mut _10: f32; - let mut _11: f32; - let mut _12: f32; - let mut _13: f32; - let mut _14: f32; - let mut _15: f32; - scope 1 { - debug a => _2; - let _6: f32; - scope 2 { - debug b => _6; - } - } - - bb0: { - StorageLive(_2); - StorageLive(_3); - _3 = const 0_usize; -- _4 = Len(_1); -+ _4 = const 2_usize; - _5 = Lt(copy _3, copy _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue]; - } - - bb1: { - _2 = copy _1[_3]; - StorageDead(_3); - StorageLive(_6); - StorageLive(_7); - _7 = const 1_usize; -- _8 = Len(_1); -+ _8 = const 2_usize; - _9 = Lt(copy _7, copy _8); - assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb2, unwind continue]; - } - - bb2: { - _6 = copy _1[_7]; - StorageDead(_7); - StorageLive(_10); - StorageLive(_11); - _11 = copy _2; - StorageLive(_12); - _12 = copy _2; - _10 = Mul(move _11, move _12); - StorageDead(_12); - StorageDead(_11); - StorageLive(_13); - StorageLive(_14); - _14 = copy _6; - StorageLive(_15); - _15 = copy _6; - _13 = Mul(move _14, move _15); - StorageDead(_15); - StorageDead(_14); - _0 = Add(move _10, move _13); - StorageDead(_13); - StorageDead(_10); - StorageDead(_6); - StorageDead(_2); - return; - } - } - diff --git a/tests/mir-opt/instsimplify/combine_array_len.rs b/tests/mir-opt/instsimplify/combine_array_len.rs deleted file mode 100644 index 91f43f75689..00000000000 --- a/tests/mir-opt/instsimplify/combine_array_len.rs +++ /dev/null @@ -1,15 +0,0 @@ -// EMIT_MIR_FOR_EACH_PANIC_STRATEGY -//@ test-mir-pass: InstSimplify-after-simplifycfg - -// EMIT_MIR combine_array_len.norm2.InstSimplify-after-simplifycfg.diff -fn norm2(x: [f32; 2]) -> f32 { - // CHECK-LABEL: fn norm2( - // CHECK-NOT: Len( - let a = x[0]; - let b = x[1]; - a * a + b * b -} - -fn main() { - assert_eq!(norm2([3.0, 4.0]), 5.0 * 5.0); -} diff --git a/tests/mir-opt/issue_72181.foo.built.after.mir b/tests/mir-opt/issue_72181.foo.built.after.mir index 314cf8b367f..7593b795432 100644 --- a/tests/mir-opt/issue_72181.foo.built.after.mir +++ b/tests/mir-opt/issue_72181.foo.built.after.mir @@ -4,15 +4,14 @@ fn foo(_1: [(Never, u32); 1]) -> u32 { debug xs => _1; let mut _0: u32; let _2: usize; - let mut _3: usize; - let mut _4: bool; + let mut _3: bool; bb0: { StorageLive(_2); _2 = const 0_usize; - _3 = Len(_1); - _4 = Lt(copy _2, copy _3); - assert(move _4, "index out of bounds: the length is {} but the index is {}", move _3, copy _2) -> [success: bb1, unwind: bb2]; + FakeRead(ForIndex, _1); + _3 = Lt(copy _2, const 1_usize); + assert(move _3, "index out of bounds: the length is {} but the index is {}", const 1_usize, copy _2) -> [success: bb1, unwind: bb2]; } bb1: { diff --git a/tests/mir-opt/issue_72181.main.built.after.mir b/tests/mir-opt/issue_72181.main.built.after.mir index aade84a6dd2..9f3803f5407 100644 --- a/tests/mir-opt/issue_72181.main.built.after.mir +++ b/tests/mir-opt/issue_72181.main.built.after.mir @@ -7,8 +7,7 @@ fn main() -> () { let mut _4: Foo; let mut _5: u64; let _6: usize; - let mut _7: usize; - let mut _8: bool; + let mut _7: bool; scope 1 { let _2: [Foo; 2]; scope 2 { @@ -38,9 +37,9 @@ fn main() -> () { StorageLive(_5); StorageLive(_6); _6 = const 0_usize; - _7 = Len(_2); - _8 = Lt(copy _6, copy _7); - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb3, unwind: bb5]; + FakeRead(ForIndex, _2); + _7 = Lt(copy _6, const 2_usize); + assert(move _7, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _6) -> [success: bb3, unwind: bb5]; } bb2: { diff --git a/tests/mir-opt/issue_91633.foo.built.after.mir b/tests/mir-opt/issue_91633.foo.built.after.mir index 50fdf08375a..bf65b5b4a8c 100644 --- a/tests/mir-opt/issue_91633.foo.built.after.mir +++ b/tests/mir-opt/issue_91633.foo.built.after.mir @@ -6,8 +6,9 @@ fn foo(_1: Box<[T]>) -> T { let _2: T; let mut _3: &T; let _4: usize; - let mut _5: usize; - let mut _6: bool; + let mut _5: *const [T]; + let mut _6: usize; + let mut _7: bool; scope 1 { debug f => _2; } @@ -17,9 +18,10 @@ fn foo(_1: Box<[T]>) -> T { StorageLive(_3); StorageLive(_4); _4 = const 0_usize; - _5 = Len((*_1)); - _6 = Lt(copy _4, copy _5); - assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind: bb5]; + _5 = &raw const (*_1); + _6 = PtrMetadata(move _5); + _7 = Lt(copy _4, copy _6); + assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _4) -> [success: bb1, unwind: bb5]; } bb1: { diff --git a/tests/mir-opt/issue_91633.fun.built.after.mir b/tests/mir-opt/issue_91633.fun.built.after.mir index 5b41b376719..d2fc438d3e8 100644 --- a/tests/mir-opt/issue_91633.fun.built.after.mir +++ b/tests/mir-opt/issue_91633.fun.built.after.mir @@ -15,7 +15,7 @@ fn fun(_1: &[T]) -> &T { StorageLive(_2); StorageLive(_3); _3 = const 0_usize; - _4 = Len((*_1)); + _4 = PtrMetadata(copy _1); _5 = Lt(copy _3, copy _4); assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind: bb2]; } diff --git a/tests/mir-opt/lower_array_len.array_bound.GVN.panic-abort.diff b/tests/mir-opt/lower_array_len.array_bound.GVN.panic-abort.diff index f052c8f63dc..98c5e868046 100644 --- a/tests/mir-opt/lower_array_len.array_bound.GVN.panic-abort.diff +++ b/tests/mir-opt/lower_array_len.array_bound.GVN.panic-abort.diff @@ -11,16 +11,14 @@ let mut _6: &[u8]; let mut _7: &[u8; N]; let _8: usize; - let mut _9: usize; - let mut _10: bool; + let mut _9: bool; bb0: { - StorageLive(_3); + nop; StorageLive(_4); _4 = copy _1; -- StorageLive(_5); -+ nop; + StorageLive(_5); StorageLive(_6); StorageLive(_7); _7 = &(*_2); @@ -40,16 +38,13 @@ } bb2: { -- StorageDead(_5); -+ nop; + StorageDead(_5); StorageDead(_4); StorageLive(_8); _8 = copy _1; -- _9 = Len((*_2)); -- _10 = Lt(copy _8, copy _9); -- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb3, unwind unreachable]; -+ _9 = const N; -+ _10 = copy _3; +- _9 = Lt(copy _8, const N); +- assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, copy _8) -> [success: bb3, unwind unreachable]; ++ _9 = copy _3; + assert(copy _3, "index out of bounds: the length is {} but the index is {}", const N, copy _1) -> [success: bb3, unwind unreachable]; } @@ -61,8 +56,7 @@ } bb4: { -- StorageDead(_5); -+ nop; + StorageDead(_5); StorageDead(_4); _0 = const 42_u8; goto -> bb5; diff --git a/tests/mir-opt/lower_array_len.array_bound.GVN.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_bound.GVN.panic-unwind.diff index 3299e300431..72c73137869 100644 --- a/tests/mir-opt/lower_array_len.array_bound.GVN.panic-unwind.diff +++ b/tests/mir-opt/lower_array_len.array_bound.GVN.panic-unwind.diff @@ -11,16 +11,14 @@ let mut _6: &[u8]; let mut _7: &[u8; N]; let _8: usize; - let mut _9: usize; - let mut _10: bool; + let mut _9: bool; bb0: { - StorageLive(_3); + nop; StorageLive(_4); _4 = copy _1; -- StorageLive(_5); -+ nop; + StorageLive(_5); StorageLive(_6); StorageLive(_7); _7 = &(*_2); @@ -40,16 +38,13 @@ } bb2: { -- StorageDead(_5); -+ nop; + StorageDead(_5); StorageDead(_4); StorageLive(_8); _8 = copy _1; -- _9 = Len((*_2)); -- _10 = Lt(copy _8, copy _9); -- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb3, unwind continue]; -+ _9 = const N; -+ _10 = copy _3; +- _9 = Lt(copy _8, const N); +- assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, copy _8) -> [success: bb3, unwind continue]; ++ _9 = copy _3; + assert(copy _3, "index out of bounds: the length is {} but the index is {}", const N, copy _1) -> [success: bb3, unwind continue]; } @@ -61,8 +56,7 @@ } bb4: { -- StorageDead(_5); -+ nop; + StorageDead(_5); StorageDead(_4); _0 = const 42_u8; goto -> bb5; diff --git a/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-abort.diff b/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-abort.diff index 329eb80b3c4..9ffaf44c02b 100644 --- a/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-abort.diff +++ b/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-abort.diff @@ -11,19 +11,16 @@ let mut _6: &[u8]; let mut _7: &[u8; N]; let _8: usize; - let mut _9: usize; - let mut _10: bool; - let _11: usize; - let mut _12: usize; - let mut _13: bool; + let mut _9: bool; + let _10: usize; + let mut _11: bool; bb0: { - StorageLive(_3); + nop; StorageLive(_4); _4 = copy _1; -- StorageLive(_5); -+ nop; + StorageLive(_5); StorageLive(_6); StorageLive(_7); _7 = &(*_2); @@ -43,16 +40,13 @@ } bb2: { -- StorageDead(_5); -+ nop; + StorageDead(_5); StorageDead(_4); StorageLive(_8); _8 = copy _1; -- _9 = Len((*_2)); -- _10 = Lt(copy _8, copy _9); -- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb3, unwind unreachable]; -+ _9 = const N; -+ _10 = copy _3; +- _9 = Lt(copy _8, const N); +- assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, copy _8) -> [success: bb3, unwind unreachable]; ++ _9 = copy _3; + assert(copy _3, "index out of bounds: the length is {} but the index is {}", const N, copy _1) -> [success: bb3, unwind unreachable]; } @@ -64,23 +58,20 @@ } bb4: { -- StorageDead(_5); -+ nop; + StorageDead(_5); StorageDead(_4); - StorageLive(_11); - _11 = const 0_usize; -- _12 = Len((*_2)); -- _13 = Lt(copy _11, copy _12); -- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb5, unwind unreachable]; -+ _12 = const N; -+ _13 = Lt(const 0_usize, const N); -+ assert(move _13, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb5, unwind unreachable]; + StorageLive(_10); + _10 = const 0_usize; +- _11 = Lt(copy _10, const N); +- assert(move _11, "index out of bounds: the length is {} but the index is {}", const N, copy _10) -> [success: bb5, unwind unreachable]; ++ _11 = Lt(const 0_usize, const N); ++ assert(move _11, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb5, unwind unreachable]; } bb5: { -- (*_2)[_11] = const 42_u8; +- (*_2)[_10] = const 42_u8; + (*_2)[0 of 1] = const 42_u8; - StorageDead(_11); + StorageDead(_10); _0 = const 42_u8; goto -> bb6; } diff --git a/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-unwind.diff index ab007e133ec..08008e46335 100644 --- a/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-unwind.diff +++ b/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-unwind.diff @@ -11,19 +11,16 @@ let mut _6: &[u8]; let mut _7: &[u8; N]; let _8: usize; - let mut _9: usize; - let mut _10: bool; - let _11: usize; - let mut _12: usize; - let mut _13: bool; + let mut _9: bool; + let _10: usize; + let mut _11: bool; bb0: { - StorageLive(_3); + nop; StorageLive(_4); _4 = copy _1; -- StorageLive(_5); -+ nop; + StorageLive(_5); StorageLive(_6); StorageLive(_7); _7 = &(*_2); @@ -43,16 +40,13 @@ } bb2: { -- StorageDead(_5); -+ nop; + StorageDead(_5); StorageDead(_4); StorageLive(_8); _8 = copy _1; -- _9 = Len((*_2)); -- _10 = Lt(copy _8, copy _9); -- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb3, unwind continue]; -+ _9 = const N; -+ _10 = copy _3; +- _9 = Lt(copy _8, const N); +- assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, copy _8) -> [success: bb3, unwind continue]; ++ _9 = copy _3; + assert(copy _3, "index out of bounds: the length is {} but the index is {}", const N, copy _1) -> [success: bb3, unwind continue]; } @@ -64,23 +58,20 @@ } bb4: { -- StorageDead(_5); -+ nop; + StorageDead(_5); StorageDead(_4); - StorageLive(_11); - _11 = const 0_usize; -- _12 = Len((*_2)); -- _13 = Lt(copy _11, copy _12); -- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb5, unwind continue]; -+ _12 = const N; -+ _13 = Lt(const 0_usize, const N); -+ assert(move _13, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb5, unwind continue]; + StorageLive(_10); + _10 = const 0_usize; +- _11 = Lt(copy _10, const N); +- assert(move _11, "index out of bounds: the length is {} but the index is {}", const N, copy _10) -> [success: bb5, unwind continue]; ++ _11 = Lt(const 0_usize, const N); ++ assert(move _11, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb5, unwind continue]; } bb5: { -- (*_2)[_11] = const 42_u8; +- (*_2)[_10] = const 42_u8; + (*_2)[0 of 1] = const 42_u8; - StorageDead(_11); + StorageDead(_10); _0 = const 42_u8; goto -> bb6; } diff --git a/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-abort.diff b/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-abort.diff index 20001f1248e..4b39e18d16c 100644 --- a/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-abort.diff +++ b/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-abort.diff @@ -36,7 +36,7 @@ StorageDead(_4); StorageLive(_7); _7 = copy _1; - _8 = Len((*_2)); + _8 = PtrMetadata(copy _2); _9 = Lt(copy _7, copy _8); assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb3, unwind unreachable]; } diff --git a/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-unwind.diff b/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-unwind.diff index ca8f92df5de..f0d4afa21ae 100644 --- a/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-unwind.diff +++ b/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-unwind.diff @@ -36,7 +36,7 @@ StorageDead(_4); StorageLive(_7); _7 = copy _1; - _8 = Len((*_2)); + _8 = PtrMetadata(copy _2); _9 = Lt(copy _7, copy _8); assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb3, unwind continue]; } diff --git a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir index 7294302609a..35e44b2314a 100644 --- a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir +++ b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir @@ -27,20 +27,19 @@ fn main() -> () { let mut _0: (); let mut _1: [usize; ValTree(Leaf(0x00000003): usize)]; let _3: usize; - let mut _4: usize; - let mut _5: bool; - let mut _7: bool; - let _8: bool; - let mut _9: usize; - let _10: bool; + let mut _4: bool; + let mut _6: bool; + let _7: bool; + let mut _8: usize; + let _9: bool; scope 1 { debug v => _1; let _2: &'?3 usize; scope 2 { debug p => _2; - let _6: &'?4 usize; + let _5: &'?4 usize; scope 3 { - debug q => _6; + debug q => _5; } } } @@ -52,50 +51,50 @@ fn main() -> () { StorageLive(_2); StorageLive(_3); _3 = const ConstValue(Scalar(0x00000000): usize); - _4 = Len(_1); - _5 = Lt(copy _3, copy _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind: bb7]; + FakeRead(ForIndex, _1); + _4 = Lt(copy _3, const ConstValue(Scalar(0x00000003): usize)); + assert(move _4, "index out of bounds: the length is {} but the index is {}", const ConstValue(Scalar(0x00000003): usize), copy _3) -> [success: bb1, unwind: bb7]; } bb1: { _2 = &'?2 _1[_3]; FakeRead(ForLet(None), _2); + StorageLive(_5); + _5 = copy _2; + FakeRead(ForLet(None), _5); StorageLive(_6); - _6 = copy _2; - FakeRead(ForLet(None), _6); - StorageLive(_7); - _7 = const ConstValue(Scalar(0x01): bool); - switchInt(move _7) -> [0: bb4, otherwise: bb2]; + _6 = const ConstValue(Scalar(0x01): bool); + switchInt(move _6) -> [0: bb4, otherwise: bb2]; } bb2: { + StorageLive(_7); StorageLive(_8); - StorageLive(_9); - _9 = copy (*_6); - _8 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(move _9) -> [return: bb3, unwind: bb7]; + _8 = copy (*_5); + _7 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(move _8) -> [return: bb3, unwind: bb7]; } bb3: { - StorageDead(_9); StorageDead(_8); + StorageDead(_7); _0 = const ConstValue(ZeroSized: ()); goto -> bb6; } bb4: { - StorageLive(_10); - _10 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(const ConstValue(Scalar(0x00000016): usize)) -> [return: bb5, unwind: bb7]; + StorageLive(_9); + _9 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(const ConstValue(Scalar(0x00000016): usize)) -> [return: bb5, unwind: bb7]; } bb5: { - StorageDead(_10); + StorageDead(_9); _0 = const ConstValue(ZeroSized: ()); goto -> bb6; } bb6: { - StorageDead(_7); StorageDead(_6); + StorageDead(_5); StorageDead(_3); StorageDead(_2); StorageDead(_1); diff --git a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir index 85b89a013c4..6d415f42d06 100644 --- a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir +++ b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir @@ -27,20 +27,19 @@ fn main() -> () { let mut _0: (); let mut _1: [usize; ValTree(Leaf(0x0000000000000003): usize)]; let _3: usize; - let mut _4: usize; - let mut _5: bool; - let mut _7: bool; - let _8: bool; - let mut _9: usize; - let _10: bool; + let mut _4: bool; + let mut _6: bool; + let _7: bool; + let mut _8: usize; + let _9: bool; scope 1 { debug v => _1; let _2: &'?3 usize; scope 2 { debug p => _2; - let _6: &'?4 usize; + let _5: &'?4 usize; scope 3 { - debug q => _6; + debug q => _5; } } } @@ -52,50 +51,50 @@ fn main() -> () { StorageLive(_2); StorageLive(_3); _3 = const ConstValue(Scalar(0x0000000000000000): usize); - _4 = Len(_1); - _5 = Lt(copy _3, copy _4); - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind: bb7]; + FakeRead(ForIndex, _1); + _4 = Lt(copy _3, const ConstValue(Scalar(0x0000000000000003): usize)); + assert(move _4, "index out of bounds: the length is {} but the index is {}", const ConstValue(Scalar(0x0000000000000003): usize), copy _3) -> [success: bb1, unwind: bb7]; } bb1: { _2 = &'?2 _1[_3]; FakeRead(ForLet(None), _2); + StorageLive(_5); + _5 = copy _2; + FakeRead(ForLet(None), _5); StorageLive(_6); - _6 = copy _2; - FakeRead(ForLet(None), _6); - StorageLive(_7); - _7 = const ConstValue(Scalar(0x01): bool); - switchInt(move _7) -> [0: bb4, otherwise: bb2]; + _6 = const ConstValue(Scalar(0x01): bool); + switchInt(move _6) -> [0: bb4, otherwise: bb2]; } bb2: { + StorageLive(_7); StorageLive(_8); - StorageLive(_9); - _9 = copy (*_6); - _8 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(move _9) -> [return: bb3, unwind: bb7]; + _8 = copy (*_5); + _7 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(move _8) -> [return: bb3, unwind: bb7]; } bb3: { - StorageDead(_9); StorageDead(_8); + StorageDead(_7); _0 = const ConstValue(ZeroSized: ()); goto -> bb6; } bb4: { - StorageLive(_10); - _10 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(const ConstValue(Scalar(0x0000000000000016): usize)) -> [return: bb5, unwind: bb7]; + StorageLive(_9); + _9 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(const ConstValue(Scalar(0x0000000000000016): usize)) -> [return: bb5, unwind: bb7]; } bb5: { - StorageDead(_10); + StorageDead(_9); _0 = const ConstValue(ZeroSized: ()); goto -> bb6; } bb6: { - StorageDead(_7); StorageDead(_6); + StorageDead(_5); StorageDead(_3); StorageDead(_2); StorageDead(_1); diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff index 6575610727b..5b39e45806e 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff @@ -7,17 +7,16 @@ let mut _2: (i32, bool); let mut _4: [i32; 6]; let _5: usize; - let mut _6: usize; - let mut _7: bool; - let mut _9: u32; + let mut _6: bool; + let mut _8: u32; scope 1 { debug x => _1; let _3: i32; scope 2 { debug y => _3; - let _8: u32; + let _7: u32; scope 3 { - debug z => _8; + debug z => _7; } } } @@ -38,10 +37,9 @@ _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32]; StorageLive(_5); _5 = const 3_usize; - _6 = const 6_usize; -- _7 = Lt(copy _5, copy _6); -- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind unreachable]; -+ _7 = const true; +- _6 = Lt(copy _5, const 6_usize); +- assert(move _6, "index out of bounds: the length is {} but the index is {}", const 6_usize, copy _5) -> [success: bb2, unwind unreachable]; ++ _6 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> [success: bb2, unwind unreachable]; } @@ -50,13 +48,13 @@ + _3 = const 3_i32; StorageDead(_5); StorageDead(_4); + StorageLive(_7); StorageLive(_8); - StorageLive(_9); - _9 = const 42_u32; -- _8 = copy _9; -+ _8 = const 42_u32; - StorageDead(_9); + _8 = const 42_u32; +- _7 = copy _8; ++ _7 = const 42_u32; StorageDead(_8); + StorageDead(_7); StorageDead(_3); StorageDead(_1); return; diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff index 1a4ed5767fe..ea2742a6471 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff @@ -7,17 +7,16 @@ let mut _2: (i32, bool); let mut _4: [i32; 6]; let _5: usize; - let mut _6: usize; - let mut _7: bool; - let mut _9: u32; + let mut _6: bool; + let mut _8: u32; scope 1 { debug x => _1; let _3: i32; scope 2 { debug y => _3; - let _8: u32; + let _7: u32; scope 3 { - debug z => _8; + debug z => _7; } } } @@ -38,10 +37,9 @@ _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32]; StorageLive(_5); _5 = const 3_usize; - _6 = const 6_usize; -- _7 = Lt(copy _5, copy _6); -- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind continue]; -+ _7 = const true; +- _6 = Lt(copy _5, const 6_usize); +- assert(move _6, "index out of bounds: the length is {} but the index is {}", const 6_usize, copy _5) -> [success: bb2, unwind continue]; ++ _6 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> [success: bb2, unwind continue]; } @@ -50,13 +48,13 @@ + _3 = const 3_i32; StorageDead(_5); StorageDead(_4); + StorageLive(_7); StorageLive(_8); - StorageLive(_9); - _9 = const 42_u32; -- _8 = copy _9; -+ _8 = const 42_u32; - StorageDead(_9); + _8 = const 42_u32; +- _7 = copy _8; ++ _7 = const 42_u32; StorageDead(_8); + StorageDead(_7); StorageDead(_3); StorageDead(_1); return; diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff index 6575610727b..5b39e45806e 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff @@ -7,17 +7,16 @@ let mut _2: (i32, bool); let mut _4: [i32; 6]; let _5: usize; - let mut _6: usize; - let mut _7: bool; - let mut _9: u32; + let mut _6: bool; + let mut _8: u32; scope 1 { debug x => _1; let _3: i32; scope 2 { debug y => _3; - let _8: u32; + let _7: u32; scope 3 { - debug z => _8; + debug z => _7; } } } @@ -38,10 +37,9 @@ _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32]; StorageLive(_5); _5 = const 3_usize; - _6 = const 6_usize; -- _7 = Lt(copy _5, copy _6); -- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind unreachable]; -+ _7 = const true; +- _6 = Lt(copy _5, const 6_usize); +- assert(move _6, "index out of bounds: the length is {} but the index is {}", const 6_usize, copy _5) -> [success: bb2, unwind unreachable]; ++ _6 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> [success: bb2, unwind unreachable]; } @@ -50,13 +48,13 @@ + _3 = const 3_i32; StorageDead(_5); StorageDead(_4); + StorageLive(_7); StorageLive(_8); - StorageLive(_9); - _9 = const 42_u32; -- _8 = copy _9; -+ _8 = const 42_u32; - StorageDead(_9); + _8 = const 42_u32; +- _7 = copy _8; ++ _7 = const 42_u32; StorageDead(_8); + StorageDead(_7); StorageDead(_3); StorageDead(_1); return; diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff index 1a4ed5767fe..ea2742a6471 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff @@ -7,17 +7,16 @@ let mut _2: (i32, bool); let mut _4: [i32; 6]; let _5: usize; - let mut _6: usize; - let mut _7: bool; - let mut _9: u32; + let mut _6: bool; + let mut _8: u32; scope 1 { debug x => _1; let _3: i32; scope 2 { debug y => _3; - let _8: u32; + let _7: u32; scope 3 { - debug z => _8; + debug z => _7; } } } @@ -38,10 +37,9 @@ _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32]; StorageLive(_5); _5 = const 3_usize; - _6 = const 6_usize; -- _7 = Lt(copy _5, copy _6); -- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind continue]; -+ _7 = const true; +- _6 = Lt(copy _5, const 6_usize); +- assert(move _6, "index out of bounds: the length is {} but the index is {}", const 6_usize, copy _5) -> [success: bb2, unwind continue]; ++ _6 = const true; + assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> [success: bb2, unwind continue]; } @@ -50,13 +48,13 @@ + _3 = const 3_i32; StorageDead(_5); StorageDead(_4); + StorageLive(_7); StorageLive(_8); - StorageLive(_9); - _9 = const 42_u32; -- _8 = copy _9; -+ _8 = const 42_u32; - StorageDead(_9); + _8 = const 42_u32; +- _7 = copy _8; ++ _7 = const 42_u32; StorageDead(_8); + StorageDead(_7); StorageDead(_3); StorageDead(_1); return; diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff index e2420a341e0..f7fe08831b9 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff @@ -7,19 +7,18 @@ let mut _2: (i32, bool); let mut _4: [i32; 6]; let _5: usize; - let mut _6: usize; - let mut _7: bool; - let mut _9: Point; + let mut _6: bool; + let mut _8: Point; ++ let mut _9: u32; + let mut _10: u32; -+ let mut _11: u32; scope 1 { debug x => _1; let _3: i32; scope 2 { debug y => _3; - let _8: u32; + let _7: u32; scope 3 { - debug z => _8; + debug z => _7; } } } @@ -37,31 +36,30 @@ _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32]; StorageLive(_5); _5 = const 3_usize; - _6 = const 6_usize; - _7 = Lt(copy _5, copy _6); - assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind unreachable]; + _6 = Lt(copy _5, const 6_usize); + assert(move _6, "index out of bounds: the length is {} but the index is {}", const 6_usize, copy _5) -> [success: bb2, unwind unreachable]; } bb2: { _3 = copy _4[_5]; StorageDead(_5); StorageDead(_4); - StorageLive(_8); -- StorageLive(_9); -- _9 = Point { x: const 12_u32, y: const 42_u32 }; -- _8 = copy (_9.1: u32); -- StorageDead(_9); + StorageLive(_7); +- StorageLive(_8); +- _8 = Point { x: const 12_u32, y: const 42_u32 }; +- _7 = copy (_8.1: u32); +- StorageDead(_8); ++ StorageLive(_9); + StorageLive(_10); -+ StorageLive(_11); + nop; -+ _10 = const 12_u32; -+ _11 = const 42_u32; ++ _9 = const 12_u32; ++ _10 = const 42_u32; + nop; -+ _8 = copy _11; ++ _7 = copy _10; ++ StorageDead(_9); + StorageDead(_10); -+ StorageDead(_11); + nop; - StorageDead(_8); + StorageDead(_7); StorageDead(_3); StorageDead(_1); return; diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff index a2fb3b979e6..6e36386bea6 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff @@ -7,19 +7,18 @@ let mut _2: (i32, bool); let mut _4: [i32; 6]; let _5: usize; - let mut _6: usize; - let mut _7: bool; - let mut _9: Point; + let mut _6: bool; + let mut _8: Point; ++ let mut _9: u32; + let mut _10: u32; -+ let mut _11: u32; scope 1 { debug x => _1; let _3: i32; scope 2 { debug y => _3; - let _8: u32; + let _7: u32; scope 3 { - debug z => _8; + debug z => _7; } } } @@ -37,31 +36,30 @@ _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32]; StorageLive(_5); _5 = const 3_usize; - _6 = const 6_usize; - _7 = Lt(copy _5, copy _6); - assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind continue]; + _6 = Lt(copy _5, const 6_usize); + assert(move _6, "index out of bounds: the length is {} but the index is {}", const 6_usize, copy _5) -> [success: bb2, unwind continue]; } bb2: { _3 = copy _4[_5]; StorageDead(_5); StorageDead(_4); - StorageLive(_8); -- StorageLive(_9); -- _9 = Point { x: const 12_u32, y: const 42_u32 }; -- _8 = copy (_9.1: u32); -- StorageDead(_9); + StorageLive(_7); +- StorageLive(_8); +- _8 = Point { x: const 12_u32, y: const 42_u32 }; +- _7 = copy (_8.1: u32); +- StorageDead(_8); ++ StorageLive(_9); + StorageLive(_10); -+ StorageLive(_11); + nop; -+ _10 = const 12_u32; -+ _11 = const 42_u32; ++ _9 = const 12_u32; ++ _10 = const 42_u32; + nop; -+ _8 = copy _11; ++ _7 = copy _10; ++ StorageDead(_9); + StorageDead(_10); -+ StorageDead(_11); + nop; - StorageDead(_8); + StorageDead(_7); StorageDead(_3); StorageDead(_1); return; diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff index e2420a341e0..f7fe08831b9 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff @@ -7,19 +7,18 @@ let mut _2: (i32, bool); let mut _4: [i32; 6]; let _5: usize; - let mut _6: usize; - let mut _7: bool; - let mut _9: Point; + let mut _6: bool; + let mut _8: Point; ++ let mut _9: u32; + let mut _10: u32; -+ let mut _11: u32; scope 1 { debug x => _1; let _3: i32; scope 2 { debug y => _3; - let _8: u32; + let _7: u32; scope 3 { - debug z => _8; + debug z => _7; } } } @@ -37,31 +36,30 @@ _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32]; StorageLive(_5); _5 = const 3_usize; - _6 = const 6_usize; - _7 = Lt(copy _5, copy _6); - assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind unreachable]; + _6 = Lt(copy _5, const 6_usize); + assert(move _6, "index out of bounds: the length is {} but the index is {}", const 6_usize, copy _5) -> [success: bb2, unwind unreachable]; } bb2: { _3 = copy _4[_5]; StorageDead(_5); StorageDead(_4); - StorageLive(_8); -- StorageLive(_9); -- _9 = Point { x: const 12_u32, y: const 42_u32 }; -- _8 = copy (_9.1: u32); -- StorageDead(_9); + StorageLive(_7); +- StorageLive(_8); +- _8 = Point { x: const 12_u32, y: const 42_u32 }; +- _7 = copy (_8.1: u32); +- StorageDead(_8); ++ StorageLive(_9); + StorageLive(_10); -+ StorageLive(_11); + nop; -+ _10 = const 12_u32; -+ _11 = const 42_u32; ++ _9 = const 12_u32; ++ _10 = const 42_u32; + nop; -+ _8 = copy _11; ++ _7 = copy _10; ++ StorageDead(_9); + StorageDead(_10); -+ StorageDead(_11); + nop; - StorageDead(_8); + StorageDead(_7); StorageDead(_3); StorageDead(_1); return; diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff index a2fb3b979e6..6e36386bea6 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff @@ -7,19 +7,18 @@ let mut _2: (i32, bool); let mut _4: [i32; 6]; let _5: usize; - let mut _6: usize; - let mut _7: bool; - let mut _9: Point; + let mut _6: bool; + let mut _8: Point; ++ let mut _9: u32; + let mut _10: u32; -+ let mut _11: u32; scope 1 { debug x => _1; let _3: i32; scope 2 { debug y => _3; - let _8: u32; + let _7: u32; scope 3 { - debug z => _8; + debug z => _7; } } } @@ -37,31 +36,30 @@ _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32]; StorageLive(_5); _5 = const 3_usize; - _6 = const 6_usize; - _7 = Lt(copy _5, copy _6); - assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind continue]; + _6 = Lt(copy _5, const 6_usize); + assert(move _6, "index out of bounds: the length is {} but the index is {}", const 6_usize, copy _5) -> [success: bb2, unwind continue]; } bb2: { _3 = copy _4[_5]; StorageDead(_5); StorageDead(_4); - StorageLive(_8); -- StorageLive(_9); -- _9 = Point { x: const 12_u32, y: const 42_u32 }; -- _8 = copy (_9.1: u32); -- StorageDead(_9); + StorageLive(_7); +- StorageLive(_8); +- _8 = Point { x: const 12_u32, y: const 42_u32 }; +- _7 = copy (_8.1: u32); +- StorageDead(_8); ++ StorageLive(_9); + StorageLive(_10); -+ StorageLive(_11); + nop; -+ _10 = const 12_u32; -+ _11 = const 42_u32; ++ _9 = const 12_u32; ++ _10 = const 42_u32; + nop; -+ _8 = copy _11; ++ _7 = copy _10; ++ StorageDead(_9); + StorageDead(_10); -+ StorageDead(_11); + nop; - StorageDead(_8); + StorageDead(_7); StorageDead(_3); StorageDead(_1); return; diff --git a/tests/mir-opt/pre-codegen/slice_index.rs b/tests/mir-opt/pre-codegen/slice_index.rs index 574062d6c35..5dac535d195 100644 --- a/tests/mir-opt/pre-codegen/slice_index.rs +++ b/tests/mir-opt/pre-codegen/slice_index.rs @@ -9,7 +9,7 @@ use std::ops::Range; // EMIT_MIR slice_index.slice_index_usize.PreCodegen.after.mir pub fn slice_index_usize(slice: &[u32], index: usize) -> u32 { // CHECK-LABEL: slice_index_usize - // CHECK: [[LEN:_[0-9]+]] = Len((*_1)) + // CHECK: [[LEN:_[0-9]+]] = PtrMetadata(copy _1) // CHECK: Lt(copy _2, copy [[LEN]]) // CHECK-NOT: precondition_check // CHECK: _0 = copy (*_1)[_2]; diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-abort.mir index cc1034229fc..81e60b8ec2c 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-abort.mir @@ -8,7 +8,7 @@ fn slice_index_usize(_1: &[u32], _2: usize) -> u32 { let mut _4: bool; bb0: { - _3 = Len((*_1)); + _3 = PtrMetadata(copy _1); _4 = Lt(copy _2, copy _3); assert(move _4, "index out of bounds: the length is {} but the index is {}", move _3, copy _2) -> [success: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-unwind.mir index 358226fb529..c0fdc839608 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-unwind.mir @@ -8,7 +8,7 @@ fn slice_index_usize(_1: &[u32], _2: usize) -> u32 { let mut _4: bool; bb0: { - _3 = Len((*_1)); + _3 = PtrMetadata(copy _1); _4 = Lt(copy _2, copy _3); assert(move _4, "index out of bounds: the length is {} but the index is {}", move _3, copy _2) -> [success: bb1, unwind continue]; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir index ecac03ad0f9..151783969dd 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir @@ -7,20 +7,19 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let mut _3: usize; let mut _4: usize; let mut _9: std::option::Option<usize>; - let mut _11: usize; - let mut _12: bool; - let mut _14: &impl Fn(usize, &T); - let mut _15: (usize, &T); - let _16: (); + let mut _11: bool; + let mut _13: &impl Fn(usize, &T); + let mut _14: (usize, &T); + let _15: (); scope 1 { debug ((iter: std::ops::Range<usize>).0: usize) => _4; debug ((iter: std::ops::Range<usize>).1: usize) => _3; let _10: usize; scope 2 { debug i => _10; - let _13: &T; + let _12: &T; scope 3 { - debug x => _13; + debug x => _12; } } scope 5 (inlined iter::range::<impl Iterator for std::ops::Range<usize>>::next) { @@ -82,23 +81,22 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { StorageDead(_6); StorageDead(_7); _10 = copy ((_9 as Some).0: usize); - _11 = Len((*_1)); - _12 = Lt(copy _10, copy _11); - assert(move _12, "index out of bounds: the length is {} but the index is {}", move _11, copy _10) -> [success: bb6, unwind unreachable]; + _11 = Lt(copy _10, copy _3); + assert(move _11, "index out of bounds: the length is {} but the index is {}", copy _3, copy _10) -> [success: bb6, unwind unreachable]; } bb6: { - _13 = &(*_1)[_10]; + _12 = &(*_1)[_10]; + StorageLive(_13); + _13 = &_2; StorageLive(_14); - _14 = &_2; - StorageLive(_15); - _15 = (copy _10, copy _13); - _16 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _14, move _15) -> [return: bb7, unwind unreachable]; + _14 = (copy _10, copy _12); + _15 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _13, move _14) -> [return: bb7, unwind unreachable]; } bb7: { - StorageDead(_15); StorageDead(_14); + StorageDead(_13); StorageDead(_9); goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir index 1032473b9b2..006329dc20d 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir @@ -7,20 +7,19 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let mut _3: usize; let mut _4: usize; let mut _9: std::option::Option<usize>; - let mut _11: usize; - let mut _12: bool; - let mut _14: &impl Fn(usize, &T); - let mut _15: (usize, &T); - let _16: (); + let mut _11: bool; + let mut _13: &impl Fn(usize, &T); + let mut _14: (usize, &T); + let _15: (); scope 1 { debug ((iter: std::ops::Range<usize>).0: usize) => _4; debug ((iter: std::ops::Range<usize>).1: usize) => _3; let _10: usize; scope 2 { debug i => _10; - let _13: &T; + let _12: &T; scope 3 { - debug x => _13; + debug x => _12; } } scope 5 (inlined iter::range::<impl Iterator for std::ops::Range<usize>>::next) { @@ -82,23 +81,22 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { StorageDead(_6); StorageDead(_7); _10 = copy ((_9 as Some).0: usize); - _11 = Len((*_1)); - _12 = Lt(copy _10, copy _11); - assert(move _12, "index out of bounds: the length is {} but the index is {}", move _11, copy _10) -> [success: bb6, unwind: bb8]; + _11 = Lt(copy _10, copy _3); + assert(move _11, "index out of bounds: the length is {} but the index is {}", copy _3, copy _10) -> [success: bb6, unwind: bb8]; } bb6: { - _13 = &(*_1)[_10]; + _12 = &(*_1)[_10]; + StorageLive(_13); + _13 = &_2; StorageLive(_14); - _14 = &_2; - StorageLive(_15); - _15 = (copy _10, copy _13); - _16 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _14, move _15) -> [return: bb7, unwind: bb8]; + _14 = (copy _10, copy _12); + _15 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _13, move _14) -> [return: bb7, unwind: bb8]; } bb7: { - StorageDead(_15); StorageDead(_14); + StorageDead(_13); StorageDead(_9); goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir index 2efbb6d9904..3f0d60b46f4 100644 --- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir @@ -7,48 +7,36 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] { debug self => _1; scope 2 (inlined Vec::<u8>::as_slice) { debug self => _1; - let mut _9: *const u8; - let mut _10: usize; + let mut _7: *const u8; + let mut _8: usize; scope 3 (inlined Vec::<u8>::as_ptr) { debug self => _1; - let mut _2: &alloc::raw_vec::RawVec<u8>; - let mut _8: *mut u8; + let mut _6: *mut u8; scope 4 (inlined alloc::raw_vec::RawVec::<u8>::ptr) { - debug self => _2; - let mut _3: &alloc::raw_vec::RawVecInner; scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::<u8>) { - debug self => _3; - let mut _7: std::ptr::NonNull<u8>; + let mut _5: std::ptr::NonNull<u8>; scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::<u8>) { - debug self => _3; - let mut _4: std::ptr::NonNull<u8>; + let mut _2: std::ptr::NonNull<u8>; scope 7 (inlined Unique::<u8>::cast::<u8>) { - debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4; - debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>; scope 8 (inlined NonNull::<u8>::cast::<u8>) { - debug self => _4; - let mut _5: *mut u8; - let mut _6: *const u8; + let mut _3: *mut u8; + let mut _4: *const u8; scope 9 (inlined NonNull::<u8>::as_ptr) { - debug self => _4; } } } scope 10 (inlined Unique::<u8>::as_non_null_ptr) { - debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _7; - debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>; } } scope 11 (inlined NonNull::<u8>::as_ptr) { - debug self => _7; } } } } scope 12 (inlined std::slice::from_raw_parts::<'_, u8>) { - debug data => _9; - debug len => _10; - let _11: *const [u8]; + debug data => _7; + debug len => _8; + let _9: *const [u8]; scope 13 (inlined core::ub_checks::check_language_ub) { scope 14 (inlined core::ub_checks::check_language_ub::runtime) { } @@ -58,11 +46,10 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] { scope 16 (inlined align_of::<u8>) { } scope 17 (inlined slice_from_raw_parts::<u8>) { - debug data => _9; - debug len => _10; + debug data => _7; + debug len => _8; scope 18 (inlined std::ptr::from_raw_parts::<[u8], u8>) { - debug data_pointer => _9; - debug metadata => _10; + debug data_pointer => _7; } } } @@ -70,37 +57,31 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] { } bb0: { - StorageLive(_8); - StorageLive(_9); + StorageLive(_6); + StorageLive(_7); + StorageLive(_5); StorageLive(_2); - _2 = &((*_1).0: alloc::raw_vec::RawVec<u8>); + _2 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>); StorageLive(_3); - _3 = &(((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner); - StorageLive(_7); StorageLive(_4); - _4 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>); - StorageLive(_5); - StorageLive(_6); - _5 = copy _4 as *mut u8 (Transmute); - _6 = copy _5 as *const u8 (PtrToPtr); - _7 = NonNull::<u8> { pointer: move _6 }; - StorageDead(_6); - StorageDead(_5); + _3 = copy _2 as *mut u8 (Transmute); + _4 = copy _3 as *const u8 (PtrToPtr); + _5 = NonNull::<u8> { pointer: move _4 }; StorageDead(_4); - _8 = copy _7 as *mut u8 (Transmute); - StorageDead(_7); StorageDead(_3); - _9 = copy _8 as *const u8 (PtrToPtr); StorageDead(_2); - StorageLive(_10); - _10 = copy ((*_1).1: usize); - StorageLive(_11); - _11 = *const [u8] from (copy _9, copy _10); - _0 = &(*_11); - StorageDead(_11); - StorageDead(_10); + _6 = copy _5 as *mut u8 (Transmute); + StorageDead(_5); + _7 = copy _6 as *const u8 (PtrToPtr); + StorageLive(_8); + _8 = copy ((*_1).1: usize); + StorageLive(_9); + _9 = *const [u8] from (copy _7, copy _8); + _0 = &(*_9); StorageDead(_9); StorageDead(_8); + StorageDead(_7); + StorageDead(_6); return; } } diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir index 2efbb6d9904..3f0d60b46f4 100644 --- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir @@ -7,48 +7,36 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] { debug self => _1; scope 2 (inlined Vec::<u8>::as_slice) { debug self => _1; - let mut _9: *const u8; - let mut _10: usize; + let mut _7: *const u8; + let mut _8: usize; scope 3 (inlined Vec::<u8>::as_ptr) { debug self => _1; - let mut _2: &alloc::raw_vec::RawVec<u8>; - let mut _8: *mut u8; + let mut _6: *mut u8; scope 4 (inlined alloc::raw_vec::RawVec::<u8>::ptr) { - debug self => _2; - let mut _3: &alloc::raw_vec::RawVecInner; scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::<u8>) { - debug self => _3; - let mut _7: std::ptr::NonNull<u8>; + let mut _5: std::ptr::NonNull<u8>; scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::<u8>) { - debug self => _3; - let mut _4: std::ptr::NonNull<u8>; + let mut _2: std::ptr::NonNull<u8>; scope 7 (inlined Unique::<u8>::cast::<u8>) { - debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4; - debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>; scope 8 (inlined NonNull::<u8>::cast::<u8>) { - debug self => _4; - let mut _5: *mut u8; - let mut _6: *const u8; + let mut _3: *mut u8; + let mut _4: *const u8; scope 9 (inlined NonNull::<u8>::as_ptr) { - debug self => _4; } } } scope 10 (inlined Unique::<u8>::as_non_null_ptr) { - debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _7; - debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>; } } scope 11 (inlined NonNull::<u8>::as_ptr) { - debug self => _7; } } } } scope 12 (inlined std::slice::from_raw_parts::<'_, u8>) { - debug data => _9; - debug len => _10; - let _11: *const [u8]; + debug data => _7; + debug len => _8; + let _9: *const [u8]; scope 13 (inlined core::ub_checks::check_language_ub) { scope 14 (inlined core::ub_checks::check_language_ub::runtime) { } @@ -58,11 +46,10 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] { scope 16 (inlined align_of::<u8>) { } scope 17 (inlined slice_from_raw_parts::<u8>) { - debug data => _9; - debug len => _10; + debug data => _7; + debug len => _8; scope 18 (inlined std::ptr::from_raw_parts::<[u8], u8>) { - debug data_pointer => _9; - debug metadata => _10; + debug data_pointer => _7; } } } @@ -70,37 +57,31 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] { } bb0: { - StorageLive(_8); - StorageLive(_9); + StorageLive(_6); + StorageLive(_7); + StorageLive(_5); StorageLive(_2); - _2 = &((*_1).0: alloc::raw_vec::RawVec<u8>); + _2 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>); StorageLive(_3); - _3 = &(((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner); - StorageLive(_7); StorageLive(_4); - _4 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>); - StorageLive(_5); - StorageLive(_6); - _5 = copy _4 as *mut u8 (Transmute); - _6 = copy _5 as *const u8 (PtrToPtr); - _7 = NonNull::<u8> { pointer: move _6 }; - StorageDead(_6); - StorageDead(_5); + _3 = copy _2 as *mut u8 (Transmute); + _4 = copy _3 as *const u8 (PtrToPtr); + _5 = NonNull::<u8> { pointer: move _4 }; StorageDead(_4); - _8 = copy _7 as *mut u8 (Transmute); - StorageDead(_7); StorageDead(_3); - _9 = copy _8 as *const u8 (PtrToPtr); StorageDead(_2); - StorageLive(_10); - _10 = copy ((*_1).1: usize); - StorageLive(_11); - _11 = *const [u8] from (copy _9, copy _10); - _0 = &(*_11); - StorageDead(_11); - StorageDead(_10); + _6 = copy _5 as *mut u8 (Transmute); + StorageDead(_5); + _7 = copy _6 as *const u8 (PtrToPtr); + StorageLive(_8); + _8 = copy ((*_1).1: usize); + StorageLive(_9); + _9 = *const [u8] from (copy _7, copy _8); + _0 = &(*_9); StorageDead(_9); StorageDead(_8); + StorageDead(_7); + StorageDead(_6); return; } } diff --git a/tests/mir-opt/strip_debuginfo.rs b/tests/mir-opt/strip_debuginfo.rs new file mode 100644 index 00000000000..310609e1e9d --- /dev/null +++ b/tests/mir-opt/strip_debuginfo.rs @@ -0,0 +1,39 @@ +//@ revisions: NONE TINY ALL +//@[NONE] compile-flags: -Zmir_strip_debuginfo=none +//@[TINY] compile-flags: -Zmir_strip_debuginfo=locals-in-tiny-functions +//@[ALL] compile-flags: -Zmir_strip_debuginfo=all-locals + +// CHECK: fn tiny_function +fn tiny_function(end: u32) -> u32 { + // CHECK: debug end => _1; + // NONE: debug a => + // NONE: debug b => + // TINY-NOT: debug a => + // TINY-NOT: debug b => + // ALL-NOT: debug a => + // ALL-NOT: debug b => + let a = !end; + let b = a ^ 1; + b +} + +#[inline(never)] +fn opaque(_: u32) {} + +// CHECK: fn looping_function +fn looping_function(end: u32) { + // CHECK: debug end => _1; + // NONE: debug i => + // NONE: debug x => + // TINY: debug i => + // TINY: debug x => + // ALL-NOT: debug i => + // ALL-NOT: debug x => + let mut i = 0; + while i < end { + let x = i ^ 1; + opaque(x); + } +} + +fn main() {} diff --git a/tests/run-make/musl-default-linking/rmake.rs b/tests/run-make/musl-default-linking/rmake.rs new file mode 100644 index 00000000000..b6d428d3f27 --- /dev/null +++ b/tests/run-make/musl-default-linking/rmake.rs @@ -0,0 +1,62 @@ +use run_make_support::{rustc, serde_json}; + +// Please do NOT add more targets to this list! +// Per https://github.com/rust-lang/compiler-team/issues/422, +// we should be trying to move these targets to dynamically link +// musl libc by default. +static LEGACY_STATIC_LINKING_TARGETS: &[&'static str] = &[ + "aarch64-unknown-linux-musl", + "arm-unknown-linux-musleabi", + "arm-unknown-linux-musleabihf", + "armv5te-unknown-linux-musleabi", + "armv7-unknown-linux-musleabi", + "armv7-unknown-linux-musleabihf", + "i586-unknown-linux-musl", + "i686-unknown-linux-musl", + "mips64-unknown-linux-musl", + "mips64-unknown-linux-muslabi64", + "mips64el-unknown-linux-muslabi64", + "powerpc-unknown-linux-musl", + "powerpc-unknown-linux-muslspe", + "powerpc64-unknown-linux-musl", + "powerpc64le-unknown-linux-musl", + "riscv32gc-unknown-linux-musl", + "s390x-unknown-linux-musl", + "thumbv7neon-unknown-linux-musleabihf", + "x86_64-unknown-linux-musl", +]; + +fn main() { + let targets = rustc().print("target-list").run().stdout_utf8(); + + for target in targets.lines() { + let abi = target.split('-').last().unwrap(); + + if !abi.starts_with("musl") { + continue; + } + + let target_spec_json = rustc() + .print("target-spec-json") + .target(target) + .arg("-Zunstable-options") + .run() + .stdout_utf8(); + + let target_spec: serde_json::Value = + serde_json::from_str(&target_spec_json).expect("failed to parse target-spec-json"); + let default = &target_spec["crt-static-default"]; + + // If the value is `null`, then the default to dynamically link from + // musl_base was not overriden. + if default.is_null() { + continue; + } + + if default.as_bool().expect("wasn't a boolean") + && !LEGACY_STATIC_LINKING_TARGETS.contains(&target) + { + panic!("{target} statically links musl libc when it should dynamically link it"); + } + } +} diff --git a/tests/rustdoc-js-std/osstring-to-string.js b/tests/rustdoc-js-std/osstring-to-string.js index 3fdc0b9f24a..17bb602a502 100644 --- a/tests/rustdoc-js-std/osstring-to-string.js +++ b/tests/rustdoc-js-std/osstring-to-string.js @@ -4,6 +4,6 @@ const EXPECTED = { 'query': 'OsString -> String', 'others': [ - { 'path': 'std::ffi::os_str::OsString', 'name': 'into_string' }, + { 'path': 'std::ffi::OsString', 'name': 'into_string' }, ] }; diff --git a/tests/rustdoc-js/reexport.js b/tests/rustdoc-js/reexport.js index 9021cc2e90f..0b9415dd3e4 100644 --- a/tests/rustdoc-js/reexport.js +++ b/tests/rustdoc-js/reexport.js @@ -14,4 +14,13 @@ const EXPECTED = [ { 'path': 'reexport', 'name': 'AnotherOne' }, ], }, + { + 'query': 'fn:Equivalent::equivalent', + 'others': [ + // These results must never contain `reexport::equivalent::NotEquivalent`, + // since that path does not exist. + { 'path': 'equivalent::Equivalent', 'name': 'equivalent' }, + { 'path': 'reexport::NotEquivalent', 'name': 'equivalent' }, + ], + }, ]; diff --git a/tests/rustdoc-js/reexport.rs b/tests/rustdoc-js/reexport.rs index 0b3718cd9a3..ecbbeca5ea8 100644 --- a/tests/rustdoc-js/reexport.rs +++ b/tests/rustdoc-js/reexport.rs @@ -2,6 +2,15 @@ // This is a DWIM case, since renaming the export probably means the intent is also different. // For the de-duplication case of exactly the same name, see reexport-dedup +//@ aux-crate:equivalent=equivalent.rs +//@ compile-flags: --extern equivalent +//@ aux-build:equivalent.rs +//@ build-aux-docs +#[doc(inline)] +pub extern crate equivalent; +#[doc(inline)] +pub use equivalent::Equivalent as NotEquivalent; + pub mod fmt { pub struct Subscriber; } diff --git a/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr b/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr index fc47404734e..385b2ccacc1 100644 --- a/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr +++ b/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr @@ -4,7 +4,6 @@ error: unclosed quote string `"` LL | / /// ```{class="} LL | | /// main; LL | | /// ``` -LL | | ... | LL | | /// main; LL | | /// ``` @@ -23,7 +22,6 @@ error: unclosed quote string `"` LL | / /// ```{class="} LL | | /// main; LL | | /// ``` -LL | | ... | LL | | /// main; LL | | /// ``` diff --git a/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.stderr b/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.stderr index 06a1cf6b118..f9080bf0785 100644 --- a/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.stderr +++ b/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.stderr @@ -308,19 +308,12 @@ LL | pub trait SVec: Index< | | | | | this trait cannot be made into an object... LL | | <Self as SVec>::Item, -LL | | -LL | | ... | LL | |/ Output = <Index<<Self as SVec>::Item, -LL | || -LL | || -LL | || ... || -LL | || LL | || Output = <Self as SVec>::Item> as SVec>::Item, | ||_________________________________________________^ ...because it uses `Self` as a type parameter ... | -LL | | LL | | > { | |__^ ...because it uses `Self` as a type parameter help: consider using an opaque type instead diff --git a/tests/rustdoc-ui/lints/check-attr.stderr b/tests/rustdoc-ui/lints/check-attr.stderr index e23806e0bab..3366c021727 100644 --- a/tests/rustdoc-ui/lints/check-attr.stderr +++ b/tests/rustdoc-ui/lints/check-attr.stderr @@ -2,9 +2,6 @@ error: unknown attribute `compile-fail` --> $DIR/check-attr.rs:3:1 | LL | / /// foo -LL | | -LL | | -LL | | ... | LL | | /// boo LL | | /// ``` @@ -22,9 +19,6 @@ error: unknown attribute `compilefail` --> $DIR/check-attr.rs:3:1 | LL | / /// foo -LL | | -LL | | -LL | | ... | LL | | /// boo LL | | /// ``` @@ -37,9 +31,6 @@ error: unknown attribute `comPile_fail` --> $DIR/check-attr.rs:3:1 | LL | / /// foo -LL | | -LL | | -LL | | ... | LL | | /// boo LL | | /// ``` @@ -52,9 +43,6 @@ error: unknown attribute `should-panic` --> $DIR/check-attr.rs:13:1 | LL | / /// bar -LL | | -LL | | -LL | | ... | LL | | /// boo LL | | /// ``` @@ -67,9 +55,6 @@ error: unknown attribute `shouldpanic` --> $DIR/check-attr.rs:13:1 | LL | / /// bar -LL | | -LL | | -LL | | ... | LL | | /// boo LL | | /// ``` @@ -82,9 +67,6 @@ error: unknown attribute `sHould_panic` --> $DIR/check-attr.rs:13:1 | LL | / /// bar -LL | | -LL | | -LL | | ... | LL | | /// boo LL | | /// ``` @@ -97,9 +79,6 @@ error: unknown attribute `no-run` --> $DIR/check-attr.rs:23:1 | LL | / /// foobar -LL | | -LL | | -LL | | ... | LL | | /// boo LL | | /// ``` @@ -112,9 +91,6 @@ error: unknown attribute `norun` --> $DIR/check-attr.rs:23:1 | LL | / /// foobar -LL | | -LL | | -LL | | ... | LL | | /// boo LL | | /// ``` @@ -127,9 +103,6 @@ error: unknown attribute `no_Run` --> $DIR/check-attr.rs:23:1 | LL | / /// foobar -LL | | -LL | | -LL | | ... | LL | | /// boo LL | | /// ``` @@ -142,9 +115,6 @@ error: unknown attribute `test-harness` --> $DIR/check-attr.rs:33:1 | LL | / /// b -LL | | -LL | | -LL | | ... | LL | | /// boo LL | | /// ``` @@ -157,9 +127,6 @@ error: unknown attribute `testharness` --> $DIR/check-attr.rs:33:1 | LL | / /// b -LL | | -LL | | -LL | | ... | LL | | /// boo LL | | /// ``` @@ -172,9 +139,6 @@ error: unknown attribute `teSt_harness` --> $DIR/check-attr.rs:33:1 | LL | / /// b -LL | | -LL | | -LL | | ... | LL | | /// boo LL | | /// ``` diff --git a/tests/rustdoc-ui/lints/check.stderr b/tests/rustdoc-ui/lints/check.stderr index f1f36e8830d..dcdf25dda64 100644 --- a/tests/rustdoc-ui/lints/check.stderr +++ b/tests/rustdoc-ui/lints/check.stderr @@ -6,7 +6,6 @@ LL | | LL | | LL | | #![warn(missing_docs)] ... | -LL | | LL | | pub fn foo() {} | |_______________^ | diff --git a/tests/rustdoc-ui/unescaped_backticks.stderr b/tests/rustdoc-ui/unescaped_backticks.stderr index 1e2b3528d4a..d93aaf5f3ca 100644 --- a/tests/rustdoc-ui/unescaped_backticks.stderr +++ b/tests/rustdoc-ui/unescaped_backticks.stderr @@ -271,9 +271,6 @@ error: unescaped backtick --> $DIR/unescaped_backticks.rs:323:5 | LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`], -LL | | -LL | | -LL | | ... | LL | | /// [`rebuild_interest_cache`][rebuild] is called after the value of the max LL | | /// level changes. @@ -290,9 +287,6 @@ error: unescaped backtick --> $DIR/unescaped_backticks.rs:323:5 | LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`], -LL | | -LL | | -LL | | ... | LL | | /// [`rebuild_interest_cache`][rebuild] is called after the value of the max LL | | /// level changes. @@ -307,9 +301,6 @@ error: unescaped backtick --> $DIR/unescaped_backticks.rs:323:5 | LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`], -LL | | -LL | | -LL | | ... | LL | | /// [`rebuild_interest_cache`][rebuild] is called after the value of the max LL | | /// level changes. @@ -326,9 +317,6 @@ error: unescaped backtick --> $DIR/unescaped_backticks.rs:323:5 | LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`], -LL | | -LL | | -LL | | ... | LL | | /// [`rebuild_interest_cache`][rebuild] is called after the value of the max LL | | /// level changes. diff --git a/tests/ui/alias-uninit-value.rs b/tests/ui/alias-uninit-value.rs deleted file mode 100644 index 0084a98e627..00000000000 --- a/tests/ui/alias-uninit-value.rs +++ /dev/null @@ -1,19 +0,0 @@ -//@ run-pass - -#![allow(non_camel_case_types)] -#![allow(dead_code)] - - - -// Regression test for issue #374 - - -enum sty { ty_nil, } - -struct RawT {struct_: sty, cname: Option<String>, hash: usize} - -fn mk_raw_ty(st: sty, cname: Option<String>) -> RawT { - return RawT {struct_: st, cname: cname, hash: 0}; -} - -pub fn main() { mk_raw_ty(sty::ty_nil, None::<String>); } diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr index de92841d7f1..80ff10e13d8 100644 --- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr +++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr @@ -7,8 +7,7 @@ LL | // fn oom( LL | || info: &Layout, LL | || ) -> () | ||_______- arguments to this function are incorrect -LL | | { -LL | | loop {} +... | LL | | } | |__^ expected `&Layout`, found `Layout` | @@ -30,8 +29,7 @@ LL | // fn oom( LL | || info: &Layout, LL | || ) -> () | ||_______^ expected `!`, found `()` -LL | | { -LL | | loop {} +... | LL | | } | |__- expected `!` because of return type | diff --git a/tests/ui/allow-non-lint-warnings.rs b/tests/ui/allow-non-lint-warnings.rs deleted file mode 100644 index f8f5a78ebff..00000000000 --- a/tests/ui/allow-non-lint-warnings.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ compile-flags: -Awarnings -//@ check-pass - -#[derive()] -#[derive(Copy, Clone)] -pub struct Foo; - -pub fn main() {} diff --git a/tests/ui/artificial-block.rs b/tests/ui/artificial-block.rs deleted file mode 100644 index 037163b4174..00000000000 --- a/tests/ui/artificial-block.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ run-pass - -fn f() -> isize { { return 3; } } - -pub fn main() { assert_eq!(f(), 3); } diff --git a/tests/ui/as-precedence.rs b/tests/ui/as-precedence.rs deleted file mode 100644 index 5021a3b677f..00000000000 --- a/tests/ui/as-precedence.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ run-pass - -#[allow(unused_parens)] -fn main() { - assert_eq!(3 as usize * 3, 9); - assert_eq!(3 as (usize) * 3, 9); - assert_eq!(3 as (usize) / 3, 1); - assert_eq!(3 as usize + 3, 6); - assert_eq!(3 as (usize) + 3, 6); -} diff --git a/tests/ui/associated-types/associated-types-eq-2.stderr b/tests/ui/associated-types/associated-types-eq-2.stderr index e5013a35d45..ccd13123d70 100644 --- a/tests/ui/associated-types/associated-types-eq-2.stderr +++ b/tests/ui/associated-types/associated-types-eq-2.stderr @@ -3,8 +3,7 @@ error[E0658]: associated const equality is incomplete | LL | impl Tr3<N | __________^ -LL | | -LL | | +... | LL | | = 42, T2 = Qux, T3 = usize> for Bar { | |____^ | @@ -198,8 +197,7 @@ error[E0229]: associated item constraints are not allowed here | LL | impl Tr3<N | __________^ -LL | | -LL | | +... | LL | | = 42, T2 = Qux, T3 = usize> for Bar { | |____^ associated item constraint not allowed here | diff --git a/tests/ui/associated-types/issue-59324.stderr b/tests/ui/associated-types/issue-59324.stderr index ec2890cc8e7..805c3e60bb6 100644 --- a/tests/ui/associated-types/issue-59324.stderr +++ b/tests/ui/associated-types/issue-59324.stderr @@ -2,8 +2,7 @@ error[E0277]: the trait bound `Bug: Foo` is not satisfied --> $DIR/issue-59324.rs:11:1 | LL | / pub trait ThriftService<Bug: NotFoo>: -LL | | -LL | | +... | LL | | Service<AssocType = <Bug as Foo>::OnlyFoo> | |______________________________________________^ the trait `Foo` is not implemented for `Bug` | @@ -20,7 +19,6 @@ LL | | LL | | LL | | Service<AssocType = <Bug as Foo>::OnlyFoo> ... | -LL | | LL | | } | |_^ the trait `Foo` is not implemented for `Bug` | diff --git a/tests/ui/associated-types/missing-associated-types.stderr b/tests/ui/associated-types/missing-associated-types.stderr index ce4b57e8af8..3a56c55896e 100644 --- a/tests/ui/associated-types/missing-associated-types.stderr +++ b/tests/ui/associated-types/missing-associated-types.stderr @@ -42,11 +42,11 @@ LL | type Bat<Rhs> = dyn Add<Rhs> + Sub<Rhs> + Fine<Rhs>; = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Add<Rhs> + Sub<Rhs> + Fine<Rhs> {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> -error[E0191]: the value of the associated types `Output` in `Div`, `Output` in `Mul` must be specified +error[E0191]: the value of the associated types `Output` in `Div<Rhs>`, `Output` in `Mul<Rhs>` must be specified --> $DIR/missing-associated-types.rs:20:21 | LL | type Bal<Rhs> = dyn X<Rhs>; - | ^^^^^^ associated types `Output` (from trait `Div`), `Output` (from trait `Mul`) must be specified + | ^^^^^^ associated types `Output` (from trait `Div<Rhs>`), `Output` (from trait `Mul<Rhs>`) must be specified | = help: consider introducing a new type parameter, adding `where` constraints using the fully-qualified path to the associated types diff --git a/tests/ui/async-await/async-block-control-flow-static-semantics.stderr b/tests/ui/async-await/async-block-control-flow-static-semantics.stderr index 3bc467cc84d..4ed15a942c6 100644 --- a/tests/ui/async-await/async-block-control-flow-static-semantics.stderr +++ b/tests/ui/async-await/async-block-control-flow-static-semantics.stderr @@ -23,7 +23,6 @@ LL | | LL | | let block = async { LL | | return 0u8; ... | -LL | | LL | | } | |_^ expected `u8`, found `()` diff --git a/tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.stderr b/tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.stderr index 649a868faa5..b60f6a08338 100644 --- a/tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.stderr +++ b/tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.stderr @@ -31,7 +31,6 @@ LL | | LL | | if true { LL | | false ... | -LL | | LL | | }) | |_____^ expected `bool`, found `Option<()>` | diff --git a/tests/ui/async-await/inference_var_self_argument.stderr b/tests/ui/async-await/inference_var_self_argument.stderr index a33c5f7b07d..7b7b3dbc757 100644 --- a/tests/ui/async-await/inference_var_self_argument.stderr +++ b/tests/ui/async-await/inference_var_self_argument.stderr @@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `&dyn Foo` LL | async fn foo(self: &dyn Foo) { | ^^^^^^^^ | - = note: type of `self` must be `Self` or some type implementing `Receiver` - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/inference_var_self_argument.rs:5:5 diff --git a/tests/ui/async-await/issue-66312.stderr b/tests/ui/async-await/issue-66312.stderr index f4db949a5f4..c95ae1147df 100644 --- a/tests/ui/async-await/issue-66312.stderr +++ b/tests/ui/async-await/issue-66312.stderr @@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `T` LL | fn is_some(self: T); | ^ | - = note: type of `self` must be `Self` or some type implementing `Receiver` - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) error[E0308]: mismatched types --> $DIR/issue-66312.rs:9:8 diff --git a/tests/ui/async-await/issue-84841.stderr b/tests/ui/async-await/issue-84841.stderr index 1e22373ba6e..69c1c882d60 100644 --- a/tests/ui/async-await/issue-84841.stderr +++ b/tests/ui/async-await/issue-84841.stderr @@ -14,8 +14,7 @@ LL | async fn foo() { LL | | // Adding an .await here avoids the ICE LL | | test()?; | | ^ cannot use the `?` operator in an async function that returns `()` -LL | | -LL | | +... | LL | | } | |_- this function should return `Result` or `Option` to accept `?` | diff --git a/tests/ui/async-await/issues/issue-72312.stderr b/tests/ui/async-await/issues/issue-72312.stderr index cd93f8a3c55..8e6fb138a1f 100644 --- a/tests/ui/async-await/issues/issue-72312.stderr +++ b/tests/ui/async-await/issues/issue-72312.stderr @@ -8,10 +8,7 @@ LL | pub async fn start(&self) { | let's call the lifetime of this reference `'1` ... LL | / require_static(async move { -LL | | -LL | | -LL | | -LL | | &self; +... | LL | | }); | | ^ | | | diff --git a/tests/ui/async-await/track-caller/async-closure-gate.afn.stderr b/tests/ui/async-await/track-caller/async-closure-gate.afn.stderr index 8344b7a07dc..6887a904211 100644 --- a/tests/ui/async-await/track-caller/async-closure-gate.afn.stderr +++ b/tests/ui/async-await/track-caller/async-closure-gate.afn.stderr @@ -66,8 +66,7 @@ LL | fn foo3() { LL | / async { LL | | LL | | let _ = #[track_caller] || { -LL | | -LL | | }; +... | LL | | } | |_____^ expected `()`, found `async` block | diff --git a/tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr b/tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr index 8344b7a07dc..6887a904211 100644 --- a/tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr +++ b/tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr @@ -66,8 +66,7 @@ LL | fn foo3() { LL | / async { LL | | LL | | let _ = #[track_caller] || { -LL | | -LL | | }; +... | LL | | } | |_____^ expected `()`, found `async` block | diff --git a/tests/ui/attributes/collapse-debuginfo-invalid.stderr b/tests/ui/attributes/collapse-debuginfo-invalid.stderr index 7cbbd1d647e..70376f985cb 100644 --- a/tests/ui/attributes/collapse-debuginfo-invalid.stderr +++ b/tests/ui/attributes/collapse-debuginfo-invalid.stderr @@ -45,7 +45,6 @@ LL | | let _ = #[collapse_debuginfo(yes)] || { }; LL | | LL | | #[collapse_debuginfo(yes)] ... | -LL | | } LL | | } | |_- not a macro definition diff --git a/tests/ui/attributes/dump_def_parents.stderr b/tests/ui/attributes/dump_def_parents.stderr index a928e8e33a4..74ecd9b0a89 100644 --- a/tests/ui/attributes/dump_def_parents.stderr +++ b/tests/ui/attributes/dump_def_parents.stderr @@ -22,7 +22,6 @@ LL | | LL | | fn bar() { LL | | fn foo() { ... | -LL | | LL | | fn main() {} | |____________^ @@ -66,7 +65,6 @@ LL | | LL | | fn bar() { LL | | fn foo() { ... | -LL | | LL | | fn main() {} | |____________^ @@ -124,7 +122,6 @@ LL | | LL | | fn bar() { LL | | fn foo() { ... | -LL | | LL | | fn main() {} | |____________^ @@ -173,7 +170,6 @@ LL | | LL | | fn bar() { LL | | fn foo() { ... | -LL | | LL | | fn main() {} | |____________^ diff --git a/tests/ui/borrowck/borrowck-describe-lvalue.rs b/tests/ui/borrowck/borrowck-describe-lvalue.rs index cdcff69d6e5..f3a4b382fa8 100644 --- a/tests/ui/borrowck/borrowck-describe-lvalue.rs +++ b/tests/ui/borrowck/borrowck-describe-lvalue.rs @@ -231,7 +231,6 @@ fn main() { let x = &mut v; v[0].y; //~^ ERROR cannot use `v[_].y` because it was mutably borrowed - //~| ERROR cannot use `*v` because it was mutably borrowed drop(x); } // Field of constant index diff --git a/tests/ui/borrowck/borrowck-describe-lvalue.stderr b/tests/ui/borrowck/borrowck-describe-lvalue.stderr index 11f2e42d42b..666a21808d8 100644 --- a/tests/ui/borrowck/borrowck-describe-lvalue.stderr +++ b/tests/ui/borrowck/borrowck-describe-lvalue.stderr @@ -1,5 +1,5 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time - --> $DIR/borrowck-describe-lvalue.rs:254:13 + --> $DIR/borrowck-describe-lvalue.rs:253:13 | LL | let y = &mut x; | ------ first mutable borrow occurs here @@ -9,7 +9,7 @@ LL | *y = 1; | ------ first borrow later used here error[E0499]: cannot borrow `x` as mutable more than once at a time - --> $DIR/borrowck-describe-lvalue.rs:264:20 + --> $DIR/borrowck-describe-lvalue.rs:263:20 | LL | let y = &mut x; | ------ first mutable borrow occurs here @@ -19,7 +19,7 @@ LL | *y = 1; | ------ first borrow later used here error: captured variable cannot escape `FnMut` closure body - --> $DIR/borrowck-describe-lvalue.rs:262:16 + --> $DIR/borrowck-describe-lvalue.rs:261:16 | LL | let mut x = 0; | ----- variable defined here @@ -300,17 +300,6 @@ LL | S { x: F { y: ref x0, .. }, .. } => LL | drop(x); | - mutable borrow later used here -error[E0503]: cannot use `*v` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:232:9 - | -LL | let x = &mut v; - | ------ `v` is borrowed here -LL | v[0].y; - | ^^^^ use of borrowed `v` -... -LL | drop(x); - | - borrow later used here - error[E0503]: cannot use `v[_].y` because it was mutably borrowed --> $DIR/borrowck-describe-lvalue.rs:232:9 | @@ -318,12 +307,12 @@ LL | let x = &mut v; | ------ `v` is borrowed here LL | v[0].y; | ^^^^^^ use of borrowed `v` -... +LL | LL | drop(x); | - borrow later used here error[E0502]: cannot borrow `v[..].x` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-describe-lvalue.rs:243:24 + --> $DIR/borrowck-describe-lvalue.rs:242:24 | LL | let x = &mut v; | ------ mutable borrow occurs here @@ -357,7 +346,7 @@ LL | drop(x); | - mutable borrow later used here error[E0382]: use of moved value: `x` - --> $DIR/borrowck-describe-lvalue.rs:274:22 + --> $DIR/borrowck-describe-lvalue.rs:273:22 | LL | drop(x); | - value moved here @@ -366,7 +355,7 @@ LL | drop(x); | = note: move occurs because `x` has type `Vec<i32>`, which does not implement the `Copy` trait -error: aborting due to 32 previous errors +error: aborting due to 31 previous errors Some errors have detailed explanations: E0382, E0499, E0502, E0503. For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/issue-109271-pass-self-into-closure.stderr b/tests/ui/borrowck/issue-109271-pass-self-into-closure.stderr index a66281a188d..aa4e5fb2f69 100644 --- a/tests/ui/borrowck/issue-109271-pass-self-into-closure.stderr +++ b/tests/ui/borrowck/issue-109271-pass-self-into-closure.stderr @@ -40,8 +40,6 @@ LL | v.call(|(), this: &mut S| { | | | | _____| first borrow later used by call | | -LL | | -LL | | ... | LL | | v.set(); | | - first borrow occurs due to use of `v` in closure diff --git a/tests/ui/borrowck/no-invalid-mut-suggestion-for-raw-pointer-issue-127562.rs b/tests/ui/borrowck/no-invalid-mut-suggestion-for-raw-pointer-issue-127562.rs new file mode 100644 index 00000000000..5425e571af0 --- /dev/null +++ b/tests/ui/borrowck/no-invalid-mut-suggestion-for-raw-pointer-issue-127562.rs @@ -0,0 +1,8 @@ +//! Regression test for invalid suggestion for `&raw const expr` reported in +//! <https://github.com/rust-lang/rust/issues/127562>. + +fn main() { + let val = 2; + let ptr = &raw const val; + unsafe { *ptr = 3; } //~ ERROR cannot assign to `*ptr`, which is behind a `*const` pointer +} diff --git a/tests/ui/borrowck/no-invalid-mut-suggestion-for-raw-pointer-issue-127562.stderr b/tests/ui/borrowck/no-invalid-mut-suggestion-for-raw-pointer-issue-127562.stderr new file mode 100644 index 00000000000..c27dcc19827 --- /dev/null +++ b/tests/ui/borrowck/no-invalid-mut-suggestion-for-raw-pointer-issue-127562.stderr @@ -0,0 +1,9 @@ +error[E0594]: cannot assign to `*ptr`, which is behind a `*const` pointer + --> $DIR/no-invalid-mut-suggestion-for-raw-pointer-issue-127562.rs:7:14 + | +LL | unsafe { *ptr = 3; } + | ^^^^^^^^ `ptr` is a `*const` pointer, so the data it refers to cannot be written + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/check-cfg/auxiliary/cfg_macro.rs b/tests/ui/check-cfg/auxiliary/cfg_macro.rs index d68accd9202..1293fd6975e 100644 --- a/tests/ui/check-cfg/auxiliary/cfg_macro.rs +++ b/tests/ui/check-cfg/auxiliary/cfg_macro.rs @@ -9,3 +9,19 @@ macro_rules! my_lib_macro { $crate::my_lib_func() }; } + +#[macro_export] +macro_rules! my_lib_macro_value { + () => { + #[cfg(panic = "UNEXPECTED_VALUE")] + $crate::my_lib_func() + }; +} + +#[macro_export] +macro_rules! my_lib_macro_feature { + () => { + #[cfg(feature = "UNEXPECTED_FEATURE")] + $crate::my_lib_func() + }; +} diff --git a/tests/ui/check-cfg/report-in-external-macros.cargo.stderr b/tests/ui/check-cfg/report-in-external-macros.cargo.stderr new file mode 100644 index 00000000000..6fb397b5529 --- /dev/null +++ b/tests/ui/check-cfg/report-in-external-macros.cargo.stderr @@ -0,0 +1,42 @@ +warning: unexpected `cfg` condition name: `my_lib_cfg` + --> $DIR/report-in-external-macros.rs:13:5 + | +LL | cfg_macro::my_lib_macro!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` + = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate + = help: try refering to `cfg_macro::my_lib_macro` crate for guidance on how handle this unexpected cfg + = help: the macro `cfg_macro::my_lib_macro` may come from an old version of it's defining crate, try updating your dependencies with `cargo update` + = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + = note: this warning originates in the macro `cfg_macro::my_lib_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: unexpected `cfg` condition value: `UNEXPECTED_VALUE` + --> $DIR/report-in-external-macros.rs:16:5 + | +LL | cfg_macro::my_lib_macro_value!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected values for `panic` are: `abort` and `unwind` + = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate + = help: try refering to `cfg_macro::my_lib_macro_value` crate for guidance on how handle this unexpected cfg + = help: the macro `cfg_macro::my_lib_macro_value` may come from an old version of it's defining crate, try updating your dependencies with `cargo update` + = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration + = note: this warning originates in the macro `cfg_macro::my_lib_macro_value` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: unexpected `cfg` condition value: `UNEXPECTED_FEATURE` + --> $DIR/report-in-external-macros.rs:19:5 + | +LL | cfg_macro::my_lib_macro_feature!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: no expected values for `feature` + = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate + = help: try refering to `cfg_macro::my_lib_macro_feature` crate for guidance on how handle this unexpected cfg + = help: the macro `cfg_macro::my_lib_macro_feature` may come from an old version of it's defining crate, try updating your dependencies with `cargo update` + = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration + = note: this warning originates in the macro `cfg_macro::my_lib_macro_feature` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 3 warnings emitted + diff --git a/tests/ui/check-cfg/report-in-external-macros.rs b/tests/ui/check-cfg/report-in-external-macros.rs index 56550b04af3..72c2f6f6618 100644 --- a/tests/ui/check-cfg/report-in-external-macros.rs +++ b/tests/ui/check-cfg/report-in-external-macros.rs @@ -3,10 +3,19 @@ //@ check-pass //@ no-auto-check-cfg +//@ revisions: cargo rustc +//@ [rustc]unset-rustc-env:CARGO_CRATE_NAME +//@ [cargo]rustc-env:CARGO_CRATE_NAME=foo //@ aux-crate: cfg_macro=cfg_macro.rs -//@ compile-flags: --check-cfg=cfg() +//@ compile-flags: --check-cfg=cfg(feature,values()) fn main() { cfg_macro::my_lib_macro!(); //~^ WARNING unexpected `cfg` condition name + + cfg_macro::my_lib_macro_value!(); + //~^ WARNING unexpected `cfg` condition value + + cfg_macro::my_lib_macro_feature!(); + //~^ WARNING unexpected `cfg` condition value } diff --git a/tests/ui/check-cfg/report-in-external-macros.rustc.stderr b/tests/ui/check-cfg/report-in-external-macros.rustc.stderr new file mode 100644 index 00000000000..1a03184ee81 --- /dev/null +++ b/tests/ui/check-cfg/report-in-external-macros.rustc.stderr @@ -0,0 +1,41 @@ +warning: unexpected `cfg` condition name: `my_lib_cfg` + --> $DIR/report-in-external-macros.rs:13:5 + | +LL | cfg_macro::my_lib_macro!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` + = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate + = help: try refering to `cfg_macro::my_lib_macro` crate for guidance on how handle this unexpected cfg + = help: to expect this configuration use `--check-cfg=cfg(my_lib_cfg)` + = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + = note: this warning originates in the macro `cfg_macro::my_lib_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: unexpected `cfg` condition value: `UNEXPECTED_VALUE` + --> $DIR/report-in-external-macros.rs:16:5 + | +LL | cfg_macro::my_lib_macro_value!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected values for `panic` are: `abort` and `unwind` + = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate + = help: try refering to `cfg_macro::my_lib_macro_value` crate for guidance on how handle this unexpected cfg + = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration + = note: this warning originates in the macro `cfg_macro::my_lib_macro_value` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: unexpected `cfg` condition value: `UNEXPECTED_FEATURE` + --> $DIR/report-in-external-macros.rs:19:5 + | +LL | cfg_macro::my_lib_macro_feature!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: no expected values for `feature` + = help: to expect this configuration use `--check-cfg=cfg(feature, values("UNEXPECTED_FEATURE"))` + = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate + = help: try refering to `cfg_macro::my_lib_macro_feature` crate for guidance on how handle this unexpected cfg + = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration + = note: this warning originates in the macro `cfg_macro::my_lib_macro_feature` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 3 warnings emitted + diff --git a/tests/ui/check-cfg/report-in-external-macros.stderr b/tests/ui/check-cfg/report-in-external-macros.stderr deleted file mode 100644 index 11300a4e402..00000000000 --- a/tests/ui/check-cfg/report-in-external-macros.stderr +++ /dev/null @@ -1,14 +0,0 @@ -warning: unexpected `cfg` condition name: `my_lib_cfg` - --> $DIR/report-in-external-macros.rs:10:5 - | -LL | cfg_macro::my_lib_macro!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` - = help: to expect this configuration use `--check-cfg=cfg(my_lib_cfg)` - = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration - = note: `#[warn(unexpected_cfgs)]` on by default - = note: this warning originates in the macro `cfg_macro::my_lib_macro` (in Nightly builds, run with -Z macro-backtrace for more info) - -warning: 1 warning emitted - diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr index 3df1545cd4a..e2ceb669482 100644 --- a/tests/ui/check-cfg/target_feature.stderr +++ b/tests/ui/check-cfg/target_feature.stderr @@ -98,6 +98,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `fp8dot2` `fp8dot4` `fp8fma` +`fpregs` `fpuv2_df` `fpuv2_sf` `fpuv3_df` @@ -261,6 +262,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `vsx` `wfxt` `wide-arithmetic` +`x87` `xop` `xsave` `xsavec` diff --git a/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr b/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr index 3c4f2de73a4..cb351d3cebd 100644 --- a/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr +++ b/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr @@ -16,7 +16,6 @@ LL | | LL | | LL | | m[0] += 10; ... | -LL | | LL | | }; | |_____^ | @@ -39,7 +38,6 @@ LL | | LL | | LL | | m[0] += 10; ... | -LL | | LL | | }; | |_____^ | diff --git a/tests/ui/closures/2229_closure_analysis/by_value.stderr b/tests/ui/closures/2229_closure_analysis/by_value.stderr index f843b76d723..af4ae34ad64 100644 --- a/tests/ui/closures/2229_closure_analysis/by_value.stderr +++ b/tests/ui/closures/2229_closure_analysis/by_value.stderr @@ -16,7 +16,6 @@ LL | | LL | | LL | | let p = t.0.0; ... | -LL | | LL | | }; | |_____^ | @@ -39,7 +38,6 @@ LL | | LL | | LL | | let p = t.0.0; ... | -LL | | LL | | }; | |_____^ | diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr index 64ae704bc90..eef201792c6 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr @@ -16,7 +16,6 @@ LL | | LL | | LL | | println!("{:?}", p); ... | -LL | | LL | | }; | |_____^ | @@ -49,7 +48,6 @@ LL | | LL | | LL | | println!("{:?}", p); ... | -LL | | LL | | }; | |_____^ | diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr index 40c075f3cc8..8fe4d2d57ab 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr @@ -16,7 +16,6 @@ LL | | LL | | LL | | let _x = p.x; ... | -LL | | LL | | }; | |_____^ | @@ -39,7 +38,6 @@ LL | | LL | | LL | | let _x = p.x; ... | -LL | | LL | | }; | |_____^ | diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr index a4689f2ea96..f1dbefe15d5 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr @@ -16,7 +16,6 @@ LL | | LL | | LL | | let _x = a.b.c; ... | -LL | | LL | | }; | |_____^ | @@ -39,7 +38,6 @@ LL | | LL | | LL | | let _x = a.b.c; ... | -LL | | LL | | }; | |_____^ | diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr index 9d3004dbbb0..91c3d6d1674 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr @@ -16,7 +16,6 @@ LL | | LL | | LL | | let _x = a.b; ... | -LL | | LL | | }; | |_____^ | @@ -39,7 +38,6 @@ LL | | LL | | LL | | let _x = a.b; ... | -LL | | LL | | }; | |_____^ | diff --git a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr index 48fbd682a5b..c9c227335a9 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr +++ b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr @@ -15,8 +15,7 @@ LL | / || { LL | | LL | | LL | | println!("{}", p.x); -LL | | -LL | | +... | LL | | }; | |_____^ | @@ -33,8 +32,7 @@ LL | / || { LL | | LL | | LL | | println!("{}", p.x); -LL | | -LL | | +... | LL | | }; | |_____^ | diff --git a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr index 496511d6025..84aac180fbb 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr +++ b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr @@ -15,8 +15,7 @@ LL | / || { LL | | LL | | LL | | println!("{}", t.0); -LL | | -LL | | +... | LL | | }; | |_____^ | @@ -33,8 +32,7 @@ LL | / || { LL | | LL | | LL | | println!("{}", t.0); -LL | | -LL | | +... | LL | | }; | |_____^ | diff --git a/tests/ui/closures/2229_closure_analysis/capture-enums.stderr b/tests/ui/closures/2229_closure_analysis/capture-enums.stderr index 2d70b614858..89a879cec46 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-enums.stderr +++ b/tests/ui/closures/2229_closure_analysis/capture-enums.stderr @@ -26,7 +26,6 @@ LL | | LL | | LL | | if let Info::Point(_, _, str) = point { ... | -LL | | } LL | | }; | |_____^ | @@ -59,7 +58,6 @@ LL | | LL | | LL | | if let Info::Point(_, _, str) = point { ... | -LL | | } LL | | }; | |_____^ | diff --git a/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr b/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr index d118f7573a4..447ad8f4a68 100644 --- a/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr +++ b/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr @@ -16,7 +16,6 @@ LL | | LL | | LL | | let x = &p.a.p.x; ... | -LL | | LL | | }; | |_____^ | @@ -44,7 +43,6 @@ LL | | LL | | LL | | let x = &p.a.p.x; ... | -LL | | LL | | }; | |_____^ | diff --git a/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr b/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr index cc5f74613e4..639d1714721 100644 --- a/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr +++ b/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr @@ -16,7 +16,6 @@ LL | | LL | | LL | | let x = &t.0.0.0; ... | -LL | | LL | | }; | |_____^ | @@ -44,7 +43,6 @@ LL | | LL | | LL | | let x = &t.0.0.0; ... | -LL | | LL | | }; | |_____^ | diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.rs index 3abc81e191e..2d22c9a856f 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.rs +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.rs @@ -12,8 +12,7 @@ fn arrays_1() { // c will capture `arr` completely, therefore another index into the // array can't be modified here arr[1] += 10; - //~^ ERROR: cannot use `arr` because it was mutably borrowed - //~| ERROR: cannot use `arr[_]` because it was mutably borrowed + //~^ ERROR: cannot use `arr[_]` because it was mutably borrowed c(); } @@ -55,8 +54,7 @@ fn arrays_4() { // c will capture `arr` completely, therefore we cannot borrow another index // into the array. println!("{}", arr[3]); - //~^ ERROR: cannot use `arr` because it was mutably borrowed - //~| ERROR: cannot borrow `arr[_]` as immutable because it is also borrowed as mutable + //~^ ERROR: cannot borrow `arr[_]` as immutable because it is also borrowed as mutable c(); } diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr index 9e5200ef34b..97ecdfab820 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr @@ -1,17 +1,3 @@ -error[E0503]: cannot use `arr` because it was mutably borrowed - --> $DIR/arrays.rs:14:5 - | -LL | let mut c = || { - | -- `arr` is borrowed here -LL | arr[0] += 10; - | --- borrow occurs due to use of `arr` in closure -... -LL | arr[1] += 10; - | ^^^^^^ use of borrowed `arr` -... -LL | c(); - | - borrow later used here - error[E0503]: cannot use `arr[_]` because it was mutably borrowed --> $DIR/arrays.rs:14:5 | @@ -22,12 +8,12 @@ LL | arr[0] += 10; ... LL | arr[1] += 10; | ^^^^^^^^^^^^ use of borrowed `arr` -... +LL | LL | c(); | - borrow later used here error[E0506]: cannot assign to `arr[_]` because it is borrowed - --> $DIR/arrays.rs:29:5 + --> $DIR/arrays.rs:28:5 | LL | let c = || { | -- `arr[_]` is borrowed here @@ -41,7 +27,7 @@ LL | c(); | - borrow later used here error[E0506]: cannot assign to `arr[_]` because it is borrowed - --> $DIR/arrays.rs:43:5 + --> $DIR/arrays.rs:42:5 | LL | let c = || { | -- `arr[_]` is borrowed here @@ -54,22 +40,8 @@ LL | LL | c(); | - borrow later used here -error[E0503]: cannot use `arr` because it was mutably borrowed - --> $DIR/arrays.rs:57:20 - | -LL | let mut c = || { - | -- `arr` is borrowed here -LL | arr[1] += 10; - | --- borrow occurs due to use of `arr` in closure -... -LL | println!("{}", arr[3]); - | ^^^^^^ use of borrowed `arr` -... -LL | c(); - | - borrow later used here - error[E0502]: cannot borrow `arr[_]` as immutable because it is also borrowed as mutable - --> $DIR/arrays.rs:57:20 + --> $DIR/arrays.rs:56:20 | LL | let mut c = || { | -- mutable borrow occurs here @@ -85,7 +57,7 @@ LL | c(); = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0502]: cannot borrow `arr` as immutable because it is also borrowed as mutable - --> $DIR/arrays.rs:73:24 + --> $DIR/arrays.rs:71:24 | LL | let mut c = || { | -- mutable borrow occurs here @@ -98,7 +70,7 @@ LL | println!("{:#?}", &arr[3..2]); LL | c(); | - mutable borrow later used here -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0502, E0503, E0506. For more information about an error, try `rustc --explain E0502`. diff --git a/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr b/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr index 6dbe8c153c0..3e4c4d3ccd3 100644 --- a/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr +++ b/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr @@ -15,8 +15,7 @@ LL | / || { LL | | LL | | LL | | println!("This uses new capture analyysis to capture s={}", s); -LL | | -LL | | +... | LL | | }; | |_____^ | @@ -33,8 +32,7 @@ LL | / || { LL | | LL | | LL | | println!("This uses new capture analyysis to capture s={}", s); -LL | | -LL | | +... | LL | | }; | |_____^ | diff --git a/tests/ui/closures/2229_closure_analysis/issue-118144.stderr b/tests/ui/closures/2229_closure_analysis/issue-118144.stderr index 85cb5adc07e..87084e60237 100644 --- a/tests/ui/closures/2229_closure_analysis/issue-118144.stderr +++ b/tests/ui/closures/2229_closure_analysis/issue-118144.stderr @@ -5,6 +5,11 @@ LL | V(x) = func_arg; | ^^^^ -------- this expression has type `&mut V` | | | expected `&mut V`, found `V` + | +help: consider dereferencing to access the inner value using the Deref trait + | +LL | V(x) = &*func_arg; + | ~~~~~~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/closures/2229_closure_analysis/issue-87378.stderr b/tests/ui/closures/2229_closure_analysis/issue-87378.stderr index 3273e92d9d1..862ae7445e8 100644 --- a/tests/ui/closures/2229_closure_analysis/issue-87378.stderr +++ b/tests/ui/closures/2229_closure_analysis/issue-87378.stderr @@ -15,8 +15,7 @@ LL | / || { LL | | LL | | LL | | unsafe { u.value } -LL | | -LL | | +... | LL | | }; | |_____^ | @@ -33,8 +32,7 @@ LL | / || { LL | | LL | | LL | | unsafe { u.value } -LL | | -LL | | +... | LL | | }; | |_____^ | diff --git a/tests/ui/closures/2229_closure_analysis/issue-88476.stderr b/tests/ui/closures/2229_closure_analysis/issue-88476.stderr index 1c0e254dbf7..225b0335cf5 100644 --- a/tests/ui/closures/2229_closure_analysis/issue-88476.stderr +++ b/tests/ui/closures/2229_closure_analysis/issue-88476.stderr @@ -23,11 +23,7 @@ error: First Pass analysis includes: | LL | let x = #[rustc_capture_analysis] move || { | _______________________________________^ -LL | | -LL | | -LL | | ... | -LL | | LL | | }; | |_____^ | @@ -42,11 +38,7 @@ error: Min Capture analysis includes: | LL | let x = #[rustc_capture_analysis] move || { | _______________________________________^ -LL | | -LL | | -LL | | ... | -LL | | LL | | }; | |_____^ | @@ -61,11 +53,7 @@ error: First Pass analysis includes: | LL | let c = #[rustc_capture_analysis] move || { | _______________________________________^ -LL | | -LL | | -LL | | ... | -LL | | LL | | }; | |_____^ | @@ -80,11 +68,7 @@ error: Min Capture analysis includes: | LL | let c = #[rustc_capture_analysis] move || { | _______________________________________^ -LL | | -LL | | -LL | | ... | -LL | | LL | | }; | |_____^ | diff --git a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr index 7125bfa3101..e7e5e7f7fa1 100644 --- a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr @@ -6,7 +6,6 @@ LL | | LL | | LL | | match variant { ... | -LL | | } LL | | }; | |_____^ | @@ -24,7 +23,6 @@ LL | | LL | | LL | | match variant { ... | -LL | | } LL | | }; | |_____^ | @@ -64,7 +62,6 @@ LL | | LL | | LL | | match variant { ... | -LL | | } LL | | }; | |_____^ | @@ -87,7 +84,6 @@ LL | | LL | | LL | | match variant { ... | -LL | | } LL | | }; | |_____^ | @@ -138,7 +134,6 @@ LL | | LL | | LL | | match variant { ... | -LL | | } LL | | }; | |_____^ | @@ -156,7 +151,6 @@ LL | | LL | | LL | | match variant { ... | -LL | | } LL | | }; | |_____^ | @@ -174,7 +168,6 @@ LL | | LL | | LL | | match slice { ... | -LL | | } LL | | }; | |_____^ | @@ -192,7 +185,6 @@ LL | | LL | | LL | | match slice { ... | -LL | | } LL | | }; | |_____^ | @@ -210,7 +202,6 @@ LL | | LL | | LL | | match slice { ... | -LL | | } LL | | }; | |_____^ | @@ -228,7 +219,6 @@ LL | | LL | | LL | | match slice { ... | -LL | | } LL | | }; | |_____^ | @@ -246,7 +236,6 @@ LL | | LL | | LL | | match slice { ... | -LL | | } LL | | }; | |_____^ | @@ -264,7 +253,6 @@ LL | | LL | | LL | | match slice { ... | -LL | | } LL | | }; | |_____^ | @@ -281,8 +269,7 @@ LL | / || { LL | | LL | | match slice { LL | | [..] => {}, -LL | | _ => {} -LL | | } +... | LL | | }; | |_____^ diff --git a/tests/ui/closures/2229_closure_analysis/move_closure.stderr b/tests/ui/closures/2229_closure_analysis/move_closure.stderr index 68754b8f7be..a4919d488d1 100644 --- a/tests/ui/closures/2229_closure_analysis/move_closure.stderr +++ b/tests/ui/closures/2229_closure_analysis/move_closure.stderr @@ -139,8 +139,7 @@ LL | / move || { LL | | LL | | LL | | t.0.0 = "new S".into(); -LL | | -LL | | +... | LL | | }; | |_____^ | @@ -157,8 +156,7 @@ LL | / move || { LL | | LL | | LL | | t.0.0 = "new S".into(); -LL | | -LL | | +... | LL | | }; | |_____^ | @@ -175,8 +173,7 @@ LL | / move || { LL | | LL | | LL | | *ref_s += 10; -LL | | -LL | | +... | LL | | }; | |_____^ | @@ -193,8 +190,7 @@ LL | / move || { LL | | LL | | LL | | *ref_s += 10; -LL | | -LL | | +... | LL | | }; | |_____^ | @@ -211,8 +207,7 @@ LL | / move || { LL | | LL | | LL | | t.0.0 = "new s".into(); -LL | | -LL | | +... | LL | | }; | |_____^ | @@ -229,8 +224,7 @@ LL | / move || { LL | | LL | | LL | | t.0.0 = "new s".into(); -LL | | -LL | | +... | LL | | }; | |_____^ | @@ -247,8 +241,7 @@ LL | / move || { LL | | LL | | LL | | let _t = t.0.0; -LL | | -LL | | +... | LL | | }; | |_____^ | @@ -265,8 +258,7 @@ LL | / move || { LL | | LL | | LL | | let _t = t.0.0; -LL | | -LL | | +... | LL | | }; | |_____^ | @@ -283,8 +275,7 @@ LL | / move || { LL | | LL | | LL | | let _t = t.0.0; -LL | | -LL | | +... | LL | | }; | |_____^ | @@ -301,8 +292,7 @@ LL | / move || { LL | | LL | | LL | | let _t = t.0.0; -LL | | -LL | | +... | LL | | }; | |_____^ | @@ -319,8 +309,7 @@ LL | / move || { LL | | LL | | LL | | let _t = b.0; -LL | | -LL | | +... | LL | | }; | |_____^ | @@ -337,8 +326,7 @@ LL | / move || { LL | | LL | | LL | | let _t = b.0; -LL | | -LL | | +... | LL | | }; | |_____^ | @@ -355,8 +343,7 @@ LL | / move || { LL | | LL | | LL | | println!("{}", b.0); -LL | | -LL | | +... | LL | | }; | |_____^ | @@ -373,8 +360,7 @@ LL | / move || { LL | | LL | | LL | | println!("{}", b.0); -LL | | -LL | | +... | LL | | }; | |_____^ | @@ -391,8 +377,7 @@ LL | / move || { LL | | LL | | LL | | println!("{}", t.1.0); -LL | | -LL | | +... | LL | | }; | |_____^ | @@ -409,8 +394,7 @@ LL | / move || { LL | | LL | | LL | | println!("{}", t.1.0); -LL | | -LL | | +... | LL | | }; | |_____^ | diff --git a/tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr b/tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr index 97f53e490e8..cbc7188a4ec 100644 --- a/tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr +++ b/tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr @@ -15,8 +15,7 @@ LL | / || { LL | | LL | | LL | | println!("{}", w.p.x); -LL | | -LL | | +... | LL | | }; | |_____^ | @@ -33,8 +32,7 @@ LL | / || { LL | | LL | | LL | | println!("{}", w.p.x); -LL | | -LL | | +... | LL | | }; | |_____^ | diff --git a/tests/ui/closures/2229_closure_analysis/nested-closure.stderr b/tests/ui/closures/2229_closure_analysis/nested-closure.stderr index 03550cb2d35..3b36069e624 100644 --- a/tests/ui/closures/2229_closure_analysis/nested-closure.stderr +++ b/tests/ui/closures/2229_closure_analysis/nested-closure.stderr @@ -60,7 +60,6 @@ LL | | LL | | LL | | println!("{}", p.x); ... | -LL | | LL | | }; | |_____^ | @@ -88,7 +87,6 @@ LL | | LL | | LL | | println!("{}", p.x); ... | -LL | | LL | | }; | |_____^ | diff --git a/tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr b/tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr index e82295f047b..c6608c05900 100644 --- a/tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr +++ b/tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr @@ -15,8 +15,7 @@ LL | / || { LL | | LL | | LL | | println!("{}", pent.points[5].x); -LL | | -LL | | +... | LL | | }; | |_____^ | @@ -33,8 +32,7 @@ LL | / || { LL | | LL | | LL | | println!("{}", pent.points[5].x); -LL | | -LL | | +... | LL | | }; | |_____^ | diff --git a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr index 65a0a317ab6..ff3cd5b8f01 100644 --- a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr +++ b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr @@ -36,7 +36,6 @@ LL | | LL | | LL | | println!("{:?}", a.0); ... | -LL | | LL | | }; | |_____^ | @@ -69,7 +68,6 @@ LL | | LL | | LL | | println!("{:?}", a.0); ... | -LL | | LL | | }; | |_____^ | @@ -102,7 +100,6 @@ LL | | LL | | LL | | println!("{:?}", a.1); ... | -LL | | LL | | }; | |_____^ | @@ -135,7 +132,6 @@ LL | | LL | | LL | | println!("{:?}", a.1); ... | -LL | | LL | | }; | |_____^ | @@ -168,7 +164,6 @@ LL | | LL | | LL | | println!("{:?}", b.1); ... | -LL | | LL | | }; | |_____^ | @@ -201,7 +196,6 @@ LL | | LL | | LL | | println!("{:?}", b.1); ... | -LL | | LL | | }; | |_____^ | diff --git a/tests/ui/closures/2229_closure_analysis/repr_packed.stderr b/tests/ui/closures/2229_closure_analysis/repr_packed.stderr index d4b2f8bfeae..bab1e8f9977 100644 --- a/tests/ui/closures/2229_closure_analysis/repr_packed.stderr +++ b/tests/ui/closures/2229_closure_analysis/repr_packed.stderr @@ -118,7 +118,6 @@ LL | | LL | | LL | | println!("{}", foo.x); ... | -LL | | LL | | }; | |_____^ | @@ -141,7 +140,6 @@ LL | | LL | | LL | | println!("{}", foo.x); ... | -LL | | LL | | }; | |_____^ | diff --git a/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr b/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr index a88bd01093a..d4201b2d4c2 100644 --- a/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr +++ b/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr @@ -16,7 +16,6 @@ LL | | LL | | LL | | p.x += 10; ... | -LL | | LL | | }; | |_____^ | @@ -39,7 +38,6 @@ LL | | LL | | LL | | p.x += 10; ... | -LL | | LL | | }; | |_____^ | diff --git a/tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr b/tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr index 54463c5277d..9f3c6576c72 100644 --- a/tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr +++ b/tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr @@ -25,8 +25,7 @@ LL | / || unsafe { LL | | LL | | LL | | println!("{:?}", (*t.0).s); -LL | | -LL | | +... | LL | | }; | |_____^ | @@ -43,8 +42,7 @@ LL | / || unsafe { LL | | LL | | LL | | println!("{:?}", (*t.0).s); -LL | | -LL | | +... | LL | | }; | |_____^ | diff --git a/tests/ui/closures/2229_closure_analysis/wild_patterns.stderr b/tests/ui/closures/2229_closure_analysis/wild_patterns.stderr index 4d6d85649da..4cb0f4a4a92 100644 --- a/tests/ui/closures/2229_closure_analysis/wild_patterns.stderr +++ b/tests/ui/closures/2229_closure_analysis/wild_patterns.stderr @@ -32,11 +32,7 @@ error: First Pass analysis includes: --> $DIR/wild_patterns.rs:26:5 | LL | / || { -LL | | -LL | | -LL | | // FIXME(arora-aman): Change `_x` to `_` ... | -LL | | LL | | }; | |_____^ | @@ -50,11 +46,7 @@ error: Min Capture analysis includes: --> $DIR/wild_patterns.rs:26:5 | LL | / || { -LL | | -LL | | -LL | | // FIXME(arora-aman): Change `_x` to `_` ... | -LL | | LL | | }; | |_____^ | @@ -68,11 +60,7 @@ error: First Pass analysis includes: --> $DIR/wild_patterns.rs:45:5 | LL | / || { -LL | | -LL | | -LL | | // FIXME(arora-aman): Change `_x` to `_` ... | -LL | | LL | | }; | |_____^ | @@ -86,11 +74,7 @@ error: Min Capture analysis includes: --> $DIR/wild_patterns.rs:45:5 | LL | / || { -LL | | -LL | | -LL | | // FIXME(arora-aman): Change `_x` to `_` ... | -LL | | LL | | }; | |_____^ | @@ -104,11 +88,7 @@ error: First Pass analysis includes: --> $DIR/wild_patterns.rs:64:5 | LL | / || { -LL | | -LL | | -LL | | // FIXME(arora-aman): Change `_x` to `_` ... | -LL | | LL | | }; | |_____^ | @@ -122,11 +102,7 @@ error: Min Capture analysis includes: --> $DIR/wild_patterns.rs:64:5 | LL | / || { -LL | | -LL | | -LL | | // FIXME(arora-aman): Change `_x` to `_` ... | -LL | | LL | | }; | |_____^ | diff --git a/tests/ui/codegen/alias-uninit-value.rs b/tests/ui/codegen/alias-uninit-value.rs new file mode 100644 index 00000000000..a8aa94caaf2 --- /dev/null +++ b/tests/ui/codegen/alias-uninit-value.rs @@ -0,0 +1,26 @@ +//! Regression test for issue #374, where previously rustc performed conditional jumps or moves that +//! incorrectly depended on uninitialized values. +//! +//! Issue: <https://github.com/rust-lang/rust/issues/374>. + +//@ run-pass + +#![allow(dead_code)] + +enum TyS { + Nil, +} + +struct RawT { + struct_: TyS, + cname: Option<String>, + hash: usize, +} + +fn mk_raw_ty(st: TyS, cname: Option<String>) -> RawT { + return RawT { struct_: st, cname: cname, hash: 0 }; +} + +pub fn main() { + mk_raw_ty(TyS::Nil, None::<String>); +} diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.ascii.svg b/tests/ui/codemap_tests/huge_multispan_highlight.ascii.svg index 6f46df0101e..1cedbf75e4b 100644 --- a/tests/ui/codemap_tests/huge_multispan_highlight.ascii.svg +++ b/tests/ui/codemap_tests/huge_multispan_highlight.ascii.svg @@ -1,4 +1,4 @@ -<svg width="743px" height="848px" xmlns="http://www.w3.org/2000/svg"> +<svg width="743px" height="758px" xmlns="http://www.w3.org/2000/svg"> <style> .fg { fill: #AAAAAA } .bg { background: #000000 } @@ -33,83 +33,73 @@ </tspan> <tspan x="10px" y="136px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold"> _________________-</tspan> </tspan> - <tspan x="10px" y="154px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> // last line shown in multispan header</tspan> + <tspan x="10px" y="154px"><tspan class="fg-ansi256-012 bold">...</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan> </tspan> - <tspan x="10px" y="172px"><tspan class="fg-ansi256-012 bold">...</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan> + <tspan x="10px" y="172px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> ),</tspan> </tspan> - <tspan x="10px" y="190px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan> + <tspan x="10px" y="190px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|_________-</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">this is found to be of type `()`</tspan> </tspan> - <tspan x="10px" y="208px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> ),</tspan> + <tspan x="10px" y="208px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> false => "</tspan> </tspan> - <tspan x="10px" y="226px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|_________-</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">this is found to be of type `()`</tspan> + <tspan x="10px" y="226px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold"> __________________^</tspan> </tspan> - <tspan x="10px" y="244px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> false => "</tspan> + <tspan x="10px" y="244px"><tspan class="fg-ansi256-012 bold">...</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan> </tspan> - <tspan x="10px" y="262px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold"> __________________^</tspan> + <tspan x="10px" y="262px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> ",</tspan> </tspan> - <tspan x="10px" y="280px"><tspan class="fg-ansi256-012 bold">...</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan> + <tspan x="10px" y="280px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|_________^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected `()`, found `&str`</tspan> </tspan> - <tspan x="10px" y="298px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan> + <tspan x="10px" y="298px"> </tspan> - <tspan x="10px" y="316px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> ",</tspan> + <tspan x="10px" y="316px"><tspan class="fg-ansi256-009 bold">error[E0308]</tspan><tspan class="bold">: `match` arms have incompatible types</tspan> </tspan> - <tspan x="10px" y="334px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|_________^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected `()`, found `&str`</tspan> + <tspan x="10px" y="334px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$DIR/huge_multispan_highlight.rs:216:18</tspan> </tspan> - <tspan x="10px" y="352px"> + <tspan x="10px" y="352px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan> </tspan> - <tspan x="10px" y="370px"><tspan class="fg-ansi256-009 bold">error[E0308]</tspan><tspan class="bold">: `match` arms have incompatible types</tspan> + <tspan x="10px" y="370px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> let _ = match true {</tspan> </tspan> - <tspan x="10px" y="388px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$DIR/huge_multispan_highlight.rs:216:18</tspan> + <tspan x="10px" y="388px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">----------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">`match` arms have incompatible types</tspan> </tspan> - <tspan x="10px" y="406px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan> + <tspan x="10px" y="406px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> true => (</tspan> </tspan> - <tspan x="10px" y="424px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> let _ = match true {</tspan> + <tspan x="10px" y="424px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold"> _________________-</tspan> </tspan> - <tspan x="10px" y="442px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">----------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">`match` arms have incompatible types</tspan> + <tspan x="10px" y="442px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan> </tspan> - <tspan x="10px" y="460px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> true => (</tspan> + <tspan x="10px" y="460px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> 1 // last line shown in multispan header</tspan> </tspan> - <tspan x="10px" y="478px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold"> _________________-</tspan> + <tspan x="10px" y="478px"><tspan class="fg-ansi256-012 bold">...</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan> </tspan> - <tspan x="10px" y="496px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan> + <tspan x="10px" y="496px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> ),</tspan> </tspan> - <tspan x="10px" y="514px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> 1 // last line shown in multispan header</tspan> + <tspan x="10px" y="514px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|_________-</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">this is found to be of type `{integer}`</tspan> </tspan> - <tspan x="10px" y="532px"><tspan class="fg-ansi256-012 bold">...</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan> + <tspan x="10px" y="532px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> false => "</tspan> </tspan> - <tspan x="10px" y="550px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan> + <tspan x="10px" y="550px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold"> __________________^</tspan> </tspan> - <tspan x="10px" y="568px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> ),</tspan> + <tspan x="10px" y="568px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan> </tspan> - <tspan x="10px" y="586px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|_________-</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">this is found to be of type `{integer}`</tspan> + <tspan x="10px" y="586px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan> </tspan> - <tspan x="10px" y="604px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> false => "</tspan> + <tspan x="10px" y="604px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> 1 last line shown in multispan</tspan> </tspan> - <tspan x="10px" y="622px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold"> __________________^</tspan> + <tspan x="10px" y="622px"><tspan class="fg-ansi256-012 bold">...</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan> </tspan> - <tspan x="10px" y="640px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan> + <tspan x="10px" y="640px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> ",</tspan> </tspan> - <tspan x="10px" y="658px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan> + <tspan x="10px" y="658px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|_________^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected integer, found `&str`</tspan> </tspan> - <tspan x="10px" y="676px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> 1 last line shown in multispan</tspan> + <tspan x="10px" y="676px"> </tspan> - <tspan x="10px" y="694px"><tspan class="fg-ansi256-012 bold">...</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan> + <tspan x="10px" y="694px"><tspan class="fg-ansi256-009 bold">error</tspan><tspan class="bold">: aborting due to 2 previous errors</tspan> </tspan> - <tspan x="10px" y="712px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan> + <tspan x="10px" y="712px"> </tspan> - <tspan x="10px" y="730px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> ",</tspan> + <tspan x="10px" y="730px"><tspan class="bold">For more information about this error, try `rustc --explain E0308`.</tspan> </tspan> - <tspan x="10px" y="748px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|_________^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected integer, found `&str`</tspan> -</tspan> - <tspan x="10px" y="766px"> -</tspan> - <tspan x="10px" y="784px"><tspan class="fg-ansi256-009 bold">error</tspan><tspan class="bold">: aborting due to 2 previous errors</tspan> -</tspan> - <tspan x="10px" y="802px"> -</tspan> - <tspan x="10px" y="820px"><tspan class="bold">For more information about this error, try `rustc --explain E0308`.</tspan> -</tspan> - <tspan x="10px" y="838px"> + <tspan x="10px" y="748px"> </tspan> </text> diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.unicode.svg b/tests/ui/codemap_tests/huge_multispan_highlight.unicode.svg index 4e1a8d14a28..36a33b74042 100644 --- a/tests/ui/codemap_tests/huge_multispan_highlight.unicode.svg +++ b/tests/ui/codemap_tests/huge_multispan_highlight.unicode.svg @@ -1,4 +1,4 @@ -<svg width="743px" height="848px" xmlns="http://www.w3.org/2000/svg"> +<svg width="743px" height="758px" xmlns="http://www.w3.org/2000/svg"> <style> .fg { fill: #AAAAAA } .bg { background: #000000 } @@ -33,83 +33,73 @@ </tspan> <tspan x="10px" y="136px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">┌─────────────────┘</tspan> </tspan> - <tspan x="10px" y="154px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> // last line shown in multispan header</tspan> + <tspan x="10px" y="154px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">‡</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan> </tspan> - <tspan x="10px" y="172px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">‡</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan> + <tspan x="10px" y="172px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> ),</tspan> </tspan> - <tspan x="10px" y="190px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan> + <tspan x="10px" y="190px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">└─────────┘</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">this is found to be of type `()`</tspan> </tspan> - <tspan x="10px" y="208px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> ),</tspan> + <tspan x="10px" y="208px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> false => "</tspan> </tspan> - <tspan x="10px" y="226px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">└─────────┘</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">this is found to be of type `()`</tspan> + <tspan x="10px" y="226px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┏━━━━━━━━━━━━━━━━━━┛</tspan> </tspan> - <tspan x="10px" y="244px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> false => "</tspan> + <tspan x="10px" y="244px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">‡</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan> </tspan> - <tspan x="10px" y="262px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┏━━━━━━━━━━━━━━━━━━┛</tspan> + <tspan x="10px" y="262px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan><tspan> ",</tspan> </tspan> - <tspan x="10px" y="280px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">‡</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan> + <tspan x="10px" y="280px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">╰╴</tspan><tspan class="fg-ansi256-009 bold">┗━━━━━━━━━┛</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected `()`, found `&str`</tspan> </tspan> - <tspan x="10px" y="298px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan> + <tspan x="10px" y="298px"> </tspan> - <tspan x="10px" y="316px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan><tspan> ",</tspan> + <tspan x="10px" y="316px"><tspan class="fg-ansi256-009 bold">error[E0308]</tspan><tspan class="bold">: `match` arms have incompatible types</tspan> </tspan> - <tspan x="10px" y="334px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">╰╴</tspan><tspan class="fg-ansi256-009 bold">┗━━━━━━━━━┛</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected `()`, found `&str`</tspan> + <tspan x="10px" y="334px"><tspan> </tspan><tspan class="fg-ansi256-012 bold"> ╭▸ </tspan><tspan>$DIR/huge_multispan_highlight.rs:216:18</tspan> </tspan> - <tspan x="10px" y="352px"> + <tspan x="10px" y="352px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan> </tspan> - <tspan x="10px" y="370px"><tspan class="fg-ansi256-009 bold">error[E0308]</tspan><tspan class="bold">: `match` arms have incompatible types</tspan> + <tspan x="10px" y="370px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> let _ = match true {</tspan> </tspan> - <tspan x="10px" y="388px"><tspan> </tspan><tspan class="fg-ansi256-012 bold"> ╭▸ </tspan><tspan>$DIR/huge_multispan_highlight.rs:216:18</tspan> + <tspan x="10px" y="388px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">──────────</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">`match` arms have incompatible types</tspan> </tspan> - <tspan x="10px" y="406px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan> + <tspan x="10px" y="406px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> true => (</tspan> </tspan> - <tspan x="10px" y="424px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> let _ = match true {</tspan> + <tspan x="10px" y="424px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">┌─────────────────┘</tspan> </tspan> - <tspan x="10px" y="442px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">──────────</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">`match` arms have incompatible types</tspan> + <tspan x="10px" y="442px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan> </tspan> - <tspan x="10px" y="460px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> true => (</tspan> + <tspan x="10px" y="460px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> 1 // last line shown in multispan header</tspan> </tspan> - <tspan x="10px" y="478px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">┌─────────────────┘</tspan> + <tspan x="10px" y="478px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">‡</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan> </tspan> - <tspan x="10px" y="496px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan> + <tspan x="10px" y="496px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> ),</tspan> </tspan> - <tspan x="10px" y="514px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> 1 // last line shown in multispan header</tspan> + <tspan x="10px" y="514px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">└─────────┘</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">this is found to be of type `{integer}`</tspan> </tspan> - <tspan x="10px" y="532px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">‡</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan> + <tspan x="10px" y="532px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> false => "</tspan> </tspan> - <tspan x="10px" y="550px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan> + <tspan x="10px" y="550px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┏━━━━━━━━━━━━━━━━━━┛</tspan> </tspan> - <tspan x="10px" y="568px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> ),</tspan> + <tspan x="10px" y="568px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan> </tspan> - <tspan x="10px" y="586px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">└─────────┘</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">this is found to be of type `{integer}`</tspan> + <tspan x="10px" y="586px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan> </tspan> - <tspan x="10px" y="604px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> false => "</tspan> + <tspan x="10px" y="604px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan><tspan> 1 last line shown in multispan</tspan> </tspan> - <tspan x="10px" y="622px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┏━━━━━━━━━━━━━━━━━━┛</tspan> + <tspan x="10px" y="622px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">‡</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan> </tspan> - <tspan x="10px" y="640px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan> + <tspan x="10px" y="640px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan><tspan> ",</tspan> </tspan> - <tspan x="10px" y="658px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan> + <tspan x="10px" y="658px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">╰╴</tspan><tspan class="fg-ansi256-009 bold">┗━━━━━━━━━┛</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected integer, found `&str`</tspan> </tspan> - <tspan x="10px" y="676px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan><tspan> 1 last line shown in multispan</tspan> + <tspan x="10px" y="676px"> </tspan> - <tspan x="10px" y="694px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">‡</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan> + <tspan x="10px" y="694px"><tspan class="fg-ansi256-009 bold">error</tspan><tspan class="bold">: aborting due to 2 previous errors</tspan> </tspan> - <tspan x="10px" y="712px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan> + <tspan x="10px" y="712px"> </tspan> - <tspan x="10px" y="730px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan><tspan> ",</tspan> + <tspan x="10px" y="730px"><tspan class="bold">For more information about this error, try `rustc --explain E0308`.</tspan> </tspan> - <tspan x="10px" y="748px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">╰╴</tspan><tspan class="fg-ansi256-009 bold">┗━━━━━━━━━┛</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected integer, found `&str`</tspan> -</tspan> - <tspan x="10px" y="766px"> -</tspan> - <tspan x="10px" y="784px"><tspan class="fg-ansi256-009 bold">error</tspan><tspan class="bold">: aborting due to 2 previous errors</tspan> -</tspan> - <tspan x="10px" y="802px"> -</tspan> - <tspan x="10px" y="820px"><tspan class="bold">For more information about this error, try `rustc --explain E0308`.</tspan> -</tspan> - <tspan x="10px" y="838px"> + <tspan x="10px" y="748px"> </tspan> </text> diff --git a/tests/ui/coercion/coerce-loop-issue-122561.stderr b/tests/ui/coercion/coerce-loop-issue-122561.stderr index 90e9f41c291..3af7e7cddb3 100644 --- a/tests/ui/coercion/coerce-loop-issue-122561.stderr +++ b/tests/ui/coercion/coerce-loop-issue-122561.stderr @@ -189,8 +189,7 @@ error[E0308]: mismatched types LL | fn while_never_type() -> ! { | - expected `!` because of return type LL | / while true { -LL | | -LL | | +... | LL | | } | |_____^ expected `!`, found `()` | diff --git a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.stderr b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.stderr index a3211b77623..58d42d82998 100644 --- a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.stderr +++ b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.stderr @@ -2,10 +2,7 @@ error: free constant item without body --> $DIR/const_arg_trivial_macro_expansion-2.rs:12:1 | LL | / const _: A< -LL | | -LL | | -LL | | { -LL | | y! { test.tou8 } +... | LL | | }, LL | | >; | | ^ help: provide a definition for the constant: `= <expr>;` diff --git a/tests/ui/const-generics/issues/issue-67945-2.full.stderr b/tests/ui/const-generics/issues/issue-67945-2.full.stderr index 837927d588c..1eca3261a4a 100644 --- a/tests/ui/const-generics/issues/issue-67945-2.full.stderr +++ b/tests/ui/const-generics/issues/issue-67945-2.full.stderr @@ -5,8 +5,7 @@ LL | A: [(); { | _____________^ LL | | LL | | let x: Option<Box<Self>> = None; -LL | | -LL | | 0 +... | LL | | }], | |_____^ blocks are not supported in generic constants | diff --git a/tests/ui/const-generics/issues/issue-71202.stderr b/tests/ui/const-generics/issues/issue-71202.stderr index a2d38221852..cc3603d1145 100644 --- a/tests/ui/const-generics/issues/issue-71202.stderr +++ b/tests/ui/const-generics/issues/issue-71202.stderr @@ -4,7 +4,6 @@ error: unconstrained generic constant LL | / const ITEM_IS_COPY: [(); 1 - { LL | | trait NotCopy { LL | | const VALUE: bool = false; -LL | | } ... | LL | | <IsCopy<T>>::VALUE LL | | } as usize] = []; diff --git a/tests/ui/const-generics/nested-type.min.stderr b/tests/ui/const-generics/nested-type.min.stderr index 8696be3faf3..cdc0b9807d9 100644 --- a/tests/ui/const-generics/nested-type.min.stderr +++ b/tests/ui/const-generics/nested-type.min.stderr @@ -25,7 +25,6 @@ LL | | struct Foo<const N: usize>; LL | | LL | | impl<const N: usize> Foo<N> { ... | -LL | | LL | | }]>; | |__^ | diff --git a/tests/ui/consts/const-eval/infinite_loop.eval_limit.stderr b/tests/ui/consts/const-eval/infinite_loop.eval_limit.stderr index d664ae88323..f326da8e26a 100644 --- a/tests/ui/consts/const-eval/infinite_loop.eval_limit.stderr +++ b/tests/ui/consts/const-eval/infinite_loop.eval_limit.stderr @@ -16,7 +16,6 @@ LL | let s = [(); { | __________________^ LL | | let mut n = 113383; // #20 in https://oeis.org/A006884 LL | | while n != 0 { -LL | | ... | LL | | n LL | | }]; diff --git a/tests/ui/consts/const-eval/infinite_loop.no_ice.stderr b/tests/ui/consts/const-eval/infinite_loop.no_ice.stderr index d664ae88323..f326da8e26a 100644 --- a/tests/ui/consts/const-eval/infinite_loop.no_ice.stderr +++ b/tests/ui/consts/const-eval/infinite_loop.no_ice.stderr @@ -16,7 +16,6 @@ LL | let s = [(); { | __________________^ LL | | let mut n = 113383; // #20 in https://oeis.org/A006884 LL | | while n != 0 { -LL | | ... | LL | | n LL | | }]; diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.allow.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.allow.stderr index 7f6625bcfcd..dddd79a4383 100644 --- a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.allow.stderr +++ b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.allow.stderr @@ -2,10 +2,7 @@ warning: constant evaluation is taking a long time --> $DIR/ctfe-simple-loop.rs:10:5 | LL | / while index < n { -LL | | -LL | | -LL | | -LL | | index = index + 1; +... | LL | | } | |_____^ the const evaluator is currently interpreting this expression | diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr index 657f0e5bcba..2bb9a8a98ec 100644 --- a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr +++ b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr @@ -2,10 +2,7 @@ warning: constant evaluation is taking a long time --> $DIR/ctfe-simple-loop.rs:10:5 | LL | / while index < n { -LL | | -LL | | -LL | | -LL | | index = index + 1; +... | LL | | } | |_____^ | @@ -26,10 +23,7 @@ warning: constant evaluation is taking a long time --> $DIR/ctfe-simple-loop.rs:10:5 | LL | / while index < n { -LL | | -LL | | -LL | | -LL | | index = index + 1; +... | LL | | } | |_____^ | @@ -45,10 +39,7 @@ warning: constant evaluation is taking a long time --> $DIR/ctfe-simple-loop.rs:10:5 | LL | / while index < n { -LL | | -LL | | -LL | | -LL | | index = index + 1; +... | LL | | } | |_____^ the const evaluator is currently interpreting this expression | diff --git a/tests/ui/consts/const-eval/stable-metric/evade-deduplication-issue-118612.stderr b/tests/ui/consts/const-eval/stable-metric/evade-deduplication-issue-118612.stderr index cb19c59b15b..f41d2ea3e62 100644 --- a/tests/ui/consts/const-eval/stable-metric/evade-deduplication-issue-118612.stderr +++ b/tests/ui/consts/const-eval/stable-metric/evade-deduplication-issue-118612.stderr @@ -2,11 +2,7 @@ warning: constant evaluation is taking a long time --> $DIR/evade-deduplication-issue-118612.rs:8:5 | LL | / loop { -LL | | -LL | | -LL | | ... | -LL | | } LL | | } | |_____^ the const evaluator is currently interpreting this expression | @@ -20,11 +16,7 @@ warning: constant evaluation is taking a long time --> $DIR/evade-deduplication-issue-118612.rs:8:5 | LL | / loop { -LL | | -LL | | -LL | | ... | -LL | | } LL | | } | |_____^ the const evaluator is currently interpreting this expression | @@ -38,11 +30,7 @@ warning: constant evaluation is taking a long time --> $DIR/evade-deduplication-issue-118612.rs:8:5 | LL | / loop { -LL | | -LL | | -LL | | ... | -LL | | } LL | | } | |_____^ the const evaluator is currently interpreting this expression | @@ -56,11 +44,7 @@ warning: constant evaluation is taking a long time --> $DIR/evade-deduplication-issue-118612.rs:8:5 | LL | / loop { -LL | | -LL | | -LL | | ... | -LL | | } LL | | } | |_____^ the const evaluator is currently interpreting this expression | @@ -74,11 +58,7 @@ warning: constant evaluation is taking a long time --> $DIR/evade-deduplication-issue-118612.rs:8:5 | LL | / loop { -LL | | -LL | | -LL | | ... | -LL | | } LL | | } | |_____^ the const evaluator is currently interpreting this expression | diff --git a/tests/ui/consts/issue-65348.rs b/tests/ui/consts/issue-65348.rs index 1443fcbe1c1..0d12da3926c 100644 --- a/tests/ui/consts/issue-65348.rs +++ b/tests/ui/consts/issue-65348.rs @@ -9,15 +9,17 @@ impl<T> Generic<T> { } pub const fn array<T>() -> &'static T { - #[allow(unconditional_panic)] + #[expect(unconditional_panic)] &Generic::<T>::ARRAY[0] } pub const fn newtype_array<T>() -> &'static T { + #[expect(unconditional_panic)] &Generic::<T>::NEWTYPE_ARRAY.0[0] } pub const fn array_field<T>() -> &'static T { + #[expect(unconditional_panic)] &(Generic::<T>::ARRAY_FIELD.0).1[0] } diff --git a/tests/ui/coroutine/drop-tracking-parent-expression.stderr b/tests/ui/coroutine/drop-tracking-parent-expression.stderr index 51fc20070bf..dc2f9768d23 100644 --- a/tests/ui/coroutine/drop-tracking-parent-expression.stderr +++ b/tests/ui/coroutine/drop-tracking-parent-expression.stderr @@ -7,7 +7,6 @@ LL | assert_send(g); LL | / type_combinations!( LL | | // OK LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though ... | LL | | }; LL | | ); @@ -26,7 +25,6 @@ LL | _ => yield, LL | / type_combinations!( LL | | // OK LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though ... | LL | | }; LL | | ); @@ -47,7 +45,6 @@ LL | assert_send(g); LL | / type_combinations!( LL | | // OK LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though ... | LL | | }; LL | | ); @@ -66,7 +63,6 @@ LL | _ => yield, LL | / type_combinations!( LL | | // OK LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though ... | LL | | }; LL | | ); @@ -87,7 +83,6 @@ LL | assert_send(g); LL | / type_combinations!( LL | | // OK LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though ... | LL | | }; LL | | ); @@ -106,7 +101,6 @@ LL | _ => yield, LL | / type_combinations!( LL | | // OK LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though ... | LL | | }; LL | | ); diff --git a/tests/ui/coroutine/issue-88653.stderr b/tests/ui/coroutine/issue-88653.stderr index ef0cc11dde8..772a7f8424a 100644 --- a/tests/ui/coroutine/issue-88653.stderr +++ b/tests/ui/coroutine/issue-88653.stderr @@ -12,8 +12,7 @@ LL | |bar| { LL | | LL | | LL | | if bar { -LL | | yield bar; -LL | | } +... | LL | | } | |_____- return type was inferred to be `{coroutine@$DIR/issue-88653.rs:15:5: 15:10}` here | diff --git a/tests/ui/coroutine/match-bindings.stderr b/tests/ui/coroutine/match-bindings.stderr index 5525bfed116..1318e6931f5 100644 --- a/tests/ui/coroutine/match-bindings.stderr +++ b/tests/ui/coroutine/match-bindings.stderr @@ -7,7 +7,6 @@ LL | | loop { LL | | if let true = true { LL | | match Enum::A(String::new()) { ... | -LL | | } LL | | }; | |_____^ | diff --git a/tests/ui/coroutine/parent-expression.stderr b/tests/ui/coroutine/parent-expression.stderr index 770ffda7a26..a9125772b5a 100644 --- a/tests/ui/coroutine/parent-expression.stderr +++ b/tests/ui/coroutine/parent-expression.stderr @@ -7,7 +7,6 @@ LL | assert_send(g); LL | / type_combinations!( LL | | // OK LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though ... | LL | | }; LL | | ); @@ -26,7 +25,6 @@ LL | _ => yield, LL | / type_combinations!( LL | | // OK LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though ... | LL | | }; LL | | ); @@ -47,7 +45,6 @@ LL | assert_send(g); LL | / type_combinations!( LL | | // OK LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though ... | LL | | }; LL | | ); @@ -66,7 +63,6 @@ LL | _ => yield, LL | / type_combinations!( LL | | // OK LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though ... | LL | | }; LL | | ); @@ -87,7 +83,6 @@ LL | assert_send(g); LL | / type_combinations!( LL | | // OK LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though ... | LL | | }; LL | | ); @@ -106,7 +101,6 @@ LL | _ => yield, LL | / type_combinations!( LL | | // OK LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; -LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though ... | LL | | }; LL | | ); diff --git a/tests/ui/coroutine/too-live-local-in-immovable-gen.stderr b/tests/ui/coroutine/too-live-local-in-immovable-gen.stderr index 48df5c5beac..4fad4036300 100644 --- a/tests/ui/coroutine/too-live-local-in-immovable-gen.stderr +++ b/tests/ui/coroutine/too-live-local-in-immovable-gen.stderr @@ -3,9 +3,6 @@ warning: unused coroutine that must be used | LL | #[coroutine] static move || { | ______________________^ -LL | | // Tests that the coroutine transformation finds out that `a` is not live -LL | | // during the yield expression. Type checking will also compute liveness -LL | | // and it should also find out that `a` is not live. ... | LL | | let _ = &a; LL | | }; diff --git a/tests/ui/coroutine/yield-in-initializer.stderr b/tests/ui/coroutine/yield-in-initializer.stderr index 1e22b787668..eff5a0fdccf 100644 --- a/tests/ui/coroutine/yield-in-initializer.stderr +++ b/tests/ui/coroutine/yield-in-initializer.stderr @@ -4,10 +4,7 @@ warning: unused coroutine that must be used LL | #[coroutine] static || { | __________________^ LL | | loop { -LL | | // Test that `opt` is not live across the yield, even when borrowed in a loop -LL | | // See https://github.com/rust-lang/rust/issues/52792 ... | -LL | | } LL | | }; | |_____^ | diff --git a/tests/ui/coverage-attr/name-value.stderr b/tests/ui/coverage-attr/name-value.stderr index 986467dda69..38101764d6f 100644 --- a/tests/ui/coverage-attr/name-value.stderr +++ b/tests/ui/coverage-attr/name-value.stderr @@ -171,8 +171,6 @@ LL | #[coverage = "off"] ... LL | / trait MyTrait { LL | | #[coverage = "off"] -LL | | -LL | | ... | LL | | type T; LL | | } diff --git a/tests/ui/coverage-attr/word-only.stderr b/tests/ui/coverage-attr/word-only.stderr index 1ce149724c6..154ea61f3a3 100644 --- a/tests/ui/coverage-attr/word-only.stderr +++ b/tests/ui/coverage-attr/word-only.stderr @@ -171,8 +171,6 @@ LL | #[coverage] ... LL | / trait MyTrait { LL | | #[coverage] -LL | | -LL | | ... | LL | | type T; LL | | } diff --git a/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs b/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs new file mode 100644 index 00000000000..40b9e6536f5 --- /dev/null +++ b/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs @@ -0,0 +1,27 @@ +// ignore-tidy-linelength +//! Check that `-A warnings` cli flag applies to non-lint warnings as well. +//! +//! This test tries to exercise that by checking that the "relaxing a default bound only does +//! something for `?Sized`; all other traits are not bound by default" non-lint warning (normally +//! warn-by-default) is suppressed if the `-A warnings` cli flag is passed. +//! +//! Take special note that `warnings` is a special pseudo lint group in relationship to non-lint +//! warnings, which is somewhat special. This test does not exercise other `-A <other_lint_group>` +//! that check that they are working in the same way, only `warnings` specifically. +//! +//! # Relevant context +//! +//! - Original impl PR: <https://github.com/rust-lang/rust/pull/21248>. +//! - RFC 507 "Release channels": +//! <https://github.com/rust-lang/rfcs/blob/c017755b9bfa0421570d92ba38082302e0f3ad4f/text/0507-release-channels.md>. +#![crate_type = "lib"] + +//@ revisions: without_flag with_flag + +//@[with_flag] compile-flags: -Awarnings + +//@ check-pass + +pub trait Trait {} +pub fn f<T: ?Trait>() {} +//[without_flag]~^ WARN relaxing a default bound only does something for `?Sized`; all other traits are not bound by default diff --git a/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr b/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr new file mode 100644 index 00000000000..b037847c70f --- /dev/null +++ b/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr @@ -0,0 +1,8 @@ +warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default + --> $DIR/allow-non-lint-warnings.rs:26:13 + | +LL | pub fn f<T: ?Trait>() {} + | ^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/diagnostic-width/E0271.ascii.stderr b/tests/ui/diagnostic-width/E0271.ascii.stderr index e276299e9e8..7446b1a543e 100644 --- a/tests/ui/diagnostic-width/E0271.ascii.stderr +++ b/tests/ui/diagnostic-width/E0271.ascii.stderr @@ -6,7 +6,6 @@ LL | | Ok::<_, ()>( LL | | Err::<(), _>( LL | | Ok::<_, ()>( ... | -LL | | ) LL | | ) | |_____^ type mismatch resolving `<Result<Result<(), Result<Result<(), ...>, ...>>, ...> as Future>::Error == Foo` | diff --git a/tests/ui/diagnostic-width/E0271.unicode.stderr b/tests/ui/diagnostic-width/E0271.unicode.stderr index 4a96ca36cd7..72df2a381a4 100644 --- a/tests/ui/diagnostic-width/E0271.unicode.stderr +++ b/tests/ui/diagnostic-width/E0271.unicode.stderr @@ -6,7 +6,6 @@ LL │ ┃ Ok::<_, ()>( LL │ ┃ Err::<(), _>( LL │ ┃ Ok::<_, ()>( ‡ ┃ -LL │ ┃ ) LL │ ┃ ) │ ┗━━━━━┛ type mismatch resolving `<Result<Result<(), Result<Result<(), ...>, ...>>, ...> as Future>::Error == Foo` ╰╴ diff --git a/tests/ui/drop/lint-tail-expr-drop-order.stderr b/tests/ui/drop/lint-tail-expr-drop-order.stderr index f0da24605e6..a3084f660e4 100644 --- a/tests/ui/drop/lint-tail-expr-drop-order.stderr +++ b/tests/ui/drop/lint-tail-expr-drop-order.stderr @@ -22,22 +22,14 @@ note: `#1` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:11:1 | LL | / impl Drop for LoudDropper { -LL | | -LL | | -LL | | ... | -LL | | } LL | | } | |_^ note: `x` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:11:1 | LL | / impl Drop for LoudDropper { -LL | | -LL | | -LL | | ... | -LL | | } LL | | } | |_^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages @@ -71,22 +63,14 @@ note: `#1` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:11:1 | LL | / impl Drop for LoudDropper { -LL | | -LL | | -LL | | ... | -LL | | } LL | | } | |_^ note: `x` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:11:1 | LL | / impl Drop for LoudDropper { -LL | | -LL | | -LL | | ... | -LL | | } LL | | } | |_^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages @@ -115,22 +99,14 @@ note: `#1` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:11:1 | LL | / impl Drop for LoudDropper { -LL | | -LL | | -LL | | ... | -LL | | } LL | | } | |_^ note: `x` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:11:1 | LL | / impl Drop for LoudDropper { -LL | | -LL | | -LL | | ... | -LL | | } LL | | } | |_^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages @@ -159,22 +135,14 @@ note: `#1` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:11:1 | LL | / impl Drop for LoudDropper { -LL | | -LL | | -LL | | ... | -LL | | } LL | | } | |_^ note: `future` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:11:1 | LL | / impl Drop for LoudDropper { -LL | | -LL | | -LL | | ... | -LL | | } LL | | } | |_^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages @@ -225,22 +193,14 @@ note: `#1` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:11:1 | LL | / impl Drop for LoudDropper { -LL | | -LL | | -LL | | ... | -LL | | } LL | | } | |_^ note: `x` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:11:1 | LL | / impl Drop for LoudDropper { -LL | | -LL | | -LL | | ... | -LL | | } LL | | } | |_^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages @@ -311,22 +271,14 @@ note: `#1` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:11:1 | LL | / impl Drop for LoudDropper { -LL | | -LL | | -LL | | ... | -LL | | } LL | | } | |_^ note: `_x` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:11:1 | LL | / impl Drop for LoudDropper { -LL | | -LL | | -LL | | ... | -LL | | } LL | | } | |_^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds.rs b/tests/ui/dyn-compatibility/assoc_type_bounds.rs index 8634ba626a1..6e2076a4822 100644 --- a/tests/ui/dyn-compatibility/assoc_type_bounds.rs +++ b/tests/ui/dyn-compatibility/assoc_type_bounds.rs @@ -7,7 +7,7 @@ trait Foo<T> { trait Cake {} impl Cake for () {} -fn foo(_: &dyn Foo<()>) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified -fn bar(_: &dyn Foo<i32>) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified +fn foo(_: &dyn Foo<()>) {} //~ ERROR: the value of the associated type `Bar` in `Foo<()>` must be specified +fn bar(_: &dyn Foo<i32>) {} //~ ERROR: the value of the associated type `Bar` in `Foo<i32>` must be specified fn main() {} diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds.stderr index 3d5482625af..21ba9030117 100644 --- a/tests/ui/dyn-compatibility/assoc_type_bounds.stderr +++ b/tests/ui/dyn-compatibility/assoc_type_bounds.stderr @@ -1,4 +1,4 @@ -error[E0191]: the value of the associated type `Bar` in `Foo` must be specified +error[E0191]: the value of the associated type `Bar` in `Foo<()>` must be specified --> $DIR/assoc_type_bounds.rs:10:16 | LL | type Bar @@ -7,7 +7,7 @@ LL | type Bar LL | fn foo(_: &dyn Foo<()>) {} | ^^^^^^^ help: specify the associated type: `Foo<(), Bar = Type>` -error[E0191]: the value of the associated type `Bar` in `Foo` must be specified +error[E0191]: the value of the associated type `Bar` in `Foo<i32>` must be specified --> $DIR/assoc_type_bounds.rs:11:16 | LL | type Bar diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds2.rs b/tests/ui/dyn-compatibility/assoc_type_bounds2.rs index f7dc2fb8839..2b35016d774 100644 --- a/tests/ui/dyn-compatibility/assoc_type_bounds2.rs +++ b/tests/ui/dyn-compatibility/assoc_type_bounds2.rs @@ -7,7 +7,7 @@ trait Foo<T> { trait Cake {} impl Cake for () {} -fn foo(_: &dyn Foo<()>) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified -fn bar(_: &dyn Foo<i32>) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified +fn foo(_: &dyn Foo<()>) {} //~ ERROR: the value of the associated type `Bar` in `Foo<()>` must be specified +fn bar(_: &dyn Foo<i32>) {} //~ ERROR: the value of the associated type `Bar` in `Foo<i32>` must be specified fn main() {} diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds2.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds2.stderr index 815747436bf..5c4163b1969 100644 --- a/tests/ui/dyn-compatibility/assoc_type_bounds2.stderr +++ b/tests/ui/dyn-compatibility/assoc_type_bounds2.stderr @@ -1,4 +1,4 @@ -error[E0191]: the value of the associated type `Bar` in `Foo` must be specified +error[E0191]: the value of the associated type `Bar` in `Foo<()>` must be specified --> $DIR/assoc_type_bounds2.rs:10:16 | LL | type Bar @@ -7,7 +7,7 @@ LL | type Bar LL | fn foo(_: &dyn Foo<()>) {} | ^^^^^^^ help: specify the associated type: `Foo<(), Bar = Type>` -error[E0191]: the value of the associated type `Bar` in `Foo` must be specified +error[E0191]: the value of the associated type `Bar` in `Foo<i32>` must be specified --> $DIR/assoc_type_bounds2.rs:11:16 | LL | type Bar diff --git a/tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.rs b/tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.rs new file mode 100644 index 00000000000..1f4e1bf653a --- /dev/null +++ b/tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.rs @@ -0,0 +1,15 @@ +trait Sup<T> { + type Assoc: Default; +} + +impl<T: Default> Sup<T> for () { + type Assoc = T; +} +impl<T: Default, U: Default> Dyn<T, U> for () {} + +trait Dyn<A, B>: Sup<A, Assoc = A> + Sup<B> {} + +fn main() { + let q: <dyn Dyn<i32, u32> as Sup<u32>>::Assoc = Default::default(); + //~^ ERROR the value of the associated type `Assoc` in `Sup<u32>` must be specified +} diff --git a/tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.stderr b/tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.stderr new file mode 100644 index 00000000000..3d89b52d522 --- /dev/null +++ b/tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.stderr @@ -0,0 +1,12 @@ +error[E0191]: the value of the associated type `Assoc` in `Sup<u32>` must be specified + --> $DIR/require-assoc-for-all-super-substs.rs:13:17 + | +LL | type Assoc: Default; + | ------------------- `Assoc` defined here +... +LL | let q: <dyn Dyn<i32, u32> as Sup<u32>>::Assoc = Default::default(); + | ^^^^^^^^^^^^^ help: specify the associated type: `Dyn<i32, u32, Assoc = Type>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr b/tests/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr index 08eb8cfac49..54bde98b57f 100644 --- a/tests/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr +++ b/tests/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr @@ -3,8 +3,7 @@ warning: anonymous parameters are deprecated and will be removed in the next edi | LL | fn test(x: u32, ( | _____________________^ -LL | | -LL | | +... | LL | | )) {} | |_____^ | diff --git a/tests/ui/expr/if/if-let-arm-types.stderr b/tests/ui/expr/if/if-let-arm-types.stderr index 285f5c4a6f2..0a8260f0fea 100644 --- a/tests/ui/expr/if/if-let-arm-types.stderr +++ b/tests/ui/expr/if/if-let-arm-types.stderr @@ -5,8 +5,7 @@ LL | / if let Some(b) = None { LL | | LL | | () | | -- expected because of this -LL | | -LL | | } else { +... | LL | | 1 | | ^ expected `()`, found integer LL | | }; diff --git a/tests/ui/extern/issue-116203.stderr b/tests/ui/extern/issue-116203.stderr index 86e4cc763bd..51ef1421e3e 100644 --- a/tests/ui/extern/issue-116203.stderr +++ b/tests/ui/extern/issue-116203.stderr @@ -22,8 +22,7 @@ LL | extern "C" { LL | / thread_local! { LL | | static FOO: u32 = 0; | | ^^^ cannot have a body -LL | | -LL | | +... | LL | | } | |_____- the invalid body | diff --git a/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.default.stderr index 0c5b8a4d3b6..d0a25e28a76 100644 --- a/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr +++ b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.default.stderr @@ -1,5 +1,5 @@ error[E0658]: `*const Bar` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature - --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:8:18 + --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:11:18 | LL | fn foo(self: *const Self) {} | ^^^^^^^^^^^ @@ -10,7 +10,7 @@ LL | fn foo(self: *const Self) {} = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` error[E0658]: `*mut Bar` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature - --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:12:18 + --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:15:18 | LL | fn bar(self: *mut Self) {} | ^^^^^^^^^ @@ -21,7 +21,7 @@ LL | fn bar(self: *mut Self) {} = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature - --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:2:18 + --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:5:18 | LL | fn foo(self: *const Self); | ^^^^^^^^^^^ diff --git a/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.feature.stderr b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.feature.stderr new file mode 100644 index 00000000000..d0a25e28a76 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.feature.stderr @@ -0,0 +1,36 @@ +error[E0658]: `*const Bar` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature + --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:11:18 + | +LL | fn foo(self: *const Self) {} + | ^^^^^^^^^^^ + | + = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information + = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` + +error[E0658]: `*mut Bar` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature + --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:15:18 + | +LL | fn bar(self: *mut Self) {} + | ^^^^^^^^^ + | + = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information + = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` + +error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature + --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:5:18 + | +LL | fn foo(self: *const Self); + | ^^^^^^^^^^^ + | + = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information + = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.rs b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.rs index 79ceb05662b..7ea1b875f79 100644 --- a/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.rs +++ b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.rs @@ -1,3 +1,6 @@ +//@ revisions: default feature +#![cfg_attr(feature, feature(arbitrary_self_types))] + trait Foo { fn foo(self: *const Self); //~ ERROR `*const Self` cannot be used as the type of `self` } diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr index eb9e51a04c3..2150effc3b7 100644 --- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr +++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr @@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Cell<&Self>` LL | fn cell(self: Cell<&Self>); | ^^^^^^^^^^^ | - = note: type of `self` must be `Self` or some type implementing `Receiver` - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) error: aborting due to 1 previous error diff --git a/tests/ui/feature-gates/feature-gate-impl-trait-in-bindings.rs b/tests/ui/feature-gates/feature-gate-impl-trait-in-bindings.rs new file mode 100644 index 00000000000..f6574b48120 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-impl-trait-in-bindings.rs @@ -0,0 +1,4 @@ +fn main() { + let x: impl Sized = (); + //~^ ERROR `impl Trait` is not allowed in the type of variable bindings +} diff --git a/tests/ui/feature-gates/feature-gate-impl-trait-in-bindings.stderr b/tests/ui/feature-gates/feature-gate-impl-trait-in-bindings.stderr new file mode 100644 index 00000000000..58f058fb564 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-impl-trait-in-bindings.stderr @@ -0,0 +1,14 @@ +error[E0562]: `impl Trait` is not allowed in the type of variable bindings + --> $DIR/feature-gate-impl-trait-in-bindings.rs:2:12 + | +LL | let x: impl Sized = (); + | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods + = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information + = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/feature-gates/feature-gate-unsafe-binders.rs b/tests/ui/feature-gates/feature-gate-unsafe-binders.rs new file mode 100644 index 00000000000..a2997ced4fa --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unsafe-binders.rs @@ -0,0 +1,7 @@ +#[cfg(any())] +fn test() { + let x: unsafe<> (); + //~^ ERROR unsafe binder types are experimental +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-unsafe-binders.stderr b/tests/ui/feature-gates/feature-gate-unsafe-binders.stderr new file mode 100644 index 00000000000..93997d6c14a --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unsafe-binders.stderr @@ -0,0 +1,13 @@ +error[E0658]: unsafe binder types are experimental + --> $DIR/feature-gate-unsafe-binders.rs:3:12 + | +LL | let x: unsafe<> (); + | ^^^^^^^^^^^ + | + = note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information + = help: add `#![feature(unsafe_binders)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr index fe764ff4925..db8c5295a2d 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr @@ -54,11 +54,7 @@ LL | #[inline] | ^^^^^^^^^ LL | LL | / mod inline { -LL | | -LL | | -LL | | ... | -LL | | LL | | } | |_- not a function or closure @@ -73,7 +69,6 @@ LL | | LL | | LL | | mod inner { #![no_link] } ... | -LL | | LL | | } | |_- not an `extern crate` item @@ -88,7 +83,6 @@ LL | | LL | | LL | | mod inner { #![export_name="2200"] } ... | -LL | | } LL | | } | |_- not a free function, impl method or static @@ -101,9 +95,7 @@ LL | LL | / mod repr { LL | | LL | | mod inner { #![repr(C)] } -LL | | ... | -LL | | LL | | } | |_- not a struct, enum, or union @@ -116,9 +108,7 @@ LL | LL | / mod repr_rust { LL | | LL | | mod inner { #![repr(Rust)] } -LL | | ... | -LL | | LL | | } | |_- not a struct, enum, or union diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr index e43cef7c150..18fb75aafbb 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -227,9 +227,7 @@ LL | #[no_mangle] LL | / mod no_mangle { LL | | LL | | mod inner { #![no_mangle] } -LL | | ... | -LL | | } LL | | } | |_- not a free function, impl method or static | @@ -270,7 +268,6 @@ LL | | LL | | LL | | mod inner { #![cold] } ... | -LL | | LL | | } | |_- not a function definition | @@ -287,7 +284,6 @@ LL | | LL | | LL | | #[link_name = "1900"] ... | -LL | | LL | | } | |_- not a foreign function or static | @@ -304,7 +300,6 @@ LL | | LL | | LL | | mod inner { #![link_section="1800"] } ... | -LL | | LL | | } | |_- not a function or static | @@ -321,7 +316,6 @@ LL | | LL | | LL | | mod inner { #![link()] } ... | -LL | | LL | | } | |_- not an `extern` block | diff --git a/tests/ui/feature-gates/issue-43106-gating-of-derive.stderr b/tests/ui/feature-gates/issue-43106-gating-of-derive.stderr index 4dee7a00544..5df3e9e73fe 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-derive.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-derive.stderr @@ -6,8 +6,6 @@ LL | #[derive(Debug)] LL | LL | / mod derive { LL | | mod inner { #![derive(Debug)] } -LL | | -LL | | ... | LL | | impl S { } LL | | } diff --git a/tests/ui/for/for-else-err.stderr b/tests/ui/for/for-else-err.stderr index bd49dc47244..a872cde5cac 100644 --- a/tests/ui/for/for-else-err.stderr +++ b/tests/ui/for/for-else-err.stderr @@ -6,8 +6,7 @@ LL | for _ in 0..1 { LL | LL | } else { | _______^ -LL | | -LL | | +... | LL | | } | |_____^ | diff --git a/tests/ui/for/for-else-let-else-err.stderr b/tests/ui/for/for-else-let-else-err.stderr index bb6558739ba..22432a18bbb 100644 --- a/tests/ui/for/for-else-let-else-err.stderr +++ b/tests/ui/for/for-else-let-else-err.stderr @@ -6,8 +6,7 @@ LL | let _ = for _ in 0..1 { LL | LL | } else { | _______^ -LL | | -LL | | +... | LL | | }; | |_____^ | diff --git a/tests/ui/generic-associated-types/collectivity-regression.stderr b/tests/ui/generic-associated-types/collectivity-regression.stderr index 0c395a1664f..1c081ac644a 100644 --- a/tests/ui/generic-associated-types/collectivity-regression.stderr +++ b/tests/ui/generic-associated-types/collectivity-regression.stderr @@ -2,10 +2,7 @@ error: `T` does not live long enough --> $DIR/collectivity-regression.rs:13:5 | LL | / || { -LL | | -LL | | // -LL | | // FIXME(#98437). This regressed at some point and -LL | | // probably should work. +... | LL | | let _x = x; LL | | }; | |_____^ diff --git a/tests/ui/generics/overlapping-errors-span-issue-123861.rs b/tests/ui/generics/overlapping-errors-span-issue-123861.rs new file mode 100644 index 00000000000..e0a27f68748 --- /dev/null +++ b/tests/ui/generics/overlapping-errors-span-issue-123861.rs @@ -0,0 +1,8 @@ +fn mainIterator<_ = _> {} +//~^ ERROR expected identifier, found reserved identifier `_` +//~| ERROR missing parameters for function definition +//~| ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions [invalid_type_param_default] +//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +//~| ERROR the placeholder `_` is not allowed within types on item signatures for functions [E0121] + +fn main() {} diff --git a/tests/ui/generics/overlapping-errors-span-issue-123861.stderr b/tests/ui/generics/overlapping-errors-span-issue-123861.stderr new file mode 100644 index 00000000000..e0a49343b0e --- /dev/null +++ b/tests/ui/generics/overlapping-errors-span-issue-123861.stderr @@ -0,0 +1,52 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/overlapping-errors-span-issue-123861.rs:1:17 + | +LL | fn mainIterator<_ = _> {} + | ^ expected identifier, found reserved identifier + +error: missing parameters for function definition + --> $DIR/overlapping-errors-span-issue-123861.rs:1:23 + | +LL | fn mainIterator<_ = _> {} + | ^ + | +help: add a parameter list + | +LL | fn mainIterator<_ = _>() {} + | ++ + +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/overlapping-errors-span-issue-123861.rs:1:17 + | +LL | fn mainIterator<_ = _> {} + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887> + = note: `#[deny(invalid_type_param_default)]` on by default + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/overlapping-errors-span-issue-123861.rs:1:21 + | +LL | fn mainIterator<_ = _> {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn mainIterator<T = T> {} + | ~ ~ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0121`. +Future incompatibility report: Future breakage diagnostic: +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/overlapping-errors-span-issue-123861.rs:1:17 + | +LL | fn mainIterator<_ = _> {} + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887> + = note: `#[deny(invalid_type_param_default)]` on by default + diff --git a/tests/ui/anonymous-higher-ranked-lifetime.rs b/tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.rs index 898fe22fa23..8d8d0e71067 100644 --- a/tests/ui/anonymous-higher-ranked-lifetime.rs +++ b/tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.rs @@ -1,3 +1,9 @@ +//! Diagnostics test to check that higher-ranked lifetimes are properly named when being pretty +//! printed in diagnostics. +//! +//! Issue: <https://github.com/rust-lang/rust/issues/44887> +//! PR: <https://github.com/rust-lang/rust/pull/44888> + fn main() { f1(|_: (), _: ()| {}); //~ ERROR type mismatch f2(|_: (), _: ()| {}); //~ ERROR type mismatch diff --git a/tests/ui/anonymous-higher-ranked-lifetime.stderr b/tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.stderr index c28d856ad55..7e0cdba6ff2 100644 --- a/tests/ui/anonymous-higher-ranked-lifetime.stderr +++ b/tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.stderr @@ -1,5 +1,5 @@ error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:2:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5 | LL | f1(|_: (), _: ()| {}); | ^^^--------------^^^^ @@ -10,7 +10,7 @@ LL | f1(|_: (), _: ()| {}); = note: expected closure signature `for<'a, 'b> fn(&'a (), &'b ()) -> _` found closure signature `fn((), ()) -> _` note: required by a bound in `f1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:16:25 + --> $DIR/anonymous-higher-ranked-lifetime.rs:22:25 | LL | fn f1<F>(_: F) where F: Fn(&(), &()) {} | ^^^^^^^^^^^^ required by this bound in `f1` @@ -20,7 +20,7 @@ LL | f1(|_: &(), _: &()| {}); | + + error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:3:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:9:5 | LL | f2(|_: (), _: ()| {}); | ^^^--------------^^^^ @@ -31,7 +31,7 @@ LL | f2(|_: (), _: ()| {}); = note: expected closure signature `for<'a, 'b> fn(&'a (), &'b ()) -> _` found closure signature `fn((), ()) -> _` note: required by a bound in `f2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:17:25 + --> $DIR/anonymous-higher-ranked-lifetime.rs:23:25 | LL | fn f2<F>(_: F) where F: for<'a> Fn(&'a (), &()) {} | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f2` @@ -41,7 +41,7 @@ LL | f2(|_: &(), _: &()| {}); | + + error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5 | LL | f3(|_: (), _: ()| {}); | ^^^--------------^^^^ @@ -52,7 +52,7 @@ LL | f3(|_: (), _: ()| {}); = note: expected closure signature `for<'a> fn(&(), &'a ()) -> _` found closure signature `fn((), ()) -> _` note: required by a bound in `f3` - --> $DIR/anonymous-higher-ranked-lifetime.rs:18:29 + --> $DIR/anonymous-higher-ranked-lifetime.rs:24:29 | LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {} | ^^^^^^^^^^^^^^^ required by this bound in `f3` @@ -62,7 +62,7 @@ LL | f3(|_: &(), _: &()| {}); | + + error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:5:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:11:5 | LL | f4(|_: (), _: ()| {}); | ^^^--------------^^^^ @@ -73,7 +73,7 @@ LL | f4(|_: (), _: ()| {}); = note: expected closure signature `for<'a, 'r> fn(&'a (), &'r ()) -> _` found closure signature `fn((), ()) -> _` note: required by a bound in `f4` - --> $DIR/anonymous-higher-ranked-lifetime.rs:19:25 + --> $DIR/anonymous-higher-ranked-lifetime.rs:25:25 | LL | fn f4<F>(_: F) where F: for<'r> Fn(&(), &'r ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f4` @@ -83,7 +83,7 @@ LL | f4(|_: &(), _: &()| {}); | + + error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5 | LL | f5(|_: (), _: ()| {}); | ^^^--------------^^^^ @@ -94,7 +94,7 @@ LL | f5(|_: (), _: ()| {}); = note: expected closure signature `for<'r> fn(&'r (), &'r ()) -> _` found closure signature `fn((), ()) -> _` note: required by a bound in `f5` - --> $DIR/anonymous-higher-ranked-lifetime.rs:20:25 + --> $DIR/anonymous-higher-ranked-lifetime.rs:26:25 | LL | fn f5<F>(_: F) where F: for<'r> Fn(&'r (), &'r ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f5` @@ -104,7 +104,7 @@ LL | f5(|_: &(), _: &()| {}); | + + error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:7:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:13:5 | LL | g1(|_: (), _: ()| {}); | ^^^--------------^^^^ @@ -115,7 +115,7 @@ LL | g1(|_: (), _: ()| {}); = note: expected closure signature `for<'a> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _` found closure signature `fn((), ()) -> _` note: required by a bound in `g1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:23:25 + --> $DIR/anonymous-higher-ranked-lifetime.rs:29:25 | LL | fn g1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g1` @@ -125,7 +125,7 @@ LL | g1(|_: &(), _: ()| {}); | + error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:14:5 | LL | g2(|_: (), _: ()| {}); | ^^^--------------^^^^ @@ -136,7 +136,7 @@ LL | g2(|_: (), _: ()| {}); = note: expected closure signature `for<'a> fn(&'a (), for<'a> fn(&'a ())) -> _` found closure signature `fn((), ()) -> _` note: required by a bound in `g2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:24:25 + --> $DIR/anonymous-higher-ranked-lifetime.rs:30:25 | LL | fn g2<F>(_: F) where F: Fn(&(), fn(&())) {} | ^^^^^^^^^^^^^^^^ required by this bound in `g2` @@ -146,7 +146,7 @@ LL | g2(|_: &(), _: ()| {}); | + error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:9:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:15:5 | LL | g3(|_: (), _: ()| {}); | ^^^--------------^^^^ @@ -157,7 +157,7 @@ LL | g3(|_: (), _: ()| {}); = note: expected closure signature `for<'s> fn(&'s (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _` found closure signature `fn((), ()) -> _` note: required by a bound in `g3` - --> $DIR/anonymous-higher-ranked-lifetime.rs:25:25 + --> $DIR/anonymous-higher-ranked-lifetime.rs:31:25 | LL | fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<dyn Fn(&())>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g3` @@ -167,7 +167,7 @@ LL | g3(|_: &(), _: ()| {}); | + error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:16:5 | LL | g4(|_: (), _: ()| {}); | ^^^--------------^^^^ @@ -178,7 +178,7 @@ LL | g4(|_: (), _: ()| {}); = note: expected closure signature `for<'a> fn(&'a (), for<'r> fn(&'r ())) -> _` found closure signature `fn((), ()) -> _` note: required by a bound in `g4` - --> $DIR/anonymous-higher-ranked-lifetime.rs:26:25 + --> $DIR/anonymous-higher-ranked-lifetime.rs:32:25 | LL | fn g4<F>(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g4` @@ -188,7 +188,7 @@ LL | g4(|_: &(), _: ()| {}); | + error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:11:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:17:5 | LL | h1(|_: (), _: (), _: (), _: ()| {}); | ^^^----------------------------^^^^ @@ -199,7 +199,7 @@ LL | h1(|_: (), _: (), _: (), _: ()| {}); = note: expected closure signature `for<'a, 'b> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>, &'b (), for<'a, 'b> fn(&'a (), &'b ())) -> _` found closure signature `fn((), (), (), ()) -> _` note: required by a bound in `h1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:29:25 + --> $DIR/anonymous-higher-ranked-lifetime.rs:35:25 | LL | fn h1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>, &(), fn(&(), &())) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h1` @@ -209,7 +209,7 @@ LL | h1(|_: &(), _: (), _: &(), _: ()| {}); | + + error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:18:5 | LL | h2(|_: (), _: (), _: (), _: ()| {}); | ^^^----------------------------^^^^ @@ -220,7 +220,7 @@ LL | h2(|_: (), _: (), _: (), _: ()| {}); = note: expected closure signature `for<'a, 't0> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>, &'t0 (), for<'a, 'b> fn(&'a (), &'b ())) -> _` found closure signature `fn((), (), (), ()) -> _` note: required by a bound in `h2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:30:25 + --> $DIR/anonymous-higher-ranked-lifetime.rs:36:25 | LL | fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<dyn Fn(&())>, &'t0 (), fn(&(), &())) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h2` diff --git a/tests/ui/impl-trait/in-bindings/bad-nesting.rs b/tests/ui/impl-trait/in-bindings/bad-nesting.rs new file mode 100644 index 00000000000..7f4b44cc691 --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/bad-nesting.rs @@ -0,0 +1,10 @@ +#![feature(impl_trait_in_bindings)] + +trait Foo<T> {} + +impl Foo<()> for () {} + +fn main() { + let x: impl Foo<impl Sized> = (); + //~^ ERROR nested `impl Trait` is not allowed +} diff --git a/tests/ui/impl-trait/in-bindings/bad-nesting.stderr b/tests/ui/impl-trait/in-bindings/bad-nesting.stderr new file mode 100644 index 00000000000..d82ce733254 --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/bad-nesting.stderr @@ -0,0 +1,12 @@ +error[E0666]: nested `impl Trait` is not allowed + --> $DIR/bad-nesting.rs:8:21 + | +LL | let x: impl Foo<impl Sized> = (); + | ---------^^^^^^^^^^- + | | | + | | nested `impl Trait` here + | outer `impl Trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0666`. diff --git a/tests/ui/impl-trait/in-bindings/escaping-bound-var.rs b/tests/ui/impl-trait/in-bindings/escaping-bound-var.rs new file mode 100644 index 00000000000..b57fef9be21 --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/escaping-bound-var.rs @@ -0,0 +1,14 @@ +#![feature(impl_trait_in_bindings)] + +trait Foo<'a> { + type Out; +} + +impl<'a> Foo<'a> for () { + type Out = (); +} + +fn main() { + let x: &dyn for<'a> Foo<'a, Out = impl Sized + 'a> = &(); + //~^ ERROR cannot capture late-bound lifetime in `impl Trait` in binding +} diff --git a/tests/ui/impl-trait/in-bindings/escaping-bound-var.stderr b/tests/ui/impl-trait/in-bindings/escaping-bound-var.stderr new file mode 100644 index 00000000000..640f6f36927 --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/escaping-bound-var.stderr @@ -0,0 +1,8 @@ +error: cannot capture late-bound lifetime in `impl Trait` in binding + --> $DIR/escaping-bound-var.rs:12:52 + | +LL | let x: &dyn for<'a> Foo<'a, Out = impl Sized + 'a> = &(); + | -- lifetime defined here ^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/impl-trait/in-bindings/lifetime-failure.rs b/tests/ui/impl-trait/in-bindings/lifetime-failure.rs new file mode 100644 index 00000000000..df685c36c43 --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/lifetime-failure.rs @@ -0,0 +1,12 @@ +#![feature(impl_trait_in_bindings)] + +trait Static: 'static {} +impl<T: 'static> Static for T {} + +struct W<T>(T); + +fn main() { + let local = 0; + let _: W<impl Static> = W(&local); + //~^ ERROR `local` does not live long enough +} diff --git a/tests/ui/impl-trait/in-bindings/lifetime-failure.stderr b/tests/ui/impl-trait/in-bindings/lifetime-failure.stderr new file mode 100644 index 00000000000..189efcbca87 --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/lifetime-failure.stderr @@ -0,0 +1,16 @@ +error[E0597]: `local` does not live long enough + --> $DIR/lifetime-failure.rs:10:31 + | +LL | let local = 0; + | ----- binding `local` declared here +LL | let _: W<impl Static> = W(&local); + | -------------- ^^^^^^ borrowed value does not live long enough + | | + | type annotation requires that `local` is borrowed for `'static` +LL | +LL | } + | - `local` dropped here while still borrowed + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/impl-trait/in-bindings/nesting-lifetime-failure.rs b/tests/ui/impl-trait/in-bindings/nesting-lifetime-failure.rs new file mode 100644 index 00000000000..7e5d2cf18bd --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/nesting-lifetime-failure.rs @@ -0,0 +1,10 @@ +#![feature(impl_trait_in_bindings)] + +trait Static {} +impl<T: 'static> Static for T {} + +fn main() { + let local = 0; + let _: impl IntoIterator<Item = impl Static> = [&local]; + //~^ ERROR `local` does not live long enough +} diff --git a/tests/ui/impl-trait/in-bindings/nesting-lifetime-failure.stderr b/tests/ui/impl-trait/in-bindings/nesting-lifetime-failure.stderr new file mode 100644 index 00000000000..c0326b37949 --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/nesting-lifetime-failure.stderr @@ -0,0 +1,16 @@ +error[E0597]: `local` does not live long enough + --> $DIR/nesting-lifetime-failure.rs:8:53 + | +LL | let local = 0; + | ----- binding `local` declared here +LL | let _: impl IntoIterator<Item = impl Static> = [&local]; + | ------------------------------------- ^^^^^^ borrowed value does not live long enough + | | + | type annotation requires that `local` is borrowed for `'static` +LL | +LL | } + | - `local` dropped here while still borrowed + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/impl-trait/in-bindings/nesting.rs b/tests/ui/impl-trait/in-bindings/nesting.rs new file mode 100644 index 00000000000..51ff42bcafe --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/nesting.rs @@ -0,0 +1,7 @@ +//@ check-pass + +#![feature(impl_trait_in_bindings)] + +fn main() { + let _: impl IntoIterator<Item = impl Sized> = ["hello", " world"]; +} diff --git a/tests/ui/impl-trait/in-bindings/simple.rs b/tests/ui/impl-trait/in-bindings/simple.rs new file mode 100644 index 00000000000..8052f5a1880 --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/simple.rs @@ -0,0 +1,10 @@ +//@ check-pass + +#![feature(impl_trait_in_bindings)] + +trait Foo {} +impl Foo for () {} + +fn main() { + let x: impl Foo = (); +} diff --git a/tests/ui/impl-trait/in-bindings/trait-failure.rs b/tests/ui/impl-trait/in-bindings/trait-failure.rs new file mode 100644 index 00000000000..e4052437f2f --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/trait-failure.rs @@ -0,0 +1,13 @@ +#![feature(impl_trait_in_bindings)] + +trait Foo {} + +struct W<T>(T); +impl<T> Foo for W<T> where T: Foo {} + +fn main() { + let x: impl Foo = W(()); + //~^ ERROR the trait bound `(): Foo` is not satisfied + let x: W<impl Foo> = W(()); + //~^ ERROR the trait bound `(): Foo` is not satisfied +} diff --git a/tests/ui/impl-trait/in-bindings/trait-failure.stderr b/tests/ui/impl-trait/in-bindings/trait-failure.stderr new file mode 100644 index 00000000000..332cefd796d --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/trait-failure.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/trait-failure.rs:9:17 + | +LL | let x: impl Foo = W(()); + | ^^^ the trait `Foo` is not implemented for `()` + | + = help: the trait `Foo` is implemented for `W<T>` +note: required for `W<()>` to implement `Foo` + --> $DIR/trait-failure.rs:6:9 + | +LL | impl<T> Foo for W<T> where T: Foo {} + | ^^^ ^^^^ --- unsatisfied trait bound introduced here + +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/trait-failure.rs:11:19 + | +LL | let x: W<impl Foo> = W(()); + | ^^^ the trait `Foo` is not implemented for `()` + | + = help: the trait `Foo` is implemented for `W<T>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr index 1ddbd75142f..e38e18857ef 100644 --- a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr +++ b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr @@ -2,9 +2,6 @@ error[E0277]: the trait bound `F: MyFn<i32>` is not satisfied --> $DIR/false-positive-predicate-entailment-error.rs:36:5 | LL | / fn autobatch<F>(self) -> impl Trait -LL | | -LL | | -LL | | ... | LL | | where LL | | F: Callback<Self::CallbackArg>, @@ -52,9 +49,6 @@ error[E0277]: the trait bound `F: MyFn<i32>` is not satisfied --> $DIR/false-positive-predicate-entailment-error.rs:36:5 | LL | / fn autobatch<F>(self) -> impl Trait -LL | | -LL | | -LL | | ... | LL | | where LL | | F: Callback<Self::CallbackArg>, @@ -105,9 +99,6 @@ error[E0277]: the trait bound `F: MyFn<i32>` is not satisfied --> $DIR/false-positive-predicate-entailment-error.rs:36:5 | LL | / fn autobatch<F>(self) -> impl Trait -LL | | -LL | | -LL | | ... | LL | | where LL | | F: Callback<Self::CallbackArg>, diff --git a/tests/ui/impl-trait/issues/issue-54600.stderr b/tests/ui/impl-trait/issues/issue-54600.stderr index c75c0fa0f05..02d60960233 100644 --- a/tests/ui/impl-trait/issues/issue-54600.stderr +++ b/tests/ui/impl-trait/issues/issue-54600.stderr @@ -5,6 +5,9 @@ LL | let x: Option<impl Debug> = Some(44_u32); | ^^^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods + = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information + = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-54840.stderr b/tests/ui/impl-trait/issues/issue-54840.stderr index de75256d5a9..805ea04f0bc 100644 --- a/tests/ui/impl-trait/issues/issue-54840.stderr +++ b/tests/ui/impl-trait/issues/issue-54840.stderr @@ -5,6 +5,9 @@ LL | let j: &impl Add = &i; | ^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods + = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information + = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-58504.stderr b/tests/ui/impl-trait/issues/issue-58504.stderr index 8231732bba1..bc921d5cd2c 100644 --- a/tests/ui/impl-trait/issues/issue-58504.stderr +++ b/tests/ui/impl-trait/issues/issue-58504.stderr @@ -5,6 +5,9 @@ LL | let gens: [impl Coroutine<Return=!, Yield=()>;2] = [ mk_gen(), mk_gen() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods + = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information + = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-58956.stderr b/tests/ui/impl-trait/issues/issue-58956.stderr index 0c81c69def3..825777e4923 100644 --- a/tests/ui/impl-trait/issues/issue-58956.stderr +++ b/tests/ui/impl-trait/issues/issue-58956.stderr @@ -13,6 +13,9 @@ LL | let x: Wrap<impl Lam> = Wrap(B); | ^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods + = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information + = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/issues/issue-70971.stderr b/tests/ui/impl-trait/issues/issue-70971.stderr index 28c463cea85..10e5fffa430 100644 --- a/tests/ui/impl-trait/issues/issue-70971.stderr +++ b/tests/ui/impl-trait/issues/issue-70971.stderr @@ -5,6 +5,9 @@ LL | let x : (impl Copy,) = (true,); | ^^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods + = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information + = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-79099.stderr b/tests/ui/impl-trait/issues/issue-79099.stderr index 96825eabec7..d7c0c494454 100644 --- a/tests/ui/impl-trait/issues/issue-79099.stderr +++ b/tests/ui/impl-trait/issues/issue-79099.stderr @@ -16,6 +16,9 @@ LL | let f: impl core::future::Future<Output = u8> = async { 1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods + = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information + = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/issues/issue-84919.stderr b/tests/ui/impl-trait/issues/issue-84919.stderr index 02d2ce28fb3..21dd355065d 100644 --- a/tests/ui/impl-trait/issues/issue-84919.stderr +++ b/tests/ui/impl-trait/issues/issue-84919.stderr @@ -5,6 +5,9 @@ LL | let _x: impl Trait = (); | ^^^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods + = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information + = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-87295.stderr b/tests/ui/impl-trait/issues/issue-87295.stderr index 78274a056ec..31f3b2f5bf2 100644 --- a/tests/ui/impl-trait/issues/issue-87295.stderr +++ b/tests/ui/impl-trait/issues/issue-87295.stderr @@ -5,6 +5,9 @@ LL | let _do_not_waste: Struct<impl Trait<Output = i32>> = Struct::new(()); | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods + = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information + = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/where-allowed.stderr b/tests/ui/impl-trait/where-allowed.stderr index 13f50fcea7b..400df87ca3f 100644 --- a/tests/ui/impl-trait/where-allowed.stderr +++ b/tests/ui/impl-trait/where-allowed.stderr @@ -333,6 +333,9 @@ LL | let _in_local_variable: impl Fn() = || {}; | ^^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods + = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information + = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in closure return types --> $DIR/where-allowed.rs:253:46 diff --git a/tests/ui/issues/issue-18611.stderr b/tests/ui/issues/issue-18611.stderr index 76848201f73..918654215b3 100644 --- a/tests/ui/issues/issue-18611.stderr +++ b/tests/ui/issues/issue-18611.stderr @@ -15,8 +15,7 @@ error[E0277]: the trait bound `isize: HasState` is not satisfied | LL | fn add_state(op: <isize as HasState>::State) { | ______________________________________________^ -LL | | -LL | | +... | LL | | } | |_^ the trait `HasState` is not implemented for `isize` | diff --git a/tests/ui/issues/issue-28344.stderr b/tests/ui/issues/issue-28344.stderr index d8febe71652..7bc965536e9 100644 --- a/tests/ui/issues/issue-28344.stderr +++ b/tests/ui/issues/issue-28344.stderr @@ -12,7 +12,7 @@ help: if this is a dyn-compatible trait, use `dyn` LL | let x: u8 = <dyn BitXor>::bitor(0 as u8, 0 as u8); | ++++ + -error[E0191]: the value of the associated type `Output` in `BitXor` must be specified +error[E0191]: the value of the associated type `Output` in `BitXor<_>` must be specified --> $DIR/issue-28344.rs:4:17 | LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8); @@ -31,7 +31,7 @@ help: if this is a dyn-compatible trait, use `dyn` LL | let g = <dyn BitXor>::bitor; | ++++ + -error[E0191]: the value of the associated type `Output` in `BitXor` must be specified +error[E0191]: the value of the associated type `Output` in `BitXor<_>` must be specified --> $DIR/issue-28344.rs:9:13 | LL | let g = BitXor::bitor; diff --git a/tests/ui/issues/issue-51714.stderr b/tests/ui/issues/issue-51714.stderr index e53e10afcaf..da3e3caea29 100644 --- a/tests/ui/issues/issue-51714.stderr +++ b/tests/ui/issues/issue-51714.stderr @@ -2,14 +2,10 @@ error[E0572]: return statement outside of function body --> $DIR/issue-51714.rs:6:13 | LL | / fn main() { -LL | | -LL | | -LL | | -LL | | +... | LL | | |_: [_; return || {}]| {}; | | ^^^^^^^^^^^^ the return is part of this body... ... | -LL | | LL | | } | |_- ...not the enclosing function body @@ -17,14 +13,10 @@ error[E0572]: return statement outside of function body --> $DIR/issue-51714.rs:10:10 | LL | / fn main() { -LL | | -LL | | -LL | | ... | LL | | [(); return || {}]; | | ^^^^^^^^^^^^ the return is part of this body... ... | -LL | | LL | | } | |_- ...not the enclosing function body @@ -32,14 +24,10 @@ error[E0572]: return statement outside of function body --> $DIR/issue-51714.rs:14:10 | LL | / fn main() { -LL | | -LL | | -LL | | ... | LL | | [(); return |ice| {}]; | | ^^^^^^^^^^^^^^^ the return is part of this body... ... | -LL | | LL | | } | |_- ...not the enclosing function body @@ -47,14 +35,10 @@ error[E0572]: return statement outside of function body --> $DIR/issue-51714.rs:18:10 | LL | / fn main() { -LL | | -LL | | -LL | | ... | LL | | [(); return while let Some(n) = Some(0) {}]; | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the return is part of this body... -LL | | -LL | | +... | LL | | } | |_- ...not the enclosing function body diff --git a/tests/ui/issues/issue-56806.stderr b/tests/ui/issues/issue-56806.stderr index 4b0a59fe12d..ec50d863758 100644 --- a/tests/ui/issues/issue-56806.stderr +++ b/tests/ui/issues/issue-56806.stderr @@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Box<(dyn Trait + 'static)>` LL | fn dyn_instead_of_self(self: Box<dyn Trait>); | ^^^^^^^^^^^^^^ | - = note: type of `self` must be `Self` or some type implementing `Receiver` - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-57741-dereference-boxed-value/issue-57741.stderr b/tests/ui/issues/issue-57741-dereference-boxed-value/issue-57741.stderr index 38014ecce75..3c19b68cffb 100644 --- a/tests/ui/issues/issue-57741-dereference-boxed-value/issue-57741.stderr +++ b/tests/ui/issues/issue-57741-dereference-boxed-value/issue-57741.stderr @@ -2,57 +2,61 @@ error[E0308]: mismatched types --> $DIR/issue-57741.rs:20:9 | LL | let y = match x { - | - - | | - | this expression has type `Box<T>` - | help: consider dereferencing the boxed value: `*x` + | - this expression has type `Box<T>` LL | T::A(a) | T::B(a) => a, | ^^^^^^^ expected `Box<T>`, found `T` | = note: expected struct `Box<T>` found enum `T` +help: consider dereferencing the boxed value + | +LL | let y = match *x { + | ~~ error[E0308]: mismatched types --> $DIR/issue-57741.rs:20:19 | LL | let y = match x { - | - - | | - | this expression has type `Box<T>` - | help: consider dereferencing the boxed value: `*x` + | - this expression has type `Box<T>` LL | T::A(a) | T::B(a) => a, | ^^^^^^^ expected `Box<T>`, found `T` | = note: expected struct `Box<T>` found enum `T` +help: consider dereferencing the boxed value + | +LL | let y = match *x { + | ~~ error[E0308]: mismatched types --> $DIR/issue-57741.rs:27:9 | LL | let y = match x { - | - - | | - | this expression has type `Box<S>` - | help: consider dereferencing the boxed value: `*x` + | - this expression has type `Box<S>` LL | S::A { a } | S::B { b: a } => a, | ^^^^^^^^^^ expected `Box<S>`, found `S` | = note: expected struct `Box<S>` found enum `S` +help: consider dereferencing the boxed value + | +LL | let y = match *x { + | ~~ error[E0308]: mismatched types --> $DIR/issue-57741.rs:27:22 | LL | let y = match x { - | - - | | - | this expression has type `Box<S>` - | help: consider dereferencing the boxed value: `*x` + | - this expression has type `Box<S>` LL | S::A { a } | S::B { b: a } => a, | ^^^^^^^^^^^^^ expected `Box<S>`, found `S` | = note: expected struct `Box<S>` found enum `S` +help: consider dereferencing the boxed value + | +LL | let y = match *x { + | ~~ error: aborting due to 4 previous errors diff --git a/tests/ui/let-else/let-else-deref-coercion.stderr b/tests/ui/let-else/let-else-deref-coercion.stderr index 143b838bac5..da8b1f4c48e 100644 --- a/tests/ui/let-else/let-else-deref-coercion.stderr +++ b/tests/ui/let-else/let-else-deref-coercion.stderr @@ -5,6 +5,11 @@ LL | let Bar::Present(z) = self else { | ^^^^^^^^^^^^^^^ ---- this expression has type `&mut Foo` | | | expected `Foo`, found `Bar` + | +help: consider dereferencing to access the inner value using the Deref trait + | +LL | let Bar::Present(z) = &**self else { + | ~~~~~~~ error[E0308]: mismatched types --> $DIR/let-else-deref-coercion.rs:68:13 @@ -13,6 +18,11 @@ LL | let Bar(z) = x; | ^^^^^^ - this expression has type `&mut irrefutable::Foo` | | | expected `Foo`, found `Bar` + | +help: consider dereferencing to access the inner value using the Deref trait + | +LL | let Bar(z) = &**x; + | ~~~~ error: aborting due to 2 previous errors diff --git a/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr b/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr index e8c3ab00226..90572fed0ed 100644 --- a/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr +++ b/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr @@ -2,9 +2,6 @@ error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32` --> $DIR/issue-76168-hr-outlives-3.rs:6:1 | LL | / async fn wrapper<F>(f: F) -LL | | -LL | | -LL | | ... | LL | | F:, LL | | for<'a> <i32 as FnOnce<(&'a mut i32,)>>::Output: Future<Output = ()> + 'a, @@ -24,9 +21,6 @@ error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32` --> $DIR/issue-76168-hr-outlives-3.rs:6:1 | LL | / async fn wrapper<F>(f: F) -LL | | -LL | | -LL | | ... | LL | | F:, LL | | for<'a> <i32 as FnOnce<(&'a mut i32,)>>::Output: Future<Output = ()> + 'a, @@ -38,9 +32,6 @@ error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32` --> $DIR/issue-76168-hr-outlives-3.rs:6:1 | LL | / async fn wrapper<F>(f: F) -LL | | -LL | | -LL | | ... | LL | | F:, LL | | for<'a> <i32 as FnOnce<(&'a mut i32,)>>::Output: Future<Output = ()> + 'a, diff --git a/tests/ui/lifetimes/issue-97194.stderr b/tests/ui/lifetimes/issue-97194.stderr index 93bde285a99..345e21cb250 100644 --- a/tests/ui/lifetimes/issue-97194.stderr +++ b/tests/ui/lifetimes/issue-97194.stderr @@ -7,10 +7,7 @@ LL | fn bget(&self, index: [usize; Self::DIM]) -> bool { | ________^^^^___________________________________________- | | | | | cannot have a body -LL | | -LL | | -LL | | -LL | | type T<'a> = &'a str; +... | LL | | } | |_____- help: remove the invalid body: `;` | diff --git a/tests/ui/lint/lints-in-foreign-macros.stderr b/tests/ui/lint/lints-in-foreign-macros.stderr index f20e16287af..c0164bd00ff 100644 --- a/tests/ui/lint/lints-in-foreign-macros.stderr +++ b/tests/ui/lint/lints-in-foreign-macros.stderr @@ -34,7 +34,6 @@ LL | | #![warn(missing_docs)] LL | | LL | | #[macro_use] ... | -LL | | LL | | fn main() {} | |____________^ | diff --git a/tests/ui/lint/non-local-defs/consts.stderr b/tests/ui/lint/non-local-defs/consts.stderr index 20fb4a6432e..077837f4a6b 100644 --- a/tests/ui/lint/non-local-defs/consts.stderr +++ b/tests/ui/lint/non-local-defs/consts.stderr @@ -124,7 +124,6 @@ LL | | impl Uto10 for Test {} | | | | | | | `Test` is not local | | `Uto10` is not local -LL | | ... | LL | | }]; | |_____- move the `impl` block outside of this constant expression `<unnameable>` and up 2 bodies diff --git a/tests/ui/lint/non-local-defs/weird-exprs.stderr b/tests/ui/lint/non-local-defs/weird-exprs.stderr index ec3517140ef..5b7d1a83744 100644 --- a/tests/ui/lint/non-local-defs/weird-exprs.stderr +++ b/tests/ui/lint/non-local-defs/weird-exprs.stderr @@ -8,7 +8,6 @@ LL | | impl Uto for *mut Test {} | | | | | | | `Test` is not local | | `Uto` is not local -LL | | ... | LL | | }]; | |_- move the `impl` block outside of this constant expression `<unnameable>` @@ -26,7 +25,6 @@ LL | | impl Uto for Test {} | | | | | | | `Test` is not local | | `Uto` is not local -LL | | ... | LL | | } | |_____- move the `impl` block outside of this constant expression `<unnameable>` @@ -61,7 +59,6 @@ LL | | impl Uto for &Test {} | | | | | | | `Test` is not local | | `Uto` is not local -LL | | ... | LL | | }]; | |_____- move the `impl` block outside of this constant expression `<unnameable>` and up 2 bodies @@ -78,7 +75,6 @@ LL | | impl Uto for &(Test,) {} | | | | | | | `Test` is not local | | `Uto` is not local -LL | | ... | LL | | }]) {} | |_____- move the `impl` block outside of this constant expression `<unnameable>` and up 2 bodies @@ -96,7 +92,6 @@ LL | | impl Uto for &(Test,Test) {} | | | | `Test` is not local | | | `Test` is not local | | `Uto` is not local -LL | | ... | LL | | }] { todo!() } | |_____- move the `impl` block outside of this constant expression `<unnameable>` and up 2 bodies diff --git a/tests/ui/loops/dont-suggest-break-thru-item.stderr b/tests/ui/loops/dont-suggest-break-thru-item.stderr index 642578ade60..e7ed7ae1501 100644 --- a/tests/ui/loops/dont-suggest-break-thru-item.stderr +++ b/tests/ui/loops/dont-suggest-break-thru-item.stderr @@ -4,8 +4,7 @@ error[E0308]: mismatched types LL | / if true { LL | | Err(1) | | ^^^^^^ expected `()`, found `Result<_, {integer}>` -LL | | -LL | | +... | LL | | } | |_____________- expected this to be `()` | @@ -22,8 +21,7 @@ error[E0308]: mismatched types LL | / if true { LL | | Err(1) | | ^^^^^^ expected `()`, found `Result<_, {integer}>` -LL | | -LL | | +... | LL | | } | |_____________- expected this to be `()` | diff --git a/tests/ui/loops/loop-else-err.stderr b/tests/ui/loops/loop-else-err.stderr index c1cbd544afd..36ccd9c4047 100644 --- a/tests/ui/loops/loop-else-err.stderr +++ b/tests/ui/loops/loop-else-err.stderr @@ -6,8 +6,7 @@ LL | loop { LL | LL | } else { | _______^ -LL | | -LL | | +... | LL | | } | |_____^ | diff --git a/tests/ui/loops/loop-else-let-else-err.stderr b/tests/ui/loops/loop-else-let-else-err.stderr index 6ee77fb47af..b2d07d4b2b2 100644 --- a/tests/ui/loops/loop-else-let-else-err.stderr +++ b/tests/ui/loops/loop-else-let-else-err.stderr @@ -6,8 +6,7 @@ LL | let _ = loop { LL | LL | } else { | _______^ -LL | | -LL | | +... | LL | | }; | |_____^ | diff --git a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr index 10e3fc92868..747d492999c 100644 --- a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr +++ b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr @@ -7,8 +7,7 @@ LL | | 0 => x, | | - this is found to be of type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` LL | | _ => y, | | ^ one type is more general than the other -LL | | -LL | | +... | LL | | }; | |_____- `match` arms have incompatible types | diff --git a/tests/ui/match/match-incompat-type-semi.stderr b/tests/ui/match/match-incompat-type-semi.stderr index 008b1c1e93d..ca5336602c7 100644 --- a/tests/ui/match/match-incompat-type-semi.stderr +++ b/tests/ui/match/match-incompat-type-semi.stderr @@ -31,8 +31,7 @@ LL | | 0; | | || | | |help: consider removing this semicolon | | expected integer, found `()` -LL | | -LL | | +... | LL | | }; | |_____- `if` and `else` have incompatible types diff --git a/tests/ui/match/match-type-err-first-arm.stderr b/tests/ui/match/match-type-err-first-arm.stderr index 1cfe7ce1ed7..69f4e22e6ae 100644 --- a/tests/ui/match/match-type-err-first-arm.stderr +++ b/tests/ui/match/match-type-err-first-arm.stderr @@ -21,8 +21,7 @@ LL | | 12 => 'b', | | --- this is found to be of type `char` LL | | _ => 42, | | ^^ expected `char`, found integer -LL | | -LL | | +... | LL | | }; | |_____- `match` arms have incompatible types @@ -40,8 +39,7 @@ LL | | 6 => 'b', LL | | LL | | _ => 42, | | ^^ expected `char`, found integer -LL | | -LL | | +... | LL | | }; | |_____- `match` arms have incompatible types @@ -55,8 +53,7 @@ LL | | x LL | | }, LL | | None => {} | | ^^ expected `u32`, found `()` -LL | | -LL | | +... | LL | | }; | |_____- `match` arms have incompatible types diff --git a/tests/ui/never_type/diverging-place-match.stderr b/tests/ui/never_type/diverging-place-match.stderr index 74e1bfa0a6b..14300c4df05 100644 --- a/tests/ui/never_type/diverging-place-match.stderr +++ b/tests/ui/never_type/diverging-place-match.stderr @@ -5,8 +5,7 @@ LL | / unsafe { LL | | LL | | let x: *const ! = 0 as _; LL | | let _: ! = *x; -LL | | // Since `*x` "diverges" in HIR, but doesn't count as a read in MIR, this -LL | | // is unsound since we act as if it diverges but it doesn't. +... | LL | | } | |_____^ expected `!`, found `()` | diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index ca7d187ac57..3c04cf300ad 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -30,10 +30,7 @@ LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { | | | lifetime `'a` defined here LL | / establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { -LL | | -LL | | -LL | | // Only works if 'x: 'y: -LL | | demand_y(x, y, x.get()) +... | LL | | }); | | ^ | | | diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index d11a64272a9..9f5762ccbfa 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -30,10 +30,7 @@ LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { | | | lifetime `'a` defined here LL | / establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { -LL | | -LL | | -LL | | // Only works if 'x: 'y: -LL | | demand_y(x, y, x.get()) +... | LL | | }); | | ^ | | | diff --git a/tests/ui/nll/snocat-regression.stderr b/tests/ui/nll/snocat-regression.stderr index 135b6951537..ae61245290b 100644 --- a/tests/ui/nll/snocat-regression.stderr +++ b/tests/ui/nll/snocat-regression.stderr @@ -2,10 +2,7 @@ error: `S` does not live long enough --> $DIR/snocat-regression.rs:7:5 | LL | / || { -LL | | -LL | | // -LL | | // FIXME(#98437). This regressed at some point and -LL | | // probably should work. +... | LL | | let _x = link; LL | | }; | |_____^ diff --git a/tests/ui/or-patterns/missing-bindings.stderr b/tests/ui/or-patterns/missing-bindings.stderr index 677b40a7f0d..6288cc58913 100644 --- a/tests/ui/or-patterns/missing-bindings.stderr +++ b/tests/ui/or-patterns/missing-bindings.stderr @@ -219,7 +219,6 @@ LL | | A( LL | | A(_, a) | LL | | B(b), ... | -LL | | LL | | ) | | |_____________^ pattern doesn't bind `c` LL | V3(c), diff --git a/tests/ui/parser/as-precedence.rs b/tests/ui/parser/as-precedence.rs new file mode 100644 index 00000000000..ca8328adb0e --- /dev/null +++ b/tests/ui/parser/as-precedence.rs @@ -0,0 +1,18 @@ +//! Parser precedence test to help with [RFC 87 "Trait Bounds with Plus"][rfc-87], to check the +//! precedence of the `as` operator in relation to some arithmetic bin-ops and parentheses. +//! +//! Editor's note: this test seems quite incomplete compared to what's possible nowadays. Maybe +//! there's another set of tests whose coverage overshadows this test? +//! +//! [rfc-87]: https://rust-lang.github.io/rfcs/0087-trait-bounds-with-plus.html + +//@ run-pass + +#[allow(unused_parens)] +fn main() { + assert_eq!(3 as usize * 3, 9); + assert_eq!(3 as (usize) * 3, 9); + assert_eq!(3 as (usize) / 3, 1); + assert_eq!(3 as usize + 3, 6); + assert_eq!(3 as (usize) + 3, 6); +} diff --git a/tests/ui/parser/brace-in-let-chain.rs b/tests/ui/parser/brace-in-let-chain.rs index 1f34c73a2c3..2009bc88d9e 100644 --- a/tests/ui/parser/brace-in-let-chain.rs +++ b/tests/ui/parser/brace-in-let-chain.rs @@ -3,7 +3,7 @@ #![feature(let_chains)] fn main() { if let () = () - && let () = () { //~ERROR: found a `{` in the middle of a let-chain + && let () = () { && let () = () { } @@ -11,7 +11,7 @@ fn main() { fn quux() { while let () = () - && let () = () { //~ERROR: found a `{` in the middle of a let-chain + && let () = () { && let () = () { } diff --git a/tests/ui/parser/brace-in-let-chain.stderr b/tests/ui/parser/brace-in-let-chain.stderr index 913a34700df..12af95c2786 100644 --- a/tests/ui/parser/brace-in-let-chain.stderr +++ b/tests/ui/parser/brace-in-let-chain.stderr @@ -27,33 +27,5 @@ LL | } LL | } | ^ -error: found a `{` in the middle of a let-chain - --> $DIR/brace-in-let-chain.rs:14:24 - | -LL | && let () = () { - | ^ -LL | && let () = () - | ------ you might have meant to continue the let-chain here - | -help: consider removing this brace to parse the `let` as part of the same chain - | -LL - && let () = () { -LL + && let () = () - | - -error: found a `{` in the middle of a let-chain - --> $DIR/brace-in-let-chain.rs:6:24 - | -LL | && let () = () { - | ^ -LL | && let () = () - | ------ you might have meant to continue the let-chain here - | -help: consider removing this brace to parse the `let` as part of the same chain - | -LL - && let () = () { -LL + && let () = () - | - -error: aborting due to 3 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/parser/circular_modules_main.stderr b/tests/ui/parser/circular_modules_main.stderr index 2de70789358..e1780fe9fd9 100644 --- a/tests/ui/parser/circular_modules_main.stderr +++ b/tests/ui/parser/circular_modules_main.stderr @@ -4,22 +4,5 @@ error: circular modules: $DIR/circular_modules_main.rs -> $DIR/circular_modules_ LL | mod circular_modules_main; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0425]: cannot find function `hi_str` in module `circular_modules_main` - --> $DIR/circular_modules_hello.rs:7:43 - | -LL | println!("{}", circular_modules_main::hi_str()); - | ^^^^^^ not found in `circular_modules_main` - | -help: consider importing this function - | -LL + use hi_str; - | -help: if you import `hi_str`, refer to it directly - | -LL - println!("{}", circular_modules_main::hi_str()); -LL + println!("{}", hi_str()); - | - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/parser/diff-markers/unclosed-delims-in-macro.rs b/tests/ui/parser/diff-markers/unclosed-delims-in-macro.rs index da1774acea5..41a7de03d4b 100644 --- a/tests/ui/parser/diff-markers/unclosed-delims-in-macro.rs +++ b/tests/ui/parser/diff-markers/unclosed-delims-in-macro.rs @@ -1,9 +1,11 @@ +// The diff marker detection was removed for this example, because it relied on +// the lexer having a dependency on the parser, which was horrible. + macro_rules! foo { <<<<<<< HEAD - //~^ ERROR encountered diff marker () { ======= () { // >>>>>>> 7a4f13c blah blah blah } -} +} //~ this file contains an unclosed delimiter diff --git a/tests/ui/parser/diff-markers/unclosed-delims-in-macro.stderr b/tests/ui/parser/diff-markers/unclosed-delims-in-macro.stderr index 927821ddfae..b33f2b5d1b8 100644 --- a/tests/ui/parser/diff-markers/unclosed-delims-in-macro.stderr +++ b/tests/ui/parser/diff-markers/unclosed-delims-in-macro.stderr @@ -1,23 +1,16 @@ -error: encountered diff marker - --> $DIR/unclosed-delims-in-macro.rs:2:1 +error: this file contains an unclosed delimiter + --> $DIR/unclosed-delims-in-macro.rs:11:48 | +LL | macro_rules! foo { + | - unclosed delimiter LL | <<<<<<< HEAD - | ^^^^^^^ between this marker and `=======` is the code that we're merging into +LL | () { + | - this delimiter might not be properly closed... ... -LL | ======= - | ------- between this marker and `>>>>>>>` is the incoming code -LL | () { // -LL | >>>>>>> 7a4f13c blah blah blah - | ^^^^^^^ this marker concludes the conflict region - | - = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts - to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers - = help: if you're having merge conflicts after pulling new code: - the top section is the code you already had and the bottom section is the remote code - if you're in the middle of a rebase: - the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased - = note: for an explanation on these markers from the `git` documentation: - visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> +LL | } + | - ^ + | | + | ...as it matches this but it has different indentation error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/unclosed-delims.rs b/tests/ui/parser/diff-markers/unclosed-delims.rs index 7d400c3827b..827c1eebb9d 100644 --- a/tests/ui/parser/diff-markers/unclosed-delims.rs +++ b/tests/ui/parser/diff-markers/unclosed-delims.rs @@ -1,18 +1,12 @@ +// The diff marker detection was removed for this example, because it relied on +// the lexer having a dependency on the parser, which was horrible. + mod tests { #[test] <<<<<<< HEAD -//~^ ERROR encountered diff marker -//~| NOTE between this marker and `=======` - -//~| NOTE conflict markers indicate that -//~| HELP if you're having merge conflicts -//~| NOTE for an explanation on these markers - fn test1() { ======= -//~^ NOTE between this marker and `>>>>>>>` fn test2() { >>>>>>> 7a4f13c blah blah blah -//~^ NOTE this marker concludes the conflict region } -} +} //~ this file contains an unclosed delimiter diff --git a/tests/ui/parser/diff-markers/unclosed-delims.stderr b/tests/ui/parser/diff-markers/unclosed-delims.stderr index 1eab96442b4..b2541aa47ba 100644 --- a/tests/ui/parser/diff-markers/unclosed-delims.stderr +++ b/tests/ui/parser/diff-markers/unclosed-delims.stderr @@ -1,23 +1,16 @@ -error: encountered diff marker - --> $DIR/unclosed-delims.rs:3:1 +error: this file contains an unclosed delimiter + --> $DIR/unclosed-delims.rs:12:48 | -LL | <<<<<<< HEAD - | ^^^^^^^ between this marker and `=======` is the code that we're merging into +LL | mod tests { + | - unclosed delimiter ... -LL | ======= - | ------- between this marker and `>>>>>>>` is the incoming code +LL | fn test1() { + | - this delimiter might not be properly closed... ... -LL | >>>>>>> 7a4f13c blah blah blah - | ^^^^^^^ this marker concludes the conflict region - | - = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts - to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers - = help: if you're having merge conflicts after pulling new code: - the top section is the code you already had and the bottom section is the remote code - if you're in the middle of a rebase: - the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased - = note: for an explanation on these markers from the `git` documentation: - visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> +LL | } + | - ^ + | | + | ...as it matches this but it has different indentation error: aborting due to 1 previous error diff --git a/tests/ui/parser/fn-arg-doc-comment.stderr b/tests/ui/parser/fn-arg-doc-comment.stderr index c8d7e2efe79..1891c708903 100644 --- a/tests/ui/parser/fn-arg-doc-comment.stderr +++ b/tests/ui/parser/fn-arg-doc-comment.stderr @@ -30,15 +30,11 @@ note: function defined here LL | pub fn f( | ^ LL | / /// Comment -LL | | -LL | | -LL | | +... | LL | | id: u8, | |__________- LL | / /// Other -LL | | -LL | | -LL | | +... | LL | | a: u8, | |_________- diff --git a/tests/ui/privacy/effective_visibilities.stderr b/tests/ui/privacy/effective_visibilities.stderr index 41d63532dea..6954279c05a 100644 --- a/tests/ui/privacy/effective_visibilities.stderr +++ b/tests/ui/privacy/effective_visibilities.stderr @@ -6,7 +6,6 @@ LL | | #![feature(rustc_attrs)] LL | | LL | | #[rustc_effective_visibility] ... | -LL | | LL | | fn main() {} | |____________^ diff --git a/tests/ui/privacy/effective_visibilities_invariants.stderr b/tests/ui/privacy/effective_visibilities_invariants.stderr index 1c19afdcdba..64d0402f84e 100644 --- a/tests/ui/privacy/effective_visibilities_invariants.stderr +++ b/tests/ui/privacy/effective_visibilities_invariants.stderr @@ -16,7 +16,6 @@ LL | / #![feature(staged_api)] LL | | LL | | pub mod m {} ... | -LL | | LL | | fn main() {} | |____________^ diff --git a/tests/ui/privacy/issue-113860-1.stderr b/tests/ui/privacy/issue-113860-1.stderr index c05452fb51c..dad9ebadf04 100644 --- a/tests/ui/privacy/issue-113860-1.stderr +++ b/tests/ui/privacy/issue-113860-1.stderr @@ -14,7 +14,6 @@ LL | | LL | | LL | | pub trait Trait { ... | -LL | | LL | | fn main() {} | |____________^ diff --git a/tests/ui/privacy/issue-113860-2.stderr b/tests/ui/privacy/issue-113860-2.stderr index c53c490ca1e..9805c22dbdf 100644 --- a/tests/ui/privacy/issue-113860-2.stderr +++ b/tests/ui/privacy/issue-113860-2.stderr @@ -14,7 +14,6 @@ LL | | LL | | LL | | pub trait Trait { ... | -LL | | LL | | fn main() {} | |____________^ diff --git a/tests/ui/privacy/issue-113860.stderr b/tests/ui/privacy/issue-113860.stderr index d813b740ac5..88efcae4a85 100644 --- a/tests/ui/privacy/issue-113860.stderr +++ b/tests/ui/privacy/issue-113860.stderr @@ -14,7 +14,6 @@ LL | | LL | | LL | | pub trait Trait { ... | -LL | | LL | | fn main() {} | |____________^ diff --git a/tests/ui/raw-ref-op/amp-raw-without-mut-const-is-a-normal-borrow.rs b/tests/ui/raw-ref-op/amp-raw-without-mut-const-is-a-normal-borrow.rs new file mode 100644 index 00000000000..9360146a0fc --- /dev/null +++ b/tests/ui/raw-ref-op/amp-raw-without-mut-const-is-a-normal-borrow.rs @@ -0,0 +1,30 @@ +//! The token sequence `&raw` *only* starts a raw borrow expr if it's immediately +//! followed by either `const` or `mut`. If that's not the case, the `&` denotes +//! the start of a normal borrow expr where `raw` is interpreted as a regular +//! identifier and thus denotes the start of a path expr. +//! +//! This test ensures that we never commit too early/overzealously in the parser +//! when encountering the sequence `&raw` (even during parse error recovery) so +//! as not to regress preexisting code. + +//@ check-pass + +fn main() { // the odd formatting in here is intentional + let raw = 0; + let _ = &raw; + + let raw = 0; + let local = 1; + let _: i32 = &raw *local; + + let raw = |_| (); + let local = [0]; + let () = &raw (local[0]); +} + +macro_rules! check { + ($e:expr) => { compile_error!("expr"); }; + (&raw $e:expr) => {}; +} + +check!(&raw local); diff --git a/tests/ui/raw-ref-op/never-place-isnt-diverging.stderr b/tests/ui/raw-ref-op/never-place-isnt-diverging.stderr index af9e7889821..0a8340545eb 100644 --- a/tests/ui/raw-ref-op/never-place-isnt-diverging.stderr +++ b/tests/ui/raw-ref-op/never-place-isnt-diverging.stderr @@ -7,8 +7,7 @@ LL | / unsafe { LL | | LL | | let x: *const ! = 0 as _; LL | | &raw const *x; -LL | | // Since `*x` is `!`, HIR typeck used to think that it diverges -LL | | // and allowed the block to coerce to any value, leading to UB. +... | LL | | } | |_____^ expected type parameter `T`, found `()` | diff --git a/tests/ui/reachable/artificial-block.rs b/tests/ui/reachable/artificial-block.rs new file mode 100644 index 00000000000..6d73ba1a972 --- /dev/null +++ b/tests/ui/reachable/artificial-block.rs @@ -0,0 +1,30 @@ +//! Check that we don't get compile errors on unreachable code after the `{ return 3; }` artificial +//! block below. This test is run-pass to also exercise the codegen, but it might be possible to +//! reduce to build-pass or even check-pass. +//! +//! This test was introduced as part of commit `a833f152baa17460e8414355e832d30d5161f8e8` which +//! removes an "artificial block". See also commit `3d738e9e0634a4cd6239d1317bd7dad53be68dc8` for +//! more elaboration, reproduced below (this is outdated for *today*'s rustc as of 2024-12-10, but +//! is helpful to understand the original intention): +//! +//! > Return a fresh, unreachable context after ret, break, and cont +//! > +//! > This ensures we don't get compile errors on unreachable code (see +//! > test/run-pass/artificial-block.rs for an example of sane code that wasn't compiling). In the +//! > future, we might want to warn about non-trivial code appearing in an unreachable context, +//! > and/or avoid generating unreachable code altogether (though I'm sure LLVM will weed it out as +//! > well). +//! +//! Since then, `ret` became `return`, `int` became `isize` and `assert` became a macro. + +//@ run-pass + +fn f() -> isize { + { + return 3; + } +} + +fn main() { + assert_eq!(f(), 3); +} diff --git a/tests/ui/resolve/parse-error-resolve.rs b/tests/ui/resolve/parse-error-resolve.rs new file mode 100644 index 00000000000..1e0772648af --- /dev/null +++ b/tests/ui/resolve/parse-error-resolve.rs @@ -0,0 +1,7 @@ +mod parse_error; +use parse_error::Canonical; // ok, `parse_error.rs` had parse errors + +fn main() { + let _ = "" + 1; //~ ERROR E0369 + parse_error::Canonical.foo(); // ok, `parse_error.rs` had parse errors +} diff --git a/tests/ui/resolve/parse-error-resolve.stderr b/tests/ui/resolve/parse-error-resolve.stderr new file mode 100644 index 00000000000..30475aa0ee6 --- /dev/null +++ b/tests/ui/resolve/parse-error-resolve.stderr @@ -0,0 +1,22 @@ +error: expected one of `+`, `,`, `::`, `=`, or `>`, found `From` + --> $DIR/parse_error.rs:2:46 + | +LL | impl<S: Into<std::borrow::Cow<'static, str>> From<S> for Canonical { + | ^^^^ expected one of `+`, `,`, `::`, `=`, or `>` + | +help: you might have meant to end the type parameters here + | +LL | impl<S: Into<std::borrow::Cow<'static, str>>> From<S> for Canonical { + | + + +error[E0369]: cannot add `{integer}` to `&str` + --> $DIR/parse-error-resolve.rs:5:16 + | +LL | let _ = "" + 1; + | -- ^ - {integer} + | | + | &str + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/resolve/parse_error.rs b/tests/ui/resolve/parse_error.rs new file mode 100644 index 00000000000..4cd025e1edf --- /dev/null +++ b/tests/ui/resolve/parse_error.rs @@ -0,0 +1,5 @@ +struct Canonical; +impl<S: Into<std::borrow::Cow<'static, str>> From<S> for Canonical { //~ ERROR expected + fn foo() {} +} +fn bar() {} diff --git a/tests/ui/resolve/parse_error.stderr b/tests/ui/resolve/parse_error.stderr new file mode 100644 index 00000000000..f764f08875f --- /dev/null +++ b/tests/ui/resolve/parse_error.stderr @@ -0,0 +1,13 @@ +error: expected one of `+`, `,`, `::`, `=`, or `>`, found `From` + --> $DIR/parse_error.rs:2:46 + | +LL | impl<S: Into<std::borrow::Cow<'static, str>> From<S> for Canonical { + | ^^^^ expected one of `+`, `,`, `::`, `=`, or `>` + | +help: you might have meant to end the type parameters here + | +LL | impl<S: Into<std::borrow::Cow<'static, str>>> From<S> for Canonical { + | + + +error: aborting due to 1 previous error + diff --git a/tests/ui/return/issue-86188-return-not-in-fn-body.stderr b/tests/ui/return/issue-86188-return-not-in-fn-body.stderr index 4f938670e5e..abbcc21141e 100644 --- a/tests/ui/return/issue-86188-return-not-in-fn-body.stderr +++ b/tests/ui/return/issue-86188-return-not-in-fn-body.stderr @@ -15,8 +15,7 @@ LL | / fn bar() { LL | | LL | | [(); return]; | | ^^^^^^ the return is part of this body... -LL | | -LL | | +... | LL | | } | |_____- ...not the enclosing function body @@ -27,8 +26,7 @@ LL | / fn foo() { LL | | LL | | [(); return]; | | ^^^^^^ the return is part of this body... -LL | | -LL | | +... | LL | | } | |_____- ...not the enclosing function body diff --git a/tests/ui/return/return-match-array-const.stderr b/tests/ui/return/return-match-array-const.stderr index 85a733adfee..c2a0ada7098 100644 --- a/tests/ui/return/return-match-array-const.stderr +++ b/tests/ui/return/return-match-array-const.stderr @@ -2,13 +2,10 @@ error[E0572]: return statement outside of function body --> $DIR/return-match-array-const.rs:5:10 | LL | / fn main() { -LL | | -LL | | -LL | | +... | LL | | [(); return match 0 { n => n }]; | | ^^^^^^^^^^^^^^^^^^^^^^^^^ the return is part of this body... ... | -LL | | LL | | } | |_- ...not the enclosing function body @@ -16,14 +13,10 @@ error[E0572]: return statement outside of function body --> $DIR/return-match-array-const.rs:9:10 | LL | / fn main() { -LL | | -LL | | -LL | | ... | LL | | [(); return match 0 { 0 => 0 }]; | | ^^^^^^^^^^^^^^^^^^^^^^^^^ the return is part of this body... ... | -LL | | LL | | } | |_- ...not the enclosing function body @@ -31,14 +24,10 @@ error[E0572]: return statement outside of function body --> $DIR/return-match-array-const.rs:13:10 | LL | / fn main() { -LL | | -LL | | -LL | | ... | LL | | [(); return match () { 'a' => 0, _ => 0 }]; | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the return is part of this body... ... | -LL | | LL | | } | |_- ...not the enclosing function body diff --git a/tests/ui/return/tail-expr-as-potential-return.stderr b/tests/ui/return/tail-expr-as-potential-return.stderr index 635a9e06633..756de2b5a16 100644 --- a/tests/ui/return/tail-expr-as-potential-return.stderr +++ b/tests/ui/return/tail-expr-as-potential-return.stderr @@ -4,8 +4,7 @@ error[E0308]: mismatched types LL | / if x { LL | | Err(42) | | ^^^^^^^ expected `()`, found `Result<_, {integer}>` -LL | | -LL | | +... | LL | | } | |_____- expected this to be `()` | @@ -22,8 +21,7 @@ error[E0308]: mismatched types LL | / if true { LL | | 1i32 | | ^^^^ expected `()`, found `i32` -LL | | -LL | | +... | LL | | } | |_____- expected this to be `()` | @@ -38,8 +36,7 @@ error[E0308]: mismatched types LL | / if x { LL | | Err(42) | | ^^^^^^^ expected `()`, found `Result<_, {integer}>` -LL | | -LL | | +... | LL | | } | |_____- expected this to be `()` | diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr index cceb3bddef4..874b32346af 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr @@ -4,9 +4,7 @@ error: extern blocks must be unsafe LL | / extern "C" { LL | | LL | | safe static TEST1: i32; -LL | | -LL | | safe fn test1(i: i32); -LL | | +... | LL | | } | |_^ diff --git a/tests/ui/self/arbitrary-self-opaque.stderr b/tests/ui/self/arbitrary-self-opaque.stderr index 0469aca27dc..c75165d9f8e 100644 --- a/tests/ui/self/arbitrary-self-opaque.stderr +++ b/tests/ui/self/arbitrary-self-opaque.stderr @@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Bar` LL | fn foo(self: Bar) {} | ^^^ | - = note: type of `self` must be `Self` or some type implementing `Receiver` - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) error: item does not constrain `Bar::{opaque#0}`, but has it in its signature --> $DIR/arbitrary-self-opaque.rs:7:8 diff --git a/tests/ui/self/arbitrary_self_types_nonnull.rs b/tests/ui/self/arbitrary_self_types_nonnull.rs new file mode 100644 index 00000000000..ab1589b956e --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_nonnull.rs @@ -0,0 +1,13 @@ +#![feature(arbitrary_self_types)] + +struct A; + +impl A { + fn m(self: std::ptr::NonNull<Self>) {} + //~^ ERROR: invalid `self` parameter type + fn n(self: &std::ptr::NonNull<Self>) {} + //~^ ERROR: invalid `self` parameter type +} + +fn main() { +} diff --git a/tests/ui/self/arbitrary_self_types_nonnull.stderr b/tests/ui/self/arbitrary_self_types_nonnull.stderr new file mode 100644 index 00000000000..5ebe58b4e48 --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_nonnull.stderr @@ -0,0 +1,23 @@ +error[E0307]: invalid `self` parameter type: `NonNull<A>` + --> $DIR/arbitrary_self_types_nonnull.rs:6:16 + | +LL | fn m(self: std::ptr::NonNull<Self>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: type of `self` must be `Self` or some type implementing `Receiver` + = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` + = note: `NonNull` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `NonNull` in a newtype wrapper for which you implement `Receiver` + +error[E0307]: invalid `self` parameter type: `&NonNull<A>` + --> $DIR/arbitrary_self_types_nonnull.rs:8:16 + | +LL | fn n(self: &std::ptr::NonNull<Self>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: type of `self` must be `Self` or some type implementing `Receiver` + = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` + = note: `NonNull` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `NonNull` in a newtype wrapper for which you implement `Receiver` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0307`. diff --git a/tests/ui/self/arbitrary_self_types_weak.rs b/tests/ui/self/arbitrary_self_types_weak.rs new file mode 100644 index 00000000000..91f2b9e0a95 --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_weak.rs @@ -0,0 +1,13 @@ +#![feature(arbitrary_self_types)] + +struct A; + +impl A { + fn m(self: std::rc::Weak<Self>) {} + //~^ ERROR: invalid `self` parameter type + fn n(self: std::sync::Weak<Self>) {} + //~^ ERROR: invalid `self` parameter type +} + +fn main() { +} diff --git a/tests/ui/self/arbitrary_self_types_weak.stderr b/tests/ui/self/arbitrary_self_types_weak.stderr new file mode 100644 index 00000000000..42d239419ad --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_weak.stderr @@ -0,0 +1,23 @@ +error[E0307]: invalid `self` parameter type: `std::rc::Weak<A>` + --> $DIR/arbitrary_self_types_weak.rs:6:16 + | +LL | fn m(self: std::rc::Weak<Self>) {} + | ^^^^^^^^^^^^^^^^^^^ + | + = note: type of `self` must be `Self` or some type implementing `Receiver` + = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` + = note: `Weak` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `Weak` in a newtype wrapper for which you implement `Receiver` + +error[E0307]: invalid `self` parameter type: `std::sync::Weak<A>` + --> $DIR/arbitrary_self_types_weak.rs:8:16 + | +LL | fn n(self: std::sync::Weak<Self>) {} + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: type of `self` must be `Self` or some type implementing `Receiver` + = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` + = note: `Weak` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `Weak` in a newtype wrapper for which you implement `Receiver` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0307`. diff --git a/tests/ui/span/issue-27522.stderr b/tests/ui/span/issue-27522.stderr index 04904b0ddc1..c57a100bbe2 100644 --- a/tests/ui/span/issue-27522.stderr +++ b/tests/ui/span/issue-27522.stderr @@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `&SomeType` LL | fn handler(self: &SomeType); | ^^^^^^^^^ | - = note: type of `self` must be `Self` or some type implementing `Receiver` - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) error: aborting due to 1 previous error diff --git a/tests/ui/specialization/min_specialization/issue-79224.stderr b/tests/ui/specialization/min_specialization/issue-79224.stderr index 84e526f4597..2b8169af6a2 100644 --- a/tests/ui/specialization/min_specialization/issue-79224.stderr +++ b/tests/ui/specialization/min_specialization/issue-79224.stderr @@ -39,10 +39,7 @@ error[E0277]: the trait bound `B: Clone` is not satisfied | LL | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ______________________________________________________________^ -LL | | -LL | | -LL | | -LL | | write!(f, "foo") +... | LL | | } | |_____^ the trait `Clone` is not implemented for `B` | diff --git a/tests/ui/stability-attribute/missing-stability-attr-at-top-level.stderr b/tests/ui/stability-attribute/missing-stability-attr-at-top-level.stderr index 3af1e82d207..fb564932cd5 100644 --- a/tests/ui/stability-attribute/missing-stability-attr-at-top-level.stderr +++ b/tests/ui/stability-attribute/missing-stability-attr-at-top-level.stderr @@ -2,8 +2,7 @@ error: module has missing stability attribute --> $DIR/missing-stability-attr-at-top-level.rs:1:1 | LL | / #![feature(staged_api)] -LL | | -LL | | +... | LL | | fn main() {} | |____________^ diff --git a/tests/ui/stability-attribute/stability-attribute-trait-impl.stderr b/tests/ui/stability-attribute/stability-attribute-trait-impl.stderr index 018786dd26d..c954282cbc7 100644 --- a/tests/ui/stability-attribute/stability-attribute-trait-impl.stderr +++ b/tests/ui/stability-attribute/stability-attribute-trait-impl.stderr @@ -23,7 +23,6 @@ LL | | LL | | LL | | #[stable(feature = "a", since = "3.3.3")] ... | -LL | | LL | | fn main() {} | |____________^ diff --git a/tests/ui/stable-mir-print/async-closure.rs b/tests/ui/stable-mir-print/async-closure.rs new file mode 100644 index 00000000000..7da532a359f --- /dev/null +++ b/tests/ui/stable-mir-print/async-closure.rs @@ -0,0 +1,12 @@ +//@ compile-flags: -Z unpretty=stable-mir --crate-type lib -C panic=abort +//@ check-pass +//@ only-x86_64 +//@ edition: 2024 +//@ needs-unwind unwind edges are different with panic=abort + +pub fn foo() { + let y = 0; + let x = async || { + let y = y; + }; +} diff --git a/tests/ui/stable-mir-print/async-closure.stdout b/tests/ui/stable-mir-print/async-closure.stdout new file mode 100644 index 00000000000..21df1fd3954 --- /dev/null +++ b/tests/ui/stable-mir-print/async-closure.stdout @@ -0,0 +1,90 @@ +// WARNING: This is highly experimental output it's intended for stable-mir developers only. +// If you find a bug or want to improve the output open a issue at https://github.com/rust-lang/project-stable-mir. +fn foo() -> () { + let mut _0: (); + let _1: i32; + let _2: {async closure@$DIR/async-closure.rs:9:13: 9:21}; + let mut _3: &i32; + debug y => _1; + debug x => _2; + bb0: { + _1 = 0_i32; + _3 = &_1; + _2 = {coroutine-closure@$DIR/async-closure.rs:9:13: 9:21}(move _3); + return; + } +} +fn foo::{closure#0}(_1: &{async closure@$DIR/async-closure.rs:9:13: 9:21}) -> {async closure body@$DIR/async-closure.rs:9:22: 11:6} { + let mut _0: {async closure body@$DIR/async-closure.rs:9:22: 11:6}; + let mut _2: &i32; + debug y => (*((*_1).0: &i32)); + bb0: { + _2 = CopyForDeref(((*_1).0: &i32)); + _0 = {coroutine@$DIR/async-closure.rs:9:22: 11:6}(_2); + return; + } +} +fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}>, _2: &mut Context<'_>) -> Poll<()> { + let mut _0: Poll<()>; + let _3: i32; + let mut _4: &i32; + let mut _5: u32; + let mut _6: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; + let mut _7: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; + let mut _8: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; + debug _task_context => _2; + debug y => (*((*(_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})).0: &i32)); + debug y => _3; + bb0: { + _6 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})); + _5 = discriminant((*_6)); + switchInt(move _5) -> [0: bb1, 1: bb2, otherwise: bb3]; + } + bb1: { + _7 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})); + _4 = CopyForDeref(((*_7).0: &i32)); + _3 = (*_4); + _0 = std::task::Poll::Ready(()); + _8 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})); + discriminant((*_8) = 1; + return; + } + bb2: { + assert(false, `async fn` resumed after completion) -> [success: bb2, unwind unreachable]; + } + bb3: { + unreachable; + } +} +fn foo::{closure#0}::{closure#1}(_1: Pin<&mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}>, _2: &mut Context<'_>) -> Poll<()> { + let mut _0: Poll<()>; + let _3: i32; + let mut _4: &i32; + let mut _5: u32; + let mut _6: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; + let mut _7: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; + let mut _8: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; + debug _task_context => _2; + debug y => (*((*(_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})).0: &i32)); + debug y => _3; + bb0: { + _6 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})); + _5 = discriminant((*_6)); + switchInt(move _5) -> [0: bb1, 1: bb2, otherwise: bb3]; + } + bb1: { + _7 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})); + _4 = CopyForDeref(((*_7).0: &i32)); + _3 = (*_4); + _0 = std::task::Poll::Ready(()); + _8 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})); + discriminant((*_8) = 1; + return; + } + bb2: { + assert(false, `async fn` resumed after completion) -> [success: bb2, unwind unreachable]; + } + bb3: { + unreachable; + } +} diff --git a/tests/ui/stable-mir-print/operands.stdout b/tests/ui/stable-mir-print/operands.stdout index 3c27878b3cf..c3b1151ae24 100644 --- a/tests/ui/stable-mir-print/operands.stdout +++ b/tests/ui/stable-mir-print/operands.stdout @@ -5,187 +5,183 @@ fn operands(_1: u8) -> () { let _2: [u8; 10]; let _3: u8; let _4: usize; - let mut _5: usize; - let mut _6: bool; - let _7: u8; - let _8: usize; - let mut _9: (usize, bool); - let mut _10: usize; - let mut _11: bool; - let mut _12: (&u8, &u8); - let mut _13: &u8; - let mut _14: &u8; - let _15: &u8; - let _16: &u8; - let mut _17: bool; - let mut _18: u8; - let mut _19: u8; - let _20: core::panicking::AssertKind; - let _21: !; - let mut _22: Option<Arguments<'_>>; - let _23: &u8; - let _24: u8; - let mut _25: (&u8, &u8); - let mut _26: &u8; - let mut _27: &u8; - let _28: &u8; - let _29: &u8; - let mut _30: bool; - let mut _31: u8; - let mut _32: u8; - let _33: core::panicking::AssertKind; - let _34: !; - let mut _35: Option<Arguments<'_>>; - let _36: (u8, u8); - let _37: u8; - let _38: u8; - let mut _39: (&u8, &u8); - let mut _40: &u8; - let mut _41: &u8; - let _42: &u8; - let _43: &u8; - let mut _44: bool; - let mut _45: u8; - let mut _46: u8; - let _47: core::panicking::AssertKind; - let _48: !; - let mut _49: Option<Arguments<'_>>; - let _50: usize; - let mut _51: &[u8]; - let mut _52: &[u8; 10]; - let _53: usize; - let _54: &usize; - let mut _55: (&usize, &usize); - let mut _56: &usize; - let mut _57: &usize; - let _58: &usize; - let _59: &usize; - let mut _60: bool; - let mut _61: usize; - let mut _62: usize; - let _63: core::panicking::AssertKind; - let _64: !; - let mut _65: Option<Arguments<'_>>; + let mut _5: bool; + let _6: u8; + let _7: usize; + let mut _8: (usize, bool); + let mut _9: bool; + let mut _10: (&u8, &u8); + let mut _11: &u8; + let mut _12: &u8; + let _13: &u8; + let _14: &u8; + let mut _15: bool; + let mut _16: u8; + let mut _17: u8; + let _18: core::panicking::AssertKind; + let _19: !; + let mut _20: Option<Arguments<'_>>; + let _21: &u8; + let _22: u8; + let mut _23: (&u8, &u8); + let mut _24: &u8; + let mut _25: &u8; + let _26: &u8; + let _27: &u8; + let mut _28: bool; + let mut _29: u8; + let mut _30: u8; + let _31: core::panicking::AssertKind; + let _32: !; + let mut _33: Option<Arguments<'_>>; + let _34: (u8, u8); + let _35: u8; + let _36: u8; + let mut _37: (&u8, &u8); + let mut _38: &u8; + let mut _39: &u8; + let _40: &u8; + let _41: &u8; + let mut _42: bool; + let mut _43: u8; + let mut _44: u8; + let _45: core::panicking::AssertKind; + let _46: !; + let mut _47: Option<Arguments<'_>>; + let _48: usize; + let mut _49: &[u8]; + let mut _50: &[u8; 10]; + let _51: usize; + let _52: &usize; + let mut _53: (&usize, &usize); + let mut _54: &usize; + let mut _55: &usize; + let _56: &usize; + let _57: &usize; + let mut _58: bool; + let mut _59: usize; + let mut _60: usize; + let _61: core::panicking::AssertKind; + let _62: !; + let mut _63: Option<Arguments<'_>>; debug val => _1; debug array => _2; debug first => _3; - debug last => _7; - debug left_val => _15; - debug right_val => _16; - debug kind => _20; - debug reference => _23; - debug dereferenced => _24; - debug left_val => _28; - debug right_val => _29; - debug kind => _33; - debug tuple => _36; - debug first_again => _37; - debug first_again_again => _38; - debug left_val => _42; - debug right_val => _43; - debug kind => _47; - debug length => _50; - debug size_of => _53; - debug left_val => _58; - debug right_val => _59; - debug kind => _63; + debug last => _6; + debug left_val => _13; + debug right_val => _14; + debug kind => _18; + debug reference => _21; + debug dereferenced => _22; + debug left_val => _26; + debug right_val => _27; + debug kind => _31; + debug tuple => _34; + debug first_again => _35; + debug first_again_again => _36; + debug left_val => _40; + debug right_val => _41; + debug kind => _45; + debug length => _48; + debug size_of => _51; + debug left_val => _56; + debug right_val => _57; + debug kind => _61; bb0: { _2 = [_1; 10]; _4 = 0_usize; - _5 = 10_usize; - _6 = Lt(_4, _5); - assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind unreachable]; + _5 = Lt(_4, 10_usize); + assert(move _5, "index out of bounds: the length is {} but the index is {}", 10_usize, _4) -> [success: bb1, unwind unreachable]; } bb1: { _3 = _2[_4]; - _9 = CheckedSub(10_usize, 1_usize); - assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", 10_usize, 1_usize) -> [success: bb2, unwind unreachable]; + _8 = CheckedSub(10_usize, 1_usize); + assert(!move (_8.1: bool), "attempt to compute `{} - {}`, which would overflow", 10_usize, 1_usize) -> [success: bb2, unwind unreachable]; } bb2: { - _8 = move (_9.0: usize); - _10 = 10_usize; - _11 = Lt(_8, _10); - assert(move _11, "index out of bounds: the length is {} but the index is {}", move _10, _8) -> [success: bb3, unwind unreachable]; + _7 = move (_8.0: usize); + _9 = Lt(_7, 10_usize); + assert(move _9, "index out of bounds: the length is {} but the index is {}", 10_usize, _7) -> [success: bb3, unwind unreachable]; } bb3: { - _7 = _2[_8]; - _13 = &_3; - _14 = &_7; - _12 = (move _13, move _14); - _15 = (_12.0: &u8); - _16 = (_12.1: &u8); - _18 = (*_15); - _19 = (*_16); - _17 = Eq(move _18, move _19); - switchInt(move _17) -> [0: bb5, otherwise: bb4]; + _6 = _2[_7]; + _11 = &_3; + _12 = &_6; + _10 = (move _11, move _12); + _13 = (_10.0: &u8); + _14 = (_10.1: &u8); + _16 = (*_13); + _17 = (*_14); + _15 = Eq(move _16, move _17); + switchInt(move _15) -> [0: bb5, otherwise: bb4]; } bb4: { - _23 = &_3; - _24 = (*_23); - _26 = &_24; - _27 = &_3; - _25 = (move _26, move _27); - _28 = (_25.0: &u8); - _29 = (_25.1: &u8); - _31 = (*_28); - _32 = (*_29); - _30 = Eq(move _31, move _32); - switchInt(move _30) -> [0: bb7, otherwise: bb6]; + _21 = &_3; + _22 = (*_21); + _24 = &_22; + _25 = &_3; + _23 = (move _24, move _25); + _26 = (_23.0: &u8); + _27 = (_23.1: &u8); + _29 = (*_26); + _30 = (*_27); + _28 = Eq(move _29, move _30); + switchInt(move _28) -> [0: bb7, otherwise: bb6]; } bb5: { - _20 = core::panicking::AssertKind::Eq; - _22 = std::option::Option::None; - _21 = core::panicking::assert_failed::<u8, u8>(move _20, _15, _16, move _22) -> unwind unreachable; + _18 = core::panicking::AssertKind::Eq; + _20 = std::option::Option::None; + _19 = core::panicking::assert_failed::<u8, u8>(move _18, _13, _14, move _20) -> unwind unreachable; } bb6: { - _36 = (_3, _7); - _37 = (_36.0: u8); - _38 = (_36.0: u8); - _40 = &_37; - _41 = &_38; - _39 = (move _40, move _41); - _42 = (_39.0: &u8); - _43 = (_39.1: &u8); - _45 = (*_42); - _46 = (*_43); - _44 = Eq(move _45, move _46); - switchInt(move _44) -> [0: bb9, otherwise: bb8]; + _34 = (_3, _6); + _35 = (_34.0: u8); + _36 = (_34.0: u8); + _38 = &_35; + _39 = &_36; + _37 = (move _38, move _39); + _40 = (_37.0: &u8); + _41 = (_37.1: &u8); + _43 = (*_40); + _44 = (*_41); + _42 = Eq(move _43, move _44); + switchInt(move _42) -> [0: bb9, otherwise: bb8]; } bb7: { - _33 = core::panicking::AssertKind::Eq; - _35 = std::option::Option::None; - _34 = core::panicking::assert_failed::<u8, u8>(move _33, _28, _29, move _35) -> unwind unreachable; + _31 = core::panicking::AssertKind::Eq; + _33 = std::option::Option::None; + _32 = core::panicking::assert_failed::<u8, u8>(move _31, _26, _27, move _33) -> unwind unreachable; } bb8: { - _52 = &_2; - _51 = move _52 as &[u8]; - _50 = PtrMetadata(move _51); - _54 = &_50; - _53 = std::mem::size_of_val::<usize>(_54) -> [return: bb10, unwind unreachable]; + _50 = &_2; + _49 = move _50 as &[u8]; + _48 = PtrMetadata(move _49); + _52 = &_48; + _51 = std::mem::size_of_val::<usize>(_52) -> [return: bb10, unwind unreachable]; } bb9: { - _47 = core::panicking::AssertKind::Eq; - _49 = std::option::Option::None; - _48 = core::panicking::assert_failed::<u8, u8>(move _47, _42, _43, move _49) -> unwind unreachable; + _45 = core::panicking::AssertKind::Eq; + _47 = std::option::Option::None; + _46 = core::panicking::assert_failed::<u8, u8>(move _45, _40, _41, move _47) -> unwind unreachable; } bb10: { - _56 = &_50; - _57 = &_53; - _55 = (move _56, move _57); - _58 = (_55.0: &usize); - _59 = (_55.1: &usize); - _61 = (*_58); - _62 = (*_59); - _60 = Eq(move _61, move _62); - switchInt(move _60) -> [0: bb12, otherwise: bb11]; + _54 = &_48; + _55 = &_51; + _53 = (move _54, move _55); + _56 = (_53.0: &usize); + _57 = (_53.1: &usize); + _59 = (*_56); + _60 = (*_57); + _58 = Eq(move _59, move _60); + switchInt(move _58) -> [0: bb12, otherwise: bb11]; } bb11: { return; } bb12: { - _63 = core::panicking::AssertKind::Eq; - _65 = std::option::Option::None; - _64 = core::panicking::assert_failed::<usize, usize>(move _63, _58, _59, move _65) -> unwind unreachable; + _61 = core::panicking::AssertKind::Eq; + _63 = std::option::Option::None; + _62 = core::panicking::assert_failed::<usize, usize>(move _61, _56, _57, move _63) -> unwind unreachable; } } fn operands::{constant#0}() -> usize { diff --git a/tests/ui/static/issue-24446.stderr b/tests/ui/static/issue-24446.stderr index 9c206e5ef3c..8cb034000be 100644 --- a/tests/ui/static/issue-24446.stderr +++ b/tests/ui/static/issue-24446.stderr @@ -20,10 +20,7 @@ error[E0277]: the size for values of type `(dyn Fn() -> u32 + 'static)` cannot b | LL | static foo: dyn Fn() -> u32 = || -> u32 { | ___________________________________^ -LL | | -LL | | -LL | | -LL | | +... | LL | | 0 LL | | }; | |_____^ doesn't have a size known at compile-time @@ -36,10 +33,7 @@ error[E0308]: mismatched types | LL | static foo: dyn Fn() -> u32 = || -> u32 { | ___________________________________^ -LL | | -LL | | -LL | | -LL | | +... | LL | | 0 LL | | }; | |_____^ expected `dyn Fn`, found closure diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr index eb9f9196a72..beafd7c2ab0 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr @@ -32,8 +32,8 @@ error[E0307]: invalid `self` parameter type: `()` LL | fn bar(self: ()) {} | ^^ | - = note: type of `self` must be `Self` or some type implementing `Receiver` - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/if-then-neeing-semi.stderr b/tests/ui/suggestions/if-then-neeing-semi.stderr index 6833e0bab2b..0556d6c50b1 100644 --- a/tests/ui/suggestions/if-then-neeing-semi.stderr +++ b/tests/ui/suggestions/if-then-neeing-semi.stderr @@ -6,12 +6,10 @@ LL | let _ = if true { LL | | LL | | async_dummy(); | | -------------- expected because of this -LL | | -LL | | } else { +... | LL | | async_dummy() | | ^^^^^^^^^^^^^ expected `()`, found future ... | -LL | | LL | | }; | |_____- `if` and `else` have incompatible types | @@ -38,12 +36,10 @@ LL | let _ = if true { LL | | LL | | async_dummy(); | | -------------- expected because of this -LL | | -LL | | } else { +... | LL | | async_dummy2() | | ^^^^^^^^^^^^^^ expected `()`, found future ... | -LL | | LL | | }; | |_____- `if` and `else` have incompatible types | @@ -72,12 +68,10 @@ LL | let _ = if true { LL | | LL | | async_dummy() | | ------------- expected because of this -LL | | -LL | | } else { +... | LL | | async_dummy2() | | ^^^^^^^^^^^^^^ expected future, found a different future -LL | | -LL | | +... | LL | | }; | |_____- `if` and `else` have incompatible types | @@ -101,8 +95,7 @@ LL | | dummy(); | | | | | | | help: consider removing this semicolon | | expected because of this -LL | | -LL | | } else { +... | LL | | dummy() | | ^^^^^^^ expected `()`, found `i32` LL | | diff --git a/tests/ui/suggestions/match-prev-arm-needing-semi.stderr b/tests/ui/suggestions/match-prev-arm-needing-semi.stderr index cf3cf45ef40..f70f6a1e157 100644 --- a/tests/ui/suggestions/match-prev-arm-needing-semi.stderr +++ b/tests/ui/suggestions/match-prev-arm-needing-semi.stderr @@ -6,12 +6,10 @@ LL | let _ = match true { LL | | true => { LL | | async_dummy(); | | -------------- this is found to be of type `()` -LL | | -LL | | } +... | LL | | false => async_dummy(), | | ^^^^^^^^^^^^^ expected `()`, found future ... | -LL | | LL | | }; | |_____- `match` arms have incompatible types | @@ -38,12 +36,10 @@ LL | let _ = match true { LL | | true => { LL | | async_dummy(); | | -------------- this is found to be of type `()` -LL | | -LL | | } +... | LL | | false => async_dummy2(), | | ^^^^^^^^^^^^^^ expected `()`, found future ... | -LL | | LL | | }; | |_____- `match` arms have incompatible types | @@ -74,8 +70,7 @@ LL | | true => async_dummy(), LL | | LL | | false => async_dummy2(), | | ^^^^^^^^^^^^^^ expected future, found a different future -LL | | -LL | | +... | LL | | }; | |_____- `match` arms have incompatible types | @@ -98,8 +93,7 @@ LL | | dummy(); | | | | | | | help: consider removing this semicolon | | this is found to be of type `()` -LL | | -LL | | } +... | LL | | false => dummy(), | | ^^^^^^^ expected `()`, found `i32` LL | | diff --git a/tests/ui/suggestions/suggest-deref-in-match-issue-132784.rs b/tests/ui/suggestions/suggest-deref-in-match-issue-132784.rs new file mode 100644 index 00000000000..205e57f4a9f --- /dev/null +++ b/tests/ui/suggestions/suggest-deref-in-match-issue-132784.rs @@ -0,0 +1,84 @@ +use std::sync::Arc; +fn main() { + let mut x = Arc::new(Some(1)); + match x { + //~^ HELP consider dereferencing to access the inner value using the Deref trait + //~| HELP consider dereferencing to access the inner value using the Deref trait + Some(_) => {} + //~^ ERROR mismatched types + None => {} + //~^ ERROR mismatched types + } + + match &x { + //~^ HELP consider dereferencing to access the inner value using the Deref trait + //~| HELP consider dereferencing to access the inner value using the Deref trait + Some(_) => {} + //~^ ERROR mismatched types + None => {} + //~^ ERROR mismatched types + } + + let mut y = Box::new(Some(1)); + match y { + //~^ HELP consider dereferencing to access the inner value using the Deref trait + //~| HELP consider dereferencing to access the inner value using the Deref trait + Some(_) => {} + //~^ ERROR mismatched types + None => {} + //~^ ERROR mismatched types + } + + let mut z = Arc::new(Some(1)); + match z as Arc<Option<i32>> { + //~^ HELP consider dereferencing to access the inner value using the Deref trait + //~| HELP consider dereferencing to access the inner value using the Deref trait + Some(_) => {} + //~^ ERROR mismatched types + None => {} + //~^ ERROR mismatched types + } + + let z_const: &Arc<Option<i32>> = &z; + match z_const { + //~^ HELP consider dereferencing to access the inner value using the Deref trait + //~| HELP consider dereferencing to access the inner value using the Deref trait + Some(_) => {} + //~^ ERROR mismatched types + None => {} + //~^ ERROR mismatched types + } + + // Normal reference because Arc doesn't implement DerefMut. + let z_mut: &mut Arc<Option<i32>> = &mut z; + match z_mut { + //~^ HELP consider dereferencing to access the inner value using the Deref trait + //~| HELP consider dereferencing to access the inner value using the Deref trait + Some(_) => {} + //~^ ERROR mismatched types + None => {} + //~^ ERROR mismatched types + } + + // Mutable reference because Box does implement DerefMut. + let y_mut: &mut Box<Option<i32>> = &mut y; + match y_mut { + //~^ HELP consider dereferencing to access the inner value using the Deref trait + //~| HELP consider dereferencing to access the inner value using the Deref trait + Some(_) => {} + //~^ ERROR mismatched types + None => {} + //~^ ERROR mismatched types + } + + // Difficult expression. + let difficult = Arc::new(Some(1)); + match (& (&difficult) ) { + //~^ HELP consider dereferencing to access the inner value using the Deref trait + //~| HELP consider dereferencing to access the inner value using the Deref trait + Some(_) => {} + //~^ ERROR mismatched types + None => {} + //~^ ERROR mismatched types + } +} diff --git a/tests/ui/suggestions/suggest-deref-in-match-issue-132784.stderr b/tests/ui/suggestions/suggest-deref-in-match-issue-132784.stderr new file mode 100644 index 00000000000..9338ef19089 --- /dev/null +++ b/tests/ui/suggestions/suggest-deref-in-match-issue-132784.stderr @@ -0,0 +1,259 @@ +error[E0308]: mismatched types + --> $DIR/suggest-deref-in-match-issue-132784.rs:7:9 + | +LL | match x { + | - this expression has type `Arc<Option<{integer}>>` +... +LL | Some(_) => {} + | ^^^^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>` + | + = note: expected struct `Arc<Option<{integer}>>` + found enum `Option<_>` +help: consider dereferencing to access the inner value using the Deref trait + | +LL | match *x { + | ~~ + +error[E0308]: mismatched types + --> $DIR/suggest-deref-in-match-issue-132784.rs:9:9 + | +LL | match x { + | - this expression has type `Arc<Option<{integer}>>` +... +LL | None => {} + | ^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>` + | + = note: expected struct `Arc<Option<{integer}>>` + found enum `Option<_>` +help: consider dereferencing to access the inner value using the Deref trait + | +LL | match *x { + | ~~ + +error[E0308]: mismatched types + --> $DIR/suggest-deref-in-match-issue-132784.rs:16:9 + | +LL | match &x { + | -- this expression has type `&Arc<Option<{integer}>>` +... +LL | Some(_) => {} + | ^^^^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>` + | + = note: expected struct `Arc<Option<{integer}>>` + found enum `Option<_>` +help: consider dereferencing to access the inner value using the Deref trait + | +LL | match &*x { + | ~~~ + +error[E0308]: mismatched types + --> $DIR/suggest-deref-in-match-issue-132784.rs:18:9 + | +LL | match &x { + | -- this expression has type `&Arc<Option<{integer}>>` +... +LL | None => {} + | ^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>` + | + = note: expected struct `Arc<Option<{integer}>>` + found enum `Option<_>` +help: consider dereferencing to access the inner value using the Deref trait + | +LL | match &*x { + | ~~~ + +error[E0308]: mismatched types + --> $DIR/suggest-deref-in-match-issue-132784.rs:26:9 + | +LL | match y { + | - this expression has type `Box<Option<{integer}>>` +... +LL | Some(_) => {} + | ^^^^^^^ expected `Box<Option<{integer}>>`, found `Option<_>` + | + = note: expected struct `Box<Option<{integer}>>` + found enum `Option<_>` +help: consider dereferencing to access the inner value using the Deref trait + | +LL | match *y { + | ~~ + +error[E0308]: mismatched types + --> $DIR/suggest-deref-in-match-issue-132784.rs:28:9 + | +LL | match y { + | - this expression has type `Box<Option<{integer}>>` +... +LL | None => {} + | ^^^^ expected `Box<Option<{integer}>>`, found `Option<_>` + | + = note: expected struct `Box<Option<{integer}>>` + found enum `Option<_>` +help: consider dereferencing to access the inner value using the Deref trait + | +LL | match *y { + | ~~ + +error[E0308]: mismatched types + --> $DIR/suggest-deref-in-match-issue-132784.rs:36:9 + | +LL | match z as Arc<Option<i32>> { + | --------------------- this expression has type `Arc<Option<i32>>` +... +LL | Some(_) => {} + | ^^^^^^^ expected `Arc<Option<i32>>`, found `Option<_>` + | + = note: expected struct `Arc<Option<i32>>` + found enum `Option<_>` +help: consider dereferencing to access the inner value using the Deref trait + | +LL | match *(z as Arc<Option<i32>>) { + | ~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/suggest-deref-in-match-issue-132784.rs:38:9 + | +LL | match z as Arc<Option<i32>> { + | --------------------- this expression has type `Arc<Option<i32>>` +... +LL | None => {} + | ^^^^ expected `Arc<Option<i32>>`, found `Option<_>` + | + = note: expected struct `Arc<Option<i32>>` + found enum `Option<_>` +help: consider dereferencing to access the inner value using the Deref trait + | +LL | match *(z as Arc<Option<i32>>) { + | ~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/suggest-deref-in-match-issue-132784.rs:46:9 + | +LL | match z_const { + | ------- this expression has type `&Arc<Option<i32>>` +... +LL | Some(_) => {} + | ^^^^^^^ expected `Arc<Option<i32>>`, found `Option<_>` + | + = note: expected struct `Arc<Option<i32>>` + found enum `Option<_>` +help: consider dereferencing to access the inner value using the Deref trait + | +LL | match &**z_const { + | ~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/suggest-deref-in-match-issue-132784.rs:48:9 + | +LL | match z_const { + | ------- this expression has type `&Arc<Option<i32>>` +... +LL | None => {} + | ^^^^ expected `Arc<Option<i32>>`, found `Option<_>` + | + = note: expected struct `Arc<Option<i32>>` + found enum `Option<_>` +help: consider dereferencing to access the inner value using the Deref trait + | +LL | match &**z_const { + | ~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/suggest-deref-in-match-issue-132784.rs:57:9 + | +LL | match z_mut { + | ----- this expression has type `&mut Arc<Option<i32>>` +... +LL | Some(_) => {} + | ^^^^^^^ expected `Arc<Option<i32>>`, found `Option<_>` + | + = note: expected struct `Arc<Option<i32>>` + found enum `Option<_>` +help: consider dereferencing to access the inner value using the Deref trait + | +LL | match &**z_mut { + | ~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/suggest-deref-in-match-issue-132784.rs:59:9 + | +LL | match z_mut { + | ----- this expression has type `&mut Arc<Option<i32>>` +... +LL | None => {} + | ^^^^ expected `Arc<Option<i32>>`, found `Option<_>` + | + = note: expected struct `Arc<Option<i32>>` + found enum `Option<_>` +help: consider dereferencing to access the inner value using the Deref trait + | +LL | match &**z_mut { + | ~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/suggest-deref-in-match-issue-132784.rs:68:9 + | +LL | match y_mut { + | ----- this expression has type `&mut Box<Option<i32>>` +... +LL | Some(_) => {} + | ^^^^^^^ expected `Box<Option<i32>>`, found `Option<_>` + | + = note: expected struct `Box<Option<i32>>` + found enum `Option<_>` +help: consider dereferencing to access the inner value using the Deref trait + | +LL | match &**y_mut { + | ~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/suggest-deref-in-match-issue-132784.rs:70:9 + | +LL | match y_mut { + | ----- this expression has type `&mut Box<Option<i32>>` +... +LL | None => {} + | ^^^^ expected `Box<Option<i32>>`, found `Option<_>` + | + = note: expected struct `Box<Option<i32>>` + found enum `Option<_>` +help: consider dereferencing to access the inner value using the Deref trait + | +LL | match &**y_mut { + | ~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/suggest-deref-in-match-issue-132784.rs:79:9 + | +LL | match (& (&difficult) ) { + | ------------------ this expression has type `&&Arc<Option<{integer}>>` +... +LL | Some(_) => {} + | ^^^^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>` + | + = note: expected struct `Arc<Option<{integer}>>` + found enum `Option<_>` +help: consider dereferencing to access the inner value using the Deref trait + | +LL | match &*difficult { + | ~~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/suggest-deref-in-match-issue-132784.rs:81:9 + | +LL | match (& (&difficult) ) { + | ------------------ this expression has type `&&Arc<Option<{integer}>>` +... +LL | None => {} + | ^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>` + | + = note: expected struct `Arc<Option<{integer}>>` + found enum `Option<_>` +help: consider dereferencing to access the inner value using the Deref trait + | +LL | match &*difficult { + | ~~~~~~~~~~~ + +error: aborting due to 16 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr index 939285498fb..a275f0c2fa8 100644 --- a/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr +++ b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr @@ -13,9 +13,7 @@ LL | / if true { LL | | LL | | x? | | ^^ expected `()`, found integer -LL | | -LL | | -LL | | +... | LL | | } | |_____- expected this to be `()` | diff --git a/tests/ui/symbol-names/types.legacy.stderr b/tests/ui/symbol-names/types.legacy.stderr index 87c3acae0bd..c368b318609 100644 --- a/tests/ui/symbol-names/types.legacy.stderr +++ b/tests/ui/symbol-names/types.legacy.stderr @@ -502,5 +502,23 @@ error: demangling-alt(a::b::Type<[T; N]>) LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 84 previous errors +error: symbol-name(_ZN1a1b35Type$LT$$u5b$u8$u3b$$u20$0$u5d$$GT$17h[HASH]E) + --> $DIR/types.rs:272:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type<[u8; 0]>::h[HASH]) + --> $DIR/types.rs:272:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type<[u8; 0]>) + --> $DIR/types.rs:272:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 87 previous errors diff --git a/tests/ui/symbol-names/types.rs b/tests/ui/symbol-names/types.rs index 7ed19e0e5a8..38735e1aa50 100644 --- a/tests/ui/symbol-names/types.rs +++ b/tests/ui/symbol-names/types.rs @@ -266,6 +266,17 @@ pub fn b() { //[v0]~| ERROR ::b::Type<[_; _]>>) //[v0]~| ERROR demangling-alt(<a::b::Type<[_; _]>>) impl<const N: usize, T> Type<[T; N]> {} + + const ZERO: usize = 0; + + #[rustc_symbol_name] + //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b35Type$LT$$u5b$u8$u3b$$u20$0$u5d$$GT$ + //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<[u8; 0]>:: + //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<[u8; 0]>) + //[v0]~^^^^ ERROR symbol-name(_RMsq_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeAhj0_E) + //[v0]~| ERROR ::b::Type<[u8; 0usize]>>) + //[v0]~| ERROR demangling-alt(<a::b::Type<[u8; 0]>>) + impl Type<[u8; ZERO]> {} } fn main() {} diff --git a/tests/ui/symbol-names/types.v0.stderr b/tests/ui/symbol-names/types.v0.stderr index 58680e00202..90012a2dcf7 100644 --- a/tests/ui/symbol-names/types.v0.stderr +++ b/tests/ui/symbol-names/types.v0.stderr @@ -502,5 +502,23 @@ error: demangling-alt(<a::b::Type<[_; _]>>) LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 84 previous errors +error: symbol-name(_RMsq_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeAhj0_E) + --> $DIR/types.rs:272:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(<a[HASH]::b::Type<[u8; 0usize]>>) + --> $DIR/types.rs:272:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(<a::b::Type<[u8; 0]>>) + --> $DIR/types.rs:272:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 87 previous errors diff --git a/tests/ui/symbol-names/types.verbose-legacy.stderr b/tests/ui/symbol-names/types.verbose-legacy.stderr index 87c3acae0bd..c368b318609 100644 --- a/tests/ui/symbol-names/types.verbose-legacy.stderr +++ b/tests/ui/symbol-names/types.verbose-legacy.stderr @@ -502,5 +502,23 @@ error: demangling-alt(a::b::Type<[T; N]>) LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 84 previous errors +error: symbol-name(_ZN1a1b35Type$LT$$u5b$u8$u3b$$u20$0$u5d$$GT$17h[HASH]E) + --> $DIR/types.rs:272:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type<[u8; 0]>::h[HASH]) + --> $DIR/types.rs:272:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type<[u8; 0]>) + --> $DIR/types.rs:272:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 87 previous errors diff --git a/tests/ui/target-feature/allowed-softfloat-target-feature-attribute.rs b/tests/ui/target-feature/allowed-softfloat-target-feature-attribute.rs new file mode 100644 index 00000000000..8b60820cc9b --- /dev/null +++ b/tests/ui/target-feature/allowed-softfloat-target-feature-attribute.rs @@ -0,0 +1,11 @@ +//@ compile-flags: --target=x86_64-unknown-none --crate-type=lib +//@ needs-llvm-components: x86 +//@ build-pass +#![feature(no_core, lang_items, x87_target_feature)] +#![no_core] + +#[lang = "sized"] +pub trait Sized {} + +#[target_feature(enable = "x87")] +pub unsafe fn my_fun() {} diff --git a/tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.rs b/tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.rs new file mode 100644 index 00000000000..e34faf5a983 --- /dev/null +++ b/tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.rs @@ -0,0 +1,9 @@ +//@ compile-flags: --target=x86_64-unknown-none --crate-type=lib +//@ needs-llvm-components: x86 +//@ compile-flags: -Ctarget-feature=-x87 +//@ build-pass +#![feature(no_core, lang_items)] +#![no_core] + +#[lang = "sized"] +pub trait Sized {} diff --git a/tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.stderr b/tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.stderr new file mode 100644 index 00000000000..309b64afd92 --- /dev/null +++ b/tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.stderr @@ -0,0 +1,6 @@ +warning: unstable feature specified for `-Ctarget-feature`: `x87` + | + = note: this feature is not stably supported; its behavior can change in the future + +warning: 1 warning emitted + diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute.rs b/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute.rs new file mode 100644 index 00000000000..b3171d52c51 --- /dev/null +++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute.rs @@ -0,0 +1,11 @@ +//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib +//@ needs-llvm-components: x86 +#![feature(no_core, lang_items)] +#![no_core] + +#[lang = "sized"] +pub trait Sized {} + +#[target_feature(enable = "x87")] +//~^ERROR: cannot be toggled with +pub unsafe fn my_fun() {} diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute.stderr b/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute.stderr new file mode 100644 index 00000000000..3ebbe69d8ae --- /dev/null +++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute.stderr @@ -0,0 +1,8 @@ +error: target feature `x87` cannot be toggled with `#[target_feature]`: unsound on hard-float targets because it changes float ABI + --> $DIR/forbidden-hardfloat-target-feature-attribute.rs:9:18 + | +LL | #[target_feature(enable = "x87")] + | ^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-cfg.rs b/tests/ui/target-feature/forbidden-hardfloat-target-feature-cfg.rs new file mode 100644 index 00000000000..8755791c1c0 --- /dev/null +++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-cfg.rs @@ -0,0 +1,14 @@ +//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib +//@ needs-llvm-components: x86 +//@ check-pass +#![feature(no_core, lang_items)] +#![no_core] +#![allow(unexpected_cfgs)] + +#[lang = "sized"] +pub trait Sized {} + +// The compile_error macro does not exist, so if the `cfg` evaluates to `true` this +// complains about the missing macro rather than showing the error... but that's good enough. +#[cfg(not(target_feature = "x87"))] +compile_error!("the x87 feature *should* be exposed in `cfg`"); diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.rs b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.rs new file mode 100644 index 00000000000..fd8023664da --- /dev/null +++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.rs @@ -0,0 +1,10 @@ +//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib +//@ needs-llvm-components: x86 +//@ compile-flags: -Ctarget-feature=-x87 +// For now this is just a warning. +//@ build-pass +#![feature(no_core, lang_items)] +#![no_core] + +#[lang = "sized"] +pub trait Sized {} diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.stderr b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.stderr new file mode 100644 index 00000000000..604ad2f991a --- /dev/null +++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.stderr @@ -0,0 +1,7 @@ +warning: target feature `x87` cannot be toggled with `-Ctarget-feature`: unsound on hard-float targets because it changes float ABI + | + = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344> + +warning: 1 warning emitted + diff --git a/tests/ui/target-feature/forbidden-target-feature-attribute.rs b/tests/ui/target-feature/forbidden-target-feature-attribute.rs index 91c56b43689..f13cdd17da6 100644 --- a/tests/ui/target-feature/forbidden-target-feature-attribute.rs +++ b/tests/ui/target-feature/forbidden-target-feature-attribute.rs @@ -1,7 +1,6 @@ //@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib //@ needs-llvm-components: x86 #![feature(no_core, lang_items)] -#![no_std] #![no_core] #[lang = "sized"] diff --git a/tests/ui/target-feature/forbidden-target-feature-attribute.stderr b/tests/ui/target-feature/forbidden-target-feature-attribute.stderr index fb318531f7e..27ac4aaf960 100644 --- a/tests/ui/target-feature/forbidden-target-feature-attribute.stderr +++ b/tests/ui/target-feature/forbidden-target-feature-attribute.stderr @@ -1,5 +1,5 @@ error: target feature `soft-float` cannot be toggled with `#[target_feature]`: unsound because it changes float ABI - --> $DIR/forbidden-target-feature-attribute.rs:10:18 + --> $DIR/forbidden-target-feature-attribute.rs:9:18 | LL | #[target_feature(enable = "soft-float")] | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/target-feature/forbidden-target-feature-cfg.rs b/tests/ui/target-feature/forbidden-target-feature-cfg.rs index 5df26e26793..1f001e9f8ff 100644 --- a/tests/ui/target-feature/forbidden-target-feature-cfg.rs +++ b/tests/ui/target-feature/forbidden-target-feature-cfg.rs @@ -2,7 +2,6 @@ //@ needs-llvm-components: x86 //@ check-pass #![feature(no_core, lang_items)] -#![no_std] #![no_core] #![allow(unexpected_cfgs)] diff --git a/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs b/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs index b27e8a10afe..b09c53bd46a 100644 --- a/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs +++ b/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs @@ -4,7 +4,6 @@ // For now this is just a warning. //@ build-pass #![feature(no_core, lang_items)] -#![no_std] #![no_core] #[lang = "sized"] diff --git a/tests/ui/target-feature/forbidden-target-feature-flag.rs b/tests/ui/target-feature/forbidden-target-feature-flag.rs index 93cebc6b536..0f688fde7f4 100644 --- a/tests/ui/target-feature/forbidden-target-feature-flag.rs +++ b/tests/ui/target-feature/forbidden-target-feature-flag.rs @@ -4,7 +4,6 @@ // For now this is just a warning. //@ build-pass #![feature(no_core, lang_items)] -#![no_std] #![no_core] #[lang = "sized"] diff --git a/tests/ui/target-feature/gate.rs b/tests/ui/target-feature/gate.rs index f35fbd11155..2626685fa0a 100644 --- a/tests/ui/target-feature/gate.rs +++ b/tests/ui/target-feature/gate.rs @@ -24,6 +24,7 @@ // gate-test-prfchw_target_feature // gate-test-s390x_target_feature // gate-test-sparc_target_feature +// gate-test-x87_target_feature #[target_feature(enable = "avx512bw")] //~^ ERROR: currently unstable diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr index b84bab370be..ba5ae79f942 100644 --- a/tests/ui/target-feature/gate.stderr +++ b/tests/ui/target-feature/gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `avx512bw` is currently unstable - --> $DIR/gate.rs:28:18 + --> $DIR/gate.rs:29:18 | LL | #[target_feature(enable = "avx512bw")] | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/ice-120503-async-const-method.stderr b/tests/ui/traits/const-traits/ice-120503-async-const-method.stderr index 66862d97bf9..e499451d897 100644 --- a/tests/ui/traits/const-traits/ice-120503-async-const-method.stderr +++ b/tests/ui/traits/const-traits/ice-120503-async-const-method.stderr @@ -26,11 +26,7 @@ LL | async const fn bar(&self) { | | | _____`async` because of this | | -LL | | -LL | | -LL | | ... | -LL | | LL | | } | |_____- @@ -38,11 +34,7 @@ error[E0407]: method `bar` is not a member of trait `MyTrait` --> $DIR/ice-120503-async-const-method.rs:6:5 | LL | / async const fn bar(&self) { -LL | | -LL | | -LL | | ... | -LL | | LL | | } | |_____^ not a member of trait `MyTrait` diff --git a/tests/ui/traits/issue-78372.stderr b/tests/ui/traits/issue-78372.stderr index 1c58915111f..86234d15a5d 100644 --- a/tests/ui/traits/issue-78372.stderr +++ b/tests/ui/traits/issue-78372.stderr @@ -61,8 +61,8 @@ error[E0307]: invalid `self` parameter type: `Smaht<Self, T>` LL | fn foo(self: Smaht<Self, T>); | ^^^^^^^^^^^^^^ | - = note: type of `self` must be `Self` or some type implementing `Receiver` - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures --> $DIR/issue-78372.rs:3:1 diff --git a/tests/ui/transmutability/alignment/align-fail.stderr b/tests/ui/transmutability/alignment/align-fail.stderr index b9801e511b2..7b69820a3c6 100644 --- a/tests/ui/transmutability/alignment/align-fail.stderr +++ b/tests/ui/transmutability/alignment/align-fail.stderr @@ -16,7 +16,6 @@ LL | | Assume { LL | | alignment: false, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_maybe_transmutable` help: consider removing the leading `&`-reference diff --git a/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr b/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr index c975ff276c8..7e5d0a6d412 100644 --- a/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr +++ b/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr @@ -16,7 +16,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_transmutable` @@ -38,7 +37,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_transmutable` @@ -60,7 +58,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_transmutable` @@ -82,7 +79,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_transmutable` @@ -104,7 +100,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_transmutable` @@ -126,7 +121,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_transmutable` @@ -148,7 +142,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_transmutable` @@ -170,7 +163,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_transmutable` @@ -192,7 +184,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_transmutable` @@ -214,7 +205,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_transmutable` @@ -236,7 +226,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_transmutable` @@ -258,7 +247,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_transmutable` @@ -280,7 +268,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_transmutable` @@ -302,7 +289,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_transmutable` @@ -324,7 +310,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_transmutable` @@ -346,7 +331,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_transmutable` @@ -368,7 +352,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_transmutable` @@ -390,7 +373,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_transmutable` @@ -412,7 +394,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_transmutable` @@ -434,7 +415,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_transmutable` diff --git a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.stderr b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.stderr index 1698021d554..8d3ab4868da 100644 --- a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.stderr +++ b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.stderr @@ -16,7 +16,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: false, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_maybe_transmutable` diff --git a/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.stderr b/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.stderr index dbd3e39b365..8651f40f3fb 100644 --- a/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.stderr +++ b/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.stderr @@ -16,7 +16,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: false, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_maybe_transmutable` diff --git a/tests/ui/transmutability/references/unit-to-u8.stderr b/tests/ui/transmutability/references/unit-to-u8.stderr index b5a79b1917f..bc9f286e097 100644 --- a/tests/ui/transmutability/references/unit-to-u8.stderr +++ b/tests/ui/transmutability/references/unit-to-u8.stderr @@ -16,7 +16,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_maybe_transmutable` diff --git a/tests/ui/transmutability/uninhabited.stderr b/tests/ui/transmutability/uninhabited.stderr index f112d2fbe44..b8b7b67f781 100644 --- a/tests/ui/transmutability/uninhabited.stderr +++ b/tests/ui/transmutability/uninhabited.stderr @@ -40,7 +40,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_maybe_transmutable` @@ -62,7 +61,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_maybe_transmutable` @@ -84,7 +82,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_maybe_transmutable` @@ -106,7 +103,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_maybe_transmutable` @@ -128,7 +124,6 @@ LL | | Assume { LL | | alignment: true, LL | | lifetimes: true, ... | -LL | | } LL | | }> | |__________^ required by this bound in `is_maybe_transmutable` diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr b/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr index 8888f2d49df..c7c93eee63e 100644 --- a/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr +++ b/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr @@ -24,10 +24,7 @@ error: item does not constrain `Bar::{opaque#0}`, but has it in its signature | LL | async fn test<const N: crate::Bar>() { | ______________________________________^ -LL | | -LL | | -LL | | -LL | | #[cfg(infer)] +... | LL | | let x: u32 = N; LL | | } | |_^ diff --git a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr index be68bac5575..8547fd53c18 100644 --- a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr +++ b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr @@ -31,8 +31,7 @@ note: this definition site has more where clauses than the opaque type | LL | / pub fn define_tait() -> Tait LL | | where -LL | | // this proves `Bar<()>: Copy`, but `define_tait` is -LL | | // now uncallable +... | LL | | (): Proj<Assoc = i32>, | |______________________________^ diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr index 08ebc3208d7..293c8ea09f1 100644 --- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr +++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr @@ -15,8 +15,7 @@ error: item does not constrain `FutNothing::{opaque#0}`, but has it in its signa --> $DIR/hkl_forbidden4.rs:22:1 | LL | / { -LL | | -LL | | +... | LL | | } | |_^ | @@ -55,8 +54,7 @@ LL | type FutNothing<'a> = impl 'a + Future<Output = ()>; | -- this generic parameter must be used with a generic lifetime parameter ... LL | / { -LL | | -LL | | +... | LL | | } | |_^ diff --git a/tests/ui/typeck/issue-100285.stderr b/tests/ui/typeck/issue-100285.stderr index 6f86fd18e0f..388510b7704 100644 --- a/tests/ui/typeck/issue-100285.stderr +++ b/tests/ui/typeck/issue-100285.stderr @@ -8,7 +8,6 @@ LL | | if n < 0 { LL | | return i; LL | | } else if n < 10 { ... | -LL | | LL | | } | |_____^ expected `i32`, found `()` | diff --git a/tests/ui/typeck/issue-104513-ice.stderr b/tests/ui/typeck/issue-104513-ice.stderr index 37d38a76a40..c3872ea8968 100644 --- a/tests/ui/typeck/issue-104513-ice.stderr +++ b/tests/ui/typeck/issue-104513-ice.stderr @@ -11,6 +11,9 @@ LL | let _: S<impl Oops> = S; | ^^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods + = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information + = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 2 previous errors diff --git a/tests/ui/typeck/rhs-ty-hint-134162.e2018.stderr b/tests/ui/typeck/rhs-ty-hint-134162.e2018.stderr new file mode 100644 index 00000000000..ff189e36ba0 --- /dev/null +++ b/tests/ui/typeck/rhs-ty-hint-134162.e2018.stderr @@ -0,0 +1,11 @@ +error[E0369]: binary operation `==` cannot be applied to type `[X; 1]` + --> $DIR/rhs-ty-hint-134162.rs:16:17 + | +LL | let _ = [X] == [panic!(); 2]; + | --- ^^ ------------- [_; 2] + | | + | [X; 1] + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/typeck/rhs-ty-hint-134162.e2021.stderr b/tests/ui/typeck/rhs-ty-hint-134162.e2021.stderr new file mode 100644 index 00000000000..ff189e36ba0 --- /dev/null +++ b/tests/ui/typeck/rhs-ty-hint-134162.e2021.stderr @@ -0,0 +1,11 @@ +error[E0369]: binary operation `==` cannot be applied to type `[X; 1]` + --> $DIR/rhs-ty-hint-134162.rs:16:17 + | +LL | let _ = [X] == [panic!(); 2]; + | --- ^^ ------------- [_; 2] + | | + | [X; 1] + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/typeck/rhs-ty-hint-134162.e2024.stderr b/tests/ui/typeck/rhs-ty-hint-134162.e2024.stderr new file mode 100644 index 00000000000..ff189e36ba0 --- /dev/null +++ b/tests/ui/typeck/rhs-ty-hint-134162.e2024.stderr @@ -0,0 +1,11 @@ +error[E0369]: binary operation `==` cannot be applied to type `[X; 1]` + --> $DIR/rhs-ty-hint-134162.rs:16:17 + | +LL | let _ = [X] == [panic!(); 2]; + | --- ^^ ------------- [_; 2] + | | + | [X; 1] + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/typeck/rhs-ty-hint-134162.rs b/tests/ui/typeck/rhs-ty-hint-134162.rs new file mode 100644 index 00000000000..a14b4bcfd26 --- /dev/null +++ b/tests/ui/typeck/rhs-ty-hint-134162.rs @@ -0,0 +1,18 @@ +//! Regression test for <https://github.com/rust-lang/rust/issues/134162>. +//! +//! <https://github.com/rust-lang/rust/pull/110877> introduced RHS type hints for when a ty doesn't +//! support a bin op. In the suggestion path, there was a `delay_bug`. +//! <https://github.com/rust-lang/rust/pull/121208> converted this `delay_bug` to `bug`, which did +//! not trigger any test failures as we did not have test coverage for this particular case. This +//! manifested in an ICE as reported in <https://github.com/rust-lang/rust/issues/134162>. + +//@ revisions: e2018 e2021 e2024 +//@[e2018] edition: 2018 +//@[e2021] edition: 2021 +//@[e2024] edition: 2024 + +fn main() { + struct X; + let _ = [X] == [panic!(); 2]; + //[e2018,e2021,e2024]~^ ERROR binary operation `==` cannot be applied to type `[X; 1]` +} diff --git a/tests/ui/ufcs/ufcs-explicit-self-bad.stderr b/tests/ui/ufcs/ufcs-explicit-self-bad.stderr index 36bdc714e05..2a8c4edbdb5 100644 --- a/tests/ui/ufcs/ufcs-explicit-self-bad.stderr +++ b/tests/ui/ufcs/ufcs-explicit-self-bad.stderr @@ -22,8 +22,8 @@ error[E0307]: invalid `self` parameter type: `isize` LL | fn foo(self: isize, x: isize) -> isize { | ^^^^^ | - = note: type of `self` must be `Self` or some type implementing `Receiver` - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) error[E0307]: invalid `self` parameter type: `Bar<isize>` --> $DIR/ufcs-explicit-self-bad.rs:19:18 @@ -31,8 +31,8 @@ error[E0307]: invalid `self` parameter type: `Bar<isize>` LL | fn foo(self: Bar<isize>, x: isize) -> isize { | ^^^^^^^^^^ | - = note: type of `self` must be `Self` or some type implementing `Receiver` - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) error[E0307]: invalid `self` parameter type: `&Bar<usize>` --> $DIR/ufcs-explicit-self-bad.rs:23:18 @@ -40,8 +40,8 @@ error[E0307]: invalid `self` parameter type: `&Bar<usize>` LL | fn bar(self: &Bar<usize>, x: isize) -> isize { | ^^^^^^^^^^^ | - = note: type of `self` must be `Self` or some type implementing `Receiver` - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) error[E0308]: mismatched `self` parameter type --> $DIR/ufcs-explicit-self-bad.rs:37:21 diff --git a/tests/ui/unsafe-binders/expr.rs b/tests/ui/unsafe-binders/expr.rs new file mode 100644 index 00000000000..d8c4c2df2cd --- /dev/null +++ b/tests/ui/unsafe-binders/expr.rs @@ -0,0 +1,13 @@ +#![feature(unsafe_binders)] +//~^ WARN the feature `unsafe_binders` is incomplete + +use std::unsafe_binder::{wrap_binder, unwrap_binder}; + +fn main() { + let x = 1; + let binder: unsafe<'a> &'a i32 = wrap_binder!(x); + //~^ ERROR unsafe binders are not yet implemented + //~| ERROR unsafe binders are not yet implemented + let rx = *unwrap_binder!(binder); + //~^ ERROR unsafe binders are not yet implemented +} diff --git a/tests/ui/unsafe-binders/expr.stderr b/tests/ui/unsafe-binders/expr.stderr new file mode 100644 index 00000000000..26fae1958b0 --- /dev/null +++ b/tests/ui/unsafe-binders/expr.stderr @@ -0,0 +1,29 @@ +warning: the feature `unsafe_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/expr.rs:1:12 + | +LL | #![feature(unsafe_binders)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: unsafe binders are not yet implemented + --> $DIR/expr.rs:8:17 + | +LL | let binder: unsafe<'a> &'a i32 = wrap_binder!(x); + | ^^^^^^^^^^^^^^^^^^ + +error: unsafe binders are not yet implemented + --> $DIR/expr.rs:8:51 + | +LL | let binder: unsafe<'a> &'a i32 = wrap_binder!(x); + | ^ + +error: unsafe binders are not yet implemented + --> $DIR/expr.rs:11:30 + | +LL | let rx = *unwrap_binder!(binder); + | ^^^^^^ + +error: aborting due to 3 previous errors; 1 warning emitted + diff --git a/tests/ui/unsafe-binders/lifetime-resolution.rs b/tests/ui/unsafe-binders/lifetime-resolution.rs new file mode 100644 index 00000000000..aebed9599d4 --- /dev/null +++ b/tests/ui/unsafe-binders/lifetime-resolution.rs @@ -0,0 +1,19 @@ +#![feature(unsafe_binders)] +//~^ WARN the feature `unsafe_binders` is incomplete + +fn foo<'a>() { + let good: unsafe<'b> &'a &'b (); + //~^ ERROR unsafe binders are not yet implemented + + let missing: unsafe<> &'missing (); + //~^ ERROR unsafe binders are not yet implemented + //~| ERROR use of undeclared lifetime name `'missing` + + fn inner<'b>() { + let outer: unsafe<> &'a &'b (); + //~^ ERROR unsafe binders are not yet implemented + //~| can't use generic parameters from outer item + } +} + +fn main() {} diff --git a/tests/ui/unsafe-binders/lifetime-resolution.stderr b/tests/ui/unsafe-binders/lifetime-resolution.stderr new file mode 100644 index 00000000000..7a8ce929df1 --- /dev/null +++ b/tests/ui/unsafe-binders/lifetime-resolution.stderr @@ -0,0 +1,65 @@ +error[E0261]: use of undeclared lifetime name `'missing` + --> $DIR/lifetime-resolution.rs:8:28 + | +LL | let missing: unsafe<> &'missing (); + | ^^^^^^^^ undeclared lifetime + | + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the type lifetime-generic with a new `'missing` lifetime + | +LL | let missing: unsafe<'missing, > &'missing (); + | +++++++++ +help: consider introducing lifetime `'missing` here + | +LL | fn foo<'missing, 'a>() { + | +++++++++ + +error[E0401]: can't use generic parameters from outer item + --> $DIR/lifetime-resolution.rs:13:30 + | +LL | fn foo<'a>() { + | -- lifetime parameter from outer item +... +LL | let outer: unsafe<> &'a &'b (); + | ^^ use of generic parameter from outer item + | +help: consider making the type lifetime-generic with a new `'a` lifetime + | +LL | let outer: unsafe<'a, > &'a &'b (); + | +++ +help: consider introducing lifetime `'a` here + | +LL | fn inner<'a, 'b>() { + | +++ + +warning: the feature `unsafe_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/lifetime-resolution.rs:1:12 + | +LL | #![feature(unsafe_binders)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: unsafe binders are not yet implemented + --> $DIR/lifetime-resolution.rs:5:15 + | +LL | let good: unsafe<'b> &'a &'b (); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: unsafe binders are not yet implemented + --> $DIR/lifetime-resolution.rs:8:18 + | +LL | let missing: unsafe<> &'missing (); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: unsafe binders are not yet implemented + --> $DIR/lifetime-resolution.rs:13:20 + | +LL | let outer: unsafe<> &'a &'b (); + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0261, E0401. +For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/unsafe-binders/simple.rs b/tests/ui/unsafe-binders/simple.rs new file mode 100644 index 00000000000..cebff2cbfb8 --- /dev/null +++ b/tests/ui/unsafe-binders/simple.rs @@ -0,0 +1,7 @@ +#![feature(unsafe_binders)] +//~^ WARN the feature `unsafe_binders` is incomplete + +fn main() { + let x: unsafe<'a> &'a (); + //~^ ERROR unsafe binders are not yet implemented +} diff --git a/tests/ui/unsafe-binders/simple.stderr b/tests/ui/unsafe-binders/simple.stderr new file mode 100644 index 00000000000..a21dbd00b4c --- /dev/null +++ b/tests/ui/unsafe-binders/simple.stderr @@ -0,0 +1,17 @@ +warning: the feature `unsafe_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/simple.rs:1:12 + | +LL | #![feature(unsafe_binders)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: unsafe binders are not yet implemented + --> $DIR/simple.rs:5:12 + | +LL | let x: unsafe<'a> &'a (); + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error; 1 warning emitted + diff --git a/tests/ui/while/while-else-err.stderr b/tests/ui/while/while-else-err.stderr index b937956108f..face0c73925 100644 --- a/tests/ui/while/while-else-err.stderr +++ b/tests/ui/while/while-else-err.stderr @@ -6,8 +6,7 @@ LL | while false { LL | LL | } else { | _______^ -LL | | -LL | | +... | LL | | }; | |_____^ | diff --git a/tests/ui/while/while-else-let-else-err.stderr b/tests/ui/while/while-else-let-else-err.stderr index 27d68ffdb24..4fc99409f78 100644 --- a/tests/ui/while/while-else-let-else-err.stderr +++ b/tests/ui/while/while-else-let-else-err.stderr @@ -6,8 +6,7 @@ LL | let _ = while false { LL | LL | } else { | _______^ -LL | | -LL | | +... | LL | | }; | |_____^ | |
