Prevent the creation of TraitRef without dedicated methods

This commit is contained in:
Oli Scherer 2022-12-13 11:18:58 +00:00
parent a5cd3bde95
commit 6af3638709
9 changed files with 44 additions and 47 deletions

View file

@ -570,7 +570,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
assoc_item,
assoc_item,
default.span,
ty::TraitRef { def_id: it.owner_id.to_def_id(), substs: trait_substs },
tcx.mk_trait_ref(it.owner_id.to_def_id(), trait_substs),
);
}
_ => {}

View file

@ -160,7 +160,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
// instead of requiring an additional `+ 'a`.
match pred.kind().skip_binder() {
ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
trait_ref: ty::TraitRef { def_id: _, substs },
trait_ref: ty::TraitRef { def_id: _, substs, .. },
constness: _,
polarity: _,
})) => {

View file

@ -13,7 +13,7 @@ use rustc_hir_analysis::astconv::AstConv;
use rustc_infer::infer;
use rustc_infer::traits::{self, StatementAsExpression};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::{self, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty};
use rustc_middle::ty::{self, Binder, DefIdTree, IsSuggestable, Ty};
use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::symbol::sym;
use rustc_span::Span;
@ -1277,17 +1277,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Check that we're in fact trying to clone into the expected type
&& self.can_coerce(*pointee_ty, expected_ty)
// And the expected type doesn't implement `Clone`
&& !self.predicate_must_hold_considering_regions(&traits::Obligation {
cause: traits::ObligationCause::dummy(),
param_env: self.param_env,
recursion_depth: 0,
predicate: ty::Binder::dummy(ty::TraitRef {
def_id: clone_trait_did,
substs: self.tcx.mk_substs([expected_ty.into()].iter()),
})
.without_const()
.to_predicate(self.tcx),
})
&& !self.predicate_must_hold_considering_regions(&traits::Obligation::new(
self.tcx,
traits::ObligationCause::dummy(),
self.param_env,
ty::Binder::dummy(self.tcx.mk_trait_ref(
clone_trait_did,
[expected_ty],
)),
))
{
diag.span_note(
callee_expr.span,

View file

@ -226,13 +226,11 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
false
};
let expected_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef {
def_id: trait_def_id,
substs: expected_substs,
});
let actual_trait_ref = self
let expected_trait_ref = self
.cx
.resolve_vars_if_possible(ty::TraitRef { def_id: trait_def_id, substs: actual_substs });
.resolve_vars_if_possible(self.cx.tcx.mk_trait_ref(trait_def_id, expected_substs));
let actual_trait_ref =
self.cx.resolve_vars_if_possible(self.cx.tcx.mk_trait_ref(trait_def_id, actual_substs));
// Search the expected and actual trait references to see (a)
// whether the sub/sup placeholders appear in them (sometimes

View file

@ -322,7 +322,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> {
Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id)))
} else {
let substs = relate_substs(relation, a.substs, b.substs)?;
Ok(ty::TraitRef { def_id: a.def_id, substs })
Ok(relation.tcx().mk_trait_ref(a.def_id, substs))
}
}
}

View file

