Skip to content

Commit 42e7338

Browse files
committed
rename needs_wf and clarify comment
1 parent 93a65c6 commit 42e7338

File tree

3 files changed

+56
-54
lines changed

3 files changed

+56
-54
lines changed

compiler/rustc_infer/src/infer/relate/combine.rs

+21-16
Original file line numberDiff line numberDiff line change
@@ -307,14 +307,18 @@ impl<'tcx> InferCtxt<'tcx> {
307307
};
308308
// FIXME(generic_const_exprs): Occurs check failures for unevaluated
309309
// constants and generic expressions are not yet handled correctly.
310-
let Generalization { value_may_be_infer: value, needs_wf: _ } = generalize::generalize(
311-
self,
312-
&mut CombineDelegate { infcx: self, span },
313-
ct,
314-
target_vid,
315-
ty::Variance::Invariant,
316-
)?;
317-
310+
let Generalization { value_may_be_infer: value, has_unconstrained_ty_var } =
311+
generalize::generalize(
312+
self,
313+
&mut CombineDelegate { infcx: self, span },
314+
ct,
315+
target_vid,
316+
ty::Variance::Invariant,
317+
)?;
318+
319+
if has_unconstrained_ty_var {
320+
span_bug!(span, "unconstrained ty var when generalizing `{ct:?}`");
321+
}
318322
self.inner
319323
.borrow_mut()
320324
.const_unification_table()
@@ -414,13 +418,14 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
414418
// `'?2` and `?3` are fresh region/type inference
415419
// variables. (Down below, we will relate `a_ty <: b_ty`,
416420
// adding constraints like `'x: '?2` and `?1 <: ?3`.)
417-
let Generalization { value_may_be_infer: b_ty, needs_wf } = generalize::generalize(
418-
self.infcx,
419-
&mut CombineDelegate { infcx: self.infcx, span: self.trace.span() },
420-
a_ty,
421-
b_vid,
422-
ambient_variance,
423-
)?;
421+
let Generalization { value_may_be_infer: b_ty, has_unconstrained_ty_var } =
422+
generalize::generalize(
423+
self.infcx,
424+
&mut CombineDelegate { infcx: self.infcx, span: self.trace.span() },
425+
a_ty,
426+
b_vid,
427+
ambient_variance,
428+
)?;
424429

425430
// Constrain `b_vid` to the generalized type `b_ty`.
426431
if let &ty::Infer(TyVar(b_ty_vid)) = b_ty.kind() {
@@ -429,7 +434,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
429434
self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty);
430435
}
431436

432-
if needs_wf {
437+
if has_unconstrained_ty_var {
433438
self.obligations.push(Obligation::new(
434439
self.tcx(),
435440
self.trace.cause.clone(),

compiler/rustc_infer/src/infer/relate/generalize.rs

+27-31
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,14 @@ pub fn generalize<'tcx, D: GeneralizerDelegate<'tcx>, T: Into<Term<'tcx>> + Rela
4343
for_universe,
4444
root_term: term.into(),
4545
in_alias: false,
46-
needs_wf: false,
46+
has_unconstrained_ty_var: false,
4747
cache: Default::default(),
4848
};
4949

5050
assert!(!term.has_escaping_bound_vars());
5151
let value_may_be_infer = generalizer.relate(term, term)?;
52-
let needs_wf = generalizer.needs_wf;
53-
Ok(Generalization { value_may_be_infer, needs_wf })
52+
let has_unconstrained_ty_var = generalizer.has_unconstrained_ty_var;
53+
Ok(Generalization { value_may_be_infer, has_unconstrained_ty_var })
5454
}
5555

5656
/// Abstracts the handling of region vars between HIR and MIR/NLL typechecking
@@ -150,8 +150,8 @@ struct Generalizer<'me, 'tcx, D> {
150150
/// hold by either normalizing the outer or the inner associated type.
151151
in_alias: bool,
152152

153-
/// See the field `needs_wf` in `Generalization`.
154-
needs_wf: bool,
153+
/// See the field `has_unconstrained_ty_var` in `Generalization`.
154+
has_unconstrained_ty_var: bool,
155155
}
156156

157157
impl<'tcx, D> Generalizer<'_, 'tcx, D> {
@@ -272,11 +272,10 @@ where
272272
}
273273
}
274274

