diff options
| author | bors <bors@rust-lang.org> | 2024-10-31 03:36:06 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-10-31 03:36:06 +0000 |
| commit | c8b83785dccdd22345d193fed7431ce44074007b (patch) | |
| tree | 3a35f3900814528be97d735217174f04e463ad66 /compiler | |
| parent | 75eff9a5749411ba5a0b37cc3299116c4e263075 (diff) | |
| parent | c1457798db03ffb7f207eaf208d8d4d77ba01563 (diff) | |
Auto merge of #131186 - compiler-errors:precise-capturing-borrowck, r=estebank
Try to point out when edition 2024 lifetime capture rules cause borrowck issues Lifetime capture rules in 2024 are modified to capture more lifetimes, which sometimes lead to some non-local borrowck errors. This PR attempts to link these back together with a useful note pointing out the capture rule changes. This is not a blocking concern, but I'd appreciate feedback (though, again, I'd like to stress that I don't want to block this PR on this): I'm worried about this note drowning in the sea of other diagnostics that borrowck emits. I was tempted to change the level of the note to `.span_warn` just so it would show up in a different color. Thoughts? Fixes #130545 Opening as a draft first since it's stacked on #131183. r? `@ghost`
Diffstat (limited to 'compiler')
22 files changed, 286 insertions, 45 deletions
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e1ee3d0af49..5a0e9e8aec0 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -272,7 +272,7 @@ enum ImplTraitContext { /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually /// equivalent to a new opaque type like `type T = impl Debug; fn foo() -> T`. /// - OpaqueTy { origin: hir::OpaqueTyOrigin }, + OpaqueTy { origin: hir::OpaqueTyOrigin<LocalDefId> }, /// `impl Trait` is unstably accepted in this position. FeatureGated(ImplTraitPosition, Symbol), /// `impl Trait` is not accepted in this position. @@ -1416,7 +1416,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_opaque_impl_trait( &mut self, span: Span, - origin: hir::OpaqueTyOrigin, + origin: hir::OpaqueTyOrigin<LocalDefId>, opaque_ty_node_id: NodeId, bounds: &GenericBounds, itctx: ImplTraitContext, @@ -1458,7 +1458,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_opaque_inner( &mut self, opaque_ty_node_id: NodeId, - origin: hir::OpaqueTyOrigin, + origin: hir::OpaqueTyOrigin<LocalDefId>, opaque_ty_span: Span, lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>], ) -> hir::TyKind<'hir> { diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index c687be69b1a..1bfb54a7bb7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1489,6 +1489,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { &borrow_msg, &value_msg, ); + self.note_due_to_edition_2024_opaque_capture_rules(borrow, &mut err); borrow_spans.var_path_only_subdiag(&mut err, crate::InitializationRequiringAction::Borrow); @@ -1561,6 +1562,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { borrow_span, &self.describe_any_place(borrow.borrowed_place.as_ref()), ); + self.note_due_to_edition_2024_opaque_capture_rules(borrow, &mut err); + borrow_spans.var_subdiag(&mut err, Some(borrow.kind), |kind, var_span| { use crate::session_diagnostics::CaptureVarCause::*; let place = &borrow.borrowed_place; @@ -1820,6 +1823,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { unreachable!() } }; + self.note_due_to_edition_2024_opaque_capture_rules(issued_borrow, &mut err); if issued_spans == borrow_spans { borrow_spans.var_subdiag(&mut err, Some(gen_borrow_kind), |kind, var_span| { @@ -2860,7 +2864,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { debug!(?place_desc, ?explanation); - let err = match (place_desc, explanation) { + let mut err = match (place_desc, explanation) { // If the outlives constraint comes from inside the closure, // for example: // @@ -2939,6 +2943,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { explanation, ), }; + self.note_due_to_edition_2024_opaque_capture_rules(borrow, &mut err); self.buffer_error(err); } @@ -3777,6 +3782,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } let mut err = self.cannot_assign_to_borrowed(span, loan_span, &descr_place); + self.note_due_to_edition_2024_opaque_capture_rules(loan, &mut err); loan_spans.var_subdiag(&mut err, Some(loan.kind), |kind, var_span| { use crate::session_diagnostics::CaptureVarCause::*; diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 801c7af2de7..3b600716036 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -48,6 +48,7 @@ mod conflict_errors; mod explain_borrow; mod move_errors; mod mutability_errors; +mod opaque_suggestions; mod region_errors; pub(crate) use bound_region_errors::{ToUniverseInfo, UniverseInfo}; diff --git a/compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs b/compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs new file mode 100644 index 00000000000..bfd7e83501c --- /dev/null +++ b/compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs @@ -0,0 +1,224 @@ +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + +use std::ops::ControlFlow; + +use either::Either; +use rustc_data_structures::fx::FxIndexSet; +use rustc_errors::{Applicability, Diag}; +use rustc_hir as hir; +use rustc_hir::def_id::DefId; +use rustc_middle::mir::{self, ConstraintCategory, Location}; +use rustc_middle::ty::{ + self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, +}; +use rustc_span::Symbol; + +use crate::MirBorrowckCtxt; +use crate::borrow_set::BorrowData; +use crate::consumers::RegionInferenceContext; +use crate::type_check::Locations; + +impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { + /// Try to note when an opaque is involved in a borrowck error and that + /// opaque captures lifetimes due to edition 2024. + // FIXME: This code is otherwise somewhat general, and could easily be adapted + // to explain why other things overcapture... like async fn and RPITITs. + pub(crate) fn note_due_to_edition_2024_opaque_capture_rules( + &self, + borrow: &BorrowData<'tcx>, + diag: &mut Diag<'_>, + ) { + // We look at all the locals. Why locals? Because it's the best thing + // I could think of that's correlated with the *instantiated* higer-ranked + // binder for calls, since we don't really store those anywhere else. + for ty in self.body.local_decls.iter().map(|local| local.ty) { + if !ty.has_opaque_types() { + continue; + } + + let tcx = self.infcx.tcx; + let ControlFlow::Break((opaque_def_id, offending_region_idx, location)) = ty + .visit_with(&mut FindOpaqueRegion { + regioncx: &self.regioncx, + tcx, + borrow_region: borrow.region, + }) + else { + continue; + }; + + // If an opaque explicitly captures a lifetime, then no need to point it out. + // FIXME: We should be using a better heuristic for `use<>`. + if tcx.rendered_precise_capturing_args(opaque_def_id).is_some() { + continue; + } + + // If one of the opaque's bounds mentions the region, then no need to + // point it out, since it would've been captured on edition 2021 as well. + // + // Also, while we're at it, collect all the lifetimes that the opaque + // *does* mention. We'll use that for the `+ use<'a>` suggestion below. + let mut visitor = CheckExplicitRegionMentionAndCollectGenerics { + tcx, + offending_region_idx, + seen_opaques: [opaque_def_id].into_iter().collect(), + seen_lifetimes: Default::default(), + }; + if tcx + .explicit_item_bounds(opaque_def_id) + .skip_binder() + .visit_with(&mut visitor) + .is_break() + { + continue; + } + + // If we successfully located a terminator, then point it out + // and provide a suggestion if it's local. + match self.body.stmt_at(location) { + Either::Right(mir::Terminator { source_info, .. }) => { + diag.span_note( + source_info.span, + "this call may capture more lifetimes than intended, \ + because Rust 2024 has adjusted the `impl Trait` lifetime capture rules", + ); + let mut seen_generics: Vec<_> = + visitor.seen_lifetimes.iter().map(ToString::to_string).collect(); + // Capture all in-scope ty/const params. + seen_generics.extend( + ty::GenericArgs::identity_for_item(tcx, opaque_def_id) + .iter() + .filter(|arg| { + matches!( + arg.unpack(), + ty::GenericArgKind::Type(_) | ty::GenericArgKind::Const(_) + ) + }) + .map(|arg| arg.to_string()), + ); + if opaque_def_id.is_local() { + diag.span_suggestion_verbose( + tcx.def_span(opaque_def_id).shrink_to_hi(), + "add a precise capturing bound to avoid overcapturing", + format!(" + use<{}>", seen_generics.join(", ")), + Applicability::MaybeIncorrect, + ); + } else { + diag.span_help( + tcx.def_span(opaque_def_id), + format!( + "if you can modify this crate, add a precise \ + capturing bound to avoid overcapturing: `+ use<{}>`", + seen_generics.join(", ") + ), + ); + } + return; + } + Either::Left(_) => {} + } + } + } +} + +/// This visitor contains the bulk of the logic for this lint. +struct FindOpaqueRegion<'a, 'tcx> { + tcx: TyCtxt<'tcx>, + regioncx: &'a RegionInferenceContext<'tcx>, + borrow_region: ty::RegionVid, +} + +impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindOpaqueRegion<'_, 'tcx> { + type Result = ControlFlow<(DefId, usize, Location), ()>; + + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { + // If we find an opaque in a local ty, then for each of its captured regions, + // try to find a path between that captured regions and our borrow region... + if let ty::Alias(ty::Opaque, opaque) = *ty.kind() + && let hir::OpaqueTyOrigin::FnReturn { parent, in_trait_or_impl: None } = + self.tcx.opaque_ty_origin(opaque.def_id) + { + let variances = self.tcx.variances_of(opaque.def_id); + for (idx, (arg, variance)) in std::iter::zip(opaque.args, variances).enumerate() { + // Skip uncaptured args. + if *variance == ty::Bivariant { + continue; + } + // We only care about regions. + let Some(opaque_region) = arg.as_region() else { + continue; + }; + // Don't try to convert a late-bound region, which shouldn't exist anyways (yet). + if opaque_region.is_bound() { + continue; + } + let opaque_region_vid = self.regioncx.to_region_vid(opaque_region); + + // Find a path between the borrow region and our opaque capture. + if let Some((path, _)) = + self.regioncx.find_constraint_paths_between_regions(self.borrow_region, |r| { + r == opaque_region_vid + }) + { + for constraint in path { + // If we find a call in this path, then check if it defines the opaque. + if let ConstraintCategory::CallArgument(Some(call_ty)) = constraint.category + && let ty::FnDef(call_def_id, _) = *call_ty.kind() + // This function defines the opaque :D + && call_def_id == parent + && let Locations::Single(location) = constraint.locations + { + return ControlFlow::Break((opaque.def_id, idx, location)); + } + } + } + } + } + + ty.super_visit_with(self) + } +} + +struct CheckExplicitRegionMentionAndCollectGenerics<'tcx> { + tcx: TyCtxt<'tcx>, + offending_region_idx: usize, + seen_opaques: FxIndexSet<DefId>, + seen_lifetimes: FxIndexSet<Symbol>, +} + +impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for CheckExplicitRegionMentionAndCollectGenerics<'tcx> { + type Result = ControlFlow<(), ()>; + + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { + match *ty.kind() { + ty::Alias(ty::Opaque, opaque) => { + if self.seen_opaques.insert(opaque.def_id) { + for (bound, _) in self + .tcx + .explicit_item_bounds(opaque.def_id) + .iter_instantiated_copied(self.tcx, opaque.args) + { + bound.visit_with(self)?; + } + } + ControlFlow::Continue(()) + } + _ => ty.super_visit_with(self), + } + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result { + match r.kind() { + ty::ReEarlyParam(param) => { + if param.index as usize == self.offending_region_idx { + ControlFlow::Break(()) + } else { + self.seen_lifetimes.insert(param.name); + ControlFlow::Continue(()) + } + } + _ => ControlFlow::Continue(()), + } + } +} diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 741dac9e763..3a2f5c35c72 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -502,7 +502,7 @@ impl<'tcx> LazyOpaqueTyEnv<'tcx> { } let &Self { tcx, def_id, .. } = self; - let origin = tcx.opaque_type_origin(def_id); + let origin = tcx.local_opaque_ty_origin(def_id); let parent = match origin { hir::OpaqueTyOrigin::FnReturn { parent, .. } | hir::OpaqueTyOrigin::AsyncFn { parent, .. } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 12b01266a93..fa76f8652ea 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2746,7 +2746,7 @@ pub struct OpaqueTy<'hir> { pub hir_id: HirId, pub def_id: LocalDefId, pub bounds: GenericBounds<'hir>, - pub origin: OpaqueTyOrigin, + pub origin: OpaqueTyOrigin<LocalDefId>, pub span: Span, } @@ -2784,33 +2784,35 @@ pub struct PreciseCapturingNonLifetimeArg { pub res: Res, } -#[derive(Copy, Clone, PartialEq, Eq, Debug, HashStable_Generic)] +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(HashStable_Generic, Encodable, Decodable)] pub enum RpitContext { Trait, TraitImpl, } /// From whence the opaque type came. -#[derive(Copy, Clone, PartialEq, Eq, Debug, HashStable_Generic)] -pub enum OpaqueTyOrigin { +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(HashStable_Generic, Encodable, Decodable)] +pub enum OpaqueTyOrigin<D> { /// `-> impl Trait` FnReturn { /// The defining function. - parent: LocalDefId, + parent: D, // Whether this is an RPITIT (return position impl trait in trait) in_trait_or_impl: Option<RpitContext>, }, /// `async fn` AsyncFn { /// The defining function. - parent: LocalDefId, + parent: D, // Whether this is an AFIT (async fn in trait) in_trait_or_impl: Option<RpitContext>, }, /// type aliases: `type Foo = impl Trait;` TyAlias { /// The type alias or associated type parent of the TAIT/ATPIT - parent: LocalDefId, + parent: D, /// associated types in impl blocks for traits. in_assoc_ty: bool, }, diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 79e84e507bc..476814c261e 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -268,7 +268,7 @@ fn check_opaque_meets_bounds<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span, - origin: &hir::OpaqueTyOrigin, + origin: &hir::OpaqueTyOrigin<LocalDefId>, ) -> Result<(), ErrorGuaranteed> { let defining_use_anchor = match *origin { hir::OpaqueTyOrigin::FnReturn { parent, .. } @@ -677,7 +677,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { DefKind::OpaqueTy => { check_opaque_precise_captures(tcx, def_id); - let origin = tcx.opaque_type_origin(def_id); + let origin = tcx.local_opaque_ty_origin(def_id); if let hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. } | hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. } = origin && let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(fn_def_id) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index c41117d213f..3f6198dbd31 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -86,7 +86,7 @@ pub fn provide(providers: &mut Providers) { impl_trait_header, coroutine_kind, coroutine_for_closure, - is_type_alias_impl_trait, + opaque_ty_origin, rendered_precise_capturing_args, ..*providers }; @@ -1759,9 +1759,18 @@ fn coroutine_for_closure(tcx: TyCtxt<'_>, def_id: LocalDefId) -> DefId { def_id.to_def_id() } -fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool { - let opaque = tcx.hir().expect_opaque_ty(def_id); - matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias { .. }) +fn opaque_ty_origin<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> hir::OpaqueTyOrigin<DefId> { + match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin { + hir::OpaqueTyOrigin::FnReturn { parent, in_trait_or_impl } => { + hir::OpaqueTyOrigin::FnReturn { parent: parent.to_def_id(), in_trait_or_impl } + } + hir::OpaqueTyOrigin::AsyncFn { parent, in_trait_or_impl } => { + hir::OpaqueTyOrigin::AsyncFn { parent: parent.to_def_id(), in_trait_or_impl } + } + hir::OpaqueTyOrigin::TyAlias { parent, in_assoc_ty } => { + hir::OpaqueTyOrigin::TyAlias { parent: parent.to_def_id(), in_assoc_ty } + } + } } fn rendered_precise_capturing_args<'tcx>( diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 2bd8a5223aa..d70e4d8345a 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -20,6 +20,7 @@ pub mod errors; pub mod generics; mod lint; +use std::assert_matches::assert_matches; use std::slice; use rustc_ast::TraitObjectSyntax; @@ -1811,7 +1812,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { match path.res { Res::Def(DefKind::OpaqueTy, did) => { // Check for desugared `impl Trait`. - assert!(tcx.is_type_alias_impl_trait(did)); + assert_matches!(tcx.opaque_ty_origin(did), hir::OpaqueTyOrigin::TyAlias { .. }); let item_segment = path.segments.split_last().unwrap(); let _ = self .prohibit_generic_args(item_segment.1.iter(), GenericsArgsErrExtend::OpaqueTy); diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 3372cae7a51..1774772b50b 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -601,7 +601,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => return None, }; let hir::OpaqueTyOrigin::FnReturn { parent: parent_def_id, .. } = - self.tcx.opaque_type_origin(def_id) + self.tcx.local_opaque_ty_origin(def_id) else { return None; }; diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 498d25aea64..2bc006c37da 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -155,7 +155,10 @@ impl<'tcx> InferCtxt<'tcx> { // however in `fn fut() -> impl Future<Output = i32> { async { 42 } }`, where // it is of no concern, so we only check for TAITs. if self.can_define_opaque_ty(b_def_id) - && self.tcx.is_type_alias_impl_trait(b_def_id) + && matches!( + self.tcx.opaque_ty_origin(b_def_id), + hir::OpaqueTyOrigin::TyAlias { .. } + ) { self.dcx().emit_err(OpaqueHiddenTypeDiag { span, diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 926eb4f6210..f06f2fdc5e5 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -316,10 +316,7 @@ provide! { tcx, def_id, other, cdata, }) .unwrap_or_default() } - is_type_alias_impl_trait => { - debug_assert_eq!(tcx.def_kind(def_id), DefKind::OpaqueTy); - cdata.root.tables.is_type_alias_impl_trait.get(cdata, def_id.index) - } + opaque_ty_origin => { table } assumed_wf_types_for_rpitit => { table } collect_return_position_impl_trait_in_trait_tys => { Ok(cdata diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index b4b48570453..7277039bb7d 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1188,7 +1188,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> | DefKind::SyntheticCoroutineBody => true, DefKind::OpaqueTy => { - let origin = tcx.opaque_type_origin(def_id); + let origin = tcx.local_opaque_ty_origin(def_id); if let hir::OpaqueTyOrigin::FnReturn { parent, .. } | hir::OpaqueTyOrigin::AsyncFn { parent, .. } = origin && let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(parent) @@ -1530,9 +1530,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if let DefKind::OpaqueTy = def_kind { self.encode_explicit_item_bounds(def_id); self.encode_explicit_item_super_predicates(def_id); - self.tables - .is_type_alias_impl_trait - .set(def_id.index, self.tcx.is_type_alias_impl_trait(def_id)); + record!(self.tables.opaque_ty_origin[def_id] <- self.tcx.opaque_ty_origin(def_id)); self.encode_precise_capturing_args(def_id); } if tcx.impl_method_has_trait_impl_trait_tys(def_id) diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 927c9fa47a1..ab878760c00 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -378,7 +378,6 @@ define_tables! { - defaulted: intrinsic: Table<DefIndex, Option<LazyValue<ty::IntrinsicDef>>>, is_macro_rules: Table<DefIndex, bool>, - is_type_alias_impl_trait: Table<DefIndex, bool>, type_alias_is_lazy: Table<DefIndex, bool>, attr_flags: Table<DefIndex, AttrFlags>, // The u64 is the crate-local part of the DefPathHash. All hashes in this crate have the same @@ -468,6 +467,7 @@ define_tables! { doc_link_resolutions: Table<DefIndex, LazyValue<DocLinkResMap>>, doc_link_traits_in_scope: Table<DefIndex, LazyArray<DefId>>, assumed_wf_types_for_rpitit: Table<DefIndex, LazyArray<(Ty<'static>, Span)>>, + opaque_ty_origin: Table<DefIndex, LazyValue<hir::OpaqueTyOrigin<DefId>>>, } #[derive(TyEncodable, TyDecodable)] diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 5f8427bd707..8cfc7f1e33e 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -280,6 +280,7 @@ trivial! { rustc_hir::IsAsync, rustc_hir::ItemLocalId, rustc_hir::LangItem, + rustc_hir::OpaqueTyOrigin<rustc_hir::def_id::DefId>, rustc_hir::OwnerId, rustc_hir::Upvar, rustc_index::bit_set::FiniteBitSet<u32>, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index d7f58963101..088b5d4ec96 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -260,11 +260,10 @@ rustc_queries! { separate_provide_extern } - query is_type_alias_impl_trait(key: DefId) -> bool + query opaque_ty_origin(key: DefId) -> hir::OpaqueTyOrigin<DefId> { - desc { "determine whether the opaque is a type-alias impl trait" } + desc { "determine where the opaque originates from" } separate_provide_extern - feedable } query unsizing_params_for_adt(key: DefId) -> &'tcx rustc_index::bit_set::BitSet<u32> diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index ac36b940725..9abad6d1a68 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -55,7 +55,7 @@ use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::lang_items::TraitSolverLangItem; pub use rustc_type_ir::lift::Lift; use rustc_type_ir::{CollectAndApply, Interner, TypeFlags, WithCachedTypeInfo, search_graph}; -use tracing::{debug, trace}; +use tracing::{debug, instrument}; use crate::arena::Arena; use crate::dep_graph::{DepGraph, DepKindStruct}; @@ -2103,11 +2103,9 @@ impl<'tcx> TyCtxt<'tcx> { } /// Returns the origin of the opaque type `def_id`. - #[track_caller] - pub fn opaque_type_origin(self, def_id: LocalDefId) -> hir::OpaqueTyOrigin { - let origin = self.hir().expect_opaque_ty(def_id).origin; - trace!("opaque_type_origin({def_id:?}) => {origin:?}"); - origin + #[instrument(skip(self), level = "trace", ret)] + pub fn local_opaque_ty_origin(self, def_id: LocalDefId) -> hir::OpaqueTyOrigin<LocalDefId> { + self.hir().expect_opaque_ty(def_id).origin } } diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 43bdce5b576..7c280bc8b49 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -94,6 +94,7 @@ trivially_parameterized_over_tcx! { rustc_hir::def_id::DefId, rustc_hir::def_id::DefIndex, rustc_hir::definitions::DefKey, + rustc_hir::OpaqueTyOrigin<rustc_hir::def_id::DefId>, rustc_index::bit_set::BitSet<u32>, rustc_index::bit_set::FiniteBitSet<u32>, rustc_session::cstore::ForeignModule, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index 0cf7c43beb5..b97f3dc303b 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -384,7 +384,10 @@ impl<T> Trait<T> for X { | DefKind::AssocFn | DefKind::AssocConst ) - && tcx.is_type_alias_impl_trait(opaque_ty.def_id) + && matches!( + tcx.opaque_ty_origin(opaque_ty.def_id), + hir::OpaqueTyOrigin::TyAlias { .. } + ) && !tcx .opaque_types_defined_by(body_owner_def_id.expect_local()) .contains(&opaque_ty.def_id.expect_local()) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 612e92ea784..7aa558cfd3f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -2648,7 +2648,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { obligation: &PredicateObligation<'tcx>, def_id: DefId, ) -> ErrorGuaranteed { - let name = match self.tcx.opaque_type_origin(def_id.expect_local()) { + let name = match self.tcx.local_opaque_ty_origin(def_id.expect_local()) { hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } => { "opaque type".to_string() } diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 161bed9d3a6..3655fa5ae0e 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -244,7 +244,7 @@ fn associated_type_for_impl_trait_in_trait( ) -> LocalDefId { let (hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. } | hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. }) = - tcx.opaque_type_origin(opaque_ty_def_id) + tcx.local_opaque_ty_origin(opaque_ty_def_id) else { bug!("expected opaque for {opaque_ty_def_id:?}"); }; @@ -281,8 +281,6 @@ fn associated_type_for_impl_trait_in_trait( // Copy defaultness of the containing function. trait_assoc_ty.defaultness(tcx.defaultness(fn_def_id)); - trait_assoc_ty.is_type_alias_impl_trait(false); - // There are no inferred outlives for the synthesized associated type. trait_assoc_ty.inferred_outlives_of(&[]); diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 5e2232ff47d..34f461aac58 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -139,7 +139,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { } // TAITs outside their defining scopes are ignored. - let origin = self.tcx.opaque_type_origin(alias_ty.def_id.expect_local()); + let origin = self.tcx.local_opaque_ty_origin(alias_ty.def_id.expect_local()); trace!(?origin); match origin { rustc_hir::OpaqueTyOrigin::FnReturn { .. } |
