From 685984a780041b8e5dc51a83439db81b3f5e3151 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 11 May 2026 08:53:22 +0200 Subject: [PATCH 01/26] Merge two functions always called after each other --- compiler/rustc_resolve/src/late.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index fb8de90d28aca..dfea0f45ec7dd 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -27,7 +27,7 @@ use rustc_errors::{ use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId}; -use rustc_hir::{MissingLifetimeKind, PrimTy, TraitCandidate}; +use rustc_hir::{MissingLifetimeKind, PrimTy}; use rustc_middle::middle::resolve_bound_vars::Set1; use rustc_middle::ty::{AssocTag, DelegationInfo, Visibility}; use rustc_middle::{bug, span_bug}; @@ -4780,8 +4780,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // it needs to be added to the trait map. if ns == ValueNS { let item_name = path.last().unwrap().ident; - let traits = self.traits_in_scope(item_name, ns); - self.r.trait_map.insert(node_id, traits); + self.record_traits_in_scope(node_id, item_name); } if PrimTy::from_name(path[0].ident.name).is_some() { @@ -5382,13 +5381,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // we need to add any trait methods we find that match the // field name so that we can do some nice error reporting // later on in typeck. - let traits = self.traits_in_scope(ident, ValueNS); - self.r.trait_map.insert(expr.id, traits); + self.record_traits_in_scope(expr.id, ident); } ExprKind::MethodCall(ref call) => { debug!("(recording candidate traits for expr) recording traits for {}", expr.id); - let traits = self.traits_in_scope(call.seg.ident, ValueNS); - self.r.trait_map.insert(expr.id, traits); + self.record_traits_in_scope(expr.id, call.seg.ident); } _ => { // Nothing to do. @@ -5396,13 +5393,14 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } } - fn traits_in_scope(&mut self, ident: Ident, ns: Namespace) -> &'tcx [TraitCandidate<'tcx>] { - self.r.traits_in_scope( + fn record_traits_in_scope(&mut self, node_id: NodeId, ident: Ident) { + let traits = self.r.traits_in_scope( self.current_trait_ref.as_ref().map(|(module, _)| *module), &self.parent_scope, ident.span, - Some((ident.name, ns)), - ) + Some((ident.name, ValueNS)), + ); + self.r.trait_map.insert(node_id, traits); } fn resolve_and_cache_rustdoc_path(&mut self, path_str: &str, ns: Namespace) -> Option { From ed8e3ba2782c602e6c3c9e1e47bd7dd6df2ab7fa Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 11 May 2026 09:39:54 +0200 Subject: [PATCH 02/26] Remove an unnecessary generic --- compiler/rustc_resolve/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index f5f4c9e6e2580..22c4f4576d44b 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -822,7 +822,7 @@ impl<'ra> Module<'ra> { } /// This modifies `self` in place. The traits will be stored in `self.traits`. - fn ensure_traits<'tcx>(self, resolver: &impl AsRef>) { + fn ensure_traits<'tcx>(self, resolver: &Resolver<'ra, 'tcx>) { let mut traits = self.traits.borrow_mut(resolver.as_ref()); if traits.is_none() { let mut collected_traits = Vec::new(); From 31a054c51b7965345a320b505805f1ad6951dd61 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 12 May 2026 12:31:24 +0200 Subject: [PATCH 03/26] Add a dedicated method for error lifetime recording --- compiler/rustc_resolve/src/late.rs | 84 ++++++++++-------------------- 1 file changed, 28 insertions(+), 56 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index dfea0f45ec7dd..9e26acfe249e3 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -781,8 +781,7 @@ pub(crate) struct DiagMetadata<'ast> { /// Accumulate the errors due to missed lifetime elision, /// and report them all at once for each function. - current_elision_failures: - Vec<(MissingLifetime, LifetimeElisionCandidate, Either>)>, + current_elision_failures: Vec<(MissingLifetime, Either>)>, } struct LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { @@ -1831,20 +1830,12 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { LifetimeRibKind::Item => break, LifetimeRibKind::ConstParamTy => { let guar = self.emit_non_static_lt_in_const_param_ty_error(lifetime); - self.record_lifetime_res( - lifetime.id, - LifetimeRes::Error(guar), - LifetimeElisionCandidate::Ignore, - ); + self.record_lifetime_err(lifetime.id, guar); return; } LifetimeRibKind::ConcreteAnonConst(cause) => { let guar = self.emit_forbidden_non_static_lifetime_error(cause, lifetime); - self.record_lifetime_res( - lifetime.id, - LifetimeRes::Error(guar), - LifetimeElisionCandidate::Ignore, - ); + self.record_lifetime_err(lifetime.id, guar); return; } LifetimeRibKind::AnonymousCreateParameter { .. } @@ -1862,11 +1853,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { .find_map(|rib| rib.bindings.get_key_value(&normalized_ident).map(|(&outer, _)| outer)); let guar = self.emit_undeclared_lifetime_error(lifetime, outer_res); - self.record_lifetime_res( - lifetime.id, - LifetimeRes::Error(guar), - LifetimeElisionCandidate::Named, - ); + self.record_lifetime_err(lifetime.id, guar); } #[instrument(level = "debug", skip(self))] @@ -2015,11 +2002,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { span: lifetime.ident.span, }) }; - self.record_lifetime_res( - lifetime.id, - LifetimeRes::Error(guar), - elision_candidate, - ); + self.record_lifetime_err(lifetime.id, guar); return; } LifetimeRibKind::Elided(res) => { @@ -2027,11 +2010,9 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { return; } LifetimeRibKind::ElisionFailure => { - self.diag_metadata.current_elision_failures.push(( - missing_lifetime, - elision_candidate, - Either::Left(lifetime.id), - )); + self.diag_metadata + .current_elision_failures + .push((missing_lifetime, Either::Left(lifetime.id))); return; } LifetimeRibKind::Item => break, @@ -2045,7 +2026,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } } let guar = self.report_missing_lifetime_specifiers([&missing_lifetime], None); - self.record_lifetime_res(lifetime.id, LifetimeRes::Error(guar), elision_candidate); + self.record_lifetime_err(lifetime.id, guar); } fn point_at_impl_lifetimes(&mut self, err: &mut Diag<'_>, i: usize, lifetime: Span) { @@ -2311,11 +2292,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { should_lint = false; for id in node_ids { - self.record_lifetime_res( - id, - LifetimeRes::Error(guar), - LifetimeElisionCandidate::Named, - ); + self.record_lifetime_err(id, guar); } break; } @@ -2345,11 +2322,9 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { break; } LifetimeRibKind::ElisionFailure => { - self.diag_metadata.current_elision_failures.push(( - missing_lifetime, - LifetimeElisionCandidate::Ignore, - Either::Right(node_ids), - )); + self.diag_metadata + .current_elision_failures + .push((missing_lifetime, Either::Right(node_ids))); break; } // `LifetimeRes::Error`, which would usually be used in the case of @@ -2360,11 +2335,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { let guar = self.report_missing_lifetime_specifiers([&missing_lifetime], None); for id in node_ids { - self.record_lifetime_res( - id, - LifetimeRes::Error(guar), - LifetimeElisionCandidate::Ignore, - ); + self.record_lifetime_err(id, guar); } break; } @@ -2412,9 +2383,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { res: LifetimeRes, candidate: LifetimeElisionCandidate, ) { - if let Some(prev_res) = self.r.lifetimes_res_map.insert(id, res) { - panic!("lifetime {id:?} resolved multiple times ({prev_res:?} before, {res:?} now)") - } + self.record_lifetime_param(id, res); match res { LifetimeRes::Param { .. } | LifetimeRes::Fresh { .. } | LifetimeRes::Static { .. } => { @@ -2426,6 +2395,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } } + #[instrument(level = "debug", skip(self))] + fn record_lifetime_err(&mut self, id: NodeId, guar: ErrorGuaranteed) { + self.record_lifetime_param(id, LifetimeRes::Error(guar)); + } + #[instrument(level = "debug", skip(self))] fn record_lifetime_param(&mut self, id: NodeId, res: LifetimeRes) { if let Some(prev_res) = self.r.lifetimes_res_map.insert(id, res) { @@ -2470,15 +2444,13 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { elision_failures.iter().map(|(missing_lifetime, ..)| missing_lifetime), Some(failure_info), ); - let mut record_res = |lifetime, candidate| { - this.record_lifetime_res(lifetime, LifetimeRes::Error(guar), candidate) - }; - for (_, candidate, nodes) in elision_failures { + let mut record_res = |lifetime| this.record_lifetime_err(lifetime, guar); + for (_, nodes) in elision_failures { match nodes { - Either::Left(node_id) => record_res(node_id, candidate), + Either::Left(node_id) => record_res(node_id), Either::Right(node_ids) => { for lifetime in node_ids { - record_res(lifetime, candidate) + record_res(lifetime) } } } @@ -3146,7 +3118,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { param.ident, ); // Record lifetime res, so lowering knows there is something fishy. - self.record_lifetime_param(param.id, LifetimeRes::Error(guar)); + self.record_lifetime_err(param.id, guar); continue; } @@ -3158,7 +3130,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { let rib = match param.kind { GenericParamKind::Lifetime => { // Record lifetime res, so lowering knows there is something fishy. - self.record_lifetime_param(param.id, LifetimeRes::Error(guar)); + self.record_lifetime_err(param.id, guar); continue; } GenericParamKind::Type { .. } => &mut function_type_rib, @@ -3193,7 +3165,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { .create_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span }) .emit_unless_delay(is_raw_underscore_lifetime); // Record lifetime res, so lowering knows there is something fishy. - self.record_lifetime_param(param.id, LifetimeRes::Error(guar)); + self.record_lifetime_err(param.id, guar); continue; } @@ -3203,7 +3175,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { lifetime: param.ident, }); // Record lifetime res, so lowering knows there is something fishy. - self.record_lifetime_param(param.id, LifetimeRes::Error(guar)); + self.record_lifetime_err(param.id, guar); continue; } From d8cddda134d970e81ad95ee4be548cf6cdd6f3fc Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 26 May 2026 13:14:02 +0200 Subject: [PATCH 04/26] Rename and document some methods --- compiler/rustc_resolve/src/late.rs | 36 +++++++++++++++++------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 9e26acfe249e3..1b3da5b9dcbb1 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1748,7 +1748,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { let ident = lifetime.ident; if ident.name == kw::StaticLifetime { - self.record_lifetime_res( + self.record_lifetime_use( lifetime.id, LifetimeRes::Static, LifetimeElisionCandidate::Named, @@ -1764,7 +1764,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { while let Some(rib) = lifetime_rib_iter.next() { let normalized_ident = ident.normalize_to_macros_2_0(); if let Some(&(_, res)) = rib.bindings.get(&normalized_ident) { - self.record_lifetime_res(lifetime.id, res, LifetimeElisionCandidate::Named); + self.record_lifetime_use(lifetime.id, res, LifetimeElisionCandidate::Named); if let LifetimeRes::Param { param, binder } = res { match self.lifetime_uses.entry(param) { @@ -1880,7 +1880,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { match rib.kind { LifetimeRibKind::AnonymousCreateParameter { binder, .. } => { let res = self.create_fresh_lifetime(lifetime.ident, binder, kind); - self.record_lifetime_res(lifetime.id, res, elision_candidate); + self.record_lifetime_use(lifetime.id, res, elision_candidate); return; } LifetimeRibKind::StaticIfNoLifetimeInScope { lint_id: node_id, emit_lint } => { @@ -1898,7 +1898,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } } if lifetimes_in_scope.is_empty() { - self.record_lifetime_res( + self.record_lifetime_use( lifetime.id, LifetimeRes::Static, elision_candidate, @@ -2006,7 +2006,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { return; } LifetimeRibKind::Elided(res) => { - self.record_lifetime_res(lifetime.id, res, elision_candidate); + self.record_lifetime_use(lifetime.id, res, elision_candidate); return; } LifetimeRibKind::ElisionFailure => { @@ -2123,7 +2123,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { let id = self.r.next_node_id(); let lt = Lifetime { id, ident: Ident::new(kw::UnderscoreLifetime, span) }; - self.record_lifetime_res( + self.record_lifetime_use( anchor_id, LifetimeRes::ElidedAnchor { start: id, end: id + 1 }, LifetimeElisionCandidate::Ignore, @@ -2144,7 +2144,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // Leave the responsibility to create the `LocalDefId` to lowering. let param = self.r.next_node_id(); let res = LifetimeRes::Fresh { param, binder, kind }; - self.record_lifetime_param(param, res); + self.record_lifetime_def(param, res); // Record the created lifetime parameter so lowering can pick it up and add it to HIR. self.r @@ -2207,7 +2207,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } let node_ids = self.r.next_node_ids(expected_lifetimes); - self.record_lifetime_res( + self.record_lifetime_use( segment_id, LifetimeRes::ElidedAnchor { start: node_ids.start, end: node_ids.end }, LifetimeElisionCandidate::Ignore, @@ -2233,7 +2233,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // Do not create a parameter for patterns and expressions: type checking can infer // the appropriate lifetime for us. for id in node_ids { - self.record_lifetime_res( + self.record_lifetime_use( id, LifetimeRes::Infer, LifetimeElisionCandidate::Named, @@ -2302,7 +2302,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { let mut candidate = LifetimeElisionCandidate::Missing(missing_lifetime); for id in node_ids { let res = self.create_fresh_lifetime(ident, binder, kind); - self.record_lifetime_res( + self.record_lifetime_use( id, res, replace(&mut candidate, LifetimeElisionCandidate::Named), @@ -2313,7 +2313,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { LifetimeRibKind::Elided(res) => { let mut candidate = LifetimeElisionCandidate::Missing(missing_lifetime); for id in node_ids { - self.record_lifetime_res( + self.record_lifetime_use( id, res, replace(&mut candidate, LifetimeElisionCandidate::Ignore), @@ -2376,14 +2376,15 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } } + /// Register a use of an already defined lifetime. #[instrument(level = "debug", skip(self))] - fn record_lifetime_res( + fn record_lifetime_use( &mut self, id: NodeId, res: LifetimeRes, candidate: LifetimeElisionCandidate, ) { - self.record_lifetime_param(id, res); + self.record_lifetime_def(id, res); match res { LifetimeRes::Param { .. } | LifetimeRes::Fresh { .. } | LifetimeRes::Static { .. } => { @@ -2395,13 +2396,16 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } } + /// Can be used for both definitions and uses of lifetimes, as an error + /// has already been reported. #[instrument(level = "debug", skip(self))] fn record_lifetime_err(&mut self, id: NodeId, guar: ErrorGuaranteed) { - self.record_lifetime_param(id, LifetimeRes::Error(guar)); + self.record_lifetime_def(id, LifetimeRes::Error(guar)); } + /// Define a new lifetime (e.g. in generics) #[instrument(level = "debug", skip(self))] - fn record_lifetime_param(&mut self, id: NodeId, res: LifetimeRes) { + fn record_lifetime_def(&mut self, id: NodeId, res: LifetimeRes) { if let Some(prev_res) = self.r.lifetimes_res_map.insert(id, res) { panic!( "lifetime parameter {id:?} resolved multiple times ({prev_res:?} before, {res:?} now)" @@ -3189,7 +3193,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } GenericParamKind::Lifetime => { let res = LifetimeRes::Param { param: def_id, binder }; - self.record_lifetime_param(param.id, res); + self.record_lifetime_def(param.id, res); function_lifetime_rib.bindings.insert(ident, (param.id, res)); continue; } From bf5045cae0ce9af1632f610f376264ada78b45f0 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 12 May 2026 12:38:57 +0200 Subject: [PATCH 05/26] Drop an unused distinction (in diagnostics code) between anonymous and named lifetimes --- compiler/rustc_resolve/src/late.rs | 12 +++++------- compiler/rustc_resolve/src/late/diagnostics.rs | 4 +--- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 1b3da5b9dcbb1..2a06244fd117a 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1751,7 +1751,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.record_lifetime_use( lifetime.id, LifetimeRes::Static, - LifetimeElisionCandidate::Named, + LifetimeElisionCandidate::Ignore, ); return; } @@ -1764,7 +1764,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { while let Some(rib) = lifetime_rib_iter.next() { let normalized_ident = ident.normalize_to_macros_2_0(); if let Some(&(_, res)) = rib.bindings.get(&normalized_ident) { - self.record_lifetime_use(lifetime.id, res, LifetimeElisionCandidate::Named); + self.record_lifetime_use(lifetime.id, res, LifetimeElisionCandidate::Ignore); if let LifetimeRes::Param { param, binder } = res { match self.lifetime_uses.entry(param) { @@ -2236,7 +2236,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.record_lifetime_use( id, LifetimeRes::Infer, - LifetimeElisionCandidate::Named, + LifetimeElisionCandidate::Ignore, ); } continue; @@ -2305,7 +2305,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.record_lifetime_use( id, res, - replace(&mut candidate, LifetimeElisionCandidate::Named), + replace(&mut candidate, LifetimeElisionCandidate::Ignore), ); } break; @@ -2529,9 +2529,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { }); all_candidates.extend(candidates.into_iter().filter_map(|(_, candidate)| { match candidate { - LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => { - None - } + LifetimeElisionCandidate::Ignore => None, LifetimeElisionCandidate::Missing(missing) => Some(missing), } })); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 419a47b126980..423c13ff87d37 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -149,10 +149,8 @@ pub(super) struct ElisionFnParameter { /// This is used to suggest introducing an explicit lifetime. #[derive(Clone, Copy, Debug)] pub(super) enum LifetimeElisionCandidate { - /// This is not a real lifetime. + /// This is not a real lifetime, or it is a named lifetime, in which case we won't suggest anything. Ignore, - /// There is a named lifetime, we won't suggest anything. - Named, Missing(MissingLifetime), } From c0819ffeca08e91b720d3f9feadc7550c17d9276 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 12 May 2026 15:19:31 +0200 Subject: [PATCH 06/26] Remove some dead code --- compiler/rustc_ast_lowering/src/item.rs | 2 +- compiler/rustc_ast_lowering/src/lib.rs | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index e38415caaa222..89052a19f57b6 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1928,7 +1928,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // Introduce extra lifetimes if late resolution tells us to. let extra_lifetimes = self.resolver.extra_lifetime_params(parent_node_id); - params.extend(extra_lifetimes.into_iter().filter_map(|&(ident, node_id, res)| { + params.extend(extra_lifetimes.into_iter().map(|&(ident, node_id, res)| { self.lifetime_res_to_generic_param( ident, node_id, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a916ee1f143bd..8d973ad3f1889 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -950,11 +950,8 @@ impl<'hir> LoweringContext<'_, 'hir> { node_id: NodeId, res: LifetimeRes, source: hir::GenericParamSource, - ) -> Option> { + ) -> hir::GenericParam<'hir> { let (name, kind) = match res { - LifetimeRes::Param { .. } => { - (hir::ParamName::Plain(ident), hir::LifetimeParamKind::Explicit) - } LifetimeRes::Fresh { param, kind, .. } => { // Late resolution delegates to us the creation of the `LocalDefId`. let _def_id = self.create_def( @@ -967,7 +964,6 @@ impl<'hir> LoweringContext<'_, 'hir> { (hir::ParamName::Fresh, hir::LifetimeParamKind::Elided(kind)) } - LifetimeRes::Static { .. } | LifetimeRes::Error(..) => return None, res => panic!( "Unexpected lifetime resolution {:?} for {:?} at {:?}", res, ident, ident.span @@ -975,7 +971,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }; let hir_id = self.lower_node_id(node_id); let def_id = self.local_def_id(node_id); - Some(hir::GenericParam { + hir::GenericParam { hir_id, def_id, name, @@ -984,7 +980,7 @@ impl<'hir> LoweringContext<'_, 'hir> { kind: hir::GenericParamKind::Lifetime { kind }, colon_span: None, source, - }) + } } /// Lowers a lifetime binder that defines `generic_params`, returning the corresponding HIR @@ -1005,7 +1001,7 @@ impl<'hir> LoweringContext<'_, 'hir> { debug!(?extra_lifetimes); let extra_lifetimes: Vec<_> = extra_lifetimes .iter() - .filter_map(|&(ident, node_id, res)| { + .map(|&(ident, node_id, res)| { self.lifetime_res_to_generic_param( ident, node_id, From 87f9c4f5b592a1cba95d406b1431c46a98fec5e2 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 12 May 2026 15:37:28 +0200 Subject: [PATCH 07/26] Remove an unused field --- compiler/rustc_hir/src/def.rs | 2 -- compiler/rustc_resolve/src/late.rs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index ad5d6b1509dfd..d275d5a28b88a 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -991,8 +991,6 @@ pub enum LifetimeRes { /// /// Creating the associated `LocalDefId` is the responsibility of lowering. param: NodeId, - /// Id of the introducing place. See `Param`. - binder: NodeId, /// Kind of elided lifetime kind: hir::MissingLifetimeKind, }, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 2a06244fd117a..91464f768cea9 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2143,7 +2143,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // Leave the responsibility to create the `LocalDefId` to lowering. let param = self.r.next_node_id(); - let res = LifetimeRes::Fresh { param, binder, kind }; + let res = LifetimeRes::Fresh { param, kind }; self.record_lifetime_def(param, res); // Record the created lifetime parameter so lowering can pick it up and add it to HIR. From 19a5af7d86f19668e8b73f341c86adb2fa17fe2e Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 12 May 2026 15:39:25 +0200 Subject: [PATCH 08/26] extra_lifetime_params_map can only ever contain `LifetimeRes::Fresh`, so just encode the fields we need --- compiler/rustc_ast_lowering/src/item.rs | 4 +-- compiler/rustc_ast_lowering/src/lib.rs | 35 +++++++++---------------- compiler/rustc_middle/src/ty/mod.rs | 5 ++-- compiler/rustc_resolve/src/late.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 4 +-- 5 files changed, 20 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 89052a19f57b6..0a50d9fffe775 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1928,11 +1928,11 @@ impl<'hir> LoweringContext<'_, 'hir> { // Introduce extra lifetimes if late resolution tells us to. let extra_lifetimes = self.resolver.extra_lifetime_params(parent_node_id); - params.extend(extra_lifetimes.into_iter().map(|&(ident, node_id, res)| { + params.extend(extra_lifetimes.into_iter().map(|&(ident, node_id, kind)| { self.lifetime_res_to_generic_param( ident, node_id, - res, + kind, hir::GenericParamSource::Generics, ) })); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 8d973ad3f1889..2366cb8db462d 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -55,7 +55,7 @@ use rustc_hir::definitions::PerParentDisambiguatorState; use rustc_hir::lints::DelayedLint; use rustc_hir::{ self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource, - LifetimeSyntax, ParamName, Target, TraitCandidate, find_attr, + LifetimeSyntax, MissingLifetimeKind, ParamName, Target, TraitCandidate, find_attr, }; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_macros::extension; @@ -310,7 +310,7 @@ impl<'tcx> ResolverAstLowering<'tcx> { /// /// The extra lifetimes that appear from the parenthesized `Fn`-trait desugaring /// should appear at the enclosing `PolyTraitRef`. - fn extra_lifetime_params(&self, id: NodeId) -> &[(Ident, NodeId, LifetimeRes)] { + fn extra_lifetime_params(&self, id: NodeId) -> &[(Ident, NodeId, MissingLifetimeKind)] { self.extra_lifetime_params_map.get(&id).map_or(&[], |v| &v[..]) } @@ -948,36 +948,27 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, ident: Ident, node_id: NodeId, - res: LifetimeRes, + kind: MissingLifetimeKind, source: hir::GenericParamSource, ) -> hir::GenericParam<'hir> { - let (name, kind) = match res { - LifetimeRes::Fresh { param, kind, .. } => { - // Late resolution delegates to us the creation of the `LocalDefId`. - let _def_id = self.create_def( - param, - Some(kw::UnderscoreLifetime), - DefKind::LifetimeParam, - ident.span, - ); - debug!(?_def_id); + // Late resolution delegates to us the creation of the `LocalDefId`. + let _def_id = self.create_def( + node_id, + Some(kw::UnderscoreLifetime), + DefKind::LifetimeParam, + ident.span, + ); + debug!(?_def_id); - (hir::ParamName::Fresh, hir::LifetimeParamKind::Elided(kind)) - } - res => panic!( - "Unexpected lifetime resolution {:?} for {:?} at {:?}", - res, ident, ident.span - ), - }; let hir_id = self.lower_node_id(node_id); let def_id = self.local_def_id(node_id); hir::GenericParam { hir_id, def_id, - name, + name: hir::ParamName::Fresh, span: self.lower_span(ident.span), pure_wrt_drop: false, - kind: hir::GenericParamKind::Lifetime { kind }, + kind: hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Elided(kind) }, colon_span: None, source, } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 74f9e75fb48c0..2958b2d5cd590 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -37,12 +37,11 @@ use rustc_data_structures::stable_hash::{StableHash, StableHashCtxt, StableHashe use rustc_data_structures::steal::Steal; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::{Diag, ErrorGuaranteed, LintBuffer}; -use rustc_hir as hir; use rustc_hir::attrs::StrippedCfgItem; use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap}; use rustc_hir::definitions::PerParentDisambiguatorState; -use rustc_hir::{LangItem, attrs as attr, find_attr}; +use rustc_hir::{self as hir, LangItem, MissingLifetimeKind, attrs as attr, find_attr}; use rustc_index::IndexVec; use rustc_index::bit_set::BitMatrix; use rustc_macros::{ @@ -232,7 +231,7 @@ pub struct ResolverAstLowering<'tcx> { /// Resolutions for lifetimes. pub lifetimes_res_map: NodeMap, /// Lifetime parameters that lowering will have to introduce. - pub extra_lifetime_params_map: NodeMap>, + pub extra_lifetime_params_map: NodeMap>, pub next_node_id: ast::NodeId, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 91464f768cea9..5c709998cfe32 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2151,7 +2151,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { .extra_lifetime_params_map .entry(binder) .or_insert_with(Vec::new) - .push((ident, param, res)); + .push((ident, param, kind)); res } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 22c4f4576d44b..2ce50b23ac5ed 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -58,7 +58,7 @@ use rustc_hir::def::{ }; use rustc_hir::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap}; use rustc_hir::definitions::{PerParentDisambiguatorState, PerParentDisambiguatorsMap}; -use rustc_hir::{PrimTy, TraitCandidate, find_attr}; +use rustc_hir::{MissingLifetimeKind, PrimTy, TraitCandidate, find_attr}; use rustc_index::bit_set::DenseBitSet; use rustc_metadata::creader::CStore; use rustc_middle::metadata::{AmbigModChild, ModChild, Reexport}; @@ -1385,7 +1385,7 @@ pub struct Resolver<'ra, 'tcx> { /// Resolutions for lifetimes. lifetimes_res_map: NodeMap = Default::default(), /// Lifetime parameters that lowering will have to introduce. - extra_lifetime_params_map: NodeMap> = Default::default(), + extra_lifetime_params_map: NodeMap> = Default::default(), /// `CrateNum` resolutions of `extern crate` items. extern_crate_map: UnordMap = Default::default(), From c8aba3e9889c9f501300f519c0d8dc4075bf402f Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Thu, 28 May 2026 13:12:34 +0000 Subject: [PATCH 09/26] Stabilize Path::is_empty --- library/std/src/path.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 222bf77996c7f..3ff591b1907d3 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -2854,7 +2854,6 @@ impl Path { /// # Examples /// /// ``` - /// #![feature(path_is_empty)] /// use std::path::Path; /// /// let path = Path::new(""); @@ -2866,7 +2865,7 @@ impl Path { /// let path = Path::new("."); /// assert!(!path.is_empty()); /// ``` - #[unstable(feature = "path_is_empty", issue = "148494")] + #[stable(feature = "path_is_empty", since = "CURRENT_RUSTC_VERSION")] pub fn is_empty(&self) -> bool { self.as_os_str().is_empty() } From 420566f17095a6c138f2f2ec58b7a799859365f9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 28 May 2026 16:17:04 +0200 Subject: [PATCH 10/26] Remove a hack introduced back when unwinding through extern "C" was UB --- library/proc_macro/src/bridge/client.rs | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index 696cd4ee3d887..0e37d05d08571 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -250,7 +250,7 @@ fn run_client Decode<'a, 's, ()>, R: Encode<()>>( ) -> Buffer { let BridgeConfig { input: mut buf, dispatch, force_show_panics, .. } = config; - panic::catch_unwind(panic::AssertUnwindSafe(|| { + let res = panic::catch_unwind(panic::AssertUnwindSafe(|| { maybe_install_panic_hook(force_show_panics); // Make sure the symbol store is empty before decoding inputs. @@ -267,23 +267,12 @@ fn run_client Decode<'a, 's, ()>, R: Encode<()>>( // Take the `cached_buffer` back out, for the output value. buf = RefCell::into_inner(state).cached_buffer; - // HACK(eddyb) Separate encoding a success value (`Ok(output)`) - // from encoding a panic (`Err(e: PanicMessage)`) to avoid - // having handles outside the `bridge.enter(|| ...)` scope, and - // to catch panics that could happen while encoding the success. - // - // Note that panics should be impossible beyond this point, but - // this is defensively trying to avoid any accidental panicking - // reaching the `extern "C"` (which should `abort` but might not - // at the moment, so this is also potentially preventing UB). - buf.clear(); - Ok::<_, ()>(output).encode(&mut buf, &mut ()); - })) - .map_err(PanicMessage::from) - .unwrap_or_else(|e| { - buf.clear(); - Err::<(), _>(e).encode(&mut buf, &mut ()); - }); + output + })); + + // Serialize response of type `Result`. + buf.clear(); + res.map_err(PanicMessage::from).encode(&mut buf, &mut ()); // Now that a response has been serialized, invalidate all symbols // registered with the interner. From 32615f248aabb8094405378a8ca7a4dbfd423a95 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 28 May 2026 16:19:49 +0200 Subject: [PATCH 11/26] Implement Encode and Decode for proc_macro::TokenStream wrapper type --- library/proc_macro/src/bridge/client.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index 0e37d05d08571..70f9da89427cc 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -47,6 +47,18 @@ impl Decode<'_, '_, S> for TokenStream { } } +impl Encode<()> for crate::TokenStream { + fn encode(self, w: &mut Buffer, s: &mut ()) { + self.0.encode(w, s) + } +} + +impl Decode<'_, '_, ()> for crate::TokenStream { + fn decode(r: &mut &[u8], s: &mut ()) -> Self { + crate::TokenStream(Some(Decode::decode(r, s))) + } +} + #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub(crate) struct Span { handle: handle::Handle, @@ -244,9 +256,9 @@ fn maybe_install_panic_hook(force_show_panics: bool) { /// Client-side helper for handling client panics, entering the bridge, /// deserializing input and serializing output. // FIXME(eddyb) maybe replace `Bridge::enter` with this? -fn run_client Decode<'a, 's, ()>, R: Encode<()>>( +fn run_client Decode<'a, 's, ()>>( config: BridgeConfig<'_>, - f: impl FnOnce(A) -> R, + f: impl FnOnce(A) -> crate::TokenStream, ) -> Buffer { let BridgeConfig { input: mut buf, dispatch, force_show_panics, .. } = config; @@ -285,7 +297,7 @@ impl Client { Client { handle_counters: &COUNTERS, run: super::selfless_reify::reify_to_extern_c_fn_hrt_bridge(move |bridge| { - run_client(bridge, |input| f(crate::TokenStream(Some(input))).0) + run_client(bridge, |input| f(input)) }), _marker: PhantomData, } @@ -299,9 +311,7 @@ impl Client<(crate::TokenStream, crate::TokenStream), crate::TokenStream> { Client { handle_counters: &COUNTERS, run: super::selfless_reify::reify_to_extern_c_fn_hrt_bridge(move |bridge| { - run_client(bridge, |(input, input2)| { - f(crate::TokenStream(Some(input)), crate::TokenStream(Some(input2))).0 - }) + run_client(bridge, |(input, input2)| f(input, input2)) }), _marker: PhantomData, } From 8f53ae3ace82a93d43e8b44225fec2b8dcc5bee3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 28 May 2026 16:21:09 +0200 Subject: [PATCH 12/26] Remove `skip_arg` attribute from `Diagnostic` and `Subdiagnostic` proc-macros, skipping fields based on whether or not they are used in error messages --- .../src/const_eval/machine.rs | 9 +- compiler/rustc_const_eval/src/errors.rs | 2 - compiler/rustc_hir_typeck/src/callee.rs | 6 +- compiler/rustc_hir_typeck/src/errors.rs | 3 +- compiler/rustc_lint/src/lints.rs | 11 +- compiler/rustc_lint/src/nonstandard_style.rs | 8 +- .../src/opaque_hidden_inferred_bound.rs | 1 - .../src/diagnostics/diagnostic.rs | 2 +- .../src/diagnostics/diagnostic_builder.rs | 80 ++++++------- .../rustc_macros/src/diagnostics/message.rs | 87 ++++++++------ .../rustc_macros/src/diagnostics/msg_macro.rs | 2 +- .../src/diagnostics/subdiagnostic.rs | 29 +++-- .../rustc_macros/src/diagnostics/utils.rs | 19 ++- compiler/rustc_macros/src/lib.rs | 2 - compiler/rustc_mir_build/src/errors.rs | 19 ++- .../src/thir/pattern/check_match.rs | 15 ++- compiler/rustc_parse/src/errors.rs | 4 - compiler/rustc_parse/src/parser/pat.rs | 20 ++-- .../diagnostic-derive-doc-comment-field.rs | 4 +- .../diagnostic-derive-inline.rs | 6 +- .../diagnostic-derive-inline.stderr | 110 +++++++----------- .../subdiagnostic-derive-inline.rs | 1 - .../subdiagnostic-derive-inline.stderr | 108 ++++++++--------- 23 files changed, 283 insertions(+), 265 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index fb456d80e465f..c24387c945d7f 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -761,14 +761,13 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { // current number of evaluated terminators is a power of 2. The latter gives us a cheap // way to implement exponential backoff. let span = ecx.cur_span(); + let mut warn = + ecx.tcx.dcx().create_warn(LongRunningWarn { span, item_span: ecx.tcx.span }); // We store a unique number in `force_duplicate` to evade `-Z deduplicate-diagnostics`. // `new_steps` is guaranteed to be unique because `ecx.machine.num_evaluated_steps` is // always increasing. - ecx.tcx.dcx().emit_warn(LongRunningWarn { - span, - item_span: ecx.tcx.span, - force_duplicate: new_steps, - }); + warn.arg("force_duplicate", new_steps); + warn.emit(); } } diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 311696a3acc99..9faf9a59fc22a 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -298,8 +298,6 @@ pub(crate) struct LongRunningWarn { pub span: Span, #[help("the constant being evaluated")] pub item_span: Span, - // Used for evading `-Z deduplicate-diagnostics`. - pub force_duplicate: usize, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index d51a0bf2c3ef4..7d687099f9715 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -845,7 +845,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut path = None; let mut err = self.dcx().create_err(errors::InvalidCallee { span: callee_expr.span, - ty: callee_ty, found: match &unit_variant { Some((_, kind, path)) => format!("{kind} `{path}`"), None => format!("`{}`", self.tcx.short_string(callee_ty, &mut path)), @@ -949,7 +948,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let Some(span) = self.tcx.hir_res_span(def) { - let callee_ty = callee_ty.to_string(); let label = match (unit_variant, inner_callee_path) { (Some((_, kind, path)), _) => { err.arg("kind", kind); @@ -959,6 +957,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (_, Some(hir::QPath::Resolved(_, path))) => { self.tcx.sess.source_map().span_to_snippet(path.span).ok().map(|p| { err.arg("func", p); + err.arg("ty", callee_ty); msg!("`{$func}` defined here returns `{$ty}`") }) } @@ -968,6 +967,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // type definitions themselves, but rather variables *of* that type. Res::Local(hir_id) => { err.arg("local_name", self.tcx.hir_name(hir_id)); + err.arg("ty", callee_ty); Some(msg!("`{$local_name}` has type `{$ty}`")) } Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => { @@ -975,7 +975,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(msg!("`{$path}` defined here")) } _ => { - err.arg("path", callee_ty); + err.arg("path", callee_ty.to_string()); Some(msg!("`{$path}` defined here")) } } diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 3457cc373413a..a9a819935287c 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -476,10 +476,9 @@ pub(crate) struct SlicingSuggestion { #[derive(Diagnostic)] #[diag("expected function, found {$found}", code = E0618)] -pub(crate) struct InvalidCallee<'tcx> { +pub(crate) struct InvalidCallee { #[primary_span] pub span: Span, - pub ty: Ty<'tcx>, pub found: String, } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index c77e70dcbe9bb..227a413ea9b07 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1562,17 +1562,16 @@ pub(crate) enum NonCamelCaseTypeSub { pub(crate) struct NonSnakeCaseDiag<'a> { pub sort: &'a str, pub name: &'a str, - pub sc: String, #[subdiagnostic] pub sub: NonSnakeCaseDiagSub, } pub(crate) enum NonSnakeCaseDiagSub { Label { span: Span }, - Help, + Help { sc: String }, RenameOrConvertSuggestion { span: Span, suggestion: Ident }, ConvertSuggestion { span: Span, suggestion: String }, - SuggestionAndNote { span: Span }, + SuggestionAndNote { sc: String, span: Span }, } impl Subdiagnostic for NonSnakeCaseDiagSub { @@ -1581,7 +1580,8 @@ impl Subdiagnostic for NonSnakeCaseDiagSub { NonSnakeCaseDiagSub::Label { span } => { diag.span_label(span, msg!("should have a snake_case name")); } - NonSnakeCaseDiagSub::Help => { + NonSnakeCaseDiagSub::Help { sc } => { + diag.arg("sc", sc); diag.help(msg!("convert the identifier to snake case: `{$sc}`")); } NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion } => { @@ -1600,7 +1600,8 @@ impl Subdiagnostic for NonSnakeCaseDiagSub { Applicability::MaybeIncorrect, ); } - NonSnakeCaseDiagSub::SuggestionAndNote { span } => { + NonSnakeCaseDiagSub::SuggestionAndNote { sc, span } => { + diag.arg("sc", sc); diag.note(msg!("`{$sc}` cannot be used as a raw identifier")); diag.span_suggestion( span, diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index fbbfbd86d319f..e3653c55f53a4 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -311,18 +311,18 @@ impl NonSnakeCase { suggestion: sc_ident, } } else { - NonSnakeCaseDiagSub::SuggestionAndNote { span } + NonSnakeCaseDiagSub::SuggestionAndNote { sc, span } } } else { - NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion: sc.clone() } + NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion: sc } } } else { - NonSnakeCaseDiagSub::Help + NonSnakeCaseDiagSub::Help { sc } } } else { NonSnakeCaseDiagSub::Label { span } }; - cx.emit_span_lint(NON_SNAKE_CASE, span, NonSnakeCaseDiag { sort, name, sc, sub }); + cx.emit_span_lint(NON_SNAKE_CASE, span, NonSnakeCaseDiag { sort, name, sub }); } } } diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 6b19aa17c6d6c..f646a558266e2 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -232,6 +232,5 @@ struct OpaqueHiddenInferredBoundLint<'tcx> { struct AddBound<'tcx> { #[primary_span] suggest_span: Span, - #[skip_arg] trait_ref: TraitPredPrintModifiersAndPath<'tcx>, } diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index 2f7c3cc6a46d2..ac777b37a4303 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -26,7 +26,7 @@ impl<'a> DiagnosticDerive<'a> { let Some(message) = builder.primary_message() else { return DiagnosticDeriveError::ErrorHandled.to_compile_error(); }; - let message = message.diag_message(Some(variant)); + let message = message.diag_message(); let init = quote! { let mut diag = rustc_errors::Diag::new( diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index e335037f2c4c9..cdff1280d69f9 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -1,5 +1,7 @@ #![deny(unused_must_use)] +use std::collections::HashSet; + use proc_macro2::{Ident, Span, TokenStream}; use quote::{format_ident, quote, quote_spanned}; use syn::parse::ParseStream; @@ -52,6 +54,7 @@ where formatting_init: TokenStream::new(), message: None, code: None, + used_fields: HashSet::new(), }; f(builder, variant) }); @@ -83,6 +86,8 @@ pub(crate) struct DiagnosticDeriveVariantBuilder { /// Error codes are a optional part of the struct attribute - this is only set to detect /// multiple specifications. pub code: SpannedOption<()>, + + pub used_fields: HashSet, } impl DiagnosticDeriveVariantBuilder { @@ -107,8 +112,7 @@ impl DiagnosticDeriveVariantBuilder { let ast = variant.ast(); let attrs = &ast.attrs; let preamble = attrs.iter().map(|attr| { - self.generate_structure_code_for_attr(attr, variant) - .unwrap_or_else(|v| v.to_compile_error()) + self.generate_structure_code_for_attr(attr).unwrap_or_else(|v| v.to_compile_error()) }); quote! { @@ -120,23 +124,34 @@ impl DiagnosticDeriveVariantBuilder { /// calls to `arg` when no attributes are present. pub(crate) fn body(&mut self, variant: &VariantInfo<'_>) -> TokenStream { let mut body = quote! {}; + let mut second_part = quote! {}; + + // Subdiagnostic additions. + for binding in variant.bindings().iter().filter(|bi| !should_generate_arg(bi.ast())) { + second_part.extend(self.generate_field_attrs_code(binding)); + } // Generate `arg` calls first.. for binding in variant.bindings().iter().filter(|bi| should_generate_arg(bi.ast())) { - body.extend(self.generate_field_code(binding)); - } - // ..and then subdiagnostic additions. - for binding in variant.bindings().iter().filter(|bi| !should_generate_arg(bi.ast())) { - body.extend(self.generate_field_attrs_code(binding, variant)); + if self.is_used_in_message(binding) { + body.extend(self.generate_field_code(binding)); + } } + body.extend(second_part); body } + fn is_used_in_message(&self, binding: &BindingInfo<'_>) -> bool { + binding.ast().ident.as_ref().is_some_and(|ident| self.used_fields.contains(ident)) + } + /// Parse a `SubdiagnosticKind` from an `Attribute`. fn parse_subdiag_attribute( - &self, + &mut self, attr: &Attribute, ) -> Result, DiagnosticDeriveError> { - let Some(subdiag) = SubdiagnosticVariant::from_attr(attr, &self.field_map)? else { + let Some(subdiag) = + SubdiagnosticVariant::from_attr(attr, &self.field_map, &mut self.used_fields)? + else { // Some attributes aren't errors - like documentation comments - but also aren't // subdiagnostics. return Ok(None); @@ -160,7 +175,6 @@ impl DiagnosticDeriveVariantBuilder { fn generate_structure_code_for_attr( &mut self, attr: &Attribute, - variant: &VariantInfo<'_>, ) -> Result { // Always allow documentation comments. if is_doc_comment(attr) { @@ -183,11 +197,14 @@ impl DiagnosticDeriveVariantBuilder { ) .emit(); } - self.message = Some(Message { - attr_span: attr.span(), - message_span: message.span(), - value: message.value(), - }); + let message = Message::new( + attr.span(), + message.span(), + message.value(), + &self.field_map, + &mut self.used_fields, + ); + self.message = Some(message); } // Parse arguments @@ -240,7 +257,7 @@ impl DiagnosticDeriveVariantBuilder { | SubdiagnosticKind::NoteOnce | SubdiagnosticKind::Help | SubdiagnosticKind::HelpOnce - | SubdiagnosticKind::Warn => Ok(self.add_subdiagnostic(&fn_ident, message, variant)), + | SubdiagnosticKind::Warn => Ok(self.add_subdiagnostic(&fn_ident, message)), SubdiagnosticKind::Label | SubdiagnosticKind::Suggestion { .. } => { throw_invalid_attr!(attr, |diag| diag .help("`#[label]` and `#[suggestion]` can only be applied to fields")); @@ -268,11 +285,7 @@ impl DiagnosticDeriveVariantBuilder { } } - fn generate_field_attrs_code( - &mut self, - binding_info: &BindingInfo<'_>, - variant: &VariantInfo<'_>, - ) -> TokenStream { + fn generate_field_attrs_code(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream { let field = binding_info.ast(); let field_binding = &binding_info.binding; @@ -311,7 +324,6 @@ impl DiagnosticDeriveVariantBuilder { attr, FieldInfo { binding: binding_info, ty: inner_ty, span: &field.span() }, binding, - variant ) .unwrap_or_else(|v| v.to_compile_error()); @@ -329,14 +341,10 @@ impl DiagnosticDeriveVariantBuilder { attr: &Attribute, info: FieldInfo<'_>, binding: TokenStream, - variant: &VariantInfo<'_>, ) -> Result { let ident = &attr.path().segments.last().unwrap().ident; let name = ident.to_string(); match (&attr.meta, name.as_str()) { - // Don't need to do anything - by virtue of the attribute existing, the - // `arg` call will not be generated. - (Meta::Path(_), "skip_arg") => return Ok(quote! {}), (Meta::Path(_), "primary_span") => { report_error_if_not_applied_to_span(attr, &info)?; @@ -359,7 +367,7 @@ impl DiagnosticDeriveVariantBuilder { match subdiag { SubdiagnosticKind::Label => { report_error_if_not_applied_to_span(attr, &info)?; - Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, message, variant)) + Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, message)) } SubdiagnosticKind::Note | SubdiagnosticKind::NoteOnce @@ -370,11 +378,11 @@ impl DiagnosticDeriveVariantBuilder { if type_matches_path(inner, &["rustc_span", "Span"]) || type_matches_path(inner, &["rustc_span", "MultiSpan"]) { - Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, message, variant)) + Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, message)) } else if type_is_unit(inner) || (matches!(info.ty, FieldInnerTy::Plain(_)) && type_is_bool(inner)) { - Ok(self.add_subdiagnostic(&fn_ident, message, variant)) + Ok(self.add_subdiagnostic(&fn_ident, message)) } else { report_type_error(attr, "`Span`, `MultiSpan`, `bool` or `()`")? } @@ -400,7 +408,7 @@ impl DiagnosticDeriveVariantBuilder { applicability.set_once(quote! { #static_applicability }, span); } - let message = message.diag_message(Some(variant)); + let message = message.diag_message(); let applicability = applicability .value() .unwrap_or_else(|| quote! { rustc_errors::Applicability::Unspecified }); @@ -428,10 +436,9 @@ impl DiagnosticDeriveVariantBuilder { field_binding: TokenStream, kind: &Ident, message: Message, - variant: &VariantInfo<'_>, ) -> TokenStream { let fn_name = format_ident!("span_{}", kind); - let message = message.diag_message(Some(variant)); + let message = message.diag_message(); quote! { diag.#fn_name( #field_binding, @@ -442,13 +449,8 @@ impl DiagnosticDeriveVariantBuilder { /// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current message /// and `fluent_attr_identifier`. - fn add_subdiagnostic( - &self, - kind: &Ident, - message: Message, - variant: &VariantInfo<'_>, - ) -> TokenStream { - let message = message.diag_message(Some(variant)); + fn add_subdiagnostic(&self, kind: &Ident, message: Message) -> TokenStream { + let message = message.diag_message(); quote! { diag.#kind(#message); } diff --git a/compiler/rustc_macros/src/diagnostics/message.rs b/compiler/rustc_macros/src/diagnostics/message.rs index 11bf904c18e1b..26c2fb98d28e2 100644 --- a/compiler/rustc_macros/src/diagnostics/message.rs +++ b/compiler/rustc_macros/src/diagnostics/message.rs @@ -1,11 +1,13 @@ +use std::collections::{HashMap, HashSet}; + use fluent_bundle::FluentResource; use fluent_syntax::ast::{Expression, InlineExpression, Pattern, PatternElement}; use proc_macro2::{Span, TokenStream}; use quote::quote; use syn::ext::IdentExt; -use synstructure::VariantInfo; use crate::diagnostics::error::span_err; +use crate::diagnostics::utils::FieldMap; #[derive(Clone)] pub(crate) struct Message { @@ -15,53 +17,66 @@ pub(crate) struct Message { } impl Message { + pub(crate) fn new( + attr_span: Span, + message_span: Span, + message_str: String, + field_map: &FieldMap, + used_fields: &mut HashSet, + ) -> Self { + // Parse the fluent message + const GENERATED_MSG_ID: &str = "generated_msg"; + let resource = + FluentResource::try_new(format!("{GENERATED_MSG_ID} = {message_str}\n")).unwrap(); + assert_eq!(resource.entries().count(), 1); + let Some(fluent_syntax::ast::Entry::Message(flt_message)) = resource.get_entry(0) else { + panic!("Did not parse into a message") + }; + + let mut fields: HashMap = + HashMap::with_capacity(field_map.len()); + for (_, (ident, _)) in field_map { + fields.insert(ident.unraw().to_string(), (ident, false)); + } + for variable in variable_references(&flt_message) { + match fields.get_mut(variable) { + Some((_, seen)) => *seen = true, + None => { + span_err( + message_span.unwrap(), + format!("Variable `{variable}` not found in diagnostic "), + ) + .help(format!( + "Available fields: {:?}", + fields.keys().map(|s| s.as_str()).collect::>().join(", ") + )) + .emit(); + } + } + } + for (name, seen) in fields.values() { + if *seen { + used_fields.insert((*name).clone()); + } + } + Self { attr_span, message_span, value: message_str } + } + /// Get the diagnostic message for this diagnostic /// The passed `variant` is used to check whether all variables in the message are used. /// For subdiagnostics, we cannot check this. - pub(crate) fn diag_message(&self, variant: Option<&VariantInfo<'_>>) -> TokenStream { + pub(crate) fn diag_message(&self) -> TokenStream { let message = &self.value; - self.verify(variant); + self.verify(); quote! { rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed(#message)) } } - fn verify(&self, variant: Option<&VariantInfo<'_>>) { - verify_variables_used(self.message_span, &self.value, variant); + fn verify(&self) { verify_message_style(self.message_span, &self.value); verify_message_formatting(self.attr_span, self.message_span, &self.value); } } -fn verify_variables_used(msg_span: Span, message_str: &str, variant: Option<&VariantInfo<'_>>) { - // Parse the fluent message - const GENERATED_MSG_ID: &str = "generated_msg"; - let resource = - FluentResource::try_new(format!("{GENERATED_MSG_ID} = {message_str}\n")).unwrap(); - assert_eq!(resource.entries().count(), 1); - let Some(fluent_syntax::ast::Entry::Message(message)) = resource.get_entry(0) else { - panic!("Did not parse into a message") - }; - - // Check if all variables are used - if let Some(variant) = variant { - let fields: Vec = variant - .bindings() - .iter() - .flat_map(|b| b.ast().ident.as_ref()) - .map(|id| id.unraw().to_string()) - .collect(); - for variable in variable_references(&message) { - if !fields.iter().any(|f| f == variable) { - span_err( - msg_span.unwrap(), - format!("Variable `{variable}` not found in diagnostic "), - ) - .help(format!("Available fields: {:?}", fields.join(", "))) - .emit(); - } - } - } -} - fn variable_references<'a>(msg: &fluent_syntax::ast::Message<&'a str>) -> Vec<&'a str> { let mut refs = vec![]; diff --git a/compiler/rustc_macros/src/diagnostics/msg_macro.rs b/compiler/rustc_macros/src/diagnostics/msg_macro.rs index 66bc200707efa..831a94432c29a 100644 --- a/compiler/rustc_macros/src/diagnostics/msg_macro.rs +++ b/compiler/rustc_macros/src/diagnostics/msg_macro.rs @@ -6,5 +6,5 @@ pub(crate) fn msg_macro(input: proc_macro::TokenStream) -> proc_macro::TokenStre let inline = parse_macro_input!(input as LitStr); let message = Message { attr_span: inline.span(), message_span: inline.span(), value: inline.value() }; - message.diag_message(None).into() + message.diag_message().into() } diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 3e094ee8d42b6..f9ef016a16af6 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -1,5 +1,7 @@ #![deny(unused_must_use)] +use std::collections::HashSet; + use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; use syn::parse::ParseStream; @@ -61,6 +63,8 @@ impl SubdiagnosticDerive { } } + let mut used_fields: HashSet = HashSet::new(); + structure.bind_with(|_| synstructure::BindStyle::Move); let variants_ = structure.each_variant(|variant| { let mut builder = SubdiagnosticDeriveVariantBuilder { @@ -74,6 +78,7 @@ impl SubdiagnosticDerive { has_suggestion_parts: false, has_subdiagnostic: false, is_enum, + used_fields: &mut used_fields, }; builder.into_tokens().unwrap_or_else(|v| v.to_compile_error()) }); @@ -142,6 +147,8 @@ struct SubdiagnosticDeriveVariantBuilder<'parent, 'a> { /// Set to true when this variant is an enum variant rather than just the body of a struct. is_enum: bool, + + used_fields: &'parent mut HashSet, } /// Provides frequently-needed information about the diagnostic kinds being derived for this type. @@ -190,7 +197,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { for attr in self.variant.ast().attrs { let Some(SubdiagnosticVariant { kind, message }) = - SubdiagnosticVariant::from_attr(attr, &self.fields)? + SubdiagnosticVariant::from_attr(attr, &self.fields, &mut self.used_fields)? else { // Some attributes aren't errors - like documentation comments - but also aren't // subdiagnostics. @@ -301,7 +308,6 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let name = name.as_str(); match name { - "skip_arg" => Ok(quote! {}), "primary_span" => { if kind_stats.has_multipart_suggestion { invalid_attr(attr) @@ -391,7 +397,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { invalid_attr(attr) .help(format!( - "only `{}`, `applicability` and `skip_arg` are valid field attributes", + "only `{}`, `applicability` is a valid field attribute", span_attrs.join(", ") )) .emit(); @@ -490,13 +496,17 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { span_attrs.push("primary_span") } diag.help(format!( - "only `{}`, `applicability` and `skip_arg` are valid field attributes", + "only `{}`, `applicability` is a valid field attribute", span_attrs.join(", ") )) }), } } + fn is_used_in_message(&self, binding: &BindingInfo<'_>) -> bool { + binding.ast().ident.as_ref().is_some_and(|ident| self.used_fields.contains(ident)) + } + pub(crate) fn into_tokens(&mut self) -> Result { let kind_messages = self.identify_kind()?; @@ -533,8 +543,13 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { .variant .bindings() .iter() - .filter(|binding| should_generate_arg(binding.ast())) - .map(|binding| self.generate_field_arg(binding)) + .filter_map(|binding| { + if should_generate_arg(binding.ast()) && self.is_used_in_message(binding) { + Some(self.generate_field_arg(binding)) + } else { + None + } + }) .collect(); let plain_args = quote! { let mut sub_args = rustc_errors::DiagArgMap::default(); @@ -546,7 +561,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let mut calls = TokenStream::new(); for (kind, messages) in kind_messages { let message = format_ident!("__message"); - let message_stream = messages.diag_message(Some(self.variant)); + let message_stream = messages.diag_message(); calls.extend(quote! { let #message = rustc_errors::format_diag_message(&#message_stream, &sub_args); }); let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind); diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 55a8445744cba..b65e39469ec51 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -1,5 +1,5 @@ use std::cell::RefCell; -use std::collections::{BTreeSet, HashMap}; +use std::collections::{BTreeSet, HashMap, HashSet}; use std::fmt; use std::str::FromStr; @@ -260,7 +260,7 @@ impl SetOnce for SpannedOption { } } -pub(super) type FieldMap = HashMap; +pub(super) type FieldMap = HashMap; /// In the strings in the attributes supplied to this macro, we want callers to be able to /// reference fields in the format string. For example: @@ -344,7 +344,7 @@ pub(super) fn build_format( let args = referenced_fields.into_iter().map(|field: String| { let field_ident = format_ident!("{}", field); let value = match field_map.get(&field) { - Some(value) => value.clone(), + Some(value) => value.1.clone(), // This field doesn't exist. Emit a diagnostic. None => { span_err(span.unwrap(), format!("`{field}` doesn't refer to a field on this type")) @@ -408,11 +408,11 @@ impl quote::ToTokens for Applicability { /// Build the mapping of field names to fields. This allows attributes to peek values from /// other fields. -pub(super) fn build_field_mapping(variant: &VariantInfo<'_>) -> HashMap { +pub(super) fn build_field_mapping(variant: &VariantInfo<'_>) -> FieldMap { let mut fields_map = FieldMap::new(); for binding in variant.bindings() { if let Some(ident) = &binding.ast().ident { - fields_map.insert(ident.to_string(), quote! { #binding }); + fields_map.insert(ident.to_string(), (ident.clone(), quote! { #binding })); } } fields_map @@ -598,6 +598,7 @@ impl SubdiagnosticVariant { pub(super) fn from_attr( attr: &Attribute, fields: &FieldMap, + used_fields: &mut HashSet, ) -> Result, DiagnosticDeriveError> { // Always allow documentation comments. if is_doc_comment(attr) { @@ -708,7 +709,13 @@ impl SubdiagnosticVariant { } if !input.is_empty() { input.parse::()?; } if is_first { - message = Some(Message { attr_span: attr.span(), message_span: inline_message.span(), value: inline_message.value() }); + message = Some(Message::new( + attr.span(), + inline_message.span(), + inline_message.value(), + fields, + used_fields, + )); is_first = false; } else { span_err(inline_message.span().unwrap(), "a diagnostic message must be the first argument to the attribute").emit(); diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 32a5d6a1c6cf2..8624e0524b04e 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -181,7 +181,6 @@ decl_derive!( note_once, warning, // field attributes - skip_arg, primary_span, label, subdiagnostic, @@ -208,7 +207,6 @@ decl_derive!( multipart_suggestion_short, multipart_suggestion_hidden, // field attributes - skip_arg, primary_span, suggestion_part, applicability)] => diagnostics::subdiagnostic_derive diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index c55275962e085..b4dac5b244f10 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -724,9 +724,25 @@ pub(crate) struct NonConstPath { pub(crate) span: Span, } +pub(crate) struct UnreachablePattern<'tcx> { + pub(crate) covered_by_many_n_more_count: Option, + pub(crate) inner: UnreachablePatternInner<'tcx>, +} + +impl<'a, 'tcx, G: EmissionGuarantee> Diagnostic<'a, G> for UnreachablePattern<'tcx> { + #[track_caller] + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { + let mut diag = self.inner.into_diag(dcx, level); + if let Some(covered_by_many_n_more_count) = self.covered_by_many_n_more_count { + diag.arg("covered_by_many_n_more_count", covered_by_many_n_more_count); + } + diag + } +} + #[derive(Diagnostic)] #[diag("unreachable pattern")] -pub(crate) struct UnreachablePattern<'tcx> { +pub(crate) struct UnreachablePatternInner<'tcx> { #[label("no value can reach this")] pub(crate) span: Option, #[label("matches no values because `{$matches_no_values_ty}` is uninhabited")] @@ -756,7 +772,6 @@ pub(crate) struct UnreachablePattern<'tcx> { pub(crate) covered_by_one: Option, #[note("multiple earlier patterns match some of the same values")] pub(crate) covered_by_many: Option, - pub(crate) covered_by_many_n_more_count: usize, #[suggestion("remove the match arm", code = "", applicability = "machine-applicable")] pub(crate) suggest_remove: Option, } 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 afd8447b17ede..b4c340cfee2c0 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -953,7 +953,7 @@ fn report_unreachable_pattern<'p, 'tcx>( ) { static CAP_COVERED_BY_MANY: usize = 4; let pat_span = pat.data().span; - let mut lint = UnreachablePattern { + let mut lint = UnreachablePatternInner { span: Some(pat_span), matches_no_values: None, matches_no_values_ty: **pat.ty(), @@ -961,13 +961,13 @@ fn report_unreachable_pattern<'p, 'tcx>( covered_by_catchall: None, covered_by_one: None, covered_by_many: None, - covered_by_many_n_more_count: 0, wanted_constant: None, accessible_constant: None, inaccessible_constant: None, pattern_let_binding: None, suggest_remove: None, }; + let mut covered_by_many_n_more_count = None; match explanation.covered_by.as_slice() { [] => { // Empty pattern; we report the uninhabited type that caused the emptiness. @@ -1006,7 +1006,7 @@ fn report_unreachable_pattern<'p, 'tcx>( if remain == 0 { multispan.push_span_label(pat_span, msg!("collectively making this unreachable")); } else { - lint.covered_by_many_n_more_count = remain; + covered_by_many_n_more_count = Some(remain); multispan.push_span_label( pat_span, msg!("...and {$covered_by_many_n_more_count} other patterns collectively make this unreachable"), @@ -1015,7 +1015,12 @@ fn report_unreachable_pattern<'p, 'tcx>( lint.covered_by_many = Some(multispan); } } - cx.tcx.emit_node_span_lint(UNREACHABLE_PATTERNS, hir_id, pat_span, lint); + cx.tcx.emit_node_span_lint( + UNREACHABLE_PATTERNS, + hir_id, + pat_span, + UnreachablePattern { inner: lint, covered_by_many_n_more_count }, + ); } /// Detect typos that were meant to be a `const` but were interpreted as a new pattern binding. @@ -1023,7 +1028,7 @@ fn find_fallback_pattern_typo<'tcx>( cx: &PatCtxt<'_, 'tcx>, hir_id: HirId, pat: &Pat<'tcx>, - lint: &mut UnreachablePattern<'_>, + lint: &mut UnreachablePatternInner<'_>, ) { if cx.tcx.lint_level_spec_at_node(UNREACHABLE_PATTERNS, hir_id).is_allow() { // This is because we use `with_no_trimmed_paths` later, so if we never emit the lint we'd diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 2d9e0a857bf5e..901f96a974dc2 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -3461,10 +3461,6 @@ pub(crate) struct UnexpectedExpressionInPattern { pub span: Span, /// Was a `RangePatternBound` expected? pub is_bound: bool, - /// The unexpected expr's precedence. Not used directly in the error message, but needed for - /// the stashing of this error to work correctly. We store a `u32` rather than an - /// `ExprPrecedence` to avoid having to impl `IntoDiagArg` for `ExprPrecedence`. - pub expr_precedence: u32, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index b8718b503df26..b66dcddc8d333 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -497,18 +497,14 @@ impl<'a> Parser<'a> { && self.look_ahead(1, Token::is_range_separator); let span = expr.span; - - Some(( - self.dcx() - .create_err(UnexpectedExpressionInPattern { - span, - is_bound, - expr_precedence: expr.precedence() as u32, - }) - .stash(span, StashKey::ExprInPat) - .unwrap(), - span, - )) + let mut diag = self.dcx().create_err(UnexpectedExpressionInPattern { span, is_bound }); + // The unexpected expr's precedence. Not used directly in the error message, but + // needed for the stashing of this error to work correctly. We store a `u32` rather + // than an `ExprPrecedence` to avoid having to impl `IntoDiagArg` for + // `ExprPrecedence`. + diag.arg("expr_precedence", expr.precedence() as u32); + + Some((diag.stash(span, StashKey::ExprInPat).unwrap(), span)) } /// Called by [`Parser::parse_stmt_without_recovery`], used to add statement-aware subdiagnostics to the errors stashed diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs index c1146de0fef1f..72b54ed472756 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs @@ -26,7 +26,7 @@ use rustc_span::Span; struct NotIntoDiagArg; #[derive(Diagnostic)] -#[diag("example message")] +#[diag("example message {$arg}")] struct Test { #[primary_span] span: Span, @@ -36,7 +36,7 @@ struct Test { } #[derive(Subdiagnostic)] -#[label("example message")] +#[label("example message {$arg}")] struct SubTest { #[primary_span] span: Span, diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs index 26d92126fe87a..0956556bf5ef2 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs @@ -327,7 +327,6 @@ struct ArgFieldWithoutSkip { #[primary_span] span: Span, other: Hello, - //~^ ERROR the trait bound `Hello: IntoDiagArg` is not satisfied } #[derive(Diagnostic)] @@ -335,9 +334,8 @@ struct ArgFieldWithoutSkip { struct ArgFieldWithSkip { #[primary_span] span: Span, - // `Hello` does not implement `IntoDiagArg` so this would result in an error if - // not for `#[skip_arg]`. - #[skip_arg] + // `Hello` does not implement `IntoDiagArg` so this would result if `Diagnostic` + // doesn't skip it correctly. other: Hello, } diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr index 28800016cea9b..486ae9c28e84b 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr @@ -253,61 +253,61 @@ LL | #[label = "bar"] | ^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive-inline.rs:389:5 + --> $DIR/diagnostic-derive-inline.rs:387:5 | LL | #[suggestion("with a suggestion", code = "...", applicability = "maybe-incorrect")] | ^ | note: previously specified here - --> $DIR/diagnostic-derive-inline.rs:391:24 + --> $DIR/diagnostic-derive-inline.rs:389:24 | LL | suggestion: (Span, Applicability), | ^^^^^^^^^^^^^ error: derive(Diagnostic): invalid applicability - --> $DIR/diagnostic-derive-inline.rs:397:69 + --> $DIR/diagnostic-derive-inline.rs:395:69 | LL | #[suggestion("with a suggestion", code = "...", applicability = "batman")] | ^^^^^^^^ error: derive(Diagnostic): the `#[help(...)]` attribute can only be applied to fields of type `Span`, `MultiSpan`, `bool` or `()` - --> $DIR/diagnostic-derive-inline.rs:460:5 + --> $DIR/diagnostic-derive-inline.rs:458:5 | LL | #[help("with a help")] | ^ error: derive(Diagnostic): no nested attribute expected here - --> $DIR/diagnostic-derive-inline.rs:469:29 + --> $DIR/diagnostic-derive-inline.rs:467:29 | LL | #[label("with a label", foo)] | ^^^ error: derive(Diagnostic): a diagnostic message must be the first argument to the attribute - --> $DIR/diagnostic-derive-inline.rs:477:29 + --> $DIR/diagnostic-derive-inline.rs:475:29 | LL | #[label("with a label", "and another one?")] | ^^^^^^^^^^^^^^^^^^ error: derive(Diagnostic): no nested attribute expected here - --> $DIR/diagnostic-derive-inline.rs:485:29 + --> $DIR/diagnostic-derive-inline.rs:483:29 | LL | #[label("with a label", foo = "...")] | ^^^ error: derive(Diagnostic): no nested attribute expected here - --> $DIR/diagnostic-derive-inline.rs:493:29 + --> $DIR/diagnostic-derive-inline.rs:491:29 | LL | #[label("with a label", foo("..."))] | ^^^ error: derive(Diagnostic): `#[error(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:513:1 + --> $DIR/diagnostic-derive-inline.rs:511:1 | LL | #[error("this is an example message", code = E0123)] | ^ error: derive(Diagnostic): diagnostic message not specified - --> $DIR/diagnostic-derive-inline.rs:513:1 + --> $DIR/diagnostic-derive-inline.rs:511:1 | LL | #[error("this is an example message", code = E0123)] | ^ @@ -315,13 +315,13 @@ LL | #[error("this is an example message", code = E0123)] = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` error: derive(Diagnostic): `#[warn_(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:520:1 + --> $DIR/diagnostic-derive-inline.rs:518:1 | LL | #[warn_("this is an example message", code = E0123)] | ^ error: derive(Diagnostic): diagnostic message not specified - --> $DIR/diagnostic-derive-inline.rs:520:1 + --> $DIR/diagnostic-derive-inline.rs:518:1 | LL | #[warn_("this is an example message", code = E0123)] | ^ @@ -329,13 +329,13 @@ LL | #[warn_("this is an example message", code = E0123)] = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` error: derive(Diagnostic): `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:527:1 + --> $DIR/diagnostic-derive-inline.rs:525:1 | LL | #[lint("this is an example message", code = E0123)] | ^ error: derive(Diagnostic): diagnostic message not specified - --> $DIR/diagnostic-derive-inline.rs:527:1 + --> $DIR/diagnostic-derive-inline.rs:525:1 | LL | #[lint("this is an example message", code = E0123)] | ^ @@ -343,19 +343,19 @@ LL | #[lint("this is an example message", code = E0123)] = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive-inline.rs:536:53 + --> $DIR/diagnostic-derive-inline.rs:534:53 | LL | #[suggestion("with a suggestion", code = "...", code = ",,,")] | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive-inline.rs:536:39 + --> $DIR/diagnostic-derive-inline.rs:534:39 | LL | #[suggestion("with a suggestion", code = "...", code = ",,,")] | ^^^^ error: derive(Diagnostic): wrong types for suggestion - --> $DIR/diagnostic-derive-inline.rs:545:24 + --> $DIR/diagnostic-derive-inline.rs:543:24 | LL | suggestion: (Span, usize), | ^^^^^ @@ -363,7 +363,7 @@ LL | suggestion: (Span, usize), = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` error: derive(Diagnostic): wrong types for suggestion - --> $DIR/diagnostic-derive-inline.rs:553:17 + --> $DIR/diagnostic-derive-inline.rs:551:17 | LL | suggestion: (Span,), | ^^^^^^^ @@ -371,13 +371,13 @@ LL | suggestion: (Span,), = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` error: derive(Diagnostic): suggestion without `code = "..."` - --> $DIR/diagnostic-derive-inline.rs:560:5 + --> $DIR/diagnostic-derive-inline.rs:558:5 | LL | #[suggestion("with a suggestion")] | ^ error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:567:1 + --> $DIR/diagnostic-derive-inline.rs:565:1 | LL | #[multipart_suggestion("with a suggestion")] | ^ @@ -385,7 +385,7 @@ LL | #[multipart_suggestion("with a suggestion")] = help: consider creating a `Subdiagnostic` instead error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:570:1 + --> $DIR/diagnostic-derive-inline.rs:568:1 | LL | #[multipart_suggestion()] | ^ @@ -393,7 +393,7 @@ LL | #[multipart_suggestion()] = help: consider creating a `Subdiagnostic` instead error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:574:5 + --> $DIR/diagnostic-derive-inline.rs:572:5 | LL | #[multipart_suggestion("with a suggestion")] | ^ @@ -401,7 +401,7 @@ LL | #[multipart_suggestion("with a suggestion")] = help: consider creating a `Subdiagnostic` instead error: derive(Diagnostic): `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:582:1 + --> $DIR/diagnostic-derive-inline.rs:580:1 | LL | #[suggestion("with a suggestion", code = "...")] | ^ @@ -409,7 +409,7 @@ LL | #[suggestion("with a suggestion", code = "...")] = help: `#[label]` and `#[suggestion]` can only be applied to fields error: derive(Diagnostic): `#[label]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:591:1 + --> $DIR/diagnostic-derive-inline.rs:589:1 | LL | #[label] | ^ @@ -417,67 +417,67 @@ LL | #[label] = help: subdiagnostic message is missing error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:625:5 + --> $DIR/diagnostic-derive-inline.rs:623:5 | LL | #[subdiagnostic(bad)] | ^ error: derive(Diagnostic): `#[subdiagnostic = ...]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:633:5 + --> $DIR/diagnostic-derive-inline.rs:631:5 | LL | #[subdiagnostic = "bad"] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:641:5 + --> $DIR/diagnostic-derive-inline.rs:639:5 | LL | #[subdiagnostic(bad, bad)] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:649:5 + --> $DIR/diagnostic-derive-inline.rs:647:5 | LL | #[subdiagnostic("bad")] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:657:5 + --> $DIR/diagnostic-derive-inline.rs:655:5 | LL | #[subdiagnostic(eager)] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:678:5 + --> $DIR/diagnostic-derive-inline.rs:676:5 | LL | #[subdiagnostic(eager)] | ^ error: derive(Diagnostic): expected at least one string literal for `code(...)` - --> $DIR/diagnostic-derive-inline.rs:709:44 + --> $DIR/diagnostic-derive-inline.rs:707:44 | LL | #[suggestion("with a suggestion", code())] | ^ error: derive(Diagnostic): `code(...)` must contain only string literals - --> $DIR/diagnostic-derive-inline.rs:717:44 + --> $DIR/diagnostic-derive-inline.rs:715:44 | LL | #[suggestion("with a suggestion", code(foo))] | ^^^ error: unexpected token, expected `)` - --> $DIR/diagnostic-derive-inline.rs:717:44 + --> $DIR/diagnostic-derive-inline.rs:715:44 | LL | #[suggestion("with a suggestion", code(foo))] | ^^^ error: expected string literal - --> $DIR/diagnostic-derive-inline.rs:726:46 + --> $DIR/diagnostic-derive-inline.rs:724:46 | LL | #[suggestion("with a suggestion", code = 3)] | ^ error: derive(Diagnostic): `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:741:5 + --> $DIR/diagnostic-derive-inline.rs:739:5 | LL | #[suggestion("with a suggestion", code = "")] | ^ @@ -487,7 +487,7 @@ LL | #[suggestion("with a suggestion", code = "")] = help: to show a variable set of suggestions, use a `Vec` of `Subdiagnostic`s annotated with `#[suggestion(...)]` error: derive(Diagnostic): Variable `nosub` not found in diagnostic - --> $DIR/diagnostic-derive-inline.rs:753:8 + --> $DIR/diagnostic-derive-inline.rs:751:8 | LL | #[diag("does not exist: {$nosub}")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -507,7 +507,7 @@ LL | #[nonsense] | ^^^^^^^^ error: cannot find attribute `error` in this scope - --> $DIR/diagnostic-derive-inline.rs:513:3 + --> $DIR/diagnostic-derive-inline.rs:511:3 | LL | #[error("this is an example message", code = E0123)] | ^^^^^ @@ -519,7 +519,7 @@ LL | struct ErrorAttribute {} | error: cannot find attribute `warn_` in this scope - --> $DIR/diagnostic-derive-inline.rs:520:3 + --> $DIR/diagnostic-derive-inline.rs:518:3 | LL | #[warn_("this is an example message", code = E0123)] | ^^^^^ @@ -531,7 +531,7 @@ LL + #[warn("this is an example message", code = E0123)] | error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive-inline.rs:527:3 + --> $DIR/diagnostic-derive-inline.rs:525:3 | LL | #[lint("this is an example message", code = E0123)] | ^^^^ @@ -543,7 +543,7 @@ LL + #[link("this is an example message", code = E0123)] | error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive-inline.rs:567:3 + --> $DIR/diagnostic-derive-inline.rs:565:3 | LL | #[multipart_suggestion("with a suggestion")] | ^^^^^^^^^^^^^^^^^^^^ @@ -555,7 +555,7 @@ LL | struct MultipartSuggestion { | error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive-inline.rs:570:3 + --> $DIR/diagnostic-derive-inline.rs:568:3 | LL | #[multipart_suggestion()] | ^^^^^^^^^^^^^^^^^^^^ @@ -567,36 +567,12 @@ LL | struct MultipartSuggestion { | error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive-inline.rs:574:7 + --> $DIR/diagnostic-derive-inline.rs:572:7 | LL | #[multipart_suggestion("with a suggestion")] | ^^^^^^^^^^^^^^^^^^^^ | = note: `multipart_suggestion` is an attribute that can be used by the derive macro `Subdiagnostic`, you might be missing a `derive` attribute -error[E0277]: the trait bound `Hello: IntoDiagArg` is not satisfied - --> $DIR/diagnostic-derive-inline.rs:329:12 - | -LL | #[derive(Diagnostic)] - | ---------- required by a bound introduced by this call -... -LL | other: Hello, - | ^^^^^ unsatisfied trait bound - | -help: the nightly-only, unstable trait `IntoDiagArg` is not implemented for `Hello` - --> $DIR/diagnostic-derive-inline.rs:41:1 - | -LL | struct Hello {} - | ^^^^^^^^^^^^ - = help: normalized in stderr - = note: there's an inherent method on `DiagInner` of the same name, which can be auto-dereferenced from `&mut DiagInner` -note: required by a bound in `Diag::<'a, G>::arg` - --> $COMPILER_DIR/rustc_errors/src/diagnostic.rs:LL:CC - ::: $COMPILER_DIR/rustc_errors/src/diagnostic.rs:LL:CC - | - = note: in this macro invocation - = note: this error originates in the macro `with_fn` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 76 previous errors +error: aborting due to 75 previous errors -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.rs index 2aed4fa9465c4..1bec8ac03c981 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.rs +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.rs @@ -290,7 +290,6 @@ struct AA { struct AB { #[primary_span] span: Span, - #[skip_arg] z: Z, } diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.stderr b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.stderr index 8e634bf78797f..cf3c9dd9ce10d 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.stderr +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.stderr @@ -142,7 +142,7 @@ error: derive(Diagnostic): `#[bar]` is not a valid attribute LL | #[bar] | ^ | - = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes + = help: only `primary_span`, `applicability` is a valid field attribute error: derive(Diagnostic): `#[bar = ...]` is not a valid attribute --> $DIR/subdiagnostic-derive-inline.rs:271:5 @@ -156,10 +156,10 @@ error: derive(Diagnostic): `#[bar(...)]` is not a valid attribute LL | #[bar("...")] | ^ | - = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes + = help: only `primary_span`, `applicability` is a valid field attribute error: unexpected unsupported untagged union - --> $DIR/subdiagnostic-derive-inline.rs:298:1 + --> $DIR/subdiagnostic-derive-inline.rs:297:1 | LL | / union AC { LL | | @@ -169,97 +169,97 @@ LL | | } | |_^ error: expected this path to be an identifier - --> $DIR/subdiagnostic-derive-inline.rs:313:28 + --> $DIR/subdiagnostic-derive-inline.rs:312:28 | LL | #[label("example message", no_crate::example)] | ^^^^^^^^^^^^^^^^^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/subdiagnostic-derive-inline.rs:326:5 + --> $DIR/subdiagnostic-derive-inline.rs:325:5 | LL | #[primary_span] | ^ | note: previously specified here - --> $DIR/subdiagnostic-derive-inline.rs:323:5 + --> $DIR/subdiagnostic-derive-inline.rs:322:5 | LL | #[primary_span] | ^ error: derive(Diagnostic): subdiagnostic kind not specified - --> $DIR/subdiagnostic-derive-inline.rs:332:8 + --> $DIR/subdiagnostic-derive-inline.rs:331:8 | LL | struct AG { | ^^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/subdiagnostic-derive-inline.rs:369:47 + --> $DIR/subdiagnostic-derive-inline.rs:368:47 | LL | #[suggestion("example message", code = "...", code = "...")] | ^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive-inline.rs:369:33 + --> $DIR/subdiagnostic-derive-inline.rs:368:33 | LL | #[suggestion("example message", code = "...", code = "...")] | ^^^^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/subdiagnostic-derive-inline.rs:387:5 + --> $DIR/subdiagnostic-derive-inline.rs:386:5 | LL | #[applicability] | ^ | note: previously specified here - --> $DIR/subdiagnostic-derive-inline.rs:384:5 + --> $DIR/subdiagnostic-derive-inline.rs:383:5 | LL | #[applicability] | ^ error: derive(Diagnostic): the `#[applicability]` attribute can only be applied to fields of type `Applicability` - --> $DIR/subdiagnostic-derive-inline.rs:397:5 + --> $DIR/subdiagnostic-derive-inline.rs:396:5 | LL | #[applicability] | ^ error: derive(Diagnostic): suggestion without `code = "..."` - --> $DIR/subdiagnostic-derive-inline.rs:410:1 + --> $DIR/subdiagnostic-derive-inline.rs:409:1 | LL | #[suggestion("example message")] | ^ error: derive(Diagnostic): invalid applicability - --> $DIR/subdiagnostic-derive-inline.rs:420:63 + --> $DIR/subdiagnostic-derive-inline.rs:419:63 | LL | #[suggestion("example message", code = "...", applicability = "foo")] | ^^^^^ error: derive(Diagnostic): suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive-inline.rs:438:1 + --> $DIR/subdiagnostic-derive-inline.rs:437:1 | LL | #[suggestion("example message", code = "...")] | ^ error: derive(Diagnostic): unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive-inline.rs:452:1 + --> $DIR/subdiagnostic-derive-inline.rs:451:1 | LL | #[label] | ^ error: derive(Diagnostic): `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive-inline.rs:472:40 + --> $DIR/subdiagnostic-derive-inline.rs:471:40 | LL | #[suggestion("example message", code = "{var}", applicability = "machine-applicable")] | ^^^^^^^ error: derive(Diagnostic): `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive-inline.rs:491:44 + --> $DIR/subdiagnostic-derive-inline.rs:490:44 | LL | #[suggestion("example message", code = "{var}", applicability = "machine-applicable")] | ^^^^^^^ error: derive(Diagnostic): `#[suggestion_part]` is not a valid attribute - --> $DIR/subdiagnostic-derive-inline.rs:514:5 + --> $DIR/subdiagnostic-derive-inline.rs:513:5 | LL | #[suggestion_part] | ^ @@ -267,7 +267,7 @@ LL | #[suggestion_part] = help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead error: derive(Diagnostic): `#[suggestion_part(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive-inline.rs:517:5 + --> $DIR/subdiagnostic-derive-inline.rs:516:5 | LL | #[suggestion_part(code = "...")] | ^ @@ -275,13 +275,13 @@ LL | #[suggestion_part(code = "...")] = help: `#[suggestion_part(...)]` is only valid in multipart suggestions error: derive(Diagnostic): suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive-inline.rs:511:1 + --> $DIR/subdiagnostic-derive-inline.rs:510:1 | LL | #[suggestion("example message", code = "...")] | ^ error: derive(Diagnostic): invalid nested attribute - --> $DIR/subdiagnostic-derive-inline.rs:526:43 + --> $DIR/subdiagnostic-derive-inline.rs:525:43 | LL | #[multipart_suggestion("example message", code = "...", applicability = "machine-applicable")] | ^^^^ @@ -289,25 +289,25 @@ LL | #[multipart_suggestion("example message", code = "...", applicability = "ma = help: only `style` and `applicability` are valid nested attributes error: derive(Diagnostic): multipart suggestion without any `#[suggestion_part(...)]` fields - --> $DIR/subdiagnostic-derive-inline.rs:526:1 + --> $DIR/subdiagnostic-derive-inline.rs:525:1 | LL | #[multipart_suggestion("example message", code = "...", applicability = "machine-applicable")] | ^ error: derive(Diagnostic): `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive-inline.rs:536:5 + --> $DIR/subdiagnostic-derive-inline.rs:535:5 | LL | #[suggestion_part] | ^ error: derive(Diagnostic): `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive-inline.rs:544:5 + --> $DIR/subdiagnostic-derive-inline.rs:543:5 | LL | #[suggestion_part()] | ^ error: derive(Diagnostic): `#[primary_span]` is not a valid attribute - --> $DIR/subdiagnostic-derive-inline.rs:553:5 + --> $DIR/subdiagnostic-derive-inline.rs:552:5 | LL | #[primary_span] | ^ @@ -315,127 +315,127 @@ LL | #[primary_span] = help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]` error: derive(Diagnostic): multipart suggestion without any `#[suggestion_part(...)]` fields - --> $DIR/subdiagnostic-derive-inline.rs:550:1 + --> $DIR/subdiagnostic-derive-inline.rs:549:1 | LL | #[multipart_suggestion("example message")] | ^ error: derive(Diagnostic): `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive-inline.rs:561:5 + --> $DIR/subdiagnostic-derive-inline.rs:560:5 | LL | #[suggestion_part] | ^ error: derive(Diagnostic): `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive-inline.rs:564:5 + --> $DIR/subdiagnostic-derive-inline.rs:563:5 | LL | #[suggestion_part()] | ^ error: derive(Diagnostic): `code` is the only valid nested attribute - --> $DIR/subdiagnostic-derive-inline.rs:567:23 + --> $DIR/subdiagnostic-derive-inline.rs:566:23 | LL | #[suggestion_part(foo = "bar")] | ^^^ error: derive(Diagnostic): the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive-inline.rs:571:5 + --> $DIR/subdiagnostic-derive-inline.rs:570:5 | LL | #[suggestion_part(code = "...")] | ^ error: derive(Diagnostic): the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive-inline.rs:574:5 + --> $DIR/subdiagnostic-derive-inline.rs:573:5 | LL | #[suggestion_part()] | ^ error: expected `,` - --> $DIR/subdiagnostic-derive-inline.rs:567:27 + --> $DIR/subdiagnostic-derive-inline.rs:566:27 | LL | #[suggestion_part(foo = "bar")] | ^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/subdiagnostic-derive-inline.rs:582:37 + --> $DIR/subdiagnostic-derive-inline.rs:581:37 | LL | #[suggestion_part(code = "...", code = ",,,")] | ^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive-inline.rs:582:23 + --> $DIR/subdiagnostic-derive-inline.rs:581:23 | LL | #[suggestion_part(code = "...", code = ",,,")] | ^^^^ error: derive(Diagnostic): `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."` - --> $DIR/subdiagnostic-derive-inline.rs:611:5 + --> $DIR/subdiagnostic-derive-inline.rs:610:5 | LL | #[applicability] | ^ error: derive(Diagnostic): expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive-inline.rs:659:28 + --> $DIR/subdiagnostic-derive-inline.rs:658:28 | LL | #[suggestion_part(code("foo"))] | ^^^^^ error: unexpected token, expected `)` - --> $DIR/subdiagnostic-derive-inline.rs:659:28 + --> $DIR/subdiagnostic-derive-inline.rs:658:28 | LL | #[suggestion_part(code("foo"))] | ^^^^^ error: derive(Diagnostic): expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive-inline.rs:669:28 + --> $DIR/subdiagnostic-derive-inline.rs:668:28 | LL | #[suggestion_part(code("foo", "bar"))] | ^^^^^ error: unexpected token, expected `)` - --> $DIR/subdiagnostic-derive-inline.rs:669:28 + --> $DIR/subdiagnostic-derive-inline.rs:668:28 | LL | #[suggestion_part(code("foo", "bar"))] | ^^^^^ error: derive(Diagnostic): expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive-inline.rs:679:28 + --> $DIR/subdiagnostic-derive-inline.rs:678:28 | LL | #[suggestion_part(code(3))] | ^ error: unexpected token, expected `)` - --> $DIR/subdiagnostic-derive-inline.rs:679:28 + --> $DIR/subdiagnostic-derive-inline.rs:678:28 | LL | #[suggestion_part(code(3))] | ^ error: derive(Diagnostic): expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive-inline.rs:689:28 + --> $DIR/subdiagnostic-derive-inline.rs:688:28 | LL | #[suggestion_part(code())] | ^ error: expected string literal - --> $DIR/subdiagnostic-derive-inline.rs:698:30 + --> $DIR/subdiagnostic-derive-inline.rs:697:30 | LL | #[suggestion_part(code = 3)] | ^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/subdiagnostic-derive-inline.rs:740:1 + --> $DIR/subdiagnostic-derive-inline.rs:739:1 | LL | #[suggestion("example message", code = "", style = "hidden", style = "normal")] | ^ | note: previously specified here - --> $DIR/subdiagnostic-derive-inline.rs:740:1 + --> $DIR/subdiagnostic-derive-inline.rs:739:1 | LL | #[suggestion("example message", code = "", style = "hidden", style = "normal")] | ^ error: derive(Diagnostic): `#[suggestion_hidden(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive-inline.rs:749:1 + --> $DIR/subdiagnostic-derive-inline.rs:748:1 | LL | #[suggestion_hidden("example message", code = "")] | ^ @@ -443,7 +443,7 @@ LL | #[suggestion_hidden("example message", code = "")] = help: Use `#[suggestion(..., style = "hidden")]` instead error: derive(Diagnostic): `#[suggestion_hidden(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive-inline.rs:757:1 + --> $DIR/subdiagnostic-derive-inline.rs:756:1 | LL | #[suggestion_hidden("example message", code = "", style = "normal")] | ^ @@ -451,7 +451,7 @@ LL | #[suggestion_hidden("example message", code = "", style = "normal")] = help: Use `#[suggestion(..., style = "hidden")]` instead error: derive(Diagnostic): invalid suggestion style - --> $DIR/subdiagnostic-derive-inline.rs:765:52 + --> $DIR/subdiagnostic-derive-inline.rs:764:52 | LL | #[suggestion("example message", code = "", style = "foo")] | ^^^^^ @@ -459,25 +459,25 @@ LL | #[suggestion("example message", code = "", style = "foo")] = help: valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only` error: expected string literal - --> $DIR/subdiagnostic-derive-inline.rs:773:52 + --> $DIR/subdiagnostic-derive-inline.rs:772:52 | LL | #[suggestion("example message", code = "", style = 42)] | ^^ error: expected `=` - --> $DIR/subdiagnostic-derive-inline.rs:781:49 + --> $DIR/subdiagnostic-derive-inline.rs:780:49 | LL | #[suggestion("example message", code = "", style)] | ^ error: expected `=` - --> $DIR/subdiagnostic-derive-inline.rs:789:49 + --> $DIR/subdiagnostic-derive-inline.rs:788:49 | LL | #[suggestion("example message", code = "", style("foo"))] | ^ error: derive(Diagnostic): `#[primary_span]` is not a valid attribute - --> $DIR/subdiagnostic-derive-inline.rs:800:5 + --> $DIR/subdiagnostic-derive-inline.rs:799:5 | LL | #[primary_span] | ^ @@ -486,7 +486,7 @@ LL | #[primary_span] = help: to create a suggestion with multiple spans, use `#[multipart_suggestion]` instead error: derive(Diagnostic): suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive-inline.rs:797:1 + --> $DIR/subdiagnostic-derive-inline.rs:796:1 | LL | #[suggestion("example message", code = "")] | ^ From 14b45f0b8bc9a755da6848ec7123251e31d6227e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 28 May 2026 17:02:17 +0200 Subject: [PATCH 13/26] Remove `#[skip_arg]` references from rustc-dev-guide --- .../rustc-dev-guide/src/diagnostics/diagnostic-structs.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md index a3a7a11258c8a..cc3690e1ae481 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md @@ -49,7 +49,6 @@ translatable error messages are written and how they are generated. Every field of the `Diagnostic` which does not have an annotation is available in Fluent messages as a variable, like `field_name` in the example above. -Fields can be annotated `#[skip_arg]` if this is undesired. Using the `#[primary_span]` attribute on a field (that has type `Span`) indicates the primary span of the diagnostic which will have the main message of the diagnostic. @@ -172,9 +171,6 @@ tcx.dcx().emit_err(FieldAlreadyDeclared { - `#[primary_span]` (_Optional_) - _Applied to `Span` fields on `Subdiagnostic`s. - Indicates the primary span of the diagnostic. -- `#[skip_arg]` (_Optional_) - - _Applied to any field._ - - Prevents the field from being provided as a diagnostic argument. ## `#[derive(Subdiagnostic)]` It is common in the compiler to write a function that conditionally adds a @@ -225,7 +221,6 @@ A primary span is only necessary for a label or suggestion, which can not be spa Every field of the type/variant which does not have an annotation is available in Fluent messages as a variable. -Fields can be annotated `#[skip_arg]` if this is undesired. Like `Diagnostic`, `Subdiagnostic` supports `Option` and `Vec` fields. @@ -348,9 +343,6 @@ to multipart suggestions) - `#[applicability]` (_Optional_; only applicable to (simple and multipart) suggestions) - _Applied to `Applicability` fields._ - Indicates the applicability of the suggestion. -- `#[skip_arg]` (_Optional_) - - _Applied to any field._ - - Prevents the field from being provided as a diagnostic argument. [defn]: https://github.com/rust-lang/rust/blob/6201eabde85db854c1ebb57624be5ec699246b50/compiler/rustc_hir_analysis/src/errors.rs#L68-L77 [use]: https://github.com/rust-lang/rust/blob/f1112099eba41abadb6f921df7edba70affe92c5/compiler/rustc_hir_analysis/src/collect.rs#L823-L827 From 53b4acd60aaca7bff177d310257b7faec8ef2008 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 28 May 2026 17:09:02 +0200 Subject: [PATCH 14/26] Remove outdated comment --- library/proc_macro/src/bridge/client.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index 70f9da89427cc..40f4052472617 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -255,7 +255,6 @@ fn maybe_install_panic_hook(force_show_panics: bool) { /// Client-side helper for handling client panics, entering the bridge, /// deserializing input and serializing output. -// FIXME(eddyb) maybe replace `Bridge::enter` with this? fn run_client Decode<'a, 's, ()>>( config: BridgeConfig<'_>, f: impl FnOnce(A) -> crate::TokenStream, From 5c56e618df39aebbaa4a6c5c1c04f44b896d0d69 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 28 May 2026 17:45:32 +0200 Subject: [PATCH 15/26] Remove unused proc_macro table from crate metadata --- compiler/rustc_metadata/src/rmeta/encoder.rs | 1 - compiler/rustc_metadata/src/rmeta/mod.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index a0db004b7f4c4..261bf935b5a3b 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2034,7 +2034,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let def_id = id.to_def_id(); self.tables.def_kind.set_some(def_id.index, DefKind::Macro(macro_kind.into())); - self.tables.proc_macro.set_some(def_id.index, macro_kind); self.encode_attrs(id); record!(self.tables.def_keys[def_id] <- def_key); record!(self.tables.def_ident_span[def_id] <- span); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index a3645a5556bf3..6a396faf914cc 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -464,7 +464,6 @@ define_tables! { variant_data: Table>, assoc_container: Table>, macro_definition: Table>, - proc_macro: Table, deduced_param_attrs: Table>, collect_return_position_impl_trait_in_trait_tys: Table>>>>, doc_link_resolutions: Table>, From bde798a604dbe12b4913b4676eb427dfc3f2bffd Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 28 May 2026 18:54:06 +0200 Subject: [PATCH 16/26] Use platform independent encoding for integers in proc-macro RPC This makes the proc-macro RPC protocol platform independent as necessary for running proc macros and rustc on different architectures. --- library/proc_macro/src/bridge/rpc.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/library/proc_macro/src/bridge/rpc.rs b/library/proc_macro/src/bridge/rpc.rs index 2ada18205673e..8804cf8459abf 100644 --- a/library/proc_macro/src/bridge/rpc.rs +++ b/library/proc_macro/src/bridge/rpc.rs @@ -15,20 +15,30 @@ pub(super) trait Decode<'a, 's, S>: Sized { } macro_rules! rpc_encode_decode { - (le $ty:ty) => { + (le $ty:ident $size:literal) => { impl Encode for $ty { fn encode(self, w: &mut Buffer, _: &mut S) { - w.extend_from_array(&self.to_le_bytes()); + const N: usize = size_of::<$ty>(); + + // We can pad with zeros without changing the value because of + // little endian encoding. + let mut bytes = [0; $size]; + bytes[..N].copy_from_slice(&self.to_le_bytes()); + + w.extend_from_array(&bytes); } } impl Decode<'_, '_, S> for $ty { fn decode(r: &mut &[u8], _: &mut S) -> Self { const N: usize = size_of::<$ty>(); + const { + assert!(N <= $size); + } let mut bytes = [0; N]; bytes.copy_from_slice(&r[..N]); - *r = &r[N..]; + *r = &r[$size..]; Self::from_le_bytes(bytes) } @@ -108,8 +118,8 @@ impl Decode<'_, '_, S> for u8 { } } -rpc_encode_decode!(le u32); -rpc_encode_decode!(le usize); +rpc_encode_decode!(le u32 4); +rpc_encode_decode!(le usize 8); impl Encode for bool { fn encode(self, w: &mut Buffer, s: &mut S) { From d31c7316c65c3953473b75d31ca3fd9b76c65df9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 28 May 2026 21:41:24 +0200 Subject: [PATCH 17/26] Move handle counters to the server side This shrinks the proc-macro ABI a bit. Nothing on the client side needs to allocate handles. This will share the counters between proc-macros, which may cause us to run out of handles earlier, but 4 bilion handles per process is still a lot. Rust-analyzer might run out at some point, but it can recover by restarting the proc-macro-server, and it could already run out before this change anyway, --- library/proc_macro/src/bridge/client.rs | 14 ------------ library/proc_macro/src/bridge/server.rs | 29 ++++++++++--------------- 2 files changed, 12 insertions(+), 31 deletions(-) diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index 40f4052472617..3d8ad719f7176 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -2,19 +2,9 @@ use std::cell::RefCell; use std::marker::PhantomData; -use std::sync::atomic::AtomicU32; use super::*; -#[repr(C)] -pub(super) struct HandleCounters { - pub(super) token_stream: AtomicU32, - pub(super) span: AtomicU32, -} - -static COUNTERS: HandleCounters = - HandleCounters { token_stream: AtomicU32::new(1), span: AtomicU32::new(1) }; - pub(crate) struct TokenStream { handle: handle::Handle, } @@ -221,8 +211,6 @@ pub(crate) fn is_available() -> bool { /// and forcing the use of APIs that take/return `S::TokenStream`, server-side. #[repr(C)] pub struct Client { - pub(super) handle_counters: &'static HandleCounters, - pub(super) run: extern "C" fn(BridgeConfig<'_>) -> Buffer, pub(super) _marker: PhantomData O>, @@ -294,7 +282,6 @@ fn run_client Decode<'a, 's, ()>>( impl Client { pub const fn expand1(f: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy) -> Self { Client { - handle_counters: &COUNTERS, run: super::selfless_reify::reify_to_extern_c_fn_hrt_bridge(move |bridge| { run_client(bridge, |input| f(input)) }), @@ -308,7 +295,6 @@ impl Client<(crate::TokenStream, crate::TokenStream), crate::TokenStream> { f: impl Fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream + Copy, ) -> Self { Client { - handle_counters: &COUNTERS, run: super::selfless_reify::reify_to_extern_c_fn_hrt_bridge(move |bridge| { run_client(bridge, |(input, input2)| f(input, input2)) }), diff --git a/library/proc_macro/src/bridge/server.rs b/library/proc_macro/src/bridge/server.rs index 1151798fccf40..6a739da7641d1 100644 --- a/library/proc_macro/src/bridge/server.rs +++ b/library/proc_macro/src/bridge/server.rs @@ -1,6 +1,7 @@ //! Server-side traits. use std::cell::Cell; +use std::sync::atomic::AtomicU32; use std::sync::mpsc; use super::*; @@ -11,10 +12,13 @@ pub(super) struct HandleStore { } impl HandleStore { - fn new(handle_counters: &'static client::HandleCounters) -> Self { + fn new() -> Self { + static TOKEN_STREAM: AtomicU32 = AtomicU32::new(1); + static SPAN: AtomicU32 = AtomicU32::new(1); + HandleStore { - token_stream: handle::OwnedStore::new(&handle_counters.token_stream), - span: handle::InternedStore::new(&handle_counters.span), + token_stream: handle::OwnedStore::new(&TOKEN_STREAM), + span: handle::InternedStore::new(&SPAN), } } } @@ -246,13 +250,12 @@ fn run_server< O: for<'a, 's> Decode<'a, 's, HandleStore>, >( strategy: &impl ExecutionStrategy, - handle_counters: &'static client::HandleCounters, server: S, input: I, run_client: extern "C" fn(BridgeConfig<'_>) -> Buffer, force_show_panics: bool, ) -> Result { - let mut dispatcher = Dispatcher { handle_store: HandleStore::new(handle_counters), server }; + let mut dispatcher = Dispatcher { handle_store: HandleStore::new(), server }; let globals = dispatcher.server.globals(); @@ -276,16 +279,9 @@ impl client::Client { where S: Server, { - let client::Client { handle_counters, run, _marker } = *self; - run_server( - strategy, - handle_counters, - server, - >::mark(input), - run, - force_show_panics, - ) - .map(|s| >>::unmark(s).unwrap_or_default()) + let client::Client { run, _marker } = *self; + run_server(strategy, server, >::mark(input), run, force_show_panics) + .map(|s| >>::unmark(s).unwrap_or_default()) } } @@ -301,10 +297,9 @@ impl client::Client<(crate::TokenStream, crate::TokenStream), crate::TokenStream where S: Server, { - let client::Client { handle_counters, run, _marker } = *self; + let client::Client { run, _marker } = *self; run_server( strategy, - handle_counters, server, (>::mark(input), >::mark(input2)), run, From fade967190f81699cabd98f72a8db212008e7bf9 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Sat, 4 Apr 2026 16:39:41 -0700 Subject: [PATCH 18/26] Give variables passed to Omp/Offload nice names on LLVM-IR level --- .../src/builder/gpu_offload.rs | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs index 73822eb7ec50c..cea9b81f96534 100644 --- a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs +++ b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs @@ -319,25 +319,25 @@ impl KernelArgsTy { geps: [&'ll Value; 3], workgroup_dims: &'ll Value, thread_dims: &'ll Value, - ) -> [(Align, &'ll Value); 13] { + ) -> [(Align, &'ll str, &'ll Value); 13] { let four = Align::from_bytes(4).expect("4 Byte alignment should work"); let eight = Align::EIGHT; [ - (four, cx.get_const_i32(KernelArgsTy::OFFLOAD_VERSION)), - (four, cx.get_const_i32(num_args)), - (eight, geps[0]), - (eight, geps[1]), - (eight, geps[2]), - (eight, memtransfer_types), + (four, "Version", cx.get_const_i32(KernelArgsTy::OFFLOAD_VERSION)), + (four, "NumArgs", cx.get_const_i32(num_args)), + (eight, "ArgBasePtrs", geps[0]), + (eight, "ArgPtrs", geps[1]), + (eight, "ArgSizes", geps[2]), + (eight, "ArgTypes", memtransfer_types), // The next two are debug infos. FIXME(offload): set them - (eight, cx.const_null(cx.type_ptr())), // dbg - (eight, cx.const_null(cx.type_ptr())), // dbg - (eight, cx.get_const_i64(KernelArgsTy::TRIPCOUNT)), - (eight, cx.get_const_i64(KernelArgsTy::FLAGS)), - (four, workgroup_dims), - (four, thread_dims), - (four, cx.get_const_i32(0)), + (eight, "ArgNames", cx.const_null(cx.type_ptr())), // dbg + (eight, "ArgMappers", cx.const_null(cx.type_ptr())), // dbg + (eight, "Tripcount", cx.get_const_i64(KernelArgsTy::TRIPCOUNT)), + (eight, "Flags", cx.get_const_i64(KernelArgsTy::FLAGS)), + (four, "NumTeams", workgroup_dims), + (four, "ThreadLimit", thread_dims), + (four, "DynCGroupMem", cx.get_const_i32(0)), ] } } @@ -760,7 +760,10 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( // Here we fill the KernelArgsTy, see the documentation above for (i, value) in values.iter().enumerate() { let ptr = builder.inbounds_gep(tgt_kernel_decl, a5, &[i32_0, cx.get_const_i32(i as u64)]); - builder.store(value.1, ptr, value.0); + let name = std::ffi::CString::new(value.1).unwrap(); + llvm::set_value_name(ptr, &name.as_bytes()); + + builder.store(value.2, ptr, value.0); } let args = vec![ From c01bfdc4052d9566188b3a85f32a698a3eddede2 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Thu, 28 May 2026 14:55:38 -0700 Subject: [PATCH 19/26] Enable requesting shared-memory at kernel launch-time via offload --- .../src/builder/gpu_offload.rs | 15 ++++++++++++--- compiler/rustc_codegen_llvm/src/intrinsic.rs | 17 +++++++++++++++-- .../rustc_hir_analysis/src/check/intrinsic.rs | 1 + library/core/src/intrinsics/mod.rs | 1 + tests/codegen-llvm/gpu_offload/control_flow.rs | 3 ++- tests/codegen-llvm/gpu_offload/gpu_host.rs | 10 +++++----- tests/codegen-llvm/gpu_offload/scalar_host.rs | 10 +++++----- tests/codegen-llvm/gpu_offload/slice_host.rs | 4 ++-- 8 files changed, 43 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs index cea9b81f96534..0b009321802cf 100644 --- a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs +++ b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs @@ -319,6 +319,7 @@ impl KernelArgsTy { geps: [&'ll Value; 3], workgroup_dims: &'ll Value, thread_dims: &'ll Value, + dyn_cache: &'ll Value, ) -> [(Align, &'ll str, &'ll Value); 13] { let four = Align::from_bytes(4).expect("4 Byte alignment should work"); let eight = Align::EIGHT; @@ -337,7 +338,7 @@ impl KernelArgsTy { (eight, "Flags", cx.get_const_i64(KernelArgsTy::FLAGS)), (four, "NumTeams", workgroup_dims), (four, "ThreadLimit", thread_dims), - (four, "DynCGroupMem", cx.get_const_i32(0)), + (four, "DynCGroupMem", dyn_cache), ] } } @@ -589,6 +590,7 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( metadata: &[OffloadMetadata], offload_globals: &OffloadGlobals<'ll>, offload_dims: &OffloadKernelDims<'ll>, + dyn_cache: &'ll Value, ) { let cx = builder.cx; let OffloadKernelGlobals { @@ -753,8 +755,15 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( num_args, s_ident_t, ); - let values = - KernelArgsTy::new(&cx, num_args, memtransfer_kernel, geps, workgroup_dims, thread_dims); + let values = KernelArgsTy::new( + &cx, + num_args, + memtransfer_kernel, + geps, + workgroup_dims, + thread_dims, + dyn_cache, + ); // Step 3) // Here we fill the KernelArgsTy, see the documentation above diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 957ea23b9167c..577f8624af95c 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1937,7 +1937,11 @@ fn codegen_offload<'ll, 'tcx>( }; let offload_dims = OffloadKernelDims::from_operands(bx, &args[1], &args[2]); - let args = get_args_from_tuple(bx, args[3], fn_target); + let dyn_cache = match args[3].val { + OperandValue::Immediate(val) => val, + _ => panic!("unparsable"), + }; + let args = get_args_from_tuple(bx, args[4], fn_target); let target_symbol = symbol_name_for_instance_in_crate(tcx, fn_target, LOCAL_CRATE); let sig = tcx.fn_sig(fn_target.def_id()).skip_binder(); @@ -1969,7 +1973,16 @@ fn codegen_offload<'ll, 'tcx>( }; register_offload(cx); let offload_data = gen_define_handling(&cx, &metadata, target_symbol, offload_globals); - gen_call_handling(bx, &offload_data, &args, &types, &metadata, offload_globals, &offload_dims); + gen_call_handling( + bx, + &offload_data, + &args, + &types, + &metadata, + offload_globals, + &offload_dims, + &dyn_cache, + ); } fn get_args_from_tuple<'ll, 'tcx>( diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index c1edbb4fc520d..e366a2f982247 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -356,6 +356,7 @@ pub(crate) fn check_intrinsic_type( param(0), Ty::new_array_with_const_len(tcx, tcx.types.u32, Const::from_target_usize(tcx, 3)), Ty::new_array_with_const_len(tcx, tcx.types.u32, Const::from_target_usize(tcx, 3)), + tcx.types.u32, param(1), ], param(2), diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 82a7e3be9228e..68fbd8c31e768 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -3569,6 +3569,7 @@ pub const fn offload( f: F, workgroup_dim: [u32; 3], thread_dim: [u32; 3], + dyn_cache: u32, args: T, ) -> R; diff --git a/tests/codegen-llvm/gpu_offload/control_flow.rs b/tests/codegen-llvm/gpu_offload/control_flow.rs index 503e9e4221cdc..605a6f08843c3 100644 --- a/tests/codegen-llvm/gpu_offload/control_flow.rs +++ b/tests/codegen-llvm/gpu_offload/control_flow.rs @@ -19,7 +19,7 @@ // CHECK-NOT define // CHECK: bb3 // CHECK: call void @__tgt_target_data_begin_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 1, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull @.offload_sizes.foo, ptr nonnull @.offload_maptypes.foo.begin, ptr null, ptr null) -// CHECK: %10 = call i32 @__tgt_target_kernel(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 256, i32 32, ptr nonnull @.foo.region_id, ptr nonnull %kernel_args) +// CHECK: = call i32 @__tgt_target_kernel(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 256, i32 32, ptr nonnull @.foo.region_id, ptr nonnull %kernel_args) // CHECK-NEXT: call void @__tgt_target_data_end_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 1, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull @.offload_sizes.foo, ptr nonnull @.offload_maptypes.foo.end, ptr null, ptr null) #[unsafe(no_mangle)] unsafe fn main() { @@ -30,6 +30,7 @@ unsafe fn main() { foo, [256, 1, 1], [32, 1, 1], + 0, (A.as_ptr() as *const [f32; 6],), ); } diff --git a/tests/codegen-llvm/gpu_offload/gpu_host.rs b/tests/codegen-llvm/gpu_offload/gpu_host.rs index 8179d868da95f..2bfaf89b45590 100644 --- a/tests/codegen-llvm/gpu_offload/gpu_host.rs +++ b/tests/codegen-llvm/gpu_offload/gpu_host.rs @@ -21,7 +21,7 @@ fn main() { } pub fn kernel_1(x: &mut [f32; 256], y: &[f32; 256]) { - core::intrinsics::offload(_kernel_1, [256, 1, 1], [32, 1, 1], (x, y)) + core::intrinsics::offload(_kernel_1, [256, 1, 1], [32, 1, 1], 0, (x, y)) } #[inline(never)] @@ -52,8 +52,8 @@ pub fn _kernel_1(x: &mut [f32; 256], y: &[f32; 256]) { // CHECK-LABEL: define{{( dso_local)?}} void @main() // CHECK-NEXT: start: -// CHECK-NEXT: %0 = alloca [8 x i8], align 8 -// CHECK-NEXT: %1 = alloca [8 x i8], align 8 +// CHECK-NEXT: {{%[^ ]+}} = alloca [8 x i8], align 8 +// CHECK-NEXT: {{%[^ ]+}} = alloca [8 x i8], align 8 // CHECK-NEXT: %y = alloca [1024 x i8], align 16 // CHECK-NEXT: %x = alloca [1024 x i8], align 16 // CHECK-NEXT: %.offload_baseptrs = alloca [2 x ptr], align 8 @@ -61,9 +61,9 @@ pub fn _kernel_1(x: &mut [f32; 256], y: &[f32; 256]) { // CHECK-NEXT: %kernel_args = alloca %struct.__tgt_kernel_arguments, align 8 // CHECK: store ptr %x, ptr %.offload_baseptrs, align 8 // CHECK-NEXT: store ptr %x, ptr %.offload_ptrs, align 8 -// CHECK-NEXT: [[BPTRS_1:%.*]] = getelementptr inbounds nuw i8, ptr %.offload_baseptrs, i64 8 +// CHECK-NEXT: [[BPTRS_1:%[^ ]+]] = getelementptr inbounds nuw i8, ptr %.offload_baseptrs, i64 8 // CHECK-NEXT: store ptr %y, ptr [[BPTRS_1]], align 8 -// CHECK-NEXT: [[PTRS_1:%.*]] = getelementptr inbounds nuw i8, ptr %.offload_ptrs, i64 8 +// CHECK-NEXT: [[PTRS_1:%[^ ]+]] = getelementptr inbounds nuw i8, ptr %.offload_ptrs, i64 8 // CHECK-NEXT: store ptr %y, ptr [[PTRS_1]], align 8 // CHECK-NEXT: call void @__tgt_target_data_begin_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 2, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull @.offload_sizes.[[K]], ptr nonnull @.offload_maptypes.[[K]].begin, ptr null, ptr null) // CHECK-NEXT: store i32 3, ptr %kernel_args, align 8 diff --git a/tests/codegen-llvm/gpu_offload/scalar_host.rs b/tests/codegen-llvm/gpu_offload/scalar_host.rs index d5b40fb0a26db..3470761be06c8 100644 --- a/tests/codegen-llvm/gpu_offload/scalar_host.rs +++ b/tests/codegen-llvm/gpu_offload/scalar_host.rs @@ -13,11 +13,11 @@ // CHECK: define{{( dso_local)?}} void @main() // CHECK-NOT: define // CHECK: %addr = alloca i64, align 8 -// CHECK: store double 4.200000e+01, ptr %0, align 8 -// CHECK: %_0.i = load double, ptr %0, align 8 -// CHECK: store double %_0.i, ptr %addr, align 8 +// CHECK: store double 4.200000e+01, ptr [[TMP:%[^,]+]], align 8 +// CHECK: [[VAL:%[0-9]+]] = load double, ptr [[TMP]], align 8 +// CHECK: store double [[VAL]], ptr %addr, align 8 // CHECK: %1 = getelementptr inbounds nuw i8, ptr %.offload_baseptrs, i64 8 -// CHECK-NEXT: store double %_0.i, ptr %1, align 8 +// CHECK-NEXT: store double [[VAL]], ptr %1, align 8 // CHECK-NEXT: %2 = getelementptr inbounds nuw i8, ptr %.offload_ptrs, i64 8 // CHECK-NEXT: store ptr %addr, ptr %2, align 8 // CHECK-NEXT: call void @__tgt_target_data_begin_mapper @@ -27,7 +27,7 @@ fn main() { let mut x = 0.0; let k = core::hint::black_box(42.0); - core::intrinsics::offload::<_, _, ()>(foo, [1, 1, 1], [1, 1, 1], (&mut x, k)); + core::intrinsics::offload::<_, _, ()>(foo, [1, 1, 1], [1, 1, 1], 0, (&mut x, k)); } unsafe extern "C" { diff --git a/tests/codegen-llvm/gpu_offload/slice_host.rs b/tests/codegen-llvm/gpu_offload/slice_host.rs index 62f12da079d82..d4157d24e03dd 100644 --- a/tests/codegen-llvm/gpu_offload/slice_host.rs +++ b/tests/codegen-llvm/gpu_offload/slice_host.rs @@ -21,13 +21,13 @@ // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr {{.*}} %.offload_sizes, ptr {{.*}} @.offload_sizes.foo, i64 16, i1 false) // CHECK: store i64 16, ptr %.offload_sizes, align 8 // CHECK: call void @__tgt_target_data_begin_mapper(ptr nonnull @anon.[[ID]].1, i64 -1, i32 2, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull %.offload_sizes, ptr nonnull @.offload_maptypes.[[K]].begin, ptr null, ptr null) -// CHECK: %11 = call i32 @__tgt_target_kernel(ptr nonnull @anon.[[ID]].1, i64 -1, i32 1, i32 1, ptr nonnull @.foo.region_id, ptr nonnull %kernel_args) +// CHECK: call i32 @__tgt_target_kernel(ptr nonnull @anon.[[ID]].1, i64 -1, i32 1, i32 1, ptr nonnull @.foo.region_id, ptr nonnull %kernel_args) // CHECK-NEXT: call void @__tgt_target_data_end_mapper(ptr nonnull @anon.[[ID]].1, i64 -1, i32 2, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull %.offload_sizes, ptr nonnull @.offload_maptypes.[[K]].end, ptr null, ptr null) #[unsafe(no_mangle)] fn main() { let mut x = [0.0, 0.0, 0.0, 0.0]; - core::intrinsics::offload::<_, _, ()>(foo, [1, 1, 1], [1, 1, 1], ((&mut x) as &mut [f64],)); + core::intrinsics::offload::<_, _, ()>(foo, [1, 1, 1], [1, 1, 1], 0, ((&mut x) as &mut [f64],)); } unsafe extern "C" { From a1d4ad104f0a1b7cda7a07973faa185364f5105e Mon Sep 17 00:00:00 2001 From: Aria Givens Date: Thu, 28 May 2026 12:56:58 -0400 Subject: [PATCH 20/26] Suggest using NameValue syntax for malformed deprecated attribute --- .../rustc_attr_parsing/src/attributes/deprecation.rs | 10 ++++++++++ tests/ui/deprecation/deprecation-sanity.stderr | 6 ++++++ tests/ui/error-codes/E0565-1.stderr | 6 ++++++ 3 files changed, 22 insertions(+) diff --git a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs index 3b6dd7a67ed17..fd8616c4e9ea0 100644 --- a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs +++ b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs @@ -76,6 +76,16 @@ impl SingleAttributeParser for DeprecatedParser { // ok } ArgParser::List(list) => { + // If the argument list contains a single string literal, suggest using NameValue syntax + if let Some(elem) = list.as_single() && let Some(lit) = elem.as_lit() && lit.kind.is_str() { + let mut adcx = cx.adcx(); + if let Some(span) = args.span() { + adcx.push_suggestion(String::from("try using `=` instead"), span, format!(" = {}", lit.kind)); + } + adcx.expected_not_literal(elem.span()); + return None; + } + for param in list.mixed() { let Some(param) = param.meta_item() else { cx.adcx().expected_not_literal(param.span()); diff --git a/tests/ui/deprecation/deprecation-sanity.stderr b/tests/ui/deprecation/deprecation-sanity.stderr index 427d14d89c19f..d0e5a8a3ed4a5 100644 --- a/tests/ui/deprecation/deprecation-sanity.stderr +++ b/tests/ui/deprecation/deprecation-sanity.stderr @@ -55,6 +55,12 @@ LL | #[deprecated("test")] | ^^^^^^^^^^^^^------^^ | | | didn't expect a literal here + | +help: try using `=` instead + | +LL - #[deprecated("test")] +LL + #[deprecated = "test"] + | error: multiple `deprecated` attributes --> $DIR/deprecation-sanity.rs:29:1 diff --git a/tests/ui/error-codes/E0565-1.stderr b/tests/ui/error-codes/E0565-1.stderr index d1aff042e8fb6..0c500d2cbf231 100644 --- a/tests/ui/error-codes/E0565-1.stderr +++ b/tests/ui/error-codes/E0565-1.stderr @@ -5,6 +5,12 @@ LL | #[deprecated("since")] | ^^^^^^^^^^^^^-------^^ | | | didn't expect a literal here + | +help: try using `=` instead + | +LL - #[deprecated("since")] +LL + #[deprecated = "since"] + | error: aborting due to 1 previous error From 9bfbf3426c06fcb7dd90ae20fe3117ccccb95a88 Mon Sep 17 00:00:00 2001 From: Aria Givens Date: Thu, 28 May 2026 14:04:46 -0400 Subject: [PATCH 21/26] Suggest using since field when malformed deprecated attribute value is version shaped --- .../src/attributes/deprecation.rs | 60 ++++++++++++++----- tests/ui/deprecation/deprecation-sanity.rs | 3 + .../ui/deprecation/deprecation-sanity.stderr | 23 +++++-- 3 files changed, 66 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs index fd8616c4e9ea0..e0adbb0900deb 100644 --- a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs +++ b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs @@ -1,3 +1,4 @@ +use rustc_ast::LitKind; use rustc_hir::attrs::{DeprecatedSince, Deprecation}; use rustc_hir::{RustcVersion, VERSION_PLACEHOLDER}; @@ -76,12 +77,34 @@ impl SingleAttributeParser for DeprecatedParser { // ok } ArgParser::List(list) => { - // If the argument list contains a single string literal, suggest using NameValue syntax - if let Some(elem) = list.as_single() && let Some(lit) = elem.as_lit() && lit.kind.is_str() { + // If the argument list contains a single string literal: + // check whether it may be a version and suggest since field + // otherwise, suggest using NameValue syntax + if let Some(elem) = list.as_single() + && let Some(lit) = elem.as_lit() + && let LitKind::Str(text, _) = lit.kind + { let mut adcx = cx.adcx(); - if let Some(span) = args.span() { - adcx.push_suggestion(String::from("try using `=` instead"), span, format!(" = {}", lit.kind)); - } + + match parse_since(text, true) { + DeprecatedSince::Future | DeprecatedSince::RustcVersion(_) => { + adcx.push_suggestion( + String::from("try specifying a deprecated since version"), + elem.span(), + format!("since = {}", lit.kind), + ); + } + _ => { + if let Some(span) = args.span() { + adcx.push_suggestion( + String::from("try using `=` instead"), + span, + format!(" = {}", lit.kind), + ); + } + } + }; + adcx.expected_not_literal(elem.span()); return None; } @@ -143,18 +166,11 @@ impl SingleAttributeParser for DeprecatedParser { } let since = if let Some(since) = since { - if since.as_str() == "TBD" { - DeprecatedSince::Future - } else if !is_rustc { - DeprecatedSince::NonStandard(since) - } else if since.as_str() == VERSION_PLACEHOLDER { - DeprecatedSince::RustcVersion(RustcVersion::CURRENT) - } else if let Some(version) = parse_version(since) { - DeprecatedSince::RustcVersion(version) - } else { + let since = parse_since(since, is_rustc); + if matches!(since, DeprecatedSince::Err) { cx.emit_err(InvalidSince { span: cx.attr_span }); - DeprecatedSince::Err } + since } else if is_rustc { cx.emit_err(MissingSince { span: cx.attr_span }); DeprecatedSince::Err @@ -173,3 +189,17 @@ impl SingleAttributeParser for DeprecatedParser { }) } } + +fn parse_since(since: Symbol, is_rustc: bool) -> DeprecatedSince { + if since.as_str() == "TBD" { + DeprecatedSince::Future + } else if !is_rustc { + DeprecatedSince::NonStandard(since) + } else if since.as_str() == VERSION_PLACEHOLDER { + DeprecatedSince::RustcVersion(RustcVersion::CURRENT) + } else if let Some(version) = parse_version(since) { + DeprecatedSince::RustcVersion(version) + } else { + DeprecatedSince::Err + } +} diff --git a/tests/ui/deprecation/deprecation-sanity.rs b/tests/ui/deprecation/deprecation-sanity.rs index d1061dc1e170b..0ad491186cc38 100644 --- a/tests/ui/deprecation/deprecation-sanity.rs +++ b/tests/ui/deprecation/deprecation-sanity.rs @@ -23,6 +23,9 @@ mod bogus_attribute_types_1 { #[deprecated("test")] //~ ERROR malformed `deprecated` attribute input [E0565] fn f8() { } + + #[deprecated("1.2.3")] //~ ERROR malformed `deprecated` attribute input [E0565] + fn f9() { } } #[deprecated(since = "a", note = "b")] diff --git a/tests/ui/deprecation/deprecation-sanity.stderr b/tests/ui/deprecation/deprecation-sanity.stderr index d0e5a8a3ed4a5..2e00b2efea5c5 100644 --- a/tests/ui/deprecation/deprecation-sanity.stderr +++ b/tests/ui/deprecation/deprecation-sanity.stderr @@ -62,20 +62,33 @@ LL - #[deprecated("test")] LL + #[deprecated = "test"] | +error[E0565]: malformed `deprecated` attribute input + --> $DIR/deprecation-sanity.rs:27:5 + | +LL | #[deprecated("1.2.3")] + | ^^^^^^^^^^^^^-------^^ + | | + | didn't expect a literal here + | +help: try specifying a deprecated since version + | +LL | #[deprecated(since = "1.2.3")] + | +++++++ + error: multiple `deprecated` attributes - --> $DIR/deprecation-sanity.rs:29:1 + --> $DIR/deprecation-sanity.rs:32:1 | LL | #[deprecated(since = "a", note = "b")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/deprecation-sanity.rs:28:1 + --> $DIR/deprecation-sanity.rs:31:1 | LL | #[deprecated(since = "a", note = "b")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0538]: malformed `deprecated` attribute input - --> $DIR/deprecation-sanity.rs:32:1 + --> $DIR/deprecation-sanity.rs:35:1 | LL | #[deprecated(since = "a", since = "b", note = "c")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^^^^^^^^^^^ @@ -83,7 +96,7 @@ LL | #[deprecated(since = "a", since = "b", note = "c")] | found `since` used as a key more than once error: `#[deprecated]` attribute cannot be used on trait impl blocks - --> $DIR/deprecation-sanity.rs:37:1 + --> $DIR/deprecation-sanity.rs:40:1 | LL | #[deprecated = "hello"] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -92,7 +105,7 @@ LL | #[deprecated = "hello"] = help: `#[deprecated]` can be applied to associated consts, associated types, constants, crates, data types, enum variants, foreign statics, functions, inherent impl blocks, macro defs, modules, statics, struct fields, traits, type aliases, and use statements = note: `#[deny(useless_deprecated)]` on by default -error: aborting due to 10 previous errors +error: aborting due to 11 previous errors Some errors have detailed explanations: E0538, E0539, E0565. For more information about an error, try `rustc --explain E0538`. From 942ac855dc786a8eb98546d9e96982b2c8ee2e4b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 28 May 2026 12:25:53 +0200 Subject: [PATCH 22/26] Eagerly resolve delegations in late resolution --- compiler/rustc_ast_lowering/src/delegation.rs | 22 +++++------------ compiler/rustc_middle/src/ty/mod.rs | 7 ++++-- compiler/rustc_resolve/src/late.rs | 24 ++++++++++++++----- 3 files changed, 29 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index df5ea7c3168ff..411b27e0dd9f4 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -124,7 +124,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // Delegation can be unresolved in illegal places such as function bodies in extern blocks (see #151356) let sig_id = if let Some(delegation_info) = self.resolver.delegation_info(self.owner.def_id) { - self.get_sig_id(delegation_info.resolution_node, span) + self.get_sig_id(delegation_info.resolution_id, span) } else { self.dcx().span_delayed_bug( span, @@ -223,22 +223,12 @@ impl<'hir> LoweringContext<'_, 'hir> { .collect::>() } - fn get_sig_id(&self, mut node_id: NodeId, span: Span) -> Result { - let mut visited: FxHashSet = Default::default(); + fn get_sig_id(&self, mut def_id: DefId, span: Span) -> Result { + let mut visited: FxHashSet = Default::default(); let mut path: SmallVec<[DefId; 1]> = Default::default(); loop { - visited.insert(node_id); - - let Some(def_id) = self.get_resolution_id(node_id) else { - return Err(self.tcx.dcx().span_delayed_bug( - span, - format!( - "LoweringContext: couldn't resolve node {:?} in delegation item", - node_id - ), - )); - }; + visited.insert(def_id); path.push(def_id); @@ -248,8 +238,8 @@ impl<'hir> LoweringContext<'_, 'hir> { if let Some(local_id) = def_id.as_local() && let Some(delegation_info) = self.resolver.delegation_info(local_id) { - node_id = delegation_info.resolution_node; - if visited.contains(&node_id) { + def_id = delegation_info.resolution_id; + if visited.contains(&def_id) { // We encountered a cycle in the resolution, or delegation callee refers to non-existent // entity, in this case emit an error. return Err(match visited.len() { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 74f9e75fb48c0..f4a5e7bc1ff4a 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -253,9 +253,12 @@ pub struct ResolverAstLowering<'tcx> { #[derive(Debug)] pub struct DelegationInfo { - // NodeId (either delegation.id or item_id in case of a trait impl) for signature resolution, + // `DefId` (either the resolution at delegation.id or item_id in case of a trait impl) for signature resolution, // for details see https://github.com/rust-lang/rust/issues/118212#issuecomment-2160686914 - pub resolution_node: ast::NodeId, + /// Refers to the next element in a delegation resolution chain. + /// Usually points to the final resolution, as most "chains" are just + /// one step to a trait or an impl. + pub resolution_id: DefId, } #[derive(Clone, Copy, Debug, StableHash)] diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index fb8de90d28aca..e7ec557243fa1 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3923,12 +3923,24 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { this.visit_path(&delegation.path); }); - self.r.delegation_infos.insert( - self.r.current_owner.def_id, - DelegationInfo { - resolution_node: if is_in_trait_impl { item_id } else { delegation.id }, - }, - ); + let resolution_id = if is_in_trait_impl { item_id } else { delegation.id }; + let def_id = self + .r + .partial_res_map + .get(&resolution_id) + .and_then(|r| r.expect_full_res().opt_def_id()); + if let Some(resolution_id) = def_id { + self.r + .delegation_infos + .insert(self.r.current_owner.def_id, DelegationInfo { resolution_id }); + } else { + self.r.tcx.dcx().span_delayed_bug( + delegation.path.span, + format!( + "LoweringContext: couldn't resolve node {resolution_id:?} in delegation item", + ), + ); + }; let Some(body) = &delegation.body else { return }; self.with_rib(ValueNS, RibKind::FnOrCoroutine, |this| { From f582193db55de1a111006d6b8e7e307b84950b4b Mon Sep 17 00:00:00 2001 From: Daria Sukhonina Date: Fri, 29 May 2026 12:29:32 +0300 Subject: [PATCH 23/26] Update reproducibly failing tests when parallel frontend is enabled --- .../diagnostics/liveness.rs | 2 +- tests/ui/lint/unused/unused-assign-148960.rs | 1 + .../lint/unused/unused-assign-148960.stderr | 14 +-- tests/ui/liveness/liveness-consts.rs | 1 + tests/ui/liveness/liveness-consts.stderr | 22 ++-- tests/ui/liveness/liveness-dead.rs | 1 + tests/ui/liveness/liveness-dead.stderr | 10 +- tests/ui/liveness/liveness-upvars.rs | 1 + tests/ui/liveness/liveness-upvars.stderr | 50 ++++----- ...signments-diverging-branch-issue-156416.rs | 1 + ...ments-diverging-branch-issue-156416.stderr | 10 +- .../empty-types.exhaustive_patterns.stderr | 100 +++++++++--------- .../usefulness/empty-types.never_pats.stderr | 86 +++++++-------- .../usefulness/empty-types.normal.stderr | 86 +++++++-------- tests/ui/pattern/usefulness/empty-types.rs | 1 + 15 files changed, 196 insertions(+), 190 deletions(-) diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/liveness.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/liveness.rs index 641066b002273..e5f7ed3a8d774 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/liveness.rs +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/liveness.rs @@ -1,6 +1,6 @@ //@ edition:2021 - //@ check-pass +//@ ignore-parallel-frontend unstable liveness diagnostics #![allow(unreachable_code)] #![warn(unused)] #![allow(dead_code)] diff --git a/tests/ui/lint/unused/unused-assign-148960.rs b/tests/ui/lint/unused/unused-assign-148960.rs index 2e51c01398a37..b7e129a4f2ab7 100644 --- a/tests/ui/lint/unused/unused-assign-148960.rs +++ b/tests/ui/lint/unused/unused-assign-148960.rs @@ -1,4 +1,5 @@ //@ check-fail +//@ ignore-parallel-frontend unstable liveness diagnostics #![deny(unused)] #![allow(dead_code)] diff --git a/tests/ui/lint/unused/unused-assign-148960.stderr b/tests/ui/lint/unused/unused-assign-148960.stderr index aa5326cea6476..60966beb36ab6 100644 --- a/tests/ui/lint/unused/unused-assign-148960.stderr +++ b/tests/ui/lint/unused/unused-assign-148960.stderr @@ -1,5 +1,5 @@ error: value assigned to `value` is never read - --> $DIR/unused-assign-148960.rs:6:21 + --> $DIR/unused-assign-148960.rs:7:21 | LL | let mut value = b"0".to_vec(); | ^^^^^^^^^^^^^ this value is reassigned later and never used @@ -7,14 +7,14 @@ LL | value = b"1".to_vec(); | ----- `value` is overwritten here before the previous value is read | note: the lint level is defined here - --> $DIR/unused-assign-148960.rs:2:9 + --> $DIR/unused-assign-148960.rs:3:9 | LL | #![deny(unused)] | ^^^^^^ = note: `#[deny(unused_assignments)]` implied by `#[deny(unused)]` error: value assigned to `x` is never read - --> $DIR/unused-assign-148960.rs:12:17 + --> $DIR/unused-assign-148960.rs:13:17 | LL | let mut x = 1; | ^ this value is reassigned later and never used @@ -22,7 +22,7 @@ LL | x = 2; | ----- `x` is overwritten here before the previous value is read error: value assigned to `x` is never read - --> $DIR/unused-assign-148960.rs:13:5 + --> $DIR/unused-assign-148960.rs:14:5 | LL | x = 2; | ^^^^^ this value is reassigned later and never used @@ -30,7 +30,7 @@ LL | x = 3; | ----- `x` is overwritten here before the previous value is read error: value assigned to `p` is never read - --> $DIR/unused-assign-148960.rs:24:17 + --> $DIR/unused-assign-148960.rs:25:17 | LL | let mut p = Point { x: 1, y: 1 }; | ^^^^^^^^^^^^^^^^^^^^ this value is reassigned later and never used @@ -38,7 +38,7 @@ LL | p = Point { x: 2, y: 2 }; | ------------------------ `p` is overwritten here before the previous value is read error: variable `foo` is assigned to, but never used - --> $DIR/unused-assign-148960.rs:38:9 + --> $DIR/unused-assign-148960.rs:39:9 | LL | let mut foo = Foo; | ^^^^^^^ @@ -52,7 +52,7 @@ LL + let Foo = Foo; | error: value assigned to `foo` is never read - --> $DIR/unused-assign-148960.rs:39:5 + --> $DIR/unused-assign-148960.rs:40:5 | LL | foo = Foo; | ^^^ diff --git a/tests/ui/liveness/liveness-consts.rs b/tests/ui/liveness/liveness-consts.rs index 7e56bf8c2cda4..b239e12b2e021 100644 --- a/tests/ui/liveness/liveness-consts.rs +++ b/tests/ui/liveness/liveness-consts.rs @@ -1,4 +1,5 @@ //@ check-pass +//@ ignore-parallel-frontend unstable liveness diagnostics #![warn(unused)] #![allow(unreachable_code)] diff --git a/tests/ui/liveness/liveness-consts.stderr b/tests/ui/liveness/liveness-consts.stderr index 6b4acf1c8de9a..f4a5b82725346 100644 --- a/tests/ui/liveness/liveness-consts.stderr +++ b/tests/ui/liveness/liveness-consts.stderr @@ -1,30 +1,30 @@ warning: unused variable: `e` - --> $DIR/liveness-consts.rs:26:13 + --> $DIR/liveness-consts.rs:27:13 | LL | let e = 1; | ^ help: if this is intentional, prefix it with an underscore: `_e` | note: the lint level is defined here - --> $DIR/liveness-consts.rs:2:9 + --> $DIR/liveness-consts.rs:3:9 | LL | #![warn(unused)] | ^^^^^^ = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` warning: unused variable: `s` - --> $DIR/liveness-consts.rs:35:24 + --> $DIR/liveness-consts.rs:36:24 | LL | pub fn f(x: [u8; { let s = 17; 100 }]) -> [u8; { let z = 18; 100 }] { | ^ help: if this is intentional, prefix it with an underscore: `_s` warning: unused variable: `z` - --> $DIR/liveness-consts.rs:35:55 + --> $DIR/liveness-consts.rs:36:55 | LL | pub fn f(x: [u8; { let s = 17; 100 }]) -> [u8; { let z = 18; 100 }] { | ^ help: if this is intentional, prefix it with an underscore: `_z` warning: variable `a` is assigned to, but never used - --> $DIR/liveness-consts.rs:7:9 + --> $DIR/liveness-consts.rs:8:9 | LL | let mut a = 0; | ^^^^^ @@ -32,7 +32,7 @@ LL | let mut a = 0; = note: consider using `_a` instead warning: value assigned to `a` is never read - --> $DIR/liveness-consts.rs:11:9 + --> $DIR/liveness-consts.rs:12:9 | LL | a += 1; | ^^^^^^ @@ -41,7 +41,7 @@ LL | a += 1; = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]` warning: value assigned to `b` is never read - --> $DIR/liveness-consts.rs:18:17 + --> $DIR/liveness-consts.rs:19:17 | LL | let mut b = 1; | ^ this value is reassigned later and never used @@ -49,7 +49,7 @@ LL | b += 1; | ------ `b` is overwritten here before the previous value is read warning: value assigned to `b` is never read - --> $DIR/liveness-consts.rs:19:5 + --> $DIR/liveness-consts.rs:20:5 | LL | b += 1; | ^^^^^^ this value is reassigned later and never used @@ -57,13 +57,13 @@ LL | b = 42; | ------ `b` is overwritten here before the previous value is read warning: unused variable: `z` - --> $DIR/liveness-consts.rs:62:13 + --> $DIR/liveness-consts.rs:63:13 | LL | let z = 42; | ^ help: if this is intentional, prefix it with an underscore: `_z` warning: value assigned to `t` is never read - --> $DIR/liveness-consts.rs:44:9 + --> $DIR/liveness-consts.rs:45:9 | LL | t = t + t; | ^^^^^^^^^ @@ -71,7 +71,7 @@ LL | t = t + t; = help: maybe it is overwritten before being read? warning: unused variable: `w` - --> $DIR/liveness-consts.rs:51:13 + --> $DIR/liveness-consts.rs:52:13 | LL | let w = 10; | ^ help: if this is intentional, prefix it with an underscore: `_w` diff --git a/tests/ui/liveness/liveness-dead.rs b/tests/ui/liveness/liveness-dead.rs index 004663c85ee50..c48b28ef74fec 100644 --- a/tests/ui/liveness/liveness-dead.rs +++ b/tests/ui/liveness/liveness-dead.rs @@ -1,3 +1,4 @@ +//@ ignore-parallel-frontend unstable liveness diagnostics #![allow(dead_code)] #![deny(unused_assignments)] diff --git a/tests/ui/liveness/liveness-dead.stderr b/tests/ui/liveness/liveness-dead.stderr index ade0e04d2e7a9..2288fae52091a 100644 --- a/tests/ui/liveness/liveness-dead.stderr +++ b/tests/ui/liveness/liveness-dead.stderr @@ -1,5 +1,5 @@ error: value assigned to `x` is never read - --> $DIR/liveness-dead.rs:9:24 + --> $DIR/liveness-dead.rs:10:24 | LL | let mut x: isize = 3; | ^ this value is reassigned later and never used @@ -7,13 +7,13 @@ LL | x = 4; | ----- `x` is overwritten here before the previous value is read | note: the lint level is defined here - --> $DIR/liveness-dead.rs:2:9 + --> $DIR/liveness-dead.rs:3:9 | LL | #![deny(unused_assignments)] | ^^^^^^^^^^^^^^^^^^ error: value assigned to `x` is never read - --> $DIR/liveness-dead.rs:17:5 + --> $DIR/liveness-dead.rs:18:5 | LL | x = 4; | ^^^^^ @@ -21,7 +21,7 @@ LL | x = 4; = help: maybe it is overwritten before being read? error: value passed to `x` is never read - --> $DIR/liveness-dead.rs:20:7 + --> $DIR/liveness-dead.rs:21:7 | LL | fn f4(mut x: i32) { | ^^^^^ @@ -29,7 +29,7 @@ LL | fn f4(mut x: i32) { = help: maybe it is overwritten before being read? error: value assigned to `x` is never read - --> $DIR/liveness-dead.rs:27:5 + --> $DIR/liveness-dead.rs:28:5 | LL | x = 4; | ^^^^^ diff --git a/tests/ui/liveness/liveness-upvars.rs b/tests/ui/liveness/liveness-upvars.rs index be58b48a40576..1a3d0e5be54ad 100644 --- a/tests/ui/liveness/liveness-upvars.rs +++ b/tests/ui/liveness/liveness-upvars.rs @@ -1,5 +1,6 @@ //@ edition:2018 //@ check-pass +//@ ignore-parallel-frontend unstable liveness diagnostics #![feature(coroutines, stmt_expr_attributes)] #![warn(unused)] #![allow(unreachable_code)] diff --git a/tests/ui/liveness/liveness-upvars.stderr b/tests/ui/liveness/liveness-upvars.stderr index 96a922772c919..b569acdccf8a7 100644 --- a/tests/ui/liveness/liveness-upvars.stderr +++ b/tests/ui/liveness/liveness-upvars.stderr @@ -1,19 +1,19 @@ warning: value captured by `last` is never read - --> $DIR/liveness-upvars.rs:10:9 + --> $DIR/liveness-upvars.rs:11:9 | LL | last = Some(s); | ^^^^ | = help: did you mean to capture by reference instead? note: the lint level is defined here - --> $DIR/liveness-upvars.rs:4:9 + --> $DIR/liveness-upvars.rs:5:9 | LL | #![warn(unused)] | ^^^^^^ = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]` warning: value assigned to `last` is never read - --> $DIR/liveness-upvars.rs:10:9 + --> $DIR/liveness-upvars.rs:11:9 | LL | last = Some(s); | ^^^^^^^^^^^^^^ @@ -21,7 +21,7 @@ LL | last = Some(s); = help: maybe it is overwritten before being read? warning: value captured by `sum` is never read - --> $DIR/liveness-upvars.rs:22:9 + --> $DIR/liveness-upvars.rs:23:9 | LL | sum += x; | ^^^ @@ -29,7 +29,7 @@ LL | sum += x; = help: did you mean to capture by reference instead? warning: value assigned to `sum` is never read - --> $DIR/liveness-upvars.rs:22:9 + --> $DIR/liveness-upvars.rs:23:9 | LL | sum += x; | ^^^^^^^^ @@ -37,7 +37,7 @@ LL | sum += x; = help: maybe it is overwritten before being read? warning: value assigned to `c` is never read - --> $DIR/liveness-upvars.rs:69:9 + --> $DIR/liveness-upvars.rs:70:9 | LL | c += 1; | ^^^^^^ @@ -45,7 +45,7 @@ LL | c += 1; = help: maybe it is overwritten before being read? warning: value assigned to `c` is never read - --> $DIR/liveness-upvars.rs:63:9 + --> $DIR/liveness-upvars.rs:64:9 | LL | c += 1; | ^^^^^^ @@ -53,7 +53,7 @@ LL | c += 1; = help: maybe it is overwritten before being read? warning: value captured by `c` is never read - --> $DIR/liveness-upvars.rs:49:9 + --> $DIR/liveness-upvars.rs:50:9 | LL | c += 1; | ^ @@ -61,7 +61,7 @@ LL | c += 1; = help: did you mean to capture by reference instead? warning: value assigned to `c` is never read - --> $DIR/liveness-upvars.rs:49:9 + --> $DIR/liveness-upvars.rs:50:9 | LL | c += 1; | ^^^^^^ @@ -69,7 +69,7 @@ LL | c += 1; = help: maybe it is overwritten before being read? warning: value captured by `c` is never read - --> $DIR/liveness-upvars.rs:44:9 + --> $DIR/liveness-upvars.rs:45:9 | LL | c += 1; | ^ @@ -77,7 +77,7 @@ LL | c += 1; = help: did you mean to capture by reference instead? warning: value assigned to `c` is never read - --> $DIR/liveness-upvars.rs:44:9 + --> $DIR/liveness-upvars.rs:45:9 | LL | c += 1; | ^^^^^^ @@ -85,7 +85,7 @@ LL | c += 1; = help: maybe it is overwritten before being read? warning: value captured by `c` is never read - --> $DIR/liveness-upvars.rs:38:9 + --> $DIR/liveness-upvars.rs:39:9 | LL | c = 1; | ^ @@ -93,7 +93,7 @@ LL | c = 1; = help: did you mean to capture by reference instead? warning: value captured by `c` is never read - --> $DIR/liveness-upvars.rs:34:9 + --> $DIR/liveness-upvars.rs:35:9 | LL | c = 1; | ^ @@ -101,7 +101,7 @@ LL | c = 1; = help: did you mean to capture by reference instead? warning: value captured by `e` is never read - --> $DIR/liveness-upvars.rs:82:13 + --> $DIR/liveness-upvars.rs:83:13 | LL | e = Some("e1"); | ^ @@ -109,7 +109,7 @@ LL | e = Some("e1"); = help: did you mean to capture by reference instead? warning: value assigned to `e` is never read - --> $DIR/liveness-upvars.rs:82:13 + --> $DIR/liveness-upvars.rs:83:13 | LL | e = Some("e1"); | ^^^^^^^^^^^^^^ this value is reassigned later and never used @@ -118,7 +118,7 @@ LL | e = Some("e2"); | -------------- `e` is overwritten here before the previous value is read warning: value assigned to `e` is never read - --> $DIR/liveness-upvars.rs:84:13 + --> $DIR/liveness-upvars.rs:85:13 | LL | e = Some("e2"); | ^^^^^^^^^^^^^^ @@ -126,7 +126,7 @@ LL | e = Some("e2"); = help: maybe it is overwritten before being read? warning: value assigned to `d` is never read - --> $DIR/liveness-upvars.rs:78:13 + --> $DIR/liveness-upvars.rs:79:13 | LL | d = Some("d1"); | ^^^^^^^^^^^^^^ this value is reassigned later and never used @@ -134,7 +134,7 @@ LL | d = Some("d2"); | -------------- `d` is overwritten here before the previous value is read warning: value assigned to `v` is never read - --> $DIR/liveness-upvars.rs:92:13 + --> $DIR/liveness-upvars.rs:93:13 | LL | v = T::default(); | ^ @@ -142,7 +142,7 @@ LL | v = T::default(); = help: maybe it is overwritten before being read? warning: value captured by `z` is never read - --> $DIR/liveness-upvars.rs:105:17 + --> $DIR/liveness-upvars.rs:106:17 | LL | z = T::default(); | ^ @@ -150,7 +150,7 @@ LL | z = T::default(); = help: did you mean to capture by reference instead? warning: value assigned to `z` is never read - --> $DIR/liveness-upvars.rs:105:17 + --> $DIR/liveness-upvars.rs:106:17 | LL | z = T::default(); | ^^^^^^^^^^^^^^^^ @@ -158,7 +158,7 @@ LL | z = T::default(); = help: maybe it is overwritten before being read? warning: value captured by `state` is never read - --> $DIR/liveness-upvars.rs:131:9 + --> $DIR/liveness-upvars.rs:132:9 | LL | state = 4; | ^^^^^ @@ -166,7 +166,7 @@ LL | state = 4; = help: did you mean to capture by reference instead? warning: value assigned to `state` is never read - --> $DIR/liveness-upvars.rs:131:9 + --> $DIR/liveness-upvars.rs:132:9 | LL | state = 4; | ^^^^^^^^^ this value is reassigned later and never used @@ -175,7 +175,7 @@ LL | state = 5; | --------- `state` is overwritten here before the previous value is read warning: value assigned to `state` is never read - --> $DIR/liveness-upvars.rs:134:9 + --> $DIR/liveness-upvars.rs:135:9 | LL | state = 5; | ^^^^^^^^^ @@ -183,7 +183,7 @@ LL | state = 5; = help: maybe it is overwritten before being read? warning: value assigned to `s` is never read - --> $DIR/liveness-upvars.rs:143:9 + --> $DIR/liveness-upvars.rs:144:9 | LL | s = 1; | ^^^^^ this value is reassigned later and never used @@ -191,7 +191,7 @@ LL | yield (s = 2); | ------- `s` is overwritten here before the previous value is read warning: value assigned to `s` is never read - --> $DIR/liveness-upvars.rs:145:9 + --> $DIR/liveness-upvars.rs:146:9 | LL | s = yield (); | ^^^^^^^^^^^^ this value is reassigned later and never used diff --git a/tests/ui/liveness/unused-assignments-diverging-branch-issue-156416.rs b/tests/ui/liveness/unused-assignments-diverging-branch-issue-156416.rs index 08cffa00f752f..d1fb55d874518 100644 --- a/tests/ui/liveness/unused-assignments-diverging-branch-issue-156416.rs +++ b/tests/ui/liveness/unused-assignments-diverging-branch-issue-156416.rs @@ -1,4 +1,5 @@ //@ run-pass +//@ ignore-parallel-frontend unstable liveness diagnostics #![allow(dead_code)] #![warn(unused_assignments)] diff --git a/tests/ui/liveness/unused-assignments-diverging-branch-issue-156416.stderr b/tests/ui/liveness/unused-assignments-diverging-branch-issue-156416.stderr index 5afb33626e055..4ec4a3d3839b7 100644 --- a/tests/ui/liveness/unused-assignments-diverging-branch-issue-156416.stderr +++ b/tests/ui/liveness/unused-assignments-diverging-branch-issue-156416.stderr @@ -1,18 +1,18 @@ warning: value assigned to `x` is never read - --> $DIR/unused-assignments-diverging-branch-issue-156416.rs:10:9 + --> $DIR/unused-assignments-diverging-branch-issue-156416.rs:11:9 | LL | x = 35; | ^^^^^^ | = help: maybe it is overwritten before being read? note: the lint level is defined here - --> $DIR/unused-assignments-diverging-branch-issue-156416.rs:3:9 + --> $DIR/unused-assignments-diverging-branch-issue-156416.rs:4:9 | LL | #![warn(unused_assignments)] | ^^^^^^^^^^^^^^^^^^ warning: value assigned to `x` is never read - --> $DIR/unused-assignments-diverging-branch-issue-156416.rs:21:13 + --> $DIR/unused-assignments-diverging-branch-issue-156416.rs:22:13 | LL | x = 35; | ^^^^^^ @@ -20,7 +20,7 @@ LL | x = 35; = help: maybe it is overwritten before being read? warning: value assigned to `x` is never read - --> $DIR/unused-assignments-diverging-branch-issue-156416.rs:36:9 + --> $DIR/unused-assignments-diverging-branch-issue-156416.rs:37:9 | LL | x = 42; | ^^^^^^ this value is reassigned later and never used @@ -29,7 +29,7 @@ LL | x = 99; | ------ `x` is overwritten here before the previous value is read warning: value assigned to `x` is never read - --> $DIR/unused-assignments-diverging-branch-issue-156416.rs:33:9 + --> $DIR/unused-assignments-diverging-branch-issue-156416.rs:34:9 | LL | x = 35; | ^^^^^^ this value is reassigned later and never used diff --git a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr index 75a633cd49a3d..d26ba93e72117 100644 --- a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr @@ -1,5 +1,5 @@ error: unreachable pattern - --> $DIR/empty-types.rs:47:9 + --> $DIR/empty-types.rs:48:9 | LL | _ => {} | ^------ @@ -9,13 +9,13 @@ LL | _ => {} | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here - --> $DIR/empty-types.rs:13:9 + --> $DIR/empty-types.rs:14:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/empty-types.rs:50:9 + --> $DIR/empty-types.rs:51:9 | LL | _x => {} | ^^------ @@ -26,7 +26,7 @@ LL | _x => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: type `&!` is non-empty - --> $DIR/empty-types.rs:54:11 + --> $DIR/empty-types.rs:55:11 | LL | match ref_never {} | ^^^^^^^^^ @@ -41,7 +41,7 @@ LL ~ } | error: unreachable pattern - --> $DIR/empty-types.rs:68:9 + --> $DIR/empty-types.rs:69:9 | LL | (_, _) => {} | ^^^^^^------ @@ -52,7 +52,7 @@ LL | (_, _) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:74:9 + --> $DIR/empty-types.rs:75:9 | LL | _ => {} | ^------ @@ -63,7 +63,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:77:9 + --> $DIR/empty-types.rs:78:9 | LL | (_, _) => {} | ^^^^^^------ @@ -74,7 +74,7 @@ LL | (_, _) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:81:9 + --> $DIR/empty-types.rs:82:9 | LL | _ => {} | ^------ @@ -85,7 +85,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `Ok(_)` not covered - --> $DIR/empty-types.rs:85:11 + --> $DIR/empty-types.rs:86:11 | LL | match res_u32_never {} | ^^^^^^^^^^^^^ pattern `Ok(_)` not covered @@ -104,7 +104,7 @@ LL ~ } | error: unreachable pattern - --> $DIR/empty-types.rs:92:9 + --> $DIR/empty-types.rs:93:9 | LL | Err(_) => {} | ^^^^^^------ @@ -115,7 +115,7 @@ LL | Err(_) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:97:9 + --> $DIR/empty-types.rs:98:9 | LL | Err(_) => {} | ^^^^^^------ @@ -126,7 +126,7 @@ LL | Err(_) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered - --> $DIR/empty-types.rs:94:11 + --> $DIR/empty-types.rs:95:11 | LL | match res_u32_never { | ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered @@ -144,7 +144,7 @@ LL ~ Ok(1_u32..=u32::MAX) => todo!() | error[E0005]: refutable pattern in local binding - --> $DIR/empty-types.rs:100:9 + --> $DIR/empty-types.rs:101:9 | LL | let Ok(_x) = res_u32_never.as_ref(); | ^^^^^^ pattern `Err(_)` not covered @@ -158,7 +158,7 @@ LL | let Ok(_x) = res_u32_never.as_ref() else { todo!() }; | ++++++++++++++++ error: unreachable pattern - --> $DIR/empty-types.rs:110:9 + --> $DIR/empty-types.rs:111:9 | LL | _ => {} | ^------ @@ -169,7 +169,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:113:9 + --> $DIR/empty-types.rs:114:9 | LL | Ok(_) => {} | ^^^^^------ @@ -180,7 +180,7 @@ LL | Ok(_) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:116:9 + --> $DIR/empty-types.rs:117:9 | LL | Ok(_) => {} | ^^^^^------ @@ -191,7 +191,7 @@ LL | Ok(_) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:117:9 + --> $DIR/empty-types.rs:118:9 | LL | _ => {} | ^------ @@ -202,7 +202,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:120:9 + --> $DIR/empty-types.rs:121:9 | LL | Ok(_) => {} | ^^^^^------ @@ -213,7 +213,7 @@ LL | Ok(_) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:121:9 + --> $DIR/empty-types.rs:122:9 | LL | Err(_) => {} | ^^^^^^------ @@ -224,7 +224,7 @@ LL | Err(_) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:130:13 + --> $DIR/empty-types.rs:131:13 | LL | _ => {} | ^------ @@ -235,7 +235,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:133:13 + --> $DIR/empty-types.rs:134:13 | LL | _ if false => {} | ^--------------- @@ -246,7 +246,7 @@ LL | _ if false => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:141:13 + --> $DIR/empty-types.rs:142:13 | LL | Some(_) => {} | ^^^^^^^------ @@ -257,7 +257,7 @@ LL | Some(_) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:145:13 + --> $DIR/empty-types.rs:146:13 | LL | None => {} | ---- matches all the relevant values @@ -265,7 +265,7 @@ LL | _ => {} | ^ no value can reach this error: unreachable pattern - --> $DIR/empty-types.rs:197:13 + --> $DIR/empty-types.rs:198:13 | LL | _ => {} | ^------ @@ -276,7 +276,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:202:13 + --> $DIR/empty-types.rs:203:13 | LL | _ => {} | ^------ @@ -287,7 +287,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:207:13 + --> $DIR/empty-types.rs:208:13 | LL | _ => {} | ^------ @@ -298,7 +298,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:212:13 + --> $DIR/empty-types.rs:213:13 | LL | _ => {} | ^------ @@ -309,7 +309,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:218:13 + --> $DIR/empty-types.rs:219:13 | LL | _ => {} | ^------ @@ -320,7 +320,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:279:9 + --> $DIR/empty-types.rs:280:9 | LL | _ => {} | ^------ @@ -331,7 +331,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:282:9 + --> $DIR/empty-types.rs:283:9 | LL | (_, _) => {} | ^^^^^^------ @@ -342,7 +342,7 @@ LL | (_, _) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:285:9 + --> $DIR/empty-types.rs:286:9 | LL | Ok(_) => {} | ^^^^^------ @@ -353,7 +353,7 @@ LL | Ok(_) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:286:9 + --> $DIR/empty-types.rs:287:9 | LL | Err(_) => {} | ^^^^^^------ @@ -364,7 +364,7 @@ LL | Err(_) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty - --> $DIR/empty-types.rs:325:11 + --> $DIR/empty-types.rs:326:11 | LL | match slice_never {} | ^^^^^^^^^^^ @@ -378,7 +378,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: `&[]` not covered - --> $DIR/empty-types.rs:336:11 + --> $DIR/empty-types.rs:337:11 | LL | match slice_never { | ^^^^^^^^^^^ pattern `&[]` not covered @@ -391,7 +391,7 @@ LL + &[] => todo!() | error[E0004]: non-exhaustive patterns: `&[]` not covered - --> $DIR/empty-types.rs:350:11 + --> $DIR/empty-types.rs:351:11 | LL | match slice_never { | ^^^^^^^^^^^ pattern `&[]` not covered @@ -405,7 +405,7 @@ LL + &[] => todo!() | error[E0004]: non-exhaustive patterns: type `[!]` is non-empty - --> $DIR/empty-types.rs:357:11 + --> $DIR/empty-types.rs:358:11 | LL | match *slice_never {} | ^^^^^^^^^^^^ @@ -419,7 +419,7 @@ LL ~ } | error: unreachable pattern - --> $DIR/empty-types.rs:366:9 + --> $DIR/empty-types.rs:367:9 | LL | _ => {} | ^------ @@ -430,7 +430,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:369:9 + --> $DIR/empty-types.rs:370:9 | LL | [_, _, _] => {} | ^^^^^^^^^------ @@ -441,7 +441,7 @@ LL | [_, _, _] => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:372:9 + --> $DIR/empty-types.rs:373:9 | LL | [_, ..] => {} | ^^^^^^^------ @@ -452,7 +452,7 @@ LL | [_, ..] => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty - --> $DIR/empty-types.rs:386:11 + --> $DIR/empty-types.rs:387:11 | LL | match array_0_never {} | ^^^^^^^^^^^^^ @@ -466,7 +466,7 @@ LL ~ } | error: unreachable pattern - --> $DIR/empty-types.rs:393:9 + --> $DIR/empty-types.rs:394:9 | LL | [] => {} | -- matches all the relevant values @@ -474,7 +474,7 @@ LL | _ => {} | ^ no value can reach this error[E0004]: non-exhaustive patterns: `[]` not covered - --> $DIR/empty-types.rs:395:11 + --> $DIR/empty-types.rs:396:11 | LL | match array_0_never { | ^^^^^^^^^^^^^ pattern `[]` not covered @@ -488,7 +488,7 @@ LL + [] => todo!() | error: unreachable pattern - --> $DIR/empty-types.rs:414:9 + --> $DIR/empty-types.rs:415:9 | LL | Some(_) => {} | ^^^^^^^------ @@ -499,7 +499,7 @@ LL | Some(_) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:419:9 + --> $DIR/empty-types.rs:420:9 | LL | Some(_a) => {} | ^^^^^^^^------ @@ -510,7 +510,7 @@ LL | Some(_a) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:424:9 + --> $DIR/empty-types.rs:425:9 | LL | None => {} | ---- matches all the relevant values @@ -519,7 +519,7 @@ LL | _ => {} | ^ no value can reach this error: unreachable pattern - --> $DIR/empty-types.rs:429:9 + --> $DIR/empty-types.rs:430:9 | LL | None => {} | ---- matches all the relevant values @@ -528,7 +528,7 @@ LL | _a => {} | ^^ no value can reach this error: unreachable pattern - --> $DIR/empty-types.rs:601:9 + --> $DIR/empty-types.rs:602:9 | LL | _ => {} | ^------ @@ -539,7 +539,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:604:9 + --> $DIR/empty-types.rs:605:9 | LL | _x => {} | ^^------ @@ -550,7 +550,7 @@ LL | _x => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:607:9 + --> $DIR/empty-types.rs:608:9 | LL | _ if false => {} | ^--------------- @@ -561,7 +561,7 @@ LL | _ if false => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:610:9 + --> $DIR/empty-types.rs:611:9 | LL | _x if false => {} | ^^--------------- diff --git a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr index 68a1bebf6b132..4dcbe6ce677f9 100644 --- a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr +++ b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr @@ -1,5 +1,5 @@ error: unreachable pattern - --> $DIR/empty-types.rs:47:9 + --> $DIR/empty-types.rs:48:9 | LL | _ => {} | ^------ @@ -9,13 +9,13 @@ LL | _ => {} | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here - --> $DIR/empty-types.rs:13:9 + --> $DIR/empty-types.rs:14:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/empty-types.rs:50:9 + --> $DIR/empty-types.rs:51:9 | LL | _x => {} | ^^------ @@ -26,7 +26,7 @@ LL | _x => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: type `&!` is non-empty - --> $DIR/empty-types.rs:54:11 + --> $DIR/empty-types.rs:55:11 | LL | match ref_never {} | ^^^^^^^^^ @@ -41,7 +41,7 @@ LL ~ } | error: unreachable pattern - --> $DIR/empty-types.rs:81:9 + --> $DIR/empty-types.rs:82:9 | LL | _ => {} | ^------ @@ -52,7 +52,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `Ok(_)` not covered - --> $DIR/empty-types.rs:85:11 + --> $DIR/empty-types.rs:86:11 | LL | match res_u32_never {} | ^^^^^^^^^^^^^ pattern `Ok(_)` not covered @@ -71,7 +71,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered - --> $DIR/empty-types.rs:94:11 + --> $DIR/empty-types.rs:95:11 | LL | match res_u32_never { | ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered @@ -89,7 +89,7 @@ LL ~ Ok(1_u32..=u32::MAX) => todo!() | error[E0005]: refutable pattern in local binding - --> $DIR/empty-types.rs:100:9 + --> $DIR/empty-types.rs:101:9 | LL | let Ok(_x) = res_u32_never.as_ref(); | ^^^^^^ pattern `Err(_)` not covered @@ -103,7 +103,7 @@ LL | let Ok(_x) = res_u32_never.as_ref() else { todo!() }; | ++++++++++++++++ error[E0005]: refutable pattern in local binding - --> $DIR/empty-types.rs:104:9 + --> $DIR/empty-types.rs:105:9 | LL | let Ok(_x) = &res_u32_never; | ^^^^^^ pattern `&Err(!)` not covered @@ -117,7 +117,7 @@ LL | let Ok(_x) = &res_u32_never else { todo!() }; | ++++++++++++++++ error: unreachable pattern - --> $DIR/empty-types.rs:130:13 + --> $DIR/empty-types.rs:131:13 | LL | _ => {} | ^------ @@ -128,7 +128,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:133:13 + --> $DIR/empty-types.rs:134:13 | LL | _ if false => {} | ^--------------- @@ -139,7 +139,7 @@ LL | _ if false => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `Some(!)` not covered - --> $DIR/empty-types.rs:154:15 + --> $DIR/empty-types.rs:155:15 | LL | match *ref_opt_void { | ^^^^^^^^^^^^^ pattern `Some(!)` not covered @@ -158,7 +158,7 @@ LL + Some(!) | error: unreachable pattern - --> $DIR/empty-types.rs:197:13 + --> $DIR/empty-types.rs:198:13 | LL | _ => {} | ^------ @@ -169,7 +169,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:202:13 + --> $DIR/empty-types.rs:203:13 | LL | _ => {} | ^------ @@ -180,7 +180,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:207:13 + --> $DIR/empty-types.rs:208:13 | LL | _ => {} | ^------ @@ -191,7 +191,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:212:13 + --> $DIR/empty-types.rs:213:13 | LL | _ => {} | ^------ @@ -202,7 +202,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:218:13 + --> $DIR/empty-types.rs:219:13 | LL | _ => {} | ^------ @@ -213,7 +213,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:279:9 + --> $DIR/empty-types.rs:280:9 | LL | _ => {} | ^------ @@ -224,7 +224,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0005]: refutable pattern in local binding - --> $DIR/empty-types.rs:295:13 + --> $DIR/empty-types.rs:296:13 | LL | let Ok(_) = *ptr_result_never_err; | ^^^^^ pattern `Err(!)` not covered @@ -238,7 +238,7 @@ LL | if let Ok(_) = *ptr_result_never_err { todo!() }; | ++ +++++++++++ error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty - --> $DIR/empty-types.rs:314:11 + --> $DIR/empty-types.rs:315:11 | LL | match *x {} | ^^ @@ -252,7 +252,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty - --> $DIR/empty-types.rs:316:11 + --> $DIR/empty-types.rs:317:11 | LL | match *x {} | ^^ @@ -266,7 +266,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: `Ok(!)` and `Err(!)` not covered - --> $DIR/empty-types.rs:318:11 + --> $DIR/empty-types.rs:319:11 | LL | match *x {} | ^^ patterns `Ok(!)` and `Err(!)` not covered @@ -288,7 +288,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty - --> $DIR/empty-types.rs:320:11 + --> $DIR/empty-types.rs:321:11 | LL | match *x {} | ^^ @@ -302,7 +302,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty - --> $DIR/empty-types.rs:325:11 + --> $DIR/empty-types.rs:326:11 | LL | match slice_never {} | ^^^^^^^^^^^ @@ -316,7 +316,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: `&[!, ..]` not covered - --> $DIR/empty-types.rs:327:11 + --> $DIR/empty-types.rs:328:11 | LL | match slice_never { | ^^^^^^^^^^^ pattern `&[!, ..]` not covered @@ -330,7 +330,7 @@ LL + &[!, ..] | error[E0004]: non-exhaustive patterns: `&[]`, `&[!]` and `&[!, !]` not covered - --> $DIR/empty-types.rs:336:11 + --> $DIR/empty-types.rs:337:11 | LL | match slice_never { | ^^^^^^^^^^^ patterns `&[]`, `&[!]` and `&[!, !]` not covered @@ -343,7 +343,7 @@ LL + &[] | &[!] | &[!, !] => todo!() | error[E0004]: non-exhaustive patterns: `&[]` and `&[!, ..]` not covered - --> $DIR/empty-types.rs:350:11 + --> $DIR/empty-types.rs:351:11 | LL | match slice_never { | ^^^^^^^^^^^ patterns `&[]` and `&[!, ..]` not covered @@ -357,7 +357,7 @@ LL + &[] | &[!, ..] => todo!() | error[E0004]: non-exhaustive patterns: type `[!]` is non-empty - --> $DIR/empty-types.rs:357:11 + --> $DIR/empty-types.rs:358:11 | LL | match *slice_never {} | ^^^^^^^^^^^^ @@ -371,7 +371,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty - --> $DIR/empty-types.rs:386:11 + --> $DIR/empty-types.rs:387:11 | LL | match array_0_never {} | ^^^^^^^^^^^^^ @@ -385,7 +385,7 @@ LL ~ } | error: unreachable pattern - --> $DIR/empty-types.rs:393:9 + --> $DIR/empty-types.rs:394:9 | LL | [] => {} | -- matches all the relevant values @@ -393,7 +393,7 @@ LL | _ => {} | ^ no value can reach this error[E0004]: non-exhaustive patterns: `[]` not covered - --> $DIR/empty-types.rs:395:11 + --> $DIR/empty-types.rs:396:11 | LL | match array_0_never { | ^^^^^^^^^^^^^ pattern `[]` not covered @@ -407,7 +407,7 @@ LL + [] => todo!() | error[E0004]: non-exhaustive patterns: `&Some(!)` not covered - --> $DIR/empty-types.rs:449:11 + --> $DIR/empty-types.rs:450:11 | LL | match ref_opt_never { | ^^^^^^^^^^^^^ pattern `&Some(!)` not covered @@ -426,7 +426,7 @@ LL + &Some(!) | error[E0004]: non-exhaustive patterns: `Some(!)` not covered - --> $DIR/empty-types.rs:490:11 + --> $DIR/empty-types.rs:491:11 | LL | match *ref_opt_never { | ^^^^^^^^^^^^^^ pattern `Some(!)` not covered @@ -445,7 +445,7 @@ LL + Some(!) | error[E0004]: non-exhaustive patterns: `Err(!)` not covered - --> $DIR/empty-types.rs:538:11 + --> $DIR/empty-types.rs:539:11 | LL | match *ref_res_never { | ^^^^^^^^^^^^^^ pattern `Err(!)` not covered @@ -464,7 +464,7 @@ LL + Err(!) | error[E0004]: non-exhaustive patterns: `Err(!)` not covered - --> $DIR/empty-types.rs:549:11 + --> $DIR/empty-types.rs:550:11 | LL | match *ref_res_never { | ^^^^^^^^^^^^^^ pattern `Err(!)` not covered @@ -483,7 +483,7 @@ LL + Err(!) | error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty - --> $DIR/empty-types.rs:568:11 + --> $DIR/empty-types.rs:569:11 | LL | match *ref_tuple_half_never {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -497,7 +497,7 @@ LL ~ } | error: unreachable pattern - --> $DIR/empty-types.rs:601:9 + --> $DIR/empty-types.rs:602:9 | LL | _ => {} | ^------ @@ -508,7 +508,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:604:9 + --> $DIR/empty-types.rs:605:9 | LL | _x => {} | ^^------ @@ -519,7 +519,7 @@ LL | _x => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:607:9 + --> $DIR/empty-types.rs:608:9 | LL | _ if false => {} | ^--------------- @@ -530,7 +530,7 @@ LL | _ if false => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:610:9 + --> $DIR/empty-types.rs:611:9 | LL | _x if false => {} | ^^--------------- @@ -541,7 +541,7 @@ LL | _x if false => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `&!` not covered - --> $DIR/empty-types.rs:635:11 + --> $DIR/empty-types.rs:636:11 | LL | match ref_never { | ^^^^^^^^^ pattern `&!` not covered @@ -557,7 +557,7 @@ LL + &! | error[E0004]: non-exhaustive patterns: `Ok(!)` not covered - --> $DIR/empty-types.rs:651:11 + --> $DIR/empty-types.rs:652:11 | LL | match *ref_result_never { | ^^^^^^^^^^^^^^^^^ pattern `Ok(!)` not covered @@ -577,7 +577,7 @@ LL + Ok(!) | error[E0004]: non-exhaustive patterns: `Some(!)` not covered - --> $DIR/empty-types.rs:671:11 + --> $DIR/empty-types.rs:672:11 | LL | match *x { | ^^ pattern `Some(!)` not covered diff --git a/tests/ui/pattern/usefulness/empty-types.normal.stderr b/tests/ui/pattern/usefulness/empty-types.normal.stderr index 320959534e522..a49050cedb4d0 100644 --- a/tests/ui/pattern/usefulness/empty-types.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-types.normal.stderr @@ -1,5 +1,5 @@ error: unreachable pattern - --> $DIR/empty-types.rs:47:9 + --> $DIR/empty-types.rs:48:9 | LL | _ => {} | ^------ @@ -9,13 +9,13 @@ LL | _ => {} | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here - --> $DIR/empty-types.rs:13:9 + --> $DIR/empty-types.rs:14:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/empty-types.rs:50:9 + --> $DIR/empty-types.rs:51:9 | LL | _x => {} | ^^------ @@ -26,7 +26,7 @@ LL | _x => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: type `&!` is non-empty - --> $DIR/empty-types.rs:54:11 + --> $DIR/empty-types.rs:55:11 | LL | match ref_never {} | ^^^^^^^^^ @@ -41,7 +41,7 @@ LL ~ } | error: unreachable pattern - --> $DIR/empty-types.rs:81:9 + --> $DIR/empty-types.rs:82:9 | LL | _ => {} | ^------ @@ -52,7 +52,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `Ok(_)` not covered - --> $DIR/empty-types.rs:85:11 + --> $DIR/empty-types.rs:86:11 | LL | match res_u32_never {} | ^^^^^^^^^^^^^ pattern `Ok(_)` not covered @@ -71,7 +71,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered - --> $DIR/empty-types.rs:94:11 + --> $DIR/empty-types.rs:95:11 | LL | match res_u32_never { | ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered @@ -89,7 +89,7 @@ LL ~ Ok(1_u32..=u32::MAX) => todo!() | error[E0005]: refutable pattern in local binding - --> $DIR/empty-types.rs:100:9 + --> $DIR/empty-types.rs:101:9 | LL | let Ok(_x) = res_u32_never.as_ref(); | ^^^^^^ pattern `Err(_)` not covered @@ -103,7 +103,7 @@ LL | let Ok(_x) = res_u32_never.as_ref() else { todo!() }; | ++++++++++++++++ error[E0005]: refutable pattern in local binding - --> $DIR/empty-types.rs:104:9 + --> $DIR/empty-types.rs:105:9 | LL | let Ok(_x) = &res_u32_never; | ^^^^^^ pattern `&Err(_)` not covered @@ -117,7 +117,7 @@ LL | let Ok(_x) = &res_u32_never else { todo!() }; | ++++++++++++++++ error: unreachable pattern - --> $DIR/empty-types.rs:130:13 + --> $DIR/empty-types.rs:131:13 | LL | _ => {} | ^------ @@ -128,7 +128,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:133:13 + --> $DIR/empty-types.rs:134:13 | LL | _ if false => {} | ^--------------- @@ -139,7 +139,7 @@ LL | _ if false => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `Some(_)` not covered - --> $DIR/empty-types.rs:154:15 + --> $DIR/empty-types.rs:155:15 | LL | match *ref_opt_void { | ^^^^^^^^^^^^^ pattern `Some(_)` not covered @@ -158,7 +158,7 @@ LL + Some(_) => todo!() | error: unreachable pattern - --> $DIR/empty-types.rs:197:13 + --> $DIR/empty-types.rs:198:13 | LL | _ => {} | ^------ @@ -169,7 +169,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:202:13 + --> $DIR/empty-types.rs:203:13 | LL | _ => {} | ^------ @@ -180,7 +180,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:207:13 + --> $DIR/empty-types.rs:208:13 | LL | _ => {} | ^------ @@ -191,7 +191,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:212:13 + --> $DIR/empty-types.rs:213:13 | LL | _ => {} | ^------ @@ -202,7 +202,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:218:13 + --> $DIR/empty-types.rs:219:13 | LL | _ => {} | ^------ @@ -213,7 +213,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:279:9 + --> $DIR/empty-types.rs:280:9 | LL | _ => {} | ^------ @@ -224,7 +224,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0005]: refutable pattern in local binding - --> $DIR/empty-types.rs:295:13 + --> $DIR/empty-types.rs:296:13 | LL | let Ok(_) = *ptr_result_never_err; | ^^^^^ pattern `Err(_)` not covered @@ -238,7 +238,7 @@ LL | if let Ok(_) = *ptr_result_never_err { todo!() }; | ++ +++++++++++ error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty - --> $DIR/empty-types.rs:314:11 + --> $DIR/empty-types.rs:315:11 | LL | match *x {} | ^^ @@ -252,7 +252,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty - --> $DIR/empty-types.rs:316:11 + --> $DIR/empty-types.rs:317:11 | LL | match *x {} | ^^ @@ -266,7 +266,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered - --> $DIR/empty-types.rs:318:11 + --> $DIR/empty-types.rs:319:11 | LL | match *x {} | ^^ patterns `Ok(_)` and `Err(_)` not covered @@ -288,7 +288,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty - --> $DIR/empty-types.rs:320:11 + --> $DIR/empty-types.rs:321:11 | LL | match *x {} | ^^ @@ -302,7 +302,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty - --> $DIR/empty-types.rs:325:11 + --> $DIR/empty-types.rs:326:11 | LL | match slice_never {} | ^^^^^^^^^^^ @@ -316,7 +316,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered - --> $DIR/empty-types.rs:327:11 + --> $DIR/empty-types.rs:328:11 | LL | match slice_never { | ^^^^^^^^^^^ pattern `&[_, ..]` not covered @@ -330,7 +330,7 @@ LL + &[_, ..] => todo!() | error[E0004]: non-exhaustive patterns: `&[]`, `&[_]` and `&[_, _]` not covered - --> $DIR/empty-types.rs:336:11 + --> $DIR/empty-types.rs:337:11 | LL | match slice_never { | ^^^^^^^^^^^ patterns `&[]`, `&[_]` and `&[_, _]` not covered @@ -343,7 +343,7 @@ LL + &[] | &[_] | &[_, _] => todo!() | error[E0004]: non-exhaustive patterns: `&[]` and `&[_, ..]` not covered - --> $DIR/empty-types.rs:350:11 + --> $DIR/empty-types.rs:351:11 | LL | match slice_never { | ^^^^^^^^^^^ patterns `&[]` and `&[_, ..]` not covered @@ -357,7 +357,7 @@ LL + &[] | &[_, ..] => todo!() | error[E0004]: non-exhaustive patterns: type `[!]` is non-empty - --> $DIR/empty-types.rs:357:11 + --> $DIR/empty-types.rs:358:11 | LL | match *slice_never {} | ^^^^^^^^^^^^ @@ -371,7 +371,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty - --> $DIR/empty-types.rs:386:11 + --> $DIR/empty-types.rs:387:11 | LL | match array_0_never {} | ^^^^^^^^^^^^^ @@ -385,7 +385,7 @@ LL ~ } | error: unreachable pattern - --> $DIR/empty-types.rs:393:9 + --> $DIR/empty-types.rs:394:9 | LL | [] => {} | -- matches all the relevant values @@ -393,7 +393,7 @@ LL | _ => {} | ^ no value can reach this error[E0004]: non-exhaustive patterns: `[]` not covered - --> $DIR/empty-types.rs:395:11 + --> $DIR/empty-types.rs:396:11 | LL | match array_0_never { | ^^^^^^^^^^^^^ pattern `[]` not covered @@ -407,7 +407,7 @@ LL + [] => todo!() | error[E0004]: non-exhaustive patterns: `&Some(_)` not covered - --> $DIR/empty-types.rs:449:11 + --> $DIR/empty-types.rs:450:11 | LL | match ref_opt_never { | ^^^^^^^^^^^^^ pattern `&Some(_)` not covered @@ -426,7 +426,7 @@ LL + &Some(_) => todo!() | error[E0004]: non-exhaustive patterns: `Some(_)` not covered - --> $DIR/empty-types.rs:490:11 + --> $DIR/empty-types.rs:491:11 | LL | match *ref_opt_never { | ^^^^^^^^^^^^^^ pattern `Some(_)` not covered @@ -445,7 +445,7 @@ LL + Some(_) => todo!() | error[E0004]: non-exhaustive patterns: `Err(_)` not covered - --> $DIR/empty-types.rs:538:11 + --> $DIR/empty-types.rs:539:11 | LL | match *ref_res_never { | ^^^^^^^^^^^^^^ pattern `Err(_)` not covered @@ -464,7 +464,7 @@ LL + Err(_) => todo!() | error[E0004]: non-exhaustive patterns: `Err(_)` not covered - --> $DIR/empty-types.rs:549:11 + --> $DIR/empty-types.rs:550:11 | LL | match *ref_res_never { | ^^^^^^^^^^^^^^ pattern `Err(_)` not covered @@ -483,7 +483,7 @@ LL + Err(_) => todo!() | error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty - --> $DIR/empty-types.rs:568:11 + --> $DIR/empty-types.rs:569:11 | LL | match *ref_tuple_half_never {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -497,7 +497,7 @@ LL ~ } | error: unreachable pattern - --> $DIR/empty-types.rs:601:9 + --> $DIR/empty-types.rs:602:9 | LL | _ => {} | ^------ @@ -508,7 +508,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:604:9 + --> $DIR/empty-types.rs:605:9 | LL | _x => {} | ^^------ @@ -519,7 +519,7 @@ LL | _x => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:607:9 + --> $DIR/empty-types.rs:608:9 | LL | _ if false => {} | ^--------------- @@ -530,7 +530,7 @@ LL | _ if false => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:610:9 + --> $DIR/empty-types.rs:611:9 | LL | _x if false => {} | ^^--------------- @@ -541,7 +541,7 @@ LL | _x if false => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `&_` not covered - --> $DIR/empty-types.rs:635:11 + --> $DIR/empty-types.rs:636:11 | LL | match ref_never { | ^^^^^^^^^ pattern `&_` not covered @@ -557,7 +557,7 @@ LL + &_ => todo!() | error[E0004]: non-exhaustive patterns: `Ok(_)` not covered - --> $DIR/empty-types.rs:651:11 + --> $DIR/empty-types.rs:652:11 | LL | match *ref_result_never { | ^^^^^^^^^^^^^^^^^ pattern `Ok(_)` not covered @@ -577,7 +577,7 @@ LL + Ok(_) => todo!() | error[E0004]: non-exhaustive patterns: `Some(_)` not covered - --> $DIR/empty-types.rs:671:11 + --> $DIR/empty-types.rs:672:11 | LL | match *x { | ^^ pattern `Some(_)` not covered diff --git a/tests/ui/pattern/usefulness/empty-types.rs b/tests/ui/pattern/usefulness/empty-types.rs index d4fdb7c1dd46a..cb0f1813e915b 100644 --- a/tests/ui/pattern/usefulness/empty-types.rs +++ b/tests/ui/pattern/usefulness/empty-types.rs @@ -1,5 +1,6 @@ //@ revisions: normal exhaustive_patterns never_pats //@ edition: 2024 +//@ ignore-parallel-frontend pattern matching error message mismatch // // This tests correct handling of empty types in exhaustiveness checking. // From ec46eac2ad32dfb7387a37a5f8ddb1077d81412b Mon Sep 17 00:00:00 2001 From: Kjetil Kjeka Date: Thu, 28 May 2026 15:30:58 +0200 Subject: [PATCH 24/26] NVPTX: Remove the deprecated ptx linker flavor --- compiler/rustc_codegen_ssa/src/back/link.rs | 4 - compiler/rustc_codegen_ssa/src/back/linker.rs | 79 ------------------- compiler/rustc_target/src/spec/mod.rs | 38 +++------ .../src/spec/targets/nvptx64_nvidia_cuda.rs | 1 - .../src/compiler-flags/codegen-options.md | 2 - src/tools/compiletest/src/runtest/assembly.rs | 3 +- tests/assembly-llvm/nvptx-arch-default.rs | 4 +- tests/assembly-llvm/nvptx-arch-emit-asm.rs | 2 +- tests/assembly-llvm/nvptx-arch-link-arg.rs | 13 --- tests/assembly-llvm/nvptx-arch-target-cpu.rs | 2 +- tests/assembly-llvm/nvptx-atomics.rs | 2 +- tests/assembly-llvm/nvptx-c-abi-arg-v7.rs | 2 +- tests/assembly-llvm/nvptx-c-abi-ret-v7.rs | 2 +- tests/assembly-llvm/nvptx-internalizing.rs | 3 +- .../nvptx-kernel-args-abi-v7.rs | 2 +- tests/assembly-llvm/nvptx-linking-binary.rs | 2 +- tests/assembly-llvm/nvptx-linking-cdylib.rs | 2 +- tests/assembly-llvm/nvptx-safe-naming.rs | 2 +- .../linkage-attr/unstable-flavor.llbc.stderr | 2 + .../linkage-attr/unstable-flavor.ptx.stderr | 2 - tests/ui/linkage-attr/unstable-flavor.rs | 8 +- .../target-feature/implied-features-nvptx.rs | 4 +- 22 files changed, 31 insertions(+), 150 deletions(-) delete mode 100644 tests/assembly-llvm/nvptx-arch-link-arg.rs create mode 100644 tests/ui/linkage-attr/unstable-flavor.llbc.stderr delete mode 100644 tests/ui/linkage-attr/unstable-flavor.ptx.stderr diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index d2c82280ad2ab..532f2d6d6af09 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1530,7 +1530,6 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { } LinkerFlavor::Bpf => "bpf-linker", LinkerFlavor::Llbc => "llvm-bitcode-linker", - LinkerFlavor::Ptx => "rust-ptx-linker", }), flavor, )), @@ -1571,7 +1570,6 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { let linker_flavor = match sess.opts.cg.linker_flavor { // The linker flavors that are non-target specific can be directly translated to LinkerFlavor Some(LinkerFlavorCli::Llbc) => Some(LinkerFlavor::Llbc), - Some(LinkerFlavorCli::Ptx) => Some(LinkerFlavor::Ptx), // The linker flavors that corresponds to targets needs logic that keeps the base LinkerFlavor linker_flavor => { linker_flavor.map(|flavor| sess.target.linker_flavor.with_cli_hints(flavor)) @@ -2764,8 +2762,6 @@ fn add_order_independent_options( if crate_info.target_features.len() > 0 { cmd.link_arg(&format!("--target-feature={}", &crate_info.target_features.join(","))); } - } else if flavor == LinkerFlavor::Ptx { - cmd.link_args(&["--fallback-arch", &crate_info.target_cpu]); } else if flavor == LinkerFlavor::Bpf { cmd.link_args(&["--cpu", &crate_info.target_cpu]); if let Some(feat) = [sess.opts.cg.target_feature.as_str(), &sess.target.options.features] diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 2155f94a7cfd3..d40340e4d8c09 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -161,7 +161,6 @@ pub(crate) fn get_linker<'a>( LinkerFlavor::EmCc => Box::new(EmLinker { cmd, sess }) as Box, LinkerFlavor::Bpf => Box::new(BpfLinker { cmd, sess }) as Box, LinkerFlavor::Llbc => Box::new(LlbcLinker { cmd, sess }) as Box, - LinkerFlavor::Ptx => Box::new(PtxLinker { cmd, sess }) as Box, } } @@ -283,7 +282,6 @@ generate_arg_methods! { L4Bender<'_> AixLinker<'_> LlbcLinker<'_> - PtxLinker<'_> BpfLinker<'_> dyn Linker + '_ } @@ -1920,83 +1918,6 @@ pub(crate) fn linked_symbols( symbols } -/// Much simplified and explicit CLI for the NVPTX linker. The linker operates -/// with bitcode and uses LLVM backend to generate a PTX assembly. -struct PtxLinker<'a> { - cmd: Command, - sess: &'a Session, -} - -impl<'a> Linker for PtxLinker<'a> { - fn cmd(&mut self) -> &mut Command { - &mut self.cmd - } - - fn set_output_kind( - &mut self, - _output_kind: LinkOutputKind, - _crate_type: CrateType, - _out_filename: &Path, - ) { - } - - fn link_staticlib_by_name(&mut self, _name: &str, _verbatim: bool, _whole_archive: bool) { - panic!("staticlibs not supported") - } - - fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) { - self.link_arg("--rlib").link_arg(path); - } - - fn debuginfo(&mut self, _strip: Strip, _: &[PathBuf]) { - self.link_arg("--debug"); - } - - fn add_object(&mut self, path: &Path) { - self.link_arg("--bitcode").link_arg(path); - } - - fn optimize(&mut self) { - match self.sess.lto() { - Lto::Thin | Lto::Fat | Lto::ThinLocal => { - self.link_arg("-Olto"); - } - - Lto::No => {} - } - } - - fn full_relro(&mut self) {} - - fn partial_relro(&mut self) {} - - fn no_relro(&mut self) {} - - fn gc_sections(&mut self, _keep_metadata: bool) {} - - fn pgo_gen(&mut self) {} - - fn no_crt_objects(&mut self) {} - - fn no_default_libraries(&mut self) {} - - fn control_flow_guard(&mut self) {} - - fn ehcont_guard(&mut self) {} - - fn export_symbols( - &mut self, - _tmpdir: &Path, - _crate_type: CrateType, - _symbols: &[(String, SymbolExportKind)], - ) { - } - - fn windows_subsystem(&mut self, _subsystem: WindowsSubsystemKind) {} - - fn linker_plugin_lto(&mut self) {} -} - /// The `self-contained` LLVM bitcode linker struct LlbcLinker<'a> { cmd: Command, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index d6a9e27c46553..37cddf56bcd30 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -132,8 +132,6 @@ pub enum LinkerFlavor { // Below: other linker-like tools with unique interfaces for exotic targets. /// Linker tool for BPF. Bpf, - /// Linker tool for Nvidia PTX. - Ptx, /// LLVM bitcode linker that can be used as a `self-contained` linker Llbc, } @@ -153,7 +151,6 @@ pub enum LinkerFlavorCli { Msvc(Lld), EmCc, Bpf, - Ptx, Llbc, // Legacy stable values @@ -174,8 +171,7 @@ impl LinkerFlavorCli { | LinkerFlavorCli::Msvc(Lld::Yes) | LinkerFlavorCli::EmCc | LinkerFlavorCli::Bpf - | LinkerFlavorCli::Llbc - | LinkerFlavorCli::Ptx => true, + | LinkerFlavorCli::Llbc => true, LinkerFlavorCli::Gcc | LinkerFlavorCli::Ld | LinkerFlavorCli::Lld(..) @@ -211,7 +207,6 @@ impl LinkerFlavor { LinkerFlavorCli::EmCc => LinkerFlavor::EmCc, LinkerFlavorCli::Bpf => LinkerFlavor::Bpf, LinkerFlavorCli::Llbc => LinkerFlavor::Llbc, - LinkerFlavorCli::Ptx => LinkerFlavor::Ptx, // Below: legacy stable values LinkerFlavorCli::Gcc => match lld_flavor { @@ -251,7 +246,6 @@ impl LinkerFlavor { LinkerFlavor::EmCc => LinkerFlavorCli::Em, LinkerFlavor::Bpf => LinkerFlavorCli::Bpf, LinkerFlavor::Llbc => LinkerFlavorCli::Llbc, - LinkerFlavor::Ptx => LinkerFlavorCli::Ptx, } } @@ -266,7 +260,6 @@ impl LinkerFlavor { LinkerFlavor::EmCc => LinkerFlavorCli::EmCc, LinkerFlavor::Bpf => LinkerFlavorCli::Bpf, LinkerFlavor::Llbc => LinkerFlavorCli::Llbc, - LinkerFlavor::Ptx => LinkerFlavorCli::Ptx, } } @@ -279,7 +272,7 @@ impl LinkerFlavor { LinkerFlavorCli::Unix(cc) => (Some(cc), None), LinkerFlavorCli::Msvc(lld) => (Some(Cc::No), Some(lld)), LinkerFlavorCli::EmCc => (Some(Cc::Yes), Some(Lld::Yes)), - LinkerFlavorCli::Bpf | LinkerFlavorCli::Ptx => (None, None), + LinkerFlavorCli::Bpf => (None, None), LinkerFlavorCli::Llbc => (None, None), // Below: legacy stable values @@ -336,7 +329,7 @@ impl LinkerFlavor { LinkerFlavor::WasmLld(cc) => LinkerFlavor::WasmLld(cc_hint.unwrap_or(cc)), LinkerFlavor::Unix(cc) => LinkerFlavor::Unix(cc_hint.unwrap_or(cc)), LinkerFlavor::Msvc(lld) => LinkerFlavor::Msvc(lld_hint.unwrap_or(lld)), - LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Llbc | LinkerFlavor::Ptx => self, + LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Llbc => self, } } @@ -355,7 +348,7 @@ impl LinkerFlavor { let compatible = |cli| { // The CLI flavor should be compatible with the target if: match (self, cli) { - // 1. they are counterparts: they have the same principal flavor. + // they are counterparts: they have the same principal flavor. (LinkerFlavor::Gnu(..), LinkerFlavorCli::Gnu(..)) | (LinkerFlavor::Darwin(..), LinkerFlavorCli::Darwin(..)) | (LinkerFlavor::WasmLld(..), LinkerFlavorCli::WasmLld(..)) @@ -363,10 +356,7 @@ impl LinkerFlavor { | (LinkerFlavor::Msvc(..), LinkerFlavorCli::Msvc(..)) | (LinkerFlavor::EmCc, LinkerFlavorCli::EmCc) | (LinkerFlavor::Bpf, LinkerFlavorCli::Bpf) - | (LinkerFlavor::Llbc, LinkerFlavorCli::Llbc) - | (LinkerFlavor::Ptx, LinkerFlavorCli::Ptx) => return true, - // 2. The linker flavor is independent of target and compatible - (LinkerFlavor::Ptx, LinkerFlavorCli::Llbc) => return true, + | (LinkerFlavor::Llbc, LinkerFlavorCli::Llbc) => return true, _ => {} } @@ -389,8 +379,7 @@ impl LinkerFlavor { | LinkerFlavor::Unix(..) | LinkerFlavor::EmCc | LinkerFlavor::Bpf - | LinkerFlavor::Llbc - | LinkerFlavor::Ptx => LldFlavor::Ld, + | LinkerFlavor::Llbc => LldFlavor::Ld, LinkerFlavor::Darwin(..) => LldFlavor::Ld64, LinkerFlavor::WasmLld(..) => LldFlavor::Wasm, LinkerFlavor::Msvc(..) => LldFlavor::Link, @@ -415,8 +404,7 @@ impl LinkerFlavor { | LinkerFlavor::Msvc(_) | LinkerFlavor::Unix(_) | LinkerFlavor::Bpf - | LinkerFlavor::Llbc - | LinkerFlavor::Ptx => false, + | LinkerFlavor::Llbc => false, } } @@ -435,8 +423,7 @@ impl LinkerFlavor { | LinkerFlavor::Msvc(_) | LinkerFlavor::Unix(_) | LinkerFlavor::Bpf - | LinkerFlavor::Llbc - | LinkerFlavor::Ptx => false, + | LinkerFlavor::Llbc => false, } } @@ -512,7 +499,6 @@ linker_flavor_cli_impls! { (LinkerFlavorCli::EmCc) "em-cc" (LinkerFlavorCli::Bpf) "bpf" (LinkerFlavorCli::Llbc) "llbc" - (LinkerFlavorCli::Ptx) "ptx" // Legacy stable flavors (LinkerFlavorCli::Gcc) "gcc" @@ -2740,8 +2726,7 @@ fn add_link_args_iter( | LinkerFlavor::Unix(..) | LinkerFlavor::EmCc | LinkerFlavor::Bpf - | LinkerFlavor::Llbc - | LinkerFlavor::Ptx => {} + | LinkerFlavor::Llbc => {} } } @@ -3127,10 +3112,7 @@ impl Target { "mixing MSVC and non-MSVC linker flavors" ); } - LinkerFlavor::EmCc - | LinkerFlavor::Bpf - | LinkerFlavor::Ptx - | LinkerFlavor::Llbc => { + LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Llbc => { check_eq!(flavor, self.linker_flavor, "mixing different linker flavors") } } diff --git a/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs b/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs index d8a0bd50ee204..b74aca48bb9ec 100644 --- a/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs +++ b/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs @@ -21,7 +21,6 @@ pub(crate) fn target() -> Target { vendor: "nvidia".into(), linker_flavor: LinkerFlavor::Llbc, - // With `ptx-linker` approach, it can be later overridden via link flags. cpu: "sm_70".into(), // No longer supported architectures diff --git a/src/doc/unstable-book/src/compiler-flags/codegen-options.md b/src/doc/unstable-book/src/compiler-flags/codegen-options.md index f927e5c439c66..efde41040184a 100644 --- a/src/doc/unstable-book/src/compiler-flags/codegen-options.md +++ b/src/doc/unstable-book/src/compiler-flags/codegen-options.md @@ -7,8 +7,6 @@ unstable-options` to be accepted. ## linker-flavor In addition to the stable set of linker flavors, the following unstable values also exist: -- `ptx`: use [`rust-ptx-linker`](https://github.com/denzp/rust-ptx-linker) - for Nvidia NVPTX GPGPU support. - `bpf`: use [`bpf-linker`](https://github.com/alessandrod/bpf-linker) for eBPF support. - `llbc`: for linking in llvm bitcode. Install the preview rustup components`llvm-bitcode-linker` and `llvm-tools` to use as a self-contained linker by passing diff --git a/src/tools/compiletest/src/runtest/assembly.rs b/src/tools/compiletest/src/runtest/assembly.rs index 0d41c29075c43..be2430f006a54 100644 --- a/src/tools/compiletest/src/runtest/assembly.rs +++ b/src/tools/compiletest/src/runtest/assembly.rs @@ -23,7 +23,7 @@ impl TestCx<'_> { fn compile_test_and_save_assembly(&self) -> (ProcRes, Utf8PathBuf) { // This works with both `--emit asm` (as default output name for the assembly) - // and `ptx-linker` because the latter can write output at requested location. + // and `llvm-bitcode-linker` because the latter can write output at requested location. let output_path = self.output_base_name().with_extension("s"); let input_file = &self.testpaths.file; @@ -31,7 +31,6 @@ impl TestCx<'_> { let emit = match self.props.assembly_output.as_deref() { Some("emit-asm") => Emit::Asm, Some("bpf-linker") => Emit::LinkArgsAsm, - Some("ptx-linker") => Emit::None, // No extra flags needed. Some(other) => self.fatal(&format!("unknown 'assembly-output' directive: {other}")), None => self.fatal("missing 'assembly-output' directive"), }; diff --git a/tests/assembly-llvm/nvptx-arch-default.rs b/tests/assembly-llvm/nvptx-arch-default.rs index e71304e453303..a0c2b5387275d 100644 --- a/tests/assembly-llvm/nvptx-arch-default.rs +++ b/tests/assembly-llvm/nvptx-arch-default.rs @@ -1,4 +1,4 @@ -//@ assembly-output: ptx-linker +//@ assembly-output: emit-asm //@ compile-flags: --crate-type cdylib //@ only-nvptx64 @@ -7,7 +7,7 @@ //@ aux-build: breakpoint-panic-handler.rs extern crate breakpoint_panic_handler; -// Verify default target arch with ptx-linker. +// Verify default arch with llvm-bitcode-linker. // CHECK: .version 7.0 // CHECK: .target sm_70 // CHECK: .address_size 64 diff --git a/tests/assembly-llvm/nvptx-arch-emit-asm.rs b/tests/assembly-llvm/nvptx-arch-emit-asm.rs index 9266309c6202e..135149679a4d1 100644 --- a/tests/assembly-llvm/nvptx-arch-emit-asm.rs +++ b/tests/assembly-llvm/nvptx-arch-emit-asm.rs @@ -4,7 +4,7 @@ #![no_std] -// Verify default arch without ptx-linker involved. +// Verify default arch without llvm-bitcode-linker involved. // CHECK: .version 7.0 // CHECK: .target sm_70 // CHECK: .address_size 64 diff --git a/tests/assembly-llvm/nvptx-arch-link-arg.rs b/tests/assembly-llvm/nvptx-arch-link-arg.rs deleted file mode 100644 index 3432e6161bf14..0000000000000 --- a/tests/assembly-llvm/nvptx-arch-link-arg.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ assembly-output: ptx-linker -//@ compile-flags: --crate-type cdylib -C link-arg=--arch=sm_60 -//@ only-nvptx64 -//@ ignore-nvptx64 - -#![no_std] - -//@ aux-build: breakpoint-panic-handler.rs -extern crate breakpoint_panic_handler; - -// Verify target arch override via `link-arg`. -// CHECK: .target sm_60 -// CHECK: .address_size 64 diff --git a/tests/assembly-llvm/nvptx-arch-target-cpu.rs b/tests/assembly-llvm/nvptx-arch-target-cpu.rs index b5062f1ba20d7..8e1ef9b13fa40 100644 --- a/tests/assembly-llvm/nvptx-arch-target-cpu.rs +++ b/tests/assembly-llvm/nvptx-arch-target-cpu.rs @@ -1,4 +1,4 @@ -//@ assembly-output: ptx-linker +//@ assembly-output: emit-asm //@ compile-flags: --crate-type cdylib -C target-cpu=sm_87 //@ only-nvptx64 diff --git a/tests/assembly-llvm/nvptx-atomics.rs b/tests/assembly-llvm/nvptx-atomics.rs index 52b8c86d8a9c1..5895a731167c6 100644 --- a/tests/assembly-llvm/nvptx-atomics.rs +++ b/tests/assembly-llvm/nvptx-atomics.rs @@ -1,4 +1,4 @@ -//@ assembly-output: ptx-linker +//@ assembly-output: emit-asm //@ compile-flags: --crate-type cdylib //@ only-nvptx64 //@ ignore-nvptx64 diff --git a/tests/assembly-llvm/nvptx-c-abi-arg-v7.rs b/tests/assembly-llvm/nvptx-c-abi-arg-v7.rs index 6f5ef792e9b34..2f27988ba3743 100644 --- a/tests/assembly-llvm/nvptx-c-abi-arg-v7.rs +++ b/tests/assembly-llvm/nvptx-c-abi-arg-v7.rs @@ -1,4 +1,4 @@ -//@ assembly-output: ptx-linker +//@ assembly-output: emit-asm //@ compile-flags: --crate-type cdylib -C target-cpu=sm_86 //@ only-nvptx64 diff --git a/tests/assembly-llvm/nvptx-c-abi-ret-v7.rs b/tests/assembly-llvm/nvptx-c-abi-ret-v7.rs index 02ec9facee7a8..e7db3108952b1 100644 --- a/tests/assembly-llvm/nvptx-c-abi-ret-v7.rs +++ b/tests/assembly-llvm/nvptx-c-abi-ret-v7.rs @@ -1,4 +1,4 @@ -//@ assembly-output: ptx-linker +//@ assembly-output: emit-asm //@ compile-flags: --crate-type cdylib -C target-cpu=sm_86 //@ only-nvptx64 diff --git a/tests/assembly-llvm/nvptx-internalizing.rs b/tests/assembly-llvm/nvptx-internalizing.rs index 0acfd5c244319..b671c876e23a2 100644 --- a/tests/assembly-llvm/nvptx-internalizing.rs +++ b/tests/assembly-llvm/nvptx-internalizing.rs @@ -1,7 +1,6 @@ -//@ assembly-output: ptx-linker +//@ assembly-output: emit-asm //@ compile-flags: --crate-type cdylib //@ only-nvptx64 -//@ ignore-nvptx64 #![feature(abi_ptx)] #![no_std] diff --git a/tests/assembly-llvm/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs b/tests/assembly-llvm/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs index 00f6fe9332d94..cb88cfd33ee58 100644 --- a/tests/assembly-llvm/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs +++ b/tests/assembly-llvm/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs @@ -1,4 +1,4 @@ -//@ assembly-output: ptx-linker +//@ assembly-output: emit-asm //@ compile-flags: --crate-type cdylib -C target-cpu=sm_86 //@ only-nvptx64 diff --git a/tests/assembly-llvm/nvptx-linking-binary.rs b/tests/assembly-llvm/nvptx-linking-binary.rs index 3b50b472ab10e..4ec9c4a0af0bf 100644 --- a/tests/assembly-llvm/nvptx-linking-binary.rs +++ b/tests/assembly-llvm/nvptx-linking-binary.rs @@ -1,4 +1,4 @@ -//@ assembly-output: ptx-linker +//@ assembly-output: emit-asm //@ compile-flags: --crate-type bin //@ only-nvptx64 //@ ignore-nvptx64 diff --git a/tests/assembly-llvm/nvptx-linking-cdylib.rs b/tests/assembly-llvm/nvptx-linking-cdylib.rs index 9742e26fb31a9..82bca1f6c1699 100644 --- a/tests/assembly-llvm/nvptx-linking-cdylib.rs +++ b/tests/assembly-llvm/nvptx-linking-cdylib.rs @@ -1,4 +1,4 @@ -//@ assembly-output: ptx-linker +//@ assembly-output: emit-asm //@ compile-flags: --crate-type cdylib //@ only-nvptx64 //@ ignore-nvptx64 diff --git a/tests/assembly-llvm/nvptx-safe-naming.rs b/tests/assembly-llvm/nvptx-safe-naming.rs index 050c3fb9d93b6..69bf71b9a7821 100644 --- a/tests/assembly-llvm/nvptx-safe-naming.rs +++ b/tests/assembly-llvm/nvptx-safe-naming.rs @@ -1,4 +1,4 @@ -//@ assembly-output: ptx-linker +//@ assembly-output: emit-asm //@ compile-flags: --crate-type cdylib //@ only-nvptx64 diff --git a/tests/ui/linkage-attr/unstable-flavor.llbc.stderr b/tests/ui/linkage-attr/unstable-flavor.llbc.stderr new file mode 100644 index 0000000000000..796daa4c4e8c2 --- /dev/null +++ b/tests/ui/linkage-attr/unstable-flavor.llbc.stderr @@ -0,0 +1,2 @@ +error: the linker flavor `llbc` is unstable, the `-Z unstable-options` flag must also be passed to use the unstable values + diff --git a/tests/ui/linkage-attr/unstable-flavor.ptx.stderr b/tests/ui/linkage-attr/unstable-flavor.ptx.stderr deleted file mode 100644 index 2ebdc1a903399..0000000000000 --- a/tests/ui/linkage-attr/unstable-flavor.ptx.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: the linker flavor `ptx` is unstable, the `-Z unstable-options` flag must also be passed to use the unstable values - diff --git a/tests/ui/linkage-attr/unstable-flavor.rs b/tests/ui/linkage-attr/unstable-flavor.rs index 5412e248f341f..adb34a9a80cd8 100644 --- a/tests/ui/linkage-attr/unstable-flavor.rs +++ b/tests/ui/linkage-attr/unstable-flavor.rs @@ -2,14 +2,14 @@ // unique codepath checking all unstable options (see `LinkerFlavorCli::is_unstable` and its // caller). If it passes, all the other unstable options are rejected as well. // -//@ revisions: bpf ptx +//@ revisions: bpf llbc //@ [bpf] compile-flags: --target=bpfel-unknown-none -C linker-flavor=bpf --crate-type=rlib //@ [bpf] needs-llvm-components: bpf -//@ [ptx] compile-flags: --target=nvptx64-nvidia-cuda -C linker-flavor=ptx --crate-type=rlib -//@ [ptx] needs-llvm-components: nvptx +//@ [llbc] compile-flags: --target=nvptx64-nvidia-cuda -C linker-flavor=llbc --crate-type=rlib +//@ [llbc] needs-llvm-components: nvptx #![feature(no_core)] #![no_core] //[bpf]~? ERROR the linker flavor `bpf` is unstable -//[ptx]~? ERROR the linker flavor `ptx` is unstable +//[llbc]~? ERROR the linker flavor `llbc` is unstable diff --git a/tests/ui/target-feature/implied-features-nvptx.rs b/tests/ui/target-feature/implied-features-nvptx.rs index 1550c99f67a8d..a51c22afaf956 100644 --- a/tests/ui/target-feature/implied-features-nvptx.rs +++ b/tests/ui/target-feature/implied-features-nvptx.rs @@ -1,5 +1,5 @@ -//@ assembly-output: ptx-linker -//@ compile-flags: --crate-type cdylib -C target-cpu=sm_80 -Z unstable-options -Clinker-flavor=llbc +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type cdylib -C target-cpu=sm_80 //@ only-nvptx64 //@ build-pass #![no_std] From 2c0f9de513810839717ddb5257a298928995cc04 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 29 May 2026 13:48:33 +0200 Subject: [PATCH 25/26] add ABI check logic for wasm --- compiler/rustc_target/src/spec/mod.rs | 13 +++++++++++++ compiler/rustc_target/src/target_features.rs | 6 ++++++ 2 files changed, 19 insertions(+) diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index d6a9e27c46553..0dd2c11e6ff81 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -3582,6 +3582,19 @@ impl Target { "invalid `target_abi` for CSky" ); } + Arch::Wasm32 | Arch::Wasm64 => { + check!( + self.llvm_abiname == LlvmAbi::Unspecified, + "`llvm_abiname` is unused on wasm" + ); + check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on wasm"); + check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on wasm"); + check_matches!( + self.cfg_abi, + CfgAbi::Unspecified | CfgAbi::Other(_), + "invalid `target_abi` for wasm" + ); + } ref arch => { check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on {arch}"); // Ensure consistency among built-in targets, but give JSON targets the opportunity diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index b009c42eb2302..c27cdc9bf2e9a 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -1312,11 +1312,17 @@ impl Target { } } Arch::Avr => { + // We only support one ABI on AVR at the moment. // SRAM is minimum requirement for C/C++ in both avr-gcc and Clang, // and backends of them only support assembly for devices have no SRAM. // See the discussion in https://github.com/rust-lang/rust/pull/146900 for more. FeatureConstraints { required: &["sram"], incompatible: &[] } } + Arch::Wasm32 | Arch::Wasm64 => { + // We only support one ABI on wasm at the moment. + // No ABI-relevant target features have been identified thus far. + NOTHING + } _ => NOTHING, } } From 77672953f8004c4bafd7fbde676d54392e22e98f Mon Sep 17 00:00:00 2001 From: aerooneqq Date: Fri, 29 May 2026 15:51:45 +0300 Subject: [PATCH 26/26] Remove DefPathTable, use `LocalDefId` instead of `DefIndex` where possible --- compiler/rustc_ast_lowering/src/lib.rs | 2 +- compiler/rustc_hir/src/definitions.rs | 175 ++++++++----------- compiler/rustc_metadata/src/rmeta/encoder.rs | 20 ++- compiler/rustc_middle/src/ty/context.rs | 4 +- 4 files changed, 84 insertions(+), 117 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a916ee1f143bd..729cc0cc31b3b 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -542,7 +542,7 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> mid_hir::Crate<'_> { let ast_index = index_crate(&resolver, &krate); let mut owners = IndexVec::from_fn_n( |_| hir::MaybeOwner::Phantom, - tcx.definitions_untracked().def_index_count(), + tcx.definitions_untracked().num_definitions(), ); let mut lowerer = item::ItemLowerer { diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 70720c6dbd981..97e739a7f3893 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -20,84 +20,6 @@ pub use crate::def_id::DefPathHash; use crate::def_id::{CRATE_DEF_INDEX, CrateNum, DefIndex, LOCAL_CRATE, LocalDefId, StableCrateId}; use crate::def_path_hash_map::DefPathHashMap; -/// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa. -/// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey` -/// stores the `DefIndex` of its parent. -/// There is one `DefPathTable` for each crate. -#[derive(Debug)] -pub struct DefPathTable { - stable_crate_id: StableCrateId, - index_to_key: IndexVec, - // We do only store the local hash, as all the definitions are from the current crate. - def_path_hashes: IndexVec, - def_path_hash_to_index: DefPathHashMap, -} - -impl DefPathTable { - fn new(stable_crate_id: StableCrateId) -> DefPathTable { - DefPathTable { - stable_crate_id, - index_to_key: Default::default(), - def_path_hashes: Default::default(), - def_path_hash_to_index: Default::default(), - } - } - - fn allocate(&mut self, key: DefKey, def_path_hash: DefPathHash) -> DefIndex { - // Assert that all DefPathHashes correctly contain the local crate's StableCrateId. - debug_assert_eq!(self.stable_crate_id, def_path_hash.stable_crate_id()); - let local_hash = def_path_hash.local_hash(); - - let index = self.index_to_key.push(key); - debug!("DefPathTable::insert() - {key:?} <-> {index:?}"); - - self.def_path_hashes.push(local_hash); - debug_assert!(self.def_path_hashes.len() == self.index_to_key.len()); - - // Check for hash collisions of DefPathHashes. These should be - // exceedingly rare. - if let Some(existing) = self.def_path_hash_to_index.insert(&local_hash, &index) { - let def_path1 = DefPath::make(LOCAL_CRATE, existing, |idx| self.def_key(idx)); - let def_path2 = DefPath::make(LOCAL_CRATE, index, |idx| self.def_key(idx)); - - // Continuing with colliding DefPathHashes can lead to correctness - // issues. We must abort compilation. - // - // The likelihood of such a collision is very small, so actually - // running into one could be indicative of a poor hash function - // being used. - // - // See the documentation for DefPathHash for more information. - panic!( - "found DefPathHash collision between {def_path1:#?} and {def_path2:#?}. \ - Compilation cannot continue." - ); - } - - index - } - - #[inline(always)] - pub fn def_key(&self, index: DefIndex) -> DefKey { - self.index_to_key[index] - } - - #[instrument(level = "trace", skip(self), ret)] - #[inline(always)] - pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash { - let hash = self.def_path_hashes[index]; - DefPathHash::new(self.stable_crate_id, hash) - } - - pub fn enumerated_keys_and_path_hashes( - &self, - ) -> impl Iterator + ExactSizeIterator { - self.index_to_key - .iter_enumerated() - .map(move |(index, key)| (index, key, self.def_path_hash(index))) - } -} - #[derive(Debug, Default, Clone)] pub struct PerParentDisambiguatorState { #[cfg(debug_assertions)] @@ -123,12 +45,13 @@ impl LocalDefIdMap { } } -/// The definition table containing node definitions. -/// It holds the `DefPathTable` for `LocalDefId`s/`DefPath`s. -/// It also stores mappings to convert `LocalDefId`s to/from `HirId`s. #[derive(Debug)] pub struct Definitions { - table: DefPathTable, + stable_crate_id: StableCrateId, + def_id_to_key: IndexVec, + // We do only store the local hash, as all the definitions are from the current crate. + def_path_hashes: IndexVec, + def_path_hash_to_index: DefPathHashMap, } /// A unique identifier that we can use to lookup a definition @@ -167,7 +90,7 @@ impl DefKey { // Construct the new DefPathHash, making sure that the `crate_id` // portion of the hash is properly copied from the parent. This way the // `crate_id` part will be recursively propagated from the root to all - // DefPathHashes in this DefPathTable. + // DefPathHashes in this Definitions. DefPathHash::new(parent.stable_crate_id(), local_hash) } @@ -324,23 +247,15 @@ pub enum DefPathData { } impl Definitions { - pub fn def_path_table(&self) -> &DefPathTable { - &self.table - } - - /// Gets the number of definitions. - pub fn def_index_count(&self) -> usize { - self.table.index_to_key.len() - } - - #[inline] + #[inline(always)] pub fn def_key(&self, id: LocalDefId) -> DefKey { - self.table.def_key(id.local_def_index) + self.def_id_to_key[id] } + #[instrument(level = "trace", skip(self), ret)] #[inline(always)] pub fn def_path_hash(&self, id: LocalDefId) -> DefPathHash { - self.table.def_path_hash(id.local_def_index) + DefPathHash::new(self.stable_crate_id, self.def_path_hashes[id]) } /// Returns the path from the crate root to `index`. The root @@ -348,6 +263,7 @@ impl Definitions { /// empty vector for the crate root). For an inlined item, this /// will be the path of the item in the external crate (but the /// path will begin with the path to the external crate). + #[inline] pub fn def_path(&self, id: LocalDefId) -> DefPath { DefPath::make(LOCAL_CRATE, id.local_def_index, |index| { self.def_key(LocalDefId { local_def_index: index }) @@ -375,12 +291,62 @@ impl Definitions { let def_path_hash = DefPathHash::new(stable_crate_id, Hash64::new(stable_crate_id.as_u64())); + let mut defs = Definitions { + stable_crate_id, + def_path_hashes: Default::default(), + def_id_to_key: Default::default(), + def_path_hash_to_index: Default::default(), + }; + // Create the root definition. - let mut table = DefPathTable::new(stable_crate_id); - let root = LocalDefId { local_def_index: table.allocate(key, def_path_hash) }; + let root = defs.allocate(key, def_path_hash); assert_eq!(root.local_def_index, CRATE_DEF_INDEX); - Definitions { table } + defs + } + + fn allocate(&mut self, key: DefKey, def_path_hash: DefPathHash) -> LocalDefId { + // Assert that all DefPathHashes correctly contain the local crate's StableCrateId. + debug_assert_eq!(self.stable_crate_id, def_path_hash.stable_crate_id()); + let local_hash = def_path_hash.local_hash(); + + let def_id = self.def_id_to_key.push(key); + debug!("def_id_to_key.push() - {key:?} <-> {:?}", def_id.local_def_index); + + self.def_path_hashes.push(local_hash); + debug_assert!(self.def_path_hashes.len() == self.def_id_to_key.len()); + + // Check for hash collisions of DefPathHashes. These should be + // exceedingly rare. + if let Some(existing) = + self.def_path_hash_to_index.insert(&local_hash, &def_id.local_def_index) + { + let def_path1 = self.def_path(LocalDefId { local_def_index: existing }); + let def_path2 = self.def_path(def_id); + + // Continuing with colliding DefPathHashes can lead to correctness + // issues. We must abort compilation. + // + // The likelihood of such a collision is very small, so actually + // running into one could be indicative of a poor hash function + // being used. + // + // See the documentation for DefPathHash for more information. + panic!( + "found DefPathHash collision between {def_path1:#?} and {def_path2:#?}. \ + Compilation cannot continue." + ); + } + + def_id + } + + pub fn enumerated_keys_and_path_hashes( + &self, + ) -> impl Iterator + ExactSizeIterator { + self.def_id_to_key + .iter_enumerated() + .map(move |(def_id, key)| (def_id.local_def_index, key, self.def_path_hash(def_id))) } /// Creates a definition with a parent definition. @@ -423,13 +389,13 @@ impl Definitions { disambiguated_data: DisambiguatedDefPathData { data, disambiguator }, }; - let parent_hash = self.table.def_path_hash(parent.local_def_index); + let parent_hash = self.def_path_hash(parent); let def_path_hash = key.compute_stable_hash(parent_hash); debug!("create_def: after disambiguation, key = {:?}", key); // Create the definition. - LocalDefId { local_def_index: self.table.allocate(key, def_path_hash) } + self.allocate(key, def_path_hash) } #[inline(always)] @@ -439,19 +405,18 @@ impl Definitions { /// if the `DefPathHash` is from a previous compilation session and /// the def-path does not exist anymore. pub fn local_def_path_hash_to_def_id(&self, hash: DefPathHash) -> Option { - debug_assert!(hash.stable_crate_id() == self.table.stable_crate_id); - self.table - .def_path_hash_to_index + debug_assert!(hash.stable_crate_id() == self.stable_crate_id); + self.def_path_hash_to_index .get(&hash.local_hash()) .map(|local_def_index| LocalDefId { local_def_index }) } pub fn def_path_hash_to_def_index_map(&self) -> &DefPathHashMap { - &self.table.def_path_hash_to_index + &self.def_path_hash_to_index } pub fn num_definitions(&self) -> usize { - self.table.def_path_hashes.len() + self.def_path_hashes.len() } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index a0db004b7f4c4..a8befd6d188d2 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -12,7 +12,7 @@ use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_data_structures::thousands::usize_with_underscores; use rustc_hir as hir; use rustc_hir::attrs::{AttributeKind, EncodeCrossCrate}; -use rustc_hir::def_id::{CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE, LocalDefId, LocalDefIdSet}; +use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalDefIdSet}; use rustc_hir::definitions::DefPathData; use rustc_hir::find_attr; use rustc_hir_pretty::id_to_string; @@ -510,18 +510,20 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_def_path_table(&mut self) { - let table = self.tcx.def_path_table(); + let defs = self.tcx.definitions(); if self.is_proc_macro { - for def_index in std::iter::once(CRATE_DEF_INDEX) - .chain(self.tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index)) + for def_id in std::iter::once(CRATE_DEF_ID) + .chain(self.tcx.resolutions(()).proc_macros.iter().copied()) { - let def_key = self.lazy(table.def_key(def_index)); - let def_path_hash = table.def_path_hash(def_index); - self.tables.def_keys.set_some(def_index, def_key); - self.tables.def_path_hashes.set(def_index, def_path_hash.local_hash().as_u64()); + let def_key = self.lazy(defs.def_key(def_id)); + let def_path_hash = defs.def_path_hash(def_id); + self.tables.def_keys.set_some(def_id.local_def_index, def_key); + self.tables + .def_path_hashes + .set(def_id.local_def_index, def_path_hash.local_hash().as_u64()); } } else { - for (def_index, def_key, def_path_hash) in table.enumerated_keys_and_path_hashes() { + for (def_index, def_key, def_path_hash) in defs.enumerated_keys_and_path_hashes() { let def_key = self.lazy(def_key); self.tables.def_keys.set_some(def_index, def_key); self.tables.def_path_hashes.set(def_index, def_path_hash.local_hash().as_u64()); diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index e756277b92d76..993edd5c2a09b 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1343,13 +1343,13 @@ impl<'tcx> TyCtxt<'tcx> { } } - pub fn def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable { + pub fn definitions(self) -> &'tcx rustc_hir::definitions::Definitions { // Depend on the `analysis` query to ensure compilation if finished. self.ensure_ok().analysis(()); // Freeze definitions once we start iterating on them, to prevent adding new ones // while iterating. If some query needs to add definitions, it should be `ensure`d above. - self.untracked.definitions.freeze().def_path_table() + self.untracked.definitions.freeze() } pub fn def_path_hash_to_def_index_map(