275-
// Bivariant: make a fresh var, but we
276-
// may need a WF predicate. See
277-
// comment on `needs_wf` field for
278-
// more info.
279-
ty::Bivariant => self.needs_wf = true,
275+
// Bivariant: make a fresh var, but remember that
276+
// it is unconstrained. See the comment in
277+
// `Generalization`.
278+
ty::Bivariant => self.has_unconstrained_ty_var = true,
280279

281280
// Co/contravariant: this will be
282281
// sufficiently constrained later on.
@@ -511,30 +510,27 @@ pub struct Generalization<T> {
511510
/// recursion.
512511
pub value_may_be_infer: T,
513512

514-
/// If true, then the generalized type may not be well-formed,
515-
/// even if the source type is well-formed, so we should add an
516-
/// additional check to enforce that it is. This arises in
517-
/// particular around 'bivariant' type parameters that are only
518-
/// constrained by a where-clause. As an example, imagine a type:
513+
/// In general, we do not check whether all types which occur during
514+
/// type checking are well-formed. We only check wf of user-provided types
515+
/// and when actually using a type, e.g. for method calls.
516+
///
517+
/// This means that when subtyping, we may end up with unconstrained
518+
/// inference variables if a generalized type has bivariant parameters.
519+
/// A parameter may only be bivariant if it is constrained by a projection
520+
/// bound in a where-clause. As an example, imagine a type:
519521
///
520522
/// struct Foo<A, B> where A: Iterator<Item = B> {
521523
/// data: A
522524
/// }
523525
///
524-
/// here, `A` will be covariant, but `B` is
525-
/// unconstrained. However, whatever it is, for `Foo` to be WF, it
526-
/// must be equal to `A::Item`. If we have an input `Foo<?A, ?B>`,
527-
/// then after generalization we will wind up with a type like
528-
/// `Foo<?C, ?D>`. When we enforce that `Foo<?A, ?B> <: Foo<?C,
529-
/// ?D>` (or `>:`), we will wind up with the requirement that `?A
530-
/// <: ?C`, but no particular relationship between `?B` and `?D`
531-
/// (after all, we do not know the variance of the normalized form
532-
/// of `A::Item` with respect to `A`). If we do nothing else, this
533-
/// may mean that `?D` goes unconstrained (as in #41677). So, in
534-
/// this scenario where we create a new type variable in a
535-
/// bivariant context, we set the `needs_wf` flag to true. This
536-
/// will force the calling code to check that `WF(Foo<?C, ?D>)`
537-
/// holds, which in turn implies that `?C::Item == ?D`. So once
538-
/// `?C` is constrained, that should suffice to restrict `?D`.
539-
pub needs_wf: bool,
526+
/// here, `A` will be covariant, but `B` is unconstrained.
527+
///
528+
/// However, whatever it is, for `Foo` to be WF, it must be equal to `A::Item`.
529+
/// If we have an input `Foo<?A, ?B>`, then after generalization we will wind
530+
/// up with a type like `Foo<?C, ?D>`. When we enforce `Foo<?A, ?B> <: Foo<?C, ?D>`,
531+
/// we will wind up with the requirement that `?A <: ?C`, but no particular
532+
/// relationship between `?B` and `?D` (after all, these types may be completely
533+
/// different). If we do nothing else, this may mean that `?D` goes unconstrained
534+
/// (as in #41677). To avoid this we emit a `WellFormed` obligation in these cases.
535+
pub has_unconstrained_ty_var: bool,
540536
}

compiler/rustc_infer/src/infer/relate/nll.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -214,13 +214,14 @@ where
214214
}
215215

216216
fn generalize(&mut self, ty: Ty<'tcx>, for_vid: ty::TyVid) -> RelateResult<'tcx, Ty<'tcx>> {
217-
let Generalization { value_may_be_infer: ty, needs_wf: _ } = generalize::generalize(
218-
self.infcx,
219-
&mut self.delegate,
220-
ty,
221-
for_vid,
222-
self.ambient_variance,
223-
)?;
217+
let Generalization { value_may_be_infer: ty, has_unconstrained_ty_var: _ } =
218+
generalize::generalize(
219+
self.infcx,
220+
&mut self.delegate,
221+
ty,
222+
for_vid,
223+
self.ambient_variance,
224+
)?;
224225

225226
if ty.is_ty_var() {
226227
span_bug!(self.delegate.span(), "occurs check failure in MIR typeck");

0 commit comments

Comments
 (0)