consider placeholders in fn term_is_fully_unconstrained
This commit is contained in:
parent
1c264ca9ca
commit
3b3514acec
@ -608,8 +608,8 @@ pub(super) fn next_term_infer_of_kind(&self, kind: ty::Term<'tcx>) -> ty::Term<'
|
||||
|
||||
/// Is the projection predicate is of the form `exists<T> <Ty as Trait>::Assoc = T`.
|
||||
///
|
||||
/// This is the case if the `term` is an inference variable in the innermost universe
|
||||
/// and does not occur in any other part of the predicate.
|
||||
/// This is the case if the `term` does not occur in any other part of the predicate
|
||||
/// and is able to name all other placeholder and inference variables.
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
pub(super) fn term_is_fully_unconstrained(
|
||||
&self,
|
||||
@ -632,55 +632,67 @@ pub(super) fn term_is_fully_unconstrained(
|
||||
}
|
||||
};
|
||||
|
||||
// Guard against `<T as Trait<?0>>::Assoc = ?0>`.
|
||||
struct ContainsTermOrNotNameable<'a, 'tcx> {
|
||||
term: ty::Term<'tcx>,
|
||||
universe_of_term: ty::UniverseIndex,
|
||||
infcx: &'a InferCtxt<'tcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> ContainsTermOrNotNameable<'a, 'tcx> {
|
||||
fn check_nameable(&self, universe: ty::UniverseIndex) -> ControlFlow<()> {
|
||||
if self.universe_of_term.can_name(universe) {
|
||||
ControlFlow::Continue(())
|
||||
} else {
|
||||
ControlFlow::Break(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTermOrNotNameable<'_, 'tcx> {
|
||||
type BreakTy = ();
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if let Some(vid) = t.ty_vid() {
|
||||
if 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 if self
|
||||
.universe_of_term
|
||||
.cannot_name(self.infcx.universe_of_ty(vid).unwrap())
|
||||
{
|
||||
ControlFlow::Break(())
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
match *t.kind() {
|
||||
ty::Infer(ty::TyVar(vid)) => {
|
||||
if 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 {
|
||||
self.check_nameable(self.infcx.universe_of_ty(vid).unwrap())
|
||||
}
|
||||
}
|
||||
ty::Placeholder(p) => self.check_nameable(p.universe),
|
||||
_ => {
|
||||
if t.has_non_region_infer() || t.has_placeholders() {
|
||||
t.super_visit_with(self)
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
} 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 let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = c.kind() {
|
||||
if 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 if self
|
||||
.universe_of_term
|
||||
.cannot_name(self.infcx.universe_of_ct(vid).unwrap())
|
||||
{
|
||||
ControlFlow::Break(())
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
match c.kind() {
|
||||
ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
|
||||
if 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 {
|
||||
self.check_nameable(self.infcx.universe_of_ct(vid).unwrap())
|
||||
}
|
||||
}
|
||||
ty::ConstKind::Placeholder(p) => self.check_nameable(p.universe),
|
||||
_ => {
|
||||
if c.has_non_region_infer() || c.has_placeholders() {
|
||||
c.super_visit_with(self)
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
} else if c.has_non_region_infer() {
|
||||
c.super_visit_with(self)
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user