diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index e05646e1e86a4..3d83c71bce0d3 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -414,6 +414,7 @@ fn push_debuginfo_type_name<'tcx>( | ty::Projection(..) | ty::Bound(..) | ty::Opaque(..) + | ty::TyAlias(..) | ty::GeneratorWitness(..) => { bug!( "debuginfo: Trying to create type name for \ diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index a964fe8465eec..4570eecc9385c 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -140,19 +140,21 @@ pub(crate) fn const_to_valtree_inner<'tcx>( ty::Never | ty::Error(_) | ty::Foreign(..) - | ty::Infer(ty::FreshIntTy(_)) - | ty::Infer(ty::FreshFloatTy(_)) - | ty::Projection(..) - | ty::Param(_) - | ty::Bound(..) - | ty::Placeholder(..) // FIXME(oli-obk): we could look behind opaque types | ty::Opaque(..) - | ty::Infer(_) // FIXME(oli-obk): we can probably encode closures just like structs | ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) => Err(ValTreeCreationError::NonSupportedType), + + ty::Infer(_) + | ty::TyAlias(..) + | ty::Projection(..) + | ty::Param(_) + | ty::Bound(..) + | ty::Placeholder(..) => { + bug!("{:?} should have errored and never gotten converted to valtree", ty.kind()) + } } } @@ -320,7 +322,8 @@ pub fn valtree_to_const_value<'tcx>( | ty::RawPtr(_) | ty::Str | ty::Slice(_) - | ty::Dynamic(..) => bug!("no ValTree should have been created for type {:?}", ty.kind()), + | ty::Dynamic(..) + | ty::TyAlias(..) => bug!("no ValTree should have been created for type {:?}", ty.kind()), } } diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 8637d6a7767e4..892180986cb7b 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -10,10 +10,9 @@ use rustc_middle::mir::{ interpret::{ConstValue, GlobalId, InterpResult, PointerArithmetic, Scalar}, BinOp, NonDivergingIntrinsic, }; -use rustc_middle::ty; use rustc_middle::ty::layout::LayoutOf as _; use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::{Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::symbol::{sym, Symbol}; use rustc_target::abi::{Abi, Align, Primitive, Size}; @@ -102,6 +101,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>( | ty::Never | ty::Tuple(_) | ty::Error(_) => ConstValue::from_machine_usize(0u64, &tcx), + ty::TyAlias(..) => bug!("unexpected TyAlias in eval_nullary_intrinsic"), }, other => bug!("`{}` is not a zero arg intrinsic", other), }) diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs index ffdb8de5b6c8c..410f8068bc996 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs @@ -64,6 +64,11 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { | ty::Closure(def_id, substs) | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs), ty::Foreign(def_id) => self.print_def_path(def_id, &[]), + ty::TyAlias(def_id, substs) => { + let binder_ty = self.tcx.bound_type_of(def_id); + let ty = binder_ty.subst(self.tcx, substs); + self.print_type(ty) + } ty::GeneratorWitness(_) => bug!("type_name: unexpected `GeneratorWitness`"), } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index d4146c2424101..8f1102a34b2b2 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -603,7 +603,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' | ty::Param(..) | ty::Opaque(..) | ty::Projection(..) - | ty::GeneratorWitness(..) => bug!("Encountered invalid type {:?}", ty), + | ty::GeneratorWitness(..) + | ty::TyAlias(..) => bug!("Encountered invalid type {:?}", ty), } } diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 6baf98449775d..eed49f62c6c18 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2391,12 +2391,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let substs = self.ast_path_substs_for_ty(span, did, item_segment.0); self.normalize_ty(span, 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(), |_| {}); + let item_segment = path.segments.split_last().unwrap(); + let substs = self.ast_path_substs_for_ty(span, def_id, item_segment.0); + self.normalize_ty(span, tcx.mk_ty_alias(def_id, substs)) + } 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_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 70a171c02b26b..78287f66d9f7b 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -14,8 +14,8 @@ use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::query::Providers; use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::{ - self, AdtKind, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, - TypeSuperVisitable, TypeVisitable, TypeVisitor, + self, AdtKind, DefIdTree, GenericParamDefKind, SubstsRef, ToPredicate, Ty, TyCtxt, + TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, }; use rustc_middle::ty::{GenericArgKind, InternalSubsts}; use rustc_session::parse::feature_err; @@ -239,6 +239,51 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { hir::ItemKind::TraitAlias(..) => { check_trait(tcx, item); } + hir::ItemKind::TyAlias { .. } => { + struct TyAliasPeeler<'t> { + tcx: TyCtxt<'t>, + visited: FxHashSet<(DefId, SubstsRef<'t>)>, + } + + impl<'t> ty::TypeFolder<'t> for TyAliasPeeler<'t> { + fn tcx<'a>(&'a self) -> TyCtxt<'t> { + self.tcx + } + + fn fold_ty(&mut self, t: Ty<'t>) -> Ty<'t> { + use crate::ty::fold::{TypeFoldable, TypeSuperFoldable}; + use crate::ty::visit::TypeVisitable; + + match *t.kind() { + ty::TyAlias(def_id, substs) => { + if !self.visited.insert((def_id, substs)) { + let def_span = self.tcx.def_span(def_id); + self.tcx + .sess + .struct_span_err( + def_span, + "cycle detected when expanding type alias", + ) + .emit(); + return t; + } + let binder_ty = self.tcx.bound_type_of(def_id); + let ty = binder_ty.subst(self.tcx, substs); + ty.fold_with(self) + } + _ if !t.has_ty_alias() => t, + _ => t.super_fold_with(self), + } + } + } + + let ty = tcx.bound_type_of(item.def_id.to_def_id()).0; + if let ty::TyAlias(def_id, substs) = *ty.kind() { + let binder_ty = tcx.bound_type_of(def_id); + let ty = binder_ty.subst(tcx, substs); + ty.fold_with(&mut TyAliasPeeler { tcx, visited: FxHashSet::default() }); + } + } // `ForeignItem`s are handled separately. hir::ItemKind::ForeignMod { .. } => {} _ => {} @@ -856,6 +901,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) { // Const parameters are well formed if their type is structural match. hir::GenericParamKind::Const { ty: hir_ty, default: _ } => { let ty = tcx.type_of(tcx.hir().local_def_id(param.hir_id)); + let ty = tcx.peel_off_ty_alias(ty); if tcx.features().adt_const_params { if let Some(non_structural_match_ty) = diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index 308ad5d5fc2c2..aca22fbeb7bea 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -187,6 +187,8 @@ impl<'tcx> InherentCollect<'tcx> { }; let self_ty = self.tcx.type_of(item.def_id); + let self_ty = self.tcx.peel_off_ty_alias(self_ty); + match *self_ty.kind() { ty::Adt(def, _) => { self.check_def_id(item, self_ty, def.did()); @@ -197,6 +199,9 @@ impl<'tcx> InherentCollect<'tcx> { ty::Dynamic(data, ..) if data.principal_def_id().is_some() => { self.check_def_id(item, self_ty, data.principal_def_id().unwrap()); } + ty::TyAlias(..) => { + span_bug!(ty.span, "unexpected TyAlias in InherentCollect::check_item"); + } ty::Dynamic(..) => { struct_span_err!( self.tcx.sess, diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 1307f74f21071..ebff934fc7f5e 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -49,6 +49,8 @@ fn do_orphan_check_impl<'tcx>( let sp = tcx.def_span(def_id); let tr = impl_.of_trait.as_ref().unwrap(); + let trait_ref = tcx.peel_off_ty_alias(trait_ref); + // Ensure no opaque types are present in this impl header. See issues #76202 and #86411 for examples, // and #84660 where it would otherwise allow unsoundness. if trait_ref.has_opaque_types() { diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index eaf0310d57aec..b935b2c5cf282 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -257,6 +257,12 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_invariant_substs(current, substs, variance); } + ty::TyAlias(def_id, substs) => { + let binder_ty = self.tcx().bound_type_of(def_id); + let ty = binder_ty.subst(self.tcx(), substs); + self.add_constraints_from_ty(current, ty, variance); + } + ty::Dynamic(data, r, _) => { // The type `Foo` is contravariant w/r/t `'a`: let contra = self.contravariant(variance); diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 60157c3b9abe0..38244dce8acac 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -123,6 +123,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We should really try to normalize here. ty::Projection(ref pi) => Some(PointerKind::OfProjection(pi)), ty::Opaque(def_id, substs) => Some(PointerKind::OfOpaque(def_id, substs)), + ty::TyAlias(..) => bug!("unexpected TyAlias in pointer_kind"), ty::Param(ref p) => Some(PointerKind::OfParam(p)), // Insufficient type information. ty::Placeholder(..) | ty::Bound(..) | ty::Infer(_) => None, diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index a3ff703634037..e0a7511cd68c1 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -456,7 +456,8 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { | ty::Projection(..) | ty::Foreign(..) | ty::Param(..) - | ty::Opaque(..) => { + | ty::Opaque(..) + | ty::TyAlias(..) => { if t.flags().intersects(self.needs_canonical_flags) { t.super_fold_with(self) } else { diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index ff5d1a05a7062..9a58f907e87a2 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -210,7 +210,8 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { | ty::Param(..) | ty::Closure(..) | ty::GeneratorWitness(..) - | ty::Opaque(..) => t.super_fold_with(self), + | ty::Opaque(..) + | ty::TyAlias(..) => t.super_fold_with(self), ty::Placeholder(..) | ty::Bound(..) => bug!("unexpected type {:?}", t), } diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index a982f11f7187f..cc88898176a43 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -52,7 +52,7 @@ impl<'tcx> InferCtxt<'tcx> { span: Span, param_env: ty::ParamEnv<'tcx>, ) -> InferOk<'tcx, T> { - if !value.has_opaque_types() { + if !value.has_opaque_types() && !value.has_ty_alias() { return InferOk { value, obligations: vec![] }; } let mut obligations = vec![]; @@ -61,7 +61,7 @@ impl<'tcx> InferCtxt<'tcx> { .as_local() .map_or(false, |def_id| self.opaque_type_origin(def_id, span).is_some()) }; - let value = value.fold_with(&mut ty::fold::BottomUpFolder { + let value = self.tcx.peel_off_ty_alias(value).fold_with(&mut ty::fold::BottomUpFolder { tcx: self.tcx, lt_op: |lt| lt, ct_op: |ct| ct, @@ -548,6 +548,9 @@ impl<'tcx> InferCtxt<'tcx> { let item_bounds = tcx.bound_explicit_item_bounds(def_id.to_def_id()); for (predicate, _) in item_bounds.subst_iter_copied(tcx, substs) { + debug!(?predicate); + let predicate = tcx.peel_off_ty_alias(predicate); + let predicate = predicate.fold_with(&mut BottomUpFolder { tcx, ty_op: |ty| match *ty.kind() { diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs index 14ee9f0519010..81ad83ce16ca5 100644 --- a/compiler/rustc_infer/src/infer/outlives/components.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -169,6 +169,12 @@ fn compute_components<'tcx>( out.push(Component::UnresolvedInferenceVariable(infer_ty)); } + ty::TyAlias(def_id, substs) => { + let binder_ty = tcx.bound_type_of(def_id); + let ty = binder_ty.subst(tcx, substs); + compute_components(tcx, ty, out, visited); + } + // Most types do not introduce any region binders, nor // involve any other subtle cases, and so the WF relation // simply constraints any regions referenced directly by diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 7c99bb2790fd0..6fa42f292040d 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -8,7 +8,9 @@ use rustc_hir::{is_range_literal, Expr, ExprKind, Node}; use rustc_macros::LintDiagnostic; use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton}; use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable}; +use rustc_middle::ty::{ + self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, +}; use rustc_span::source_map; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol, DUMMY_SP}; @@ -1134,6 +1136,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { FfiSafe } + ty::TyAlias(def_id, substs) => { + let binder_ty = tcx.bound_type_of(def_id); + let ty = binder_ty.subst(tcx, substs); + let ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, ty); + self.check_type_for_ffi(cache, ty) + } + ty::Foreign(..) => FfiSafe, // While opaque types are checked for earlier, if a projection in a struct field diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 3d7e2a0839abc..af3572c633bd6 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1726,6 +1726,37 @@ impl<'tcx> TyCtxt<'tcx> { pub fn local_visibility(self, def_id: LocalDefId) -> Visibility { self.visibility(def_id).expect_local() } + + /// As long as the kind of `ty` is `TyAlias`, then it'll continue to peel it off and return + /// the type below it. + pub fn peel_off_ty_alias>(self, ty: T) -> T { + struct TyAliasPeeler<'t> { + tcx: TyCtxt<'t>, + } + + impl<'t> ty::TypeFolder<'t> for TyAliasPeeler<'t> { + fn tcx<'a>(&'a self) -> TyCtxt<'t> { + self.tcx + } + + fn fold_ty(&mut self, t: Ty<'t>) -> Ty<'t> { + use crate::ty::fold::{TypeFoldable, TypeSuperFoldable}; + use crate::ty::visit::TypeVisitable; + + match *t.kind() { + ty::TyAlias(def_id, substs) => { + let binder_ty = self.tcx.bound_type_of(def_id); + let ty = binder_ty.subst(self.tcx, substs); + ty.fold_with(self) + } + _ if !t.has_ty_alias() => t, + _ => t.super_fold_with(self), + } + } + } + + ty.fold_with(&mut TyAliasPeeler { tcx: self }) + } } /// A trait implemented for all `X<'a>` types that can be safely and @@ -1996,7 +2027,7 @@ pub mod tls { } macro_rules! sty_debug_print { - ($fmt: expr, $ctxt: expr, $($variant: ident),*) => {{ + ($fmt: expr, $ctxt: expr, $($variant: ident),* $(,)?) => {{ // Curious inner module to allow variant names to be used as // variable names. #[allow(non_snake_case)] @@ -2095,7 +2126,8 @@ impl<'tcx> TyCtxt<'tcx> { Infer, Projection, Opaque, - Foreign + Foreign, + TyAlias, )?; writeln!(fmt, "InternalSubsts interner: #{}", self.0.interners.substs.len())?; @@ -2633,6 +2665,11 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_ty(Opaque(def_id, substs)) } + #[inline] + pub fn mk_ty_alias(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> { + self.mk_ty(TyAlias(def_id, substs)) + } + pub fn mk_place_field(self, place: Place<'tcx>, f: Field, ty: Ty<'tcx>) -> Place<'tcx> { self.mk_place_elem(place, PlaceElem::Field(f, ty)) } diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 52f16ad88f693..45f1cc100ca1a 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -329,6 +329,7 @@ impl<'tcx> Ty<'tcx> { ty::Param(p) => format!("type parameter `{}`", p).into(), ty::Opaque(..) => "opaque type".into(), ty::Error(_) => "type error".into(), + ty::TyAlias(_, _) => "type alias".into(), } } @@ -366,6 +367,7 @@ impl<'tcx> Ty<'tcx> { ty::Projection(_) => "associated type".into(), ty::Param(_) => "type parameter".into(), ty::Opaque(..) => "opaque type".into(), + ty::TyAlias(_, _) => "type alias".into(), } } } diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 3be0bc4defc5c..6275d2f3806f1 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -127,6 +127,9 @@ pub fn simplify_type<'tcx>( TreatParams::AsPlaceholder => Some(PlaceholderSimplifiedType), TreatParams::AsInfer => None, }, + // A `TyAlias` is never fully normalized as you can always normalize it further so returning + // `None` all the time. + ty::TyAlias(..) => None, ty::Projection(_) => match treat_params { // When treating `ty::Param` as a placeholder, projections also // don't unify with anything else as long as they are fully normalized. @@ -229,7 +232,7 @@ impl DeepRejectCtxt { match impl_ty.kind() { // Start by checking whether the type in the impl may unify with // pretty much everything. Just return `true` in that case. - ty::Param(_) | ty::Projection(_) | ty::Error(_) => return true, + ty::Param(_) | ty::Projection(_) | ty::TyAlias(_, _) | ty::Error(_) => return true, // These types only unify with inference variables or their own // variant. ty::Bool @@ -352,7 +355,7 @@ impl DeepRejectCtxt { // projections can unify with other stuff. // // Looking forward to lazy normalization this is the safer strategy anyways. - ty::Projection(_) => true, + ty::Projection(_) | ty::TyAlias(_, _) => true, ty::Error(_) => true, diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 7201737be657b..c7ae2f3bc812a 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -155,6 +155,11 @@ impl FlagComputation { self.add_substs(substs); } + &ty::TyAlias(_, substs) => { + self.add_flags(TypeFlags::HAS_TY_ALIAS); + self.add_substs(substs); + } + &ty::Projection(data) => { self.add_flags(TypeFlags::HAS_TY_PROJECTION); self.add_projection_ty(data); diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 0a109fd8f44f8..919a45c2cff83 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -365,6 +365,12 @@ impl<'tcx> SizeSkeleton<'tcx> { } } + ty::TyAlias(def_id, substs) => { + let generic_ty = tcx.bound_type_of(def_id); + let concrete_ty = generic_ty.subst(tcx, substs); + SizeSkeleton::compute(concrete_ty, tcx, param_env) + } + _ => Err(err), } } @@ -637,7 +643,9 @@ where } }; - match *this.ty.kind() { + let ty = tcx.peel_off_ty_alias(this.ty); + + match *ty.kind() { ty::Bool | ty::Char | ty::Int(_) @@ -662,7 +670,7 @@ where // as the `Abi` or `FieldsShape` is checked by users. if i == 0 { let nil = tcx.mk_unit(); - let unit_ptr_ty = if this.ty.is_unsafe_ptr() { + let unit_ptr_ty = if ty.is_unsafe_ptr() { tcx.mk_mut_ptr(nil) } else { tcx.mk_mut_ref(tcx.lifetimes.re_static, nil) @@ -672,7 +680,7 @@ where // the `Result` should always work because the type is // always either `*mut ()` or `&'static mut ()`. return TyMaybeWithLayout::TyAndLayout(TyAndLayout { - ty: this.ty, + ty, ..tcx.layout_of(ty::ParamEnv::reveal_all().and(unit_ptr_ty)).unwrap() }); } @@ -770,7 +778,8 @@ where | ty::Opaque(..) | ty::Param(_) | ty::Infer(_) - | ty::Error(_) => bug!("TyAndLayout::field: unexpected type `{}`", this.ty), + | ty::TyAlias(_, _) + | ty::Error(_) => bug!("TyAndLayout::field: unexpected type `{}`", ty), } } diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 44b9548db89c8..ed9cc118f9a1f 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -264,6 +264,10 @@ fn characteristic_def_id_of_type_cached<'a>( return None; }), + // `TyAlias` always return `None` since the type alias' defining module is irrelevant for + // any decisions. + ty::TyAlias(..) => None, + ty::FnDef(def_id, _) | ty::Closure(def_id, _) | ty::Generator(def_id, _, _) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index c1c2e162f2839..26af425bf624a 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -780,6 +780,7 @@ pub trait PrettyPrinter<'tcx>: p!("]") } ty::Slice(ty) => p!("[", print(ty), "]"), + ty::TyAlias(def_id, substs) => p!(print_def_path(def_id, substs)), } Ok(self) diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 2cad333e3f52a..89266fcd85c92 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -639,6 +639,7 @@ impl<'tcx> TypeSuperFoldable<'tcx> for Ty<'tcx> { ty::Closure(did, substs) => ty::Closure(did, substs.try_fold_with(folder)?), ty::Projection(data) => ty::Projection(data.try_fold_with(folder)?), ty::Opaque(did, substs) => ty::Opaque(did, substs.try_fold_with(folder)?), + ty::TyAlias(did, substs) => ty::TyAlias(did, substs.try_fold_with(folder)?), ty::Bool | ty::Char @@ -685,6 +686,7 @@ impl<'tcx> TypeSuperVisitable<'tcx> for Ty<'tcx> { ty::Closure(_did, ref substs) => substs.visit_with(visitor), ty::Projection(ref data) => data.visit_with(visitor), ty::Opaque(_, ref substs) => substs.visit_with(visitor), + ty::TyAlias(_, ref substs) => substs.visit_with(visitor), ty::Bool | ty::Char diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index cf420bafeb12f..7f30b60c4ea16 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2021,6 +2021,12 @@ impl<'tcx> Ty<'tcx> { ty::Adt(adt, _) if adt.is_enum() => adt.repr().discr_type().to_ty(tcx), ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx), + ty::TyAlias(def_id, substs) => { + let binder_ty = tcx.bound_type_of(*def_id); + let ty = binder_ty.subst(tcx, substs); + ty.discriminant_ty(tcx) + } + ty::Param(_) | ty::Projection(_) | ty::Opaque(..) | ty::Infer(ty::TyVar(_)) => { let assoc_items = tcx.associated_item_def_ids( tcx.require_lang_item(hir::LangItem::DiscriminantKind, None), @@ -2106,6 +2112,7 @@ impl<'tcx> Ty<'tcx> { ty::Infer(ty::TyVar(_)) | ty::Bound(..) | ty::Placeholder(..) + | ty::TyAlias(..) | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { bug!("`ptr_metadata_ty` applied to unexpected type: {:?} (tail = {:?})", self, tail) } @@ -2178,7 +2185,7 @@ impl<'tcx> Ty<'tcx> { ty::Adt(def, _substs) => def.sized_constraint(tcx).0.is_empty(), - ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => false, + ty::Projection(_) | ty::Param(_) | ty::Opaque(..) | ty::TyAlias(..) => false, ty::Infer(ty::TyVar(_)) => false, @@ -2236,7 +2243,11 @@ impl<'tcx> Ty<'tcx> { // Might be, but not "trivial" so just giving the safe answer. ty::Adt(..) | ty::Closure(..) | ty::Opaque(..) => false, - ty::Projection(..) | ty::Param(..) | ty::Infer(..) | ty::Error(..) => false, + ty::Projection(..) + | ty::Param(..) + | ty::Infer(..) + | ty::TyAlias(_, _) + | ty::Error(..) => false, ty::Bound(..) | ty::Placeholder(..) => { bug!("`is_trivially_pure_clone_copy` applied to unexpected type: {:?}", self); diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index f73d062ba30a6..e0fa7dd2c6588 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -269,7 +269,7 @@ impl<'tcx> TyCtxt<'tcx> { ty::Tuple(_) => break, - ty::Projection(_) | ty::Opaque(..) => { + ty::Projection(_) | ty::Opaque(..) | ty::TyAlias(..) => { let normalized = normalize(ty); if ty == normalized { return ty; @@ -881,7 +881,8 @@ impl<'tcx> Ty<'tcx> { | ty::Opaque(..) | ty::Param(_) | ty::Placeholder(_) - | ty::Projection(_) => false, + | ty::Projection(_) + | ty::TyAlias(_, _) => false, } } @@ -921,7 +922,8 @@ impl<'tcx> Ty<'tcx> { | ty::Opaque(..) | ty::Param(_) | ty::Placeholder(_) - | ty::Projection(_) => false, + | ty::Projection(_) + | ty::TyAlias(_, _) => false, } } @@ -1048,6 +1050,12 @@ impl<'tcx> Ty<'tcx> { | ty::Placeholder(_) | ty::Infer(_) => false, + ty::TyAlias(def_id, substs) => { + let binder_ty = tcx.bound_type_of(*def_id); + let ty = binder_ty.subst(tcx, substs); + ty.is_structural_eq_shallow(tcx) + } + ty::Foreign(_) | ty::GeneratorWitness(..) | ty::Error(_) => false, } } @@ -1184,7 +1192,8 @@ pub fn needs_drop_components<'tcx>( | ty::Opaque(..) | ty::Infer(_) | ty::Closure(..) - | ty::Generator(..) => Ok(smallvec![ty]), + | ty::Generator(..) + | ty::TyAlias(_, _) => Ok(smallvec![ty]), } } @@ -1212,7 +1221,8 @@ pub fn is_trivially_const_drop<'tcx>(ty: Ty<'tcx>) -> bool { | ty::Param(_) | ty::Placeholder(_) | ty::Projection(_) - | ty::Infer(_) => false, + | ty::Infer(_) + | ty::TyAlias(_, _) => false, // Not trivial because they have components, and instead of looking inside, // we'll just perform trait selection. diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index c09f71f9a6d09..3c1e7471971e8 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -92,6 +92,9 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone { fn has_opaque_types(&self) -> bool { self.has_type_flags(TypeFlags::HAS_TY_OPAQUE) } + fn has_ty_alias(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_TY_ALIAS) + } fn references_error(&self) -> bool { self.has_type_flags(TypeFlags::HAS_ERROR) } diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 91db9698c41b2..7c0045b4724cd 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -2,7 +2,7 @@ //! WARNING: this does not keep track of the region depth. use crate::ty::subst::{GenericArg, GenericArgKind}; -use crate::ty::{self, Ty}; +use crate::ty::{self, Ty, TyCtxt}; use rustc_data_structures::sso::SsoHashSet; use smallvec::{self, SmallVec}; @@ -194,6 +194,16 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) | ty::FnDef(_, substs) => { stack.extend(substs.iter().rev()); } + ty::TyAlias(def_id, substs) => { + let ty = crate::ty::tls::with(|tcx| { + let tcx: TyCtxt<'tcx> = unsafe { std::mem::transmute(tcx) }; + let binder_ty = tcx.bound_type_of(def_id); + let ty = binder_ty.subst(tcx, substs); + + tcx.peel_off_ty_alias(ty) + }); + stack.extend([ty.into()]); + } ty::Tuple(ts) => stack.extend(ts.as_substs().iter().rev()), ty::GeneratorWitness(ts) => { stack.extend(ts.skip_binder().iter().rev().map(|ty| ty.into())); diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index cf8ae776be969..859edaf8806d7 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -139,6 +139,9 @@ impl<'tcx> ConstToPat<'tcx> { ty::RawPtr(..) => { "raw pointers cannot be used in patterns".to_string() } + ty::TyAlias(..) => { + bug!("use of a value of a type alias inside a pattern") + } _ => { bug!("use of a value of `{non_sm_ty}` inside a pattern") } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index df8454ed4ee06..99119536f4ba7 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -253,6 +253,11 @@ where })?; } } + ty::TyAlias(def_id, substs) => { + let generic_ty = tcx.bound_type_of(def_id); + let concrete_ty = tcx.peel_off_ty_alias(generic_ty.subst(tcx, substs)); + return self.visit_ty(concrete_ty); + } // These types don't have their own def-ids (but may have subcomponents // with def-ids that should be visited recursively). ty::Bool diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index 6aa031c8378e6..7b8d4dc4c9429 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -641,6 +641,12 @@ fn encode_ty<'tcx>( typeid.push_str(&s); } + ty::TyAlias(def_id, substs) => { + let binder_ty = tcx.bound_type_of(*def_id); + let ty = binder_ty.subst(tcx, substs); + return encode_ty(tcx, ty, dict, options); + } + // Unexpected types ty::Bound(..) | ty::Error(..) @@ -795,6 +801,12 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio } } + ty::TyAlias(def_id, substs) => { + let binder_ty = tcx.bound_type_of(*def_id); + let ty = binder_ty.subst(tcx, substs); + return transform_ty(tcx, ty, options); + } + ty::Bound(..) | ty::Error(..) | ty::GeneratorWitness(..) diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index ecfe6861e84cb..4529476a74513 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -387,6 +387,8 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { } let start = self.out.len(); + let ty = self.tcx.peel_off_ty_alias(ty); + match *ty.kind() { // Basic types, handled above. ty::Bool | ty::Char | ty::Str | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Never => { @@ -439,9 +441,9 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { // Mangle all nominal types as paths. ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), substs) | ty::FnDef(def_id, substs) + | ty::Closure(def_id, substs) | ty::Opaque(def_id, substs) | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) - | ty::Closure(def_id, substs) | ty::Generator(def_id, substs, _) => { self = self.print_def_path(def_id, substs)?; } @@ -490,6 +492,8 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { } ty::GeneratorWitness(_) => bug!("symbol_names: unexpected `GeneratorWitness`"), + + ty::TyAlias(..) => bug!("symbol_names: unexpected projection"), } // Only cache types that do not refer to an enclosing diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 8aab75490a81b..49b8c4ad6b1cc 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -735,6 +735,8 @@ impl<'tcx> TypeVisitor<'tcx> for OrphanChecker<'tcx> { // that they implement, so we don't use this behavior. self.found_non_local_ty(ty) } + + ty::TyAlias(..) => self.visit_ty(self.tcx.peel_off_ty_alias(ty)), }; // A bit of a hack, the `OrphanChecker` is only used to visit a `TraitRef`, so // the first type we visit is always the self type. diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 1217d264a9c1a..288dfe6b99d82 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1752,6 +1752,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ty::Generator(..) => Some(16), ty::Foreign(..) => Some(17), ty::GeneratorWitness(..) => Some(18), + ty::TyAlias(..) => Some(19), ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None, } } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 0bf54c096cd40..a6ca4c5060b7b 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -153,6 +153,8 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>( infcx.tcx.def_path_str(def_id) ); + let ty = infcx.tcx.peel_off_ty_alias(ty); + let trait_ref = ty::Binder::dummy(ty::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) }); let obligation = Obligation { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index c8276854016f0..4b350101a4d61 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -30,6 +30,7 @@ use rustc_hir::lang_items::LangItem; use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; +use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable}; use rustc_middle::ty::DefIdTree; use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt}; @@ -383,12 +384,16 @@ where pub(crate) fn needs_normalization<'tcx, T: TypeVisitable<'tcx>>(value: &T, reveal: Reveal) -> bool { match reveal { - Reveal::UserFacing => value - .has_type_flags(ty::TypeFlags::HAS_TY_PROJECTION | ty::TypeFlags::HAS_CT_PROJECTION), + Reveal::UserFacing => value.has_type_flags( + ty::TypeFlags::HAS_TY_PROJECTION + | ty::TypeFlags::HAS_CT_PROJECTION + | ty::TypeFlags::HAS_TY_ALIAS, + ), Reveal::All => value.has_type_flags( ty::TypeFlags::HAS_TY_PROJECTION | ty::TypeFlags::HAS_TY_OPAQUE - | ty::TypeFlags::HAS_CT_PROJECTION, + | ty::TypeFlags::HAS_CT_PROJECTION + | ty::TypeFlags::HAS_TY_ALIAS, ), } } @@ -459,6 +464,28 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { value.fold_with(self) } } + + fn fold_alias_or_revealed_opaque( + &mut self, + ty: Ty<'tcx>, + def_id: DefId, + substs: SubstsRef<'tcx>, + ) -> Ty<'tcx> { + let recursion_limit = self.tcx().recursion_limit(); + if !recursion_limit.value_within_limit(self.depth) { + let obligation = + Obligation::with_depth(self.cause.clone(), recursion_limit.0, self.param_env, ty); + self.selcx.infcx().err_ctxt().report_overflow_error(&obligation, true); + } + + let substs = substs.fold_with(self); + let generic_ty = self.tcx().bound_type_of(def_id); + let concrete_ty = generic_ty.subst(self.tcx(), substs); + self.depth += 1; + let folded_ty = self.fold_ty(concrete_ty); + self.depth -= 1; + folded_ty + } } impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { @@ -512,30 +539,12 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { // Only normalize `impl Trait` outside of type inference, usually in codegen. match self.param_env.reveal() { Reveal::UserFacing => ty.super_fold_with(self), - - Reveal::All => { - let recursion_limit = self.tcx().recursion_limit(); - if !recursion_limit.value_within_limit(self.depth) { - let obligation = Obligation::with_depth( - self.cause.clone(), - recursion_limit.0, - self.param_env, - ty, - ); - self.selcx.infcx().err_ctxt().report_overflow_error(&obligation, true); - } - - let substs = substs.fold_with(self); - let generic_ty = self.tcx().bound_type_of(def_id); - let concrete_ty = generic_ty.subst(self.tcx(), substs); - self.depth += 1; - let folded_ty = self.fold_ty(concrete_ty); - self.depth -= 1; - folded_ty - } + Reveal::All => self.fold_alias_or_revealed_opaque(ty, def_id, substs), } } + ty::TyAlias(def_id, substs) => self.fold_alias_or_revealed_opaque(ty, def_id, substs), + ty::Projection(data) if !data.has_escaping_bound_vars() => { // This branch is *mostly* just an optimization: when we don't // have escaping bound vars, we don't need to replace them with @@ -1414,6 +1423,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( let bounds = match *obligation.predicate.self_ty().kind() { ty::Projection(ref data) => tcx.bound_item_bounds(data.item_def_id).subst(tcx, data.substs), ty::Opaque(def_id, substs) => tcx.bound_item_bounds(def_id).subst(tcx, substs), + // ty::TyAlias(def_id, substs) => tcx.bound_item_bounds(def_id).subst(tcx, substs), ty::Infer(ty::TyVar(_)) => { // If the self-type is an inference variable, then it MAY wind up // being a projected type, so induce an ambiguity. @@ -1650,6 +1660,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::Bound(..) | ty::Placeholder(..) | ty::Infer(..) + | ty::TyAlias(..) | ty::Error(_) => false, } } @@ -1735,6 +1746,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( } false } + + ty::TyAlias(..) => unreachable!(), } } super::ImplSource::Param(..) => { diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index aad3c37f84e5a..8bd79a7d99abe 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -68,6 +68,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { | ty::Placeholder(..) | ty::Infer(_) | ty::Bound(..) - | ty::Generator(..) => false, + | ty::Generator(..) + | ty::TyAlias(..) => false, } } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 715f5be8e2f4b..4a108e067b1b3 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -10,8 +10,10 @@ use crate::traits::project::{needs_normalization, BoundVarReplacer, PlaceholderR use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal}; use rustc_data_structures::sso::SsoHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_hir::def_id::DefId; use rustc_infer::traits::Normalized; use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; +use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor}; use rustc_span::DUMMY_SP; @@ -163,6 +165,40 @@ struct QueryNormalizer<'cx, 'tcx> { universes: Vec>, } +impl<'cx, 'tcx> QueryNormalizer<'cx, 'tcx> { + fn fold_alias_or_revealed_opaque( + &mut self, + ty: Ty<'tcx>, + def_id: DefId, + substs: SubstsRef<'tcx>, + ) -> Result, >::Error> { + let substs = substs.try_fold_with(self)?; + let recursion_limit = self.tcx().recursion_limit(); + if !recursion_limit.value_within_limit(self.anon_depth) { + let obligation = + Obligation::with_depth(self.cause.clone(), recursion_limit.0, self.param_env, ty); + self.infcx.err_ctxt().report_overflow_error(&obligation, true); + } + + let generic_ty = self.tcx().bound_type_of(def_id); + let concrete_ty = generic_ty.subst(self.tcx(), substs); + self.anon_depth += 1; + if concrete_ty == ty { + bug!( + "infinite recursion generic_ty: {:#?}, substs: {:#?}, \ + concrete_ty: {:#?}, ty: {:#?}", + generic_ty, + substs, + concrete_ty, + ty + ); + } + let folded_ty = ensure_sufficient_stack(|| self.try_fold_ty(concrete_ty)); + self.anon_depth -= 1; + folded_ty + } +} + impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { type Error = NoSolution; @@ -202,40 +238,12 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { // Only normalize `impl Trait` outside of type inference, usually in codegen. match self.param_env.reveal() { Reveal::UserFacing => ty.try_super_fold_with(self), - - Reveal::All => { - let substs = substs.try_fold_with(self)?; - let recursion_limit = self.tcx().recursion_limit(); - if !recursion_limit.value_within_limit(self.anon_depth) { - let obligation = Obligation::with_depth( - self.cause.clone(), - recursion_limit.0, - self.param_env, - ty, - ); - self.infcx.err_ctxt().report_overflow_error(&obligation, true); - } - - let generic_ty = self.tcx().bound_type_of(def_id); - let concrete_ty = generic_ty.subst(self.tcx(), substs); - self.anon_depth += 1; - if concrete_ty == ty { - bug!( - "infinite recursion generic_ty: {:#?}, substs: {:#?}, \ - concrete_ty: {:#?}, ty: {:#?}", - generic_ty, - substs, - concrete_ty, - ty - ); - } - let folded_ty = ensure_sufficient_stack(|| self.try_fold_ty(concrete_ty)); - self.anon_depth -= 1; - folded_ty - } + Reveal::All => self.fold_alias_or_revealed_opaque(ty, def_id, substs), } } + ty::TyAlias(def_id, substs) => self.fold_alias_or_revealed_opaque(ty, def_id, substs), + ty::Projection(data) if !data.has_escaping_bound_vars() => { // This branch is just an optimization: when we don't have escaping bound vars, // we don't need to replace them with placeholders (see branch below). diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 4c5bc333961dc..70d6fa01dc35f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -959,7 +959,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Bound(..) | ty::Param(_) | ty::Placeholder(_) - | ty::Projection(_) => { + | ty::Projection(_) + | ty::TyAlias(..) => { // We don't know if these are `~const Destruct`, at least // not structurally... so don't push a candidate. } @@ -1018,7 +1019,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { - let self_ty = self.infcx().shallow_resolve(obligation.self_ty().skip_binder()); + let infcx = self.infcx(); + let self_ty = infcx.shallow_resolve(obligation.self_ty().skip_binder()); + let self_ty = infcx.tcx.peel_off_ty_alias(self_ty); match self_ty.kind() { ty::Tuple(_) => { candidates.vec.push(BuiltinCandidate { has_nested: false }); @@ -1052,6 +1055,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Error(_) | ty::Infer(_) | ty::Placeholder(_) => {} + ty::TyAlias(..) => unreachable!(), } } } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index ed22058c64615..cac57906f7a9b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -154,6 +154,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let (def_id, substs) = match *placeholder_self_ty.kind() { ty::Projection(proj) => (proj.item_def_id, proj.substs), ty::Opaque(def_id, substs) => (def_id, substs), + ty::TyAlias(def_id, substs) => (def_id, substs), _ => bug!("projection candidate for unexpected type: {:?}", placeholder_self_ty), }; @@ -1249,7 +1250,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // If we have a projection type, make sure to normalize it so we replace it // with a fresh infer variable - ty::Projection(..) => { + ty::Projection(..) | ty::TyAlias(..) => { let predicate = normalize_with_depth_to( self, obligation.param_env, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 9ebff48920160..19131e61bdff7 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1842,7 +1842,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { })) } - ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => None, + ty::Projection(_) | ty::Param(_) | ty::Opaque(..) | ty::TyAlias(..) => None, ty::Infer(ty::TyVar(_)) => Ambiguous, ty::Placeholder(..) @@ -1942,7 +1942,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - ty::Adt(..) | ty::Projection(..) | ty::Param(..) | ty::Opaque(..) => { + ty::Adt(..) | ty::Projection(..) | ty::Param(..) | ty::Opaque(..) | ty::TyAlias(..) => { // Fallback to whatever user-defined impls exist in this case. None } @@ -2034,8 +2034,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { t.rebind(def.all_fields().map(|f| f.ty(self.tcx(), substs)).collect()) } - ty::Opaque(def_id, substs) => { - // We can resolve the `impl Trait` to its concrete type, + ty::Opaque(def_id, substs) | ty::TyAlias(def_id, substs) => { + // We can resolve the `impl Trait` and the type alias to its concrete type, // which enforces a DAG between the functions requiring // the auto trait bounds in question. t.rebind(vec![self.tcx().bound_type_of(def_id).subst(self.tcx(), substs)]) diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs index 932dbbb81e5cc..aeecf2e7f7910 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_match.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs @@ -209,6 +209,11 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> { } } + ty::TyAlias(..) => { + // Type aliases are transparent and should never be seen by structural match checking. + bug!("unexpected TyAlias in TypeVisitor::visit_ty"); + } + ty::Float(_) => { if !self.adt_const_param { return ControlFlow::CONTINUE; diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 30feabe1a0959..1fbd4d853b2ef 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -4,7 +4,8 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeVisitable}; +use rustc_middle::ty::walk::TypeWalker; +use rustc_middle::ty::{self, ParamEnv, ToPredicate, Ty, TyCtxt, TypeVisitable}; use rustc_span::Span; use std::iter; @@ -430,6 +431,218 @@ impl<'tcx> WfPredicates<'tcx> { } } + fn compute_ty( + &mut self, + ty: Ty<'tcx>, + walker: &mut TypeWalker<'tcx>, + depth: usize, + param_env: ParamEnv<'tcx>, + ) { + match *ty.kind() { + ty::Bool + | ty::Char + | ty::Int(..) + | ty::Uint(..) + | ty::Float(..) + | ty::Error(_) + | ty::Str + | ty::GeneratorWitness(..) + | ty::Never + | ty::Param(_) + | ty::Bound(..) + | ty::Placeholder(..) + | ty::Foreign(..) => { + // WfScalar, WfParameter, etc + } + + // Can only infer to `ty::Int(_) | ty::Uint(_)`. + ty::Infer(ty::IntVar(_)) => {} + + // Can only infer to `ty::Float(_)`. + ty::Infer(ty::FloatVar(_)) => {} + + ty::Slice(subty) => { + self.require_sized(subty, traits::SliceOrArrayElem); + } + + ty::Array(subty, _) => { + self.require_sized(subty, traits::SliceOrArrayElem); + // Note that we handle the len is implicitly checked while walking `arg`. + } + + ty::Tuple(ref tys) => { + if let Some((_last, rest)) = tys.split_last() { + for &elem in rest { + self.require_sized(elem, traits::TupleElem); + } + } + } + + ty::RawPtr(_) => { + // Simple cases that are WF if their type args are WF. + } + + ty::Projection(data) => { + walker.skip_current_subtree(); // Subtree handled by compute_projection. + self.compute_projection(data); + } + + ty::Adt(def, substs) => { + // WfNominalType + let obligations = self.nominal_obligations(def.did(), substs); + self.out.extend(obligations); + } + + ty::FnDef(did, substs) => { + let obligations = self.nominal_obligations(did, substs); + self.out.extend(obligations); + } + + ty::Ref(r, rty, _) => { + // WfReference + if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() { + let cause = self.cause(traits::ReferenceOutlivesReferent(ty)); + self.out.push(traits::Obligation::with_depth( + cause, + depth, + param_env, + ty::Binder::dummy(ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate( + rty, r, + ))) + .to_predicate(self.tcx()), + )); + } + } + + ty::Generator(did, substs, ..) => { + // Walk ALL the types in the generator: this will + // include the upvar types as well as the yield + // type. Note that this is mildly distinct from + // the closure case, where we have to be careful + // about the signature of the closure. We don't + // have the problem of implied bounds here since + // generators don't take arguments. + let obligations = self.nominal_obligations(did, substs); + self.out.extend(obligations); + } + + ty::Closure(did, substs) => { + // Only check the upvar types for WF, not the rest + // of the types within. This is needed because we + // capture the signature and it may not be WF + // without the implied bounds. Consider a closure + // like `|x: &'a T|` -- it may be that `T: 'a` is + // not known to hold in the creator's context (and + // indeed the closure may not be invoked by its + // creator, but rather turned to someone who *can* + // verify that). + // + // The special treatment of closures here really + // ought not to be necessary either; the problem + // is related to #25860 -- there is no way for us + // to express a fn type complete with the implied + // bounds that it is assuming. I think in reality + // the WF rules around fn are a bit messed up, and + // that is the rot problem: `fn(&'a T)` should + // probably always be WF, because it should be + // shorthand for something like `where(T: 'a) { + // fn(&'a T) }`, as discussed in #25860. + walker.skip_current_subtree(); // subtree handled below + // FIXME(eddyb) add the type to `walker` instead of recursing. + self.compute(substs.as_closure().tupled_upvars_ty().into()); + // Note that we cannot skip the generic types + // types. Normally, within the fn + // body where they are created, the generics will + // always be WF, and outside of that fn body we + // are not directly inspecting closure types + // anyway, except via auto trait matching (which + // only inspects the upvar types). + // But when a closure is part of a type-alias-impl-trait + // then the function that created the defining site may + // have had more bounds available than the type alias + // specifies. This may cause us to have a closure in the + // hidden type that is not actually well formed and + // can cause compiler crashes when the user abuses unsafe + // code to procure such a closure. + // See src/test/ui/type-alias-impl-trait/wf_check_closures.rs + let obligations = self.nominal_obligations(did, substs); + self.out.extend(obligations); + } + + ty::FnPtr(_) => { + // let the loop iterate into the argument/return + // types appearing in the fn signature + } + + ty::Opaque(did, substs) => { + // All of the requirements on type parameters + // have already been checked for `impl Trait` in + // return position. We do need to check type-alias-impl-trait though. + if ty::is_impl_trait_defn(self.tcx, did).is_none() { + let obligations = self.nominal_obligations(did, substs); + self.out.extend(obligations); + } + } + + ty::Dynamic(data, r, _) => { + // WfObject + // + // Here, we defer WF checking due to higher-ranked + // regions. This is perhaps not ideal. + self.from_object_ty(ty, data, r); + + // FIXME(#27579) RFC also considers adding trait + // obligations that don't refer to Self and + // checking those + + let defer_to_coercion = self.tcx().features().object_safe_for_dispatch; + + if !defer_to_coercion { + let cause = self.cause(traits::WellFormed(None)); + let component_traits = data.auto_traits().chain(data.principal_def_id()); + let tcx = self.tcx(); + self.out.extend(component_traits.map(|did| { + traits::Obligation::with_depth( + cause.clone(), + depth, + param_env, + ty::Binder::dummy(ty::PredicateKind::ObjectSafe(did)).to_predicate(tcx), + ) + })); + } + } + + // Inference variables are the complicated case, since we don't + // know what type they are. We do two things: + // + // 1. Check if they have been resolved, and if so proceed with + // THAT type. + // 2. If not, we've at least simplified things (e.g., we went + // from `Vec<$0>: WF` to `$0: WF`), so we can + // register a pending obligation and keep + // moving. (Goal is that an "inductive hypothesis" + // is satisfied to ensure termination.) + // See also the comment on `fn obligations`, describing "livelock" + // prevention, which happens before this can be reached. + ty::Infer(_) => { + let cause = self.cause(traits::WellFormed(None)); + self.out.push(traits::Obligation::with_depth( + cause, + self.recursion_depth, + param_env, + ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())) + .to_predicate(self.tcx()), + )); + } + + ty::TyAlias(def_id, substs) => { + let binder_ty = self.tcx().bound_type_of(def_id); + let ty = binder_ty.subst(self.tcx(), substs); + self.compute_ty(ty, walker, depth, param_env); + } + } + } + /// Pushes all the predicates needed to validate that `ty` is WF into `out`. #[instrument(level = "debug", skip(self))] fn compute(&mut self, arg: GenericArg<'tcx>) { @@ -487,208 +700,7 @@ impl<'tcx> WfPredicates<'tcx> { } }; - debug!("wf bounds for ty={:?} ty.kind={:#?}", ty, ty.kind()); - - match *ty.kind() { - ty::Bool - | ty::Char - | ty::Int(..) - | ty::Uint(..) - | ty::Float(..) - | ty::Error(_) - | ty::Str - | ty::GeneratorWitness(..) - | ty::Never - | ty::Param(_) - | ty::Bound(..) - | ty::Placeholder(..) - | ty::Foreign(..) => { - // WfScalar, WfParameter, etc - } - - // Can only infer to `ty::Int(_) | ty::Uint(_)`. - ty::Infer(ty::IntVar(_)) => {} - - // Can only infer to `ty::Float(_)`. - ty::Infer(ty::FloatVar(_)) => {} - - ty::Slice(subty) => { - self.require_sized(subty, traits::SliceOrArrayElem); - } - - ty::Array(subty, _) => { - self.require_sized(subty, traits::SliceOrArrayElem); - // Note that we handle the len is implicitly checked while walking `arg`. - } - - ty::Tuple(ref tys) => { - if let Some((_last, rest)) = tys.split_last() { - for &elem in rest { - self.require_sized(elem, traits::TupleElem); - } - } - } - - ty::RawPtr(_) => { - // Simple cases that are WF if their type args are WF. - } - - ty::Projection(data) => { - walker.skip_current_subtree(); // Subtree handled by compute_projection. - self.compute_projection(data); - } - - ty::Adt(def, substs) => { - // WfNominalType - let obligations = self.nominal_obligations(def.did(), substs); - self.out.extend(obligations); - } - - ty::FnDef(did, substs) => { - let obligations = self.nominal_obligations(did, substs); - self.out.extend(obligations); - } - - ty::Ref(r, rty, _) => { - // WfReference - if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() { - let cause = self.cause(traits::ReferenceOutlivesReferent(ty)); - self.out.push(traits::Obligation::with_depth( - cause, - depth, - param_env, - ty::Binder::dummy(ty::PredicateKind::TypeOutlives( - ty::OutlivesPredicate(rty, r), - )) - .to_predicate(self.tcx()), - )); - } - } - - ty::Generator(did, substs, ..) => { - // Walk ALL the types in the generator: this will - // include the upvar types as well as the yield - // type. Note that this is mildly distinct from - // the closure case, where we have to be careful - // about the signature of the closure. We don't - // have the problem of implied bounds here since - // generators don't take arguments. - let obligations = self.nominal_obligations(did, substs); - self.out.extend(obligations); - } - - ty::Closure(did, substs) => { - // Only check the upvar types for WF, not the rest - // of the types within. This is needed because we - // capture the signature and it may not be WF - // without the implied bounds. Consider a closure - // like `|x: &'a T|` -- it may be that `T: 'a` is - // not known to hold in the creator's context (and - // indeed the closure may not be invoked by its - // creator, but rather turned to someone who *can* - // verify that). - // - // The special treatment of closures here really - // ought not to be necessary either; the problem - // is related to #25860 -- there is no way for us - // to express a fn type complete with the implied - // bounds that it is assuming. I think in reality - // the WF rules around fn are a bit messed up, and - // that is the rot problem: `fn(&'a T)` should - // probably always be WF, because it should be - // shorthand for something like `where(T: 'a) { - // fn(&'a T) }`, as discussed in #25860. - walker.skip_current_subtree(); // subtree handled below - // FIXME(eddyb) add the type to `walker` instead of recursing. - self.compute(substs.as_closure().tupled_upvars_ty().into()); - // Note that we cannot skip the generic types - // types. Normally, within the fn - // body where they are created, the generics will - // always be WF, and outside of that fn body we - // are not directly inspecting closure types - // anyway, except via auto trait matching (which - // only inspects the upvar types). - // But when a closure is part of a type-alias-impl-trait - // then the function that created the defining site may - // have had more bounds available than the type alias - // specifies. This may cause us to have a closure in the - // hidden type that is not actually well formed and - // can cause compiler crashes when the user abuses unsafe - // code to procure such a closure. - // See src/test/ui/type-alias-impl-trait/wf_check_closures.rs - let obligations = self.nominal_obligations(did, substs); - self.out.extend(obligations); - } - - ty::FnPtr(_) => { - // let the loop iterate into the argument/return - // types appearing in the fn signature - } - - ty::Opaque(did, substs) => { - // All of the requirements on type parameters - // have already been checked for `impl Trait` in - // return position. We do need to check type-alias-impl-trait though. - if ty::is_impl_trait_defn(self.tcx, did).is_none() { - let obligations = self.nominal_obligations(did, substs); - self.out.extend(obligations); - } - } - - ty::Dynamic(data, r, _) => { - // WfObject - // - // Here, we defer WF checking due to higher-ranked - // regions. This is perhaps not ideal. - self.from_object_ty(ty, data, r); - - // FIXME(#27579) RFC also considers adding trait - // obligations that don't refer to Self and - // checking those - - let defer_to_coercion = self.tcx().features().object_safe_for_dispatch; - - if !defer_to_coercion { - let cause = self.cause(traits::WellFormed(None)); - let component_traits = data.auto_traits().chain(data.principal_def_id()); - let tcx = self.tcx(); - self.out.extend(component_traits.map(|did| { - traits::Obligation::with_depth( - cause.clone(), - depth, - param_env, - ty::Binder::dummy(ty::PredicateKind::ObjectSafe(did)) - .to_predicate(tcx), - ) - })); - } - } - - // Inference variables are the complicated case, since we don't - // know what type they are. We do two things: - // - // 1. Check if they have been resolved, and if so proceed with - // THAT type. - // 2. If not, we've at least simplified things (e.g., we went - // from `Vec<$0>: WF` to `$0: WF`), so we can - // register a pending obligation and keep - // moving. (Goal is that an "inductive hypothesis" - // is satisfied to ensure termination.) - // See also the comment on `fn obligations`, describing "livelock" - // prevention, which happens before this can be reached. - ty::Infer(_) => { - let cause = self.cause(traits::WellFormed(None)); - self.out.push(traits::Obligation::with_depth( - cause, - self.recursion_depth, - param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())) - .to_predicate(self.tcx()), - )); - } - } - - debug!(?self.out); + self.compute_ty(ty, &mut walker, depth, param_env); } } diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 45d5ea93d547f..0fa32ede0840d 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -268,7 +268,9 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { let uint = |i| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(i)); let float = |f| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Float(f)); - match *self.kind() { + let ty = interner.tcx.peel_off_ty_alias(self); + + match *ty.kind() { ty::Bool => chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Bool), ty::Char => chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Char), ty::Int(ty) => match ty { @@ -365,6 +367,9 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { } ty::Infer(_infer) => unimplemented!(), ty::Error(_) => chalk_ir::TyKind::Error, + ty::TyAlias(..) => { + bug!("TyAlias should have been normalized before reaching this point") + } } .intern(interner) } diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs index d5a8ca5ea784a..96280df648cab 100644 --- a/compiler/rustc_traits/src/dropck_outlives.rs +++ b/compiler/rustc_traits/src/dropck_outlives.rs @@ -281,7 +281,7 @@ fn dtorck_constraint_for_ty<'tcx>( } // Types that can't be resolved. Pass them forward. - ty::Projection(..) | ty::Opaque(..) | ty::Param(..) => { + ty::Projection(..) | ty::Opaque(..) | ty::Param(..) | ty::TyAlias(..) => { constraints.dtorck_types.push(ty); } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 345911f4309ae..51527ca908c0c 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -1345,6 +1345,12 @@ fn layout_of_uncached<'tcx>( bug!("Layout::compute: unexpected type `{}`", ty) } + ty::TyAlias(def_id, substs) => { + let binder_ty = tcx.bound_type_of(def_id); + let ty = binder_ty.subst(tcx, substs); + return layout_of_uncached(cx, ty); + } + ty::Bound(..) | ty::Param(_) | ty::Error(_) => { return Err(LayoutError::Unknown(ty)); } diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs index 7f48fb804178d..3f865d5fed214 100644 --- a/compiler/rustc_ty_utils/src/representability.rs +++ b/compiler/rustc_ty_utils/src/representability.rs @@ -47,6 +47,16 @@ fn representability_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Representabilit } Representability::Representable } + ty::TyAlias(def_id, substs) => { + let binder_ty = tcx.bound_type_of(def_id); + let ty = binder_ty.subst(tcx, substs); + representability_ty(tcx, ty) + } + ty::Closure(..) => { + // this check is run on type definitions, so we don't expect + // to see closure types + bug!("requires check invoked on inapplicable type: {:?}", ty) + } _ => Representability::Representable, } } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 3eebb4ace477f..5d3f399f813e4 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -37,7 +37,7 @@ fn sized_constraint_for_ty<'tcx>( .collect() } - Projection(..) | Opaque(..) => { + Projection(..) | Opaque(..) | TyAlias(..) => { // must calculate explicitly. // FIXME: consider special-casing always-Sized projections vec![ty] diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 7fbe78aa52353..00718f494abb8 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -230,7 +230,8 @@ bitflags! { /// Could this type be normalized further? const HAS_PROJECTION = TypeFlags::HAS_TY_PROJECTION.bits | TypeFlags::HAS_TY_OPAQUE.bits - | TypeFlags::HAS_CT_PROJECTION.bits; + | TypeFlags::HAS_CT_PROJECTION.bits + | TypeFlags::HAS_TY_ALIAS.bits; /// Is an error type/const reachable? const HAS_ERROR = 1 << 13; @@ -255,6 +256,9 @@ bitflags! { /// Does this value have `InferConst::Fresh`? const HAS_CT_FRESH = 1 << 19; + + /// Does this have `TyAlias`? + const HAS_TY_ALIAS = 1 << 20; } } diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs index a4fb1480fa448..d4188c03649b9 100644 --- a/compiler/rustc_type_ir/src/sty.rs +++ b/compiler/rustc_type_ir/src/sty.rs @@ -109,6 +109,10 @@ pub enum TyKind { /// ``` FnDef(I::DefId, I::SubstsRef), + /// A type alias (`type Alias = i8;`) containing the `DefId` of the aliased type and its + /// generics. + TyAlias(I::DefId, I::SubstsRef), + /// A pointer to a function. Written as `fn() -> i32`. /// /// Note that both functions and closures start out as either @@ -259,6 +263,7 @@ const fn tykind_discriminant(value: &TyKind) -> usize { Placeholder(_) => 24, Infer(_) => 25, Error(_) => 26, + TyAlias(_, _) => 27, } } @@ -293,6 +298,7 @@ impl Clone for TyKind { Placeholder(p) => Placeholder(p.clone()), Infer(t) => Infer(t.clone()), Error(e) => Error(e.clone()), + TyAlias(t, s) => TyAlias(t.clone(), s.clone()), } } } @@ -351,6 +357,9 @@ impl PartialEq for TyKind { (&Placeholder(ref __self_0), &Placeholder(ref __arg_1_0)) => __self_0 == __arg_1_0, (&Infer(ref __self_0), &Infer(ref __arg_1_0)) => __self_0 == __arg_1_0, (&Error(ref __self_0), &Error(ref __arg_1_0)) => __self_0 == __arg_1_0, + (&TyAlias(ref __self_0, ref __self_1), &TyAlias(ref __arg_1_0, ref __arg_1_1)) => { + __self_0 == __arg_1_0 && __self_1 == __arg_1_1 + } _ => true, } } else { @@ -464,6 +473,12 @@ impl Ord for TyKind { } (&Infer(ref __self_0), &Infer(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0), (&Error(ref __self_0), &Error(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0), + (&TyAlias(ref __self_0, ref __self_1), &TyAlias(ref __arg_1_0, ref __arg_1_1)) => { + match Ord::cmp(__self_0, __arg_1_0) { + Ordering::Equal => Ord::cmp(__self_1, __arg_1_1), + cmp => cmp, + } + } _ => Ordering::Equal, } } else { @@ -580,6 +595,11 @@ impl hash::Hash for TyKind { hash::Hash::hash(&tykind_discriminant(self), state); hash::Hash::hash(__self_0, state) } + (&TyAlias(ref __self_0, ref __self_1),) => { + hash::Hash::hash(&tykind_discriminant(self), state); + hash::Hash::hash(__self_0, state); + hash::Hash::hash(__self_1, state) + } _ => hash::Hash::hash(&tykind_discriminant(self), state), } } @@ -619,6 +639,7 @@ impl fmt::Debug for TyKind { Placeholder(f0) => Formatter::debug_tuple_field1_finish(f, "Placeholder", f0), Infer(f0) => Formatter::debug_tuple_field1_finish(f, "Infer", f0), TyKind::Error(f0) => Formatter::debug_tuple_field1_finish(f, "Error", f0), + TyAlias(f0, f1) => Formatter::debug_tuple_field2_finish(f, "TyAlias", f0, f1), } } } @@ -721,6 +742,10 @@ where def_id.encode(e); substs.encode(e); }), + TyAlias(def_id, substs) => e.emit_enum_variant(disc, |e| { + def_id.encode(e); + substs.encode(e); + }), Param(p) => e.emit_enum_variant(disc, |e| { p.encode(e); }), @@ -796,6 +821,7 @@ where 24 => Placeholder(Decodable::decode(d)), 25 => Infer(Decodable::decode(d)), 26 => Error(Decodable::decode(d)), + 27 => TyAlias(Decodable::decode(d), Decodable::decode(d)), _ => panic!( "{}", format!( @@ -924,6 +950,10 @@ where Error(d) => { d.hash_stable(__hcx, __hasher); } + TyAlias(def_id, substs) => { + def_id.hash_stable(__hcx, __hasher); + substs.hash_stable(__hcx, __hasher); + } } } } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index b9f787729c148..09d4752427c8b 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -297,7 +297,7 @@ fn build_union(cx: &mut DocContext<'_>, did: DefId) -> clean::Union { clean::Union { generics, fields } } -fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> Box { +pub(crate) fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> Box { let predicates = cx.tcx.explicit_predicates_of(did); let type_ = clean_middle_ty(cx.tcx.type_of(did), cx, Some(did)); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d5322f5c4662e..7ddd9ca1f4324 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1733,6 +1733,11 @@ pub(crate) fn clean_middle_ty<'tcx>( clean_middle_opaque_bounds(cx, bounds) } + ty::TyAlias(def_id, substs) => { + let path = external_path(cx, def_id, false, ThinVec::new(), substs); + Type::Path { path } + } + ty::Closure(..) => panic!("Closure"), ty::Generator(..) => panic!("Generator"), ty::Bound(..) => panic!("Bound"), diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 8aa0abd369cd5..158e740625163 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -537,6 +537,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did, .. }, _)), _) | ty::Foreign(did) => { Res::from_def_id(self.cx.tcx, did) } + ty::TyAlias(def_id, _) => Res::Def(self.cx.tcx.def_kind(def_id), def_id), ty::Projection(_) | ty::Closure(..) | ty::Generator(..) diff --git a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs index 2cb1ed6fcb76b..b64fbea15b3d3 100644 --- a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs +++ b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs @@ -39,6 +39,7 @@ fn main() { TyKind::Bound(..) => (), //~ ERROR usage of `ty::TyKind::` TyKind::Placeholder(..) => (), //~ ERROR usage of `ty::TyKind::` TyKind::Infer(..) => (), //~ ERROR usage of `ty::TyKind::` + TyKind::TyAlias(..) => (), //~ ERROR usage of `ty::TyKind::` TyKind::Error(_) => (), //~ ERROR usage of `ty::TyKind::` } diff --git a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr index 171f49087d695..76c434f145e78 100644 --- a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr +++ b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr @@ -169,17 +169,23 @@ LL | TyKind::Infer(..) => (), error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:42:9 | +LL | TyKind::TyAlias(..) => (), + | ^^^^^^ help: try using `ty::` directly: `ty` + +error: usage of `ty::TyKind::` + --> $DIR/ty_tykind_usage.rs:43:9 + | LL | TyKind::Error(_) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:47:12 + --> $DIR/ty_tykind_usage.rs:48:12 | LL | if let TyKind::Int(int_ty) = kind {} | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind` - --> $DIR/ty_tykind_usage.rs:49:24 + --> $DIR/ty_tykind_usage.rs:50:24 | LL | fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {} | ^^^^^^^^^^ @@ -187,7 +193,7 @@ LL | fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {} = help: try using `Ty` instead error: usage of `ty::TyKind` - --> $DIR/ty_tykind_usage.rs:51:37 + --> $DIR/ty_tykind_usage.rs:52:37 | LL | fn ir_ty_kind(bad: IrTyKind) -> IrTyKind { | ^^^^^^^^^^^ @@ -195,7 +201,7 @@ LL | fn ir_ty_kind(bad: IrTyKind) -> IrTyKind { = help: try using `Ty` instead error: usage of `ty::TyKind` - --> $DIR/ty_tykind_usage.rs:51:53 + --> $DIR/ty_tykind_usage.rs:52:53 | LL | fn ir_ty_kind(bad: IrTyKind) -> IrTyKind { | ^^^^^^^^^^^ @@ -203,12 +209,12 @@ LL | fn ir_ty_kind(bad: IrTyKind) -> IrTyKind { = help: try using `Ty` instead error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:54:9 + --> $DIR/ty_tykind_usage.rs:55:9 | LL | IrTyKind::Bool | --------^^^^^^ | | | help: try using `ty::` directly: `ty` -error: aborting due to 33 previous errors +error: aborting due to 34 previous errors diff --git a/src/test/ui/impl-trait/trait_type.stderr b/src/test/ui/impl-trait/trait_type.stderr index bea24339837a2..e084f8e0729c8 100644 --- a/src/test/ui/impl-trait/trait_type.stderr +++ b/src/test/ui/impl-trait/trait_type.stderr @@ -16,7 +16,7 @@ error[E0050]: method `fmt` has 1 parameter but the declaration in trait `std::fm LL | fn fmt(&self) -> () { } | ^^^^^ expected 2 parameters, found 1 | - = note: `fmt` from trait: `fn(&Self, &mut Formatter<'_>) -> Result<(), std::fmt::Error>` + = note: `fmt` from trait: `fn(&Self, &mut Formatter<'_>) -> std::fmt::Result` error[E0186]: method `fmt` has a `&self` declaration in the trait, but not in the impl --> $DIR/trait_type.rs:17:4 @@ -24,7 +24,7 @@ error[E0186]: method `fmt` has a `&self` declaration in the trait, but not in th LL | fn fmt() -> () { } | ^^^^^^^^^^^^^^ expected `&self` in impl | - = note: `fmt` from trait: `fn(&Self, &mut Formatter<'_>) -> Result<(), std::fmt::Error>` + = note: `fmt` from trait: `fn(&Self, &mut Formatter<'_>) -> std::fmt::Result` error[E0046]: not all trait items implemented, missing: `fmt` --> $DIR/trait_type.rs:21:1 @@ -32,7 +32,7 @@ error[E0046]: not all trait items implemented, missing: `fmt` LL | impl std::fmt::Display for MyType4 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `fmt` in implementation | - = help: implement the missing item: `fn fmt(&self, _: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { todo!() }` + = help: implement the missing item: `fn fmt(&self, _: &mut Formatter<'_>) -> std::fmt::Result { todo!() }` error: aborting due to 4 previous errors diff --git a/src/test/ui/infinite/infinite-type-alias-mutual-recursion.rs b/src/test/ui/infinite/infinite-type-alias-mutual-recursion.rs index 5381eedcfacfc..7588c13f629e5 100644 --- a/src/test/ui/infinite/infinite-type-alias-mutual-recursion.rs +++ b/src/test/ui/infinite/infinite-type-alias-mutual-recursion.rs @@ -1,6 +1,8 @@ type X1 = X2; -//~^ ERROR cycle detected when expanding type alias `X1` +//~^ ERROR cycle detected when expanding type alias type X2 = X3; +//~^ ERROR cycle detected when expanding type alias type X3 = X1; +//~^ ERROR cycle detected when expanding type alias fn main() {} diff --git a/src/test/ui/infinite/infinite-type-alias-mutual-recursion.stderr b/src/test/ui/infinite/infinite-type-alias-mutual-recursion.stderr index 7f82b294434f1..745147949f181 100644 --- a/src/test/ui/infinite/infinite-type-alias-mutual-recursion.stderr +++ b/src/test/ui/infinite/infinite-type-alias-mutual-recursion.stderr @@ -1,34 +1,20 @@ -error[E0391]: cycle detected when expanding type alias `X1` - --> $DIR/infinite-type-alias-mutual-recursion.rs:1:11 - | -LL | type X1 = X2; - | ^^ - | -note: ...which requires expanding type alias `X2`... - --> $DIR/infinite-type-alias-mutual-recursion.rs:3:11 - | -LL | type X2 = X3; - | ^^ -note: ...which requires expanding type alias `X3`... - --> $DIR/infinite-type-alias-mutual-recursion.rs:4:11 +error: cycle detected when expanding type alias + --> $DIR/infinite-type-alias-mutual-recursion.rs:5:1 | LL | type X3 = X1; - | ^^ - = note: ...which again requires expanding type alias `X1`, completing the cycle - = note: type aliases cannot be recursive - = help: consider using a struct, enum, or union instead to break the cycle - = help: see for more information -note: cycle used when collecting item types in top-level module + | ^^^^^^^ + +error: cycle detected when expanding type alias --> $DIR/infinite-type-alias-mutual-recursion.rs:1:1 | -LL | / type X1 = X2; -LL | | -LL | | type X2 = X3; -LL | | type X3 = X1; -LL | | -LL | | fn main() {} - | |____________^ +LL | type X1 = X2; + | ^^^^^^^ + +error: cycle detected when expanding type alias + --> $DIR/infinite-type-alias-mutual-recursion.rs:3:1 + | +LL | type X2 = X3; + | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/nll/type-alias-free-regions.stderr b/src/test/ui/nll/type-alias-free-regions.stderr index 45fd5a2f1d657..e20ab995c3d5d 100644 --- a/src/test/ui/nll/type-alias-free-regions.stderr +++ b/src/test/ui/nll/type-alias-free-regions.stderr @@ -4,7 +4,7 @@ error: lifetime may not live long enough LL | impl<'a> FromBox<'a> for C<'a> { | -- lifetime `'a` defined here LL | fn from_box(b: Box) -> Self { - | - has type `Box>` + | - has type `Box>` LL | C { f: b } | ^^^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` @@ -14,7 +14,7 @@ error: lifetime may not live long enough LL | impl<'a> FromTuple<'a> for C<'a> { | -- lifetime `'a` defined here LL | fn from_tuple(b: (B,)) -> Self { - | - has type `(Box<&'1 isize>,)` + | - has type `(B<'1>,)` LL | C { f: Box::new(b.0) } | ^^^^^^^^^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` diff --git a/src/test/ui/privacy/private-in-public-warn.rs b/src/test/ui/privacy/private-in-public-warn.rs index 0fa1de975b040..aea693a490366 100644 --- a/src/test/ui/privacy/private-in-public-warn.rs +++ b/src/test/ui/privacy/private-in-public-warn.rs @@ -247,7 +247,7 @@ mod aliases_priv { //~^ ERROR private trait `PrivTr1` in public interface //~| WARNING hard error pub trait Tr2: PrivUseAliasTr {} - //~^ ERROR private trait `PrivTr1` in public interface + //~^ ERROR private trait `PrivTr1` in public interface //~| WARNING hard error //~| ERROR private type `Priv2` in public interface //~| WARNING hard error diff --git a/src/test/ui/privacy/private-in-public-warn.stderr b/src/test/ui/privacy/private-in-public-warn.stderr index 66f91ce6fd683..d3dd80f151c87 100644 --- a/src/test/ui/privacy/private-in-public-warn.stderr +++ b/src/test/ui/privacy/private-in-public-warn.stderr @@ -291,7 +291,7 @@ LL | pub trait Tr1: PrivUseAliasTr {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 -error: private trait `PrivTr1` in public interface (error E0445) +error: private trait `PrivTr1` in public interface (error E0445) --> $DIR/private-in-public-warn.rs:249:5 | LL | pub trait Tr2: PrivUseAliasTr {} diff --git a/src/test/ui/regions/regions-infer-paramd-indirect.stderr b/src/test/ui/regions/regions-infer-paramd-indirect.stderr index afabdc1de1c7d..e253fb18e89cd 100644 --- a/src/test/ui/regions/regions-infer-paramd-indirect.stderr +++ b/src/test/ui/regions/regions-infer-paramd-indirect.stderr @@ -5,7 +5,7 @@ LL | impl<'a> SetF<'a> for C<'a> { | -- lifetime `'a` defined here ... LL | fn set_f_bad(&mut self, b: Box) { - | - has type `Box>` + | - has type `Box>` LL | self.f = b; | ^^^^^^ assignment requires that `'1` must outlive `'a` diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr index fccee5d436363..028ced07a656b 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr @@ -30,7 +30,7 @@ error: lifetime may not live long enough --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:15:58 | LL | fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } - | -- ---- has type `Pin<&'1 Foo>` ^^^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a` + | -- ---- has type `Alias<&'1 Foo>` ^^^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a` | | | lifetime `'a` defined here diff --git a/src/test/ui/span/impl-wrong-item-for-trait.stderr b/src/test/ui/span/impl-wrong-item-for-trait.stderr index f919092f9ee92..d592f2b960022 100644 --- a/src/test/ui/span/impl-wrong-item-for-trait.stderr +++ b/src/test/ui/span/impl-wrong-item-for-trait.stderr @@ -58,7 +58,7 @@ error[E0046]: not all trait items implemented, missing: `fmt` LL | impl Debug for FooTypeForMethod {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `fmt` in implementation | - = help: implement the missing item: `fn fmt(&self, _: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { todo!() }` + = help: implement the missing item: `fn fmt(&self, _: &mut Formatter<'_>) -> std::fmt::Result { todo!() }` error: aborting due to 7 previous errors diff --git a/src/test/ui/symbol-names/basic.legacy.stderr b/src/test/ui/symbol-names/basic.legacy.stderr index 3ad4ed24cf7fc..fe490a6000d7b 100644 --- a/src/test/ui/symbol-names/basic.legacy.stderr +++ b/src/test/ui/symbol-names/basic.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN5basic4main17hcbad207c0eeb0b3bE) +error: symbol-name(_ZN5basic4main17he9f658e438f1cac0E) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(basic::main::hcbad207c0eeb0b3b) +error: demangling(basic::main::he9f658e438f1cac0) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] diff --git a/src/test/ui/symbol-names/issue-60925.legacy.stderr b/src/test/ui/symbol-names/issue-60925.legacy.stderr index 21bf21ee71c6f..29b42f48d803a 100644 --- a/src/test/ui/symbol-names/issue-60925.legacy.stderr +++ b/src/test/ui/symbol-names/issue-60925.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h2f2efcf580c9b1eeE) +error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h13209029be24b923E) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(issue_60925::foo::Foo::foo::h2f2efcf580c9b1ee) +error: demangling(issue_60925::foo::Foo::foo::h13209029be24b923) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] diff --git a/src/test/ui/symbol-names/ty-alias.legacy.stderr b/src/test/ui/symbol-names/ty-alias.legacy.stderr new file mode 100644 index 0000000000000..650428ad78a68 --- /dev/null +++ b/src/test/ui/symbol-names/ty-alias.legacy.stderr @@ -0,0 +1,38 @@ +error: symbol-name(_ZN8ty_alias5Trait6method17ha7d0f40d408a4a48E) + --> $DIR/ty-alias.rs:11:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(ty_alias::Trait::method::ha7d0f40d408a4a48) + --> $DIR/ty-alias.rs:11:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(ty_alias::Trait::method) + --> $DIR/ty-alias.rs:11:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN118_$LT$ty_alias..Foo$LT$T$GT$$u20$as$u20$ty_alias..Trait$LT$$LT$T$u20$as$u20$core..ops..deref..Deref$GT$..Target$GT$$GT$6method17he3e1099a8910c704E) + --> $DIR/ty-alias.rs:23:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling( as ty_alias::Trait<::Target>>::method::he3e1099a8910c704) + --> $DIR/ty-alias.rs:23:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt( as ty_alias::Trait<::Target>>::method) + --> $DIR/ty-alias.rs:23:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/symbol-names/ty-alias.rs b/src/test/ui/symbol-names/ty-alias.rs new file mode 100644 index 0000000000000..c75b9f3af3b80 --- /dev/null +++ b/src/test/ui/symbol-names/ty-alias.rs @@ -0,0 +1,34 @@ +// build-fail +// ignore-tidy-linelength +// revisions: legacy v0 +//[legacy]compile-flags: -Z unstable-options -C symbol-mangling-version=legacy + //[v0]compile-flags: -C symbol-mangling-version=v0 + +#![feature(rustc_attrs)] +#![crate_type = "lib"] + +pub trait Trait { + #[rustc_symbol_name] + //[legacy]~^ ERROR symbol-name(_ZN8ty_alias5Trait6method + //[legacy]~| ERROR demangling(ty_alias::Trait::method::ha7 + //[legacy]~| ERROR demangling-alt(ty_alias::Trait::method) + //[v0]~^^^^ ERROR symbol-name(_RNvYpINtCs7cCwHY5bdWN_8ty_alias5TraitpE6methodB6_) + //[v0]~| ERROR demangling(<_ as ty_alias[53e789f59d55e7ab]::Trait<_>>::method) + //[v0]~| ERROR demangling-alt(<_ as ty_alias::Trait<_>>::method) + fn method() -> &'static (); +} + +pub struct Foo(T); +impl Trait for Foo { + #[rustc_symbol_name] + //[legacy]~^ ERROR symbol-name(_ZN118_$LT$ty_alias..Foo$LT$T$GT$$u20$as$u20$ty_alias..Trait$LT$$LT$T$u20$as$u20$core..ops..deref..Deref$GT$..Target$GT$$GT$6method17 + //[legacy]~| ERROR demangling( as ty_alias::Trait<::Target>>::method::he3 + //[legacy]~| ERROR demangling-alt( as ty_alias::Trait<::Target>>::method) + //[v0]~^^^^ ERROR symbol-name(_RNvXINICs7cCwHY5bdWN_8ty_alias0pEINtB5_3FoopEINtB5_5TraitNtYpNtNtNtCskRLgSi4TGgx_4core3ops5deref5Deref6TargetE6methodB5_) + //[v0]~| ERROR demangling( as ty_alias[53e789f59d55e7ab]::Trait<<_ as core[f30d6cf379d2fe73]::ops::deref::Deref>::Target>>::method) + //[v0]~| ERROR demangling-alt( as ty_alias::Trait<<_ as core::ops::deref::Deref>::Target>>::method) + fn method() -> &'static () { + static FOO: () = (); + &FOO + } +} diff --git a/src/test/ui/symbol-names/ty-alias.v0.stderr b/src/test/ui/symbol-names/ty-alias.v0.stderr new file mode 100644 index 0000000000000..af87bb5448762 --- /dev/null +++ b/src/test/ui/symbol-names/ty-alias.v0.stderr @@ -0,0 +1,38 @@ +error: symbol-name(_RNvYpINtCsCRATE_HASH_8ty_alias5TraitpE6methodB_) + --> $DIR/ty-alias.rs:11:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(<_ as ty_alias[53e789f59d55e7ab]::Trait<_>>::method) + --> $DIR/ty-alias.rs:11:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(<_ as ty_alias::Trait<_>>::method) + --> $DIR/ty-alias.rs:11:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_RNvXINICsCRATE_HASH_8ty_alias0pEINtB_3FoopEINtB_5TraitNtYpNtNtNtCsCRATE_HASH_4core3ops5deref5Deref6TargetE6methodB_) + --> $DIR/ty-alias.rs:23:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling( as ty_alias[53e789f59d55e7ab]::Trait<<_ as core[f30d6cf379d2fe73]::ops::deref::Deref>::Target>>::method) + --> $DIR/ty-alias.rs:23:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt( as ty_alias::Trait<<_ as core::ops::deref::Deref>::Target>>::method) + --> $DIR/ty-alias.rs:23:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index a95d9f5390de3..6968242ad7019 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -1323,6 +1323,11 @@ fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedenc ty::Infer(_) | ty::Error(_) | ty::Bound(..) | ty::Opaque(..) | ty::Placeholder(_) | ty::Dynamic(..) => { Position::ReborrowStable(precedence).into() }, + ty::TyAlias(def_id, substs) => { + let binder_ty = cx.tcx.bound_type_of(def_id); + ty = binder_ty.subst(cx.tcx, substs); + continue; + } ty::Adt(..) if ty.has_placeholders() || ty.has_opaque_types() => { Position::ReborrowStable(precedence).into() },