Skip to content

Commit b6a080e

Browse files
committed
rework relate_type_and_user_type to use type inference variables
We used to use a kind of "home-grown" variant where we tracked the value of each canonical variable.
1 parent a3409a1 commit b6a080e

File tree

1 file changed

+39
-74
lines changed

1 file changed

+39
-74
lines changed

src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs

Lines changed: 39 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,15 @@
1010

1111
use borrow_check::nll::constraints::OutlivesConstraint;
1212
use borrow_check::nll::type_check::{BorrowCheckContext, Locations};
13-
use rustc::infer::canonical::{Canonical, CanonicalVarInfos, CanonicalVarValues};
1413
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
1514
use rustc::mir::ConstraintCategory;
1615
use rustc::traits::query::Fallible;
1716
use rustc::ty::fold::{TypeFoldable, TypeVisitor};
1817
use rustc::ty::relate::{self, Relate, RelateResult, TypeRelation};
1918
use rustc::ty::subst::Kind;
20-
use rustc::ty::{self, CanonicalTy, CanonicalVar, Ty, TyCtxt};
19+
use rustc::ty::{self, CanonicalTy, Ty, TyCtxt};
2120
use rustc_data_structures::fx::FxHashMap;
22-
use rustc_data_structures::indexed_vec::IndexVec;
21+
use syntax::source_map::DUMMY_SP;
2322

2423
/// Adds sufficient constraints to ensure that `a <: b`.
2524
pub(super) fn sub_types<'tcx>(
@@ -35,7 +34,6 @@ pub(super) fn sub_types<'tcx>(
3534
infcx,
3635
NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category),
3736
ty::Variance::Covariant,
38-
ty::List::empty(),
3937
).relate(&a, &b)?;
4038
Ok(())
4139
}
@@ -54,7 +52,6 @@ pub(super) fn eq_types<'tcx>(
5452
infcx,
5553
NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category),
5654
ty::Variance::Invariant,
57-
ty::List::empty(),
5855
).relate(&a, &b)?;
5956
Ok(())
6057
}
@@ -66,19 +63,20 @@ pub(super) fn relate_type_and_user_type<'tcx>(
6663
infcx: &InferCtxt<'_, '_, 'tcx>,
6764
a: Ty<'tcx>,
6865
v: ty::Variance,
69-
b: CanonicalTy<'tcx>,
66+
canonical_b: CanonicalTy<'tcx>,
7067
locations: Locations,
7168
category: ConstraintCategory,
7269
borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>,
7370
) -> Fallible<Ty<'tcx>> {
7471
debug!(
75-
"sub_type_and_user_type(a={:?}, b={:?}, locations={:?})",
76-
a, b, locations
72+
"relate_type_and_user_type(a={:?}, v={:?}, b={:?}, locations={:?})",
73+
a, v, canonical_b, locations
74+
);
75+
76+
let (b, _values) = infcx.instantiate_canonical_with_fresh_inference_vars(
77+
DUMMY_SP,
78+
&canonical_b,
7779
);
78-
let Canonical {
79-
variables: b_variables,
80-
value: b_value,
81-
} = b;
8280

8381
// The `TypeRelating` code assumes that the "canonical variables"
8482
// appear in the "a" side, so flip `Contravariant` ambient
@@ -89,20 +87,10 @@ pub(super) fn relate_type_and_user_type<'tcx>(
8987
infcx,
9088
NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category),
9189
v1,
92-
b_variables,
9390
);
94-
type_relating.relate(&b_value, &a)?;
95-
96-
Ok(b.substitute(
97-
infcx.tcx,
98-
&CanonicalVarValues {
99-
var_values: type_relating
100-
.canonical_var_values
101-
.into_iter()
102-
.map(|x| x.expect("unsubstituted canonical variable"))
103-
.collect(),
104-
},
105-
))
91+
type_relating.relate(&b, &a)?;
92+
93+
Ok(b)
10694
}
10795

10896
struct TypeRelating<'me, 'gcx: 'tcx, 'tcx: 'me, D>
@@ -136,19 +124,6 @@ where
136124

137125
/// Same as `a_scopes`, but for the `b` type.
138126
b_scopes: Vec<BoundRegionScope<'tcx>>,
139-
140-
/// As we execute, the type on the LHS *may* come from a canonical
141-
/// source. In that case, we will sometimes find a constraint like
142-
/// `?0 = B`, where `B` is a type from the RHS. The first time we
143-
/// find that, we simply record `B` (and the list of scopes that
144-
/// tells us how to *interpret* `B`). The next time we encounter
145-
/// `?0`, then, we can read this value out and use it.
146-
///
147-
/// One problem: these variables may be in some other universe,
148-
/// how can we enforce that? I guess I could add some kind of
149-
/// "minimum universe constraint" that we can feed to the NLL checker.
150-
/// --> also, we know this doesn't happen
151-
canonical_var_values: IndexVec<CanonicalVar, Option<Kind<'tcx>>>,
152127
}
153128

