Skip to content

Commit c137984

Browse files
committed
no behavior changes
1 parent 64bab84 commit c137984

File tree

2 files changed

+73
-27
lines changed

2 files changed

+73
-27
lines changed

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

Lines changed: 70 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
55
use rustc_hir::def_id::DefId;
66
use rustc_middle::bug;
77
use rustc_middle::ty::error::TypeError;
8+
use rustc_middle::ty::relate::{relate_args_invariantly, relate_args_with_variances};
89
use rustc_middle::ty::{
910
self, AliasRelationDirection, InferConst, Term, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
1011
TypeVisitableExt, TypeVisitor, TypingMode,
@@ -70,13 +71,14 @@ impl<'tcx> InferCtxt<'tcx> {
7071
//
7172
// We then relate `generalized_ty <: source_ty`, adding constraints like `'x: '?2` and
7273
// `?1 <: ?3`.
73-
let Generalization { value_may_be_infer: generalized_ty } = self.generalize(
74-
relation.span(),
75-
relation.structurally_relate_aliases(),
76-
target_vid,
77-
instantiation_variance,
78-
source_ty,
79-
)?;
74+
let Generalization { value_may_be_infer: generalized_ty, has_unconstrained_ty_var } = self
75+
.generalize(
76+
relation.span(),
77+
relation.structurally_relate_aliases(),
78+
target_vid,
79+
instantiation_variance,
80+
source_ty,
81+
)?;
8082

8183
// Constrain `b_vid` to the generalized type `generalized_ty`.
8284
if let &ty::Infer(ty::TyVar(generalized_vid)) = generalized_ty.kind() {
@@ -85,6 +87,11 @@ impl<'tcx> InferCtxt<'tcx> {
8587
self.inner.borrow_mut().type_variables().instantiate(target_vid, generalized_ty);
8688
}
8789

90+
// See the comment on `Generalization::has_unconstrained_ty_var`.
91+
if has_unconstrained_ty_var {
92+
relation.register_predicates([ty::ClauseKind::WellFormed(generalized_ty.into())]);
93+
}
94+
8895
// Finally, relate `generalized_ty` to `source_ty`, as described in previous comment.
8996
//
9097
// FIXME(#16847): This code is non-ideal because all these subtype
@@ -204,15 +211,19 @@ impl<'tcx> InferCtxt<'tcx> {
204211
) -> RelateResult<'tcx, ()> {
205212
// FIXME(generic_const_exprs): Occurs check failures for unevaluated
206213
// constants and generic expressions are not yet handled correctly.
207-
let Generalization { value_may_be_infer: generalized_ct } = self.generalize(
208-
relation.span(),
209-
relation.structurally_relate_aliases(),
210-
target_vid,
211-
ty::Invariant,
212-
source_ct,
213-
)?;
214+
let Generalization { value_may_be_infer: generalized_ct, has_unconstrained_ty_var } = self
215+
.generalize(
216+
relation.span(),
217+
relation.structurally_relate_aliases(),
218+
target_vid,
219+
ty::Invariant,
220+
source_ct,
221+
)?;
214222

215223
debug_assert!(!generalized_ct.is_ct_infer());
224+
if has_unconstrained_ty_var {
225+
bug!("unconstrained ty var when generalizing `{source_ct:?}`");
226+
}
216227

217228
self.inner
218229
.borrow_mut()
@@ -271,10 +282,12 @@ impl<'tcx> InferCtxt<'tcx> {
271282
ambient_variance,
272283
in_alias: false,
273284
cache: Default::default(),
285+
has_unconstrained_ty_var: false,
274286
};
275287

276288
let value_may_be_infer = generalizer.relate(source_term, source_term)?;
277-
Ok(Generalization { value_may_be_infer })
289+
let has_unconstrained_ty_var = generalizer.has_unconstrained_ty_var;
290+
Ok(Generalization { value_may_be_infer, has_unconstrained_ty_var })
278291
}
279292
}
280293

@@ -364,6 +377,9 @@ struct Generalizer<'me, 'tcx> {
364377
in_alias: bool,
365378

366379
cache: SsoHashMap<(Ty<'tcx>, ty::Variance, bool), Ty<'tcx>>,
380+
381+
/// See the field `has_unconstrained_ty_var` in `Generalization`.
382+
has_unconstrained_ty_var: bool,
367383
}
368384

369385
impl<'tcx> Generalizer<'_, 'tcx> {
@@ -376,8 +392,10 @@ impl<'tcx> Generalizer<'_, 'tcx> {
376392
}
377393

378394
/// Create a new type variable in the universe of the target when
379-
/// generalizing an alias.
395+
/// generalizing an alias. This has to set `has_unconstrained_ty_var`
396+
/// if we're currently in a bivariant context.
380397
fn next_ty_var_for_alias(&mut self) -> Ty<'tcx> {
398+
self.has_unconstrained_ty_var |= self.ambient_variance == ty::Bivariant;
381399
self.infcx.next_ty_var_in_universe(self.span, self.for_universe)
382400
}
383401

