Validate ExistentialPredicate args
This commit is contained in:
parent
9368b9f57e
commit
2239f1c5cd
@ -250,7 +250,6 @@ pub(super) fn lower_trait_object_ty(
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let args = tcx.mk_args(&args);
|
||||
|
||||
let span = i.bottom().1;
|
||||
let empty_generic_args = hir_trait_bounds.iter().any(|(hir_bound, _)| {
|
||||
@ -283,7 +282,7 @@ pub(super) fn lower_trait_object_ty(
|
||||
.emit();
|
||||
}
|
||||
|
||||
ty::ExistentialTraitRef { def_id: trait_ref.def_id, args }
|
||||
ty::ExistentialTraitRef::new(tcx, trait_ref.def_id, args)
|
||||
})
|
||||
});
|
||||
|
||||
|
@ -279,6 +279,26 @@ fn debug_assert_args_compatible(self, def_id: DefId, args: ty::GenericArgsRef<'t
|
||||
self.debug_assert_args_compatible(def_id, args);
|
||||
}
|
||||
|
||||
/// Assert that the args from an `ExistentialTraitRef` or `ExistentialProjection`
|
||||
/// are compatible with the `DefId`. Since we're missing a `Self` type, stick on
|
||||
/// a dummy self type and forward to `debug_assert_args_compatible`.
|
||||
fn debug_assert_existential_args_compatible(
|
||||
self,
|
||||
def_id: Self::DefId,
|
||||
args: Self::GenericArgs,
|
||||
) {
|
||||
// FIXME: We could perhaps add a `skip: usize` to `debug_assert_args_compatible`
|
||||
// to avoid needing to reintern the set of args...
|
||||
if cfg!(debug_assertions) {
|
||||
self.debug_assert_args_compatible(
|
||||
def_id,
|
||||
self.mk_args_from_iter(
|
||||
[self.types.trait_object_dummy_self.into()].into_iter().chain(args.iter()),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn mk_type_list_from_iter<I, T>(self, args: I) -> T::Output
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
|
@ -322,7 +322,7 @@ fn propagate_from_alloc(&mut self, alloc: ConstAllocation<'tcx>) {
|
||||
self.visit(ty);
|
||||
// Manually visit to actually see the trait's `DefId`. Type visitors won't see it
|
||||
if let Some(trait_ref) = dyn_ty.principal() {
|
||||
let ExistentialTraitRef { def_id, args } = trait_ref.skip_binder();
|
||||
let ExistentialTraitRef { def_id, args, .. } = trait_ref.skip_binder();
|
||||
self.visit_def_id(def_id, "", &"");
|
||||
self.visit(args);
|
||||
}
|
||||
|
@ -32,8 +32,8 @@
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::print::PrintTraitRefExt as _;
|
||||
use rustc_middle::ty::{
|
||||
self, Const, GenericArgs, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable,
|
||||
TypeVisitable, TypeVisitor,
|
||||
self, Const, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
|
||||
TypeVisitor,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::lint;
|
||||
@ -246,10 +246,10 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
|
||||
ty::ExistentialPredicate::Trait(trait_ref) => trait_ref,
|
||||
ty::ExistentialPredicate::Projection(proj) => proj.trait_ref(tcx),
|
||||
ty::ExistentialPredicate::AutoTrait(def_id) => {
|
||||
ty::ExistentialTraitRef { def_id, args: GenericArgs::empty() }
|
||||
ty::ExistentialTraitRef::new(tcx, def_id, ty::GenericArgs::empty())
|
||||
}
|
||||
};
|
||||
let ty::ExistentialTraitRef { def_id, args: _ } = trait_ref;
|
||||
let ty::ExistentialTraitRef { def_id, .. } = trait_ref;
|
||||
try_visit!(self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref));
|
||||
}
|
||||
}
|
||||
|
@ -245,11 +245,15 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc
|
||||
alias_ty.to_ty(tcx),
|
||||
);
|
||||
debug!("Resolved {:?} -> {resolved}", alias_ty.to_ty(tcx));
|
||||
ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
|
||||
def_id: assoc_ty.def_id,
|
||||
args: ty::ExistentialTraitRef::erase_self_ty(tcx, super_trait_ref).args,
|
||||
term: resolved.into(),
|
||||
})
|
||||
ty::ExistentialPredicate::Projection(
|
||||
ty::ExistentialProjection::erase_self_ty(
|
||||
tcx,
|
||||
ty::ProjectionPredicate {
|
||||
projection_term: alias_ty.into(),
|
||||
term: resolved.into(),
|
||||
},
|
||||
),
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -318,10 +322,11 @@ pub fn transform_instance<'tcx>(
|
||||
.lang_items()
|
||||
.drop_trait()
|
||||
.unwrap_or_else(|| bug!("typeid_for_instance: couldn't get drop_trait lang item"));
|
||||
let predicate = ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef {
|
||||
let predicate = ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::new_from_args(
|
||||
tcx,
|
||||
def_id,
|
||||
args: List::empty(),
|
||||
});
|
||||
ty::List::empty(),
|
||||
));
|
||||
let predicates = tcx.mk_poly_existential_predicates(&[ty::Binder::dummy(predicate)]);
|
||||
let self_ty = Ty::new_dynamic(tcx, predicates, tcx.lifetimes.re_erased, ty::Dyn);
|
||||
instance.args = tcx.mk_args_trait(self_ty, List::empty());
|
||||
|
@ -380,11 +380,12 @@ impl RustcInternal for ExistentialProjection {
|
||||
type T<'tcx> = rustc_ty::ExistentialProjection<'tcx>;
|
||||
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
rustc_ty::ExistentialProjection {
|
||||
def_id: self.def_id.0.internal(tables, tcx),
|
||||
args: self.generic_args.internal(tables, tcx),
|
||||
term: self.term.internal(tables, tcx),
|
||||
}
|
||||
rustc_ty::ExistentialProjection::new_from_args(
|
||||
tcx,
|
||||
self.def_id.0.internal(tables, tcx),
|
||||
self.generic_args.internal(tables, tcx),
|
||||
self.term.internal(tables, tcx),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -403,10 +404,11 @@ impl RustcInternal for ExistentialTraitRef {
|
||||
type T<'tcx> = rustc_ty::ExistentialTraitRef<'tcx>;
|
||||
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
rustc_ty::ExistentialTraitRef {
|
||||
def_id: self.def_id.0.internal(tables, tcx),
|
||||
args: self.generic_args.internal(tables, tcx),
|
||||
}
|
||||
rustc_ty::ExistentialTraitRef::new_from_args(
|
||||
tcx,
|
||||
self.def_id.0.internal(tables, tcx),
|
||||
self.generic_args.internal(tables, tcx),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ impl<'tcx> Stable<'tcx> for ty::ExistentialTraitRef<'tcx> {
|
||||
type T = stable_mir::ty::ExistentialTraitRef;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
let ty::ExistentialTraitRef { def_id, args } = self;
|
||||
let ty::ExistentialTraitRef { def_id, args, .. } = self;
|
||||
stable_mir::ty::ExistentialTraitRef {
|
||||
def_id: tables.trait_def(*def_id),
|
||||
generic_args: args.stable(tables),
|
||||
@ -95,7 +95,7 @@ impl<'tcx> Stable<'tcx> for ty::ExistentialProjection<'tcx> {
|
||||
type T = stable_mir::ty::ExistentialProjection;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
let ty::ExistentialProjection { def_id, args, term } = self;
|
||||
let ty::ExistentialProjection { def_id, args, term, .. } = self;
|
||||
stable_mir::ty::ExistentialProjection {
|
||||
def_id: tables.trait_def(*def_id),
|
||||
generic_args: args.stable(tables),
|
||||
|
@ -15,9 +15,7 @@
|
||||
CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult, SolverMode,
|
||||
};
|
||||
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
|
||||
use crate::{
|
||||
search_graph, {self as ty},
|
||||
};
|
||||
use crate::{self as ty, search_graph};
|
||||
|
||||
pub trait Interner:
|
||||
Sized
|
||||
@ -173,6 +171,10 @@ fn mk_args_from_iter<I, T>(self, args: I) -> T::Output
|
||||
|
||||
fn debug_assert_args_compatible(self, def_id: Self::DefId, args: Self::GenericArgs);
|
||||
|
||||
/// Assert that the args from an `ExistentialTraitRef` or `ExistentialProjection`
|
||||
/// are compatible with the `DefId`.
|
||||
fn debug_assert_existential_args_compatible(self, def_id: Self::DefId, args: Self::GenericArgs);
|
||||
|
||||
fn mk_type_list_from_iter<I, T>(self, args: I) -> T::Output
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
|
@ -289,9 +289,26 @@ pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> I::Clause {
|
||||
pub struct ExistentialTraitRef<I: Interner> {
|
||||
pub def_id: I::DefId,
|
||||
pub args: I::GenericArgs,
|
||||
/// This field exists to prevent the creation of `ExistentialTraitRef` without
|
||||
/// calling [`ExistentialTraitRef::new_from_args`].
|
||||
_use_existential_trait_ref_new_instead: (),
|
||||
}
|
||||
|
||||
impl<I: Interner> ExistentialTraitRef<I> {
|
||||
pub fn new_from_args(interner: I, trait_def_id: I::DefId, args: I::GenericArgs) -> Self {
|
||||
interner.debug_assert_existential_args_compatible(trait_def_id, args);
|
||||
Self { def_id: trait_def_id, args, _use_existential_trait_ref_new_instead: () }
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
interner: I,
|
||||
trait_def_id: I::DefId,
|
||||
args: impl IntoIterator<Item: Into<I::GenericArg>>,
|
||||
) -> Self {
|
||||
let args = interner.mk_args_from_iter(args.into_iter().map(Into::into));
|
||||
Self::new_from_args(interner, trait_def_id, args)
|
||||
}
|
||||
|
||||
pub fn erase_self_ty(interner: I, trait_ref: TraitRef<I>) -> ExistentialTraitRef<I> {
|
||||
// Assert there is a Self.
|
||||
trait_ref.args.type_at(0);
|
||||
@ -299,6 +316,7 @@ pub fn erase_self_ty(interner: I, trait_ref: TraitRef<I>) -> ExistentialTraitRef
|
||||
ExistentialTraitRef {
|
||||
def_id: trait_ref.def_id,
|
||||
args: interner.mk_args(&trait_ref.args.as_slice()[1..]),
|
||||
_use_existential_trait_ref_new_instead: (),
|
||||
}
|
||||
}
|
||||
|
||||
@ -336,9 +354,33 @@ pub struct ExistentialProjection<I: Interner> {
|
||||
pub def_id: I::DefId,
|
||||
pub args: I::GenericArgs,
|
||||
pub term: I::Term,
|
||||
|
||||
/// This field exists to prevent the creation of `ExistentialProjection`
|
||||
/// without using [`ExistentialProjection::new_from_args`].
|
||||
use_existential_projection_new_instead: (),
|
||||
}
|
||||
|
||||
impl<I: Interner> ExistentialProjection<I> {
|
||||
pub fn new_from_args(
|
||||
interner: I,
|
||||
def_id: I::DefId,
|
||||
args: I::GenericArgs,
|
||||
term: I::Term,
|
||||
) -> ExistentialProjection<I> {
|
||||
interner.debug_assert_existential_args_compatible(def_id, args);
|
||||
Self { def_id, args, term, use_existential_projection_new_instead: () }
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
interner: I,
|
||||
def_id: I::DefId,
|
||||
args: impl IntoIterator<Item: Into<I::GenericArg>>,
|
||||
term: I::Term,
|
||||
) -> ExistentialProjection<I> {
|
||||
let args = interner.mk_args_from_iter(args.into_iter().map(Into::into));
|
||||
Self::new_from_args(interner, def_id, args, term)
|
||||
}
|
||||
|
||||
/// Extracts the underlying existential trait reference from this projection.
|
||||
/// For example, if this is a projection of `exists T. <T as Iterator>::Item == X`,
|
||||
/// then this function would return an `exists T. T: Iterator` existential trait
|
||||
@ -347,7 +389,7 @@ pub fn trait_ref(&self, interner: I) -> ExistentialTraitRef<I> {
|
||||
let def_id = interner.parent(self.def_id);
|
||||
let args_count = interner.generics_of(def_id).count() - 1;
|
||||
let args = interner.mk_args(&self.args.as_slice()[..args_count]);
|
||||
ExistentialTraitRef { def_id, args }
|
||||
ExistentialTraitRef { def_id, args, _use_existential_trait_ref_new_instead: () }
|
||||
}
|
||||
|
||||
pub fn with_self_ty(&self, interner: I, self_ty: I::Ty) -> ProjectionPredicate<I> {
|
||||
@ -372,6 +414,7 @@ pub fn erase_self_ty(interner: I, projection_predicate: ProjectionPredicate<I>)
|
||||
def_id: projection_predicate.projection_term.def_id,
|
||||
args: interner.mk_args(&projection_predicate.projection_term.args.as_slice()[1..]),
|
||||
term: projection_predicate.term,
|
||||
use_existential_projection_new_instead: (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -308,7 +308,7 @@ fn relate<R: TypeRelation<I>>(
|
||||
a.args,
|
||||
b.args,
|
||||
)?;
|
||||
Ok(ty::ExistentialProjection { def_id: a.def_id, args, term })
|
||||
Ok(ty::ExistentialProjection::new_from_args(relation.cx(), a.def_id, args, term))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -348,7 +348,7 @@ fn relate<R: TypeRelation<I>>(
|
||||
}))
|
||||
} else {
|
||||
let args = relate_args_invariantly(relation, a.args, b.args)?;
|
||||
Ok(ty::ExistentialTraitRef { def_id: a.def_id, args })
|
||||
Ok(ty::ExistentialTraitRef::new_from_args(relation.cx(), a.def_id, args))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user