Skip to content

Commit

Permalink
Rollup merge of #131049 - compiler-errors:more-validation, r=spastorino
Browse files Browse the repository at this point in the history
Validate args are correct for `UnevaluatedConst`, `ExistentialTraitRef`/`ExistentialProjection`

For the `Existential*` ones, we have to do some adjustment to the args list to deal with the missing `Self` type, so we introduce a `debug_assert_existential_args_compatible` function to the interner as well.
  • Loading branch information
matthiaskrgr authored Oct 22, 2024
2 parents 4d378f2 + 2239f1c commit 3f15d29
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
})
.collect();
let args = tcx.mk_args(&args);

let span = i.bottom().1;
let empty_generic_args = hir_trait_bounds.iter().any(|hir_bound| {
Expand Down Expand Up @@ -292,7 +291,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
.emit();
}

ty::ExistentialTraitRef { def_id: trait_ref.def_id, args }
ty::ExistentialTraitRef::new(tcx, trait_ref.def_id, args)
})
});

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/ty/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ impl<'tcx> Const<'tcx> {

#[inline]
pub fn new_unevaluated(tcx: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>) -> Const<'tcx> {
tcx.debug_assert_args_compatible(uv.def, uv.args);
Const::new(tcx, ty::ConstKind::Unevaluated(uv))
}

Expand Down
20 changes: 20 additions & 0 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,26 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
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>,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_passes/src/reachable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ impl<'tcx> ReachableContext<'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);
}
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_privacy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility,
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;
Expand Down Expand Up @@ -246,10 +246,10 @@ where
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));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
},
),
)
})
})
})
Expand Down Expand Up @@ -318,10 +322,11 @@ pub(crate) 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());
Expand Down
20 changes: 11 additions & 9 deletions compiler/rustc_smir/src/rustc_internal/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
)
}
}

Expand All @@ -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),
)
}
}

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_smir/src/rustc_smir/convert/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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),
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_type_ir/src/interner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ use crate::solve::{
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
Expand Down Expand Up @@ -173,6 +171,10 @@ pub trait Interner:

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>,
Expand Down
45 changes: 44 additions & 1 deletion compiler/rustc_type_ir/src/predicate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,16 +289,34 @@ impl<I: Interner> ty::Binder<I, ExistentialPredicate<I>> {
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);

ExistentialTraitRef {
def_id: trait_ref.def_id,
args: interner.mk_args(&trait_ref.args.as_slice()[1..]),
_use_existential_trait_ref_new_instead: (),
}
}

Expand Down Expand Up @@ -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
Expand All @@ -347,7 +389,7 @@ impl<I: Interner> ExistentialProjection<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> {
Expand All @@ -372,6 +414,7 @@ impl<I: Interner> ExistentialProjection<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: (),
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_type_ir/src/relate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ impl<I: Interner> Relate<I> for ty::ExistentialProjection<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))
}
}
}
Expand Down Expand Up @@ -373,7 +373,7 @@ impl<I: Interner> Relate<I> for ty::ExistentialTraitRef<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))
}
}
}
Expand Down

0 comments on commit 3f15d29

Please sign in to comment.