@@ -457,15 +475,13 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
457475
// Avoid fetching the variance if we are in an invariant
458476
// context; no need, and it can induce dependency cycles
459477
// (e.g., #41849).
460-
relate::relate_args_invariantly(self, a_args, b_args)
478+
relate_args_invariantly(self, a_args, b_args)
461479
} else {
462-
let tcx = self.cx();
463-
let variances = tcx.variances_of(def_id);
464-
relate::relate_args_with_variances(self, variances, a_args, b_args)
480+
let variances = self.cx().variances_of(def_id);
481+
relate_args_with_variances(self, variances, a_args, b_args)
465482
}?;
466483
if args == a_args { Ok(a_ty) } else { Ok(mk(args)) }
467484
}
468-
469485
#[instrument(level = "debug", skip(self, variance, b), ret)]
470486
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
471487
&mut self,
@@ -525,8 +541,14 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
525541
}
526542
}
527543

528-
// We do need a fresh type variable otherwise.
529-
ty::Bivariant | ty::Covariant | ty::Contravariant => (),
544+
// Bivariant: make a fresh var, but remember that
545+
// it is unconstrained. See the comment in
546+
// `Generalization`.
547+
ty::Bivariant => self.has_unconstrained_ty_var = true,
548+
549+
// Co/contravariant: this will be
550+
// sufficiently constrained later on.
551+
ty::Covariant | ty::Contravariant => (),
530552
}
531553

532554
let origin = inner.type_variables().var_origin(vid);
@@ -745,8 +767,32 @@ struct Generalization<T> {
745767
/// for `?0` generalization returns an inference
746768
/// variable.
747769
///
748-
/// This has to be handled with care as it can
770+
/// This has to be handled wotj care as it can
749771
/// otherwise very easily result in infinite
750772
/// recursion.
751773
pub value_may_be_infer: T,
774+
775+
/// In general, we do not check whether all types which occur during
776+
/// type checking are well-formed. We only check wf of user-provided types
777+
/// and when actually using a type, e.g. for method calls.
778+
///
779+
/// This means that when subtyping, we may end up with unconstrained
780+
/// inference variables if a generalized type has bivariant parameters.
781+
/// A parameter may only be bivariant if it is constrained by a projection
782+
/// bound in a where-clause. As an example, imagine a type:
783+
///
784+
/// struct Foo<A, B> where A: Iterator<Item = B> {
785+
/// data: A
786+
/// }
787+
///
788+
/// here, `A` will be covariant, but `B` is unconstrained.
789+
///
790+
/// However, whatever it is, for `Foo` to be WF, it must be equal to `A::Item`.
791+
/// If we have an input `Foo<?A, ?B>`, then after generalization we will wind
792+
/// up with a type like `Foo<?C, ?D>`. When we enforce `Foo<?A, ?B> <: Foo<?C, ?D>`,
793+
/// we will wind up with the requirement that `?A <: ?C`, but no particular
794+
/// relationship between `?B` and `?D` (after all, these types may be completely
795+
/// different). If we do nothing else, this may mean that `?D` goes unconstrained
796+
/// (as in #41677). To avoid this we emit a `WellFormed` obligation in these cases.
797+
pub has_unconstrained_ty_var: bool,
752798
}

compiler/rustc_type_ir/src/relate/combine.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ where
226226
pub fn combine_ty_args<Infcx, I, R>(
227227
relation: &mut R,
228228
a_ty: I::Ty,
229-
b_ty: I::Ty,
229+
_: I::Ty,
230230
variances: I::VariancesOf,
231231
a_args: I::GenericArgs,
232232
b_args: I::GenericArgs,
@@ -278,12 +278,12 @@ where
278278
// different). If we do nothing else, this may mean that `?D` goes unconstrained
279279
// (as in #41677). To avoid this we emit a `WellFormed` when relating types with
280280
// bivariant arguments.
281-
if has_bivariant_arg {
281+
/*if has_bivariant_arg {
282282
relation.register_predicates([
283283
ty::ClauseKind::WellFormed(a_ty.into()),
284284
ty::ClauseKind::WellFormed(b_ty.into()),
285285
]);
286-
}
286+
}*/
287287

288288
if a_args == args { Ok(a_ty) } else { Ok(mk(args)) }
289289
}

0 commit comments

Comments
 (0)