Rollup merge of #108879 - compiler-errors:constrained-root-var, r=lcnr

Unconstrained terms should account for infer vars being equated

Follow-up from the canonicalization PR, wanted to break this one out so I can approve the other PR.

r? `@lcnr`
This commit is contained in:
Matthias Krüger 2023-03-10 12:31:58 +01:00 committed by GitHub
commit 4bd32ac31d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -93,37 +93,42 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
};
// Guard against `<T as Trait<?0>>::Assoc = ?0>`.
struct ContainsTerm<'tcx> {
struct ContainsTerm<'a, 'tcx> {
term: ty::Term<'tcx>,
infcx: &'a InferCtxt<'tcx>,
}
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTerm<'tcx> {
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTerm<'_, 'tcx> {
type BreakTy = ();
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if t.needs_infer() {
if ty::Term::from(t) == self.term {
if let Some(vid) = t.ty_vid()
&& let ty::TermKind::Ty(term) = self.term.unpack()
&& let Some(term_vid) = term.ty_vid()
&& self.infcx.root_var(vid) == self.infcx.root_var(term_vid)
{
ControlFlow::Break(())
} else {
} else if t.has_non_region_infer() {
t.super_visit_with(self)
}
} else {
ControlFlow::Continue(())
}
}
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
if c.needs_infer() {
if ty::Term::from(c) == self.term {
if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = c.kind()
&& let ty::TermKind::Const(term) = self.term.unpack()
&& let ty::ConstKind::Infer(ty::InferConst::Var(term_vid)) = term.kind()
&& self.infcx.root_const_var(vid) == self.infcx.root_const_var(term_vid)
{
ControlFlow::Break(())
} else {
} else if c.has_non_region_infer() {
c.super_visit_with(self)
}
} else {
ControlFlow::Continue(())
}
}
}
let mut visitor = ContainsTerm { term: goal.predicate.term };
let mut visitor = ContainsTerm { infcx: self.infcx, term: goal.predicate.term };
term_is_infer
&& goal.predicate.projection_ty.visit_with(&mut visitor).is_continue()