1
Fork 0

Auto merge of #104986 - compiler-errors:opaques, r=oli-obk

Combine `ty::Projection` and `ty::Opaque` into `ty::Alias`

Implements https://github.com/rust-lang/types-team/issues/79.

This PR consolidates `ty::Projection` and `ty::Opaque` into a single `ty::Alias`, with an `AliasKind` and `AliasTy` type (renamed from `ty::ProjectionTy`, which is the inner data of `ty::Projection`) defined as so:

```
enum AliasKind {
  Projection,
  Opaque,
}

struct AliasTy<'tcx> {
  def_id: DefId,
  substs: SubstsRef<'tcx>,
}
```

Since we don't have access to `TyCtxt` in type flags computation, and because repeatedly calling `DefKind` on the def-id is expensive, these two types are distinguished with `ty::AliasKind`, conveniently glob-imported into `ty::{Projection, Opaque}`. For example:

```diff
  match ty.kind() {
-   ty::Opaque(..) =>
+   ty::Alias(ty::Opaque, ..) => {}
    _ => {}
  }
```

This PR also consolidates match arms that treated `ty::Opaque` and `ty::Projection` identically.

r? `@ghost`
This commit is contained in:
bors 2022-12-14 01:19:24 +00:00
commit 918d0ac38e
115 changed files with 632 additions and 674 deletions

View file

@ -250,7 +250,7 @@ pub enum ObligationCauseCode<'tcx> {
TupleElem,
/// This is the trait reference from the given projection.
ProjectionWf(ty::ProjectionTy<'tcx>),
ProjectionWf(ty::AliasTy<'tcx>),
/// Must satisfy all of the where-clause predicates of the
/// given item.

View file

@ -76,8 +76,7 @@ pub mod type_op {
}
}
pub type CanonicalProjectionGoal<'tcx> =
Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::ProjectionTy<'tcx>>>;
pub type CanonicalProjectionGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::AliasTy<'tcx>>>;
pub type CanonicalTyGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>>;
@ -218,6 +217,6 @@ pub struct NormalizationResult<'tcx> {
pub enum OutlivesBound<'tcx> {
RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>),
RegionSubProjection(ty::Region<'tcx>, ty::AliasTy<'tcx>),
RegionSubOpaque(ty::Region<'tcx>, DefId, SubstsRef<'tcx>),
}

View file

@ -18,12 +18,11 @@ use crate::thir::Thir;
use crate::traits;
use crate::ty::query::{self, TyCtxtAt};
use crate::ty::{
self, AdtDef, AdtDefData, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig,
self, AdtDef, AdtDefData, AdtKind, AliasTy, Binder, BindingMode, BoundVar, CanonicalPolyFnSig,
ClosureSizeProfileData, Const, ConstS, DefIdTree, FloatTy, FloatVar, FloatVid,
GenericParamDefKind, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy,
PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, ProjectionTy, Region,
RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy,
Visibility,
PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind, ReprOptions,
TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy, Visibility,
};
use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubsts};
use rustc_ast as ast;
@ -116,7 +115,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
type ListBinderExistentialPredicate = &'tcx List<PolyExistentialPredicate<'tcx>>;
type BinderListTy = Binder<'tcx, &'tcx List<Ty<'tcx>>>;
type ListTy = &'tcx List<Ty<'tcx>>;
type ProjectionTy = ty::ProjectionTy<'tcx>;
type AliasTy = ty::AliasTy<'tcx>;
type ParamTy = ParamTy;
type BoundTy = ty::BoundTy;
type PlaceholderType = ty::PlaceholderType;
@ -2145,8 +2144,7 @@ impl<'tcx> TyCtxt<'tcx> {
Bound,
Param,
Infer,
Projection,
Opaque,
Alias,
Foreign
)?;
@ -2323,7 +2321,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Given a `ty`, return whether it's an `impl Future<...>`.
pub fn ty_is_opaque_future(self, ty: Ty<'_>) -> bool {
let ty::Opaque(def_id, _) = ty.kind() else { return false };
let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs: _ }) = ty.kind() else { return false };
let future_trait = self.require_lang_item(LangItem::Future, None);
self.explicit_item_bounds(def_id).iter().any(|(predicate, _)| {
@ -2598,7 +2596,7 @@ impl<'tcx> TyCtxt<'tcx> {
substs.len(),
"wrong number of generic parameters for {item_def_id:?}: {substs:?}",
);
self.mk_ty(Projection(ProjectionTy { item_def_id, substs }))
self.mk_ty(Alias(ty::Projection, AliasTy { def_id: item_def_id, substs }))
}
#[inline]
@ -2668,7 +2666,7 @@ impl<'tcx> TyCtxt<'tcx> {
#[inline]
pub fn mk_opaque(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
self.mk_ty(Opaque(def_id, substs))
self.mk_ty(Alias(ty::Opaque, ty::AliasTy { def_id, substs }))
}
pub fn mk_place_field(self, place: Place<'tcx>, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {

View file

@ -3,8 +3,8 @@
use std::ops::ControlFlow;
use crate::ty::{
visit::TypeVisitable, Const, ConstKind, DefIdTree, ExistentialPredicate, InferConst, InferTy,
PolyTraitPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor,
visit::TypeVisitable, AliasTy, Const, ConstKind, DefIdTree, ExistentialPredicate, InferConst,
InferTy, Opaque, PolyTraitPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor,
};
use rustc_data_structures::fx::FxHashMap;
@ -457,11 +457,11 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
return ControlFlow::Break(());
}
Opaque(did, _) => {
let parent = self.tcx.parent(*did);
Alias(Opaque, AliasTy { def_id, substs: _ }) => {
let parent = self.tcx.parent(*def_id);
if let hir::def::DefKind::TyAlias | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent)
&& let Opaque(parent_did, _) = self.tcx.type_of(parent).kind()
&& parent_did == did
&& let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, substs: _ }) = self.tcx.type_of(parent).kind()
&& parent_opaque_def_id == def_id
{
// Okay
} else {

View file

@ -337,9 +337,9 @@ impl<'tcx> Ty<'tcx> {
ty::Infer(ty::FreshTy(_)) => "fresh type".into(),
ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(),
ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
ty::Projection(_) => "associated type".into(),
ty::Alias(ty::Projection, _) => "associated type".into(),
ty::Param(p) => format!("type parameter `{}`", p).into(),
ty::Opaque(..) => "opaque type".into(),
ty::Alias(ty::Opaque, ..) => "opaque type".into(),
ty::Error(_) => "type error".into(),
}
}
@ -375,9 +375,9 @@ impl<'tcx> Ty<'tcx> {
ty::Tuple(..) => "tuple".into(),
ty::Placeholder(..) => "higher-ranked type".into(),
ty::Bound(..) => "bound type variable".into(),
ty::Projection(_) => "associated type".into(),
ty::Alias(ty::Projection, _) => "associated type".into(),
ty::Param(_) => "type parameter".into(),
ty::Opaque(..) => "opaque type".into(),
ty::Alias(ty::Opaque, ..) => "opaque type".into(),
}
}
}
@ -400,7 +400,7 @@ impl<'tcx> TyCtxt<'tcx> {
diag.note("no two closures, even if identical, have the same type");
diag.help("consider boxing your closure and/or using it as a trait object");
}
(ty::Opaque(..), ty::Opaque(..)) => {
(ty::Alias(ty::Opaque, ..), ty::Alias(ty::Opaque, ..)) => {
// Issue #63167
diag.note("distinct uses of `impl Trait` result in different opaque types");
}
@ -439,11 +439,11 @@ impl<'tcx> TyCtxt<'tcx> {
#traits-as-parameters",
);
}
(ty::Projection(_), ty::Projection(_)) => {
(ty::Alias(ty::Projection, _), ty::Alias(ty::Projection, _)) => {
diag.note("an associated type was expected, but a different one was found");
}
(ty::Param(p), ty::Projection(proj)) | (ty::Projection(proj), ty::Param(p))
if self.def_kind(proj.item_def_id) != DefKind::ImplTraitPlaceholder =>
(ty::Param(p), ty::Alias(ty::Projection, proj)) | (ty::Alias(ty::Projection, proj), ty::Param(p))
if self.def_kind(proj.def_id) != DefKind::ImplTraitPlaceholder =>
{
let generics = self.generics_of(body_owner_def_id);
let p_span = self.def_span(generics.type_param(p, self).def_id);
@ -466,7 +466,7 @@ impl<'tcx> TyCtxt<'tcx> {
let (trait_ref, assoc_substs) = proj.trait_ref_and_own_substs(self);
let path =
self.def_path_str_with_substs(trait_ref.def_id, trait_ref.substs);
let item_name = self.item_name(proj.item_def_id);
let item_name = self.item_name(proj.def_id);
let item_args = self.format_generic_args(assoc_substs);
let path = if path.ends_with('>') {
@ -493,8 +493,8 @@ impl<'tcx> TyCtxt<'tcx> {
diag.note("you might be missing a type parameter or trait bound");
}
}
(ty::Param(p), ty::Dynamic(..) | ty::Opaque(..))
| (ty::Dynamic(..) | ty::Opaque(..), ty::Param(p)) => {
(ty::Param(p), ty::Dynamic(..) | ty::Alias(ty::Opaque, ..))
| (ty::Dynamic(..) | ty::Alias(ty::Opaque, ..), ty::Param(p)) => {
let generics = self.generics_of(body_owner_def_id);
let p_span = self.def_span(generics.type_param(p, self).def_id);
if !sp.contains(p_span) {
@ -553,7 +553,7 @@ impl<T> Trait<T> for X {
diag.span_label(p_span, "this type parameter");
}
}
(ty::Projection(proj_ty), _) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => {
(ty::Alias(ty::Projection, proj_ty), _) if self.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
self.expected_projection(
diag,
proj_ty,
@ -562,7 +562,7 @@ impl<T> Trait<T> for X {
cause.code(),
);
}
(_, ty::Projection(proj_ty)) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => {
(_, ty::Alias(ty::Projection, proj_ty)) if self.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
let msg = format!(
"consider constraining the associated type `{}` to `{}`",
values.found, values.expected,
@ -624,10 +624,10 @@ impl<T> Trait<T> for X {
diag: &mut Diagnostic,
msg: &str,
body_owner_def_id: DefId,
proj_ty: &ty::ProjectionTy<'tcx>,
proj_ty: &ty::AliasTy<'tcx>,
ty: Ty<'tcx>,
) -> bool {
let assoc = self.associated_item(proj_ty.item_def_id);
let assoc = self.associated_item(proj_ty.def_id);
let (trait_ref, assoc_substs) = proj_ty.trait_ref_and_own_substs(self);
if let Some(item) = self.hir().get_if_local(body_owner_def_id) {
if let Some(hir_generics) = item.generics() {
@ -680,7 +680,7 @@ impl<T> Trait<T> for X {
fn expected_projection(
self,
diag: &mut Diagnostic,
proj_ty: &ty::ProjectionTy<'tcx>,
proj_ty: &ty::AliasTy<'tcx>,
values: ExpectedFound<Ty<'tcx>>,
body_owner_def_id: DefId,
cause_code: &ObligationCauseCode<'_>,
@ -703,7 +703,7 @@ impl<T> Trait<T> for X {
);
let impl_comparison =
matches!(cause_code, ObligationCauseCode::CompareImplItemObligation { .. });
let assoc = self.associated_item(proj_ty.item_def_id);
let assoc = self.associated_item(proj_ty.def_id);
if !callable_scope || impl_comparison {
// We do not want to suggest calling functions when the reason of the
// type error is a comparison of an `impl` with its `trait` or when the
@ -716,7 +716,7 @@ impl<T> Trait<T> for X {
diag,
assoc.container_id(self),
current_method_ident,
proj_ty.item_def_id,
proj_ty.def_id,
values.expected,
);
// Possibly suggest constraining the associated type to conform to the
@ -775,11 +775,12 @@ fn foo(&self) -> Self::T { String::new() }
self,
diag: &mut Diagnostic,
msg: &str,
proj_ty: &ty::ProjectionTy<'tcx>,
proj_ty: &ty::AliasTy<'tcx>,
ty: Ty<'tcx>,
) -> bool {
let assoc = self.associated_item(proj_ty.item_def_id);
if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() {
let assoc = self.associated_item(proj_ty.def_id);
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs: _ }) = *proj_ty.self_ty().kind()
{
let opaque_local_def_id = def_id.as_local();
let opaque_hir_ty = if let Some(opaque_local_def_id) = opaque_local_def_id {
match &self.hir().expect_item(opaque_local_def_id).kind {
@ -828,7 +829,7 @@ fn foo(&self) -> Self::T { String::new() }
.filter_map(|(_, item)| {
let method = self.fn_sig(item.def_id);
match *method.output().skip_binder().kind() {
ty::Projection(ty::ProjectionTy { item_def_id, .. })
ty::Alias(ty::Projection, ty::AliasTy { def_id: item_def_id, .. })
if item_def_id == proj_ty_item_def_id =>
{
Some((

View file

@ -126,7 +126,7 @@ pub fn simplify_type<'tcx>(
TreatParams::AsPlaceholder => Some(PlaceholderSimplifiedType),
TreatParams::AsInfer => None,
},
ty::Opaque(..) | ty::Projection(_) => match treat_params {
ty::Alias(..) => 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.
//
@ -225,7 +225,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(_) | ty::Opaque(..) => return true,
ty::Param(_) | ty::Error(_) | ty::Alias(..) => return true,
// These types only unify with inference variables or their own
// variant.
ty::Bool
@ -323,8 +323,6 @@ impl DeepRejectCtxt {
_ => false,
},
ty::Opaque(..) => true,
// Impls cannot contain these types as these cannot be named directly.
ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false,
@ -344,7 +342,7 @@ impl DeepRejectCtxt {
// projections can unify with other stuff.
//
// Looking forward to lazy normalization this is the safer strategy anyways.
ty::Projection(_) => true,
ty::Alias(..) => true,
ty::Error(_) => true,

View file

@ -155,12 +155,12 @@ impl FlagComputation {
self.add_substs(substs);
}
&ty::Projection(data) => {
&ty::Alias(ty::Projection, data) => {
self.add_flags(TypeFlags::HAS_TY_PROJECTION);
self.add_projection_ty(data);
}
&ty::Opaque(_, substs) => {
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: _, substs }) => {
self.add_flags(TypeFlags::HAS_TY_OPAQUE);
self.add_substs(substs);
}
@ -345,7 +345,7 @@ impl FlagComputation {
}
}
fn add_projection_ty(&mut self, projection_ty: ty::ProjectionTy<'_>) {
fn add_projection_ty(&mut self, projection_ty: ty::AliasTy<'_>) {
self.add_substs(projection_ty.substs);
}

View file

@ -112,7 +112,7 @@ impl<'tcx> Ty<'tcx> {
InhabitedPredicate::True
}
Never => InhabitedPredicate::False,
Param(_) | Projection(_) => InhabitedPredicate::GenericType(self),
Param(_) | Alias(ty::Projection, _) => InhabitedPredicate::GenericType(self),
Tuple(tys) if tys.is_empty() => InhabitedPredicate::True,
// use a query for more complex cases
Adt(..) | Array(..) | Tuple(_) => tcx.inhabited_predicate_type(self),

View file

@ -271,7 +271,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
let non_zero = !ty.is_unsafe_ptr();
let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
match tail.kind() {
ty::Param(_) | ty::Projection(_) => {
ty::Param(_) | ty::Alias(ty::Projection, _) => {
debug_assert!(tail.has_non_region_param());
Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) })
}
@ -349,7 +349,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
}
}
ty::Projection(_) | ty::Opaque(..) => {
ty::Alias(..) => {
let normalized = tcx.normalize_erasing_regions(param_env, ty);
if ty == normalized {
Err(err)
@ -757,10 +757,9 @@ where
}
}
ty::Projection(_)
ty::Alias(..)
| ty::Bound(..)
| ty::Placeholder(..)
| ty::Opaque(..)
| ty::Param(_)
| ty::Infer(_)
| ty::Error(_) => bug!("TyAndLayout::field: unexpected type `{}`", this.ty),

View file

@ -64,6 +64,7 @@ use std::ops::ControlFlow;
use std::{fmt, str};
pub use crate::ty::diagnostics::*;
pub use rustc_type_ir::AliasKind::*;
pub use rustc_type_ir::DynKind::*;
pub use rustc_type_ir::InferTy::*;
pub use rustc_type_ir::RegionKind::*;
@ -93,14 +94,13 @@ pub use self::parameterized::ParameterizedOverTcx;
pub use self::rvalue_scopes::RvalueScopes;
pub use self::sty::BoundRegionKind::*;
pub use self::sty::{
Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid,
EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig,
FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts,
InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialPredicate,
PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef,
ProjectionTy, Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts,
VarianceDiagInfo,
Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo,
};
pub use self::trait_def::TraitDef;
@ -1010,7 +1010,7 @@ impl<'tcx> TermKind<'tcx> {
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct ProjectionPredicate<'tcx> {
pub projection_ty: ProjectionTy<'tcx>,
pub projection_ty: AliasTy<'tcx>,
pub term: Term<'tcx>,
}
@ -1046,7 +1046,7 @@ impl<'tcx> PolyProjectionPredicate<'tcx> {
/// associated type, which is in `tcx.associated_item(projection_def_id()).container`.
pub fn projection_def_id(&self) -> DefId {
// Ok to skip binder since trait `DefId` does not care about regions.
self.skip_binder().projection_ty.item_def_id
self.skip_binder().projection_ty.def_id
}
}

View file

@ -275,10 +275,9 @@ fn characteristic_def_id_of_type_cached<'a>(
| ty::Uint(_)
| ty::Str
| ty::FnPtr(_)
| ty::Projection(_)
| ty::Alias(..)
| ty::Placeholder(..)
| ty::Param(_)
| ty::Opaque(..)
| ty::Infer(_)
| ty::Bound(..)
| ty::Error(_)

View file

@ -718,17 +718,17 @@ pub trait PrettyPrinter<'tcx>:
ty::Foreign(def_id) => {
p!(print_def_path(def_id, &[]));
}
ty::Projection(ref data) => {
ty::Alias(ty::Projection, ref data) => {
if !(self.should_print_verbose() || NO_QUERIES.with(|q| q.get()))
&& self.tcx().def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder
&& self.tcx().def_kind(data.def_id) == DefKind::ImplTraitPlaceholder
{
return self.pretty_print_opaque_impl_type(data.item_def_id, data.substs);
return self.pretty_print_opaque_impl_type(data.def_id, data.substs);
} else {
p!(print(data))
}
}
ty::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
ty::Opaque(def_id, substs) => {
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs }) => {
// FIXME(eddyb) print this with `print_def_path`.
// We use verbose printing in 'NO_QUERIES' mode, to
// avoid needing to call `predicates_of`. This should
@ -743,7 +743,9 @@ pub trait PrettyPrinter<'tcx>:
let parent = self.tcx().parent(def_id);
match self.tcx().def_kind(parent) {
DefKind::TyAlias | DefKind::AssocTy => {
if let ty::Opaque(d, _) = *self.tcx().type_of(parent).kind() {
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: d, substs: _ }) =
*self.tcx().type_of(parent).kind()
{
if d == def_id {
// If the type alias directly starts with the `impl` of the
// opaque type we're printing, then skip the `::{opaque#1}`.
@ -1019,8 +1021,8 @@ pub trait PrettyPrinter<'tcx>:
// Skip printing `<[generator@] as Generator<_>>::Return` from async blocks,
// unless we can find out what generator return type it comes from.
let term = if let Some(ty) = term.skip_binder().ty()
&& let ty::Projection(proj) = ty.kind()
&& let Some(assoc) = tcx.opt_associated_item(proj.item_def_id)
&& let ty::Alias(ty::Projection, proj) = ty.kind()
&& let Some(assoc) = tcx.opt_associated_item(proj.def_id)
&& assoc.trait_container(tcx) == tcx.lang_items().gen_trait()
&& assoc.name == rustc_span::sym::Return
{
@ -2653,7 +2655,7 @@ define_print_and_forward_display! {
}
ty::ExistentialProjection<'tcx> {
let name = cx.tcx().associated_item(self.item_def_id).name;
let name = cx.tcx().associated_item(self.def_id).name;
p!(write("{} = ", name), print(self.term))
}
@ -2740,8 +2742,8 @@ define_print_and_forward_display! {
}
}
ty::ProjectionTy<'tcx> {
p!(print_def_path(self.item_def_id, self.substs));
ty::AliasTy<'tcx> {
p!(print_def_path(self.def_id, self.substs));
}
ty::ClosureKind {

View file

@ -270,21 +270,17 @@ impl<'tcx> Relate<'tcx> for abi::Abi {
}
}
impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> {
impl<'tcx> Relate<'tcx> for ty::AliasTy<'tcx> {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
a: ty::ProjectionTy<'tcx>,
b: ty::ProjectionTy<'tcx>,
) -> RelateResult<'tcx, ty::ProjectionTy<'tcx>> {
if a.item_def_id != b.item_def_id {
Err(TypeError::ProjectionMismatched(expected_found(
relation,
a.item_def_id,
b.item_def_id,
)))
a: ty::AliasTy<'tcx>,
b: ty::AliasTy<'tcx>,
) -> RelateResult<'tcx, ty::AliasTy<'tcx>> {
if a.def_id != b.def_id {
Err(TypeError::ProjectionMismatched(expected_found(relation, a.def_id, b.def_id)))
} else {
let substs = relation.relate(a.substs, b.substs)?;
Ok(ty::ProjectionTy { item_def_id: a.item_def_id, substs: &substs })
Ok(ty::AliasTy { def_id: a.def_id, substs: &substs })
}
}
}
@ -295,12 +291,8 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
a: ty::ExistentialProjection<'tcx>,
b: ty::ExistentialProjection<'tcx>,
) -> RelateResult<'tcx, ty::ExistentialProjection<'tcx>> {
if a.item_def_id != b.item_def_id {
Err(TypeError::ProjectionMismatched(expected_found(
relation,
a.item_def_id,
b.item_def_id,
)))
if a.def_id != b.def_id {
Err(TypeError::ProjectionMismatched(expected_found(relation, a.def_id, b.def_id)))
} else {
let term = relation.relate_with_variance(
ty::Invariant,
@ -314,7 +306,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
a.substs,
b.substs,
)?;
Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, term })
Ok(ty::ExistentialProjection { def_id: a.def_id, substs, term })
}
}
}
@ -559,14 +551,15 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
}
// these two are already handled downstream in case of lazy normalization
(&ty::Projection(a_data), &ty::Projection(b_data)) => {
(&ty::Alias(ty::Projection, a_data), &ty::Alias(ty::Projection, b_data)) => {
let projection_ty = relation.relate(a_data, b_data)?;
Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs))
Ok(tcx.mk_projection(projection_ty.def_id, projection_ty.substs))
}
(&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs))
if a_def_id == b_def_id =>
{
(
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, substs: a_substs }),
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, substs: b_substs }),
) if a_def_id == b_def_id => {
if relation.intercrate() {
// During coherence, opaque types should be treated as equal to each other, even if their generic params
// differ, as they could resolve to the same hidden type, even for different generic params.

View file

@ -651,8 +651,7 @@ impl<'tcx> TypeSuperFoldable<'tcx> for Ty<'tcx> {
}
ty::GeneratorWitness(types) => ty::GeneratorWitness(types.try_fold_with(folder)?),
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::Alias(kind, data) => ty::Alias(kind, data.try_fold_with(folder)?),
ty::Bool
| ty::Char
@ -697,8 +696,7 @@ impl<'tcx> TypeSuperVisitable<'tcx> for Ty<'tcx> {
ty::Generator(_did, ref substs, _) => substs.visit_with(visitor),
ty::GeneratorWitness(ref types) => types.visit_with(visitor),
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::Alias(_, ref data) => data.visit_with(visitor),
ty::Bool
| ty::Char

View file

@ -693,7 +693,7 @@ impl<'tcx> ExistentialPredicate<'tcx> {
match (*self, *other) {
(Trait(_), Trait(_)) => Ordering::Equal,
(Projection(ref a), Projection(ref b)) => {
tcx.def_path_hash(a.item_def_id).cmp(&tcx.def_path_hash(b.item_def_id))
tcx.def_path_hash(a.def_id).cmp(&tcx.def_path_hash(b.def_id))
}
(AutoTrait(ref a), AutoTrait(ref b)) => {
tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b))
@ -1139,28 +1139,41 @@ impl<'tcx, T: IntoIterator> Binder<'tcx, T> {
}
}
/// Represents the projection of an associated type. In explicit UFCS
/// form this would be written `<T as Trait<..>>::N`.
/// Represents the projection of an associated type.
///
/// For a projection, this would be `<Ty as Trait<...>>::N`.
///
/// For an opaque type, there is no explicit syntax.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct ProjectionTy<'tcx> {
/// The parameters of the associated item.
pub struct AliasTy<'tcx> {
/// The parameters of the associated or opaque item.
///
/// For a projection, these are the substitutions for the trait and the
/// GAT substitutions, if there are any.
///
/// For RPIT the substitutions are for the generics of the function,
/// while for TAIT it is used for the generic parameters of the alias.
pub substs: SubstsRef<'tcx>,
/// The `DefId` of the `TraitItem` for the associated type `N`.
/// The `DefId` of the `TraitItem` for the associated type `N` if this is a projection,
/// or the `OpaqueType` item if this is an opaque.
///
/// Note that this is not the `DefId` of the `TraitRef` containing this
/// associated type, which is in `tcx.associated_item(item_def_id).container`,
/// aka. `tcx.parent(item_def_id).unwrap()`.
pub item_def_id: DefId,
/// During codegen, `tcx.type_of(def_id)` can be used to get the type of the
/// underlying type if the type is an opaque.
///
/// Note that if this is an associated type, this is not the `DefId` of the
/// `TraitRef` containing this associated type, which is in `tcx.associated_item(def_id).container`,
/// aka. `tcx.parent(def_id)`.
pub def_id: DefId,
}
impl<'tcx> ProjectionTy<'tcx> {
impl<'tcx> AliasTy<'tcx> {
pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
match tcx.def_kind(self.item_def_id) {
DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.item_def_id),
match tcx.def_kind(self.def_id) {
DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
DefKind::ImplTraitPlaceholder => {
tcx.parent(tcx.impl_trait_in_trait_parent(self.item_def_id))
tcx.parent(tcx.impl_trait_in_trait_parent(self.def_id))
}
kind => bug!("unexpected DefKind in ProjectionTy: {kind:?}"),
}
@ -1173,11 +1186,14 @@ impl<'tcx> ProjectionTy<'tcx> {
&self,
tcx: TyCtxt<'tcx>,
) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
let def_id = tcx.parent(self.item_def_id);
assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
let trait_generics = tcx.generics_of(def_id);
debug_assert!(matches!(tcx.def_kind(self.def_id), DefKind::AssocTy | DefKind::AssocConst));
let trait_def_id = self.trait_def_id(tcx);
let trait_generics = tcx.generics_of(trait_def_id);
(
ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, trait_generics) },
ty::TraitRef {
def_id: trait_def_id,
substs: self.substs.truncate_to(tcx, trait_generics),
},
&self.substs[trait_generics.count()..],
)
}
@ -1405,7 +1421,7 @@ impl From<BoundVar> for BoundTy {
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct ExistentialProjection<'tcx> {
pub item_def_id: DefId,
pub def_id: DefId,
pub substs: SubstsRef<'tcx>,
pub term: Term<'tcx>,
}
@ -1418,7 +1434,7 @@ impl<'tcx> ExistentialProjection<'tcx> {
/// then this function would return an `exists T. T: Iterator` existential trait
/// reference.
pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> {
let def_id = tcx.parent(self.item_def_id);
let def_id = tcx.parent(self.def_id);
let subst_count = tcx.generics_of(def_id).count() - 1;
let substs = tcx.intern_substs(&self.substs[..subst_count]);
ty::ExistentialTraitRef { def_id, substs }
@ -1433,8 +1449,8 @@ impl<'tcx> ExistentialProjection<'tcx> {
debug_assert!(!self_ty.has_escaping_bound_vars());
ty::ProjectionPredicate {
projection_ty: ty::ProjectionTy {
item_def_id: self.item_def_id,
projection_ty: ty::AliasTy {
def_id: self.def_id,
substs: tcx.mk_substs_trait(self_ty, self.substs),
},
term: self.term,
@ -1449,7 +1465,7 @@ impl<'tcx> ExistentialProjection<'tcx> {
projection_predicate.projection_ty.substs.type_at(0);
Self {
item_def_id: projection_predicate.projection_ty.item_def_id,
def_id: projection_predicate.projection_ty.def_id,
substs: tcx.intern_substs(&projection_predicate.projection_ty.substs[1..]),
term: projection_predicate.term,
}
@ -1466,7 +1482,7 @@ impl<'tcx> PolyExistentialProjection<'tcx> {
}
pub fn item_def_id(&self) -> DefId {
self.skip_binder().item_def_id
self.skip_binder().def_id
}
}
@ -1973,7 +1989,7 @@ impl<'tcx> Ty<'tcx> {
#[inline]
pub fn is_impl_trait(self) -> bool {
matches!(self.kind(), Opaque(..))
matches!(self.kind(), Alias(ty::Opaque, ..))
}
#[inline]
@ -2040,7 +2056,7 @@ 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::Param(_) | ty::Projection(_) | ty::Opaque(..) | ty::Infer(ty::TyVar(_)) => {
ty::Param(_) | ty::Alias(..) | ty::Infer(ty::TyVar(_)) => {
let assoc_items = tcx.associated_item_def_ids(
tcx.require_lang_item(hir::LangItem::DiscriminantKind, None),
);
@ -2120,7 +2136,7 @@ impl<'tcx> Ty<'tcx> {
// type parameters only have unit metadata if they're sized, so return true
// to make sure we double check this during confirmation
ty::Param(_) | ty::Projection(_) | ty::Opaque(..) => (tcx.types.unit, true),
ty::Param(_) | ty::Alias(..) => (tcx.types.unit, true),
ty::Infer(ty::TyVar(_))
| ty::Bound(..)
@ -2196,7 +2212,7 @@ impl<'tcx> Ty<'tcx> {
ty::Adt(def, _substs) => def.sized_constraint(tcx).0.is_empty(),
ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => false,
ty::Alias(..) | ty::Param(_) => false,
ty::Infer(ty::TyVar(_)) => false,
@ -2252,9 +2268,12 @@ impl<'tcx> Ty<'tcx> {
ty::Generator(..) | ty::GeneratorWitness(..) => false,
// Might be, but not "trivial" so just giving the safe answer.
ty::Adt(..) | ty::Closure(..) | ty::Opaque(..) => false,
ty::Adt(..) | ty::Closure(..) => false,
ty::Projection(..) | ty::Param(..) | ty::Infer(..) | ty::Error(..) => false,
// Needs normalization or revealing to determine, so no is the safe answer.
ty::Alias(..) => false,
ty::Param(..) | ty::Infer(..) | ty::Error(..) => false,
ty::Bound(..) | ty::Placeholder(..) => {
bug!("`is_trivially_pure_clone_copy` applied to unexpected type: {:?}", self);

View file

@ -259,7 +259,7 @@ impl<'tcx> TyCtxt<'tcx> {
ty::Tuple(_) => break,
ty::Projection(_) | ty::Opaque(..) => {
ty::Alias(..) => {
let normalized = normalize(ty);
if ty == normalized {
return ty;
@ -332,8 +332,7 @@ impl<'tcx> TyCtxt<'tcx> {
break;
}
}
(ty::Projection(_) | ty::Opaque(..), _)
| (_, ty::Projection(_) | ty::Opaque(..)) => {
(ty::Alias(..), _) | (_, ty::Alias(..)) => {
// If either side is a projection, attempt to
// progress via normalization. (Should be safe to
// apply to both sides as normalization is
@ -826,7 +825,7 @@ impl<'tcx> TypeFolder<'tcx> for OpaqueTypeExpander<'tcx> {
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if let ty::Opaque(def_id, substs) = *t.kind() {
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs }) = *t.kind() {
self.expand_opaque_ty(def_id, substs).unwrap_or(t)
} else if t.has_opaque_types() {
t.super_fold_with(self)
@ -938,10 +937,9 @@ impl<'tcx> Ty<'tcx> {
| ty::Generator(..)
| ty::GeneratorWitness(_)
| ty::Infer(_)
| ty::Opaque(..)
| ty::Alias(..)
| ty::Param(_)
| ty::Placeholder(_)
| ty::Projection(_) => false,
| ty::Placeholder(_) => false,
}
}
@ -978,10 +976,9 @@ impl<'tcx> Ty<'tcx> {
| ty::Generator(..)
| ty::GeneratorWitness(_)
| ty::Infer(_)
| ty::Opaque(..)
| ty::Alias(..)
| ty::Param(_)
| ty::Placeholder(_)
| ty::Projection(_) => false,
| ty::Placeholder(_) => false,
}
}
@ -1101,12 +1098,9 @@ impl<'tcx> Ty<'tcx> {
//
// FIXME(ecstaticmorse): Maybe we should `bug` here? This should probably only be
// called for known, fully-monomorphized types.
ty::Projection(_)
| ty::Opaque(..)
| ty::Param(_)
| ty::Bound(..)
| ty::Placeholder(_)
| ty::Infer(_) => false,
ty::Alias(..) | ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) => {
false
}
ty::Foreign(_) | ty::GeneratorWitness(..) | ty::Error(_) => false,
}
@ -1237,11 +1231,10 @@ pub fn needs_drop_components<'tcx>(
// These require checking for `Copy` bounds or `Adt` destructors.
ty::Adt(..)
| ty::Projection(..)
| ty::Alias(..)
| ty::Param(_)
| ty::Bound(..)
| ty::Placeholder(..)
| ty::Opaque(..)
| ty::Infer(_)
| ty::Closure(..)
| ty::Generator(..) => Ok(smallvec![ty]),
@ -1265,13 +1258,12 @@ pub fn is_trivially_const_drop<'tcx>(ty: Ty<'tcx>) -> bool {
| ty::Never
| ty::Foreign(_) => true,
ty::Opaque(..)
ty::Alias(..)
| ty::Dynamic(..)
| ty::Error(_)
| ty::Bound(..)
| ty::Param(_)
| ty::Placeholder(_)
| ty::Projection(_)
| ty::Infer(_) => false,
// Not trivial because they have components, and instead of looking inside,

View file

@ -654,7 +654,7 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
// ignore the inputs to a projection, as they may not appear
// in the normalized form
if self.just_constrained {
if let ty::Projection(..) | ty::Opaque(..) = t.kind() {
if let ty::Alias(..) = t.kind() {
return ControlFlow::CONTINUE;
}
}

View file

@ -165,7 +165,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
stack.push(ty.into());
stack.push(lt.into());
}
ty::Projection(data) => {
ty::Alias(_, data) => {
stack.extend(data.substs.iter().rev());
}
ty::Dynamic(obj, lt, _) => {
@ -188,7 +188,6 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
}));
}
ty::Adt(_, substs)
| ty::Opaque(_, substs)
| ty::Closure(_, substs)
| ty::Generator(_, substs, _)
| ty::FnDef(_, substs) => {