From a197c452b075fcdbac619a22dbe07cb7e4949f2e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 20 Apr 2022 16:51:52 +0200 Subject: [PATCH 01/28] Add rustc_type_ir::TyKind::TyAlias variant --- compiler/rustc_middle/src/ty/sty.rs | 192 +++++++++++++++++++++++++--- compiler/rustc_type_ir/src/sty.rs | 30 +++++ 2 files changed, 207 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index cf420bafeb12f..2a10273ebc88b 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -98,22 +98,184 @@ impl BoundRegionKind { } } -pub trait Article { - fn article(&self) -> &'static str; -} +/// Defines the kinds of types used by the type system. +/// +/// Types written by the user start out as [hir::TyKind](rustc_hir::TyKind) and get +/// converted to this representation using `AstConv::ast_ty_to_ty`. +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable, Debug)] +#[derive(HashStable)] +#[rustc_diagnostic_item = "TyKind"] +pub enum TyKind<'tcx> { + /// The primitive boolean type. Written as `bool`. + Bool, -impl<'tcx> Article for TyKind<'tcx> { - /// Get the article ("a" or "an") to use with this type. - fn article(&self) -> &'static str { - match self { - Int(_) | Float(_) | Array(_, _) => "an", - Adt(def, _) if def.is_enum() => "an", - // This should never happen, but ICEing and causing the user's code - // to not compile felt too harsh. - Error(_) => "a", - _ => "a", - } - } + /// The primitive character type; holds a Unicode scalar value + /// (a non-surrogate code point). Written as `char`. + Char, + + /// A primitive signed integer type. For example, `i32`. + Int(ty::IntTy), + + /// A primitive unsigned integer type. For example, `u32`. + Uint(ty::UintTy), + + /// A primitive floating-point type. For example, `f64`. + Float(ty::FloatTy), + + /// Algebraic data types (ADT). For example: structures, enumerations and unions. + /// + /// For example, the type `List` would be represented using the `AdtDef` + /// for `struct List` and the substs `[i32]`. + /// + /// Note that generic parameters in fields only get lazily substituted + /// by using something like `adt_def.all_fields().map(|field| field.ty(tcx, substs))`. + Adt(AdtDef<'tcx>, SubstsRef<'tcx>), + + /// An unsized FFI type that is opaque to Rust. Written as `extern type T`. + Foreign(DefId), + + /// The pointee of a string slice. Written as `str`. + Str, + + /// An array with the given length. Written as `[T; N]`. + Array(Ty<'tcx>, ty::Const<'tcx>), + + /// The pointee of an array slice. Written as `[T]`. + Slice(Ty<'tcx>), + + /// A raw pointer. Written as `*mut T` or `*const T` + RawPtr(TypeAndMut<'tcx>), + + /// A reference; a pointer with an associated lifetime. Written as + /// `&'a mut T` or `&'a T`. + Ref(Region<'tcx>, Ty<'tcx>, hir::Mutability), + + /// The anonymous type of a function declaration/definition. Each + /// function has a unique type. + /// + /// For the function `fn foo() -> i32 { 3 }` this type would be + /// shown to the user as `fn() -> i32 {foo}`. + /// + /// For example the type of `bar` here: + /// ```rust + /// fn foo() -> i32 { 1 } + /// let bar = foo; // bar: fn() -> i32 {foo} + /// ``` + FnDef(DefId, SubstsRef<'tcx>), + + /// A type alias (`type Alias = i8;`) containing the `DefId` of the aliased type and its + /// generics. + TyAlias(DefId, SubstsRef<'tcx>), + + /// A pointer to a function. Written as `fn() -> i32`. + /// + /// Note that both functions and closures start out as either + /// [FnDef] or [Closure] which can be then be coerced to this variant. + /// + /// For example the type of `bar` here: + /// + /// ```rust + /// fn foo() -> i32 { 1 } + /// let bar: fn() -> i32 = foo; + /// ``` + FnPtr(PolyFnSig<'tcx>), + + /// A trait object. Written as `dyn for<'b> Trait<'b, Assoc = u32> + Send + 'a`. + Dynamic(&'tcx List>>, ty::Region<'tcx>), + + /// The anonymous type of a closure. Used to represent the type of `|a| a`. + /// + /// Closure substs contain both the - potentially substituted - generic parameters + /// of its parent and some synthetic parameters. See the documentation for + /// [ClosureSubsts] for more details. + Closure(DefId, SubstsRef<'tcx>), + + /// The anonymous type of a generator. Used to represent the type of + /// `|a| yield a`. + /// + /// For more info about generator substs, visit the documentation for + /// [GeneratorSubsts]. + Generator(DefId, SubstsRef<'tcx>, hir::Movability), + + /// A type representing the types stored inside a generator. + /// This should only appear as part of the [GeneratorSubsts]. + /// + /// Note that the captured variables for generators are stored separately + /// using a tuple in the same way as for closures. + /// + /// Unlike upvars, the witness can reference lifetimes from + /// inside of the generator itself. To deal with them in + /// the type of the generator, we convert them to higher ranked + /// lifetimes bound by the witness itself. + /// + /// Looking at the following example, the witness for this generator + /// may end up as something like `for<'a> [Vec, &'a Vec]`: + /// + /// ```ignore UNSOLVED (ask @compiler-errors, should this error? can we just swap the yields?) + /// #![feature(generators)] + /// |a| { + /// let x = &vec![3]; + /// yield a; + /// yield x[0]; + /// } + /// # ; + /// ``` + GeneratorWitness(Binder<'tcx, &'tcx List>>), + + /// The never type `!`. + Never, + + /// A tuple type. For example, `(i32, bool)`. + Tuple(&'tcx List>), + + /// The projection of an associated type. For example, + /// `>::N`. + Projection(ProjectionTy<'tcx>), + + /// Opaque (`impl Trait`) type found in a return type. + /// + /// The `DefId` comes either from + /// * the `impl Trait` ast::Ty node, + /// * or the `type Foo = impl Trait` declaration + /// + /// For RPIT the substitutions are for the generics of the function, + /// while for TAIT it is used for the generic parameters of the alias. + /// + /// During codegen, `tcx.type_of(def_id)` can be used to get the underlying type. + Opaque(DefId, SubstsRef<'tcx>), + + /// A type parameter; for example, `T` in `fn f(x: T) {}`. + Param(ParamTy), + + /// Bound type variable, used to represent the `'a` in `for<'a> fn(&'a ())`. + /// + /// For canonical queries, we replace inference variables with bound variables, + /// so e.g. when checking whether `&'_ (): Trait<_>` holds, we canonicalize that to + /// `for<'a, T> &'a (): Trait` and then convert the introduced bound variables + /// back to inference variables in a new inference context when inside of the query. + /// + /// See the `rustc-dev-guide` for more details about + /// [higher-ranked trait bounds][1] and [canonical queries][2]. + /// + /// [1]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html + /// [2]: https://rustc-dev-guide.rust-lang.org/traits/canonical-queries.html + Bound(ty::DebruijnIndex, BoundTy), + + /// A placeholder type, used during higher ranked subtyping to instantiate + /// bound variables. + Placeholder(ty::PlaceholderType), + + /// A type variable used during type checking. + /// + /// Similar to placeholders, inference variables also live in a universe to + /// correctly deal with higher ranked types. Though unlike placeholders, + /// that universe is stored in the `InferCtxt` instead of directly + /// inside of the type. + Infer(InferTy), + + /// A placeholder for a type which could not be computed; this is + /// propagated to avoid useless error messages. + Error(DelaySpanBugEmitted), } // `TyKind` is used a lot. Make sure it doesn't unintentionally get bigger. 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); + } } } } From 61705b399e7687169a5409654267ac3cc6474981 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 20 Apr 2022 17:54:07 +0200 Subject: [PATCH 02/28] Add TyKind::TyAlias support in rustc_middle --- compiler/rustc_middle/src/ty/context.rs | 20 +- compiler/rustc_middle/src/ty/error.rs | 2 + compiler/rustc_middle/src/ty/fast_reject.rs | 7 +- compiler/rustc_middle/src/ty/flags.rs | 5 + compiler/rustc_middle/src/ty/layout.rs | 5 +- compiler/rustc_middle/src/ty/print/mod.rs | 4 + compiler/rustc_middle/src/ty/print/pretty.rs | 1 + .../rustc_middle/src/ty/structural_impls.rs | 2 + compiler/rustc_middle/src/ty/sty.rs | 207 +++--------------- compiler/rustc_middle/src/ty/util.rs | 16 +- compiler/rustc_middle/src/ty/walk.rs | 12 +- 11 files changed, 91 insertions(+), 190 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 3d7e2a0839abc..9ba6f37a3aae9 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1726,6 +1726,16 @@ 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, mut ty: Ty<'tcx>) -> Ty<'tcx> { + while let ty::TyAlias(def_id, substs) = *ty.kind() { + let binder_ty = self.bound_type_of(def_id); + ty = binder_ty.subst(self, substs); + } + ty + } } /// A trait implemented for all `X<'a>` types that can be safely and @@ -1996,7 +2006,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 +2105,8 @@ impl<'tcx> TyCtxt<'tcx> { Infer, Projection, Opaque, - Foreign + Foreign, + TyAlias, )?; writeln!(fmt, "InternalSubsts interner: #{}", self.0.interners.substs.len())?; @@ -2633,6 +2644,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..623d5ce74d6c7 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_PROJECTION); + 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..1107b246467b5 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -637,7 +637,9 @@ where } }; - match *this.ty.kind() { + let ty = tcx.peel_off_ty_alias(this.ty); + + match *ty.kind() { ty::Bool | ty::Char | ty::Int(_) @@ -770,6 +772,7 @@ where | ty::Opaque(..) | ty::Param(_) | ty::Infer(_) + | ty::TyAlias(_, _) | ty::Error(_) => bug!("TyAndLayout::field: unexpected type `{}`", this.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 2a10273ebc88b..7f30b60c4ea16 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -98,184 +98,22 @@ impl BoundRegionKind { } } -/// Defines the kinds of types used by the type system. -/// -/// Types written by the user start out as [hir::TyKind](rustc_hir::TyKind) and get -/// converted to this representation using `AstConv::ast_ty_to_ty`. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable, Debug)] -#[derive(HashStable)] -#[rustc_diagnostic_item = "TyKind"] -pub enum TyKind<'tcx> { - /// The primitive boolean type. Written as `bool`. - Bool, - - /// The primitive character type; holds a Unicode scalar value - /// (a non-surrogate code point). Written as `char`. - Char, - - /// A primitive signed integer type. For example, `i32`. - Int(ty::IntTy), - - /// A primitive unsigned integer type. For example, `u32`. - Uint(ty::UintTy), - - /// A primitive floating-point type. For example, `f64`. - Float(ty::FloatTy), - - /// Algebraic data types (ADT). For example: structures, enumerations and unions. - /// - /// For example, the type `List` would be represented using the `AdtDef` - /// for `struct List` and the substs `[i32]`. - /// - /// Note that generic parameters in fields only get lazily substituted - /// by using something like `adt_def.all_fields().map(|field| field.ty(tcx, substs))`. - Adt(AdtDef<'tcx>, SubstsRef<'tcx>), - - /// An unsized FFI type that is opaque to Rust. Written as `extern type T`. - Foreign(DefId), - - /// The pointee of a string slice. Written as `str`. - Str, - - /// An array with the given length. Written as `[T; N]`. - Array(Ty<'tcx>, ty::Const<'tcx>), - - /// The pointee of an array slice. Written as `[T]`. - Slice(Ty<'tcx>), - - /// A raw pointer. Written as `*mut T` or `*const T` - RawPtr(TypeAndMut<'tcx>), - - /// A reference; a pointer with an associated lifetime. Written as - /// `&'a mut T` or `&'a T`. - Ref(Region<'tcx>, Ty<'tcx>, hir::Mutability), - - /// The anonymous type of a function declaration/definition. Each - /// function has a unique type. - /// - /// For the function `fn foo() -> i32 { 3 }` this type would be - /// shown to the user as `fn() -> i32 {foo}`. - /// - /// For example the type of `bar` here: - /// ```rust - /// fn foo() -> i32 { 1 } - /// let bar = foo; // bar: fn() -> i32 {foo} - /// ``` - FnDef(DefId, SubstsRef<'tcx>), - - /// A type alias (`type Alias = i8;`) containing the `DefId` of the aliased type and its - /// generics. - TyAlias(DefId, SubstsRef<'tcx>), - - /// A pointer to a function. Written as `fn() -> i32`. - /// - /// Note that both functions and closures start out as either - /// [FnDef] or [Closure] which can be then be coerced to this variant. - /// - /// For example the type of `bar` here: - /// - /// ```rust - /// fn foo() -> i32 { 1 } - /// let bar: fn() -> i32 = foo; - /// ``` - FnPtr(PolyFnSig<'tcx>), - - /// A trait object. Written as `dyn for<'b> Trait<'b, Assoc = u32> + Send + 'a`. - Dynamic(&'tcx List>>, ty::Region<'tcx>), - - /// The anonymous type of a closure. Used to represent the type of `|a| a`. - /// - /// Closure substs contain both the - potentially substituted - generic parameters - /// of its parent and some synthetic parameters. See the documentation for - /// [ClosureSubsts] for more details. - Closure(DefId, SubstsRef<'tcx>), - - /// The anonymous type of a generator. Used to represent the type of - /// `|a| yield a`. - /// - /// For more info about generator substs, visit the documentation for - /// [GeneratorSubsts]. - Generator(DefId, SubstsRef<'tcx>, hir::Movability), - - /// A type representing the types stored inside a generator. - /// This should only appear as part of the [GeneratorSubsts]. - /// - /// Note that the captured variables for generators are stored separately - /// using a tuple in the same way as for closures. - /// - /// Unlike upvars, the witness can reference lifetimes from - /// inside of the generator itself. To deal with them in - /// the type of the generator, we convert them to higher ranked - /// lifetimes bound by the witness itself. - /// - /// Looking at the following example, the witness for this generator - /// may end up as something like `for<'a> [Vec, &'a Vec]`: - /// - /// ```ignore UNSOLVED (ask @compiler-errors, should this error? can we just swap the yields?) - /// #![feature(generators)] - /// |a| { - /// let x = &vec![3]; - /// yield a; - /// yield x[0]; - /// } - /// # ; - /// ``` - GeneratorWitness(Binder<'tcx, &'tcx List>>), - - /// The never type `!`. - Never, - - /// A tuple type. For example, `(i32, bool)`. - Tuple(&'tcx List>), - - /// The projection of an associated type. For example, - /// `>::N`. - Projection(ProjectionTy<'tcx>), - - /// Opaque (`impl Trait`) type found in a return type. - /// - /// The `DefId` comes either from - /// * the `impl Trait` ast::Ty node, - /// * or the `type Foo = impl Trait` declaration - /// - /// For RPIT the substitutions are for the generics of the function, - /// while for TAIT it is used for the generic parameters of the alias. - /// - /// During codegen, `tcx.type_of(def_id)` can be used to get the underlying type. - Opaque(DefId, SubstsRef<'tcx>), - - /// A type parameter; for example, `T` in `fn f(x: T) {}`. - Param(ParamTy), - - /// Bound type variable, used to represent the `'a` in `for<'a> fn(&'a ())`. - /// - /// For canonical queries, we replace inference variables with bound variables, - /// so e.g. when checking whether `&'_ (): Trait<_>` holds, we canonicalize that to - /// `for<'a, T> &'a (): Trait` and then convert the introduced bound variables - /// back to inference variables in a new inference context when inside of the query. - /// - /// See the `rustc-dev-guide` for more details about - /// [higher-ranked trait bounds][1] and [canonical queries][2]. - /// - /// [1]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html - /// [2]: https://rustc-dev-guide.rust-lang.org/traits/canonical-queries.html - Bound(ty::DebruijnIndex, BoundTy), - - /// A placeholder type, used during higher ranked subtyping to instantiate - /// bound variables. - Placeholder(ty::PlaceholderType), +pub trait Article { + fn article(&self) -> &'static str; +} - /// A type variable used during type checking. - /// - /// Similar to placeholders, inference variables also live in a universe to - /// correctly deal with higher ranked types. Though unlike placeholders, - /// that universe is stored in the `InferCtxt` instead of directly - /// inside of the type. - Infer(InferTy), - - /// A placeholder for a type which could not be computed; this is - /// propagated to avoid useless error messages. - Error(DelaySpanBugEmitted), +impl<'tcx> Article for TyKind<'tcx> { + /// Get the article ("a" or "an") to use with this type. + fn article(&self) -> &'static str { + match self { + Int(_) | Float(_) | Array(_, _) => "an", + Adt(def, _) if def.is_enum() => "an", + // This should never happen, but ICEing and causing the user's code + // to not compile felt too harsh. + Error(_) => "a", + _ => "a", + } + } } // `TyKind` is used a lot. Make sure it doesn't unintentionally get bigger. @@ -2183,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), @@ -2268,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) } @@ -2340,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, @@ -2398,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..e485fc4b4e471 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,8 @@ impl<'tcx> Ty<'tcx> { | ty::Placeholder(_) | ty::Infer(_) => false, + ty::TyAlias(def_id, _) => tcx.type_of(def_id).is_structural_eq_shallow(tcx), + ty::Foreign(_) | ty::GeneratorWitness(..) | ty::Error(_) => false, } } @@ -1184,7 +1188,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 +1217,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/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())); From ed3f028012ee29d6fb6c134c70ec6c187cb941f0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 20 Apr 2022 17:59:29 +0200 Subject: [PATCH 03/28] Add TyKind::TyAlias support in rustc_symbol_mangling --- .../src/typeid/typeid_itanium_cxx_abi.rs | 12 ++++++++++++ compiler/rustc_symbol_mangling/src/v0.rs | 6 +++++- 2 files changed, 17 insertions(+), 1 deletion(-) 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 From 2a25b280aee3c6794e67d5ce0402d8bbc29ad04a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Apr 2022 17:56:11 +0200 Subject: [PATCH 04/28] Add TyKind::TyAlias support in rustc_infer --- compiler/rustc_infer/src/infer/canonical/canonicalizer.rs | 3 ++- compiler/rustc_infer/src/infer/freshen.rs | 3 ++- compiler/rustc_infer/src/infer/opaque_types.rs | 7 +++++-- compiler/rustc_infer/src/infer/outlives/components.rs | 4 ++++ 4 files changed, 13 insertions(+), 4 deletions(-) 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..9d30535dee213 100644 --- a/compiler/rustc_infer/src/infer/outlives/components.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -169,6 +169,10 @@ fn compute_components<'tcx>( out.push(Component::UnresolvedInferenceVariable(infer_ty)); } + ty::TyAlias(def_id, _) => { + compute_components(tcx, tcx.type_of(def_id), 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 From 71357dcfcacc2d92d5e1564e096ab643723a3b3e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Apr 2022 20:02:45 +0200 Subject: [PATCH 05/28] Add TyKind::TyAlias support in rustc_codegen_ssa --- compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs | 1 + 1 file changed, 1 insertion(+) 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 \ From 02ee18f7cffef890d94b9fc4f49bd4a26dced581 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Apr 2022 20:46:28 +0200 Subject: [PATCH 06/28] Add TyKind::TyAlias support in rustc_trait_selection --- .../src/traits/coherence.rs | 2 + .../src/traits/error_reporting/mod.rs | 1 + .../rustc_trait_selection/src/traits/mod.rs | 2 + .../src/traits/project.rs | 46 ++-- .../src/traits/query/dropck_outlives.rs | 3 +- .../src/traits/query/normalize.rs | 70 +++--- .../src/traits/select/candidate_assembly.rs | 8 +- .../src/traits/select/confirmation.rs | 2 +- .../src/traits/select/mod.rs | 8 +- .../src/traits/structural_match.rs | 5 + .../rustc_trait_selection/src/traits/wf.rs | 224 ++++++++++++++++++ 11 files changed, 311 insertions(+), 60 deletions(-) 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..de3b37091ef35 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::{Subst, SubstsRef}; use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable}; use rustc_middle::ty::DefIdTree; use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt}; @@ -459,6 +460,23 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { value.fold_with(self) } } + + fn fold_reveal(&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 +530,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_reveal(ty, def_id, substs), } } + ty::TyAlias(def_id, substs) => self.fold_reveal(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 +1414,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 +1651,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::Bound(..) | ty::Placeholder(..) | ty::Infer(..) + | ty::TyAlias(..) | ty::Error(_) => false, } } @@ -1735,6 +1737,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..a8fae37c0a00b 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::{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_reveal( + &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_reveal(ty, def_id, substs), } } + ty::TyAlias(def_id, substs) => self.fold_reveal(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..3536494c824f4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -1249,7 +1249,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..2b3f305f59620 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -430,6 +430,226 @@ 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(..) => { + // 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. + } + + 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 + // should've been checked by the instantiation + // of whatever returned this exact `impl Trait`. + + // for named opaque `impl Trait` types we still need to check them + if ty::is_impl_trait_defn(self.infcx.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 ty = self.infcx.shallow_resolve(ty); + if let ty::Infer(ty::TyVar(_)) = ty.kind() { + // Not yet resolved, but we've made progress. + 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()), + )); + } else { + // Yes, resolved, proceed with the result. + // FIXME(eddyb) add the type to `walker` instead of recursing. + self.compute(ty.into()); + } + } + + 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>) { @@ -686,6 +906,10 @@ impl<'tcx> WfPredicates<'tcx> { .to_predicate(self.tcx()), )); } + + ty::TyAlias(..) => { + bug!("unexpected TyAlias in WfPredicates::compute"); + } } debug!(?self.out); From 5cb94e7cc3038014584106570ad594f085eb5407 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Apr 2022 20:49:45 +0200 Subject: [PATCH 07/28] Add TyKind::TyAlias support in rustc_ty_utils --- compiler/rustc_ty_utils/src/layout.rs | 6 ++++++ compiler/rustc_ty_utils/src/representability.rs | 10 ++++++++++ compiler/rustc_ty_utils/src/ty.rs | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) 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] From 5ea1e632ad108b61f232148f44d5b54e1c5829b0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Apr 2022 21:15:06 +0200 Subject: [PATCH 08/28] Add TyKind::TyAlias support in rustc_traits --- compiler/rustc_traits/src/chalk/lowering.rs | 7 ++++++- compiler/rustc_traits/src/dropck_outlives.rs | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) 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); } From 87df97855672c774a3c843eb4633832a1f753479 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Apr 2022 21:18:51 +0200 Subject: [PATCH 09/28] Add TyKind::TyAlias support in rustc_lint --- compiler/rustc_lint/src/types.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 7c99bb2790fd0..adc2f880e8548 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1134,6 +1134,19 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { FfiSafe } + ty::TyAlias(def_id, substs) => { + for ty in substs.types() { + let ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, ty); + match self.check_type_for_ffi(cache, ty) { + FfiSafe => {} + r => return r, + }; + } + let ty = tcx.type_of(def_id); + 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 From db39bcdb77e4e6f55cf6945a174df1dae366442f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Apr 2022 21:20:49 +0200 Subject: [PATCH 10/28] Add traits::NonStructuralMatchTy::TyAlias support in rustc_mir_build --- compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs | 3 +++ 1 file changed, 3 insertions(+) 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..96fd77f1292ec 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() } + traits::NonStructuralMatchTyKind::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") } From 5aa4e3ccfee80f4e7e071cf2912e04a0cd13ee9f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 13 Jun 2022 01:04:58 +0200 Subject: [PATCH 11/28] Add TyKind::TyAlias support in rustc_mir_build --- compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 96fd77f1292ec..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,7 +139,7 @@ impl<'tcx> ConstToPat<'tcx> { ty::RawPtr(..) => { "raw pointers cannot be used in patterns".to_string() } - traits::NonStructuralMatchTyKind::TyAlias => { + ty::TyAlias(..) => { bug!("use of a value of a type alias inside a pattern") } _ => { From b7569291f4aca31a3d8980ff7c59b6fe49d2f0f2 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Apr 2022 21:29:27 +0200 Subject: [PATCH 12/28] Add TyKind::TyAlias support in rustc_const_eval --- compiler/rustc_const_eval/src/const_eval/valtrees.rs | 5 ++++- compiler/rustc_const_eval/src/interpret/intrinsics.rs | 4 ++-- .../rustc_const_eval/src/interpret/intrinsics/type_name.rs | 5 +++++ compiler/rustc_const_eval/src/interpret/validity.rs | 3 ++- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index a964fe8465eec..0f1d3b8e92fd0 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -152,6 +152,8 @@ pub(crate) fn const_to_valtree_inner<'tcx>( // FIXME(oli-obk): we can probably encode closures just like structs | ty::Closure(..) | ty::Generator(..) + // FIXME: we could look behind type aliases. + | ty::TyAlias(..) | ty::GeneratorWitness(..) => Err(ValTreeCreationError::NonSupportedType), } } @@ -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), } } From 8b20c6a42c94e8b465da9c0f6ad2c9b9b89b41e6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Apr 2022 21:35:00 +0200 Subject: [PATCH 13/28] Add TyKind::TyAlias support in rustc_typeck --- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 1 + compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs | 5 +++++ compiler/rustc_hir_analysis/src/coherence/orphan.rs | 2 ++ compiler/rustc_hir_analysis/src/variance/constraints.rs | 4 ++++ compiler/rustc_hir_typeck/src/cast.rs | 1 + 5 files changed, 13 insertions(+) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 70a171c02b26b..1627e5e751229 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -856,6 +856,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..6499086eebd81 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -257,6 +257,10 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_invariant_substs(current, substs, variance); } + ty::TyAlias(_, substs) => { + self.add_constraints_from_invariant_substs(current, substs, 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..9cd0e41966723 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(..) => span_bug!(span, "unexpected TyAlias in pointer_kind"), ty::Param(ref p) => Some(PointerKind::OfParam(p)), // Insufficient type information. ty::Placeholder(..) | ty::Bound(..) | ty::Infer(_) => None, From 2e215cd6e8b614b9df2dba54a76c0ec57ca01abf Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 4 May 2022 16:19:31 +0200 Subject: [PATCH 14/28] Add TyKind::TyAlias support in rustc_privacy --- compiler/rustc_privacy/src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index df8454ed4ee06..6404462b8e41c 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 @@ -270,6 +275,7 @@ where | ty::FnPtr(..) | ty::Param(..) | ty::Error(_) + | ty::TyAlias(..) | ty::GeneratorWitness(..) => {} ty::Bound(..) | ty::Placeholder(..) | ty::Infer(..) => { bug!("unexpected type: {:?}", ty) From 61b0cf7cbc971c41d25c6e1e3960b84810d6ad41 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 4 May 2022 16:19:47 +0200 Subject: [PATCH 15/28] Add TyKind::TyAlias support in librustdoc --- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/mod.rs | 5 +++++ src/librustdoc/passes/collect_intra_doc_links.rs | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) 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(..) From 83ce0446cb713fdf1dd3883540ab535b5ff19da1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 13 Jun 2022 00:19:29 +0200 Subject: [PATCH 16/28] Add HAS_TY_ALIAS into TypeFlags --- compiler/rustc_middle/src/ty/flags.rs | 2 +- compiler/rustc_trait_selection/src/traits/project.rs | 10 +++++++--- compiler/rustc_type_ir/src/lib.rs | 6 +++++- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 623d5ce74d6c7..c7ae2f3bc812a 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -156,7 +156,7 @@ impl FlagComputation { } &ty::TyAlias(_, substs) => { - self.add_flags(TypeFlags::HAS_TY_PROJECTION); + self.add_flags(TypeFlags::HAS_TY_ALIAS); self.add_substs(substs); } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index de3b37091ef35..ecc5c8c98b259 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -384,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, ), } } 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; } } From 042c9edecb79417d26281af092f903efe8b260a1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 13 Jun 2022 00:52:52 +0200 Subject: [PATCH 17/28] Replace `.type_of()` calls with `.bound_type_of()` --- .../rustc_infer/src/infer/outlives/components.rs | 6 ++++-- compiler/rustc_lint/src/types.rs | 14 +++++--------- compiler/rustc_middle/src/ty/layout.rs | 6 ++++++ compiler/rustc_middle/src/ty/util.rs | 6 +++++- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs index 9d30535dee213..81ad83ce16ca5 100644 --- a/compiler/rustc_infer/src/infer/outlives/components.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -169,8 +169,10 @@ fn compute_components<'tcx>( out.push(Component::UnresolvedInferenceVariable(infer_ty)); } - ty::TyAlias(def_id, _) => { - compute_components(tcx, tcx.type_of(def_id), out, visited); + 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 diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index adc2f880e8548..e25b6636b89bb 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, Subst, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, +}; use rustc_span::source_map; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol, DUMMY_SP}; @@ -1135,14 +1137,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } ty::TyAlias(def_id, substs) => { - for ty in substs.types() { - let ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, ty); - match self.check_type_for_ffi(cache, ty) { - FfiSafe => {} - r => return r, - }; - } - let ty = tcx.type_of(def_id); + 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) } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 1107b246467b5..8efeaf51fce38 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), } } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index e485fc4b4e471..e0fa7dd2c6588 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1050,7 +1050,11 @@ impl<'tcx> Ty<'tcx> { | ty::Placeholder(_) | ty::Infer(_) => false, - ty::TyAlias(def_id, _) => tcx.type_of(def_id).is_structural_eq_shallow(tcx), + 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, } From 4f632c331dc070b85e6b01645cc4cee3298cf831 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 13 Jun 2022 13:21:02 +0200 Subject: [PATCH 18/28] Update failing mangling ui tests --- src/test/ui/symbol-names/basic.legacy.stderr | 4 ++-- src/test/ui/symbol-names/issue-60925.legacy.stderr | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) 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] From cc95610dd31ea3642301ac571b7d2f5398a98710 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 15 Jun 2022 13:20:48 +0200 Subject: [PATCH 19/28] Update ui-fulldeps test --- .../internal-lints/ty_tykind_usage.rs | 1 + .../internal-lints/ty_tykind_usage.stderr | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) 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 From 45f038f5586d3bf424711c942b81164a886dbefe Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 20 Jun 2022 12:04:46 +0200 Subject: [PATCH 20/28] crash if invalid type kind in const_to_valtree_inner --- .../src/const_eval/valtrees.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 0f1d3b8e92fd0..4570eecc9385c 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -140,21 +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(..) - // FIXME: we could look behind type aliases. - | ty::TyAlias(..) | 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()) + } } } From 94da5372f0d148b8750c2c9a93ad4c0d84f30c2a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 27 Jun 2022 21:32:04 +0200 Subject: [PATCH 21/28] Add missing mk_ty_alias call into astconv --- compiler/rustc_hir_analysis/src/astconv/mod.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) 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); From 338167327a87322dd9d428064e7810988f9b1f68 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 28 Jun 2022 00:03:04 +0200 Subject: [PATCH 22/28] Add UI test for ty alias mangling --- .../ui/symbol-names/ty-alias.legacy.stderr | 38 +++++++++++++++++++ src/test/ui/symbol-names/ty-alias.rs | 34 +++++++++++++++++ src/test/ui/symbol-names/ty-alias.v0.stderr | 38 +++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 src/test/ui/symbol-names/ty-alias.legacy.stderr create mode 100644 src/test/ui/symbol-names/ty-alias.rs create mode 100644 src/test/ui/symbol-names/ty-alias.v0.stderr 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 + From 29d628c38b4fe302c9f8b1439edab415fc2c8ec6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 30 Jun 2022 21:46:00 +0200 Subject: [PATCH 23/28] Fix compilation errors for TyAlias --- .../src/coherence/inherent_impls.rs | 2 +- compiler/rustc_hir_typeck/src/cast.rs | 2 +- compiler/rustc_middle/src/ty/layout.rs | 6 +++--- compiler/rustc_privacy/src/lib.rs | 3 +-- .../rustc_trait_selection/src/traits/project.rs | 13 +++++++++---- .../src/traits/query/normalize.rs | 6 +++--- .../src/traits/select/confirmation.rs | 1 + compiler/rustc_trait_selection/src/traits/wf.rs | 5 +++-- 8 files changed, 22 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index aca22fbeb7bea..86c8e25b93788 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -12,7 +12,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams}; -use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt}; +use rustc_middle::ty::{self, CrateInherentImpls, Subst, Ty, TyCtxt}; use rustc_span::symbol::sym; use rustc_span::Span; diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 9cd0e41966723..38244dce8acac 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -123,7 +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(..) => span_bug!(span, "unexpected TyAlias in pointer_kind"), + 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_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 8efeaf51fce38..919a45c2cff83 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -670,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) @@ -680,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() }); } @@ -779,7 +779,7 @@ where | ty::Param(_) | ty::Infer(_) | ty::TyAlias(_, _) - | ty::Error(_) => bug!("TyAndLayout::field: unexpected type `{}`", this.ty), + | ty::Error(_) => bug!("TyAndLayout::field: unexpected type `{}`", ty), } } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 6404462b8e41c..8682205b94fe1 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -28,7 +28,7 @@ use rustc_middle::span_bug; use rustc_middle::ty::abstract_const::{walk_abstract_const, AbstractConst, Node as ACNode}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::subst::InternalSubsts; -use rustc_middle::ty::{self, Const, DefIdTree, GenericParamDefKind}; +use rustc_middle::ty::{self, Const, DefIdTree, GenericParamDefKind, Subst}; use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor}; use rustc_session::lint; use rustc_span::hygiene::Transparency; @@ -275,7 +275,6 @@ where | ty::FnPtr(..) | ty::Param(..) | ty::Error(_) - | ty::TyAlias(..) | ty::GeneratorWitness(..) => {} ty::Bound(..) | ty::Placeholder(..) | ty::Infer(..) => { bug!("unexpected type: {:?}", ty) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index ecc5c8c98b259..a6d4f91152b9f 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -465,7 +465,12 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { } } - fn fold_reveal(&mut self, ty: Ty<'tcx>, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> { + 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 = @@ -534,11 +539,11 @@ 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 => self.fold_reveal(ty, def_id, substs), + Reveal::All => self.fold_alias_or_revealed_opaque(ty, def_id, substs), } } - ty::TyAlias(def_id, substs) => self.fold_reveal(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 @@ -1418,7 +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::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. diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index a8fae37c0a00b..3d14abf3b9d79 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -166,7 +166,7 @@ struct QueryNormalizer<'cx, 'tcx> { } impl<'cx, 'tcx> QueryNormalizer<'cx, 'tcx> { - fn fold_reveal( + fn fold_alias_or_revealed_opaque( &mut self, ty: Ty<'tcx>, def_id: DefId, @@ -238,11 +238,11 @@ 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 => self.fold_reveal(ty, def_id, substs), + Reveal::All => self.fold_alias_or_revealed_opaque(ty, def_id, substs), } } - ty::TyAlias(def_id, substs) => self.fold_reveal(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, diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 3536494c824f4..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), }; diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 2b3f305f59620..e525d33cb304a 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -907,8 +907,9 @@ impl<'tcx> WfPredicates<'tcx> { )); } - ty::TyAlias(..) => { - bug!("unexpected TyAlias in WfPredicates::compute"); + ty::TyAlias(did, substs) => { + let obligations = self.nominal_obligations(did, substs); + self.out.extend(obligations); } } From 4815a60864c4ee5bf490974d172c4209a603bbdc Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 7 Jul 2022 15:55:29 +0200 Subject: [PATCH 24/28] Improve code --- .../src/coherence/inherent_impls.rs | 2 +- .../src/variance/constraints.rs | 8 +- .../rustc_trait_selection/src/traits/wf.rs | 260 ++---------------- 3 files changed, 30 insertions(+), 240 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index 86c8e25b93788..aca22fbeb7bea 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -12,7 +12,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams}; -use rustc_middle::ty::{self, CrateInherentImpls, Subst, Ty, TyCtxt}; +use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt}; use rustc_span::symbol::sym; use rustc_span::Span; diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index 6499086eebd81..96c7436a18d5a 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -7,7 +7,7 @@ use hir::def_id::{DefId, LocalDefId}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, Subst, Ty, TyCtxt}; use super::terms::VarianceTerm::*; use super::terms::*; @@ -257,8 +257,10 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_invariant_substs(current, substs, variance); } - ty::TyAlias(_, substs) => { - 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, _) => { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index e525d33cb304a..a32069a7ea5c8 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, Subst, ToPredicate, Ty, TyCtxt, TypeVisitable}; use rustc_span::Span; use std::iter; @@ -505,15 +506,15 @@ impl<'tcx> WfPredicates<'tcx> { cause, depth, param_env, - ty::Binder::dummy(ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate( - rty, r, - ))) + ty::Binder::dummy(ty::PredicateKind::TypeOutlives( + ty::OutlivesPredicate(rty, r), + )) .to_predicate(self.tcx()), )); } } - ty::Generator(..) => { + 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 @@ -521,6 +522,8 @@ impl<'tcx> WfPredicates<'tcx> { // 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) => { @@ -572,18 +575,16 @@ impl<'tcx> WfPredicates<'tcx> { } ty::Opaque(did, substs) => { - // all of the requirements on type parameters - // should've been checked by the instantiation - // of whatever returned this exact `impl Trait`. - - // for named opaque `impl Trait` types we still need to check them - if ty::is_impl_trait_defn(self.infcx.tcx, did).is_none() { + // 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) => { + ty::Dynamic(data, r, _) => { // WfObject // // Here, we defer WF checking due to higher-ranked @@ -605,7 +606,8 @@ impl<'tcx> WfPredicates<'tcx> { cause.clone(), depth, param_env, - ty::Binder::dummy(ty::PredicateKind::ObjectSafe(did)).to_predicate(tcx), + ty::Binder::dummy(ty::PredicateKind::ObjectSafe(did)) + .to_predicate(tcx), ) })); } @@ -624,22 +626,14 @@ impl<'tcx> WfPredicates<'tcx> { // See also the comment on `fn obligations`, describing "livelock" // prevention, which happens before this can be reached. ty::Infer(_) => { - let ty = self.infcx.shallow_resolve(ty); - if let ty::Infer(ty::TyVar(_)) = ty.kind() { - // Not yet resolved, but we've made progress. - 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()), - )); - } else { - // Yes, resolved, proceed with the result. - // FIXME(eddyb) add the type to `walker` instead of recursing. - self.compute(ty.into()); - } + 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) => { @@ -707,213 +701,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()), - )); - } - - ty::TyAlias(did, substs) => { - let obligations = self.nominal_obligations(did, substs); - self.out.extend(obligations); - } - } - - debug!(?self.out); + self.compute_ty(ty, &mut walker, depth, param_env); } } From dcca5d5dc298b8e19ce185bc10bf3a9ea250c2c5 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 11 Jul 2022 22:59:37 +0200 Subject: [PATCH 25/28] Update clippy to handle TyAlias --- src/tools/clippy/clippy_lints/src/dereference.rs | 5 +++++ 1 file changed, 5 insertions(+) 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() }, From 7d76dc9d11d6a1083a286810b2b5f10d99584615 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 22 Jul 2022 01:15:47 +0200 Subject: [PATCH 26/28] Improve TyCtxt::peel_off_ty_alias --- compiler/rustc_middle/src/ty/context.rs | 31 +++++++++++++++++++++---- compiler/rustc_middle/src/ty/visit.rs | 3 +++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 9ba6f37a3aae9..af3572c633bd6 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1729,12 +1729,33 @@ impl<'tcx> TyCtxt<'tcx> { /// 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, mut ty: Ty<'tcx>) -> Ty<'tcx> { - while let ty::TyAlias(def_id, substs) = *ty.kind() { - let binder_ty = self.bound_type_of(def_id); - ty = binder_ty.subst(self, substs); + pub fn peel_off_ty_alias>(self, ty: T) -> T { + struct TyAliasPeeler<'t> { + tcx: TyCtxt<'t>, } - ty + + 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 }) } } 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) } From 9e7f02b3959383cbea1e06c4fbec90357782afa4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Jul 2022 16:23:29 +0200 Subject: [PATCH 27/28] Update some UI tests --- src/test/ui/impl-trait/trait_type.stderr | 6 +++--- src/test/ui/nll/type-alias-free-regions.stderr | 4 ++-- src/test/ui/privacy/private-in-public-warn.rs | 2 +- src/test/ui/privacy/private-in-public-warn.stderr | 2 +- src/test/ui/regions/regions-infer-paramd-indirect.stderr | 2 +- .../self/arbitrary_self_types_pin_lifetime_mismatch.stderr | 2 +- src/test/ui/span/impl-wrong-item-for-trait.stderr | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) 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/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 From c383c9daded50c800a091c5a806c7f03c7d2bd0c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 6 Sep 2022 16:11:57 +0200 Subject: [PATCH 28/28] Fix missing type alias cycle detection --- .../rustc_hir_analysis/src/check/wfcheck.rs | 49 ++++++++++++++++++- .../src/variance/constraints.rs | 2 +- compiler/rustc_lint/src/types.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 2 +- .../src/traits/project.rs | 2 +- .../src/traits/query/normalize.rs | 2 +- .../rustc_trait_selection/src/traits/wf.rs | 11 ++--- .../infinite-type-alias-mutual-recursion.rs | 4 +- ...nfinite-type-alias-mutual-recursion.stderr | 42 ++++++---------- 9 files changed, 74 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 1627e5e751229..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 { .. } => {} _ => {} diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index 96c7436a18d5a..b935b2c5cf282 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -7,7 +7,7 @@ use hir::def_id::{DefId, LocalDefId}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; -use rustc_middle::ty::{self, Subst, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use super::terms::VarianceTerm::*; use super::terms::*; diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index e25b6636b89bb..6fa42f292040d 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -9,7 +9,7 @@ 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, Subst, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, + self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, }; use rustc_span::source_map; use rustc_span::symbol::sym; diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 8682205b94fe1..99119536f4ba7 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -28,7 +28,7 @@ use rustc_middle::span_bug; use rustc_middle::ty::abstract_const::{walk_abstract_const, AbstractConst, Node as ACNode}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::subst::InternalSubsts; -use rustc_middle::ty::{self, Const, DefIdTree, GenericParamDefKind, Subst}; +use rustc_middle::ty::{self, Const, DefIdTree, GenericParamDefKind}; use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor}; use rustc_session::lint; use rustc_span::hygiene::Transparency; diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index a6d4f91152b9f..4b350101a4d61 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -30,7 +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::{Subst, SubstsRef}; +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}; diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 3d14abf3b9d79..4a108e067b1b3 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -13,7 +13,7 @@ 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::{Subst, SubstsRef}; +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; diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index a32069a7ea5c8..1fbd4d853b2ef 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -5,7 +5,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; use rustc_middle::ty::walk::TypeWalker; -use rustc_middle::ty::{self, ParamEnv, Subst, ToPredicate, Ty, TyCtxt, TypeVisitable}; +use rustc_middle::ty::{self, ParamEnv, ToPredicate, Ty, TyCtxt, TypeVisitable}; use rustc_span::Span; use std::iter; @@ -506,9 +506,9 @@ impl<'tcx> WfPredicates<'tcx> { cause, depth, param_env, - ty::Binder::dummy(ty::PredicateKind::TypeOutlives( - ty::OutlivesPredicate(rty, r), - )) + ty::Binder::dummy(ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate( + rty, r, + ))) .to_predicate(self.tcx()), )); } @@ -606,8 +606,7 @@ impl<'tcx> WfPredicates<'tcx> { cause.clone(), depth, param_env, - ty::Binder::dummy(ty::PredicateKind::ObjectSafe(did)) - .to_predicate(tcx), + ty::Binder::dummy(ty::PredicateKind::ObjectSafe(did)).to_predicate(tcx), ) })); } 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`.