@ -816,11 +816,14 @@ impl<'tcx> List<ty::PolyExistentialPredicate<'tcx>> {
pub struct TraitRef<'tcx> {
pub def_id: DefId,
pub substs: SubstsRef<'tcx>,
/// This field exists to prevent the creation of `TraitRef` without
/// calling [TyCtxt::mk_trait_ref].
_use_mk_trait_ref_instead: (),
}
impl<'tcx> TraitRef<'tcx> {
pub fn new(def_id: DefId, substs: SubstsRef<'tcx>) -> TraitRef<'tcx> {
TraitRef { def_id, substs }
TraitRef { def_id, substs, _use_mk_trait_ref_instead: () }
}
pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
@ -836,6 +839,7 @@ impl<'tcx> TraitRef<'tcx> {
ty::Binder::dummy(TraitRef {
def_id,
substs: InternalSubsts::identity_for_item(tcx, def_id),
_use_mk_trait_ref_instead: (),
})
}
@ -850,7 +854,11 @@ impl<'tcx> TraitRef<'tcx> {
substs: SubstsRef<'tcx>,
) -> ty::TraitRef<'tcx> {
let defs = tcx.generics_of(trait_id);
ty::TraitRef { def_id: trait_id, substs: tcx.intern_substs(&substs[..defs.params.len()]) }
ty::TraitRef {
def_id: trait_id,
substs: tcx.intern_substs(&substs[..defs.params.len()]),
_use_mk_trait_ref_instead: (),
}
}
}
@ -1194,10 +1202,7 @@ impl<'tcx> AliasTy<'tcx> {
let trait_def_id = self.trait_def_id(tcx);
let trait_generics = tcx.generics_of(trait_def_id);
(
ty::TraitRef {
def_id: trait_def_id,
substs: self.substs.truncate_to(tcx, trait_generics),
},
tcx.mk_trait_ref(trait_def_id, self.substs.truncate_to(tcx, trait_generics)),
&self.substs[trait_generics.count()..],
)
}
@ -1211,7 +1216,7 @@ impl<'tcx> AliasTy<'tcx> {
/// as well.
pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
let def_id = self.trait_def_id(tcx);
ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, tcx.generics_of(def_id)) }
tcx.mk_trait_ref(def_id, self.substs.truncate_to(tcx, tcx.generics_of(def_id)))
}
pub fn self_ty(&self) -> Ty<'tcx> {

View file

@ -110,26 +110,25 @@ where
V: DefIdVisitor<'tcx> + ?Sized,
{
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<V::BreakTy> {
let TraitRef { def_id, substs } = trait_ref;
let TraitRef { def_id, substs, .. } = trait_ref;
self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path())?;
if self.def_id_visitor.shallow() { ControlFlow::CONTINUE } else { substs.visit_with(self) }
}
fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow<V::BreakTy> {
let tcx = self.def_id_visitor.tcx();
let (trait_ref, assoc_substs) = if tcx.def_kind(projection.def_id)
!= DefKind::ImplTraitPlaceholder
{
projection.trait_ref_and_own_substs(tcx)
} else {
// HACK(RPITIT): Remove this when RPITITs are lowered to regular assoc tys
let def_id = tcx.impl_trait_in_trait_parent(projection.def_id);
let trait_generics = tcx.generics_of(def_id);
(
ty::TraitRef { def_id, substs: projection.substs.truncate_to(tcx, trait_generics) },
&projection.substs[trait_generics.count()..],
)
};
let (trait_ref, assoc_substs) =
if tcx.def_kind(projection.def_id) != DefKind::ImplTraitPlaceholder {
projection.trait_ref_and_own_substs(tcx)
} else {
// HACK(RPITIT): Remove this when RPITITs are lowered to regular assoc tys
let def_id = tcx.impl_trait_in_trait_parent(projection.def_id);
let trait_generics = tcx.generics_of(def_id);
(
tcx.mk_trait_ref(def_id, projection.substs.truncate_to(tcx, trait_generics)),
&projection.substs[trait_generics.count()..],
)
};
self.visit_trait(trait_ref)?;
if self.def_id_visitor.shallow() {
ControlFlow::CONTINUE

View file

@ -703,9 +703,7 @@ fn receiver_is_dispatchable<'tcx>(
}
});
ty::Binder::dummy(ty::TraitRef { def_id: unsize_did, substs })
.without_const()
.to_predicate(tcx)
ty::Binder::dummy(tcx.mk_trait_ref(unsize_did, substs)).to_predicate(tcx)
};
let caller_bounds: Vec<Predicate<'tcx>> =

View file

@ -1309,8 +1309,7 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
let trait_substs =
obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id));
// FIXME(named-returns): Binders
let trait_predicate =
ty::Binder::dummy(ty::TraitRef { def_id: trait_def_id, substs: trait_substs });
let trait_predicate = ty::Binder::dummy(tcx.mk_trait_ref(trait_def_id, trait_substs));
let _ = selcx.infcx.commit_if_ok(|_| {
match selcx.select(&obligation.with(tcx, trait_predicate)) {