154129
trait TypeRelatingDelegate<'tcx> {
@@ -279,14 +254,11 @@ where
279254
infcx: &'me InferCtxt<'me, 'gcx, 'tcx>,
280255
delegate: D,
281256
ambient_variance: ty::Variance,
282-
canonical_var_infos: CanonicalVarInfos<'tcx>,
283257
) -> Self {
284-
let canonical_var_values = IndexVec::from_elem_n(None, canonical_var_infos.len());
285258
Self {
286259
infcx,
287260
delegate,
288261
ambient_variance,
289-
canonical_var_values,
290262
a_scopes: vec![],
291263
b_scopes: vec![],
292264
}
@@ -400,19 +372,13 @@ where
400372
/// equated, then equate it again.
401373
fn relate_var(
402374
&mut self,
403-
var: CanonicalVar,
404-
b_kind: Kind<'tcx>,
405-
) -> RelateResult<'tcx, Kind<'tcx>> {
406-
debug!("equate_var(var={:?}, b_kind={:?})", var, b_kind);
407-
408-
let generalized_kind = match self.canonical_var_values[var] {
409-
Some(v) => v,
410-
None => {
411-
let generalized_kind = self.generalize_value(b_kind);
412-
self.canonical_var_values[var] = Some(generalized_kind);
413-
generalized_kind
414-
}
415-
};
375+
var_ty: Ty<'tcx>,
376+
value_ty: Ty<'tcx>,
377+
) -> RelateResult<'tcx, Ty<'tcx>> {
378+
debug!("equate_var(var_ty={:?}, value_ty={:?})", var_ty, value_ty);
379+
380+
let generalized_ty = self.generalize_value(value_ty);
381+
self.infcx.force_instantiate_unchecked(var_ty, generalized_ty);
416382

417383
// The generalized values we extract from `canonical_var_values` have
418384
// been fully instantiated and hence the set of scopes we have
@@ -421,16 +387,16 @@ where
421387
let old_a_scopes = ::std::mem::replace(&mut self.a_scopes, vec![]);
422388

423389
// Relate the generalized kind to the original one.
424-
let result = self.relate(&generalized_kind, &b_kind);
390+
let result = self.relate(&generalized_ty, &value_ty);
425391

426392
// Restore the old scopes now.
427393
self.a_scopes = old_a_scopes;
428394

429395
debug!("equate_var: complete, result = {:?}", result);
430-
return result;
396+
result
431397
}
432398

433-
fn generalize_value(&mut self, kind: Kind<'tcx>) -> Kind<'tcx> {
399+
fn generalize_value<T: Relate<'tcx>>(&mut self, value: T) -> T {
434400
TypeGeneralizer {
435401
tcx: self.infcx.tcx,
436402
delegate: &mut self.delegate,
@@ -440,7 +406,7 @@ where
440406
// These always correspond to an `_` or `'_` written by
441407
// user, and those are always in the root universe.
442408
universe: ty::UniverseIndex::ROOT,
443-
}.relate(&kind, &kind)
409+
}.relate(&value, &value)
444410
.unwrap()
445411
}
446412
}
@@ -490,18 +456,22 @@ where
490456
}
491457

492458
fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
493-
// Watch out for the case that we are matching a `?T` against the
494-
// right-hand side.
495-
if let ty::Infer(ty::CanonicalTy(var)) = a.sty {
496-
self.relate_var(var, b.into())?;
497-
Ok(a)
498-
} else {
499-
debug!(
500-
"tys(a={:?}, b={:?}, variance={:?})",
501-
a, b, self.ambient_variance
502-
);
459+
let a = self.infcx.shallow_resolve(a);
460+
match a.sty {
461+
ty::Infer(ty::TyVar(_)) |
462+
ty::Infer(ty::IntVar(_)) |
463+
ty::Infer(ty::FloatVar(_)) => {
464+
self.relate_var(a.into(), b.into())
465+
}
466+
467+
_ => {
468+
debug!(
469+
"tys(a={:?}, b={:?}, variance={:?})",
470+
a, b, self.ambient_variance
471+
);
503472

504-
relate::super_relate_tys(self, a, b)
473+
relate::super_relate_tys(self, a, b)
474+
}
505475
}
506476
}
507477

@@ -510,11 +480,6 @@ where
510480
a: ty::Region<'tcx>,
511481
b: ty::Region<'tcx>,
512482
) -> RelateResult<'tcx, ty::Region<'tcx>> {
513-
if let ty::ReCanonical(var) = a {
514-
self.relate_var(*var, b.into())?;
515-
return Ok(a);
516-
}
517-
518483
debug!(
519484
"regions(a={:?}, b={:?}, variance={:?})",
520485
a, b, self.ambient_variance

0 commit comments

Comments
 (0)