cleanup and comments
This commit is contained in:
parent
f69d67221e
commit
407c117e88
10 changed files with 224 additions and 26 deletions
|
@ -326,7 +326,9 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
) -> RelateResult<'tcx, ty::Const<'tcx>> {
|
||||
let span =
|
||||
self.inner.borrow_mut().const_unification_table().probe_value(target_vid).origin.span;
|
||||
let Generalization { value, needs_wf: _ } = generalize::generalize(
|
||||
// FIXME(generic_const_exprs): Occurs check failures for unevaluated
|
||||
// constants and generic expressions are not yet handled correctly.
|
||||
let Generalization { value_may_be_infer: value, needs_wf: _ } = generalize::generalize(
|
||||
self,
|
||||
&mut CombineDelegate { infcx: self, span, param_env },
|
||||
ct,
|
||||
|
@ -334,10 +336,6 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
ty::Variance::Invariant,
|
||||
)?;
|
||||
|
||||
// FIXME(generic_const_exprs): Occurs check failures for unevaluated
|
||||
// constants and generic expressions are not yet handled correctly.
|
||||
let value = value.may_be_infer();
|
||||
|
||||
self.inner.borrow_mut().const_unification_table().union_value(
|
||||
target_vid,
|
||||
ConstVarValue {
|
||||
|
@ -449,7 +447,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
|||
// `'?2` and `?3` are fresh region/type inference
|
||||
// variables. (Down below, we will relate `a_ty <: b_ty`,
|
||||
// adding constraints like `'x: '?2` and `?1 <: ?3`.)
|
||||
let Generalization { value, needs_wf } = generalize::generalize(
|
||||
let Generalization { value_may_be_infer: b_ty, needs_wf } = generalize::generalize(
|
||||
self.infcx,
|
||||
&mut CombineDelegate {
|
||||
infcx: self.infcx,
|
||||
|
@ -461,7 +459,6 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
|||
ambient_variance,
|
||||
)?;
|
||||
|
||||
let b_ty = value.may_be_infer(); // we handle this further down.
|
||||
self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty);
|
||||
|
||||
if needs_wf {
|
||||
|
@ -501,6 +498,11 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: This does not handle subtyping correctly, we should switch to
|
||||
// alias-relate in the new solver and could instead create a new inference
|
||||
// variable for `a_ty`, emitting `Projection(a_ty, a_infer)` and
|
||||
// `a_infer <: b_ty`.
|
||||
self.obligations.push(Obligation::new(
|
||||
self.tcx(),
|
||||
self.trace.cause.clone(),
|
||||
|
|
|
@ -47,9 +47,9 @@ pub(super) fn generalize<'tcx, D: GeneralizerDelegate<'tcx>, T: Into<Term<'tcx>>
|
|||
};
|
||||
|
||||
assert!(!term.has_escaping_bound_vars());
|
||||
let value = generalizer.relate(term, term)?;
|
||||
let value_may_be_infer = generalizer.relate(term, term)?;
|
||||
let needs_wf = generalizer.needs_wf;
|
||||
Ok(Generalization { value: HandleProjection(value), needs_wf })
|
||||
Ok(Generalization { value_may_be_infer, needs_wf })
|
||||
}
|
||||
|
||||
/// Abstracts the handling of region vars between HIR and MIR/NLL typechecking
|
||||
|
@ -153,10 +153,11 @@ struct Generalizer<'me, 'tcx, D> {
|
|||
|
||||
cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
|
||||
|
||||
/// This is set once we're generalizing the arguments of an alias. In case
|
||||
/// we encounter an occurs check failure we generalize the alias to an
|
||||
/// inference variable instead of erroring. This is necessary to avoid
|
||||
/// incorrect errors when relating `?0` with `<?0 as Trait>::Assoc`.
|
||||
/// This is set once we're generalizing the arguments of an alias.
|
||||
///
|
||||
/// This is necessary to correctly handle
|
||||
/// `<T as Bar<<?0 as Foo>::Assoc>::Assoc == ?0`. This equality can
|
||||
/// hold by either normalizing the outer or the inner associated type.
|
||||
in_alias: bool,
|
||||
|
||||
/// See the field `needs_wf` in `Generalization`.
|
||||
|
@ -330,6 +331,12 @@ where
|
|||
}
|
||||
|
||||
ty::Alias(kind, data) => {
|
||||
// An occurs check failure inside of an alias does not mean
|
||||
// that the types definitely don't unify. We may be able
|
||||
// to normalize the alias after all.
|
||||
//
|
||||
// We handle this by lazily equating the alias and generalizing
|
||||
// it to an inference variable.
|
||||
let is_nested_alias = mem::replace(&mut self.in_alias, true);
|
||||
let result = match self.relate(data, data) {
|
||||
Ok(data) => Ok(Ty::new_alias(self.tcx(), kind, data)),
|
||||
|
@ -343,7 +350,7 @@ where
|
|||
self.for_universe.can_name(visitor.max_universe())
|
||||
&& !t.has_escaping_bound_vars();
|
||||
if !infer_replacement_is_complete {
|
||||
warn!("incomplete generalization of an alias type: {t:?}");
|
||||
warn!("may incompletely handle alias type: {t:?}");
|
||||
}
|
||||
|
||||
debug!("generalization failure in alias");
|
||||
|
@ -504,20 +511,20 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct HandleProjection<T>(T);
|
||||
impl<T> HandleProjection<T> {
|
||||
pub(super) fn may_be_infer(self) -> T {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Result from a generalization operation. This includes
|
||||
/// not only the generalized type, but also a bool flag
|
||||
/// indicating whether further WF checks are needed.
|
||||
#[derive(Debug)]
|
||||
pub(super) struct Generalization<T> {
|
||||
pub(super) value: HandleProjection<T>,
|
||||
/// When generalizing `<?0 as Trait>::Assoc` or
|
||||
/// `<T as Bar<<?0 as Foo>::Assoc>>::Assoc`
|
||||
/// for `?0` generalization returns an inference
|
||||
/// variable.
|
||||
///
|
||||
/// This has to be handled wotj care as it can
|
||||
/// otherwise very easily result in infinite
|
||||
/// recursion.
|
||||
pub(super) value_may_be_infer: T,
|
||||
|
||||
/// If true, then the generalized type may not be well-formed,
|
||||
/// even if the source type is well-formed, so we should add an
|
||||
|
|
|
@ -214,7 +214,7 @@ where
|
|||
}
|
||||
|
||||
fn generalize(&mut self, ty: Ty<'tcx>, for_vid: ty::TyVid) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
let Generalization { value, needs_wf: _ } = generalize::generalize(
|
||||
let Generalization { value_may_be_infer: ty, needs_wf: _ } = generalize::generalize(
|
||||
self.infcx,
|
||||
&mut self.delegate,
|
||||
ty,
|
||||
|
@ -222,9 +222,8 @@ where
|
|||
self.ambient_variance,
|
||||
)?;
|
||||
|
||||
let ty = value.may_be_infer();
|
||||
if ty.is_ty_var() {
|
||||
warn!("occurs check failure in MIR typeck");
|
||||
span_bug!(self.delegate.span(), "occurs check failure in MIR typeck");
|
||||
}
|
||||
Ok(ty)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue