Skip to content

Commit cd23553

Browse files
committed
use TypeFolder in generalization instead of Relate
This kills the annoying `relate(a, a)` hack
1 parent 60dd5f7 commit cd23553

File tree

4 files changed

+114
-119
lines changed

4 files changed

+114
-119
lines changed

src/librustc/infer/combine.rs

+40-48
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ use super::lub::Lub;
2929
use super::sub::Sub;
3030
use super::type_variable::TypeVariableValue;
3131

32-
use crate::hir::def_id::DefId;
3332
use crate::ty::{IntType, UintType};
3433
use crate::ty::{self, Ty, TyCtxt};
34+
use crate::ty::fold::{TypeFoldable, TypeFolder};
3535
use crate::ty::error::TypeError;
36-
use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
37-
use crate::ty::subst::Substs;
36+
use crate::ty::relate::{RelateResult, TypeRelation};
3837
use crate::traits::{Obligation, PredicateObligations};
38+
use crate::util::common::ErrorReported;
3939

4040
use syntax::ast;
4141
use syntax_pos::Span;
@@ -264,7 +264,7 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> {
264264
root_ty: ty,
265265
};
266266

267-
let ty = match generalize.relate(&ty, &ty) {
267+
let ty = match ty.fold_with(&mut generalize) {
268268
Ok(ty) => ty,
269269
Err(e) => {
270270
debug!("generalize: failure {:?}", e);
@@ -332,60 +332,40 @@ struct Generalization<'tcx> {
332332
needs_wf: bool,
333333
}
334334

335-
impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, 'tcx> {
336-
fn tcx(&self) -> TyCtxt<'cx, 'gcx, 'tcx> {
337-
self.infcx.tcx
338-
}
339-
340-
fn tag(&self) -> &'static str {
341-
"Generalizer"
342-
}
335+
impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Generalizer<'cx, 'gcx, 'tcx> {
336+
type Error = TypeError<'tcx>;
343337

344-
fn a_is_expected(&self) -> bool {
345-
true
346-
}
347-
348-
fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
349-
-> RelateResult<'tcx, ty::Binder<T>>
350-
where T: Relate<'tcx>
351-
{
352-
Ok(ty::Binder::bind(self.relate(a.skip_binder(), b.skip_binder())?))
338+
fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> {
339+
self.infcx.tcx
353340
}
354341

355-
fn relate_item_substs(&mut self,
356-
item_def_id: DefId,
357-
a_subst: &'tcx Substs<'tcx>,
358-
b_subst: &'tcx Substs<'tcx>)
359-
-> RelateResult<'tcx, &'tcx Substs<'tcx>>
360-
{
342+
fn use_variances(&self) -> bool {
361343
if self.ambient_variance == ty::Variance::Invariant {
362344
// Avoid fetching the variance if we are in an invariant
363345
// context; no need, and it can induce dependency cycles
364346
// (e.g., #41849).
365-
relate::relate_substs(self, None, a_subst, b_subst)
347+
false
366348
} else {
367-
let opt_variances = self.tcx().variances_of(item_def_id);
368-
relate::relate_substs(self, Some(&opt_variances), a_subst, b_subst)
349+
true
369350
}
370351
}
371352

372-
fn relate_with_variance<T: Relate<'tcx>>(&mut self,
373-
variance: ty::Variance,
374-
a: &T,
375-
b: &T)
376-
-> RelateResult<'tcx, T>
353+
fn fold_with_variance<T: TypeFoldable<'tcx>>(&mut self,
354+
variance: ty::Variance,
355+
a: &T)
356+
-> RelateResult<'tcx, T>
377357
{
378358
let old_ambient_variance = self.ambient_variance;
359+
debug!("Generalize: fold_with_variance({:?}, {:?}, old_variance={:?})", variance, a, old_ambient_variance);
379360
self.ambient_variance = self.ambient_variance.xform(variance);
380361

381-
let result = self.relate(a, b);
362+
let result = a.fold_with(self);
382363
self.ambient_variance = old_ambient_variance;
383364
result
384365
}
385366

