diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 0454633091568..736e90ae24890 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -165,6 +165,7 @@ language_item_table! { DynMetadata, sym::dyn_metadata, dyn_metadata, Target::Struct, GenericRequirement::None; Freeze, sym::freeze, freeze_trait, Target::Trait, GenericRequirement::Exact(0); + Identity, sym::identity, identity_type, Target::AssocTy, GenericRequirement::None; Drop, sym::drop, drop_trait, Target::Trait, GenericRequirement::None; Destruct, sym::destruct, destruct_trait, Target::Trait, GenericRequirement::None; diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 3d5f189e233bb..566654f866c3f 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2626,12 +2626,25 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let substs = self.ast_path_substs_for_ty(span, did, item_segment.0); tcx.mk_opaque(did, substs) } + Res::Def(DefKind::TyAlias, def_id) => { + assert_eq!(opt_self_ty, None); + self.prohibit_generics(path.segments.split_last().unwrap().1.iter(), |_| {}); + + if let Some(identity_def_id) = tcx.lang_items().identity_type() && std::env::var("TEST_WITH_IDENTITY").is_ok() { + let item_segment = path.segments.split_last().unwrap(); + + let substs = self.ast_path_substs_for_ty(span, def_id, item_segment.0); + let binder_ty = tcx.bound_type_of(def_id); + let ty = binder_ty.subst(tcx, substs); + + let substs = tcx.mk_substs_trait(ty, []); + tcx.mk_projection(identity_def_id, substs) + } else { + self.ast_path_to_ty(span, def_id, path.segments.last().unwrap()) + } + } Res::Def( - DefKind::Enum - | DefKind::TyAlias - | DefKind::Struct - | DefKind::Union - | DefKind::ForeignTy, + DefKind::Enum | DefKind::Struct | DefKind::Union | DefKind::ForeignTy, did, ) => { assert_eq!(opt_self_ty, None); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 1ced75cccbb30..5ddff430d2151 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -790,6 +790,7 @@ symbols! { i64, i8, ident, + identity, identity_future, if_let, if_let_guard, diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index e11bca5962a15..83dd77667265f 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -779,6 +779,26 @@ unsafe impl Freeze for *mut T {} unsafe impl Freeze for &T {} unsafe impl Freeze for &mut T {} +/// Compiler-internal trait used to handle more easily trait aliases. +/// They get generated like projections. For example: +/// ```ignore (pseudo-code) +/// type Foo = Bar; +/// // becomes: +/// type Foo = ::Identity; +/// ``` +#[stable(feature = "pin", since = "1.33.0")] +pub trait Identity { + #[cfg_attr(not(bootstrap), lang = "identity")] + #[stable(feature = "pin", since = "1.33.0")] + /// doc + type Identity: ?Sized; +} + +#[stable(feature = "pin", since = "1.33.0")] +impl Identity for T { + type Identity = T; +} + /// Types that can be safely moved after being pinned. /// /// Rust itself has no notion of immovable types, and considers moves (e.g.,