Encode cross-crate opaque type origin

This commit is contained in:
Michael Goulet 2024-10-02 23:16:31 -04:00
parent 4add5e4211
commit e093b82a41
19 changed files with 53 additions and 43 deletions

View File

@ -272,7 +272,7 @@ enum ImplTraitContext {
/// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
/// equivalent to a new opaque type like `type T = impl Debug; fn foo() -> T`. /// 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. /// `impl Trait` is unstably accepted in this position.
FeatureGated(ImplTraitPosition, Symbol), FeatureGated(ImplTraitPosition, Symbol),
/// `impl Trait` is not accepted in this position. /// `impl Trait` is not accepted in this position.
@ -1416,7 +1416,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_opaque_impl_trait( fn lower_opaque_impl_trait(
&mut self, &mut self,
span: Span, span: Span,
origin: hir::OpaqueTyOrigin, origin: hir::OpaqueTyOrigin<LocalDefId>,
opaque_ty_node_id: NodeId, opaque_ty_node_id: NodeId,
bounds: &GenericBounds, bounds: &GenericBounds,
itctx: ImplTraitContext, itctx: ImplTraitContext,
@ -1458,7 +1458,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_opaque_inner( fn lower_opaque_inner(
&mut self, &mut self,
opaque_ty_node_id: NodeId, opaque_ty_node_id: NodeId,
origin: hir::OpaqueTyOrigin, origin: hir::OpaqueTyOrigin<LocalDefId>,
opaque_ty_span: Span, opaque_ty_span: Span,
lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>], lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],
) -> hir::TyKind<'hir> { ) -> hir::TyKind<'hir> {

View File

@ -502,7 +502,7 @@ impl<'tcx> LazyOpaqueTyEnv<'tcx> {
} }
let &Self { tcx, def_id, .. } = self; 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 { let parent = match origin {
hir::OpaqueTyOrigin::FnReturn { parent, .. } hir::OpaqueTyOrigin::FnReturn { parent, .. }
| hir::OpaqueTyOrigin::AsyncFn { parent, .. } | hir::OpaqueTyOrigin::AsyncFn { parent, .. }

View File

@ -2746,7 +2746,7 @@ pub struct OpaqueTy<'hir> {
pub hir_id: HirId, pub hir_id: HirId,
pub def_id: LocalDefId, pub def_id: LocalDefId,
pub bounds: GenericBounds<'hir>, pub bounds: GenericBounds<'hir>,
pub origin: OpaqueTyOrigin, pub origin: OpaqueTyOrigin<LocalDefId>,
pub span: Span, pub span: Span,
} }
@ -2784,33 +2784,35 @@ pub struct PreciseCapturingNonLifetimeArg {
pub res: Res, 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 { pub enum RpitContext {
Trait, Trait,
TraitImpl, TraitImpl,
} }
/// From whence the opaque type came. /// From whence the opaque type came.
#[derive(Copy, Clone, PartialEq, Eq, Debug, HashStable_Generic)] #[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum OpaqueTyOrigin { #[derive(HashStable_Generic, Encodable, Decodable)]
pub enum OpaqueTyOrigin<D> {
/// `-> impl Trait` /// `-> impl Trait`
FnReturn { FnReturn {
/// The defining function. /// The defining function.
parent: LocalDefId, parent: D,
// Whether this is an RPITIT (return position impl trait in trait) // Whether this is an RPITIT (return position impl trait in trait)
in_trait_or_impl: Option<RpitContext>, in_trait_or_impl: Option<RpitContext>,
}, },
/// `async fn` /// `async fn`
AsyncFn { AsyncFn {
/// The defining function. /// The defining function.
parent: LocalDefId, parent: D,
// Whether this is an AFIT (async fn in trait) // Whether this is an AFIT (async fn in trait)
in_trait_or_impl: Option<RpitContext>, in_trait_or_impl: Option<RpitContext>,
}, },
/// type aliases: `type Foo = impl Trait;` /// type aliases: `type Foo = impl Trait;`
TyAlias { TyAlias {
/// The type alias or associated type parent of the TAIT/ATPIT /// The type alias or associated type parent of the TAIT/ATPIT
parent: LocalDefId, parent: D,
/// associated types in impl blocks for traits. /// associated types in impl blocks for traits.
in_assoc_ty: bool, in_assoc_ty: bool,
}, },

View File

@ -268,7 +268,7 @@ fn check_opaque_meets_bounds<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
def_id: LocalDefId, def_id: LocalDefId,
span: Span, span: Span,
origin: &hir::OpaqueTyOrigin, origin: &hir::OpaqueTyOrigin<LocalDefId>,
) -> Result<(), ErrorGuaranteed> { ) -> Result<(), ErrorGuaranteed> {
let defining_use_anchor = match *origin { let defining_use_anchor = match *origin {
hir::OpaqueTyOrigin::FnReturn { parent, .. } hir::OpaqueTyOrigin::FnReturn { parent, .. }
@ -677,7 +677,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
DefKind::OpaqueTy => { DefKind::OpaqueTy => {
check_opaque_precise_captures(tcx, def_id); 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, .. } if let hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. }
| hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. } = origin | hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. } = origin
&& let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(fn_def_id) && let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(fn_def_id)

View File

@ -86,7 +86,7 @@ pub fn provide(providers: &mut Providers) {
impl_trait_header, impl_trait_header,
coroutine_kind, coroutine_kind,
coroutine_for_closure, coroutine_for_closure,
is_type_alias_impl_trait, opaque_ty_origin,
rendered_precise_capturing_args, rendered_precise_capturing_args,
..*providers ..*providers
}; };
@ -1759,9 +1759,18 @@ fn coroutine_for_closure(tcx: TyCtxt<'_>, def_id: LocalDefId) -> DefId {
def_id.to_def_id() def_id.to_def_id()
} }
fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool { fn opaque_ty_origin<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> hir::OpaqueTyOrigin<DefId> {
let opaque = tcx.hir().expect_opaque_ty(def_id); match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin {
matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias { .. }) 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>( fn rendered_precise_capturing_args<'tcx>(

View File

@ -20,6 +20,7 @@ pub mod errors;
pub mod generics; pub mod generics;
mod lint; mod lint;
use std::assert_matches::assert_matches;
use std::slice; use std::slice;
use rustc_ast::TraitObjectSyntax; use rustc_ast::TraitObjectSyntax;
@ -1811,7 +1812,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
match path.res { match path.res {
Res::Def(DefKind::OpaqueTy, did) => { Res::Def(DefKind::OpaqueTy, did) => {
// Check for desugared `impl Trait`. // 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 item_segment = path.segments.split_last().unwrap();
let _ = self let _ = self
.prohibit_generic_args(item_segment.1.iter(), GenericsArgsErrExtend::OpaqueTy); .prohibit_generic_args(item_segment.1.iter(), GenericsArgsErrExtend::OpaqueTy);

View File

@ -601,7 +601,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => return None, _ => return None,
}; };
let hir::OpaqueTyOrigin::FnReturn { parent: parent_def_id, .. } = let hir::OpaqueTyOrigin::FnReturn { parent: parent_def_id, .. } =
self.tcx.opaque_type_origin(def_id) self.tcx.local_opaque_ty_origin(def_id)
else { else {
return None; return None;
}; };

View File

@ -155,7 +155,10 @@ impl<'tcx> InferCtxt<'tcx> {
// however in `fn fut() -> impl Future<Output = i32> { async { 42 } }`, where // however in `fn fut() -> impl Future<Output = i32> { async { 42 } }`, where
// it is of no concern, so we only check for TAITs. // it is of no concern, so we only check for TAITs.
if self.can_define_opaque_ty(b_def_id) 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 { self.dcx().emit_err(OpaqueHiddenTypeDiag {
span, span,

View File

@ -316,10 +316,7 @@ provide! { tcx, def_id, other, cdata,
}) })
.unwrap_or_default() .unwrap_or_default()
} }
is_type_alias_impl_trait => { opaque_ty_origin => { table }
debug_assert_eq!(tcx.def_kind(def_id), DefKind::OpaqueTy);
cdata.root.tables.is_type_alias_impl_trait.get(cdata, def_id.index)
}
assumed_wf_types_for_rpitit => { table } assumed_wf_types_for_rpitit => { table }
collect_return_position_impl_trait_in_trait_tys => { collect_return_position_impl_trait_in_trait_tys => {
Ok(cdata Ok(cdata

View File

@ -1188,7 +1188,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
| DefKind::SyntheticCoroutineBody => true, | DefKind::SyntheticCoroutineBody => true,
DefKind::OpaqueTy => { 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, .. } if let hir::OpaqueTyOrigin::FnReturn { parent, .. }
| hir::OpaqueTyOrigin::AsyncFn { parent, .. } = origin | hir::OpaqueTyOrigin::AsyncFn { parent, .. } = origin
&& let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(parent) && 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 { if let DefKind::OpaqueTy = def_kind {
self.encode_explicit_item_bounds(def_id); self.encode_explicit_item_bounds(def_id);
self.encode_explicit_item_super_predicates(def_id); self.encode_explicit_item_super_predicates(def_id);
self.tables record!(self.tables.opaque_ty_origin[def_id] <- self.tcx.opaque_ty_origin(def_id));
.is_type_alias_impl_trait
.set(def_id.index, self.tcx.is_type_alias_impl_trait(def_id));
self.encode_precise_capturing_args(def_id); self.encode_precise_capturing_args(def_id);
} }
if tcx.impl_method_has_trait_impl_trait_tys(def_id) if tcx.impl_method_has_trait_impl_trait_tys(def_id)

View File

@ -378,7 +378,6 @@ define_tables! {
- defaulted: - defaulted:
intrinsic: Table<DefIndex, Option<LazyValue<ty::IntrinsicDef>>>, intrinsic: Table<DefIndex, Option<LazyValue<ty::IntrinsicDef>>>,
is_macro_rules: Table<DefIndex, bool>, is_macro_rules: Table<DefIndex, bool>,
is_type_alias_impl_trait: Table<DefIndex, bool>,
type_alias_is_lazy: Table<DefIndex, bool>, type_alias_is_lazy: Table<DefIndex, bool>,
attr_flags: Table<DefIndex, AttrFlags>, attr_flags: Table<DefIndex, AttrFlags>,
// The u64 is the crate-local part of the DefPathHash. All hashes in this crate have the same // The u64 is the crate-local part of the DefPathHash. All hashes in this crate have the same
@ -469,6 +468,7 @@ define_tables! {
doc_link_resolutions: Table<DefIndex, LazyValue<DocLinkResMap>>, doc_link_resolutions: Table<DefIndex, LazyValue<DocLinkResMap>>,
doc_link_traits_in_scope: Table<DefIndex, LazyArray<DefId>>, doc_link_traits_in_scope: Table<DefIndex, LazyArray<DefId>>,
assumed_wf_types_for_rpitit: Table<DefIndex, LazyArray<(Ty<'static>, Span)>>, assumed_wf_types_for_rpitit: Table<DefIndex, LazyArray<(Ty<'static>, Span)>>,
opaque_ty_origin: Table<DefIndex, LazyValue<hir::OpaqueTyOrigin<DefId>>>,
} }
#[derive(TyEncodable, TyDecodable)] #[derive(TyEncodable, TyDecodable)]

View File

@ -280,6 +280,7 @@ trivial! {
rustc_hir::IsAsync, rustc_hir::IsAsync,
rustc_hir::ItemLocalId, rustc_hir::ItemLocalId,
rustc_hir::LangItem, rustc_hir::LangItem,
rustc_hir::OpaqueTyOrigin<rustc_hir::def_id::DefId>,
rustc_hir::OwnerId, rustc_hir::OwnerId,
rustc_hir::Upvar, rustc_hir::Upvar,
rustc_index::bit_set::FiniteBitSet<u32>, rustc_index::bit_set::FiniteBitSet<u32>,

View File

@ -260,11 +260,10 @@ rustc_queries! {
separate_provide_extern 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 separate_provide_extern
feedable
} }
query unsizing_params_for_adt(key: DefId) -> &'tcx rustc_index::bit_set::BitSet<u32> query unsizing_params_for_adt(key: DefId) -> &'tcx rustc_index::bit_set::BitSet<u32>

View File

@ -2103,11 +2103,9 @@ impl<'tcx> TyCtxt<'tcx> {
} }
/// Returns the origin of the opaque type `def_id`. /// Returns the origin of the opaque type `def_id`.
#[track_caller] #[instrument(skip(self), level = "trace", ret)]
pub fn opaque_type_origin(self, def_id: LocalDefId) -> hir::OpaqueTyOrigin { pub fn local_opaque_ty_origin(self, def_id: LocalDefId) -> hir::OpaqueTyOrigin<LocalDefId> {
let origin = self.hir().expect_opaque_ty(def_id).origin; self.hir().expect_opaque_ty(def_id).origin
trace!("opaque_type_origin({def_id:?}) => {origin:?}");
origin
} }
} }

View File

@ -94,6 +94,7 @@ trivially_parameterized_over_tcx! {
rustc_hir::def_id::DefId, rustc_hir::def_id::DefId,
rustc_hir::def_id::DefIndex, rustc_hir::def_id::DefIndex,
rustc_hir::definitions::DefKey, rustc_hir::definitions::DefKey,
rustc_hir::OpaqueTyOrigin<rustc_hir::def_id::DefId>,
rustc_index::bit_set::BitSet<u32>, rustc_index::bit_set::BitSet<u32>,
rustc_index::bit_set::FiniteBitSet<u32>, rustc_index::bit_set::FiniteBitSet<u32>,
rustc_session::cstore::ForeignModule, rustc_session::cstore::ForeignModule,

View File

@ -384,7 +384,10 @@ impl<T> Trait<T> for X {
| DefKind::AssocFn | DefKind::AssocFn
| DefKind::AssocConst | 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 && !tcx
.opaque_types_defined_by(body_owner_def_id.expect_local()) .opaque_types_defined_by(body_owner_def_id.expect_local())
.contains(&opaque_ty.def_id.expect_local()) .contains(&opaque_ty.def_id.expect_local())

View File

@ -2648,7 +2648,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
def_id: DefId, def_id: DefId,
) -> ErrorGuaranteed { ) -> 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 { .. } => { hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } => {
"opaque type".to_string() "opaque type".to_string()
} }

View File

@ -246,7 +246,7 @@ fn associated_type_for_impl_trait_in_trait(
) -> LocalDefId { ) -> LocalDefId {
let (hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. } let (hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. }
| hir::OpaqueTyOrigin::AsyncFn { 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 { else {
bug!("expected opaque for {opaque_ty_def_id:?}"); bug!("expected opaque for {opaque_ty_def_id:?}");
}; };
@ -284,8 +284,6 @@ fn associated_type_for_impl_trait_in_trait(
// Copy defaultness of the containing function. // Copy defaultness of the containing function.
trait_assoc_ty.defaultness(tcx.defaultness(fn_def_id)); 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. // There are no inferred outlives for the synthesized associated type.
trait_assoc_ty.inferred_outlives_of(&[]); trait_assoc_ty.inferred_outlives_of(&[]);

View File

@ -139,7 +139,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
} }
// TAITs outside their defining scopes are ignored. // 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); trace!(?origin);
match origin { match origin {
rustc_hir::OpaqueTyOrigin::FnReturn { .. } rustc_hir::OpaqueTyOrigin::FnReturn { .. }