386-
fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
387-
assert_eq!(t, t2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
388-
367+
fn fold_ty(&mut self, t: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
368+
debug!("Generalize: fold_ty({:?}, variance={:?})", t, self.ambient_variance);
389369
// Check to see whether the type we are genealizing references
390370
// any other type variable related to `vid` via
391371
// subtyping. This is basically our "occurs check", preventing
@@ -403,7 +383,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
403383
match variables.probe(vid) {
404384
TypeVariableValue::Known { value: u } => {
405385
drop(variables);
406-
self.relate(&u, &u)
386+
u.fold_with(self)
407387
}
408388
TypeVariableValue::Unknown { universe } => {
409389
match self.ambient_variance {
@@ -423,7 +403,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
423403

424404
let origin = *variables.var_origin(vid);
425405
let new_var_id = variables.new_var(universe, false, origin);
426-
let u = self.tcx().mk_var(new_var_id);
406+
let u = self.infcx.tcx.mk_var(new_var_id);
427407
debug!("generalize: replacing original vid={:?} with new={:?}",
428408
vid, u);
429409
return Ok(u);
@@ -433,21 +413,33 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
433413
}
434414
ty::Infer(ty::IntVar(_)) |
435415
ty::Infer(ty::FloatVar(_)) => {
436-
// No matter what mode we are in,
437-
// integer/floating-point types must be equal to be
438-
// relatable.
439416
Ok(t)
440417
}
418+
ty::Array(_, sz) => {
419+
// HACK, not sure how desirable this is: propagate errors from
420+
// array lengths to the array type itself. This makes error
421+
// messages a bit nicer, and used to be the case before because
422+
// we used `ty::relate` instead of `TypeFoldable`, so I'll keep
423+
// it here.
424+
//
425+
// This does not serve any functional purpose, but it does
426+
// avoid some "duplicate" errors.
427+
match self.infcx.tcx.force_eval_array_length(*sz) {
428+
Ok(_) => t.super_fold_with(self),
429+
Err(ErrorReported) => {
430+
Ok(self.infcx.tcx.types.err)
431+
}
432+
}
433+
}
441434
_ => {
442-
relate::super_relate_tys(self, t, t)
435+
t.super_fold_with(self)
443436
}
444437
}
445438
}
446439

447-
fn regions(&mut self, r: ty::Region<'tcx>, r2: ty::Region<'tcx>)
440+
fn fold_region(&mut self, r: ty::Region<'tcx>)
448441
-> RelateResult<'tcx, ty::Region<'tcx>> {
449-
assert_eq!(r, r2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
450-
442+
debug!("Generalize: fold_region({:?}, variance={:?})", r, self.ambient_variance);
451443
match *r {
452444
// Never make variables for regions bound within the type itself,
453445
// nor for erased regions.

src/librustc/infer/nll_relate/mod.rs

+35-33
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
//! constituents)
2323
2424
use crate::infer::InferCtxt;
25-
use crate::ty::fold::{TypeFoldable, TypeVisitor};
26-
use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
25+
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
26+
use crate::ty::relate::{Relate, RelateResult, TypeRelation};
2727
use crate::ty::subst::Kind;
2828
use crate::ty::{self, Ty, TyCtxt};
2929
use crate::ty::error::TypeError;
@@ -344,7 +344,7 @@ where
344344
result
345345
}
346346

347-
fn generalize_value<T: Relate<'tcx>>(
347+
fn generalize_value<T: TypeFoldable<'tcx>>(
348348
&mut self,
349349
value: T,
350350
for_vid: ty::TyVid
@@ -360,7 +360,7 @@ where
360360
universe,
361361
};
362362

363-
generalizer.relate(&value, &value)
363+
value.fold_with(&mut generalizer)
364364
}
365365
}
366366

@@ -680,54 +680,58 @@ where
680680
universe: ty::UniverseIndex,
681681
}
682682

683-
impl<D> TypeRelation<'me, 'gcx, 'tcx> for TypeGeneralizer<'me, 'gcx, 'tcx, D>
683+
impl<D> TypeFolder<'gcx, 'tcx> for TypeGeneralizer<'me, 'gcx, 'tcx, D>
684684
where
685685
D: TypeRelatingDelegate<'tcx>,
686686
{
687-
fn tcx(&self) -> TyCtxt<'me, 'gcx, 'tcx> {
688-
self.infcx.tcx
689-
}
687+
type Error = TypeError<'tcx>;
690688

691-
fn tag(&self) -> &'static str {
692-
"nll::generalizer"
689+
fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> {
690+
self.infcx.tcx
693691
}
694692

695-
fn a_is_expected(&self) -> bool {
696-
true
693+
fn use_variances(&self) -> bool {
694+
if self.ambient_variance == ty::Variance::Invariant {
695+
// Avoid fetching the variance if we are in an invariant
696+
// context; no need, and it can induce dependency cycles
697+
// (e.g., #41849).
698+
false
699+
} else {
700+
true
701+
}
697702
}
698703

699-
fn relate_with_variance<T: Relate<'tcx>>(
704+
fn fold_with_variance<T: TypeFoldable<'tcx>>(
700705
&mut self,
701706
variance: ty::Variance,
702707
a: &T,
703-
b: &T,
704708
) -> RelateResult<'tcx, T> {
705709
debug!(
706-
"TypeGeneralizer::relate_with_variance(variance={:?}, a={:?}, b={:?})",
707-
variance, a, b
710+
"TypeGeneralizer::fold_with_variance(variance={:?}, a={:?})",
711+
variance, a
708712
);
709713

710714
let old_ambient_variance = self.ambient_variance;
711715
self.ambient_variance = self.ambient_variance.xform(variance);
712716

713717
debug!(
714-
"TypeGeneralizer::relate_with_variance: ambient_variance = {:?}",
718+
"TypeGeneralizer::fold_with_variance: ambient_variance = {:?}",
715719
self.ambient_variance
716720
);
717721

718-
let r = self.relate(a, b)?;
722+
let r = a.super_fold_with(self)?;
719723

720724
self.ambient_variance = old_ambient_variance;
721725

722-
debug!("TypeGeneralizer::relate_with_variance: r={:?}", r);
726+
debug!("TypeGeneralizer::fold_with_variance: r={:?}", r);
723727

724728
Ok(r)
725729
}
726730

