diff options
| author | lcnr <rust@lcnr.de> | 2024-02-17 00:25:49 +0100 |
|---|---|---|
| committer | lcnr <rust@lcnr.de> | 2024-02-17 00:25:49 +0100 |
| commit | 42e7338eae9f60a7eaf65d45f61f0e5b06c6ef25 (patch) | |
| tree | 70a9e86dc48889c2dcaff27c3d27f9ce608a83c0 | |
| parent | 93a65c69ce60cb7b619eb1853866dff62f446e2b (diff) | |
| download | rust-42e7338eae9f60a7eaf65d45f61f0e5b06c6ef25.tar.gz rust-42e7338eae9f60a7eaf65d45f61f0e5b06c6ef25.zip | |
rename `needs_wf` and clarify comment
| -rw-r--r-- | compiler/rustc_infer/src/infer/relate/combine.rs | 37 | ||||
| -rw-r--r-- | compiler/rustc_infer/src/infer/relate/generalize.rs | 58 | ||||
| -rw-r--r-- | compiler/rustc_infer/src/infer/relate/nll.rs | 15 |
3 files changed, 56 insertions, 54 deletions
diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs index 7edfbf02a68..2e856f6a145 100644 --- a/compiler/rustc_infer/src/infer/relate/combine.rs +++ b/compiler/rustc_infer/src/infer/relate/combine.rs @@ -307,14 +307,18 @@ impl<'tcx> InferCtxt<'tcx> { }; // 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 }, - ct, - target_vid, - ty::Variance::Invariant, - )?; - + let Generalization { value_may_be_infer: value, has_unconstrained_ty_var } = + generalize::generalize( + self, + &mut CombineDelegate { infcx: self, span }, + ct, + target_vid, + ty::Variance::Invariant, + )?; + + if has_unconstrained_ty_var { + span_bug!(span, "unconstrained ty var when generalizing `{ct:?}`"); + } self.inner .borrow_mut() .const_unification_table() @@ -414,13 +418,14 @@ 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_may_be_infer: b_ty, needs_wf } = generalize::generalize( - self.infcx, - &mut CombineDelegate { infcx: self.infcx, span: self.trace.span() }, - a_ty, - b_vid, - ambient_variance, - )?; + let Generalization { value_may_be_infer: b_ty, has_unconstrained_ty_var } = + generalize::generalize( + self.infcx, + &mut CombineDelegate { infcx: self.infcx, span: self.trace.span() }, + a_ty, + b_vid, + ambient_variance, + )?; // Constrain `b_vid` to the generalized type `b_ty`. if let &ty::Infer(TyVar(b_ty_vid)) = b_ty.kind() { @@ -429,7 +434,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty); } - if needs_wf { + if has_unconstrained_ty_var { self.obligations.push(Obligation::new( self.tcx(), self.trace.cause.clone(), diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index bc16d613ccb..52d2661bdaf 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -43,14 +43,14 @@ pub fn generalize<'tcx, D: GeneralizerDelegate<'tcx>, T: Into<Term<'tcx>> + Rela for_universe, root_term: term.into(), in_alias: false, - needs_wf: false, + has_unconstrained_ty_var: false, cache: Default::default(), }; assert!(!term.has_escaping_bound_vars()); let value_may_be_infer = generalizer.relate(term, term)?; - let needs_wf = generalizer.needs_wf; - Ok(Generalization { value_may_be_infer, needs_wf }) + let has_unconstrained_ty_var = generalizer.has_unconstrained_ty_var; + Ok(Generalization { value_may_be_infer, has_unconstrained_ty_var }) } /// Abstracts the handling of region vars between HIR and MIR/NLL typechecking @@ -150,8 +150,8 @@ struct Generalizer<'me, 'tcx, D> { /// hold by either normalizing the outer or the inner associated type. in_alias: bool, - /// See the field `needs_wf` in `Generalization`. - needs_wf: bool, + /// See the field `has_unconstrained_ty_var` in `Generalization`. + has_unconstrained_ty_var: bool, } impl<'tcx, D> Generalizer<'_, 'tcx, D> { @@ -272,11 +272,10 @@ where } } - // Bivariant: make a fresh var, but we - // may need a WF predicate. See - // comment on `needs_wf` field for - // more info. - ty::Bivariant => self.needs_wf = true, + // Bivariant: make a fresh var, but remember that + // it is unconstrained. See the comment in + // `Generalization`. + ty::Bivariant => self.has_unconstrained_ty_var = true, // Co/contravariant: this will be // sufficiently constrained later on. @@ -511,30 +510,27 @@ pub struct Generalization<T> { /// recursion. pub 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 - /// additional check to enforce that it is. This arises in - /// particular around 'bivariant' type parameters that are only - /// constrained by a where-clause. As an example, imagine a type: + /// In general, we do not check whether all types which occur during + /// type checking are well-formed. We only check wf of user-provided types + /// and when actually using a type, e.g. for method calls. + /// + /// This means that when subtyping, we may end up with unconstrained + /// inference variables if a generalized type has bivariant parameters. + /// A parameter may only be bivariant if it is constrained by a projection + /// bound in a where-clause. As an example, imagine a type: /// /// struct Foo<A, B> where A: Iterator<Item = B> { /// data: A /// } /// - /// here, `A` will be covariant, but `B` is - /// unconstrained. However, whatever it is, for `Foo` to be WF, it - /// must be equal to `A::Item`. If we have an input `Foo<?A, ?B>`, - /// then after generalization we will wind up with a type like - /// `Foo<?C, ?D>`. When we enforce that `Foo<?A, ?B> <: Foo<?C, - /// ?D>` (or `>:`), we will wind up with the requirement that `?A - /// <: ?C`, but no particular relationship between `?B` and `?D` - /// (after all, we do not know the variance of the normalized form - /// of `A::Item` with respect to `A`). If we do nothing else, this - /// may mean that `?D` goes unconstrained (as in #41677). So, in - /// this scenario where we create a new type variable in a - /// bivariant context, we set the `needs_wf` flag to true. This - /// will force the calling code to check that `WF(Foo<?C, ?D>)` - /// holds, which in turn implies that `?C::Item == ?D`. So once - /// `?C` is constrained, that should suffice to restrict `?D`. - pub needs_wf: bool, + /// here, `A` will be covariant, but `B` is unconstrained. + /// + /// However, whatever it is, for `Foo` to be WF, it must be equal to `A::Item`. + /// If we have an input `Foo<?A, ?B>`, then after generalization we will wind + /// up with a type like `Foo<?C, ?D>`. When we enforce `Foo<?A, ?B> <: Foo<?C, ?D>`, + /// we will wind up with the requirement that `?A <: ?C`, but no particular + /// relationship between `?B` and `?D` (after all, these types may be completely + /// different). If we do nothing else, this may mean that `?D` goes unconstrained + /// (as in #41677). To avoid this we emit a `WellFormed` obligation in these cases. + pub has_unconstrained_ty_var: bool, } diff --git a/compiler/rustc_infer/src/infer/relate/nll.rs b/compiler/rustc_infer/src/infer/relate/nll.rs index 5e2d2af9b85..fac597c9432 100644 --- a/compiler/rustc_infer/src/infer/relate/nll.rs +++ b/compiler/rustc_infer/src/infer/relate/nll.rs @@ -214,13 +214,14 @@ where } fn generalize(&mut self, ty: Ty<'tcx>, for_vid: ty::TyVid) -> RelateResult<'tcx, Ty<'tcx>> { - let Generalization { value_may_be_infer: ty, needs_wf: _ } = generalize::generalize( - self.infcx, - &mut self.delegate, - ty, - for_vid, - self.ambient_variance, - )?; + let Generalization { value_may_be_infer: ty, has_unconstrained_ty_var: _ } = + generalize::generalize( + self.infcx, + &mut self.delegate, + ty, + for_vid, + self.ambient_variance, + )?; if ty.is_ty_var() { span_bug!(self.delegate.span(), "occurs check failure in MIR typeck"); |
