From 9f089e080c47bc282aa98f1e8c72ff44076afbb9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 27 Mar 2025 09:33:02 +1100 Subject: [PATCH 01/23] Add `{ast,hir,thir}::PatKind::Missing` variants. "Missing" patterns are possible in bare fn types (`fn f(u32)`) and similar places. Currently these are represented in the AST with `ast::PatKind::Ident` with no `by_ref`, no `mut`, an empty ident, and no sub-pattern. This flows through to `{hir,thir}::PatKind::Binding` for HIR and THIR. This is a bit nasty. It's very non-obvious, and easy to forget to check for the exceptional empty identifier case. This commit adds a new variant, `PatKind::Missing`, to do it properly. The process I followed: - Add a `Missing` variant to `{ast,hir,thir}::PatKind`. - Chang `parse_param_general` to produce `ast::PatKind::Missing` instead of `ast::PatKind::Missing`. - Look through `kw::Empty` occurrences to find functions where an existing empty ident check needs replacing with a `PatKind::Missing` check: `print_param`, `check_trait_item`, `is_named_param`. - Add a `PatKind::Missing => unreachable!(),` arm to every exhaustive match identified by the compiler. - Find which arms are actually reachable by running the test suite, changing them to something appropriate, usually by looking at what would happen to a `PatKind::Ident`/`PatKind::Binding` with no ref, no `mut`, an empty ident, and no subpattern. Quite a few of the `unreachable!()` arms were never reached. This makes sense because `PatKind::Missing` can't happen in every pattern, only in places like bare fn tys and trait fn decls. I also tried an alternative approach: modifying `ast::Param::pat` to hold an `Option>` instead of a `P`, but that quickly turned into a very large and painful change. Adding `PatKind::Missing` is much easier. --- compiler/rustc_ast/src/ast.rs | 8 +++++- compiler/rustc_ast/src/mut_visit.rs | 2 +- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_ast_lowering/src/lib.rs | 3 ++- compiler/rustc_ast_lowering/src/pat.rs | 1 + .../rustc_ast_passes/src/ast_validation.rs | 2 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 11 +++----- compiler/rustc_hir/src/hir.rs | 6 ++++- compiler/rustc_hir/src/intravisit.rs | 2 +- .../rustc_hir_analysis/src/check/region.rs | 1 + compiler/rustc_hir_pretty/src/lib.rs | 1 + compiler/rustc_hir_typeck/src/expr.rs | 3 ++- .../rustc_hir_typeck/src/expr_use_visitor.rs | 2 ++ compiler/rustc_hir_typeck/src/pat.rs | 11 +++++--- compiler/rustc_lint/src/builtin.rs | 26 +++++++++---------- compiler/rustc_lint/src/unused.rs | 3 ++- compiler/rustc_middle/src/thir.rs | 3 +++ compiler/rustc_middle/src/thir/visit.rs | 3 ++- .../src/builder/matches/match_pair.rs | 2 +- .../src/builder/matches/mod.rs | 1 + .../rustc_mir_build/src/check_unsafety.rs | 1 + .../rustc_mir_build/src/thir/pattern/mod.rs | 2 ++ compiler/rustc_mir_build/src/thir/print.rs | 1 + compiler/rustc_parse/src/parser/item.rs | 4 +-- compiler/rustc_passes/src/input_stats.rs | 2 ++ compiler/rustc_pattern_analysis/src/rustc.rs | 2 +- src/librustdoc/clean/utils.rs | 1 + .../clippy_lints/src/equatable_if_let.rs | 1 + .../src/matches/match_same_arms.rs | 1 + .../clippy_lints/src/matches/single_match.rs | 1 + .../clippy_lints/src/unnested_or_patterns.rs | 1 + .../clippy/clippy_lints/src/utils/author.rs | 1 + .../clippy/clippy_utils/src/ast_utils/mod.rs | 1 + .../clippy/clippy_utils/src/hir_utils.rs | 1 + src/tools/clippy/clippy_utils/src/lib.rs | 1 + src/tools/rustfmt/src/items.rs | 6 +---- src/tools/rustfmt/src/patterns.rs | 2 ++ tests/ui/macros/stringify.rs | 2 ++ tests/ui/unpretty/expanded-exhaustive.rs | 5 ++++ tests/ui/unpretty/expanded-exhaustive.stdout | 3 +++ 40 files changed, 86 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 064f05ef1f3ef..944ae65ffc679 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -563,6 +563,7 @@ impl Pat { /// This is intended for use by diagnostics. pub fn to_ty(&self) -> Option> { let kind = match &self.kind { + PatKind::Missing => unreachable!(), // In a type expression `_` is an inference variable. PatKind::Wild => TyKind::Infer, // An IDENT pattern with no binding mode would be valid as path to a type. E.g. `u32`. @@ -625,7 +626,8 @@ impl Pat { | PatKind::Guard(s, _) => s.walk(it), // These patterns do not contain subpatterns, skip. - PatKind::Wild + PatKind::Missing + | PatKind::Wild | PatKind::Rest | PatKind::Never | PatKind::Expr(_) @@ -676,6 +678,7 @@ impl Pat { /// Return a name suitable for diagnostics. pub fn descr(&self) -> Option { match &self.kind { + PatKind::Missing => unreachable!(), PatKind::Wild => Some("_".to_string()), PatKind::Ident(BindingMode::NONE, ident, None) => Some(format!("{ident}")), PatKind::Ref(pat, mutbl) => pat.descr().map(|d| format!("&{}{d}", mutbl.prefix_str())), @@ -769,6 +772,9 @@ pub enum RangeSyntax { // Adding a new variant? Please update `test_pat` in `tests/ui/macros/stringify.rs`. #[derive(Clone, Encodable, Decodable, Debug)] pub enum PatKind { + /// A missing pattern, e.g. for an anonymous param in a bare fn like `fn f(u32)`. + Missing, + /// Represents a wildcard pattern (`_`). Wild, diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 274fe312f7fad..8c6ddf2a69c9a 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1572,7 +1572,7 @@ pub fn walk_pat(vis: &mut T, pat: &mut P) { vis.visit_id(id); match kind { PatKind::Err(_guar) => {} - PatKind::Wild | PatKind::Rest | PatKind::Never => {} + PatKind::Missing | PatKind::Wild | PatKind::Rest | PatKind::Never => {} PatKind::Ident(_binding_mode, ident, sub) => { vis.visit_ident(ident); visit_opt(sub, |sub| vis.visit_pat(sub)); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 2716601ca4f9d..3d78f65f634bf 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -727,7 +727,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Res try_visit!(visitor.visit_pat(subpattern)); try_visit!(visitor.visit_expr(guard_condition)); } - PatKind::Wild | PatKind::Rest | PatKind::Never => {} + PatKind::Missing | PatKind::Wild | PatKind::Rest | PatKind::Never => {} PatKind::Err(_guar) => {} PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => { walk_list!(visitor, visit_pat, elems); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index ced9064fd9f41..4041e5d092aa8 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1495,6 +1495,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Option] { self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind { + PatKind::Missing => None, PatKind::Ident(_, ident, _) => { if ident.name != kw::Empty { Some(self.lower_ident(ident)) @@ -1506,7 +1507,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { _ => { self.dcx().span_delayed_bug( param.pat.span, - "non-ident/wild param pat must trigger an error", + "non-missing/ident/wild param pat must trigger an error", ); None } diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 07cc64a1358ee..f94d788a9b0e6 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -26,6 +26,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let pat_hir_id = self.lower_node_id(pattern.id); let node = loop { match &pattern.kind { + PatKind::Missing => break hir::PatKind::Missing, PatKind::Wild => break hir::PatKind::Wild, PatKind::Never => break hir::PatKind::Never, PatKind::Ident(binding_mode, ident, sub) => { diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index a1487ca74be87..ab6d4644f7e94 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -239,7 +239,7 @@ impl<'a> AstValidator<'a> { fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option, bool)) { for Param { pat, .. } in &decl.inputs { match pat.kind { - PatKind::Ident(BindingMode::NONE, _, None) | PatKind::Wild => {} + PatKind::Missing | PatKind::Ident(BindingMode::NONE, _, None) | PatKind::Wild => {} PatKind::Ident(BindingMode::MUT, ident, None) => { report_err(pat.span, Some(ident), true) } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index cdb1817944987..f9e17fb0539d8 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1622,9 +1622,9 @@ impl<'a> State<'a> { fn print_pat(&mut self, pat: &ast::Pat) { self.maybe_print_comment(pat.span.lo()); self.ann.pre(self, AnnNode::Pat(pat)); - /* Pat isn't normalized, but the beauty of it - is that it doesn't matter */ + /* Pat isn't normalized, but the beauty of it is that it doesn't matter */ match &pat.kind { + PatKind::Missing => unreachable!(), PatKind::Wild => self.word("_"), PatKind::Never => self.word("!"), PatKind::Ident(BindingMode(by_ref, mutbl), ident, sub) => { @@ -1946,12 +1946,7 @@ impl<'a> State<'a> { if let Some(eself) = input.to_self() { self.print_explicit_self(&eself); } else { - let invalid = if let PatKind::Ident(_, ident, _) = input.pat.kind { - ident.name == kw::Empty - } else { - false - }; - if !invalid { + if !matches!(input.pat.kind, PatKind::Missing) { self.print_pat(&input.pat); self.word(":"); self.space(); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 751c379b21a64..08e37accb8a30 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1516,6 +1516,7 @@ impl<'hir> Pat<'hir> { use PatKind::*; match self.kind { + Missing => unreachable!(), Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => true, Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_short_(it), Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)), @@ -1543,7 +1544,7 @@ impl<'hir> Pat<'hir> { use PatKind::*; match self.kind { - Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => {} + Missing | Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => {} Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_(it), Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)), TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)), @@ -1681,6 +1682,9 @@ pub enum TyPatKind<'hir> { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum PatKind<'hir> { + /// A missing pattern, e.g. for an anonymous param in a bare fn like `fn f(u32)`. + Missing, + /// Represents a wildcard pattern (i.e., `_`). Wild, diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 506358341b501..ea3f396761b16 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -744,7 +744,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V: visit_opt!(visitor, visit_pat_expr, lower_bound); visit_opt!(visitor, visit_pat_expr, upper_bound); } - PatKind::Never | PatKind::Wild | PatKind::Err(_) => (), + PatKind::Missing | PatKind::Never | PatKind::Wild | PatKind::Err(_) => (), PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => { walk_list!(visitor, visit_pat, prepatterns); visit_opt!(visitor, visit_pat, slice_pattern); diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 255f5fee52a80..d63fef8c0ef26 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -701,6 +701,7 @@ fn resolve_local<'tcx>( PatKind::Ref(_, _) | PatKind::Binding(hir::BindingMode(hir::ByRef::No, _), ..) + | PatKind::Missing | PatKind::Wild | PatKind::Never | PatKind::Expr(_) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index ddaca89ccf82d..a4961fc2c8506 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1875,6 +1875,7 @@ impl<'a> State<'a> { // Pat isn't normalized, but the beauty of it // is that it doesn't matter match pat.kind { + PatKind::Missing => unreachable!(), PatKind::Wild => self.word("_"), PatKind::Never => self.word("!"), PatKind::Binding(BindingMode(by_ref, mutbl), _, ident, sub) => { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index a75f6f4caac91..0ed03a03c1b48 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -482,7 +482,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // All of these constitute a read, or match on something that isn't `!`, // which would require a `NeverToAny` coercion. - hir::PatKind::Binding(_, _, _, _) + hir::PatKind::Missing + | hir::PatKind::Binding(_, _, _, _) | hir::PatKind::Struct(_, _, _) | hir::PatKind::TupleStruct(_, _, _) | hir::PatKind::Tuple(_, _) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index c71a5ea8b9761..d50f235ad4d10 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -611,6 +611,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx for pat in pats { self.cat_pattern(discr_place.clone(), pat, &mut |place, pat| { match &pat.kind { + PatKind::Missing => unreachable!(), PatKind::Binding(.., opt_sub_pat) => { // If the opt_sub_pat is None, then the binding does not count as // a wildcard for the purpose of borrowing discr. @@ -1884,6 +1885,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx | PatKind::Expr(..) | PatKind::Range(..) | PatKind::Never + | PatKind::Missing | PatKind::Wild | PatKind::Err(_) => { // always ok diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index f1f956779c94f..0d4ecbc867b73 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -341,7 +341,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let ty = match pat.kind { - PatKind::Wild | PatKind::Err(_) => expected, + PatKind::Missing | PatKind::Wild | PatKind::Err(_) => expected, // We allow any type here; we ensure that the type is uninhabited during match checking. PatKind::Never => expected, PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => { @@ -505,9 +505,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, // Ref patterns are complicated, we handle them in `check_pat_ref`. - PatKind::Ref(..) => AdjustMode::Pass, + PatKind::Ref(..) + // No need to do anything on a missing pattern. + | PatKind::Missing // A `_` pattern works with any expected type, so there's no need to do anything. - PatKind::Wild + | PatKind::Wild // A malformed pattern doesn't have an expected type, so let's just accept any type. | PatKind::Err(_) // Bindings also work with whatever the expected type is, @@ -1037,7 +1039,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | PatKind::Tuple(..) | PatKind::Slice(..) => "binding", - PatKind::Wild + PatKind::Missing + | PatKind::Wild | PatKind::Never | PatKind::Binding(..) | PatKind::Box(..) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 9dccd4a0552c3..0b5cdf99de5aa 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -778,21 +778,19 @@ impl EarlyLintPass for AnonymousParameters { } if let ast::AssocItemKind::Fn(box Fn { ref sig, .. }) = it.kind { for arg in sig.decl.inputs.iter() { - if let ast::PatKind::Ident(_, ident, None) = arg.pat.kind { - if ident.name == kw::Empty { - let ty_snip = cx.sess().source_map().span_to_snippet(arg.ty.span); + if let ast::PatKind::Missing = arg.pat.kind { + let ty_snip = cx.sess().source_map().span_to_snippet(arg.ty.span); - let (ty_snip, appl) = if let Ok(ref snip) = ty_snip { - (snip.as_str(), Applicability::MachineApplicable) - } else { - ("", Applicability::HasPlaceholders) - }; - cx.emit_span_lint( - ANONYMOUS_PARAMETERS, - arg.pat.span, - BuiltinAnonymousParams { suggestion: (arg.pat.span, appl), ty_snip }, - ); - } + let (ty_snip, appl) = if let Ok(ref snip) = ty_snip { + (snip.as_str(), Applicability::MachineApplicable) + } else { + ("", Applicability::HasPlaceholders) + }; + cx.emit_span_lint( + ANONYMOUS_PARAMETERS, + arg.pat.span, + BuiltinAnonymousParams { suggestion: (arg.pat.span, appl), ty_snip }, + ); } } } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 7b43aac90c741..806bca78f7875 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1201,7 +1201,8 @@ impl EarlyLintPass for UnusedParens { // Do not lint on `(..)` as that will result in the other arms being useless. Paren(_) // The other cases do not contain sub-patterns. - | Wild | Never | Rest | Expr(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) | Err(_) => {}, + | Missing | Wild | Never | Rest | Expr(..) | MacCall(..) | Range(..) | Ident(.., None) + | Path(..) | Err(_) => {}, // These are list-like patterns; parens can always be removed. TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps { self.check_unused_parens_pat(cx, p, false, false, keep_space); diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 6783bbf8bf42f..413717e45ebfa 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -747,6 +747,9 @@ pub struct Ascription<'tcx> { #[derive(Clone, Debug, HashStable, TypeVisitable)] pub enum PatKind<'tcx> { + /// A missing pattern, e.g. for an anonymous param in a bare fn like `fn f(u32)`. + Missing, + /// A wildcard pattern: `_`. Wild, diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 7d62ab7970d01..f3da2a5cc8e4e 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -250,7 +250,8 @@ pub(crate) fn for_each_immediate_subpat<'a, 'tcx>( mut callback: impl FnMut(&'a Pat<'tcx>), ) { match &pat.kind { - PatKind::Wild + PatKind::Missing + | PatKind::Wild | PatKind::Binding { subpattern: None, .. } | PatKind::Constant { value: _ } | PatKind::Range(_) diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index 29d400a957b47..11672163b658f 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -118,7 +118,7 @@ impl<'tcx> MatchPairTree<'tcx> { let place = place_builder.try_to_place(cx); let mut subpairs = Vec::new(); let test_case = match pattern.kind { - PatKind::Wild | PatKind::Error(_) => None, + PatKind::Missing | PatKind::Wild | PatKind::Error(_) => None, PatKind::Or { ref pats } => Some(TestCase::Or { pats: pats.iter().map(|pat| FlatPat::new(place_builder.clone(), pat, cx)).collect(), diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index 3acf2a6a2a61a..977d4f3e931b5 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -920,6 +920,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { PatKind::Constant { .. } | PatKind::Range { .. } + | PatKind::Missing | PatKind::Wild | PatKind::Never | PatKind::Error(_) => {} diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 7f2e7d5ca8385..9572dfc52dac8 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -313,6 +313,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { fn visit_pat(&mut self, pat: &'a Pat<'tcx>) { if self.in_union_destructure { match pat.kind { + PatKind::Missing => unreachable!(), // binding to a variable allows getting stuff out of variable PatKind::Binding { .. } // match is conditional on having this value diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 4bfeab44bf4b9..f36a895849a14 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -290,6 +290,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let mut span = pat.span; let kind = match pat.kind { + hir::PatKind::Missing => PatKind::Missing, + hir::PatKind::Wild => PatKind::Wild, hir::PatKind::Never => PatKind::Never, diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 16cef0ec3acbc..ac71bb845a886 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -664,6 +664,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { print_indented!(self, "kind: PatKind {", depth_lvl); match pat_kind { + PatKind::Missing => unreachable!(), PatKind::Wild => { print_indented!(self, "Wild", depth_lvl + 1); } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index aad1857837554..0f5d8d9fbedd4 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2941,9 +2941,7 @@ impl<'a> Parser<'a> { } match ty { Ok(ty) => { - let ident = Ident::new(kw::Empty, this.prev_token.span); - let bm = BindingMode::NONE; - let pat = this.mk_pat_ident(ty.span, bm, ident); + let pat = this.mk_pat(ty.span, PatKind::Missing); (pat, ty) } // If this is a C-variadic argument and we hit an error, return the error. diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index 1278e98afcf61..7181544817225 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -295,6 +295,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { record_variants!( (self, p, p.kind, Some(p.hir_id), hir, Pat, PatKind), [ + Missing, Wild, Binding, Struct, @@ -597,6 +598,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { record_variants!( (self, p, p.kind, None, ast, Pat, PatKind), [ + Missing, Wild, Ident, Struct, diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index a25a80cd45f74..e815273405244 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -457,7 +457,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { PatKind::AscribeUserType { subpattern, .. } | PatKind::ExpandedConstant { subpattern, .. } => return self.lower_pat(subpattern), PatKind::Binding { subpattern: Some(subpat), .. } => return self.lower_pat(subpat), - PatKind::Binding { subpattern: None, .. } | PatKind::Wild => { + PatKind::Missing | PatKind::Binding { subpattern: None, .. } | PatKind::Wild => { ctor = Wildcard; fields = vec![]; arity = 0; diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index f81db58950cbd..afcca81a485ff 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -304,6 +304,7 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { Symbol::intern(&match &p.kind { // FIXME(never_patterns): does this make sense? + PatKind::Missing => unreachable!(), PatKind::Wild | PatKind::Err(_) | PatKind::Never diff --git a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs index cd9ab2764ac48..3afb687040f45 100644 --- a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs +++ b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs @@ -45,6 +45,7 @@ fn unary_pattern(pat: &Pat<'_>) -> bool { pats.iter().all(unary_pattern) } match &pat.kind { + PatKind::Missing => unreachable!(), PatKind::Slice(_, _, _) | PatKind::Range(_, _, _) | PatKind::Binding(..) diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs index 250f17fa9025a..a21597ffb93d7 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs @@ -253,6 +253,7 @@ fn iter_matching_struct_fields<'a>( impl<'a> NormalizedPat<'a> { fn from_pat(cx: &LateContext<'_>, arena: &'a DroplessArena, pat: &'a Pat<'_>) -> Self { match pat.kind { + PatKind::Missing => unreachable!(), PatKind::Wild | PatKind::Binding(.., None) => Self::Wild, PatKind::Binding(.., Some(pat)) | PatKind::Box(pat) diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs index 56fbd626eefc4..836c46240ce7b 100644 --- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs @@ -406,6 +406,7 @@ impl<'a> PatState<'a> { pats.iter().map(|p| p.pat), ), + PatKind::Missing => unreachable!(), PatKind::Wild | PatKind::Binding(_, _, _, None) | PatKind::Expr(_) diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs index f43715d6752e3..8966e6851ac2f 100644 --- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs @@ -224,6 +224,7 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec>, focus_idx: us // We're trying to find whatever kind (~"constructor") we found in `alternatives[start..]`. let changed = match &mut focus_kind { + Missing => unreachable!(), // These pattern forms are "leafs" and do not have sub-patterns. // Therefore they are not some form of constructor `C`, // with which a pattern `C(p_0)` may be formed, diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 4309cd2c9abdf..b7dcd2ffb0eea 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -676,6 +676,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { } match pat.value.kind { + PatKind::Missing => unreachable!(), PatKind::Wild => kind!("Wild"), PatKind::Never => kind!("Never"), PatKind::Binding(ann, _, name, sub) => { diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs index 6023ae9cc7b16..ed99f966d2b76 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs @@ -33,6 +33,7 @@ pub fn eq_id(l: Ident, r: Ident) -> bool { pub fn eq_pat(l: &Pat, r: &Pat) -> bool { use PatKind::*; match (&l.kind, &r.kind) { + (Missing, _) | (_, Missing) => unreachable!(), (Paren(l), _) => eq_pat(l, r), (_, Paren(r)) => eq_pat(l, r), (Wild, Wild) | (Rest, Rest) => true, diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 9938e64d24264..b813cd361ed8c 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -1124,6 +1124,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { pub fn hash_pat(&mut self, pat: &Pat<'_>) { std::mem::discriminant(&pat.kind).hash(&mut self.s); match pat.kind { + PatKind::Missing => unreachable!(), PatKind::Binding(BindingMode(by_ref, mutability), _, _, pat) => { std::mem::discriminant(&by_ref).hash(&mut self.s); std::mem::discriminant(&mutability).hash(&mut self.s); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 1307ff79bc5dd..bdcbe1437d0e2 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -1857,6 +1857,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool { } match pat.kind { + PatKind::Missing => unreachable!(), PatKind::Wild | PatKind::Never => false, // If `!` typechecked then the type is empty, so not refutable. PatKind::Binding(_, _, _, pat) => pat.is_some_and(|pat| is_refutable(cx, pat)), PatKind::Box(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat), diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 3fb3284e3d7fd..81ff6327a4fc0 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -2433,11 +2433,7 @@ pub(crate) fn span_hi_for_param(context: &RewriteContext<'_>, param: &ast::Param } pub(crate) fn is_named_param(param: &ast::Param) -> bool { - if let ast::PatKind::Ident(_, ident, _) = param.pat.kind { - ident.name != symbol::kw::Empty - } else { - true - } + !matches!(param.pat.kind, ast::PatKind::Missing) } #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs index bafed41e39f42..8ec3de286dcb7 100644 --- a/src/tools/rustfmt/src/patterns.rs +++ b/src/tools/rustfmt/src/patterns.rs @@ -42,6 +42,7 @@ pub(crate) fn is_short_pattern( fn is_short_pattern_inner(context: &RewriteContext<'_>, pat: &ast::Pat) -> bool { match &pat.kind { + ast::PatKind::Missing => unreachable!(), ast::PatKind::Rest | ast::PatKind::Never | ast::PatKind::Wild | ast::PatKind::Err(_) => { true } @@ -100,6 +101,7 @@ impl Rewrite for Pat { fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { match self.kind { + PatKind::Missing => unreachable!(), PatKind::Or(ref pats) => { let pat_strs = pats .iter() diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs index 40033f546d30b..3490d3efc5992 100644 --- a/tests/ui/macros/stringify.rs +++ b/tests/ui/macros/stringify.rs @@ -515,6 +515,8 @@ fn test_meta() { #[test] fn test_pat() { + // PatKind::Missing: untestable in isolation. + // PatKind::Wild c1!(pat, [ _ ], "_"); diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs index 31af323ecdab5..4d1f12e349001 100644 --- a/tests/ui/unpretty/expanded-exhaustive.rs +++ b/tests/ui/unpretty/expanded-exhaustive.rs @@ -574,6 +574,11 @@ mod items { } mod patterns { + /// PatKind::Missing + fn pat_missing() { + let _: fn(u32, T, &str); + } + /// PatKind::Wild fn pat_wild() { let _; diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout index 19ae66f7a07aa..d8da941a34077 100644 --- a/tests/ui/unpretty/expanded-exhaustive.stdout +++ b/tests/ui/unpretty/expanded-exhaustive.stdout @@ -361,6 +361,7 @@ mod expressions { + { builtin # offset_of(T, field) }; @@ -517,6 +518,8 @@ mod items { } } mod patterns { + /// PatKind::Missing + fn pat_missing() { let _: fn(u32, T, &str); } /// PatKind::Wild fn pat_wild() { let _; } /// PatKind::Ident From 909f4492475988ba5e1b84efadacb16eb7d7ff0e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 27 Mar 2025 17:00:27 +1100 Subject: [PATCH 02/23] Remove `kw::Extra` checks that are no longer necessary. Thanks to the introduction of `PatKind::Missing`. --- compiler/rustc_ast_lowering/src/lib.rs | 8 +------- compiler/rustc_passes/src/liveness.rs | 5 +---- compiler/rustc_resolve/src/late.rs | 13 ++++--------- 3 files changed, 6 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4041e5d092aa8..a3e0f96031613 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1496,13 +1496,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Option] { self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind { PatKind::Missing => None, - PatKind::Ident(_, ident, _) => { - if ident.name != kw::Empty { - Some(self.lower_ident(ident)) - } else { - None - } - } + PatKind::Ident(_, ident, _) => Some(self.lower_ident(ident)), PatKind::Wild => Some(Ident::new(kw::Underscore, self.lower_span(param.pat.span))), _ => { self.dcx().span_delayed_bug( diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index ed70d9ee91f5a..07e3b28bcf658 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -96,7 +96,7 @@ use rustc_middle::query::Providers; use rustc_middle::span_bug; use rustc_middle::ty::{self, RootVariableMinCaptureList, Ty, TyCtxt}; use rustc_session::lint; -use rustc_span::{BytePos, Span, Symbol, kw, sym}; +use rustc_span::{BytePos, Span, Symbol, sym}; use tracing::{debug, instrument}; use self::LiveNodeKind::*; @@ -1481,9 +1481,6 @@ impl<'tcx> Liveness<'_, 'tcx> { fn should_warn(&self, var: Variable) -> Option { let name = self.ir.variable_name(var); - if name == kw::Empty { - return None; - } let name = name.as_str(); if name.as_bytes()[0] == b'_' { return None; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 533e216ddb291..117d2ccdde380 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3999,22 +3999,17 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.report_error(ident.span, error(ident)); } - // Record as bound if it's valid: - let ident_valid = ident.name != kw::Empty; - if ident_valid { - bindings.last_mut().unwrap().1.insert(ident); - } + // Record as bound. + bindings.last_mut().unwrap().1.insert(ident); if already_bound_or { // `Variant1(a) | Variant2(a)`, ok // Reuse definition from the first `a`. self.innermost_rib_bindings(ValueNS)[&ident] } else { + // A completely fresh binding is added to the set. let res = Res::Local(pat_id); - if ident_valid { - // A completely fresh binding add to the set if it's valid. - self.innermost_rib_bindings(ValueNS).insert(ident, res); - } + self.innermost_rib_bindings(ValueNS).insert(ident, res); res } } From 3123df8ef0cc32318d96b90620396d8b22d2ffb3 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 27 Mar 2025 18:29:58 +0100 Subject: [PATCH 03/23] Implement `super let`. --- compiler/rustc_ast/src/ast.rs | 3 +- compiler/rustc_ast/src/mut_visit.rs | 3 +- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_ast_lowering/src/block.rs | 3 +- compiler/rustc_ast_lowering/src/lib.rs | 1 + compiler/rustc_ast_pretty/src/pprust/state.rs | 3 + compiler/rustc_expand/src/build.rs | 2 + compiler/rustc_hir/src/hir.rs | 4 +- .../rustc_hir_analysis/src/check/region.rs | 91 +++++++++++++++---- compiler/rustc_hir_pretty/src/lib.rs | 10 +- .../rustc_hir_typeck/src/gather_locals.rs | 2 +- compiler/rustc_parse/src/parser/stmt.rs | 14 +-- tests/ui/stats/input-stats.stderr | 36 ++++---- 13 files changed, 126 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 97e6879c33e99..78cc663a8e379 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1169,6 +1169,7 @@ pub enum MacStmtStyle { #[derive(Clone, Encodable, Decodable, Debug)] pub struct Local { pub id: NodeId, + pub super_: Option, pub pat: P, pub ty: Option>, pub kind: LocalKind, @@ -3926,7 +3927,7 @@ mod size_asserts { static_assert_size!(Item, 144); static_assert_size!(ItemKind, 80); static_assert_size!(LitKind, 24); - static_assert_size!(Local, 80); + static_assert_size!(Local, 96); static_assert_size!(MetaItemLit, 40); static_assert_size!(Param, 40); static_assert_size!(Pat, 72); diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index f7d13acdfc402..58af024dc1639 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -704,7 +704,8 @@ fn walk_parenthesized_parameter_data(vis: &mut T, args: &mut Pare } fn walk_local(vis: &mut T, local: &mut P) { - let Local { id, pat, ty, kind, span, colon_sp, attrs, tokens } = local.deref_mut(); + let Local { id, super_, pat, ty, kind, span, colon_sp, attrs, tokens } = local.deref_mut(); + visit_opt(super_, |sp| vis.visit_span(sp)); vis.visit_id(id); visit_attrs(vis, attrs); vis.visit_pat(pat); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 1ef92ff8898ef..37e32671b2948 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -323,7 +323,7 @@ pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) -> V::R } pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) -> V::Result { - let Local { id: _, pat, ty, kind, span: _, colon_sp: _, attrs, tokens: _ } = local; + let Local { id: _, super_: _, pat, ty, kind, span: _, colon_sp: _, attrs, tokens: _ } = local; walk_list!(visitor, visit_attribute, attrs); try_visit!(visitor.visit_pat(pat)); visit_opt!(visitor, visit_ty, ty); diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 1d9ca6bb9c8cb..c3222b79e55c9 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -95,6 +95,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_local(&mut self, l: &Local) -> &'hir hir::LetStmt<'hir> { // Let statements are allowed to have impl trait in bindings. + let super_ = l.super_; let ty = l.ty.as_ref().map(|t| { self.lower_ty(t, self.impl_trait_in_bindings_ctxt(ImplTraitPosition::Variable)) }); @@ -109,7 +110,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let span = self.lower_span(l.span); let source = hir::LocalSource::Normal; self.lower_attrs(hir_id, &l.attrs, l.span); - self.arena.alloc(hir::LetStmt { hir_id, ty, pat, init, els, span, source }) + self.arena.alloc(hir::LetStmt { hir_id, super_, ty, pat, init, els, span, source }) } fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index d5d6dcd8d631d..0dd8bd79604e3 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2223,6 +2223,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.attrs.insert(hir_id.local_id, a); } let local = hir::LetStmt { + super_: None, hir_id, init, pat, diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 3dbfc191f8f50..e2dc334f7efca 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1336,6 +1336,9 @@ impl<'a> State<'a> { self.print_outer_attributes(&loc.attrs); self.space_if_not_bol(); self.ibox(INDENT_UNIT); + if loc.super_.is_some() { + self.word_nbsp("let"); + } self.word_nbsp("let"); self.ibox(INDENT_UNIT); diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index f68172c1f67c0..6d616cf84bbd4 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -230,6 +230,7 @@ impl<'a> ExtCtxt<'a> { self.pat_ident(sp, ident) }; let local = P(ast::Local { + super_: None, pat, ty, id: ast::DUMMY_NODE_ID, @@ -245,6 +246,7 @@ impl<'a> ExtCtxt<'a> { /// Generates `let _: Type;`, which is usually used for type assertions. pub fn stmt_let_type_only(&self, span: Span, ty: P) -> ast::Stmt { let local = P(ast::Local { + super_: None, pat: self.pat_wild(span), ty: Some(ty), id: ast::DUMMY_NODE_ID, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 1a6c15b66a45f..14b7c31285ef7 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1817,6 +1817,8 @@ pub enum StmtKind<'hir> { /// Represents a `let` statement (i.e., `let : = ;`). #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct LetStmt<'hir> { + /// Span of `super` in `super let`. + pub super_: Option, pub pat: &'hir Pat<'hir>, /// Type annotation, if any (otherwise the type will be inferred). pub ty: Option<&'hir Ty<'hir>>, @@ -4850,7 +4852,7 @@ mod size_asserts { static_assert_size!(ImplItemKind<'_>, 40); static_assert_size!(Item<'_>, 88); static_assert_size!(ItemKind<'_>, 64); - static_assert_size!(LetStmt<'_>, 64); + static_assert_size!(LetStmt<'_>, 72); static_assert_size!(Param<'_>, 32); static_assert_size!(Pat<'_>, 72); static_assert_size!(Path<'_>, 40); diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index cf66ab708bb9e..15d1217589184 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -8,6 +8,7 @@ use std::mem; +use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, Visitor}; @@ -44,6 +45,8 @@ struct ScopeResolutionVisitor<'tcx> { scope_tree: ScopeTree, cx: Context, + + extended_super_lets: FxHashMap>, } /// Records the lifetime of a local variable as `cx.var_parent` @@ -214,18 +217,29 @@ fn resolve_stmt<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, stmt: &'tcx hi let stmt_id = stmt.hir_id.local_id; debug!("resolve_stmt(stmt.id={:?})", stmt_id); - // Every statement will clean up the temporaries created during - // execution of that statement. Therefore each statement has an - // associated destruction scope that represents the scope of the - // statement plus its destructors, and thus the scope for which - // regions referenced by the destructors need to survive. + if let hir::StmtKind::Let(LetStmt { super_: Some(_), .. }) = stmt.kind { + // `super let` statement does not start a new scope, such that + // + // { super let x = identity(&temp()); &x }.method(); + // + // behaves exactly as + // + // (&identity(&temp()).method(); + intravisit::walk_stmt(visitor, stmt); + } else { + // Every statement will clean up the temporaries created during + // execution of that statement. Therefore each statement has an + // associated destruction scope that represents the scope of the + // statement plus its destructors, and thus the scope for which + // regions referenced by the destructors need to survive. - let prev_parent = visitor.cx.parent; - visitor.enter_node_scope_with_dtor(stmt_id, true); + let prev_parent = visitor.cx.parent; + visitor.enter_node_scope_with_dtor(stmt_id, true); - intravisit::walk_stmt(visitor, stmt); + intravisit::walk_stmt(visitor, stmt); - visitor.cx.parent = prev_parent; + visitor.cx.parent = prev_parent; + } } fn resolve_expr<'tcx>( @@ -485,10 +499,9 @@ fn resolve_local<'tcx>( visitor: &mut ScopeResolutionVisitor<'tcx>, pat: Option<&'tcx hir::Pat<'tcx>>, init: Option<&'tcx hir::Expr<'tcx>>, + super_let: bool, ) { - debug!("resolve_local(pat={:?}, init={:?})", pat, init); - - let blk_scope = visitor.cx.var_parent; + debug!("resolve_local(pat={:?}, init={:?}, super_let={:?})", pat, init, super_let); // As an exception to the normal rules governing temporary // lifetimes, initializers in a let have a temporary lifetime @@ -546,14 +559,50 @@ fn resolve_local<'tcx>( // A, but the inner rvalues `a()` and `b()` have an extended lifetime // due to rule C. + if super_let { + if let Some(scope) = visitor.extended_super_lets.remove(&pat.unwrap().hir_id.local_id) { + // This expression was lifetime-extended by a parent let binding. E.g. + // + // let a = { + // super let b = temp(); + // &b + // }; + // + // (Which needs to behave exactly as: let a = &temp();) + // + // Processing of `let a` will have already decided to extend the lifetime of this + // `super let` to its own var_scope. We use that scope. + visitor.cx.var_parent = scope; + } else { + // This `super let` is not subject to lifetime extension from a parent let binding. E.g. + // + // identity({ super let x = temp(); &x }).method(); + // + // (Which needs to behave exactly as: identity(&temp()).method();) + // + // Iterate up to the enclosing destruction scope to find the same scope that will also + // be used for the result of the block itself. + while let Some(s) = visitor.cx.var_parent { + let parent = visitor.scope_tree.parent_map.get(&s).cloned(); + if let Some(Scope { data: ScopeData::Destruction, .. }) = parent { + break; + } + visitor.cx.var_parent = parent; + } + } + } + if let Some(expr) = init { - record_rvalue_scope_if_borrow_expr(visitor, expr, blk_scope); + record_rvalue_scope_if_borrow_expr(visitor, expr, visitor.cx.var_parent); if let Some(pat) = pat { if is_binding_pat(pat) { visitor.scope_tree.record_rvalue_candidate( expr.hir_id, - RvalueCandidate { target: expr.hir_id.local_id, lifetime: blk_scope }, + RvalueCandidate { + target: expr.hir_id.local_id, + lifetime: visitor.cx.var_parent, + }, ); } } @@ -565,6 +614,7 @@ fn resolve_local<'tcx>( if let Some(expr) = init { visitor.visit_expr(expr); } + if let Some(pat) = pat { visitor.visit_pat(pat); } @@ -642,6 +692,7 @@ fn resolve_local<'tcx>( /// | [ ..., E&, ... ] /// | ( ..., E&, ... ) /// | {...; E&} + /// | { super let ... = E&; ... } /// | if _ { ...; E& } else { ...; E& } /// | match _ { ..., _ => E&, ... } /// | box E& @@ -678,6 +729,13 @@ fn resolve_local<'tcx>( if let Some(subexpr) = block.expr { record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id); } + for stmt in block.stmts { + if let hir::StmtKind::Let(local) = stmt.kind + && let Some(_) = local.super_ + { + visitor.extended_super_lets.insert(local.pat.hir_id.local_id, blk_id); + } + } } hir::ExprKind::If(_, then_block, else_block) => { record_rvalue_scope_if_borrow_expr(visitor, then_block, blk_id); @@ -803,7 +861,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { local_id: body.value.hir_id.local_id, data: ScopeData::Destruction, }); - resolve_local(this, None, Some(body.value)); + resolve_local(this, None, Some(body.value), false); } }) } @@ -821,7 +879,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { resolve_expr(self, ex, false); } fn visit_local(&mut self, l: &'tcx LetStmt<'tcx>) { - resolve_local(self, Some(l.pat), l.init) + resolve_local(self, Some(l.pat), l.init, l.super_.is_some()); } fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) { let body = self.tcx.hir_body(c.body); @@ -850,6 +908,7 @@ pub(crate) fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree { cx: Context { parent: None, var_parent: None }, pessimistic_yield: false, fixup_scopes: vec![], + extended_super_lets: Default::default(), }; visitor.scope_tree.root_body = Some(body.value.hir_id); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 8c0c17f7a7d6a..5a3849e7afdc7 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -960,12 +960,16 @@ impl<'a> State<'a> { fn print_local( &mut self, + super_: bool, init: Option<&hir::Expr<'_>>, els: Option<&hir::Block<'_>>, decl: impl Fn(&mut Self), ) { self.space_if_not_bol(); self.ibox(INDENT_UNIT); + if super_ { + self.word_nbsp("super"); + } self.word_nbsp("let"); self.ibox(INDENT_UNIT); @@ -995,7 +999,9 @@ impl<'a> State<'a> { self.maybe_print_comment(st.span.lo()); match st.kind { hir::StmtKind::Let(loc) => { - self.print_local(loc.init, loc.els, |this| this.print_local_decl(loc)); + self.print_local(loc.super_.is_some(), loc.init, loc.els, |this| { + this.print_local_decl(loc) + }); } hir::StmtKind::Item(item) => self.ann.nested(self, Nested::Item(item)), hir::StmtKind::Expr(expr) => { @@ -1488,7 +1494,7 @@ impl<'a> State<'a> { // Print `let _t = $init;`: let temp = Ident::from_str("_t"); - self.print_local(Some(init), None, |this| this.print_ident(temp)); + self.print_local(false, Some(init), None, |this| this.print_ident(temp)); self.word(";"); // Print `_t`: diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index 48fd5f1f98249..5d87e800096fe 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -43,7 +43,7 @@ pub(super) struct Declaration<'a> { impl<'a> From<&'a hir::LetStmt<'a>> for Declaration<'a> { fn from(local: &'a hir::LetStmt<'a>) -> Self { - let hir::LetStmt { hir_id, pat, ty, span, init, els, source: _ } = *local; + let hir::LetStmt { hir_id, super_: _, pat, ty, span, init, els, source: _ } = *local; Declaration { hir_id, pat, ty, span, init, origin: DeclOrigin::LocalDecl { els } } } } diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 2cd09aa8959c4..e00fd40ecee75 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -75,10 +75,11 @@ impl<'a> Parser<'a> { let stmt = if self.token.is_keyword(kw::Super) && self.is_keyword_ahead(1, &[kw::Let]) { self.collect_tokens(None, attrs, force_collect, |this, attrs| { + let super_span = this.token.span; this.expect_keyword(exp!(Super))?; - this.psess.gated_spans.gate(sym::super_let, this.prev_token.span); this.expect_keyword(exp!(Let))?; - let local = this.parse_local(attrs)?; // FIXME(mara): implement super let + this.psess.gated_spans.gate(sym::super_let, super_span); + let local = this.parse_local(Some(super_span), attrs)?; let trailing = Trailing::from(capture_semi && this.token == token::Semi); Ok(( this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), @@ -89,7 +90,7 @@ impl<'a> Parser<'a> { } else if self.token.is_keyword(kw::Let) { self.collect_tokens(None, attrs, force_collect, |this, attrs| { this.expect_keyword(exp!(Let))?; - let local = this.parse_local(attrs)?; + let local = this.parse_local(None, attrs)?; let trailing = Trailing::from(capture_semi && this.token == token::Semi); Ok(( this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), @@ -294,7 +295,7 @@ impl<'a> Parser<'a> { force_collect: ForceCollect, ) -> PResult<'a, Stmt> { let stmt = self.collect_tokens(None, attrs, force_collect, |this, attrs| { - let local = this.parse_local(attrs)?; + let local = this.parse_local(None, attrs)?; // FIXME - maybe capture semicolon in recovery? Ok(( this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), @@ -308,8 +309,8 @@ impl<'a> Parser<'a> { } /// Parses a local variable declaration. - fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P> { - let lo = self.prev_token.span; + fn parse_local(&mut self, super_: Option, attrs: AttrVec) -> PResult<'a, P> { + let lo = super_.unwrap_or(self.prev_token.span); if self.token.is_keyword(kw::Const) && self.look_ahead(1, |t| t.is_ident()) { self.dcx().emit_err(errors::ConstLetMutuallyExclusive { span: lo.to(self.token.span) }); @@ -411,6 +412,7 @@ impl<'a> Parser<'a> { }; let hi = if self.token == token::Semi { self.token.span } else { self.prev_token.span }; Ok(P(ast::Local { + super_, ty, pat, kind, diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr index 24e3894864787..b369af62f8760 100644 --- a/tests/ui/stats/input-stats.stderr +++ b/tests/ui/stats/input-stats.stderr @@ -5,25 +5,25 @@ ast-stats-1 Crate 40 ( 0.6%) 1 40 ast-stats-1 GenericArgs 40 ( 0.6%) 1 40 ast-stats-1 - AngleBracketed 40 ( 0.6%) 1 ast-stats-1 ExprField 48 ( 0.7%) 1 48 -ast-stats-1 Attribute 64 ( 1.0%) 2 32 +ast-stats-1 Attribute 64 ( 0.9%) 2 32 ast-stats-1 - DocComment 32 ( 0.5%) 1 ast-stats-1 - Normal 32 ( 0.5%) 1 ast-stats-1 WherePredicate 72 ( 1.1%) 1 72 ast-stats-1 - BoundPredicate 72 ( 1.1%) 1 ast-stats-1 ForeignItem 80 ( 1.2%) 1 80 ast-stats-1 - Fn 80 ( 1.2%) 1 -ast-stats-1 Local 80 ( 1.2%) 1 80 ast-stats-1 Arm 96 ( 1.4%) 2 48 +ast-stats-1 Local 96 ( 1.4%) 1 96 ast-stats-1 FnDecl 120 ( 1.8%) 5 24 ast-stats-1 Param 160 ( 2.4%) 4 40 ast-stats-1 Stmt 160 ( 2.4%) 5 32 ast-stats-1 - Let 32 ( 0.5%) 1 ast-stats-1 - MacCall 32 ( 0.5%) 1 ast-stats-1 - Expr 96 ( 1.4%) 3 -ast-stats-1 Block 192 ( 2.9%) 6 32 +ast-stats-1 Block 192 ( 2.8%) 6 32 ast-stats-1 FieldDef 208 ( 3.1%) 2 104 ast-stats-1 Variant 208 ( 3.1%) 2 104 -ast-stats-1 AssocItem 320 ( 4.8%) 4 80 +ast-stats-1 AssocItem 320 ( 4.7%) 4 80 ast-stats-1 - Fn 160 ( 2.4%) 2 ast-stats-1 - Type 160 ( 2.4%) 2 ast-stats-1 GenericBound 352 ( 5.2%) 4 88 @@ -33,7 +33,7 @@ ast-stats-1 Pat 504 ( 7.5%) 7 72 ast-stats-1 - Struct 72 ( 1.1%) 1 ast-stats-1 - Wild 72 ( 1.1%) 1 ast-stats-1 - Ident 360 ( 5.3%) 5 -ast-stats-1 Expr 576 ( 8.6%) 8 72 +ast-stats-1 Expr 576 ( 8.5%) 8 72 ast-stats-1 - Match 72 ( 1.1%) 1 ast-stats-1 - Path 72 ( 1.1%) 1 ast-stats-1 - Struct 72 ( 1.1%) 1 @@ -41,8 +41,8 @@ ast-stats-1 - Lit 144 ( 2.1%) 2 ast-stats-1 - Block 216 ( 3.2%) 3 ast-stats-1 PathSegment 744 (11.0%) 31 24 ast-stats-1 Ty 896 (13.3%) 14 64 -ast-stats-1 - Ptr 64 ( 1.0%) 1 -ast-stats-1 - Ref 64 ( 1.0%) 1 +ast-stats-1 - Ptr 64 ( 0.9%) 1 +ast-stats-1 - Ref 64 ( 0.9%) 1 ast-stats-1 - ImplicitSelf 128 ( 1.9%) 2 ast-stats-1 - Path 640 ( 9.5%) 10 ast-stats-1 Item 1_296 (19.2%) 9 144 @@ -53,7 +53,7 @@ ast-stats-1 - Trait 144 ( 2.1%) 1 ast-stats-1 - Fn 288 ( 4.3%) 2 ast-stats-1 - Use 432 ( 6.4%) 3 ast-stats-1 ---------------------------------------------------------------- -ast-stats-1 Total 6_736 116 +ast-stats-1 Total 6_752 116 ast-stats-1 ast-stats-2 POST EXPANSION AST STATS ast-stats-2 Name Accumulated Size Count Item Size @@ -66,8 +66,8 @@ ast-stats-2 WherePredicate 72 ( 1.0%) 1 72 ast-stats-2 - BoundPredicate 72 ( 1.0%) 1 ast-stats-2 ForeignItem 80 ( 1.1%) 1 80 ast-stats-2 - Fn 80 ( 1.1%) 1 -ast-stats-2 Local 80 ( 1.1%) 1 80 ast-stats-2 Arm 96 ( 1.3%) 2 48 +ast-stats-2 Local 96 ( 1.3%) 1 96 ast-stats-2 FnDecl 120 ( 1.6%) 5 24 ast-stats-2 InlineAsm 120 ( 1.6%) 1 120 ast-stats-2 Attribute 128 ( 1.7%) 4 32 @@ -84,14 +84,14 @@ ast-stats-2 Variant 208 ( 2.8%) 2 104 ast-stats-2 AssocItem 320 ( 4.3%) 4 80 ast-stats-2 - Fn 160 ( 2.2%) 2 ast-stats-2 - Type 160 ( 2.2%) 2 -ast-stats-2 GenericBound 352 ( 4.8%) 4 88 -ast-stats-2 - Trait 352 ( 4.8%) 4 +ast-stats-2 GenericBound 352 ( 4.7%) 4 88 +ast-stats-2 - Trait 352 ( 4.7%) 4 ast-stats-2 GenericParam 480 ( 6.5%) 5 96 ast-stats-2 Pat 504 ( 6.8%) 7 72 ast-stats-2 - Struct 72 ( 1.0%) 1 ast-stats-2 - Wild 72 ( 1.0%) 1 ast-stats-2 - Ident 360 ( 4.9%) 5 -ast-stats-2 Expr 648 ( 8.8%) 9 72 +ast-stats-2 Expr 648 ( 8.7%) 9 72 ast-stats-2 - InlineAsm 72 ( 1.0%) 1 ast-stats-2 - Match 72 ( 1.0%) 1 ast-stats-2 - Path 72 ( 1.0%) 1 @@ -113,7 +113,7 @@ ast-stats-2 - Trait 144 ( 1.9%) 1 ast-stats-2 - Fn 288 ( 3.9%) 2 ast-stats-2 - Use 576 ( 7.8%) 4 ast-stats-2 ---------------------------------------------------------------- -ast-stats-2 Total 7_400 127 +ast-stats-2 Total 7_416 127 ast-stats-2 hir-stats HIR STATS hir-stats Name Accumulated Size Count Item Size @@ -126,11 +126,11 @@ hir-stats TraitItemRef 56 ( 0.6%) 2 28 hir-stats GenericArg 64 ( 0.7%) 4 16 hir-stats - Type 16 ( 0.2%) 1 hir-stats - Lifetime 48 ( 0.5%) 3 -hir-stats Local 64 ( 0.7%) 1 64 hir-stats Param 64 ( 0.7%) 2 32 hir-stats Body 72 ( 0.8%) 3 24 hir-stats ImplItemRef 72 ( 0.8%) 2 36 hir-stats InlineAsm 72 ( 0.8%) 1 72 +hir-stats Local 72 ( 0.8%) 1 72 hir-stats WherePredicate 72 ( 0.8%) 3 24 hir-stats - BoundPredicate 72 ( 0.8%) 3 hir-stats Arm 80 ( 0.9%) 2 40 @@ -143,8 +143,8 @@ hir-stats Attribute 128 ( 1.4%) 4 32 hir-stats FieldDef 128 ( 1.4%) 2 64 hir-stats GenericArgs 144 ( 1.6%) 3 48 hir-stats Variant 144 ( 1.6%) 2 72 -hir-stats GenericBound 256 ( 2.9%) 4 64 -hir-stats - Trait 256 ( 2.9%) 4 +hir-stats GenericBound 256 ( 2.8%) 4 64 +hir-stats - Trait 256 ( 2.8%) 4 hir-stats Block 288 ( 3.2%) 6 48 hir-stats Pat 360 ( 4.0%) 5 72 hir-stats - Struct 72 ( 0.8%) 1 @@ -156,7 +156,7 @@ hir-stats Ty 720 ( 8.0%) 15 48 hir-stats - Ptr 48 ( 0.5%) 1 hir-stats - Ref 48 ( 0.5%) 1 hir-stats - Path 624 ( 6.9%) 13 -hir-stats Expr 768 ( 8.6%) 12 64 +hir-stats Expr 768 ( 8.5%) 12 64 hir-stats - InlineAsm 64 ( 0.7%) 1 hir-stats - Match 64 ( 0.7%) 1 hir-stats - Path 64 ( 0.7%) 1 @@ -174,5 +174,5 @@ hir-stats - Use 352 ( 3.9%) 4 hir-stats Path 1_240 (13.8%) 31 40 hir-stats PathSegment 1_920 (21.4%) 40 48 hir-stats ---------------------------------------------------------------- -hir-stats Total 8_980 180 +hir-stats Total 8_988 180 hir-stats From f02e2786397f9954ad019ba2af7f574c1e17c904 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 2 Apr 2025 23:48:13 +0200 Subject: [PATCH 04/23] Fix typo in pretty printing super let. Co-authored-by: lcnr --- compiler/rustc_ast_pretty/src/pprust/state.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index e2dc334f7efca..5e0bfc210e4bd 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1337,7 +1337,7 @@ impl<'a> State<'a> { self.space_if_not_bol(); self.ibox(INDENT_UNIT); if loc.super_.is_some() { - self.word_nbsp("let"); + self.word_nbsp("super"); } self.word_nbsp("let"); From 3e6cc7689d467fce677faed22672b592363b0f5f Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 2 Apr 2025 23:55:41 +0200 Subject: [PATCH 05/23] Boolean hate. --- .../rustc_hir_analysis/src/check/region.rs | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 15d1217589184..fedca3302f9bf 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -495,13 +495,19 @@ fn resolve_expr<'tcx>( visitor.cx = prev_cx; } +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +enum LetKind { + Regular, + Super, +} + fn resolve_local<'tcx>( visitor: &mut ScopeResolutionVisitor<'tcx>, pat: Option<&'tcx hir::Pat<'tcx>>, init: Option<&'tcx hir::Expr<'tcx>>, - super_let: bool, + let_kind: LetKind, ) { - debug!("resolve_local(pat={:?}, init={:?}, super_let={:?})", pat, init, super_let); + debug!("resolve_local(pat={:?}, init={:?}, let_kind={:?})", pat, init, let_kind); // As an exception to the normal rules governing temporary // lifetimes, initializers in a let have a temporary lifetime @@ -559,7 +565,7 @@ fn resolve_local<'tcx>( // A, but the inner rvalues `a()` and `b()` have an extended lifetime // due to rule C. - if super_let { + if let_kind == LetKind::Super { if let Some(scope) = visitor.extended_super_lets.remove(&pat.unwrap().hir_id.local_id) { // This expression was lifetime-extended by a parent let binding. E.g. // @@ -861,7 +867,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { local_id: body.value.hir_id.local_id, data: ScopeData::Destruction, }); - resolve_local(this, None, Some(body.value), false); + resolve_local(this, None, Some(body.value), LetKind::Regular); } }) } @@ -879,7 +885,11 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { resolve_expr(self, ex, false); } fn visit_local(&mut self, l: &'tcx LetStmt<'tcx>) { - resolve_local(self, Some(l.pat), l.init, l.super_.is_some()); + let let_kind = match l.super_ { + Some(_) => LetKind::Super, + None => LetKind::Regular, + }; + resolve_local(self, Some(l.pat), l.init, let_kind); } fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) { let body = self.tcx.hir_body(c.body); From b9babad9277fbf0b6209a3075e01f7b2dd043bf4 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 4 Apr 2025 09:38:04 +0200 Subject: [PATCH 06/23] Add feature gate test for cfg'd out super let. --- tests/ui/feature-gates/feature-gate-super-let.rs | 7 +++++++ tests/ui/feature-gates/feature-gate-super-let.stderr | 12 +++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/ui/feature-gates/feature-gate-super-let.rs b/tests/ui/feature-gates/feature-gate-super-let.rs index cfe92a42669d1..7be0800391338 100644 --- a/tests/ui/feature-gates/feature-gate-super-let.rs +++ b/tests/ui/feature-gates/feature-gate-super-let.rs @@ -2,3 +2,10 @@ fn main() { super let a = 1; //~^ ERROR `super let` is experimental } + +// Check that it also isn't accepted in cfg'd out code. +#[cfg(any())] +fn a() { + super let a = 1; + //~^ ERROR `super let` is experimental +} diff --git a/tests/ui/feature-gates/feature-gate-super-let.stderr b/tests/ui/feature-gates/feature-gate-super-let.stderr index a64e1b374f9c0..4d088594f6df5 100644 --- a/tests/ui/feature-gates/feature-gate-super-let.stderr +++ b/tests/ui/feature-gates/feature-gate-super-let.stderr @@ -8,6 +8,16 @@ LL | super let a = 1; = help: add `#![feature(super_let)]` 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 +error[E0658]: `super let` is experimental + --> $DIR/feature-gate-super-let.rs:9:5 + | +LL | super let a = 1; + | ^^^^^ + | + = note: see issue #139076 for more information + = help: add `#![feature(super_let)]` 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 For more information about this error, try `rustc --explain E0658`. From 6c3417dd15cb560a860ddea063193c68b5b47b87 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 4 Apr 2025 11:16:32 +0200 Subject: [PATCH 07/23] fixup! Implement `super let`. --- compiler/rustc_feature/src/unstable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 710e129b609fe..7647f8e4b2360 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -630,7 +630,7 @@ declare_features! ( /// Allows string patterns to dereference values to match them. (unstable, string_deref_patterns, "1.67.0", Some(87121)), /// Allows `super let` statements. - (incomplete, super_let, "CURRENT_RUSTC_VERSION", Some(139076)), + (unstable, super_let, "CURRENT_RUSTC_VERSION", Some(139076)), /// Allows subtrait items to shadow supertrait items. (unstable, supertrait_item_shadowing, "1.86.0", Some(89151)), /// Allows using `#[thread_local]` on `static` items. From 0522ed059db967db26143387747b46c11528f49b Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Fri, 4 Apr 2025 15:32:00 +0300 Subject: [PATCH 08/23] Default auto traits: fix perf --- .../src/collect/predicates_of.rs | 30 +--------- .../src/hir_ty_lowering/bounds.rs | 56 ++++++++++++++++--- 2 files changed, 51 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 776b23bea8e11..320225a7a663a 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -172,33 +172,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen }; if let Node::TraitItem(item) = node { - let parent = tcx.local_parent(item.hir_id().owner.def_id); - let Node::Item(parent_trait) = tcx.hir_node_by_def_id(parent) else { - unreachable!(); - }; - - let (trait_generics, trait_bounds) = match parent_trait.kind { - hir::ItemKind::Trait(_, _, _, generics, supertraits, _) => (generics, supertraits), - hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits), - _ => unreachable!(), - }; - - // Implicitly add `Self: DefaultAutoTrait` clauses on trait associated items if - // they are not added as super trait bounds to the trait itself. See comment on - // `requires_default_supertraits` for more details. - if !icx.lowerer().requires_default_supertraits(trait_bounds, trait_generics) { - let mut bounds = Vec::new(); - let self_ty_where_predicates = (parent, item.generics.predicates); - icx.lowerer().add_default_traits_with_filter( - &mut bounds, - tcx.types.self_param, - &[], - Some(self_ty_where_predicates), - item.span, - |tr| tr != hir::LangItem::Sized, - ); - predicates.extend(bounds); - } + let mut bounds = Vec::new(); + icx.lowerer().add_default_trait_item_bounds(item, &mut bounds); + predicates.extend(bounds); } let generics = tcx.generics_of(def_id); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index c3bb860538ee8..55087d1f400f5 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -43,12 +43,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } /// Checks whether `Self: DefaultAutoTrait` bounds should be added on trait super bounds - /// or associative items. + /// or associated items. /// /// To keep backward compatibility with existing code, `experimental_default_bounds` bounds /// should be added everywhere, including super bounds. However this causes a huge performance /// costs. For optimization purposes instead of adding default supertraits, bounds - /// are added to the associative items: + /// are added to the associated items: /// /// ```ignore(illustrative) /// // Default bounds are generated in the following way: @@ -81,7 +81,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// /// Therefore, `experimental_default_bounds` are still being added to supertraits if /// the `SelfTyParam` or `AssocItemConstraint` were found in a trait header. - pub(crate) fn requires_default_supertraits( + fn requires_default_supertraits( &self, hir_bounds: &'tcx [hir::GenericBound<'tcx>], hir_generics: &'tcx hir::Generics<'tcx>, @@ -120,6 +120,43 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { found } + /// Implicitly add `Self: DefaultAutoTrait` clauses on trait associated items if + /// they are not added as super trait bounds to the trait itself. See + /// `requires_default_supertraits` for more information. + pub(crate) fn add_default_trait_item_bounds( + &self, + trait_item: &hir::TraitItem<'tcx>, + bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, + ) { + let tcx = self.tcx(); + if !tcx.sess.opts.unstable_opts.experimental_default_bounds { + return; + } + + let parent = tcx.local_parent(trait_item.hir_id().owner.def_id); + let hir::Node::Item(parent_trait) = tcx.hir_node_by_def_id(parent) else { + unreachable!(); + }; + + let (trait_generics, trait_bounds) = match parent_trait.kind { + hir::ItemKind::Trait(_, _, _, generics, supertraits, _) => (generics, supertraits), + hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits), + _ => unreachable!(), + }; + + if !self.requires_default_supertraits(trait_bounds, trait_generics) { + let self_ty_where_predicates = (parent, trait_item.generics.predicates); + self.add_default_traits_with_filter( + bounds, + tcx.types.self_param, + &[], + Some(self_ty_where_predicates), + trait_item.span, + |tr| tr != hir::LangItem::Sized, + ); + } + } + /// Lazily sets `experimental_default_bounds` to true on trait super bounds. /// See `requires_default_supertraits` for more information. pub(crate) fn add_default_super_traits( @@ -130,6 +167,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir_generics: &'tcx hir::Generics<'tcx>, span: Span, ) { + if !self.tcx().sess.opts.unstable_opts.experimental_default_bounds { + return; + } + assert!(matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias)); if self.requires_default_supertraits(hir_bounds, hir_generics) { let self_ty_where_predicates = (trait_def_id, hir_generics.predicates); @@ -263,11 +304,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { seen_unbound = true; } let emit_relax_err = || { - let unbound_traits = - match self.tcx().sess.opts.unstable_opts.experimental_default_bounds { - true => "`?Sized` and `experimental_default_bounds`", - false => "`?Sized`", - }; + let unbound_traits = match tcx.sess.opts.unstable_opts.experimental_default_bounds { + true => "`?Sized` and `experimental_default_bounds`", + false => "`?Sized`", + }; // There was a `?Trait` bound, but it was neither `?Sized` nor `experimental_default_bounds`. tcx.dcx().span_err( unbound.span, From ccbef74fc5a6bf5adfdd79fd15601fe91aa22c66 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 4 Apr 2025 11:16:37 +0200 Subject: [PATCH 09/23] Add tests for super let. --- tests/ui/super-let.borrowck.stderr | 174 ++++++++++++++++++ tests/ui/super-let.rs | 286 +++++++++++++++++++++++++++++ 2 files changed, 460 insertions(+) create mode 100644 tests/ui/super-let.borrowck.stderr create mode 100644 tests/ui/super-let.rs diff --git a/tests/ui/super-let.borrowck.stderr b/tests/ui/super-let.borrowck.stderr new file mode 100644 index 0000000000000..01ef29d875880 --- /dev/null +++ b/tests/ui/super-let.borrowck.stderr @@ -0,0 +1,174 @@ +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:30:28 + | +LL | super let b = DropMe(&mut x); + | ------ `x` is borrowed here +... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +... +LL | } + | - borrow might be used here, when `b` is dropped and runs the `Drop` code for type `DropMe` + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:46:28 + | +LL | super let b = &DropMe(&mut x); + | -------------- + | | | + | | `x` is borrowed here + | a temporary with access to the borrow is created here ... +... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +... +LL | } + | - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `DropMe` + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:64:32 + | +LL | super let b = identity(&DropMe(&mut x)); + | -------------- + | | | + | | `x` is borrowed here + | a temporary with access to the borrow is created here ... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +... +LL | }; + | - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `DropMe` + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:87:36 + | +LL | super let b = identity(&DropMe(&mut x)); + | -------------- + | | | + | | `x` is borrowed here + | a temporary with access to the borrow is created here ... +... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +... +LL | )); + | - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `DropMe` + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:107:28 + | +LL | super let b = DropMe(&mut x); + | ------ `x` is borrowed here +... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +... +LL | } + | - borrow might be used here, when `b` is dropped and runs the `Drop` code for type `DropMe` + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:125:28 + | +LL | super let b = DropMe(&mut x); + | ------ `x` is borrowed here +... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +... +LL | } + | - borrow might be used here, when `b` is dropped and runs the `Drop` code for type `DropMe` + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:143:28 + | +LL | super let b = DropMe(&mut x); + | ------ `x` is borrowed here +... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +... +LL | } + | - borrow might be used here, when `b` is dropped and runs the `Drop` code for type `DropMe` + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:159:28 + | +LL | b = DropMe(&mut x); + | ------ `x` is borrowed here +... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +LL | drop(a); + | - borrow later used here + +error[E0716]: temporary value dropped while borrowed + --> $DIR/super-let.rs:172:33 + | +LL | #[cfg(borrowck)] { a = &String::from("asdf"); }; + | ^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +... +LL | let _ = a; + | - borrow later used here + | + = note: consider using a `let` binding to create a longer lived value + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:206:28 + | +LL | super let d = &DropMe(&mut x); + | -------------- + | | | + | | `x` is borrowed here + | a temporary with access to the borrow is created here ... +... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +... +LL | } + | - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `DropMe` + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:227:32 + | +LL | super let d = identity(&DropMe(&mut x)); + | -------------- + | | | + | | `x` is borrowed here + | a temporary with access to the borrow is created here ... +... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +... +LL | }; + | - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `DropMe` + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:246:28 + | +LL | super let b = DropMe(&mut x); + | ------ `x` is borrowed here +... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +... +LL | } + | - borrow might be used here, when `b` is dropped and runs the `Drop` code for type `DropMe` + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:263:28 + | +LL | let dropme = Some(DropMe(&mut x)); + | ------ `x` is borrowed here +... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +... +LL | } + | - borrow might be used here, when `x` is dropped and runs the `Drop` code for type `DropMe` + +error: aborting due to 13 previous errors + +Some errors have detailed explanations: E0506, E0716. +For more information about an error, try `rustc --explain E0506`. diff --git a/tests/ui/super-let.rs b/tests/ui/super-let.rs new file mode 100644 index 0000000000000..380470f792fe1 --- /dev/null +++ b/tests/ui/super-let.rs @@ -0,0 +1,286 @@ +// Check in two ways: +// - borrowck: Check with borrow checking errors when things are alive and dead. +// - runtime: Check with a mutable bool if things are dropped on time. +// +//@ revisions: runtime borrowck +//@ [runtime] run-pass +//@ [borrowck] check-fail + +#![allow(dropping_references)] +#![feature(super_let, stmt_expr_attributes)] + +use std::convert::identity; + +struct DropMe<'a>(&'a mut bool); + +impl Drop for DropMe<'_> { + fn drop(&mut self) { + *self.0 = true; + } +} + +// Check that a super let variable lives as long as the result of a block. +fn extended_variable() { + let mut x = false; + { + let a = { + super let b = DropMe(&mut x); + &b + }; + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + drop(a); + // DropMe is still alive here... + } + // ... but not here. + assert_eq!(x, true) // ok +} + +// Check that the init expression of a super let is subject to (temporary) lifetime extension. +fn extended_temporary() { + let mut x = false; + { + let a = { + super let b = &DropMe(&mut x); + b + }; + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + drop(a); + // DropMe is still alive here... + } + // ... but not here. + assert_eq!(x, true); // ok +} + +// Check that even non-extended temporaries live until the end of the block, +// but (unlike extended temporaries) not beyond that. +// +// This is necessary for things like select(pin!(identity(&temp()))) to work. +fn non_extended() { + let mut x = false; + { + let _a = { + // Use identity() to supress temporary lifetime extension. + super let b = identity(&DropMe(&mut x)); + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + b + // DropMe is still alive here... + }; + // ... but not here. + assert_eq!(x, true); // ok + } +} + +// Check that even non-extended temporaries live until the end of the block, +// but (unlike extended temporaries) not beyond that. +// +// This is necessary for things like select(pin!(identity(&temp()))) to work. +fn non_extended_in_expression() { + let mut x = false; + { + identity(( + { + // Use identity() to supress temporary lifetime extension. + super let b = identity(&DropMe(&mut x)); + b + }, + { + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + // DropMe is still alive here... + } + )); + // ... but not here. + assert_eq!(x, true); // ok + } +} + +// Check `super let` in a match arm. +fn match_arm() { + let mut x = false; + { + let a = match Some(123) { + Some(_) => { + super let b = DropMe(&mut x); + &b + } + None => unreachable!(), + }; + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + drop(a); + // DropMe is still alive here... + } + // ... but not here. + assert_eq!(x, true); // ok +} + +// Check `super let` in an if body. +fn if_body() { + let mut x = false; + { + let a = if true { + super let b = DropMe(&mut x); + &b + } else { + unreachable!() + }; + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + drop(a); + // DropMe is still alive here... + } + // ... but not here. + assert_eq!(x, true); // ok +} + +// Check `super let` in an else body. +fn else_body() { + let mut x = false; + { + let a = if false { + unreachable!() + } else { + super let b = DropMe(&mut x); + &b + }; + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + drop(a); + // DropMe is still alive here... + } + // ... but not here. + assert_eq!(x, true); // ok +} + +fn without_initializer() { + let mut x = false; + { + let a = { + super let b; + b = DropMe(&mut x); + b + }; + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + drop(a); + // DropMe is still alive here... + } + // ... but not here. + assert_eq!(x, true); +} + +// Assignment isn't special, even when assigning to a `super let` variable. +fn assignment() { + let mut x = false; + { + super let a; + #[cfg(borrowck)] { a = &String::from("asdf"); }; //[borrowck]~ ERROR dropped while borrowed + #[cfg(runtime)] { a = drop(&DropMe(&mut x)); } // Temporary dropped at the `;` as usual. + assert_eq!(x, true); + let _ = a; + } +} + +// `super let mut` should work just fine. +fn mutable() { + let mut x = false; + { + let a = { + super let mut b = None; + &mut b + }; + *a = Some(DropMe(&mut x)); + } + assert_eq!(x, true); +} + +// Temporary lifetime extension should recurse through `super let`s. +fn multiple_levels() { + let mut x = false; + { + let a = { + super let b = { + super let c = { + super let d = &DropMe(&mut x); + d + }; + c + }; + b + }; + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + drop(a); + // DropMe is still alive here... + } + // ... but not here. + assert_eq!(x, true); +} + +// Non-extended temporaries should be dropped at the +// end of the first parent statement that isn't `super`. +fn multiple_levels_but_no_extension() { + let mut x = false; + { + let _a = { + super let b = { + super let c = { + super let d = identity(&DropMe(&mut x)); + d + }; + c + }; + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + b + // DropMe is still alive here... + }; + // ... but not here. + assert_eq!(x, true); + } +} + +// Check for potential weird interactions with `let else`. +fn super_let_and_let_else() { + let mut x = false; + { + let a = 'a: { + let Some(_) = Some(123) else { unreachable!() }; + super let b = DropMe(&mut x); + let None = Some(123) else { break 'a &b }; + unreachable!() + }; + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + // DropMe is still alive here... + drop(a); + } + // ... but not here. + assert_eq!(x, true); +} + +// Check if `super let .. else ..;` works. +fn super_let_else() { + let mut x = false; + { + let a = { + let dropme = Some(DropMe(&mut x)); + super let Some(x) = dropme else { unreachable!() }; + &x + }; + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + // DropMe is still alive here... + drop(a); + } + // ... but not here. + assert_eq!(x, true); +} + +fn main() { + extended_variable(); + extended_temporary(); + non_extended(); + non_extended_in_expression(); + match_arm(); + if_body(); + else_body(); + without_initializer(); + assignment(); + mutable(); + multiple_levels(); + multiple_levels_but_no_extension(); + super_let_and_let_else(); + super_let_else(); +} From de57c0515d39a285541039205e7f9d6b06430031 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 29 Mar 2025 13:38:48 +0100 Subject: [PATCH 10/23] Let `const_to_pat` handle the `ExpandedConstant` wrapping --- .../src/thir/pattern/const_to_pat.rs | 10 +++++++++- .../rustc_mir_build/src/thir/pattern/mod.rs | 17 +++-------------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 372453688d242..0fca9775530c9 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -5,6 +5,7 @@ use rustc_apfloat::Float; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Diag; use rustc_hir as hir; +use rustc_hir::def::DefKind; use rustc_index::Idx; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::Obligation; @@ -182,7 +183,14 @@ impl<'tcx> ConstToPat<'tcx> { } } - inlined_const_as_pat + // Wrap the pattern in a marker node to indicate that it is the result of lowering a + // constant. This is used for diagnostics, and for unsafety checking of inline const blocks. + let kind = PatKind::ExpandedConstant { + subpattern: inlined_const_as_pat, + def_id: uv.def, + is_inline: matches!(self.tcx.def_kind(uv.def), DefKind::InlineConst), + }; + Box::new(Pat { kind, ty, span: self.span }) } fn field_pats( diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index d20e051548bf1..fbb3a0995e286 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -567,15 +567,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // Lower the named constant to a THIR pattern. let args = self.typeck_results.node_args(id); let c = ty::Const::new_unevaluated(self.tcx, ty::UnevaluatedConst { def: def_id, args }); - let subpattern = self.const_to_pat(c, ty, id, span); - - // Wrap the pattern in a marker node to indicate that it is the result - // of lowering a named constant. This marker is used for improved - // diagnostics in some situations, but has no effect at runtime. - let mut pattern = { - let kind = PatKind::ExpandedConstant { subpattern, def_id, is_inline: false }; - Box::new(Pat { span, ty, kind }) - }; + let mut pattern = self.const_to_pat(c, ty, id, span); // If this is an associated constant with an explicit user-written // type, add an ascription node (e.g. ` as MyTrait>::CONST`). @@ -619,11 +611,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { debug_assert!(!args.has_free_regions()); let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args }; - let subpattern = self.const_to_pat(ty::Const::new_unevaluated(self.tcx, ct), ty, id, span); - - // Wrap the pattern in a marker node to indicate that it is the result - // of lowering an inline const block. - PatKind::ExpandedConstant { subpattern, def_id: def_id.to_def_id(), is_inline: true } + let c = ty::Const::new_unevaluated(self.tcx, ct); + self.const_to_pat(c, ty, id, span).kind } /// Lowers the kinds of "expression" that can appear in a HIR pattern: From 090d76497f67f915f977c1176d50acaa2c962aeb Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 29 Mar 2025 13:55:05 +0100 Subject: [PATCH 11/23] Remove the `is_inline` field from `PatKind::ExpandedConstant` --- compiler/rustc_middle/src/thir.rs | 22 +++++--------- .../src/builder/custom/parse/instruction.rs | 2 +- .../src/builder/matches/match_pair.rs | 11 ++++--- .../rustc_mir_build/src/check_unsafety.rs | 4 +-- .../src/thir/pattern/check_match.rs | 5 ++-- .../src/thir/pattern/const_to_pat.rs | 7 +---- .../rustc_mir_build/src/thir/pattern/mod.rs | 29 +++++++------------ compiler/rustc_mir_build/src/thir/print.rs | 3 +- 8 files changed, 32 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 8d373cb3b3091..bc49c197ef811 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -812,23 +812,17 @@ pub enum PatKind<'tcx> { }, /// Pattern obtained by converting a constant (inline or named) to its pattern - /// representation using `const_to_pat`. + /// representation using `const_to_pat`. This is used for unsafety checking. ExpandedConstant { - /// [DefId] of the constant, we need this so that we have a - /// reference that can be used by unsafety checking to visit nested - /// unevaluated constants and for diagnostics. If the `DefId` doesn't - /// correspond to a local crate, it points at the `const` item. + /// [DefId] of the constant item. def_id: DefId, - /// If `false`, then `def_id` points at a `const` item, otherwise it - /// corresponds to a local inline const. - is_inline: bool, - /// If the inline constant is used in a range pattern, this subpattern - /// represents the range (if both ends are inline constants, there will - /// be multiple InlineConstant wrappers). + /// The pattern that the constant lowered to. /// - /// Otherwise, the actual pattern that the constant lowered to. As with - /// other constants, inline constants are matched structurally where - /// possible. + /// HACK: we need to keep the `DefId` of inline constants around for unsafety checking; + /// therefore when a range pattern contains inline constants, we re-wrap the range pattern + /// with the `ExpandedConstant` nodes that correspond to the range endpoints. Hence + /// `subpattern` may actually be a range pattern, and `def_id` be the constant for one of + /// its endpoints. subpattern: Box>, }, diff --git a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs index 19669021eefb4..5918498f2392d 100644 --- a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs @@ -145,7 +145,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { let arm = &self.thir[*arm]; let value = match arm.pattern.kind { PatKind::Constant { value } => value, - PatKind::ExpandedConstant { ref subpattern, def_id: _, is_inline: false } + PatKind::ExpandedConstant { ref subpattern, def_id: _ } if let PatKind::Constant { value } = subpattern.kind => { value diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index 29d400a957b47..c84664bd68e31 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -1,5 +1,6 @@ use std::sync::Arc; +use rustc_hir::def::DefKind; use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; @@ -201,15 +202,13 @@ impl<'tcx> MatchPairTree<'tcx> { None } - PatKind::ExpandedConstant { subpattern: ref pattern, def_id: _, is_inline: false } => { - MatchPairTree::for_pattern(place_builder, pattern, cx, &mut subpairs, extra_data); - None - } - PatKind::ExpandedConstant { subpattern: ref pattern, def_id, is_inline: true } => { + PatKind::ExpandedConstant { subpattern: ref pattern, def_id } => { MatchPairTree::for_pattern(place_builder, pattern, cx, &mut subpairs, extra_data); // Apply a type ascription for the inline constant to the value at `match_pair.place` - if let Some(source) = place { + if let Some(source) = place + && matches!(cx.tcx.def_kind(def_id), DefKind::InlineConst) + { let span = pattern.span; let parent_id = cx.tcx.typeck_root_def_id(cx.def_id.to_def_id()); let args = ty::InlineConstArgs::new( diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 6fb9974fc8e27..b52d0d1e30045 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -403,9 +403,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { visit::walk_pat(self, pat); self.inside_adt = old_inside_adt; } - PatKind::ExpandedConstant { def_id, is_inline, .. } => { + PatKind::ExpandedConstant { def_id, .. } => { if let Some(def) = def_id.as_local() - && *is_inline + && matches!(self.tcx.def_kind(def_id), DefKind::InlineConst) { self.visit_inner_body(def); } diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 9f5e2c06b229d..78583a402fe9a 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -676,7 +676,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { unpeeled_pat = subpattern; } - if let PatKind::ExpandedConstant { def_id, is_inline: false, .. } = unpeeled_pat.kind + if let PatKind::ExpandedConstant { def_id, .. } = unpeeled_pat.kind && let DefKind::Const = self.tcx.def_kind(def_id) && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span) // We filter out paths with multiple path::segments. @@ -1296,7 +1296,8 @@ fn report_non_exhaustive_match<'p, 'tcx>( for &arm in arms { let arm = &thir.arms[arm]; - if let PatKind::ExpandedConstant { def_id, is_inline: false, .. } = arm.pattern.kind + if let PatKind::ExpandedConstant { def_id, .. } = arm.pattern.kind + && !matches!(cx.tcx.def_kind(def_id), DefKind::InlineConst) && let Ok(snippet) = cx.tcx.sess.source_map().span_to_snippet(arm.pattern.span) // We filter out paths with multiple path::segments. && snippet.chars().all(|c| c.is_alphanumeric() || c == '_') diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 0fca9775530c9..a40001bf74556 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -5,7 +5,6 @@ use rustc_apfloat::Float; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Diag; use rustc_hir as hir; -use rustc_hir::def::DefKind; use rustc_index::Idx; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::Obligation; @@ -185,11 +184,7 @@ impl<'tcx> ConstToPat<'tcx> { // Wrap the pattern in a marker node to indicate that it is the result of lowering a // constant. This is used for diagnostics, and for unsafety checking of inline const blocks. - let kind = PatKind::ExpandedConstant { - subpattern: inlined_const_as_pat, - def_id: uv.def, - is_inline: matches!(self.tcx.def_kind(uv.def), DefKind::InlineConst), - }; + let kind = PatKind::ExpandedConstant { subpattern: inlined_const_as_pat, def_id: uv.def }; Box::new(Pat { kind, ty, span: self.span }) } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index fbb3a0995e286..e7850962785e4 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -20,7 +20,7 @@ use rustc_middle::thir::{ use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::{bug, span_bug}; -use rustc_span::def_id::LocalDefId; +use rustc_span::def_id::DefId; use rustc_span::{ErrorGuaranteed, Span}; use tracing::{debug, instrument}; @@ -124,7 +124,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { expr: Option<&'tcx hir::PatExpr<'tcx>>, // Out-parameters collecting extra data to be reapplied by the caller ascriptions: &mut Vec>, - inline_consts: &mut Vec, + expanded_consts: &mut Vec, ) -> Result>, ErrorGuaranteed> { let Some(expr) = expr else { return Ok(None) }; @@ -139,10 +139,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { ascriptions.push(ascription); kind = subpattern.kind; } - PatKind::ExpandedConstant { is_inline, def_id, subpattern } => { - if is_inline { - inline_consts.extend(def_id.as_local()); - } + PatKind::ExpandedConstant { def_id, subpattern } => { + expanded_consts.push(def_id); kind = subpattern.kind; } _ => break, @@ -221,10 +219,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // Collect extra data while lowering the endpoints, to be reapplied later. let mut ascriptions = vec![]; - let mut inline_consts = vec![]; + let mut expanded_consts = vec![]; let mut lower_endpoint = - |expr| self.lower_pattern_range_endpoint(expr, &mut ascriptions, &mut inline_consts); + |expr| self.lower_pattern_range_endpoint(expr, &mut ascriptions, &mut expanded_consts); let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity); let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity); @@ -269,17 +267,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated // constants somewhere. Have them on the range pattern. for ascription in ascriptions { - kind = PatKind::AscribeUserType { - ascription, - subpattern: Box::new(Pat { span, ty, kind }), - }; + let subpattern = Box::new(Pat { span, ty, kind }); + kind = PatKind::AscribeUserType { ascription, subpattern }; } - for def in inline_consts { - kind = PatKind::ExpandedConstant { - def_id: def.to_def_id(), - is_inline: true, - subpattern: Box::new(Pat { span, ty, kind }), - }; + for def_id in expanded_consts { + let subpattern = Box::new(Pat { span, ty, kind }); + kind = PatKind::ExpandedConstant { def_id, subpattern }; } Ok(kind) } diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 16cef0ec3acbc..aa8d2e5897ea7 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -740,10 +740,9 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { print_indented!(self, format!("value: {:?}", value), depth_lvl + 2); print_indented!(self, "}", depth_lvl + 1); } - PatKind::ExpandedConstant { def_id, is_inline, subpattern } => { + PatKind::ExpandedConstant { def_id, subpattern } => { print_indented!(self, "ExpandedConstant {", depth_lvl + 1); print_indented!(self, format!("def_id: {def_id:?}"), depth_lvl + 2); - print_indented!(self, format!("is_inline: {is_inline:?}"), depth_lvl + 2); print_indented!(self, "subpattern:", depth_lvl + 2); self.print_pat(subpattern, depth_lvl + 2); print_indented!(self, "}", depth_lvl + 1); From 50e10b37c040af7b33b034eec4f7de9b9323b4a2 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 29 Mar 2025 12:32:07 +0100 Subject: [PATCH 12/23] Tweak `lower_pat_expr` --- .../rustc_mir_build/src/thir/pattern/mod.rs | 68 +++++++++---------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index e7850962785e4..153a3b8a72986 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -617,43 +617,41 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { expr: &'tcx hir::PatExpr<'tcx>, pat_ty: Option>, ) -> PatKind<'tcx> { - let (lit, neg) = match &expr.kind { - hir::PatExprKind::Path(qpath) => { - return self.lower_path(qpath, expr.hir_id, expr.span).kind; - } + match &expr.kind { + hir::PatExprKind::Path(qpath) => self.lower_path(qpath, expr.hir_id, expr.span).kind, hir::PatExprKind::ConstBlock(anon_const) => { - return self.lower_inline_const(anon_const, expr.hir_id, expr.span); + self.lower_inline_const(anon_const, expr.hir_id, expr.span) } - hir::PatExprKind::Lit { lit, negated } => (lit, *negated), - }; - - // We handle byte string literal patterns by using the pattern's type instead of the - // literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference, - // the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the - // pattern's type means we'll properly translate it to a slice reference pattern. This works - // because slices and arrays have the same valtree representation. - // HACK: As an exception, use the literal's type if `pat_ty` is `String`; this can happen if - // `string_deref_patterns` is enabled. There's a special case for that when lowering to MIR. - // FIXME(deref_patterns): This hack won't be necessary once `string_deref_patterns` is - // superseded by a more general implementation of deref patterns. - let ct_ty = match pat_ty { - Some(pat_ty) - if let ty::Adt(def, _) = *pat_ty.kind() - && self.tcx.is_lang_item(def.did(), LangItem::String) => - { - if !self.tcx.features().string_deref_patterns() { - span_bug!( - expr.span, - "matching on `String` went through without enabling string_deref_patterns" - ); - } - self.typeck_results.node_type(expr.hir_id) + hir::PatExprKind::Lit { lit, negated } => { + // We handle byte string literal patterns by using the pattern's type instead of the + // literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference, + // the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the + // pattern's type means we'll properly translate it to a slice reference pattern. This works + // because slices and arrays have the same valtree representation. + // HACK: As an exception, use the literal's type if `pat_ty` is `String`; this can happen if + // `string_deref_patterns` is enabled. There's a special case for that when lowering to MIR. + // FIXME(deref_patterns): This hack won't be necessary once `string_deref_patterns` is + // superseded by a more general implementation of deref patterns. + let ct_ty = match pat_ty { + Some(pat_ty) + if let ty::Adt(def, _) = *pat_ty.kind() + && self.tcx.is_lang_item(def.did(), LangItem::String) => + { + if !self.tcx.features().string_deref_patterns() { + span_bug!( + expr.span, + "matching on `String` went through without enabling string_deref_patterns" + ); + } + self.typeck_results.node_type(expr.hir_id) + } + Some(pat_ty) => pat_ty, + None => self.typeck_results.node_type(expr.hir_id), + }; + let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg: *negated }; + let constant = self.tcx.at(expr.span).lit_to_const(lit_input); + self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind } - Some(pat_ty) => pat_ty, - None => self.typeck_results.node_type(expr.hir_id), - }; - let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg }; - let constant = self.tcx.at(expr.span).lit_to_const(lit_input); - self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind + } } } From 961c7463d8df79bef545af0c07a534aabfd258c2 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 29 Mar 2025 15:13:14 +0100 Subject: [PATCH 13/23] Add the inline const type annotation in pattern lowering --- .../src/builder/matches/match_pair.rs | 30 +--------------- .../rustc_mir_build/src/thir/pattern/mod.rs | 36 +++++++++++++++++-- 2 files changed, 35 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index c84664bd68e31..fcfacf1e1f862 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -1,6 +1,5 @@ use std::sync::Arc; -use rustc_hir::def::DefKind; use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; @@ -202,35 +201,8 @@ impl<'tcx> MatchPairTree<'tcx> { None } - PatKind::ExpandedConstant { subpattern: ref pattern, def_id } => { + PatKind::ExpandedConstant { subpattern: ref pattern, .. } => { MatchPairTree::for_pattern(place_builder, pattern, cx, &mut subpairs, extra_data); - - // Apply a type ascription for the inline constant to the value at `match_pair.place` - if let Some(source) = place - && matches!(cx.tcx.def_kind(def_id), DefKind::InlineConst) - { - let span = pattern.span; - let parent_id = cx.tcx.typeck_root_def_id(cx.def_id.to_def_id()); - let args = ty::InlineConstArgs::new( - cx.tcx, - ty::InlineConstArgsParts { - parent_args: ty::GenericArgs::identity_for_item(cx.tcx, parent_id), - ty: cx.infcx.next_ty_var(span), - }, - ) - .args; - 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, - span, - user_ty: Box::new(user_ty), - }; - let variance = ty::Contravariant; - extra_data.ascriptions.push(super::Ascription { annotation, source, variance }); - } - None } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 153a3b8a72986..7da0c872dfe9a 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -13,12 +13,15 @@ use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::pat_util::EnumerateAndAdjustIterator; use rustc_hir::{self as hir, LangItem, RangeEnd}; use rustc_index::Idx; +use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::interpret::LitToConstInput; use rustc_middle::thir::{ Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary, }; use rustc_middle::ty::layout::IntegerExt; -use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{ + self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypeVisitableExt, TypingMode, +}; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::DefId; use rustc_span::{ErrorGuaranteed, Span}; @@ -605,7 +608,36 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args }; let c = ty::Const::new_unevaluated(self.tcx, ct); - self.const_to_pat(c, ty, id, span).kind + let pattern = self.const_to_pat(c, ty, id, span); + + // Apply a type ascription for the inline constant. + // FIXME: reusing the `args` above causes an ICE + let annotation = { + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); + let args = ty::InlineConstArgs::new( + tcx, + ty::InlineConstArgsParts { + parent_args: ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id), + ty: infcx.next_ty_var(span), + }, + ) + .args; + infcx.canonicalize_user_type_annotation(ty::UserType::new(ty::UserTypeKind::TypeOf( + def_id.to_def_id(), + ty::UserArgs { args, user_self_ty: None }, + ))) + }; + let annotation = + CanonicalUserTypeAnnotation { user_ty: Box::new(annotation), span, inferred_ty: ty }; + PatKind::AscribeUserType { + subpattern: pattern, + ascription: Ascription { + annotation, + // Note that we use `Contravariant` here. See the `variance` field documentation + // for details. + variance: ty::Contravariant, + }, + } } /// Lowers the kinds of "expression" that can appear in a HIR pattern: From d912c0352516bc8196437bbf00566a1df985b621 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 29 Mar 2025 15:23:37 +0100 Subject: [PATCH 14/23] Reuse `parent_args` --- compiler/rustc_mir_build/src/thir/pattern/mod.rs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 7da0c872dfe9a..7ceeebbb70df1 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -19,9 +19,7 @@ use rustc_middle::thir::{ Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary, }; use rustc_middle::ty::layout::IntegerExt; -use rustc_middle::ty::{ - self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypeVisitableExt, TypingMode, -}; +use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypingMode}; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::DefId; use rustc_span::{ErrorGuaranteed, Span}; @@ -600,26 +598,19 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let ty = tcx.typeck(def_id).node_type(block.hir_id); let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()); - let parent_args = - tcx.erase_regions(ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id)); + let parent_args = ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id); let args = ty::InlineConstArgs::new(tcx, ty::InlineConstArgsParts { parent_args, ty }).args; - debug_assert!(!args.has_free_regions()); - let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args }; let c = ty::Const::new_unevaluated(self.tcx, ct); let pattern = self.const_to_pat(c, ty, id, span); // Apply a type ascription for the inline constant. - // FIXME: reusing the `args` above causes an ICE let annotation = { let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let args = ty::InlineConstArgs::new( tcx, - ty::InlineConstArgsParts { - parent_args: ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id), - ty: infcx.next_ty_var(span), - }, + ty::InlineConstArgsParts { parent_args, ty: infcx.next_ty_var(span) }, ) .args; infcx.canonicalize_user_type_annotation(ty::UserType::new(ty::UserTypeKind::TypeOf( From 5eb535c568de730a36bbf96f0ec1163942301b15 Mon Sep 17 00:00:00 2001 From: Skgland <3877590+Skgland@users.noreply.github.com> Date: Sun, 6 Apr 2025 21:32:58 +0200 Subject: [PATCH 15/23] remove compiler support for `extern "rust-intrinsic"` blocks --- compiler/rustc_abi/src/extern_abi.rs | 4 +- compiler/rustc_ast_lowering/src/stability.rs | 4 - .../rustc_hir_analysis/src/check/check.rs | 108 ++++++++---------- .../rustc_hir_analysis/src/check/intrinsic.rs | 2 +- compiler/rustc_hir_analysis/src/check/mod.rs | 9 -- compiler/rustc_hir_analysis/src/collect.rs | 8 +- compiler/rustc_hir_typeck/src/check.rs | 4 +- compiler/rustc_hir_typeck/src/coercion.rs | 5 - compiler/rustc_metadata/src/native_libs.rs | 2 +- compiler/rustc_middle/src/ty/instance.rs | 2 +- compiler/rustc_middle/src/ty/layout.rs | 4 +- compiler/rustc_middle/src/ty/util.rs | 7 +- compiler/rustc_passes/src/check_attr.rs | 2 +- .../rustc_smir/src/rustc_internal/internal.rs | 1 - .../rustc_smir/src/rustc_smir/convert/ty.rs | 1 - compiler/rustc_smir/src/stable_mir/ty.rs | 1 - .../rustc_target/src/callconv/loongarch.rs | 10 +- compiler/rustc_target/src/callconv/mod.rs | 13 +-- compiler/rustc_target/src/callconv/riscv.rs | 10 +- compiler/rustc_target/src/callconv/x86.rs | 11 +- compiler/rustc_target/src/spec/mod.rs | 11 +- compiler/rustc_ty_utils/src/abi.rs | 4 +- src/librustdoc/clean/types.rs | 3 - 23 files changed, 79 insertions(+), 147 deletions(-) diff --git a/compiler/rustc_abi/src/extern_abi.rs b/compiler/rustc_abi/src/extern_abi.rs index 4d70afd4e0bca..55f4845d21670 100644 --- a/compiler/rustc_abi/src/extern_abi.rs +++ b/compiler/rustc_abi/src/extern_abi.rs @@ -60,7 +60,6 @@ pub enum ExternAbi { System { unwind: bool, }, - RustIntrinsic, RustCall, /// *Not* a stable ABI, just directly use the Rust types to describe the ABI for LLVM. Even /// normally ABI-compatible Rust types can become ABI-incompatible with this ABI! @@ -128,7 +127,6 @@ abi_impls! { RiscvInterruptS =><= "riscv-interrupt-s", RustCall =><= "rust-call", RustCold =><= "rust-cold", - RustIntrinsic =><= "rust-intrinsic", Stdcall { unwind: false } =><= "stdcall", Stdcall { unwind: true } =><= "stdcall-unwind", System { unwind: false } =><= "system", @@ -199,7 +197,7 @@ impl ExternAbi { /// - are subject to change between compiler versions pub fn is_rustic_abi(self) -> bool { use ExternAbi::*; - matches!(self, Rust | RustCall | RustIntrinsic | RustCold) + matches!(self, Rust | RustCall | RustCold) } pub fn supports_varargs(self) -> bool { diff --git a/compiler/rustc_ast_lowering/src/stability.rs b/compiler/rustc_ast_lowering/src/stability.rs index a2004bbb39f09..eb052ba1c6d78 100644 --- a/compiler/rustc_ast_lowering/src/stability.rs +++ b/compiler/rustc_ast_lowering/src/stability.rs @@ -79,10 +79,6 @@ pub fn extern_abi_stability(abi: ExternAbi) -> Result<(), UnstableAbi> { | ExternAbi::SysV64 { .. } | ExternAbi::System { .. } | ExternAbi::EfiApi => Ok(()), - // implementation details - ExternAbi::RustIntrinsic => { - Err(UnstableAbi { abi, feature: sym::intrinsics, explain: GateReason::ImplDetail }) - } ExternAbi::Unadjusted => { Err(UnstableAbi { abi, feature: sym::abi_unadjusted, explain: GateReason::ImplDetail }) } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index a079865676304..e3ed20e1b318d 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -741,10 +741,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { for &assoc_item in assoc_items.in_definition_order() { match assoc_item.kind { - ty::AssocKind::Fn => { - let abi = tcx.fn_sig(assoc_item.def_id).skip_binder().abi(); - forbid_intrinsic_abi(tcx, assoc_item.ident(tcx).span, abi); - } ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => { let trait_args = GenericArgs::identity_for_item(tcx, def_id); let _: Result<_, rustc_errors::ErrorGuaranteed> = check_type_bounds( @@ -788,65 +784,59 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { }; check_abi(tcx, it.span, abi); - match abi { - ExternAbi::RustIntrinsic => { - for item in items { - intrinsic::check_intrinsic_type( - tcx, - item.id.owner_id.def_id, - item.span, - item.ident.name, - abi, - ); - } + for item in items { + let def_id = item.id.owner_id.def_id; + + if tcx.has_attr(def_id, sym::rustc_intrinsic) { + intrinsic::check_intrinsic_type( + tcx, + item.id.owner_id.def_id, + item.span, + item.ident.name, + abi, + ); } - _ => { - for item in items { - let def_id = item.id.owner_id.def_id; - let generics = tcx.generics_of(def_id); - let own_counts = generics.own_counts(); - if generics.own_params.len() - own_counts.lifetimes != 0 { - let (kinds, kinds_pl, egs) = match (own_counts.types, own_counts.consts) - { - (_, 0) => ("type", "types", Some("u32")), - // We don't specify an example value, because we can't generate - // a valid value for any type. - (0, _) => ("const", "consts", None), - _ => ("type or const", "types or consts", None), - }; - struct_span_code_err!( - tcx.dcx(), - item.span, - E0044, - "foreign items may not have {kinds} parameters", - ) - .with_span_label(item.span, format!("can't have {kinds} parameters")) - .with_help( - // FIXME: once we start storing spans for type arguments, turn this - // into a suggestion. - format!( - "replace the {} parameters with concrete {}{}", - kinds, - kinds_pl, - egs.map(|egs| format!(" like `{egs}`")).unwrap_or_default(), - ), - ) - .emit(); - } + let generics = tcx.generics_of(def_id); + let own_counts = generics.own_counts(); + if generics.own_params.len() - own_counts.lifetimes != 0 { + let (kinds, kinds_pl, egs) = match (own_counts.types, own_counts.consts) { + (_, 0) => ("type", "types", Some("u32")), + // We don't specify an example value, because we can't generate + // a valid value for any type. + (0, _) => ("const", "consts", None), + _ => ("type or const", "types or consts", None), + }; + struct_span_code_err!( + tcx.dcx(), + item.span, + E0044, + "foreign items may not have {kinds} parameters", + ) + .with_span_label(item.span, format!("can't have {kinds} parameters")) + .with_help( + // FIXME: once we start storing spans for type arguments, turn this + // into a suggestion. + format!( + "replace the {} parameters with concrete {}{}", + kinds, + kinds_pl, + egs.map(|egs| format!(" like `{egs}`")).unwrap_or_default(), + ), + ) + .emit(); + } - let item = tcx.hir_foreign_item(item.id); - match &item.kind { - hir::ForeignItemKind::Fn(sig, _, _) => { - require_c_abi_if_c_variadic(tcx, sig.decl, abi, item.span); - } - hir::ForeignItemKind::Static(..) => { - check_static_inhabited(tcx, def_id); - check_static_linkage(tcx, def_id); - } - _ => {} - } + let item = tcx.hir_foreign_item(item.id); + match &item.kind { + hir::ForeignItemKind::Fn(sig, _, _) => { + require_c_abi_if_c_variadic(tcx, sig.decl, abi, item.span); + } + hir::ForeignItemKind::Static(..) => { + check_static_inhabited(tcx, def_id); + check_static_linkage(tcx, def_id); } + _ => {} } } } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 42d785c8dd0fe..0bf9e127989f0 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -1,4 +1,4 @@ -//! Type-checking for the rust-intrinsic intrinsics that the compiler exposes. +//! Type-checking for the `#[rustc_intrinsic]` intrinsics that the compiler exposes. use rustc_abi::ExternAbi; use rustc_errors::codes::*; diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 7c5d7b33a34d3..30921b6f055d5 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -137,15 +137,6 @@ fn get_owner_return_paths( }) } -/// Forbid defining intrinsics in Rust code, -/// as they must always be defined by the compiler. -// FIXME: Move this to a more appropriate place. -pub fn forbid_intrinsic_abi(tcx: TyCtxt<'_>, sp: Span, abi: ExternAbi) { - if let ExternAbi::RustIntrinsic = abi { - tcx.dcx().span_err(sp, "intrinsic must be in `extern \"rust-intrinsic\" { ... }` block"); - } -} - pub(super) fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) { // Only restricted on wasm target for now if !tcx.sess.target.is_like_wasm { diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 625f51dd29eac..e9cd22435d958 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -42,7 +42,6 @@ use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::ObligationCtxt; use tracing::{debug, instrument}; -use crate::check::intrinsic::intrinsic_operation_unsafety; use crate::errors; use crate::hir_ty_lowering::errors::assoc_kind_str; use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer, RegionInferReason}; @@ -1704,18 +1703,13 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( abi: ExternAbi, safety: hir::Safety, ) -> ty::PolyFnSig<'tcx> { - let safety = if abi == ExternAbi::RustIntrinsic { - intrinsic_operation_unsafety(tcx, def_id) - } else { - safety - }; let hir_id = tcx.local_def_id_to_hir_id(def_id); let fty = ItemCtxt::new(tcx, def_id).lowerer().lower_fn_ty(hir_id, safety, abi, decl, None, None); // Feature gate SIMD types in FFI, since I am not sure that the // ABIs are handled at all correctly. -huonw - if abi != ExternAbi::RustIntrinsic && !tcx.features().simd_ffi() { + if !tcx.features().simd_ffi() { let check = |hir_ty: &hir::Ty<'_>, ty: Ty<'_>| { if ty.is_simd() { let snip = tcx diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index dabae7b1d094c..2189fdf0f3439 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -5,7 +5,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; -use rustc_hir_analysis::check::{check_function_signature, forbid_intrinsic_abi}; +use rustc_hir_analysis::check::check_function_signature; use rustc_infer::infer::RegionVariableOrigin; use rustc_infer::traits::WellFormedLoc; use rustc_middle::ty::{self, Binder, Ty, TyCtxt}; @@ -50,8 +50,6 @@ pub(super) fn check_fn<'a, 'tcx>( let span = body.value.span; - forbid_intrinsic_abi(tcx, span, fn_sig.abi); - GatherLocalsVisitor::new(fcx).visit_body(body); // C-variadic fns also have a `VaList` input that's not listed in `fn_sig` diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index f42ca3af2b35c..f1571cf4c8317 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -37,7 +37,6 @@ use std::ops::Deref; -use rustc_abi::ExternAbi; use rustc_attr_parsing::InlineAttr; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, struct_span_code_err}; @@ -1240,10 +1239,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; if let (Some(a_sig), Some(b_sig)) = (a_sig, b_sig) { - // Intrinsics are not coercible to function pointers. - if a_sig.abi() == ExternAbi::RustIntrinsic || b_sig.abi() == ExternAbi::RustIntrinsic { - return Err(TypeError::IntrinsicCast); - } // The signature must match. let (a_sig, b_sig) = self.normalize(new.span, (a_sig, b_sig)); let sig = self diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 130a425e9c74a..cfb0de8475c8f 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -207,7 +207,7 @@ impl<'tcx> Collector<'tcx> { let sess = self.tcx.sess; - if matches!(abi, ExternAbi::Rust | ExternAbi::RustIntrinsic) { + if matches!(abi, ExternAbi::Rust) { return; } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 55ebd15248c61..07f2a602f2bf2 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -71,7 +71,7 @@ pub enum InstanceKind<'tcx> { /// - coroutines Item(DefId), - /// An intrinsic `fn` item (with `"rust-intrinsic"` ABI). + /// An intrinsic `fn` item (with`#[rustc_instrinsic]`). /// /// Alongside `Virtual`, this is the only `InstanceKind` that does not have its own callable MIR. /// Instead, codegen and const eval "magically" evaluate calls to intrinsics purely in the diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index ebb6a8c08a54c..7ebfebea44e56 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1265,9 +1265,7 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option, abi: ExternAbi) | CCmseNonSecureCall | CCmseNonSecureEntry | Unadjusted => false, - Rust | RustCall | RustCold | RustIntrinsic => { - tcx.sess.panic_strategy() == PanicStrategy::Unwind - } + Rust | RustCall | RustCold => tcx.sess.panic_strategy() == PanicStrategy::Unwind, } } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index e4863896fc8b3..857b462b9eb1e 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -2,7 +2,7 @@ use std::{fmt, iter}; -use rustc_abi::{ExternAbi, Float, Integer, IntegerType, Size}; +use rustc_abi::{Float, Integer, IntegerType, Size}; use rustc_apfloat::Float as _; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -1719,10 +1719,7 @@ pub fn is_doc_notable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool { /// the compiler to make some assumptions about its shape; if the user doesn't use a feature gate, they may /// cause an ICE that we otherwise may want to prevent. pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { - if tcx.features().intrinsics() - && (matches!(tcx.fn_sig(def_id).skip_binder().abi(), ExternAbi::RustIntrinsic) - || tcx.has_attr(def_id, sym::rustc_intrinsic)) - { + if tcx.features().intrinsics() && tcx.has_attr(def_id, sym::rustc_intrinsic) { let must_be_overridden = match tcx.hir_node_by_def_id(def_id) { hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { has_body, .. }, .. }) => { !has_body diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 669349f3380aa..9161b23428a00 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1598,7 +1598,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { if target == Target::ForeignMod && let hir::Node::Item(item) = self.tcx.hir_node(hir_id) && let Item { kind: ItemKind::ForeignMod { abi, .. }, .. } = item - && !matches!(abi, ExternAbi::Rust | ExternAbi::RustIntrinsic) + && !matches!(abi, ExternAbi::Rust) { return; } diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index 36b68cc139826..6e13b87c41d73 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -491,7 +491,6 @@ impl RustcInternal for Abi { Abi::CCmseNonSecureCall => rustc_abi::ExternAbi::CCmseNonSecureCall, Abi::CCmseNonSecureEntry => rustc_abi::ExternAbi::CCmseNonSecureEntry, Abi::System { unwind } => rustc_abi::ExternAbi::System { unwind }, - Abi::RustIntrinsic => rustc_abi::ExternAbi::RustIntrinsic, Abi::RustCall => rustc_abi::ExternAbi::RustCall, Abi::Unadjusted => rustc_abi::ExternAbi::Unadjusted, Abi::RustCold => rustc_abi::ExternAbi::RustCold, diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index 1ba25aa0e971a..28fc68d5e491b 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -871,7 +871,6 @@ impl<'tcx> Stable<'tcx> for rustc_abi::ExternAbi { ExternAbi::CCmseNonSecureCall => Abi::CCmseNonSecureCall, ExternAbi::CCmseNonSecureEntry => Abi::CCmseNonSecureEntry, ExternAbi::System { unwind } => Abi::System { unwind }, - ExternAbi::RustIntrinsic => Abi::RustIntrinsic, ExternAbi::RustCall => Abi::RustCall, ExternAbi::Unadjusted => Abi::Unadjusted, ExternAbi::RustCold => Abi::RustCold, diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 1efa2fe13c565..3fcbbb0e138be 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -1093,7 +1093,6 @@ pub enum Abi { CCmseNonSecureCall, CCmseNonSecureEntry, System { unwind: bool }, - RustIntrinsic, RustCall, Unadjusted, RustCold, diff --git a/compiler/rustc_target/src/callconv/loongarch.rs b/compiler/rustc_target/src/callconv/loongarch.rs index 209d7483e612a..c779720f97b9c 100644 --- a/compiler/rustc_target/src/callconv/loongarch.rs +++ b/compiler/rustc_target/src/callconv/loongarch.rs @@ -1,6 +1,6 @@ use rustc_abi::{ - BackendRepr, ExternAbi, FieldsShape, HasDataLayout, Primitive, Reg, RegKind, Size, - TyAbiInterface, TyAndLayout, Variants, + BackendRepr, FieldsShape, HasDataLayout, Primitive, Reg, RegKind, Size, TyAbiInterface, + TyAndLayout, Variants, }; use crate::callconv::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Uniform}; @@ -364,15 +364,11 @@ where } } -pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, abi: ExternAbi) +pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, { - if abi == ExternAbi::RustIntrinsic { - return; - } - let grlen = cx.data_layout().pointer_size.bits(); for arg in fn_abi.args.iter_mut() { diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 55e39d093e233..7ecc46cc69db9 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -717,16 +717,16 @@ impl<'a, Ty> FnAbi<'a, Ty> { } } - pub fn adjust_for_rust_abi(&mut self, cx: &C, abi: ExternAbi) + pub fn adjust_for_rust_abi(&mut self, cx: &C) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, { let spec = cx.target_spec(); match &*spec.arch { - "x86" => x86::compute_rust_abi_info(cx, self, abi), - "riscv32" | "riscv64" => riscv::compute_rust_abi_info(cx, self, abi), - "loongarch64" => loongarch::compute_rust_abi_info(cx, self, abi), + "x86" => x86::compute_rust_abi_info(cx, self), + "riscv32" | "riscv64" => riscv::compute_rust_abi_info(cx, self), + "loongarch64" => loongarch::compute_rust_abi_info(cx, self), "aarch64" => aarch64::compute_rust_abi_info(cx, self), _ => {} }; @@ -850,10 +850,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { // // Note that the intrinsic ABI is exempt here as those are not // real functions anyway, and the backend expects very specific types. - if abi != ExternAbi::RustIntrinsic - && spec.simd_types_indirect - && !can_pass_simd_directly(arg) - { + if spec.simd_types_indirect && !can_pass_simd_directly(arg) { arg.make_indirect(); } } diff --git a/compiler/rustc_target/src/callconv/riscv.rs b/compiler/rustc_target/src/callconv/riscv.rs index 7368e225efa74..cd1d3cd1eee05 100644 --- a/compiler/rustc_target/src/callconv/riscv.rs +++ b/compiler/rustc_target/src/callconv/riscv.rs @@ -5,8 +5,8 @@ // https://github.com/llvm/llvm-project/blob/8e780252a7284be45cf1ba224cabd884847e8e92/clang/lib/CodeGen/TargetInfo.cpp#L9311-L9773 use rustc_abi::{ - BackendRepr, ExternAbi, FieldsShape, HasDataLayout, Primitive, Reg, RegKind, Size, - TyAbiInterface, TyAndLayout, Variants, + BackendRepr, FieldsShape, HasDataLayout, Primitive, Reg, RegKind, Size, TyAbiInterface, + TyAndLayout, Variants, }; use crate::callconv::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Uniform}; @@ -370,15 +370,11 @@ where } } -pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, abi: ExternAbi) +pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, { - if abi == ExternAbi::RustIntrinsic { - return; - } - let xlen = cx.data_layout().pointer_size.bits(); for arg in fn_abi.args.iter_mut() { diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs index ba3c140621129..8328f818f9b8f 100644 --- a/compiler/rustc_target/src/callconv/x86.rs +++ b/compiler/rustc_target/src/callconv/x86.rs @@ -1,6 +1,6 @@ use rustc_abi::{ - AddressSpace, Align, BackendRepr, ExternAbi, HasDataLayout, Primitive, Reg, RegKind, - TyAbiInterface, TyAndLayout, + AddressSpace, Align, BackendRepr, HasDataLayout, Primitive, Reg, RegKind, TyAbiInterface, + TyAndLayout, }; use crate::callconv::{ArgAttribute, FnAbi, PassMode}; @@ -193,7 +193,7 @@ pub(crate) fn fill_inregs<'a, Ty, C>( } } -pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, abi: ExternAbi) +pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, @@ -201,10 +201,7 @@ where // Avoid returning floats in x87 registers on x86 as loading and storing from x87 // registers will quiet signalling NaNs. Also avoid using SSE registers since they // are not always available (depending on target features). - if !fn_abi.ret.is_ignore() - // Intrinsics themselves are not "real" functions, so theres no need to change their ABIs. - && abi != ExternAbi::RustIntrinsic - { + if !fn_abi.ret.is_ignore() { let has_float = match fn_abi.ret.layout.backend_repr { BackendRepr::Scalar(s) => matches!(s.primitive(), Primitive::Float(_)), BackendRepr::ScalarPair(s1, s2) => { diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 79f73ef28b36f..64171fcc7ab34 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2962,14 +2962,9 @@ impl Target { pub fn is_abi_supported(&self, abi: ExternAbi) -> bool { use ExternAbi::*; match abi { - Rust - | C { .. } - | System { .. } - | RustIntrinsic - | RustCall - | Unadjusted - | Cdecl { .. } - | RustCold => true, + Rust | C { .. } | System { .. } | RustCall | Unadjusted | Cdecl { .. } | RustCold => { + true + } EfiApi => { ["arm", "aarch64", "riscv32", "riscv64", "x86", "x86_64"].contains(&&self.arch[..]) } diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 48d5a4a0fcb0d..3d4ab33240af2 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -244,7 +244,7 @@ fn fn_sig_for_fn_abi<'tcx>( fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: ExternAbi, c_variadic: bool) -> Conv { use rustc_abi::ExternAbi::*; match tcx.sess.target.adjust_abi(abi, c_variadic) { - RustIntrinsic | Rust | RustCall => Conv::Rust, + Rust | RustCall => Conv::Rust, // This is intentionally not using `Conv::Cold`, as that has to preserve // even SIMD registers, which is generally not a good trade-off. @@ -660,7 +660,7 @@ fn fn_abi_adjust_for_abi<'tcx>( let tcx = cx.tcx(); if abi.is_rustic_abi() { - fn_abi.adjust_for_rust_abi(cx, abi); + fn_abi.adjust_for_rust_abi(cx); // Look up the deduced parameter attributes for this function, if we have its def ID and // we're optimizing in non-incremental mode. We'll tag its parameters with those attributes diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index d3ddb77c0b33c..06e75fe1764e0 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -11,7 +11,6 @@ use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::{BodyId, Mutability}; -use rustc_hir_analysis::check::intrinsic::intrinsic_operation_unsafety; use rustc_index::IndexVec; use rustc_metadata::rendered_const; use rustc_middle::span_bug; @@ -687,8 +686,6 @@ impl Item { hir::FnHeader { safety: if tcx.codegen_fn_attrs(def_id).safe_target_features { hir::HeaderSafety::SafeTargetFeatures - } else if abi == ExternAbi::RustIntrinsic { - intrinsic_operation_unsafety(tcx, def_id.expect_local()).into() } else { safety.into() }, From 51b51b51d7931da85280382a81c4dd80c73ca754 Mon Sep 17 00:00:00 2001 From: Skgland <3877590+Skgland@users.noreply.github.com> Date: Sun, 6 Apr 2025 21:34:00 +0200 Subject: [PATCH 16/23] remove rust-analyser support for `extern "rust-intrinsic"` blocks --- .../rust-analyzer/crates/hir-ty/src/lib.rs | 3 --- .../crates/hir-ty/src/mir/eval/shim.rs | 14 +--------- .../rust-analyzer/crates/hir-ty/src/utils.rs | 26 +++++-------------- .../src/completions/extern_abi.rs | 1 - .../crates/intern/src/symbol/symbols.rs | 1 - 5 files changed, 7 insertions(+), 38 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index cc02b71f05c19..e4c50f2ebdb44 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -400,7 +400,6 @@ pub enum FnAbi { Rust, RustCall, RustCold, - RustIntrinsic, Stdcall, StdcallUnwind, System, @@ -457,7 +456,6 @@ impl FnAbi { s if *s == sym::riscv_dash_interrupt_dash_s => FnAbi::RiscvInterruptS, s if *s == sym::rust_dash_call => FnAbi::RustCall, s if *s == sym::rust_dash_cold => FnAbi::RustCold, - s if *s == sym::rust_dash_intrinsic => FnAbi::RustIntrinsic, s if *s == sym::Rust => FnAbi::Rust, s if *s == sym::stdcall_dash_unwind => FnAbi::StdcallUnwind, s if *s == sym::stdcall => FnAbi::Stdcall, @@ -500,7 +498,6 @@ impl FnAbi { FnAbi::Rust => "Rust", FnAbi::RustCall => "rust-call", FnAbi::RustCold => "rust-cold", - FnAbi::RustIntrinsic => "rust-intrinsic", FnAbi::Stdcall => "stdcall", FnAbi::StdcallUnwind => "stdcall-unwind", FnAbi::System => "system", diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs index f61ecabb7e41d..06ac5b1ffad90 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs @@ -59,19 +59,7 @@ impl Evaluator<'_> { let function_data = self.db.function_data(def); let attrs = self.db.attrs(def.into()); - let is_intrinsic = attrs.by_key(&sym::rustc_intrinsic).exists() - // Keep this around for a bit until extern "rustc-intrinsic" abis are no longer used - || (match &function_data.abi { - Some(abi) => *abi == sym::rust_dash_intrinsic, - None => match def.lookup(self.db.upcast()).container { - hir_def::ItemContainerId::ExternBlockId(block) => { - let id = block.lookup(self.db.upcast()).id; - id.item_tree(self.db.upcast())[id.value].abi.as_ref() - == Some(&sym::rust_dash_intrinsic) - } - _ => false, - }, - }); + let is_intrinsic = attrs.by_key(&sym::rustc_intrinsic).exists(); if is_intrinsic { return self.exec_intrinsic( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs index 89d89fe2230af..0cfd36d9166b8 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs @@ -18,7 +18,6 @@ use hir_def::{ TypeOrConstParamId, }; use hir_expand::name::Name; -use intern::sym; use rustc_abi::TargetDataLayout; use rustc_hash::FxHashSet; use smallvec::{smallvec, SmallVec}; @@ -303,26 +302,13 @@ pub fn is_fn_unsafe_to_call( let loc = func.lookup(db.upcast()); match loc.container { - hir_def::ItemContainerId::ExternBlockId(block) => { - let id = block.lookup(db.upcast()).id; - let is_intrinsic_block = - id.item_tree(db.upcast())[id.value].abi.as_ref() == Some(&sym::rust_dash_intrinsic); - if is_intrinsic_block { - // legacy intrinsics - // extern "rust-intrinsic" intrinsics are unsafe unless they have the rustc_safe_intrinsic attribute - if db.attrs(func.into()).by_key(&sym::rustc_safe_intrinsic).exists() { - Unsafety::Safe - } else { - Unsafety::Unsafe - } + hir_def::ItemContainerId::ExternBlockId(_block) => { + // Function in an `extern` block are always unsafe to call, except when + // it is marked as `safe`. + if data.is_safe() { + Unsafety::Safe } else { - // Function in an `extern` block are always unsafe to call, except when - // it is marked as `safe`. - if data.is_safe() { - Unsafety::Safe - } else { - Unsafety::Unsafe - } + Unsafety::Unsafe } } _ => Unsafety::Safe, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs index 7c2cc2a6c1d8f..a3554114f4c36 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs @@ -36,7 +36,6 @@ const SUPPORTED_CALLING_CONVENTIONS: &[&str] = &[ "wasm", "system", "system-unwind", - "rust-intrinsic", "rust-call", "unadjusted", ]; diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs index 6b77c72cee897..d4f334289f034 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs @@ -125,7 +125,6 @@ define_symbols! { riscv_dash_interrupt_dash_s = "riscv-interrupt-s", rust_dash_call = "rust-call", rust_dash_cold = "rust-cold", - rust_dash_intrinsic = "rust-intrinsic", stdcall_dash_unwind = "stdcall-unwind", system_dash_unwind = "system-unwind", sysv64_dash_unwind = "sysv64-unwind", From 6dfb29624cf2fd1b6d2f31e6321bcef5e4a4a84e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bennet=20Ble=C3=9Fmann?= Date: Sun, 6 Apr 2025 15:10:23 +0200 Subject: [PATCH 17/23] update docs - src\doc\nomicon\src\ffi.md should also have its ABI list updated --- .../src/intrinsics/mod.rs | 3 +- compiler/rustc_feature/src/unstable.rs | 2 +- library/core/src/intrinsics/mod.rs | 1 + .../src/language-features/intrinsics.md | 30 ++----------------- .../crates/ide/src/hover/tests.rs | 28 ++--------------- 5 files changed, 7 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 75f3a3c19724f..d3f47ad726334 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -1,5 +1,4 @@ -//! Codegen of intrinsics. This includes `extern "rust-intrinsic"`, -//! functions marked with the `#[rustc_intrinsic]` attribute +//! Codegen of intrinsics. This includes functions marked with the `#[rustc_intrinsic]` attribute //! and LLVM intrinsics that have symbol names starting with `llvm.`. macro_rules! intrinsic_args { diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 710e129b609fe..77d8965602ccb 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -211,7 +211,7 @@ declare_features! ( (internal, custom_mir, "1.65.0", None), /// Outputs useful `assert!` messages (unstable, generic_assert, "1.63.0", None), - /// Allows using the `rust-intrinsic`'s "ABI". + /// Allows using the #[rustc_intrinsic] attribute. (internal, intrinsics, "1.0.0", None), /// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic. (internal, lang_items, "1.0.0", None), diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index afd6192d7c473..7fa57df9928c3 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -8,6 +8,7 @@ //! Note: any changes to the constness of intrinsics should be discussed with the language team. //! This includes changes in the stability of the constness. //! +//! //FIXME(#132735) "old" style intrinsics support has been removed //! In order to make an intrinsic usable at compile-time, it needs to be declared in the "new" //! style, i.e. as a `#[rustc_intrinsic]` function, not inside an `extern` block. Then copy the //! implementation from to diff --git a/src/doc/unstable-book/src/language-features/intrinsics.md b/src/doc/unstable-book/src/language-features/intrinsics.md index 975b400447eb8..a0e38f340f581 100644 --- a/src/doc/unstable-book/src/language-features/intrinsics.md +++ b/src/doc/unstable-book/src/language-features/intrinsics.md @@ -52,9 +52,8 @@ with any regular function. Various intrinsics have native MIR operations that they correspond to. Instead of requiring backends to implement both the intrinsic and the MIR operation, the `lower_intrinsics` pass will convert the calls to the MIR operation. Backends do not need to know about these intrinsics -at all. These intrinsics only make sense without a body, and can either be declared as a "rust-intrinsic" -or as a `#[rustc_intrinsic]`. The body is never used, as calls to the intrinsic do not exist -anymore after MIR analyses. +at all. These intrinsics only make sense without a body, and can be declared as a `#[rustc_intrinsic]`. +The body is never used, as calls to the intrinsic do not exist anymore after MIR analyses. ## Intrinsics without fallback logic @@ -70,28 +69,3 @@ These are written without a body: #[rustc_intrinsic] pub fn abort() -> !; ``` - -### Legacy extern ABI based intrinsics - -*This style is deprecated, always prefer the above form.* - -These are imported as if they were FFI functions, with the special -`rust-intrinsic` ABI. For example, if one was in a freestanding -context, but wished to be able to `transmute` between types, and -perform efficient pointer arithmetic, one would import those functions -via a declaration like - -```rust -#![feature(intrinsics)] -#![allow(internal_features)] -# fn main() {} - -extern "rust-intrinsic" { - fn transmute(x: T) -> U; - - fn arith_offset(dst: *const T, offset: isize) -> *const T; -} -``` - -As with any other FFI functions, these are by default always `unsafe` to call. -You can add `#[rustc_safe_intrinsic]` to the intrinsic to make it safe to call. diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index 6b470d921f7a7..5dfd826d7f966 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -6945,9 +6945,8 @@ fn hover_feature() { Various intrinsics have native MIR operations that they correspond to. Instead of requiring backends to implement both the intrinsic and the MIR operation, the `lower_intrinsics` pass will convert the calls to the MIR operation. Backends do not need to know about these intrinsics - at all. These intrinsics only make sense without a body, and can either be declared as a "rust-intrinsic" - or as a `#[rustc_intrinsic]`. The body is never used, as calls to the intrinsic do not exist - anymore after MIR analyses. + at all. These intrinsics only make sense without a body, and can be as a `#[rustc_intrinsic]`. + The body is never used, as calls to the intrinsic do not exist anymore after MIR analyses. ## Intrinsics without fallback logic @@ -6960,29 +6959,6 @@ fn hover_feature() { `#[rustc_intrinsic_must_be_overridden]` to the function to ensure that backends don't invoke the body. - ### Legacy extern ABI based intrinsics - - These are imported as if they were FFI functions, with the special - `rust-intrinsic` ABI. For example, if one was in a freestanding - context, but wished to be able to `transmute` between types, and - perform efficient pointer arithmetic, one would import those functions - via a declaration like - - ```rust - #![feature(intrinsics)] - #![allow(internal_features)] - # fn main() {} - - extern "rust-intrinsic" { - fn transmute(x: T) -> U; - - fn arith_offset(dst: *const T, offset: isize) -> *const T; - } - ``` - - As with any other FFI functions, these are by default always `unsafe` to call. - You can add `#[rustc_safe_intrinsic]` to the intrinsic to make it safe to call. - "#]], ) } From 7dd57f085cab4cc671b01d6dd27977c76d04de28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bennet=20Ble=C3=9Fmann?= Date: Sun, 6 Apr 2025 15:12:24 +0200 Subject: [PATCH 18/23] update/bless tests --- .../src/error_codes/E0622.md | 10 +- tests/assembly/simd-bitmask.rs | 5 +- tests/assembly/simd-intrinsic-gather.rs | 5 +- tests/assembly/simd-intrinsic-mask-load.rs | 5 +- tests/assembly/simd-intrinsic-mask-reduce.rs | 8 +- tests/assembly/simd-intrinsic-mask-store.rs | 5 +- tests/assembly/simd-intrinsic-scatter.rs | 5 +- tests/assembly/simd-intrinsic-select.rs | 5 +- tests/codegen/avr/avr-func-addrspace.rs | 5 +- .../codegen/emscripten-catch-unwind-js-eh.rs | 13 +- .../emscripten-catch-unwind-wasm-eh.rs | 14 +- tests/codegen/intrinsic-no-unnamed-attr.rs | 6 +- tests/codegen/intrinsics/nontemporal.rs | 5 +- tests/mir-opt/lower_intrinsics.rs | 9 +- .../atomic-lock-free/atomic_lock_free.rs | 5 +- .../avr-rjmp-offset/avr-rjmp-offsets.rs | 7 +- ...abi-typo-unstable.feature_disabled.stderr} | 8 +- .../abi-typo-unstable.feature_enabled.stderr | 16 + tests/ui/abi/abi-typo-unstable.rs | 11 +- ...sociated-types-in-ambiguous-context.stderr | 36 +- ...ice-mutability-error-slicing-121807.stderr | 12 +- .../trait-impl-argument-difference-ice.stderr | 12 +- tests/ui/delegation/ice-issue-124347.rs | 1 - tests/ui/delegation/ice-issue-124347.stderr | 12 +- ...-fn-inputs-and-outputs-issue-125139.stderr | 320 +++++++++--------- tests/ui/error-codes/E0092.rs | 9 +- tests/ui/error-codes/E0092.stderr | 6 +- tests/ui/error-codes/E0093.rs | 11 +- tests/ui/error-codes/E0093.stderr | 6 +- tests/ui/error-codes/E0622.rs | 14 +- tests/ui/error-codes/E0622.stderr | 6 +- tests/ui/extern/extern-with-type-bounds.rs | 21 -- .../ui/extern/extern-with-type-bounds.stderr | 9 - tests/ui/feature-gates/feature-gate-abi.rs | 21 -- .../ui/feature-gates/feature-gate-abi.stderr | 172 +--------- .../feature-gates/feature-gate-intrinsics.rs | 9 +- .../feature-gate-intrinsics.stderr | 36 +- .../feature-gated-feature-in-macro-arg.rs | 6 +- .../feature-gated-feature-in-macro-arg.stderr | 10 +- tests/ui/intrinsics/always-extern.rs | 17 - tests/ui/intrinsics/always-extern.stderr | 34 -- .../ui/intrinsics/auxiliary/cci_intrinsic.rs | 9 +- .../incorrect-read_via_copy-defn.rs | 7 +- .../incorrect-read_via_copy-defn.stderr | 21 +- tests/ui/intrinsics/incorrect-transmute.rs | 7 +- .../ui/intrinsics/incorrect-transmute.stderr | 21 +- tests/ui/intrinsics/intrinsic-atomics.rs | 74 ++-- .../intrinsics/invalid-ABI-rust-intrinsic.rs | 19 ++ .../invalid-ABI-rust-intrinsic.stderr | 35 ++ tests/ui/intrinsics/issue-28575.rs | 1 + tests/ui/intrinsics/issue-28575.stderr | 15 +- .../ui/intrinsics/safe-intrinsic-mismatch.rs | 11 +- .../intrinsics/safe-intrinsic-mismatch.stderr | 21 +- tests/ui/lint/internal_features.rs | 5 +- tests/ui/print-calling-conventions.stdout | 1 - ...it-should-use-self-2021-without-dyn.stderr | 56 +-- tests/ui/suggestions/issue-116434-2015.stderr | 26 +- .../typeck_type_placeholder_item.stderr | 24 +- ...ir-wf-check-anon-const-issue-122199.stderr | 12 +- 59 files changed, 550 insertions(+), 742 deletions(-) rename tests/ui/abi/{abi-typo-unstable.stderr => abi-typo-unstable.feature_disabled.stderr} (55%) create mode 100644 tests/ui/abi/abi-typo-unstable.feature_enabled.stderr delete mode 100644 tests/ui/extern/extern-with-type-bounds.rs delete mode 100644 tests/ui/extern/extern-with-type-bounds.stderr delete mode 100644 tests/ui/intrinsics/always-extern.rs delete mode 100644 tests/ui/intrinsics/always-extern.stderr create mode 100644 tests/ui/intrinsics/invalid-ABI-rust-intrinsic.rs create mode 100644 tests/ui/intrinsics/invalid-ABI-rust-intrinsic.stderr diff --git a/compiler/rustc_error_codes/src/error_codes/E0622.md b/compiler/rustc_error_codes/src/error_codes/E0622.md index 4cb605b636d2e..e6ff949d3e9f9 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0622.md +++ b/compiler/rustc_error_codes/src/error_codes/E0622.md @@ -6,8 +6,9 @@ Erroneous code example: #![feature(intrinsics)] #![allow(internal_features)] -extern "rust-intrinsic" { - pub static atomic_singlethreadfence_seqcst: fn(); +extern "C" { + #[rustc_intrinsic] + pub static atomic_singlethreadfence_seqcst: unsafe fn(); // error: intrinsic must be a function } @@ -22,9 +23,8 @@ error, just declare a function. Example: #![feature(intrinsics)] #![allow(internal_features)] -extern "rust-intrinsic" { - pub fn atomic_singlethreadfence_seqcst(); // ok! -} +#[rustc_intrinsic] +pub unsafe fn atomic_singlethreadfence_seqcst(); // ok! fn main() { unsafe { atomic_singlethreadfence_seqcst(); } } ``` diff --git a/tests/assembly/simd-bitmask.rs b/tests/assembly/simd-bitmask.rs index a632791153b2e..e412246108700 100644 --- a/tests/assembly/simd-bitmask.rs +++ b/tests/assembly/simd-bitmask.rs @@ -35,9 +35,8 @@ pub struct m64x2([i64; 2]); #[repr(simd)] pub struct m64x4([i64; 4]); -extern "rust-intrinsic" { - fn simd_bitmask(mask: V) -> B; -} +#[rustc_intrinsic] +unsafe fn simd_bitmask(mask: V) -> B; // CHECK-LABEL: bitmask_m8x16 #[no_mangle] diff --git a/tests/assembly/simd-intrinsic-gather.rs b/tests/assembly/simd-intrinsic-gather.rs index 8c17a58046d8b..bcab0ba1cc09b 100644 --- a/tests/assembly/simd-intrinsic-gather.rs +++ b/tests/assembly/simd-intrinsic-gather.rs @@ -22,9 +22,8 @@ pub struct m64x4([i64; 4]); #[repr(simd)] pub struct pf64x4([*const f64; 4]); -extern "rust-intrinsic" { - fn simd_gather(values: V, mask: M, pointer: P) -> V; -} +#[rustc_intrinsic] +unsafe fn simd_gather(values: V, mask: M, pointer: P) -> V; // CHECK-LABEL: gather_f64x4 #[no_mangle] diff --git a/tests/assembly/simd-intrinsic-mask-load.rs b/tests/assembly/simd-intrinsic-mask-load.rs index a0d0514c0141d..d3f3453a780a4 100644 --- a/tests/assembly/simd-intrinsic-mask-load.rs +++ b/tests/assembly/simd-intrinsic-mask-load.rs @@ -34,9 +34,8 @@ pub struct f64x4([f64; 4]); #[repr(simd)] pub struct m64x4([i64; 4]); -extern "rust-intrinsic" { - fn simd_masked_load(mask: M, pointer: P, values: T) -> T; -} +#[rustc_intrinsic] +unsafe fn simd_masked_load(mask: M, pointer: P, values: T) -> T; // CHECK-LABEL: load_i8x16 #[no_mangle] diff --git a/tests/assembly/simd-intrinsic-mask-reduce.rs b/tests/assembly/simd-intrinsic-mask-reduce.rs index 959c4ddefdb0e..8b15ed0a254c6 100644 --- a/tests/assembly/simd-intrinsic-mask-reduce.rs +++ b/tests/assembly/simd-intrinsic-mask-reduce.rs @@ -20,10 +20,10 @@ use minicore::*; #[repr(simd)] pub struct mask8x16([i8; 16]); -extern "rust-intrinsic" { - fn simd_reduce_all(x: T) -> bool; - fn simd_reduce_any(x: T) -> bool; -} +#[rustc_intrinsic] +unsafe fn simd_reduce_all(x: T) -> bool; +#[rustc_intrinsic] +unsafe fn simd_reduce_any(x: T) -> bool; // CHECK-LABEL: mask_reduce_all: #[no_mangle] diff --git a/tests/assembly/simd-intrinsic-mask-store.rs b/tests/assembly/simd-intrinsic-mask-store.rs index 4be9194943c78..001762e5060db 100644 --- a/tests/assembly/simd-intrinsic-mask-store.rs +++ b/tests/assembly/simd-intrinsic-mask-store.rs @@ -34,9 +34,8 @@ pub struct f64x4([f64; 4]); #[repr(simd)] pub struct m64x4([i64; 4]); -extern "rust-intrinsic" { - fn simd_masked_store(mask: M, pointer: P, values: T); -} +#[rustc_intrinsic] +unsafe fn simd_masked_store(mask: M, pointer: P, values: T); // CHECK-LABEL: store_i8x16 #[no_mangle] diff --git a/tests/assembly/simd-intrinsic-scatter.rs b/tests/assembly/simd-intrinsic-scatter.rs index 715de04af4d76..d77dfad3546d8 100644 --- a/tests/assembly/simd-intrinsic-scatter.rs +++ b/tests/assembly/simd-intrinsic-scatter.rs @@ -22,9 +22,8 @@ pub struct m64x4([i64; 4]); #[repr(simd)] pub struct pf64x4([*mut f64; 4]); -extern "rust-intrinsic" { - fn simd_scatter(values: V, pointer: P, mask: M); -} +#[rustc_intrinsic] +unsafe fn simd_scatter(values: V, pointer: P, mask: M); // CHECK-LABEL: scatter_f64x4 #[no_mangle] diff --git a/tests/assembly/simd-intrinsic-select.rs b/tests/assembly/simd-intrinsic-select.rs index 7f1e42662bfb3..4f8d6b825b611 100644 --- a/tests/assembly/simd-intrinsic-select.rs +++ b/tests/assembly/simd-intrinsic-select.rs @@ -48,9 +48,8 @@ pub struct f64x8([f64; 8]); #[repr(simd)] pub struct m64x8([i64; 8]); -extern "rust-intrinsic" { - fn simd_select(mask: M, a: V, b: V) -> V; -} +#[rustc_intrinsic] +unsafe fn simd_select(mask: M, a: V, b: V) -> V; // CHECK-LABEL: select_i8x16 #[no_mangle] diff --git a/tests/codegen/avr/avr-func-addrspace.rs b/tests/codegen/avr/avr-func-addrspace.rs index 2ae2f40d7b349..e0192f8b45ab8 100644 --- a/tests/codegen/avr/avr-func-addrspace.rs +++ b/tests/codegen/avr/avr-func-addrspace.rs @@ -17,9 +17,8 @@ extern crate minicore; use minicore::*; -extern "rust-intrinsic" { - pub fn transmute(src: Src) -> Dst; -} +#[rustc_intrinsic] +pub unsafe fn transmute(src: Src) -> Dst; pub static mut STORAGE_FOO: fn(&usize, &mut u32) -> Result<(), ()> = arbitrary_black_box; pub static mut STORAGE_BAR: u32 = 12; diff --git a/tests/codegen/emscripten-catch-unwind-js-eh.rs b/tests/codegen/emscripten-catch-unwind-js-eh.rs index 018ad5454fc23..3ab4b5c9c6312 100644 --- a/tests/codegen/emscripten-catch-unwind-js-eh.rs +++ b/tests/codegen/emscripten-catch-unwind-js-eh.rs @@ -23,13 +23,12 @@ fn size_of() -> usize { loop {} } -extern "rust-intrinsic" { - fn catch_unwind( - try_fn: fn(_: *mut u8), - data: *mut u8, - catch_fn: fn(_: *mut u8, _: *mut u8), - ) -> i32; -} +#[rustc_intrinsic] +unsafe fn catch_unwind( + try_fn: fn(_: *mut u8), + data: *mut u8, + catch_fn: fn(_: *mut u8, _: *mut u8), +) -> i32; // CHECK-LABEL: @ptr_size #[no_mangle] diff --git a/tests/codegen/emscripten-catch-unwind-wasm-eh.rs b/tests/codegen/emscripten-catch-unwind-wasm-eh.rs index 0fc9ae96720e4..d0571e4df0816 100644 --- a/tests/codegen/emscripten-catch-unwind-wasm-eh.rs +++ b/tests/codegen/emscripten-catch-unwind-wasm-eh.rs @@ -21,14 +21,12 @@ impl Copy for *mut T {} fn size_of() -> usize { loop {} } - -extern "rust-intrinsic" { - fn catch_unwind( - try_fn: fn(_: *mut u8), - data: *mut u8, - catch_fn: fn(_: *mut u8, _: *mut u8), - ) -> i32; -} +#[rustc_intrinsic] +unsafe fn catch_unwind( + try_fn: fn(_: *mut u8), + data: *mut u8, + catch_fn: fn(_: *mut u8, _: *mut u8), +) -> i32; // CHECK-LABEL: @ptr_size #[no_mangle] diff --git a/tests/codegen/intrinsic-no-unnamed-attr.rs b/tests/codegen/intrinsic-no-unnamed-attr.rs index fce0de80d7b60..35eb025ab6bb6 100644 --- a/tests/codegen/intrinsic-no-unnamed-attr.rs +++ b/tests/codegen/intrinsic-no-unnamed-attr.rs @@ -2,9 +2,9 @@ #![feature(intrinsics)] -extern "rust-intrinsic" { - fn sqrtf32(x: f32) -> f32; -} +#[rustc_intrinsic] +unsafe fn sqrtf32(x: f32) -> f32; + // CHECK: @llvm.sqrt.f32(float) #{{[0-9]*}} fn main() { diff --git a/tests/codegen/intrinsics/nontemporal.rs b/tests/codegen/intrinsics/nontemporal.rs index 1d4fae83c29dd..a151d4bd29741 100644 --- a/tests/codegen/intrinsics/nontemporal.rs +++ b/tests/codegen/intrinsics/nontemporal.rs @@ -18,9 +18,8 @@ extern crate minicore; use minicore::*; -extern "rust-intrinsic" { - pub fn nontemporal_store(ptr: *mut T, val: T); -} +#[rustc_intrinsic] +pub unsafe fn nontemporal_store(ptr: *mut T, val: T); #[no_mangle] pub fn a(a: &mut u32, b: u32) { diff --git a/tests/mir-opt/lower_intrinsics.rs b/tests/mir-opt/lower_intrinsics.rs index 4859d93546196..5afddc5ff7301 100644 --- a/tests/mir-opt/lower_intrinsics.rs +++ b/tests/mir-opt/lower_intrinsics.rs @@ -153,11 +153,10 @@ pub fn discriminant(t: T) { core::intrinsics::discriminant_value(&E::B); } -extern "rust-intrinsic" { - // Cannot use `std::intrinsics::copy_nonoverlapping` as that is a wrapper function - #[rustc_nounwind] - fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); -} +// Cannot use `std::intrinsics::copy_nonoverlapping` as that is a wrapper function +#[rustc_nounwind] +#[rustc_intrinsic] +unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); // EMIT_MIR lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff pub fn f_copy_nonoverlapping() { diff --git a/tests/run-make/atomic-lock-free/atomic_lock_free.rs b/tests/run-make/atomic-lock-free/atomic_lock_free.rs index 1f1116b9bfd17..b49c5044f31d6 100644 --- a/tests/run-make/atomic-lock-free/atomic_lock_free.rs +++ b/tests/run-make/atomic-lock-free/atomic_lock_free.rs @@ -2,9 +2,8 @@ #![crate_type = "rlib"] #![no_core] -extern "rust-intrinsic" { - fn atomic_xadd_seqcst(dst: *mut T, src: T) -> T; -} +#[rustc_intrinsic] +unsafe fn atomic_xadd_seqcst(dst: *mut T, src: T) -> T; #[lang = "sized"] trait Sized {} diff --git a/tests/run-make/avr-rjmp-offset/avr-rjmp-offsets.rs b/tests/run-make/avr-rjmp-offset/avr-rjmp-offsets.rs index 2f97fc1ed95ab..c91cd695ceea8 100644 --- a/tests/run-make/avr-rjmp-offset/avr-rjmp-offsets.rs +++ b/tests/run-make/avr-rjmp-offset/avr-rjmp-offsets.rs @@ -37,10 +37,9 @@ mod minicore { #[inline] #[rustc_diagnostic_item = "ptr_write_volatile"] pub unsafe fn write_volatile(dst: *mut T, src: T) { - extern "rust-intrinsic" { - #[rustc_nounwind] - pub fn volatile_store(dst: *mut T, val: T); - } + #[rustc_intrinsic] + pub unsafe fn volatile_store(dst: *mut T, val: T); + unsafe { volatile_store(dst, src) }; } } diff --git a/tests/ui/abi/abi-typo-unstable.stderr b/tests/ui/abi/abi-typo-unstable.feature_disabled.stderr similarity index 55% rename from tests/ui/abi/abi-typo-unstable.stderr rename to tests/ui/abi/abi-typo-unstable.feature_disabled.stderr index 9ba67ad7dbe4a..1934b483c47a0 100644 --- a/tests/ui/abi/abi-typo-unstable.stderr +++ b/tests/ui/abi/abi-typo-unstable.feature_disabled.stderr @@ -1,8 +1,8 @@ -error[E0703]: invalid ABI: found `rust-intrinsec` - --> $DIR/abi-typo-unstable.rs:2:8 +error[E0703]: invalid ABI: found `rust-cull` + --> $DIR/abi-typo-unstable.rs:5:8 | -LL | extern "rust-intrinsec" fn rust_intrinsic() {} - | ^^^^^^^^^^^^^^^^ invalid ABI +LL | extern "rust-cull" fn rust_call(_: ()) {} + | ^^^^^^^^^^^ invalid ABI | = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions diff --git a/tests/ui/abi/abi-typo-unstable.feature_enabled.stderr b/tests/ui/abi/abi-typo-unstable.feature_enabled.stderr new file mode 100644 index 0000000000000..868b9509830b0 --- /dev/null +++ b/tests/ui/abi/abi-typo-unstable.feature_enabled.stderr @@ -0,0 +1,16 @@ +error[E0703]: invalid ABI: found `rust-cull` + --> $DIR/abi-typo-unstable.rs:5:8 + | +LL | extern "rust-cull" fn rust_call(_: ()) {} + | ^^^^^^^^^^^ invalid ABI + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions +help: there's a similarly named valid ABI `rust-call` + | +LL - extern "rust-cull" fn rust_call(_: ()) {} +LL + extern "rust-call" fn rust_call(_: ()) {} + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0703`. diff --git a/tests/ui/abi/abi-typo-unstable.rs b/tests/ui/abi/abi-typo-unstable.rs index 94991a5eb17e8..75366217fa26f 100644 --- a/tests/ui/abi/abi-typo-unstable.rs +++ b/tests/ui/abi/abi-typo-unstable.rs @@ -1,6 +1,11 @@ -// rust-intrinsic is unstable and not enabled, so it should not be suggested as a fix -extern "rust-intrinsec" fn rust_intrinsic() {} //~ ERROR invalid ABI +//@ revisions: feature_disabled feature_enabled +#![cfg_attr(feature_enabled, feature(unboxed_closures))] + +// rust-call is unstable and not enabled, so it should not be suggested as a fix +extern "rust-cull" fn rust_call(_: ()) {} +//~^ ERROR invalid ABI +//[feature_enabled]~| HELP there's a similarly named valid ABI fn main() { - rust_intrinsic(); + rust_call(()); } diff --git a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr index d7d2161e7ad97..1be8db5ddf44f 100644 --- a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr +++ b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr @@ -10,24 +10,6 @@ LL - fn get(x: T, y: U) -> Get::Value {} LL + fn get(x: T, y: U) -> ::Value {} | -error[E0223]: ambiguous associated type - --> $DIR/associated-types-in-ambiguous-context.rs:13:23 - | -LL | fn grab(&self) -> Grab::Value; - | ^^^^^^^^^^^ help: use fully-qualified syntax: `::Value` - -error[E0223]: ambiguous associated type - --> $DIR/associated-types-in-ambiguous-context.rs:16:22 - | -LL | fn get(&self) -> Get::Value; - | ^^^^^^^^^^ - | -help: if there were a type named `Example` that implemented `Get`, you could use the fully-qualified path - | -LL - fn get(&self) -> Get::Value; -LL + fn get(&self) -> ::Value; - | - error[E0223]: ambiguous associated type --> $DIR/associated-types-in-ambiguous-context.rs:22:17 | @@ -56,6 +38,24 @@ LL + type X = as Deref>::Target; | and N other candidates +error[E0223]: ambiguous associated type + --> $DIR/associated-types-in-ambiguous-context.rs:13:23 + | +LL | fn grab(&self) -> Grab::Value; + | ^^^^^^^^^^^ help: use fully-qualified syntax: `::Value` + +error[E0223]: ambiguous associated type + --> $DIR/associated-types-in-ambiguous-context.rs:16:22 + | +LL | fn get(&self) -> Get::Value; + | ^^^^^^^^^^ + | +help: if there were a type named `Example` that implemented `Get`, you could use the fully-qualified path + | +LL - fn get(&self) -> Get::Value; +LL + fn get(&self) -> ::Value; + | + error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/borrowck/ice-mutability-error-slicing-121807.stderr b/tests/ui/borrowck/ice-mutability-error-slicing-121807.stderr index 3a6b8008fceb3..02d5231f7134d 100644 --- a/tests/ui/borrowck/ice-mutability-error-slicing-121807.stderr +++ b/tests/ui/borrowck/ice-mutability-error-slicing-121807.stderr @@ -23,12 +23,6 @@ LL | extern "C" fn read_dword(Self::Assoc<'_>) -> u16; = note: for more information, see issue #41686 = note: `#[warn(anonymous_parameters)]` on by default -error[E0220]: associated type `Assoc` not found for `Self` - --> $DIR/ice-mutability-error-slicing-121807.rs:7:36 - | -LL | extern "C" fn read_dword(Self::Assoc<'_>) -> u16; - | ^^^^^ associated type `Assoc` not found - error[E0185]: method `read_dword` has a `&self` declaration in the impl, but not in the trait --> $DIR/ice-mutability-error-slicing-121807.rs:17:5 | @@ -47,6 +41,12 @@ LL | extern "C" fn read_word(&mut self) -> u8; LL | impl MemoryUnit for ROM { | ^^^^^^^^^^^^^^^^^^^^^^^ missing `read_word` in implementation +error[E0220]: associated type `Assoc` not found for `Self` + --> $DIR/ice-mutability-error-slicing-121807.rs:7:36 + | +LL | extern "C" fn read_dword(Self::Assoc<'_>) -> u16; + | ^^^^^ associated type `Assoc` not found + error: aborting due to 4 previous errors; 1 warning emitted Some errors have detailed explanations: E0046, E0185, E0220, E0261. diff --git a/tests/ui/borrowck/trait-impl-argument-difference-ice.stderr b/tests/ui/borrowck/trait-impl-argument-difference-ice.stderr index 190ddeaa8f285..a656bb67bcba0 100644 --- a/tests/ui/borrowck/trait-impl-argument-difference-ice.stderr +++ b/tests/ui/borrowck/trait-impl-argument-difference-ice.stderr @@ -8,12 +8,6 @@ LL | extern "C" fn read_dword(Self::Assoc<'_>) -> u16; = note: for more information, see issue #41686 = note: `#[warn(anonymous_parameters)]` on by default -error[E0220]: associated type `Assoc` not found for `Self` - --> $DIR/trait-impl-argument-difference-ice.rs:4:36 - | -LL | extern "C" fn read_dword(Self::Assoc<'_>) -> u16; - | ^^^^^ associated type `Assoc` not found - error[E0185]: method `read_dword` has a `&self` declaration in the impl, but not in the trait --> $DIR/trait-impl-argument-difference-ice.rs:14:5 | @@ -32,6 +26,12 @@ LL | extern "C" fn read_word(&mut self) -> u8; LL | impl MemoryUnit for ROM { | ^^^^^^^^^^^^^^^^^^^^^^^ missing `read_word` in implementation +error[E0220]: associated type `Assoc` not found for `Self` + --> $DIR/trait-impl-argument-difference-ice.rs:4:36 + | +LL | extern "C" fn read_dword(Self::Assoc<'_>) -> u16; + | ^^^^^ associated type `Assoc` not found + error[E0596]: cannot borrow `*self` as mutable, as it is behind a `&` reference --> $DIR/trait-impl-argument-difference-ice.rs:16:19 | diff --git a/tests/ui/delegation/ice-issue-124347.rs b/tests/ui/delegation/ice-issue-124347.rs index b2b3c61a722b3..3e0a5b36ddcf3 100644 --- a/tests/ui/delegation/ice-issue-124347.rs +++ b/tests/ui/delegation/ice-issue-124347.rs @@ -4,7 +4,6 @@ // FIXME(fn_delegation): `recursive delegation` error should be emitted here trait Trait { reuse Trait::foo { &self.0 } - //~^ ERROR recursive delegation is not supported yet } reuse foo; diff --git a/tests/ui/delegation/ice-issue-124347.stderr b/tests/ui/delegation/ice-issue-124347.stderr index 74c4b5cd949a3..2955c04420348 100644 --- a/tests/ui/delegation/ice-issue-124347.stderr +++ b/tests/ui/delegation/ice-issue-124347.stderr @@ -1,23 +1,17 @@ -error: recursive delegation is not supported yet - --> $DIR/ice-issue-124347.rs:6:18 - | -LL | reuse Trait::foo { &self.0 } - | ^^^ callee defined here - error[E0391]: cycle detected when computing generics of `foo` - --> $DIR/ice-issue-124347.rs:10:7 + --> $DIR/ice-issue-124347.rs:9:7 | LL | reuse foo; | ^^^ | = note: ...which immediately requires computing generics of `foo` again note: cycle used when checking that `foo` is well-formed - --> $DIR/ice-issue-124347.rs:10:7 + --> $DIR/ice-issue-124347.rs:9:7 | LL | reuse foo; | ^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr index 832e7ef4dc38c..2cf244185e697 100644 --- a/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr +++ b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr @@ -187,166 +187,6 @@ help: consider using the `'static` lifetime, but this is uncommon unless you're LL | fn parrot() -> &'static mut Trait { | +++++++ -error[E0782]: expected a type, found a trait - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:52:16 - | -LL | fn foo(_: &Trait); - | ^^^^^ - | -help: use a new generic type parameter, constrained by `Trait` - | -LL - fn foo(_: &Trait); -LL + fn foo(_: &T); - | -help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference - | -LL | fn foo(_: &impl Trait); - | ++++ -help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch - | -LL | fn foo(_: &dyn Trait); - | +++ - -error[E0782]: expected a type, found a trait - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:55:19 - | -LL | fn bar(_: &'a Trait); - | ^^^^^ - | -help: use a new generic type parameter, constrained by `Trait` - | -LL - fn bar(_: &'a Trait); -LL + fn bar(_: &'a T); - | -help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference - | -LL | fn bar(_: &'a impl Trait); - | ++++ -help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch - | -LL | fn bar(_: &'a dyn Trait); - | +++ - -error[E0782]: expected a type, found a trait - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:59:22 - | -LL | fn alice<'a>(_: &Trait); - | ^^^^^ - | -help: use a new generic type parameter, constrained by `Trait` - | -LL - fn alice<'a>(_: &Trait); -LL + fn alice<'a, T: Trait>(_: &T); - | -help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference - | -LL | fn alice<'a>(_: &impl Trait); - | ++++ -help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch - | -LL | fn alice<'a>(_: &dyn Trait); - | +++ - -error[E0782]: expected a type, found a trait - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:62:23 - | -LL | fn bob<'a>(_: &'a Trait); - | ^^^^^ - | -help: use a new generic type parameter, constrained by `Trait` - | -LL - fn bob<'a>(_: &'a Trait); -LL + fn bob<'a, T: Trait>(_: &'a T); - | -help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference - | -LL | fn bob<'a>(_: &'a impl Trait); - | ++++ -help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch - | -LL | fn bob<'a>(_: &'a dyn Trait); - | +++ - -error[E0782]: expected a type, found a trait - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:65:18 - | -LL | fn cat() -> &Trait; - | ^^^^^ - | -help: use `impl Trait` to return an opaque type, as long as you return a single underlying type - | -LL | fn cat() -> &impl Trait; - | ++++ -help: alternatively, you can return an owned trait object - | -LL - fn cat() -> &Trait; -LL + fn cat() -> Box; - | - -error[E0782]: expected a type, found a trait - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:69:22 - | -LL | fn dog<'a>() -> &Trait { - | ^^^^^ - | -help: use `impl Trait` to return an opaque type, as long as you return a single underlying type - | -LL | fn dog<'a>() -> &impl Trait { - | ++++ -help: alternatively, you can return an owned trait object - | -LL - fn dog<'a>() -> &Trait { -LL + fn dog<'a>() -> Box { - | - -error[E0782]: expected a type, found a trait - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:75:24 - | -LL | fn kitten() -> &'a Trait { - | ^^^^^ - | -help: use `impl Trait` to return an opaque type, as long as you return a single underlying type - | -LL | fn kitten() -> &'a impl Trait { - | ++++ -help: alternatively, you can return an owned trait object - | -LL - fn kitten() -> &'a Trait { -LL + fn kitten() -> Box { - | - -error[E0782]: expected a type, found a trait - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:81:27 - | -LL | fn puppy<'a>() -> &'a Trait { - | ^^^^^ - | -help: use `impl Trait` to return an opaque type, as long as you return a single underlying type - | -LL | fn puppy<'a>() -> &'a impl Trait { - | ++++ -help: alternatively, you can return an owned trait object - | -LL - fn puppy<'a>() -> &'a Trait { -LL + fn puppy<'a>() -> Box { - | - -error[E0782]: expected a type, found a trait - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:86:25 - | -LL | fn parrot() -> &mut Trait { - | ^^^^^ - | -help: use `impl Trait` to return an opaque type, as long as you return a single underlying type - | -LL | fn parrot() -> &mut impl Trait { - | ++++ -help: alternatively, you can return an owned trait object - | -LL - fn parrot() -> &mut Trait { -LL + fn parrot() -> Box { - | - error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:93:12 | @@ -667,6 +507,166 @@ LL - fn parrot() -> &mut Trait { LL + fn parrot() -> Box { | +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:52:16 + | +LL | fn foo(_: &Trait); + | ^^^^^ + | +help: use a new generic type parameter, constrained by `Trait` + | +LL - fn foo(_: &Trait); +LL + fn foo(_: &T); + | +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn foo(_: &impl Trait); + | ++++ +help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch + | +LL | fn foo(_: &dyn Trait); + | +++ + +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:55:19 + | +LL | fn bar(_: &'a Trait); + | ^^^^^ + | +help: use a new generic type parameter, constrained by `Trait` + | +LL - fn bar(_: &'a Trait); +LL + fn bar(_: &'a T); + | +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn bar(_: &'a impl Trait); + | ++++ +help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch + | +LL | fn bar(_: &'a dyn Trait); + | +++ + +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:59:22 + | +LL | fn alice<'a>(_: &Trait); + | ^^^^^ + | +help: use a new generic type parameter, constrained by `Trait` + | +LL - fn alice<'a>(_: &Trait); +LL + fn alice<'a, T: Trait>(_: &T); + | +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn alice<'a>(_: &impl Trait); + | ++++ +help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch + | +LL | fn alice<'a>(_: &dyn Trait); + | +++ + +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:62:23 + | +LL | fn bob<'a>(_: &'a Trait); + | ^^^^^ + | +help: use a new generic type parameter, constrained by `Trait` + | +LL - fn bob<'a>(_: &'a Trait); +LL + fn bob<'a, T: Trait>(_: &'a T); + | +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn bob<'a>(_: &'a impl Trait); + | ++++ +help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch + | +LL | fn bob<'a>(_: &'a dyn Trait); + | +++ + +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:65:18 + | +LL | fn cat() -> &Trait; + | ^^^^^ + | +help: use `impl Trait` to return an opaque type, as long as you return a single underlying type + | +LL | fn cat() -> &impl Trait; + | ++++ +help: alternatively, you can return an owned trait object + | +LL - fn cat() -> &Trait; +LL + fn cat() -> Box; + | + +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:69:22 + | +LL | fn dog<'a>() -> &Trait { + | ^^^^^ + | +help: use `impl Trait` to return an opaque type, as long as you return a single underlying type + | +LL | fn dog<'a>() -> &impl Trait { + | ++++ +help: alternatively, you can return an owned trait object + | +LL - fn dog<'a>() -> &Trait { +LL + fn dog<'a>() -> Box { + | + +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:75:24 + | +LL | fn kitten() -> &'a Trait { + | ^^^^^ + | +help: use `impl Trait` to return an opaque type, as long as you return a single underlying type + | +LL | fn kitten() -> &'a impl Trait { + | ++++ +help: alternatively, you can return an owned trait object + | +LL - fn kitten() -> &'a Trait { +LL + fn kitten() -> Box { + | + +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:81:27 + | +LL | fn puppy<'a>() -> &'a Trait { + | ^^^^^ + | +help: use `impl Trait` to return an opaque type, as long as you return a single underlying type + | +LL | fn puppy<'a>() -> &'a impl Trait { + | ++++ +help: alternatively, you can return an owned trait object + | +LL - fn puppy<'a>() -> &'a Trait { +LL + fn puppy<'a>() -> Box { + | + +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:86:25 + | +LL | fn parrot() -> &mut Trait { + | ^^^^^ + | +help: use `impl Trait` to return an opaque type, as long as you return a single underlying type + | +LL | fn parrot() -> &mut impl Trait { + | ++++ +help: alternatively, you can return an owned trait object + | +LL - fn parrot() -> &mut Trait { +LL + fn parrot() -> Box { + | + error: aborting due to 42 previous errors Some errors have detailed explanations: E0106, E0261, E0782. diff --git a/tests/ui/error-codes/E0092.rs b/tests/ui/error-codes/E0092.rs index ddaace98bd4af..19a7c65a48ed2 100644 --- a/tests/ui/error-codes/E0092.rs +++ b/tests/ui/error-codes/E0092.rs @@ -1,7 +1,6 @@ #![feature(intrinsics)] -extern "rust-intrinsic" { - fn atomic_foo(); //~ ERROR E0092 -} -fn main() { -} +#[rustc_intrinsic] +unsafe fn atomic_foo(); //~ ERROR E0092 + +fn main() {} diff --git a/tests/ui/error-codes/E0092.stderr b/tests/ui/error-codes/E0092.stderr index 4ff2e6f077d24..003c989fd5961 100644 --- a/tests/ui/error-codes/E0092.stderr +++ b/tests/ui/error-codes/E0092.stderr @@ -1,8 +1,8 @@ error[E0092]: unrecognized atomic operation function: `foo` - --> $DIR/E0092.rs:3:5 + --> $DIR/E0092.rs:4:11 | -LL | fn atomic_foo(); - | ^^^^^^^^^^^^^^^^ unrecognized atomic operation +LL | unsafe fn atomic_foo(); + | ^^^^^^^^^^ unrecognized atomic operation error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0093.rs b/tests/ui/error-codes/E0093.rs index a2f0b1ae44379..24df7a9a32b97 100644 --- a/tests/ui/error-codes/E0093.rs +++ b/tests/ui/error-codes/E0093.rs @@ -1,8 +1,7 @@ #![feature(intrinsics)] -extern "rust-intrinsic" { - fn foo(); - //~^ ERROR E0093 -} -fn main() { -} +#[rustc_intrinsic] +unsafe fn foo(); +//~^ ERROR E0093 + +fn main() {} diff --git a/tests/ui/error-codes/E0093.stderr b/tests/ui/error-codes/E0093.stderr index 51c367b343ab1..d81bf53976aee 100644 --- a/tests/ui/error-codes/E0093.stderr +++ b/tests/ui/error-codes/E0093.stderr @@ -1,8 +1,8 @@ error[E0093]: unrecognized intrinsic function: `foo` - --> $DIR/E0093.rs:3:5 + --> $DIR/E0093.rs:4:11 | -LL | fn foo(); - | ^^^^^^^^^ unrecognized intrinsic +LL | unsafe fn foo(); + | ^^^ unrecognized intrinsic | = help: if you're adding an intrinsic, be sure to update `check_intrinsic_type` diff --git a/tests/ui/error-codes/E0622.rs b/tests/ui/error-codes/E0622.rs index 08c6d17129604..0c2a4f226d80c 100644 --- a/tests/ui/error-codes/E0622.rs +++ b/tests/ui/error-codes/E0622.rs @@ -1,6 +1,14 @@ #![feature(intrinsics)] -extern "rust-intrinsic" { - pub static atomic_singlethreadfence_seqcst : unsafe extern "rust-intrinsic" fn(); + +extern "C" { + + #[rustc_intrinsic] + pub static atomic_singlethreadfence_seqcst: unsafe extern "C" fn(); //~^ ERROR intrinsic must be a function [E0622] } -fn main() { unsafe { atomic_singlethreadfence_seqcst(); } } + +fn main() { + unsafe { + atomic_singlethreadfence_seqcst(); + } +} diff --git a/tests/ui/error-codes/E0622.stderr b/tests/ui/error-codes/E0622.stderr index 739ec984fc606..c0aea542af04e 100644 --- a/tests/ui/error-codes/E0622.stderr +++ b/tests/ui/error-codes/E0622.stderr @@ -1,8 +1,8 @@ error[E0622]: intrinsic must be a function - --> $DIR/E0622.rs:3:5 + --> $DIR/E0622.rs:6:5 | -LL | pub static atomic_singlethreadfence_seqcst : unsafe extern "rust-intrinsic" fn(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a function +LL | pub static atomic_singlethreadfence_seqcst: unsafe extern "C" fn(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a function error: aborting due to 1 previous error diff --git a/tests/ui/extern/extern-with-type-bounds.rs b/tests/ui/extern/extern-with-type-bounds.rs deleted file mode 100644 index 3fbddfc99a6fa..0000000000000 --- a/tests/ui/extern/extern-with-type-bounds.rs +++ /dev/null @@ -1,21 +0,0 @@ -#![feature(intrinsics, rustc_attrs)] - -// Intrinsics are the only (?) extern blocks supporting generics. -// Once intrinsics have to be declared via `#[rustc_intrinsic]`, -// the entire support for generics in extern fn can probably be removed. - -extern "rust-intrinsic" { - // Silent bounds made explicit to make sure they are actually - // resolved. - fn transmute(val: T) -> U; - - // Bounds aren't checked right now, so this should work - // even though it's incorrect. - fn size_of_val(x: *const T) -> usize; - - // Unresolved bounds should still error. - fn align_of() -> usize; - //~^ ERROR cannot find trait `NoSuchTrait` in this scope -} - -fn main() {} diff --git a/tests/ui/extern/extern-with-type-bounds.stderr b/tests/ui/extern/extern-with-type-bounds.stderr deleted file mode 100644 index 893947e831fd7..0000000000000 --- a/tests/ui/extern/extern-with-type-bounds.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0405]: cannot find trait `NoSuchTrait` in this scope - --> $DIR/extern-with-type-bounds.rs:17:20 - | -LL | fn align_of() -> usize; - | ^^^^^^^^^^^ not found in this scope - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/feature-gates/feature-gate-abi.rs b/tests/ui/feature-gates/feature-gate-abi.rs index 2af623734ee87..bafd3643788e0 100644 --- a/tests/ui/feature-gates/feature-gate-abi.rs +++ b/tests/ui/feature-gates/feature-gate-abi.rs @@ -8,19 +8,10 @@ extern crate minicore; use minicore::*; -// Functions -extern "rust-intrinsic" fn f1() {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail - //~^ ERROR intrinsic must be in -extern "rust-intrinsic" fn f2() {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail - //~^ ERROR intrinsic must be in extern "rust-call" fn f4(_: ()) {} //~ ERROR extern "rust-call" ABI is experimental and subject to change // Methods in trait definition trait Tr { - extern "rust-intrinsic" fn m1(); //~ ERROR extern "rust-intrinsic" ABI is an implementation detail - //~^ ERROR intrinsic must be in - extern "rust-intrinsic" fn m2(); //~ ERROR extern "rust-intrinsic" ABI is an implementation detail - //~^ ERROR intrinsic must be in extern "rust-call" fn m4(_: ()); //~ ERROR extern "rust-call" ABI is experimental and subject to change extern "rust-call" fn dm4(_: ()) {} //~ ERROR extern "rust-call" ABI is experimental and subject to change @@ -30,28 +21,16 @@ struct S; // Methods in trait impl impl Tr for S { - extern "rust-intrinsic" fn m1() {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail - //~^ ERROR intrinsic must be in - extern "rust-intrinsic" fn m2() {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail - //~^ ERROR intrinsic must be in extern "rust-call" fn m4(_: ()) {} //~ ERROR extern "rust-call" ABI is experimental and subject to change } // Methods in inherent impl impl S { - extern "rust-intrinsic" fn im1() {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail - //~^ ERROR intrinsic must be in - extern "rust-intrinsic" fn im2() {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail - //~^ ERROR intrinsic must be in extern "rust-call" fn im4(_: ()) {} //~ ERROR extern "rust-call" ABI is experimental and subject to change } // Function pointer types -type A1 = extern "rust-intrinsic" fn(); //~ ERROR extern "rust-intrinsic" ABI is an implementation detail -type A2 = extern "rust-intrinsic" fn(); //~ ERROR extern "rust-intrinsic" ABI is an implementation detail type A4 = extern "rust-call" fn(_: ()); //~ ERROR extern "rust-call" ABI is experimental and subject to change // Foreign modules -extern "rust-intrinsic" {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail -extern "rust-intrinsic" {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail extern "rust-call" {} //~ ERROR extern "rust-call" ABI is experimental and subject to change diff --git a/tests/ui/feature-gates/feature-gate-abi.stderr b/tests/ui/feature-gates/feature-gate-abi.stderr index a974c0099cbde..7897a60b34f44 100644 --- a/tests/ui/feature-gates/feature-gate-abi.stderr +++ b/tests/ui/feature-gates/feature-gate-abi.stderr @@ -1,23 +1,5 @@ -error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:12:8 - | -LL | extern "rust-intrinsic" fn f1() {} - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:14:8 - | -LL | extern "rust-intrinsic" fn f2() {} - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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[E0658]: the extern "rust-call" ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:16:8 + --> $DIR/feature-gate-abi.rs:11:8 | LL | extern "rust-call" fn f4(_: ()) {} | ^^^^^^^^^^^ @@ -26,26 +8,8 @@ LL | extern "rust-call" fn f4(_: ()) {} = help: add `#![feature(unboxed_closures)]` 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[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:20:12 - | -LL | extern "rust-intrinsic" fn m1(); - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:22:12 - | -LL | extern "rust-intrinsic" fn m2(); - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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[E0658]: the extern "rust-call" ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:24:12 + --> $DIR/feature-gate-abi.rs:15:12 | LL | extern "rust-call" fn m4(_: ()); | ^^^^^^^^^^^ @@ -55,7 +19,7 @@ LL | extern "rust-call" fn m4(_: ()); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the extern "rust-call" ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:26:12 + --> $DIR/feature-gate-abi.rs:17:12 | LL | extern "rust-call" fn dm4(_: ()) {} | ^^^^^^^^^^^ @@ -64,26 +28,8 @@ LL | extern "rust-call" fn dm4(_: ()) {} = help: add `#![feature(unboxed_closures)]` 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[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:33:12 - | -LL | extern "rust-intrinsic" fn m1() {} - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:35:12 - | -LL | extern "rust-intrinsic" fn m2() {} - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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[E0658]: the extern "rust-call" ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:37:12 + --> $DIR/feature-gate-abi.rs:24:12 | LL | extern "rust-call" fn m4(_: ()) {} | ^^^^^^^^^^^ @@ -92,26 +38,8 @@ LL | extern "rust-call" fn m4(_: ()) {} = help: add `#![feature(unboxed_closures)]` 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[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:42:12 - | -LL | extern "rust-intrinsic" fn im1() {} - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:44:12 - | -LL | extern "rust-intrinsic" fn im2() {} - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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[E0658]: the extern "rust-call" ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:46:12 + --> $DIR/feature-gate-abi.rs:29:12 | LL | extern "rust-call" fn im4(_: ()) {} | ^^^^^^^^^^^ @@ -120,26 +48,8 @@ LL | extern "rust-call" fn im4(_: ()) {} = help: add `#![feature(unboxed_closures)]` 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[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:50:18 - | -LL | type A1 = extern "rust-intrinsic" fn(); - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:51:18 - | -LL | type A2 = extern "rust-intrinsic" fn(); - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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[E0658]: the extern "rust-call" ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:52:18 + --> $DIR/feature-gate-abi.rs:33:18 | LL | type A4 = extern "rust-call" fn(_: ()); | ^^^^^^^^^^^ @@ -148,26 +58,8 @@ LL | type A4 = extern "rust-call" fn(_: ()); = help: add `#![feature(unboxed_closures)]` 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[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:55:8 - | -LL | extern "rust-intrinsic" {} - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:56:8 - | -LL | extern "rust-intrinsic" {} - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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[E0658]: the extern "rust-call" ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:57:8 + --> $DIR/feature-gate-abi.rs:36:8 | LL | extern "rust-call" {} | ^^^^^^^^^^^ @@ -176,54 +68,6 @@ LL | extern "rust-call" {} = help: add `#![feature(unboxed_closures)]` 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: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:20:32 - | -LL | extern "rust-intrinsic" fn m1(); - | ^^ - -error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:22:32 - | -LL | extern "rust-intrinsic" fn m2(); - | ^^ - -error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:12:33 - | -LL | extern "rust-intrinsic" fn f1() {} - | ^^ - -error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:14:33 - | -LL | extern "rust-intrinsic" fn f2() {} - | ^^ - -error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:33:37 - | -LL | extern "rust-intrinsic" fn m1() {} - | ^^ - -error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:35:37 - | -LL | extern "rust-intrinsic" fn m2() {} - | ^^ - -error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:42:38 - | -LL | extern "rust-intrinsic" fn im1() {} - | ^^ - -error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:44:38 - | -LL | extern "rust-intrinsic" fn im2() {} - | ^^ - -error: aborting due to 27 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-intrinsics.rs b/tests/ui/feature-gates/feature-gate-intrinsics.rs index 65806a0223e74..b7ebba672728d 100644 --- a/tests/ui/feature-gates/feature-gate-intrinsics.rs +++ b/tests/ui/feature-gates/feature-gate-intrinsics.rs @@ -1,8 +1,5 @@ -extern "rust-intrinsic" { //~ ERROR "rust-intrinsic" ABI is an implementation detail - fn bar(); //~ ERROR unrecognized intrinsic function: `bar` -} - -extern "rust-intrinsic" fn baz() {} //~ ERROR "rust-intrinsic" ABI is an implementation detail -//~^ ERROR intrinsic must be in +#[rustc_intrinsic] +//~^ ERROR the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items +fn bar(); fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-intrinsics.stderr b/tests/ui/feature-gates/feature-gate-intrinsics.stderr index 97246f05258f0..a7a725883a928 100644 --- a/tests/ui/feature-gates/feature-gate-intrinsics.stderr +++ b/tests/ui/feature-gates/feature-gate-intrinsics.stderr @@ -1,36 +1,12 @@ -error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-intrinsics.rs:1:8 +error[E0658]: the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items + --> $DIR/feature-gate-intrinsics.rs:1:1 | -LL | extern "rust-intrinsic" { - | ^^^^^^^^^^^^^^^^ +LL | #[rustc_intrinsic] + | ^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(intrinsics)]` 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[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-intrinsics.rs:5:8 - | -LL | extern "rust-intrinsic" fn baz() {} - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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[E0093]: unrecognized intrinsic function: `bar` - --> $DIR/feature-gate-intrinsics.rs:2:5 - | -LL | fn bar(); - | ^^^^^^^^^ unrecognized intrinsic - | - = help: if you're adding an intrinsic, be sure to update `check_intrinsic_type` - -error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-intrinsics.rs:5:34 - | -LL | extern "rust-intrinsic" fn baz() {} - | ^^ - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0093, E0658. -For more information about an error, try `rustc --explain E0093`. +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs index 2328798d74c32..44c0f1130f05d 100644 --- a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs +++ b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs @@ -5,9 +5,9 @@ fn main() { let a = &[1, 2, 3]; println!("{}", { - extern "rust-intrinsic" { //~ ERROR "rust-intrinsic" ABI is an implementation detail - fn atomic_fence(); - } + #[rustc_intrinsic] //~ ERROR the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items + unsafe fn atomic_fence(); + atomic_fence(); //~ ERROR: is unsafe 42 }); diff --git a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr index 86f88fdff5fc8..aaaaeece67a84 100644 --- a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr +++ b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr @@ -1,13 +1,13 @@ -error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gated-feature-in-macro-arg.rs:8:16 +error[E0658]: the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items + --> $DIR/feature-gated-feature-in-macro-arg.rs:8:9 | -LL | extern "rust-intrinsic" { - | ^^^^^^^^^^^^^^^^ +LL | #[rustc_intrinsic] + | ^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(intrinsics)]` 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[E0133]: call to unsafe function `main::atomic_fence` is unsafe and requires unsafe function or block +error[E0133]: call to unsafe function `atomic_fence` is unsafe and requires unsafe function or block --> $DIR/feature-gated-feature-in-macro-arg.rs:11:9 | LL | atomic_fence(); diff --git a/tests/ui/intrinsics/always-extern.rs b/tests/ui/intrinsics/always-extern.rs deleted file mode 100644 index 0afd8353455f2..0000000000000 --- a/tests/ui/intrinsics/always-extern.rs +++ /dev/null @@ -1,17 +0,0 @@ -#![feature(intrinsics)] - -trait Foo { - extern "rust-intrinsic" fn foo(&self); //~ ERROR intrinsic must -} - -impl Foo for () { - extern "rust-intrinsic" fn foo(&self) { //~ ERROR intrinsic must - } -} - -extern "rust-intrinsic" fn hello() {//~ ERROR intrinsic must - //~^ ERROR unrecognized intrinsic function: `hello` -} - -fn main() { -} diff --git a/tests/ui/intrinsics/always-extern.stderr b/tests/ui/intrinsics/always-extern.stderr deleted file mode 100644 index 44b889c6faac6..0000000000000 --- a/tests/ui/intrinsics/always-extern.stderr +++ /dev/null @@ -1,34 +0,0 @@ -error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/always-extern.rs:4:32 - | -LL | extern "rust-intrinsic" fn foo(&self); - | ^^^ - -error[E0093]: unrecognized intrinsic function: `hello` - --> $DIR/always-extern.rs:12:28 - | -LL | extern "rust-intrinsic" fn hello() { - | ^^^^^ unrecognized intrinsic - | - = help: if you're adding an intrinsic, be sure to update `check_intrinsic_type` - -error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/always-extern.rs:8:43 - | -LL | extern "rust-intrinsic" fn foo(&self) { - | ___________________________________________^ -LL | | } - | |_____^ - -error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/always-extern.rs:12:36 - | -LL | extern "rust-intrinsic" fn hello() { - | ____________________________________^ -LL | | -LL | | } - | |_^ - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0093`. diff --git a/tests/ui/intrinsics/auxiliary/cci_intrinsic.rs b/tests/ui/intrinsics/auxiliary/cci_intrinsic.rs index f3b9d569ce3b1..1014ac6f5609e 100644 --- a/tests/ui/intrinsics/auxiliary/cci_intrinsic.rs +++ b/tests/ui/intrinsics/auxiliary/cci_intrinsic.rs @@ -1,14 +1,11 @@ #![feature(intrinsics)] pub mod rusti { - extern "rust-intrinsic" { - pub fn atomic_xchg_seqcst(dst: *mut T, src: T) -> T; - } + #[rustc_intrinsic] + pub unsafe fn atomic_xchg_seqcst(dst: *mut T, src: T) -> T; } #[inline(always)] pub fn atomic_xchg_seqcst(dst: *mut isize, src: isize) -> isize { - unsafe { - rusti::atomic_xchg_seqcst(dst, src) - } + unsafe { rusti::atomic_xchg_seqcst(dst, src) } } diff --git a/tests/ui/intrinsics/incorrect-read_via_copy-defn.rs b/tests/ui/intrinsics/incorrect-read_via_copy-defn.rs index 5520430e140b3..e9f9270de87f3 100644 --- a/tests/ui/intrinsics/incorrect-read_via_copy-defn.rs +++ b/tests/ui/intrinsics/incorrect-read_via_copy-defn.rs @@ -1,7 +1,8 @@ fn main() { read_via_copy(); + //~^ ERROR call to unsafe function `read_via_copy` is unsafe and requires unsafe function or block } -extern "rust-intrinsic" fn read_via_copy() {} -//~^ ERROR "rust-intrinsic" ABI is an implementation detail -//~| ERROR intrinsic must be in `extern "rust-intrinsic" { ... }` block +#[rustc_intrinsic] +//~^ ERROR the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items +unsafe fn read_via_copy() {} diff --git a/tests/ui/intrinsics/incorrect-read_via_copy-defn.stderr b/tests/ui/intrinsics/incorrect-read_via_copy-defn.stderr index c6682693f7409..6711c77a11eb3 100644 --- a/tests/ui/intrinsics/incorrect-read_via_copy-defn.stderr +++ b/tests/ui/intrinsics/incorrect-read_via_copy-defn.stderr @@ -1,18 +1,21 @@ -error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/incorrect-read_via_copy-defn.rs:5:8 +error[E0658]: the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items + --> $DIR/incorrect-read_via_copy-defn.rs:6:1 | -LL | extern "rust-intrinsic" fn read_via_copy() {} - | ^^^^^^^^^^^^^^^^ +LL | #[rustc_intrinsic] + | ^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(intrinsics)]` 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: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/incorrect-read_via_copy-defn.rs:5:44 +error[E0133]: call to unsafe function `read_via_copy` is unsafe and requires unsafe function or block + --> $DIR/incorrect-read_via_copy-defn.rs:2:5 | -LL | extern "rust-intrinsic" fn read_via_copy() {} - | ^^ +LL | read_via_copy(); + | ^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0133, E0658. +For more information about an error, try `rustc --explain E0133`. diff --git a/tests/ui/intrinsics/incorrect-transmute.rs b/tests/ui/intrinsics/incorrect-transmute.rs index 15d1ab939ed0b..25fbc7a92ee7c 100644 --- a/tests/ui/intrinsics/incorrect-transmute.rs +++ b/tests/ui/intrinsics/incorrect-transmute.rs @@ -1,7 +1,8 @@ fn main() { transmute(); // does not ICE + //~^ ERROR call to unsafe function `transmute` is unsafe and requires unsafe function or block } -extern "rust-intrinsic" fn transmute() {} -//~^ ERROR "rust-intrinsic" ABI is an implementation detail -//~| ERROR intrinsic must be in `extern "rust-intrinsic" { ... }` block +#[rustc_intrinsic] +//~^ ERROR the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items +unsafe fn transmute() {} diff --git a/tests/ui/intrinsics/incorrect-transmute.stderr b/tests/ui/intrinsics/incorrect-transmute.stderr index 99dfb9847ff2e..6145a11c4ae0f 100644 --- a/tests/ui/intrinsics/incorrect-transmute.stderr +++ b/tests/ui/intrinsics/incorrect-transmute.stderr @@ -1,18 +1,21 @@ -error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/incorrect-transmute.rs:5:8 +error[E0658]: the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items + --> $DIR/incorrect-transmute.rs:6:1 | -LL | extern "rust-intrinsic" fn transmute() {} - | ^^^^^^^^^^^^^^^^ +LL | #[rustc_intrinsic] + | ^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(intrinsics)]` 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: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/incorrect-transmute.rs:5:40 +error[E0133]: call to unsafe function `transmute` is unsafe and requires unsafe function or block + --> $DIR/incorrect-transmute.rs:2:5 | -LL | extern "rust-intrinsic" fn transmute() {} - | ^^ +LL | transmute(); // does not ICE + | ^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0133, E0658. +For more information about an error, try `rustc --explain E0133`. diff --git a/tests/ui/intrinsics/intrinsic-atomics.rs b/tests/ui/intrinsics/intrinsic-atomics.rs index 4ad267e3ddb3f..6bc3f8d884db1 100644 --- a/tests/ui/intrinsics/intrinsic-atomics.rs +++ b/tests/ui/intrinsics/intrinsic-atomics.rs @@ -2,33 +2,51 @@ #![feature(intrinsics)] mod rusti { - extern "rust-intrinsic" { - pub fn atomic_cxchg_seqcst_seqcst(dst: *mut T, old: T, src: T) -> (T, bool); - pub fn atomic_cxchg_acquire_acquire(dst: *mut T, old: T, src: T) -> (T, bool); - pub fn atomic_cxchg_release_relaxed(dst: *mut T, old: T, src: T) -> (T, bool); - pub fn atomic_cxchgweak_seqcst_seqcst(dst: *mut T, old: T, src: T) -> (T, bool); - pub fn atomic_cxchgweak_acquire_acquire(dst: *mut T, old: T, src: T) -> (T, bool); - pub fn atomic_cxchgweak_release_relaxed(dst: *mut T, old: T, src: T) -> (T, bool); - - pub fn atomic_load_seqcst(src: *const T) -> T; - pub fn atomic_load_acquire(src: *const T) -> T; - - pub fn atomic_store_seqcst(dst: *mut T, val: T); - pub fn atomic_store_release(dst: *mut T, val: T); - - pub fn atomic_xchg_seqcst(dst: *mut T, src: T) -> T; - pub fn atomic_xchg_acquire(dst: *mut T, src: T) -> T; - pub fn atomic_xchg_release(dst: *mut T, src: T) -> T; - - pub fn atomic_xadd_seqcst(dst: *mut T, src: T) -> T; - pub fn atomic_xadd_acquire(dst: *mut T, src: T) -> T; - pub fn atomic_xadd_release(dst: *mut T, src: T) -> T; - - pub fn atomic_xsub_seqcst(dst: *mut T, src: T) -> T; - pub fn atomic_xsub_acquire(dst: *mut T, src: T) -> T; - pub fn atomic_xsub_release(dst: *mut T, src: T) -> T; - } + #[rustc_intrinsic] + pub unsafe fn atomic_cxchg_seqcst_seqcst(dst: *mut T, old: T, src: T) -> (T, bool); + #[rustc_intrinsic] + pub unsafe fn atomic_cxchg_acquire_acquire(dst: *mut T, old: T, src: T) -> (T, bool); + #[rustc_intrinsic] + pub unsafe fn atomic_cxchg_release_relaxed(dst: *mut T, old: T, src: T) -> (T, bool); + + #[rustc_intrinsic] + pub unsafe fn atomic_cxchgweak_seqcst_seqcst(dst: *mut T, old: T, src: T) -> (T, bool); + #[rustc_intrinsic] + pub unsafe fn atomic_cxchgweak_acquire_acquire(dst: *mut T, old: T, src: T) -> (T, bool); + #[rustc_intrinsic] + pub unsafe fn atomic_cxchgweak_release_relaxed(dst: *mut T, old: T, src: T) -> (T, bool); + + #[rustc_intrinsic] + pub unsafe fn atomic_load_seqcst(src: *const T) -> T; + #[rustc_intrinsic] + pub unsafe fn atomic_load_acquire(src: *const T) -> T; + + #[rustc_intrinsic] + pub unsafe fn atomic_store_seqcst(dst: *mut T, val: T); + #[rustc_intrinsic] + pub unsafe fn atomic_store_release(dst: *mut T, val: T); + + #[rustc_intrinsic] + pub unsafe fn atomic_xchg_seqcst(dst: *mut T, src: T) -> T; + #[rustc_intrinsic] + pub unsafe fn atomic_xchg_acquire(dst: *mut T, src: T) -> T; + #[rustc_intrinsic] + pub unsafe fn atomic_xchg_release(dst: *mut T, src: T) -> T; + + #[rustc_intrinsic] + pub unsafe fn atomic_xadd_seqcst(dst: *mut T, src: T) -> T; + #[rustc_intrinsic] + pub unsafe fn atomic_xadd_acquire(dst: *mut T, src: T) -> T; + #[rustc_intrinsic] + pub unsafe fn atomic_xadd_release(dst: *mut T, src: T) -> T; + + #[rustc_intrinsic] + pub unsafe fn atomic_xsub_seqcst(dst: *mut T, src: T) -> T; + #[rustc_intrinsic] + pub unsafe fn atomic_xsub_acquire(dst: *mut T, src: T) -> T; + #[rustc_intrinsic] + pub unsafe fn atomic_xsub_release(dst: *mut T, src: T) -> T; } pub fn main() { @@ -39,9 +57,9 @@ pub fn main() { *x = 5; assert_eq!(rusti::atomic_load_acquire(&*x), 5); - rusti::atomic_store_seqcst(&mut *x,3); + rusti::atomic_store_seqcst(&mut *x, 3); assert_eq!(*x, 3); - rusti::atomic_store_release(&mut *x,1); + rusti::atomic_store_release(&mut *x, 1); assert_eq!(*x, 1); assert_eq!(rusti::atomic_cxchg_seqcst_seqcst(&mut *x, 1, 2), (1, true)); diff --git a/tests/ui/intrinsics/invalid-ABI-rust-intrinsic.rs b/tests/ui/intrinsics/invalid-ABI-rust-intrinsic.rs new file mode 100644 index 0000000000000..4b777deb8b502 --- /dev/null +++ b/tests/ui/intrinsics/invalid-ABI-rust-intrinsic.rs @@ -0,0 +1,19 @@ +#![feature(intrinsics)] + +trait Foo { + extern "rust-intrinsic" fn foo(&self); //~ ERROR invalid ABI +} + +impl Foo for () { + extern "rust-intrinsic" fn foo(&self) { //~ ERROR invalid ABI + } +} + +extern "rust-intrinsic" fn hello() { //~ ERROR invalid ABI +} + +extern "rust-intrinsic" { + //~^ ERROR invalid ABI +} + +fn main() {} diff --git a/tests/ui/intrinsics/invalid-ABI-rust-intrinsic.stderr b/tests/ui/intrinsics/invalid-ABI-rust-intrinsic.stderr new file mode 100644 index 0000000000000..fc8bf62915b1b --- /dev/null +++ b/tests/ui/intrinsics/invalid-ABI-rust-intrinsic.stderr @@ -0,0 +1,35 @@ +error[E0703]: invalid ABI: found `rust-intrinsic` + --> $DIR/invalid-ABI-rust-intrinsic.rs:4:12 + | +LL | extern "rust-intrinsic" fn foo(&self); + | ^^^^^^^^^^^^^^^^ invalid ABI + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions + +error[E0703]: invalid ABI: found `rust-intrinsic` + --> $DIR/invalid-ABI-rust-intrinsic.rs:8:12 + | +LL | extern "rust-intrinsic" fn foo(&self) { + | ^^^^^^^^^^^^^^^^ invalid ABI + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions + +error[E0703]: invalid ABI: found `rust-intrinsic` + --> $DIR/invalid-ABI-rust-intrinsic.rs:12:8 + | +LL | extern "rust-intrinsic" fn hello() { + | ^^^^^^^^^^^^^^^^ invalid ABI + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions + +error[E0703]: invalid ABI: found `rust-intrinsic` + --> $DIR/invalid-ABI-rust-intrinsic.rs:15:8 + | +LL | extern "rust-intrinsic" { + | ^^^^^^^^^^^^^^^^ invalid ABI + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0703`. diff --git a/tests/ui/intrinsics/issue-28575.rs b/tests/ui/intrinsics/issue-28575.rs index 141136d25b215..841bc45138a14 100644 --- a/tests/ui/intrinsics/issue-28575.rs +++ b/tests/ui/intrinsics/issue-28575.rs @@ -2,6 +2,7 @@ extern "C" { pub static FOO: extern "rust-intrinsic" fn(); + //~^ ERROR invalid ABI } fn main() { diff --git a/tests/ui/intrinsics/issue-28575.stderr b/tests/ui/intrinsics/issue-28575.stderr index 8a7816f231f70..09c52aa4c9982 100644 --- a/tests/ui/intrinsics/issue-28575.stderr +++ b/tests/ui/intrinsics/issue-28575.stderr @@ -1,11 +1,20 @@ +error[E0703]: invalid ABI: found `rust-intrinsic` + --> $DIR/issue-28575.rs:4:28 + | +LL | pub static FOO: extern "rust-intrinsic" fn(); + | ^^^^^^^^^^^^^^^^ invalid ABI + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions + error[E0133]: use of extern static is unsafe and requires unsafe function or block - --> $DIR/issue-28575.rs:8:5 + --> $DIR/issue-28575.rs:9:5 | LL | FOO() | ^^^ use of extern static | = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior -error: aborting due to 1 previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0133`. +Some errors have detailed explanations: E0133, E0703. +For more information about an error, try `rustc --explain E0133`. diff --git a/tests/ui/intrinsics/safe-intrinsic-mismatch.rs b/tests/ui/intrinsics/safe-intrinsic-mismatch.rs index 915a23b59053d..4c301f9dbb09e 100644 --- a/tests/ui/intrinsics/safe-intrinsic-mismatch.rs +++ b/tests/ui/intrinsics/safe-intrinsic-mismatch.rs @@ -1,13 +1,14 @@ #![feature(intrinsics)] #![feature(rustc_attrs)] -extern "rust-intrinsic" { - fn size_of() -> usize; //~ ERROR intrinsic safety mismatch - //~^ ERROR intrinsic safety mismatch -} +#[rustc_intrinsic] +unsafe fn size_of() -> usize; +//~^ ERROR intrinsic safety mismatch +//~| ERROR intrinsic has wrong type #[rustc_intrinsic] -const fn assume(_b: bool) {} //~ ERROR intrinsic safety mismatch +const fn assume(_b: bool) {} +//~^ ERROR intrinsic safety mismatch //~| ERROR intrinsic has wrong type #[rustc_intrinsic] diff --git a/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr b/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr index aa4f294232d2d..04f6daeced2a9 100644 --- a/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr +++ b/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr @@ -1,16 +1,17 @@ error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `size_of` - --> $DIR/safe-intrinsic-mismatch.rs:5:5 + --> $DIR/safe-intrinsic-mismatch.rs:5:1 | -LL | fn size_of() -> usize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | unsafe fn size_of() -> usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `size_of` - --> $DIR/safe-intrinsic-mismatch.rs:5:5 +error[E0308]: intrinsic has wrong type + --> $DIR/safe-intrinsic-mismatch.rs:5:18 | -LL | fn size_of() -> usize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | unsafe fn size_of() -> usize; + | ^^^ expected safe fn, found unsafe fn | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + = note: expected signature `fn() -> _` + found signature `unsafe fn() -> _` error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `assume` --> $DIR/safe-intrinsic-mismatch.rs:10:1 @@ -28,13 +29,13 @@ LL | const fn assume(_b: bool) {} found signature `fn(_)` error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `const_deallocate` - --> $DIR/safe-intrinsic-mismatch.rs:14:1 + --> $DIR/safe-intrinsic-mismatch.rs:15:1 | LL | const fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: intrinsic has wrong type - --> $DIR/safe-intrinsic-mismatch.rs:14:26 + --> $DIR/safe-intrinsic-mismatch.rs:15:26 | LL | const fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} | ^ expected unsafe fn, found safe fn diff --git a/tests/ui/lint/internal_features.rs b/tests/ui/lint/internal_features.rs index 32ce9540cb364..6456078a5c2fa 100644 --- a/tests/ui/lint/internal_features.rs +++ b/tests/ui/lint/internal_features.rs @@ -4,8 +4,7 @@ //~^ ERROR: internal //~| ERROR: internal -extern "rust-intrinsic" { - fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); -} +#[rustc_intrinsic] +unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); fn main() {} diff --git a/tests/ui/print-calling-conventions.stdout b/tests/ui/print-calling-conventions.stdout index 539b2d5dee405..feee8cc3aa9c3 100644 --- a/tests/ui/print-calling-conventions.stdout +++ b/tests/ui/print-calling-conventions.stdout @@ -19,7 +19,6 @@ riscv-interrupt-m riscv-interrupt-s rust-call rust-cold -rust-intrinsic stdcall stdcall-unwind system diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr index 7b0fd9799919c..e189012d15c94 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr @@ -26,6 +26,20 @@ help: `A` is dyn-incompatible, use `impl A` to return an opaque type, as long as LL | fn f(a: A) -> impl A; | ++++ +error: associated item referring to unboxed trait object for its own trait + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:13 + | +LL | trait A: Sized { + | - in this trait +LL | fn f(a: A) -> A; + | ^ ^ + | +help: you might have meant to use `Self` to refer to the implementing type + | +LL - fn f(a: A) -> A; +LL + fn f(a: Self) -> Self; + | + error[E0782]: expected a type, found a trait --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:10:13 | @@ -54,6 +68,20 @@ help: `B` is dyn-incompatible, use `impl B` to return an opaque type, as long as LL | fn f(b: B) -> impl B; | ++++ +error: associated item referring to unboxed trait object for its own trait + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:10:13 + | +LL | trait B { + | - in this trait +LL | fn f(b: B) -> B; + | ^ ^ + | +help: you might have meant to use `Self` to refer to the implementing type + | +LL - fn f(b: B) -> B; +LL + fn f(b: Self) -> Self; + | + error[E0782]: expected a type, found a trait --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:16:20 | @@ -82,34 +110,6 @@ help: `C` is dyn-incompatible, use `impl C` to return an opaque type, as long as LL | fn f(&self, c: C) -> impl C; | ++++ -error: associated item referring to unboxed trait object for its own trait - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:13 - | -LL | trait A: Sized { - | - in this trait -LL | fn f(a: A) -> A; - | ^ ^ - | -help: you might have meant to use `Self` to refer to the implementing type - | -LL - fn f(a: A) -> A; -LL + fn f(a: Self) -> Self; - | - -error: associated item referring to unboxed trait object for its own trait - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:10:13 - | -LL | trait B { - | - in this trait -LL | fn f(b: B) -> B; - | ^ ^ - | -help: you might have meant to use `Self` to refer to the implementing type - | -LL - fn f(b: B) -> B; -LL + fn f(b: Self) -> Self; - | - error: associated item referring to unboxed trait object for its own trait --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:16:20 | diff --git a/tests/ui/suggestions/issue-116434-2015.stderr b/tests/ui/suggestions/issue-116434-2015.stderr index e7b8cd2f101d8..07a254432a28d 100644 --- a/tests/ui/suggestions/issue-116434-2015.stderr +++ b/tests/ui/suggestions/issue-116434-2015.stderr @@ -12,19 +12,6 @@ help: if this is a dyn-compatible trait, use `dyn` LL | fn foo() -> dyn Clone; | +++ -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-116434-2015.rs:18:20 - | -LL | fn handle() -> DbHandle; - | ^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see -help: if this is a dyn-compatible trait, use `dyn` - | -LL | fn handle() -> dyn DbHandle; - | +++ - warning: trait objects without an explicit `dyn` are deprecated --> $DIR/issue-116434-2015.rs:3:17 | @@ -53,6 +40,19 @@ help: there is an associated type with the same name LL | fn foo() -> Self::Clone; | ++++++ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-116434-2015.rs:18:20 + | +LL | fn handle() -> DbHandle; + | ^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: if this is a dyn-compatible trait, use `dyn` + | +LL | fn handle() -> dyn DbHandle; + | +++ + warning: trait objects without an explicit `dyn` are deprecated --> $DIR/issue-116434-2015.rs:18:20 | diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index 2a4a5a62ab4c5..7184244f5dc9d 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -439,6 +439,18 @@ LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } | | not allowed in type signatures | help: replace with the correct return type: `(i32, i32)` +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:154:21 + | +LL | struct BadStruct<_>(_); + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL - struct BadStruct<_>(_); +LL + struct BadStruct(T); + | + error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:140:31 | @@ -515,18 +527,6 @@ LL - fn assoc_fn_test3() -> _; LL + fn assoc_fn_test3() -> T; | -error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs - --> $DIR/typeck_type_placeholder_item.rs:154:21 - | -LL | struct BadStruct<_>(_); - | ^ not allowed in type signatures - | -help: use type parameters instead - | -LL - struct BadStruct<_>(_); -LL + struct BadStruct(T); - | - error[E0121]: the placeholder `_` is not allowed within types on item signatures for implementations --> $DIR/typeck_type_placeholder_item.rs:159:15 | diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr index 3b4de0753af0b..59eef0c63278a 100644 --- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr @@ -53,6 +53,12 @@ LL | trait Trait { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:6:12 + | +LL | fn fnc(&self) -> Trait { + | ^^^^^^^^^^^^^^^^^^^^ + warning: trait objects without an explicit `dyn` are deprecated --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:6:44 | @@ -66,12 +72,6 @@ help: if this is a dyn-compatible trait, use `dyn` LL | fn fnc(&self) -> dyn Trait { | +++ -error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:6:12 - | -LL | fn fnc(&self) -> Trait { - | ^^^^^^^^^^^^^^^^^^^^ - warning: trait objects without an explicit `dyn` are deprecated --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:6:21 | From c8649a31a8eea7c4ed33d68d3fc3b71a2cffd119 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 6 Apr 2025 21:55:06 +0000 Subject: [PATCH 19/23] Stop calling source_span query in significant drop order code --- .../src/ty/significant_drop_order.rs | 22 +-- .../drop/drop-order-comparisons.e2021.stderr | 176 +++++------------- ...nt-if-let-rescope-gated.edition2021.stderr | 8 +- .../lint-if-let-rescope-with-macro.stderr | 8 +- tests/ui/drop/lint-if-let-rescope.stderr | 64 ++----- .../ui/drop/lint-tail-expr-drop-order.stderr | 84 +++------ ...expr_drop_order-on-coroutine-unwind.stderr | 18 +- 7 files changed, 100 insertions(+), 280 deletions(-) diff --git a/compiler/rustc_middle/src/ty/significant_drop_order.rs b/compiler/rustc_middle/src/ty/significant_drop_order.rs index 4881d611c1282..ce4208f2c445f 100644 --- a/compiler/rustc_middle/src/ty/significant_drop_order.rs +++ b/compiler/rustc_middle/src/ty/significant_drop_order.rs @@ -143,25 +143,11 @@ pub fn ty_dtor_span<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option { | ty::UnsafeBinder(_) => None, ty::Adt(adt_def, _) => { - let did = adt_def.did(); - let try_local_did_span = |did: DefId| { - if let Some(local) = did.as_local() { - tcx.source_span(local) - } else { - tcx.def_span(did) - } - }; - let dtor = if let Some(dtor) = tcx.adt_destructor(did) { - dtor.did - } else if let Some(dtor) = tcx.adt_async_destructor(did) { - return Some(tcx.source_span(dtor.impl_did)); + if let Some(dtor) = tcx.adt_destructor(adt_def.did()) { + Some(tcx.def_span(tcx.parent(dtor.did))) } else { - return Some(try_local_did_span(did)); - }; - let def_key = tcx.def_key(dtor); - let Some(parent_index) = def_key.parent else { return Some(try_local_did_span(dtor)) }; - let parent_did = DefId { index: parent_index, krate: dtor.krate }; - Some(try_local_did_span(parent_did)) + Some(tcx.def_span(adt_def.did())) + } } ty::Coroutine(did, _) | ty::CoroutineWitness(did, _) diff --git a/tests/ui/drop/drop-order-comparisons.e2021.stderr b/tests/ui/drop/drop-order-comparisons.e2021.stderr index 601b0a38412f0..0717a8c1b9b94 100644 --- a/tests/ui/drop/drop-order-comparisons.e2021.stderr +++ b/tests/ui/drop/drop-order-comparisons.e2021.stderr @@ -31,39 +31,23 @@ LL | | }, e.mark(3), e.ok(4)); note: `#3` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `#1` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `_v` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `#2` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages note: the lint level is defined here --> $DIR/drop-order-comparisons.rs:28:25 @@ -95,21 +79,13 @@ LL | | }, e.mark(1), e.ok(4)); note: `#2` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `#1` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages warning: relative drop order changing in Rust 2024 @@ -135,21 +111,13 @@ LL | | }, e.mark(1), e.ok(4)); note: `#2` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `#1` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages warning: relative drop order changing in Rust 2024 @@ -175,21 +143,13 @@ LL | | }, e.mark(2), e.ok(3)); note: `#2` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `#1` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages warning: relative drop order changing in Rust 2024 @@ -215,21 +175,13 @@ LL | | }, e.mark(2), e.ok(3)); note: `#2` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `#1` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages warning: `if let` assigns a shorter lifetime since Edition 2024 @@ -245,12 +197,8 @@ LL | _ = (if let Ok(_) = e.ok(4).as_ref() { note: value invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/drop-order-comparisons.rs:127:5 | @@ -279,12 +227,8 @@ LL | _ = (if let Ok(_) = e.err(4).as_ref() {} else { note: value invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/drop-order-comparisons.rs:145:44 | @@ -312,12 +256,8 @@ LL | if let Ok(_) = e.err(4).as_ref() {} else { note: value invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/drop-order-comparisons.rs:247:43 | @@ -345,12 +285,8 @@ LL | if let true = e.err(9).is_ok() {} else { note: value invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/drop-order-comparisons.rs:352:41 | @@ -378,12 +314,8 @@ LL | if let Ok(_v) = e.err(8) {} else { note: value invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/drop-order-comparisons.rs:355:35 | @@ -411,12 +343,8 @@ LL | if let Ok(_) = e.err(7) {} else { note: value invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/drop-order-comparisons.rs:358:34 | @@ -444,12 +372,8 @@ LL | if let Ok(_) = e.err(6).as_ref() {} else { note: value invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/drop-order-comparisons.rs:361:43 | @@ -477,12 +401,8 @@ LL | if let Ok(_v) = e.err(5) {} else { note: value invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/drop-order-comparisons.rs:365:35 | @@ -510,12 +430,8 @@ LL | if let Ok(_) = e.err(4) {} else { note: value invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/drop-order-comparisons.rs:368:34 | @@ -543,12 +459,8 @@ LL | if let Ok(_) = e.err(4).as_ref() {} else { note: value invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/drop-order-comparisons.rs:404:43 | diff --git a/tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr b/tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr index 070ba1c6a4cfa..0d6974d516b6e 100644 --- a/tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr +++ b/tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr @@ -11,12 +11,8 @@ LL | if let Some(_value) = Droppy.get() { note: value invokes this custom destructor --> $DIR/lint-if-let-rescope-gated.rs:14:1 | -LL | / impl Drop for Droppy { -LL | | fn drop(&mut self) { -LL | | println!("dropped"); -LL | | } -LL | | } - | |_^ +LL | impl Drop for Droppy { + | ^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/lint-if-let-rescope-gated.rs:30:5 | diff --git a/tests/ui/drop/lint-if-let-rescope-with-macro.stderr b/tests/ui/drop/lint-if-let-rescope-with-macro.stderr index f1ca0ba57de4f..a0afb8eddb532 100644 --- a/tests/ui/drop/lint-if-let-rescope-with-macro.stderr +++ b/tests/ui/drop/lint-if-let-rescope-with-macro.stderr @@ -18,12 +18,8 @@ LL | | }; note: value invokes this custom destructor --> $DIR/lint-if-let-rescope-with-macro.rs:22:1 | -LL | / impl Drop for Droppy { -LL | | fn drop(&mut self) { -LL | | println!("dropped"); -LL | | } -LL | | } - | |_^ +LL | impl Drop for Droppy { + | ^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/lint-if-let-rescope-with-macro.rs:12:38 | diff --git a/tests/ui/drop/lint-if-let-rescope.stderr b/tests/ui/drop/lint-if-let-rescope.stderr index e95ec8fcea7fe..ca2416efcb1a2 100644 --- a/tests/ui/drop/lint-if-let-rescope.stderr +++ b/tests/ui/drop/lint-if-let-rescope.stderr @@ -11,12 +11,8 @@ LL | if let Some(_value) = droppy().get() { note: value invokes this custom destructor --> $DIR/lint-if-let-rescope.rs:11:1 | -LL | / impl Drop for Droppy { -LL | | fn drop(&mut self) { -LL | | println!("dropped"); -LL | | } -LL | | } - | |_^ +LL | impl Drop for Droppy { + | ^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/lint-if-let-rescope.rs:32:5 | @@ -55,21 +51,13 @@ LL | } else if let Some(_value) = droppy().get() { note: value invokes this custom destructor --> $DIR/lint-if-let-rescope.rs:11:1 | -LL | / impl Drop for Droppy { -LL | | fn drop(&mut self) { -LL | | println!("dropped"); -LL | | } -LL | | } - | |_^ +LL | impl Drop for Droppy { + | ^^^^^^^^^^^^^^^^^^^^ note: value invokes this custom destructor --> $DIR/lint-if-let-rescope.rs:11:1 | -LL | / impl Drop for Droppy { -LL | | fn drop(&mut self) { -LL | | println!("dropped"); -LL | | } -LL | | } - | |_^ +LL | impl Drop for Droppy { + | ^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/lint-if-let-rescope.rs:42:5 | @@ -105,12 +93,8 @@ LL | } else if let Some(_value) = droppy().get() { note: value invokes this custom destructor --> $DIR/lint-if-let-rescope.rs:11:1 | -LL | / impl Drop for Droppy { -LL | | fn drop(&mut self) { -LL | | println!("dropped"); -LL | | } -LL | | } - | |_^ +LL | impl Drop for Droppy { + | ^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/lint-if-let-rescope.rs:54:5 | @@ -140,12 +124,8 @@ LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else note: value invokes this custom destructor --> $DIR/lint-if-let-rescope.rs:11:1 | -LL | / impl Drop for Droppy { -LL | | fn drop(&mut self) { -LL | | println!("dropped"); -LL | | } -LL | | } - | |_^ +LL | impl Drop for Droppy { + | ^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/lint-if-let-rescope.rs:58:69 | @@ -170,12 +150,8 @@ LL | if (if let Some(_value) = droppy().get() { true } else { false }) { note: value invokes this custom destructor --> $DIR/lint-if-let-rescope.rs:11:1 | -LL | / impl Drop for Droppy { -LL | | fn drop(&mut self) { -LL | | println!("dropped"); -LL | | } -LL | | } - | |_^ +LL | impl Drop for Droppy { + | ^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/lint-if-let-rescope.rs:72:53 | @@ -200,12 +176,8 @@ LL | } else if (((if let Some(_value) = droppy().get() { true } else { false note: value invokes this custom destructor --> $DIR/lint-if-let-rescope.rs:11:1 | -LL | / impl Drop for Droppy { -LL | | fn drop(&mut self) { -LL | | println!("dropped"); -LL | | } -LL | | } - | |_^ +LL | impl Drop for Droppy { + | ^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/lint-if-let-rescope.rs:78:62 | @@ -230,12 +202,8 @@ LL | while (if let Some(_value) = droppy().get() { false } else { true }) { note: value invokes this custom destructor --> $DIR/lint-if-let-rescope.rs:11:1 | -LL | / impl Drop for Droppy { -LL | | fn drop(&mut self) { -LL | | println!("dropped"); -LL | | } -LL | | } - | |_^ +LL | impl Drop for Droppy { + | ^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/lint-if-let-rescope.rs:90:57 | diff --git a/tests/ui/drop/lint-tail-expr-drop-order.stderr b/tests/ui/drop/lint-tail-expr-drop-order.stderr index 6ff9b7c12681d..e124e9874d0b4 100644 --- a/tests/ui/drop/lint-tail-expr-drop-order.stderr +++ b/tests/ui/drop/lint-tail-expr-drop-order.stderr @@ -21,17 +21,13 @@ LL | } note: `#1` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:10:1 | -LL | / impl Drop for LoudDropper { -... | -LL | | } - | |_^ +LL | impl Drop for LoudDropper { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: `x` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:10:1 | -LL | / impl Drop for LoudDropper { -... | -LL | | } - | |_^ +LL | impl Drop for LoudDropper { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages note: the lint level is defined here --> $DIR/lint-tail-expr-drop-order.rs:6:9 @@ -62,17 +58,13 @@ LL | } note: `#1` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:10:1 | -LL | / impl Drop for LoudDropper { -... | -LL | | } - | |_^ +LL | impl Drop for LoudDropper { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: `x` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:10:1 | -LL | / impl Drop for LoudDropper { -... | -LL | | } - | |_^ +LL | impl Drop for LoudDropper { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages error: relative drop order changing in Rust 2024 @@ -98,17 +90,13 @@ LL | } note: `#1` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:10:1 | -LL | / impl Drop for LoudDropper { -... | -LL | | } - | |_^ +LL | impl Drop for LoudDropper { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: `x` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:10:1 | -LL | / impl Drop for LoudDropper { -... | -LL | | } - | |_^ +LL | impl Drop for LoudDropper { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages error: relative drop order changing in Rust 2024 @@ -134,10 +122,8 @@ LL | } note: `#1` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:10:1 | -LL | / impl Drop for LoudDropper { -... | -LL | | } - | |_^ +LL | impl Drop for LoudDropper { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages error: relative drop order changing in Rust 2024 @@ -185,17 +171,13 @@ LL | } note: `#1` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:10:1 | -LL | / impl Drop for LoudDropper { -... | -LL | | } - | |_^ +LL | impl Drop for LoudDropper { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: `x` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:10:1 | -LL | / impl Drop for LoudDropper { -... | -LL | | } - | |_^ +LL | impl Drop for LoudDropper { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages error: relative drop order changing in Rust 2024 @@ -221,23 +203,13 @@ LL | } note: `#1` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:193:5 | -LL | / impl Drop for LoudDropper3 { -LL | | -LL | | fn drop(&mut self) { -LL | | println!("loud drop"); -LL | | } -LL | | } - | |_____^ +LL | impl Drop for LoudDropper3 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `x` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:205:5 | -LL | / impl Drop for LoudDropper2 { -LL | | -LL | | fn drop(&mut self) { -LL | | println!("loud drop"); -LL | | } -LL | | } - | |_____^ +LL | impl Drop for LoudDropper2 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages error: relative drop order changing in Rust 2024 @@ -263,17 +235,13 @@ LL | )); note: `#1` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:10:1 | -LL | / impl Drop for LoudDropper { -... | -LL | | } - | |_^ +LL | impl Drop for LoudDropper { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: `_x` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:10:1 | -LL | / impl Drop for LoudDropper { -... | -LL | | } - | |_^ +LL | impl Drop for LoudDropper { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages error: aborting due to 8 previous errors diff --git a/tests/ui/drop/tail_expr_drop_order-on-coroutine-unwind.stderr b/tests/ui/drop/tail_expr_drop_order-on-coroutine-unwind.stderr index b0f971dd5cec6..7bf452e2496cb 100644 --- a/tests/ui/drop/tail_expr_drop_order-on-coroutine-unwind.stderr +++ b/tests/ui/drop/tail_expr_drop_order-on-coroutine-unwind.stderr @@ -27,24 +27,18 @@ LL | } note: `#2` invokes this custom destructor --> $DIR/tail_expr_drop_order-on-coroutine-unwind.rs:9:1 | -LL | / impl std::ops::Drop for Drop { -LL | | fn drop(&mut self) {} -LL | | } - | |_^ +LL | impl std::ops::Drop for Drop { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `#1` invokes this custom destructor --> $DIR/tail_expr_drop_order-on-coroutine-unwind.rs:9:1 | -LL | / impl std::ops::Drop for Drop { -LL | | fn drop(&mut self) {} -LL | | } - | |_^ +LL | impl std::ops::Drop for Drop { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `e` invokes this custom destructor --> $DIR/tail_expr_drop_order-on-coroutine-unwind.rs:9:1 | -LL | / impl std::ops::Drop for Drop { -LL | | fn drop(&mut self) {} -LL | | } - | |_^ +LL | impl std::ops::Drop for Drop { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages note: the lint level is defined here --> $DIR/tail_expr_drop_order-on-coroutine-unwind.rs:6:9 From d111aa87f1588d2ac0c282baa1b7d70e87231d52 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 7 Apr 2025 05:03:35 +0000 Subject: [PATCH 20/23] Trivial tweaks to stop tracking source span directly --- .../rustc_borrowck/src/region_infer/mod.rs | 32 +++++++++++-------- compiler/rustc_hir_typeck/src/closure.rs | 2 +- compiler/rustc_hir_typeck/src/lib.rs | 2 +- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index a80d74d9e370a..5756a5e7c7c5e 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -22,7 +22,7 @@ use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex, use rustc_mir_dataflow::points::DenseLocationMap; use rustc_span::hygiene::DesugaringKind; use rustc_span::{DUMMY_SP, Span}; -use tracing::{debug, instrument, trace}; +use tracing::{Level, debug, enabled, instrument, trace}; use crate::BorrowckInferCtxt; use crate::constraints::graph::{self, NormalConstraintGraph, RegionGraph}; @@ -327,11 +327,13 @@ fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: &ConstraintSccs) { let mut var_to_origin_sorted = var_to_origin.clone().into_iter().collect::>(); var_to_origin_sorted.sort_by_key(|vto| vto.0); - let mut reg_vars_to_origins_str = "region variables to origins:\n".to_string(); - for (reg_var, origin) in var_to_origin_sorted.into_iter() { - reg_vars_to_origins_str.push_str(&format!("{reg_var:?}: {origin:?}\n")); + if enabled!(Level::DEBUG) { + let mut reg_vars_to_origins_str = "region variables to origins:\n".to_string(); + for (reg_var, origin) in var_to_origin_sorted.into_iter() { + reg_vars_to_origins_str.push_str(&format!("{reg_var:?}: {origin:?}\n")); + } + debug!("{}", reg_vars_to_origins_str); } - debug!("{}", reg_vars_to_origins_str); let num_components = sccs.num_sccs(); let mut components = vec![FxIndexSet::default(); num_components]; @@ -342,16 +344,18 @@ fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: &ConstraintSccs) { components[scc_idx.as_usize()].insert((reg_var, *origin)); } - let mut components_str = "strongly connected components:".to_string(); - for (scc_idx, reg_vars_origins) in components.iter().enumerate() { - let regions_info = reg_vars_origins.clone().into_iter().collect::>(); - components_str.push_str(&format!( - "{:?}: {:?},\n)", - ConstraintSccIndex::from_usize(scc_idx), - regions_info, - )) + if enabled!(Level::DEBUG) { + let mut components_str = "strongly connected components:".to_string(); + for (scc_idx, reg_vars_origins) in components.iter().enumerate() { + let regions_info = reg_vars_origins.clone().into_iter().collect::>(); + components_str.push_str(&format!( + "{:?}: {:?},\n)", + ConstraintSccIndex::from_usize(scc_idx), + regions_info, + )) + } + debug!("{}", components_str); } - debug!("{}", components_str); // calculate the best representative for each component let components_representatives = components diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 467ca26e7eab1..b8968b58769a2 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -970,7 +970,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.typeck_results.borrow_mut().user_provided_sigs.insert(expr_def_id, c_result); // Normalize only after registering in `user_provided_sigs`. - self.normalize(self.tcx.hir_span(hir_id), result) + self.normalize(self.tcx.def_span(expr_def_id), result) } /// Invoked when we are translating the coroutine that results diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 46389668de7c3..1d86ff14471a5 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -117,7 +117,7 @@ fn typeck_with_inspect<'tcx>( let id = tcx.local_def_id_to_hir_id(def_id); let node = tcx.hir_node(id); - let span = tcx.hir_span(id); + let span = tcx.def_span(def_id); // Figure out what primary body this item has. let body_id = node.body_id().unwrap_or_else(|| { From 4322b6e97d6ad438c6c9ef1ea92e8ba00c056d9c Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 31 Mar 2025 12:51:16 +1100 Subject: [PATCH 21/23] coverage: Build the CGU's global file table as late as possible --- .../src/coverageinfo/mapgen.rs | 152 ++++++++++-------- .../src/coverageinfo/mapgen/covfun.rs | 42 +++-- .../src/coverageinfo/mapgen/unused.rs | 4 +- 3 files changed, 110 insertions(+), 88 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 5e62ce285dd8c..55b1e728b70db 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -53,13 +53,6 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { None => return, }; - // The order of entries in this global file table needs to be deterministic, - // and ideally should also be independent of the details of stable-hashing, - // because coverage tests snapshots (`.cov-map`) can observe the order and - // would need to be re-blessed if it changes. As long as those requirements - // are satisfied, the order can be arbitrary. - let mut global_file_table = GlobalFileTable::new(); - let mut covfun_records = instances_used .iter() .copied() @@ -67,17 +60,13 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { // order that doesn't depend on the stable-hash-based order in which // instances were visited during codegen. .sorted_by_cached_key(|&instance| tcx.symbol_name(instance).name) - .filter_map(|instance| prepare_covfun_record(tcx, &mut global_file_table, instance, true)) + .filter_map(|instance| prepare_covfun_record(tcx, instance, true)) .collect::>(); // In a single designated CGU, also prepare covfun records for functions // in this crate that were instrumented for coverage, but are unused. if cx.codegen_unit.is_code_coverage_dead_code_cgu() { - unused::prepare_covfun_records_for_unused_functions( - cx, - &mut global_file_table, - &mut covfun_records, - ); + unused::prepare_covfun_records_for_unused_functions(cx, &mut covfun_records); } // If there are no covfun records for this CGU, don't generate a covmap record. @@ -89,68 +78,88 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { return; } - // Encode all filenames referenced by coverage mappings in this CGU. - let filenames_buffer = global_file_table.make_filenames_buffer(tcx); - // 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); + // Prepare the global file table for this CGU, containing all paths needed + // by one or more covfun records. + let global_file_table = + GlobalFileTable::build(tcx, covfun_records.iter().flat_map(|c| c.all_source_files())); for covfun in &covfun_records { - covfun::generate_covfun_record(cx, filenames_hash, covfun) + covfun::generate_covfun_record(cx, &global_file_table, covfun) } // 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_buffer); + generate_covmap_record(cx, covmap_version, &global_file_table.filenames_buffer); } -/// Maps "global" (per-CGU) file ID numbers to their underlying source files. +/// Maps "global" (per-CGU) file ID numbers to their underlying source file paths. +#[derive(Debug)] struct GlobalFileTable { /// This "raw" table doesn't include the working dir, so a file's /// global ID is its index in this set **plus one**. - raw_file_table: FxIndexMap>, + raw_file_table: FxIndexMap, + + /// The file table in encoded form (possibly compressed), which can be + /// included directly in this CGU's `__llvm_covmap` record. + filenames_buffer: Vec, + + /// Truncated hash of the bytes in `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. + filenames_hash: u64, } impl GlobalFileTable { - fn new() -> Self { - Self { raw_file_table: FxIndexMap::default() } - } + /// Builds a "global file table" for this CGU, mapping numeric IDs to + /// path strings. + fn build<'a>(tcx: TyCtxt<'_>, all_files: impl Iterator) -> Self { + let mut raw_file_table = FxIndexMap::default(); + + for file in all_files { + raw_file_table.entry(file.stable_id).or_insert_with(|| { + file.name + .for_scope(tcx.sess, RemapPathScopeComponents::MACRO) + .to_string_lossy() + .into_owned() + }); + } + + // FIXME(Zalathar): Consider sorting the file table here, but maybe + // only after adding filename support to coverage-dump, so that the + // table order isn't directly visible in `.coverage-map` snapshots. + + let mut table = Vec::with_capacity(raw_file_table.len() + 1); + + // Since version 6 of the LLVM coverage mapping format, the first entry + // in the global file table is treated as a base directory, used to + // resolve any other entries that are stored as relative paths. + let base_dir = tcx + .sess + .opts + .working_dir + .for_scope(tcx.sess, RemapPathScopeComponents::MACRO) + .to_string_lossy(); + table.push(base_dir.as_ref()); - fn global_file_id_for_file(&mut self, file: &Arc) -> GlobalFileId { - // Ensure the given file has a table entry, and get its index. - let entry = self.raw_file_table.entry(file.stable_id); - let raw_id = entry.index(); - entry.or_insert_with(|| Arc::clone(file)); - - // The raw file table doesn't include an entry for the working dir - // (which has ID 0), so add 1 to get the correct ID. - GlobalFileId::from_usize(raw_id + 1) - } + // Add the regular entries after the base directory. + table.extend(raw_file_table.values().map(|name| name.as_str())); - fn make_filenames_buffer(&self, tcx: TyCtxt<'_>) -> Vec { - let mut table = Vec::with_capacity(self.raw_file_table.len() + 1); - - // LLVM Coverage Mapping Format version 6 (zero-based encoded as 5) - // requires setting the first filename to the compilation directory. - // Since rustc generates coverage maps with relative paths, the - // compilation directory can be combined with the relative paths - // to get absolute paths, if needed. - table.push( - tcx.sess - .opts - .working_dir - .for_scope(tcx.sess, RemapPathScopeComponents::MACRO) - .to_string_lossy(), - ); + // Encode the file table into a buffer, and get the hash of its encoded + // bytes, so that we can embed that hash in `__llvm_covfun` records. + let filenames_buffer = llvm_cov::write_filenames_to_buffer(&table); + let filenames_hash = llvm_cov::hash_bytes(&filenames_buffer); - // Add the regular entries after the base directory. - table.extend(self.raw_file_table.values().map(|file| { - file.name.for_scope(tcx.sess, RemapPathScopeComponents::MACRO).to_string_lossy() - })); + Self { raw_file_table, filenames_buffer, filenames_hash } + } - llvm_cov::write_filenames_to_buffer(&table) + fn get_existing_id(&self, file: &SourceFile) -> Option { + let raw_id = self.raw_file_table.get_index_of(&file.stable_id)?; + // The raw file table doesn't include an entry for the base dir + // (which has ID 0), so add 1 to get the correct ID. + Some(GlobalFileId::from_usize(raw_id + 1)) } } @@ -166,26 +175,31 @@ rustc_index::newtype_index! { struct LocalFileId {} } -/// Holds a mapping from "local" (per-function) file IDs to "global" (per-CGU) -/// file IDs. +/// Holds a mapping from "local" (per-function) file IDs to their corresponding +/// source files. #[derive(Debug, Default)] struct VirtualFileMapping { - local_to_global: IndexVec, - global_to_local: FxIndexMap, + local_file_table: IndexVec>, } impl VirtualFileMapping { - fn local_id_for_global(&mut self, global_file_id: GlobalFileId) -> LocalFileId { - *self - .global_to_local - .entry(global_file_id) - .or_insert_with(|| self.local_to_global.push(global_file_id)) + fn push_file(&mut self, source_file: &Arc) -> LocalFileId { + self.local_file_table.push(Arc::clone(source_file)) } - fn to_vec(&self) -> Vec { - // This clone could be avoided by transmuting `&[GlobalFileId]` to `&[u32]`, - // but it isn't hot or expensive enough to justify the extra unsafety. - self.local_to_global.iter().map(|&global| GlobalFileId::as_u32(global)).collect() + /// Resolves all of the filenames in this local file mapping to a list of + /// global file IDs in its CGU, for inclusion in this function's + /// `__llvm_covfun` record. + /// + /// The global file IDs are returned as `u32` to make FFI easier. + fn resolve_all(&self, global_file_table: &GlobalFileTable) -> Option> { + self.local_file_table + .iter() + .map(|file| try { + let id = global_file_table.get_existing_id(file)?; + GlobalFileId::as_u32(id) + }) + .collect::>>() } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs index 93419c2caad25..7bdbc68595290 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs @@ -5,6 +5,7 @@ //! [^win]: On Windows the section name is `.lcovfun`. use std::ffi::CString; +use std::sync::Arc; use rustc_abi::Align; use rustc_codegen_ssa::traits::{ @@ -15,7 +16,7 @@ use rustc_middle::mir::coverage::{ MappingKind, Op, }; use rustc_middle::ty::{Instance, TyCtxt}; -use rustc_span::Span; +use rustc_span::{SourceFile, Span}; use rustc_target::spec::HasTargetSpec; use tracing::debug; @@ -37,9 +38,16 @@ pub(crate) struct CovfunRecord<'tcx> { regions: ffi::Regions, } +impl<'tcx> CovfunRecord<'tcx> { + /// Iterator that yields all source files referred to by this function's + /// coverage mappings. Used to build the global file table for the CGU. + pub(crate) fn all_source_files(&self) -> impl Iterator { + self.virtual_file_mapping.local_file_table.iter().map(Arc::as_ref) + } +} + pub(crate) fn prepare_covfun_record<'tcx>( tcx: TyCtxt<'tcx>, - global_file_table: &mut GlobalFileTable, instance: Instance<'tcx>, is_used: bool, ) -> Option> { @@ -57,7 +65,7 @@ pub(crate) fn prepare_covfun_record<'tcx>( regions: ffi::Regions::default(), }; - fill_region_tables(tcx, global_file_table, fn_cov_info, ids_info, &mut covfun); + fill_region_tables(tcx, fn_cov_info, ids_info, &mut covfun); if covfun.regions.has_no_regions() { debug!(?covfun, "function has no mappings to embed; skipping"); @@ -92,7 +100,6 @@ fn prepare_expressions(ids_info: &CoverageIdsInfo) -> Vec( tcx: TyCtxt<'tcx>, - global_file_table: &mut GlobalFileTable, fn_cov_info: &'tcx FunctionCoverageInfo, ids_info: &'tcx CoverageIdsInfo, covfun: &mut CovfunRecord<'tcx>, @@ -106,11 +113,7 @@ fn fill_region_tables<'tcx>( }; let source_file = source_map.lookup_source_file(first_span.lo()); - // Look up the global file ID for that file. - let global_file_id = global_file_table.global_file_id_for_file(&source_file); - - // Associate that global file ID with a local file ID for this function. - let local_file_id = covfun.virtual_file_mapping.local_id_for_global(global_file_id); + let local_file_id = covfun.virtual_file_mapping.push_file(&source_file); // In rare cases, _all_ of a function's spans are discarded, and coverage // codegen needs to handle that gracefully to avoid #133606. @@ -179,7 +182,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_hash: u64, + global_file_table: &GlobalFileTable, covfun: &CovfunRecord<'tcx>, ) { let &CovfunRecord { @@ -191,12 +194,19 @@ pub(crate) fn generate_covfun_record<'tcx>( ref regions, } = covfun; + let Some(local_file_table) = virtual_file_mapping.resolve_all(global_file_table) else { + debug_assert!( + false, + "all local files should be present in the global file table: \ + global_file_table = {global_file_table:?}, \ + virtual_file_mapping = {virtual_file_mapping:?}" + ); + return; + }; + // Encode the function's coverage mappings into a buffer. - let coverage_mapping_buffer = llvm_cov::write_function_mappings_to_buffer( - &virtual_file_mapping.to_vec(), - expressions, - regions, - ); + let coverage_mapping_buffer = + llvm_cov::write_function_mappings_to_buffer(&local_file_table, expressions, regions); // 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. @@ -209,7 +219,7 @@ pub(crate) fn generate_covfun_record<'tcx>( 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_u64(global_file_table.filenames_hash), cx.const_bytes(&coverage_mapping_buffer), ], // This struct needs to be packed, so that the 32-bit length field diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs index ab030f5b6152a..68f60f169b5b5 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs @@ -7,7 +7,6 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::DefIdSet; use crate::common::CodegenCx; -use crate::coverageinfo::mapgen::GlobalFileTable; use crate::coverageinfo::mapgen::covfun::{CovfunRecord, prepare_covfun_record}; use crate::llvm; @@ -21,7 +20,6 @@ use crate::llvm; /// its embedded coverage data. pub(crate) fn prepare_covfun_records_for_unused_functions<'tcx>( cx: &CodegenCx<'_, 'tcx>, - global_file_table: &mut GlobalFileTable, covfun_records: &mut Vec>, ) { assert!(cx.codegen_unit.is_code_coverage_dead_code_cgu()); @@ -33,7 +31,7 @@ pub(crate) fn prepare_covfun_records_for_unused_functions<'tcx>( // Try to create a covfun record for each unused function. let mut name_globals = Vec::with_capacity(unused_instances.len()); covfun_records.extend(unused_instances.into_iter().filter_map(|unused| try { - let record = prepare_covfun_record(cx.tcx, global_file_table, unused.instance, false)?; + let record = prepare_covfun_record(cx.tcx, unused.instance, false)?; // If successful, also store its symbol name in a global constant. name_globals.push(cx.const_str(unused.symbol_name.name).0); record From d6467d34ae4057f493e2706a5625e0784f2a68bf Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Mon, 7 Apr 2025 07:07:16 -0400 Subject: [PATCH 22/23] handle sret for scalar autodiff --- .../rustc_ast/src/expand/autodiff_attrs.rs | 6 +++++ .../src/builder/autodiff.rs | 24 +++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_ast/src/expand/autodiff_attrs.rs b/compiler/rustc_ast/src/expand/autodiff_attrs.rs index f01c781f46c65..13a7c5a180576 100644 --- a/compiler/rustc_ast/src/expand/autodiff_attrs.rs +++ b/compiler/rustc_ast/src/expand/autodiff_attrs.rs @@ -92,6 +92,12 @@ pub struct AutoDiffAttrs { pub input_activity: Vec, } +impl AutoDiffAttrs { + pub fn has_primal_ret(&self) -> bool { + matches!(self.ret_activity, DiffActivity::Active | DiffActivity::Dual) + } +} + impl DiffMode { pub fn is_rev(&self) -> bool { matches!(self, DiffMode::Reverse) diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs index 7d264ba4d00c8..5e7ef27143b14 100644 --- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs +++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs @@ -201,7 +201,23 @@ fn compute_enzyme_fn_ty<'ll>( } if attrs.width == 1 { - todo!("Handle sret for scalar ad"); + // Enzyme returns a struct of style: + // `{ original_ret(if requested), float, float, ... }` + let mut struct_elements = vec![]; + if attrs.has_primal_ret() { + struct_elements.push(inner_ret_ty); + } + // Next, we push the list of active floats, since they will be lowered to `enzyme_out`, + // and therefore part of the return struct. + let param_tys = cx.func_params_types(fn_ty); + for (act, param_ty) in attrs.input_activity.iter().zip(param_tys) { + if matches!(act, DiffActivity::Active) { + // Now find the float type at position i based on the fn_ty, + // to know what (f16/f32/f64/...) to add to the struct. + struct_elements.push(param_ty); + } + } + ret_ty = cx.type_struct(&struct_elements, false); } else { // First we check if we also have to deal with the primal return. match attrs.mode { @@ -388,7 +404,11 @@ fn generate_enzyme_call<'ll>( // now store the result of the enzyme call into the sret pointer. let sret_ptr = outer_args[0]; let call_ty = cx.val_ty(call); - assert_eq!(cx.type_kind(call_ty), TypeKind::Array); + if attrs.width == 1 { + assert_eq!(cx.type_kind(call_ty), TypeKind::Struct); + } else { + assert_eq!(cx.type_kind(call_ty), TypeKind::Array); + } llvm::LLVMBuildStore(&builder.llbuilder, call, sret_ptr); } builder.ret_void(); From ca5bea3ebbc4725c187abf4eac68f6c57fa938c1 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Mon, 7 Apr 2025 07:11:52 -0400 Subject: [PATCH 23/23] move old tests, add sret test --- .../{autodiffv.rs => autodiff/batched.rs} | 0 .../{autodiff.rs => autodiff/scalar.rs} | 0 tests/codegen/autodiff/sret.rs | 45 +++++++++++++++++++ 3 files changed, 45 insertions(+) rename tests/codegen/{autodiffv.rs => autodiff/batched.rs} (100%) rename tests/codegen/{autodiff.rs => autodiff/scalar.rs} (100%) create mode 100644 tests/codegen/autodiff/sret.rs diff --git a/tests/codegen/autodiffv.rs b/tests/codegen/autodiff/batched.rs similarity index 100% rename from tests/codegen/autodiffv.rs rename to tests/codegen/autodiff/batched.rs diff --git a/tests/codegen/autodiff.rs b/tests/codegen/autodiff/scalar.rs similarity index 100% rename from tests/codegen/autodiff.rs rename to tests/codegen/autodiff/scalar.rs diff --git a/tests/codegen/autodiff/sret.rs b/tests/codegen/autodiff/sret.rs new file mode 100644 index 0000000000000..5ead90041edc3 --- /dev/null +++ b/tests/codegen/autodiff/sret.rs @@ -0,0 +1,45 @@ +//@ compile-flags: -Zautodiff=Enable -C opt-level=3 -Clto=fat +//@ no-prefer-dynamic +//@ needs-enzyme + +// This test is almost identical to the scalar.rs one, +// but we intentionally add a few more floats. +// `df` would ret `{ f64, f32, f32 }`, but is lowered as an sret. +// We therefore use this test to verify some of our sret handling. + +#![feature(autodiff)] + +use std::autodiff::autodiff; + +#[no_mangle] +#[autodiff(df, Reverse, Active, Active, Active)] +fn primal(x: f32, y: f32) -> f64 { + (x * x * y) as f64 +} + +// CHECK:define internal fastcc void @_ZN4sret2df17h93be4316dd8ea006E(ptr dead_on_unwind noalias nocapture noundef nonnull writable writeonly align 8 dereferenceable(16) initializes((0, 16)) %_0, float noundef %x, float noundef %y) +// CHECK-NEXT:start: +// CHECK-NEXT: %0 = tail call fastcc { double, float, float } @diffeprimal(float %x, float %y) +// CHECK-NEXT: %.elt = extractvalue { double, float, float } %0, 0 +// CHECK-NEXT: store double %.elt, ptr %_0, align 8 +// CHECK-NEXT: %_0.repack1 = getelementptr inbounds nuw i8, ptr %_0, i64 8 +// CHECK-NEXT: %.elt2 = extractvalue { double, float, float } %0, 1 +// CHECK-NEXT: store float %.elt2, ptr %_0.repack1, align 8 +// CHECK-NEXT: %_0.repack3 = getelementptr inbounds nuw i8, ptr %_0, i64 12 +// CHECK-NEXT: %.elt4 = extractvalue { double, float, float } %0, 2 +// CHECK-NEXT: store float %.elt4, ptr %_0.repack3, align 4 +// CHECK-NEXT: ret void +// CHECK-NEXT:} + +fn main() { + let x = std::hint::black_box(3.0); + let y = std::hint::black_box(2.5); + let scalar = std::hint::black_box(1.0); + let (r1, r2, r3) = df(x, y, scalar); + // 3*3*1.5 = 22.5 + assert_eq!(r1, 22.5); + // 2*x*y = 2*3*2.5 = 15.0 + assert_eq!(r2, 15.0); + // x*x*1 = 3*3 = 9 + assert_eq!(r3, 9.0); +}