727-
fn tys(&mut self, a: Ty<'tcx>, _: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
731+
fn fold_ty(&mut self, a: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
728732
use crate::infer::type_variable::TypeVariableValue;
729733

730-
debug!("TypeGeneralizer::tys(a={:?})", a,);
734+
debug!("TypeGeneralizer::fold_ty(a={:?})", a,);
731735

732736
match a.sty {
733737
ty::Infer(ty::TyVar(_)) | ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_))
@@ -746,13 +750,13 @@ where
746750
if sub_vid == self.for_vid_sub_root {
747751
// If sub-roots are equal, then `for_vid` and
748752
// `vid` are related via subtyping.
749-
debug!("TypeGeneralizer::tys: occurs check failed");
753+
debug!("TypeGeneralizer::fold_ty: occurs check failed");
750754
return Err(TypeError::Mismatch);
751755
} else {
752756
match variables.probe(vid) {
753757
TypeVariableValue::Known { value: u } => {
754758
drop(variables);
755-
self.relate(&u, &u)
759+
u.fold_with(self)
756760
}
757761
TypeVariableValue::Unknown { universe: _universe } => {
758762
if self.ambient_variance == ty::Bivariant {
@@ -789,7 +793,7 @@ where
789793
ty::Placeholder(placeholder) => {
790794
if self.universe.cannot_name(placeholder.universe) {
791795
debug!(
792-
"TypeGeneralizer::tys: root universe {:?} cannot name\
796+
"TypeGeneralizer::fold_ty: root universe {:?} cannot name\
793797
placeholder in universe {:?}",
794798
self.universe,
795799
placeholder.universe
@@ -801,17 +805,16 @@ where
801805
}
802806

803807
_ => {
804-
relate::super_relate_tys(self, a, a)
808+
a.super_fold_with(self)
805809
}
806810
}
807811
}
808812

809-
fn regions(
813+
fn fold_region(
810814
&mut self,
811815
a: ty::Region<'tcx>,
812-
_: ty::Region<'tcx>,
813816
) -> RelateResult<'tcx, ty::Region<'tcx>> {
814-
debug!("TypeGeneralizer::regions(a={:?})", a,);
817+
debug!("TypeGeneralizer::fold_region(a={:?})", a,);
815818

816819
if let ty::ReLateBound(debruijn, _) = a {
817820
if *debruijn < self.first_free_index {
@@ -840,18 +843,17 @@ where
840843
Ok(replacement_region_vid)
841844
}
842845

843-
fn binders<T>(
846+
fn fold_binder<T>(
844847
&mut self,
845848
a: &ty::Binder<T>,
846-
_: &ty::Binder<T>,
847849
) -> RelateResult<'tcx, ty::Binder<T>>
848850
where
849-
T: Relate<'tcx>,
851+
T: TypeFoldable<'tcx>,
850852
{
851-
debug!("TypeGeneralizer::binders(a={:?})", a,);
853+
debug!("TypeGeneralizer::fold_binder(a={:?})", a,);
852854

853855
self.first_free_index.shift_in(1);
854-
let result = self.relate(a.skip_binder(), a.skip_binder())?;
856+
let result = a.skip_binder().fold_with(self)?;
855857
self.first_free_index.shift_out(1);
856858
Ok(ty::Binder::bind(result))
857859
}

src/librustc/ty/relate.rs

+2-38
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ use crate::hir::def_id::DefId;
88
use crate::ty::subst::{Kind, UnpackedKind, Substs};
99
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
1010
use crate::ty::error::{ExpectedFound, TypeError};
11-
use crate::mir::interpret::GlobalId;
1211
use crate::util::common::ErrorReported;
13-
use syntax_pos::DUMMY_SP;
1412
use std::rc::Rc;
1513
use std::iter;
1614
use rustc_target::spec::abi;
@@ -468,42 +466,8 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
468466
(&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) =>
469467
{
470468
let t = relation.relate(&a_t, &b_t)?;
471-
let to_u64 = |x: ty::LazyConst<'tcx>| -> Result<u64, ErrorReported> {
472-
match x {
473-
ty::LazyConst::Unevaluated(def_id, substs) => {
474-
// FIXME(eddyb) get the right param_env.
475-
let param_env = ty::ParamEnv::empty();
476-
if let Some(substs) = tcx.lift_to_global(&substs) {
477-
let instance = ty::Instance::resolve(
478-
tcx.global_tcx(),
479-
param_env,
480-
def_id,
481-
substs,
482-
);
483-
if let Some(instance) = instance {
484-
let cid = GlobalId {
485-
instance,
486-
promoted: None
487-
};
488-
if let Some(s) = tcx.const_eval(param_env.and(cid))
489-
.ok()
490-
.map(|c| c.unwrap_usize(tcx)) {
491-
return Ok(s)
492-
}
493-
}
494-
}
495-
tcx.sess.delay_span_bug(tcx.def_span(def_id),
496-
"array length could not be evaluated");
497-
Err(ErrorReported)
498-
}
499-
ty::LazyConst::Evaluated(c) => c.assert_usize(tcx).ok_or_else(|| {
500-
tcx.sess.delay_span_bug(DUMMY_SP,
501-
"array length could not be evaluated");
502-
ErrorReported
503-
})
504-
}
505-
};
506-
match (to_u64(*sz_a), to_u64(*sz_b)) {
469+
match (tcx.force_eval_array_length(*sz_a),
470+
tcx.force_eval_array_length(*sz_b)) {
507471
(Ok(sz_a_u64), Ok(sz_b_u64)) => {
508472
if sz_a_u64 == sz_b_u64 {
509473
Ok(tcx.mk_ty(ty::Array(t, sz_a)))

0 commit comments

Comments
 (0)