Skip to content

Commit 51ce4d1

Browse files
authored
Unrolled build for rust-lang#121479
Rollup merge of rust-lang#121479 - lcnr:fix-generalize, r=compiler-errors fix generalizer unsoundness I ended up getting confused while trying to flip the variances when flipping the order. Should be all right now. This is only exploitable when generalizing if the `ambient_variance` of the relation is `Contravariant`. This can currently only be the case in the NLL generalizer which only rarely generalizes, causing us to miss this regression. Very much an issue with rust-lang#121462 however.
2 parents ea2cc43 + dabacb7 commit 51ce4d1

File tree

2 files changed

+33
-23
lines changed

2 files changed

+33
-23
lines changed

Diff for: compiler/rustc_borrowck/src/type_check/relate_tys.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,11 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
123123
// `handle_opaque_type` cannot handle subtyping, so to support subtyping
124124
// we instead eagerly generalize here. This is a bit of a mess but will go
125125
// away once we're using the new solver.
126-
let mut enable_subtyping = |ty, ty_is_expected| {
126+
//
127+
// Given `opaque rel B`, we create a new infer var `ty_vid` constrain it
128+
// by using `ty_vid rel B` and then finally and end by equating `ty_vid` to
129+
// the opaque.
130+
let mut enable_subtyping = |ty, opaque_is_expected| {
127131
let ty_vid = infcx.next_ty_var_id_in_universe(
128132
TypeVariableOrigin {
129133
kind: TypeVariableOriginKind::MiscVariable,
@@ -132,15 +136,15 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
132136
ty::UniverseIndex::ROOT,
133137
);
134138

135-
let variance = if ty_is_expected {
139+
let variance = if opaque_is_expected {
136140
self.ambient_variance
137141
} else {
138142
self.ambient_variance.xform(ty::Contravariant)
139143
};
140144

141145
self.type_checker.infcx.instantiate_ty_var(
142146
self,
143-
ty_is_expected,
147+
opaque_is_expected,
144148
ty_vid,
145149
variance,
146150
ty,
@@ -149,8 +153,8 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
149153
};
150154

151155
let (a, b) = match (a.kind(), b.kind()) {
152-
(&ty::Alias(ty::Opaque, ..), _) => (a, enable_subtyping(b, false)?),
153-
(_, &ty::Alias(ty::Opaque, ..)) => (enable_subtyping(a, true)?, b),
156+
(&ty::Alias(ty::Opaque, ..), _) => (a, enable_subtyping(b, true)?),
157+
(_, &ty::Alias(ty::Opaque, ..)) => (enable_subtyping(a, false)?, b),
154158
_ => unreachable!(
155159
"expected at least one opaque type in `relate_opaques`, got {a} and {b}."
156160
),

Diff for: compiler/rustc_infer/src/infer/relate/generalize.rs

+24-18
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ impl<'tcx> InferCtxt<'tcx> {
2626
/// This is *not* expected to be used anywhere except for an implementation of
2727
/// `TypeRelation`. Do not use this, and instead please use `At::eq`, for all
2828
/// other usecases (i.e. setting the value of a type var).
29-
#[instrument(level = "debug", skip(self, relation, target_is_expected))]
29+
#[instrument(level = "debug", skip(self, relation))]
3030
pub fn instantiate_ty_var<R: ObligationEmittingRelation<'tcx>>(
3131
&self,
3232
relation: &mut R,
3333
target_is_expected: bool,
3434
target_vid: ty::TyVid,
35-
ambient_variance: ty::Variance,
35+
instantiation_variance: ty::Variance,
3636
source_ty: Ty<'tcx>,
3737
) -> RelateResult<'tcx, ()> {
3838
debug_assert!(self.inner.borrow_mut().type_variables().probe(target_vid).is_unknown());
@@ -46,7 +46,7 @@ impl<'tcx> InferCtxt<'tcx> {
4646
//
4747
// We then relate `generalized_ty <: source_ty`,adding constraints like `'x: '?2` and `?1 <: ?3`.
4848
let Generalization { value_may_be_infer: generalized_ty, has_unconstrained_ty_var } =
49-
self.generalize(relation.span(), target_vid, ambient_variance, source_ty)?;
49+
self.generalize(relation.span(), target_vid, instantiation_variance, source_ty)?;
5050

5151
// Constrain `b_vid` to the generalized type `generalized_ty`.
5252
if let &ty::Infer(ty::TyVar(generalized_vid)) = generalized_ty.kind() {
@@ -73,7 +73,7 @@ impl<'tcx> InferCtxt<'tcx> {
7373
// the alias can be normalized to something which does not
7474
// mention `?0`.
7575
if self.next_trait_solver() {
76-
let (lhs, rhs, direction) = match ambient_variance {
76+
let (lhs, rhs, direction) = match instantiation_variance {
7777
ty::Variance::Invariant => {
7878
(generalized_ty.into(), source_ty.into(), AliasRelationDirection::Equate)
7979
}
@@ -106,22 +106,28 @@ impl<'tcx> InferCtxt<'tcx> {
106106
}
107107
}
108108
} else {
109-
// HACK: make sure that we `a_is_expected` continues to be
110-
// correct when relating the generalized type with the source.
109+
// NOTE: The `instantiation_variance` is not the same variance as
110+
// used by the relation. When instantiating `b`, `target_is_expected`
111+
// is flipped and the `instantion_variance` is also flipped. To
112+
// constrain the `generalized_ty` while using the original relation,
113+
// we therefore only have to flip the arguments.
114+
//
115+
// ```ignore (not code)
116+
// ?a rel B
117+
// instantiate_ty_var(?a, B) # expected and variance not flipped
118+
// B' rel B
119+
// ```
120+
// or
121+
// ```ignore (not code)
122+
// A rel ?b
123+
// instantiate_ty_var(?b, A) # expected and variance flipped
124+
// A rel A'
125+
// ```
111126
if target_is_expected == relation.a_is_expected() {
112-
relation.relate_with_variance(
113-
ambient_variance,
114-
ty::VarianceDiagInfo::default(),
115-
generalized_ty,
116-
source_ty,
117-
)?;
127+
relation.relate(generalized_ty, source_ty)?;
118128
} else {
119-
relation.relate_with_variance(
120-
ambient_variance.xform(ty::Contravariant),
121-
ty::VarianceDiagInfo::default(),
122-
source_ty,
123-
generalized_ty,
124-
)?;
129+
debug!("flip relation");
130+
relation.relate(source_ty, generalized_ty)?;
125131
}
126132
}
127133

0 commit comments

Comments
 (0)