Skip to content

Commit 0cb7926

Browse files
nikomatsakisscalexm
authored andcommitted
refactor so that relate_ty_var can accommodate vid on a or b side
1 parent 356ea0b commit 0cb7926

File tree

1 file changed

+130
-22
lines changed
  • src/librustc/infer/nll_relate

1 file changed

+130
-22
lines changed

src/librustc/infer/nll_relate/mod.rs

+130-22
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
2929
use crate::ty::subst::Kind;
3030
use crate::ty::{self, Ty, TyCtxt};
3131
use rustc_data_structures::fx::FxHashMap;
32+
use std::fmt::Debug;
3233

3334
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
3435
pub enum NormalizationStrategy {
@@ -294,14 +295,34 @@ where
294295
}
295296
}
296297

297-
/// Relate a type inference variable with a value type.
298-
fn relate_ty_var(
298+
/// Relate a type inference variable with a value type. This works
299+
/// by creating a "generalization" G of the value where all the
300+
/// lifetimes are replaced with fresh inference values. This
301+
/// genearlization G becomes the value of the inference variable,
302+
/// and is then related in turn to the value. So e.g. if you had
303+
/// `vid = ?0` and `value = &'a u32`, we might first instantiate
304+
/// `?0` to a type like `&'0 u32` where `'0` is a fresh variable,
305+
/// and then relate `&'0 u32` with `&'a u32` (resulting in
306+
/// relations between `'0` and `'a`).
307+
///
308+
/// The variable `pair` can be either a `(vid, ty)` or `(ty, vid)`
309+
/// -- in other words, it is always a (unresolved) inference
310+
/// variable `vid` and a type `ty` that are being related, but the
311+
/// vid may appear either as the "a" type or the "b" type,
312+
/// depending on where it appears in the tuple. The trait
313+
/// `VidValuePair` lets us work with the vid/type while preserving
314+
/// the "sidedness" when necessary -- the sidedness is relevant in
315+
/// particular for the variance and set of in-scope things.
316+
fn relate_ty_var<PAIR: VidValuePair<'tcx>>(
299317
&mut self,
300-
vid: ty::TyVid,
301-
value_ty: Ty<'tcx>,
318+
pair: PAIR,
302319
) -> RelateResult<'tcx, Ty<'tcx>> {
303-
debug!("relate_ty_var(vid={:?}, value_ty={:?})", vid, value_ty);
320+
debug!("relate_ty_var({:?})", pair);
321+
322+
let vid = pair.vid();
323+
let value_ty = pair.value_ty();
304324

325+
// FIXME -- this logic assumes invariance, but that is wrong
305326
match value_ty.sty {
306327
ty::Infer(ty::TyVar(value_vid)) => {
307328
// Two type variables: just equate them.
@@ -338,13 +359,13 @@ where
338359
// been fully instantiated and hence the set of scopes we have
339360
// doesn't matter -- just to be sure, put an empty vector
340361
// in there.
341-
let old_a_scopes = ::std::mem::replace(&mut self.a_scopes, vec![]);
362+
let old_a_scopes = ::std::mem::replace(pair.vid_scopes(self), vec![]);
342363

343364
// Relate the generalized kind to the original one.
344-
let result = self.relate(&generalized_ty, &value_ty);
365+
let result = pair.relate_generalized_ty(self, generalized_ty);
345366

346367
// Restore the old scopes now.
347-
self.a_scopes = old_a_scopes;
368+
*pair.vid_scopes(self) = old_a_scopes;
348369

349370
debug!("relate_ty_var: complete, result = {:?}", result);
350371
result
@@ -370,6 +391,104 @@ where
370391
}
371392
}
372393

394+
/// When we instantiate a inference variable with a value in
395+
/// `relate_ty_var`, we always have the pair of a `TyVid` and a `Ty`,
396+
/// but the ordering may vary (depending on whether the inference
397+
/// variable was found on the `a` or `b` sides). Therefore, this trait
398+
/// allows us to factor out common code, while preserving the order
399+
/// when needed.
400+
trait VidValuePair<'tcx>: Debug {
401+
/// Extract the inference variable (which could be either the
402+
/// first or second part of the tuple).
403+
fn vid(&self) -> ty::TyVid;
404+
405+
/// Extract the value it is being related to (which will be the
406+
/// opposite part of the tuple from the vid).
407+
fn value_ty(&self) -> Ty<'tcx>;
408+
409+
/// Extract the scopes that apply to whichever side of the tuple
410+
/// the vid was found on. See the comment where this is called
411+
/// for more details on why we want them.
412+
fn vid_scopes<D: TypeRelatingDelegate<'tcx>>(
413+
&self,
414+
relate: &'r mut TypeRelating<'_, '_, 'tcx, D>,
415+
) -> &'r mut Vec<BoundRegionScope<'tcx>>;
416+
417+
/// Given a generalized type G that should replace the vid, relate
418+
/// G to the value, putting G on whichever side the vid would have
419+
/// appeared.
420+
fn relate_generalized_ty<D>(
421+
&self,
422+
relate: &mut TypeRelating<'_, '_, 'tcx, D>,
423+
generalized_ty: Ty<'tcx>,
424+
) -> RelateResult<'tcx, Ty<'tcx>>
425+
where
426+
D: TypeRelatingDelegate<'tcx>;
427+
}
428+
429+
impl VidValuePair<'tcx> for (ty::TyVid, Ty<'tcx>) {
430+
fn vid(&self) -> ty::TyVid {
431+
self.0
432+
}
433+
434+
fn value_ty(&self) -> Ty<'tcx> {
435+
self.1
436+
}
437+
438+
fn vid_scopes<D>(
439+
&self,
440+
relate: &'r mut TypeRelating<'_, '_, 'tcx, D>,
441+
) -> &'r mut Vec<BoundRegionScope<'tcx>>
442+
where
443+
D: TypeRelatingDelegate<'tcx>,
444+
{
445+
&mut relate.a_scopes
446+
}
447+
448+
fn relate_generalized_ty<D>(
449+
&self,
450+
relate: &mut TypeRelating<'_, '_, 'tcx, D>,
451+
generalized_ty: Ty<'tcx>,
452+
) -> RelateResult<'tcx, Ty<'tcx>>
453+
where
454+
D: TypeRelatingDelegate<'tcx>,
455+
{
456+
relate.relate(&generalized_ty, &self.value_ty())
457+
}
458+
}
459+
460+
// In this case, the "vid" is the "b" type.
461+
impl VidValuePair<'tcx> for (Ty<'tcx>, ty::TyVid) {
462+
fn vid(&self) -> ty::TyVid {
463+
self.1
464+
}
465+
466+
fn value_ty(&self) -> Ty<'tcx> {
467+
self.0
468+
}
469+
470+
fn vid_scopes<D>(
471+
&self,
472+
relate: &'r mut TypeRelating<'_, '_, 'tcx, D>,
473+
) -> &'r mut Vec<BoundRegionScope<'tcx>>
474+
where
475+
D: TypeRelatingDelegate<'tcx>,
476+
{
477+
&mut relate.b_scopes
478+
}
479+
480+
fn relate_generalized_ty<D>(
481+
&self,
482+
relate: &mut TypeRelating<'_, '_, 'tcx, D>,
483+
generalized_ty: Ty<'tcx>,
484+
) -> RelateResult<'tcx, Ty<'tcx>>
485+
where
486+
D: TypeRelatingDelegate<'tcx>,
487+
{
488+
relate.relate(&self.value_ty(), &generalized_ty)
489+
}
490+
}
491+
373492
impl<D> TypeRelation<'me, 'gcx, 'tcx> for TypeRelating<'me, 'gcx, 'tcx, D>
374493
where
375494
D: TypeRelatingDelegate<'tcx>,
@@ -427,17 +546,11 @@ where
427546
// Forbid inference variables in the RHS.
428547
bug!("unexpected inference var {:?}", b)
429548
} else {
430-
// We swap the order of `a` and `b` in the call to
431-
// `relate_ty_var` below, so swap the corresponding scopes
432-
// as well.
433-
std::mem::swap(&mut self.a_scopes, &mut self.b_scopes);
434-
let res = self.relate_ty_var(vid, a);
435-
std::mem::swap(&mut self.a_scopes, &mut self.b_scopes);
436-
res
549+
self.relate_ty_var((a, vid))
437550
}
438551
}
439552

440-
(&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var(vid, b),
553+
(&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)),
441554

442555
(&ty::Projection(projection_ty), _)
443556
if D::normalization() == NormalizationStrategy::Lazy =>
@@ -448,12 +561,7 @@ where
448561
(_, &ty::Projection(projection_ty))
449562
if D::normalization() == NormalizationStrategy::Lazy =>
450563
{
451-
// Swap the respective scopes of `a` and `b` (see comment
452-
// above).
453-
std::mem::swap(&mut self.a_scopes, &mut self.b_scopes);
454-
let res = self.relate_projection_ty(projection_ty, a);
455-
std::mem::swap(&mut self.a_scopes, &mut self.b_scopes);
456-
Ok(res)
564+
Ok(self.relate_projection_ty(projection_ty, a))
457565
}
458566

459567
_ => {

0 commit comments

Comments
 (0)