Skip to content

Commit bfc39b9

Browse files
varkoryodaldevoid
andcommitted
Implement TypeRelation::consts
Co-Authored-By: Gabriel Smith <[email protected]>
1 parent 7d71a1c commit bfc39b9

File tree

9 files changed

+315
-18
lines changed

9 files changed

+315
-18
lines changed

src/librustc/infer/canonical/canonicalizer.rs

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ use crate::infer::canonical::{
1010
OriginalQueryValues,
1111
};
1212
use crate::infer::InferCtxt;
13+
use crate::mir::interpret::ConstValue;
1314
use std::sync::atomic::Ordering;
1415
use crate::ty::fold::{TypeFoldable, TypeFolder};
1516
use crate::ty::subst::Kind;
16-
use crate::ty::{self, BoundVar, Lift, List, Ty, TyCtxt, TypeFlags};
17+
use crate::ty::{self, BoundVar, InferConst, Lift, List, Ty, TyCtxt, TypeFlags};
1718

1819
use rustc_data_structures::fx::FxHashMap;
1920
use rustc_data_structures::indexed_vec::Idx;
@@ -432,6 +433,54 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
432433
}
433434
}
434435
}
436+
437+
fn fold_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
438+
if let ty::LazyConst::Evaluated(ct) = c {
439+
match ct.val {
440+
ConstValue::Infer(InferConst::Var(vid)) => {
441+
debug!("canonical: const var found with vid {:?}", vid);
442+
match self.infcx.unwrap().probe_const_var(vid) {
443+
Ok(c) => {
444+
debug!("(resolved to {:?})", c);
445+
return self.fold_const(c);
446+
}
447+
448+
// `ConstVar(vid)` is unresolved, track its universe index in the
449+
// canonicalized result
450+
Err(mut ui) => {
451+
if !self.infcx.unwrap().tcx.sess.opts.debugging_opts.chalk {
452+
// FIXME: perf problem described in #55921.
453+
ui = ty::UniverseIndex::ROOT;
454+
}
455+
return self.canonicalize_const_var(
456+
CanonicalVarInfo {
457+
kind: CanonicalVarKind::Const(ui)
458+
},
459+
c
460+
);
461+
}
462+
}
463+
}
464+
ConstValue::Infer(InferConst::Fresh(_)) => {
465+
bug!("encountered a fresh const during canonicalization")
466+
}
467+
ConstValue::Infer(InferConst::Canonical(debruijn, _)) => {
468+
if debruijn >= self.binder_index {
469+
bug!("escaping bound type during canonicalization")
470+
} else {
471+
return c;
472+
}
473+
}
474+
_ => {}
475+
}
476+
}
477+
478+
if c.type_flags().intersects(self.needs_canonical_flags) {
479+
c.super_fold_with(self)
480+
} else {
481+
c
482+
}
483+
}
435484
}
436485

437486
impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
@@ -625,7 +674,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
625674
/// `ty_var`.
626675
fn canonicalize_ty_var(&mut self, info: CanonicalVarInfo, ty_var: Ty<'tcx>) -> Ty<'tcx> {
627676
let infcx = self.infcx.expect("encountered ty-var without infcx");
628-
let bound_to = infcx.shallow_resolve(ty_var);
677+
let bound_to = infcx.shallow_resolve_type(ty_var);
629678
if bound_to != ty_var {
630679
self.fold_ty(bound_to)
631680
} else {

src/librustc/infer/combine.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
464464

465465
debug!("generalize: t={:?}", t);
466466

467-
// Check to see whether the type we are genealizing references
467+
// Check to see whether the type we are generalizing references
468468
// any other type variable related to `vid` via
469469
// subtyping. This is basically our "occurs check", preventing
470470
// us from creating infinitely sized types.
@@ -576,6 +576,32 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
576576
// very descriptive origin for this region variable.
577577
Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.span), self.for_universe))
578578
}
579+
580+
fn consts(
581+
&mut self,
582+
c: &'tcx ty::LazyConst<'tcx>,
583+
c2: &'tcx ty::LazyConst<'tcx>
584+
) -> RelateResult<'tcx, &'tcx ty::LazyConst<'tcx>> {
585+
assert_eq!(c, c2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
586+
587+
match c {
588+
LazyConst::Evaluated(ty::Const {
589+
val: ConstValue::Infer(InferConst::Var(vid)),
590+
..
591+
}) => {
592+
let mut variable_table = self.infcx.const_unification_table.borrow_mut();
593+
match variable_table.probe(*vid).known() {
594+
Some(u) => {
595+
self.relate(&u, &u)
596+
}
597+
None => Ok(c),
598+
}
599+
}
600+
_ => {
601+
relate::super_relate_consts(self, c, c)
602+
}
603+
}
604+
}
579605
}
580606

581607
pub trait RelateResultCompare<'tcx, T> {

src/librustc/infer/equate.rs

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
use super::combine::{CombineFields, RelationDir};
2-
use super::{Subtype};
1+
use super::combine::{CombineFields, RelationDir, const_unification_error};
2+
use super::Subtype;
33

44
use crate::hir::def_id::DefId;
55

6-
use crate::ty::{self, Ty, TyCtxt};
6+
use crate::ty::{self, Ty, TyCtxt, InferConst};
77
use crate::ty::TyVar;
88
use crate::ty::subst::SubstsRef;
99
use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
10+
use crate::mir::interpret::ConstValue;
1011

1112
/// Ensures `a` is made equal to `b`. Returns `a` on success.
1213
pub struct Equate<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
@@ -100,6 +101,47 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
100101
Ok(a)
101102
}
102103

104+
fn consts(
105+
&mut self,
106+
a: &'tcx ty::LazyConst<'tcx>,
107+
b: &'tcx ty::LazyConst<'tcx>,
108+
) -> RelateResult<'tcx, &'tcx ty::LazyConst<'tcx>> {
109+
debug!("{}.consts({:?}, {:?})", self.tag(), a, b);
110+
if a == b { return Ok(a); }
111+
112+
let infcx = self.fields.infcx;
113+
let a = infcx.const_unification_table.borrow_mut().replace_if_possible(a);
114+
let b = infcx.const_unification_table.borrow_mut().replace_if_possible(b);
115+
let a_is_expected = self.a_is_expected();
116+
if let (&ty::LazyConst::Evaluated(a_eval), &ty::LazyConst::Evaluated(b_eval)) = (a, b) {
117+
match (a_eval.val, b_eval.val) {
118+
(ConstValue::Infer(InferConst::Var(a_vid)),
119+
ConstValue::Infer(InferConst::Var(b_vid))) => {
120+
infcx.const_unification_table
121+
.borrow_mut()
122+
.unify_var_var(a_vid, b_vid)
123+
.map_err(|e| const_unification_error(a_is_expected, e))?;
124+
return Ok(a);
125+
}
126+
127+
(ConstValue::Infer(InferConst::Var(a_id)), _) => {
128+
self.fields.infcx.unify_const_variable(a_is_expected, a_id, b)?;
129+
return Ok(a);
130+
}
131+
132+
(_, ConstValue::Infer(InferConst::Var(b_id))) => {
133+
self.fields.infcx.unify_const_variable(!a_is_expected, b_id, a)?;
134+
return Ok(a);
135+
}
136+
137+
_ => {}
138+
}
139+
}
140+
141+
self.fields.infcx.super_combine_consts(self, a, b)?;
142+
Ok(a)
143+
}
144+
103145
fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
104146
-> RelateResult<'tcx, ty::Binder<T>>
105147
where T: Relate<'tcx>

src/librustc/infer/glb.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,19 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
6060
Ok(self.fields.infcx.borrow_region_constraints().glb_regions(self.tcx(), origin, a, b))
6161
}
6262

63+
fn consts(
64+
&mut self,
65+
a: &'tcx ty::LazyConst<'tcx>,
66+
b: &'tcx ty::LazyConst<'tcx>,
67+
) -> RelateResult<'tcx, &'tcx ty::LazyConst<'tcx>> {
68+
debug!("{}.consts({:?}, {:?})", self.tag(), a, b);
69+
if a == b {
70+
return Ok(a);
71+
}
72+
73+
self.fields.infcx.super_combine_consts(self, a, b)
74+
}
75+
6376
fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
6477
-> RelateResult<'tcx, ty::Binder<T>>
6578
where T: Relate<'tcx>

src/librustc/infer/lub.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,19 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
6060
Ok(self.fields.infcx.borrow_region_constraints().lub_regions(self.tcx(), origin, a, b))
6161
}
6262

63+
fn consts(
64+
&mut self,
65+
a: &'tcx ty::LazyConst<'tcx>,
66+
b: &'tcx ty::LazyConst<'tcx>,
67+
) -> RelateResult<'tcx, &'tcx ty::LazyConst<'tcx>> {
68+
debug!("{}.consts({:?}, {:?})", self.tag(), a, b);
69+
if a == b {
70+
return Ok(a);
71+
}
72+
73+
self.fields.infcx.super_combine_consts(self, a, b)
74+
}
75+
6376
fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
6477
-> RelateResult<'tcx, ty::Binder<T>>
6578
where T: Relate<'tcx>

src/librustc/infer/nll_relate/mod.rs

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use crate::ty::error::TypeError;
2727
use crate::ty::fold::{TypeFoldable, TypeVisitor};
2828
use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
2929
use crate::ty::subst::Kind;
30-
use crate::ty::{self, Ty, TyCtxt};
30+
use crate::ty::{self, Ty, TyCtxt, InferConst};
3131
use rustc_data_structures::fx::FxHashMap;
3232
use std::fmt::Debug;
3333

@@ -537,10 +537,10 @@ where
537537
}
538538

539539
fn tys(&mut self, a: Ty<'tcx>, mut b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
540-
let a = self.infcx.shallow_resolve(a);
540+
let a = self.infcx.shallow_resolve_type(a);
541541

542542
if !D::forbid_inference_vars() {
543-
b = self.infcx.shallow_resolve(b);
543+
b = self.infcx.shallow_resolve_type(b);
544544
}
545545

546546
match (&a.sty, &b.sty) {
@@ -608,6 +608,24 @@ where
608608
Ok(a)
609609
}
610610

611+
fn consts(
612+
&mut self,
613+
a: &'tcx ty::LazyConst<'tcx>,
614+
b: &'tcx ty::LazyConst<'tcx>,
615+
) -> RelateResult<'tcx, &'tcx ty::LazyConst<'tcx>> {
616+
if let ty::LazyConst::Evaluated(ty::Const {
617+
val: ConstValue::Infer(InferConst::Canonical(_, _)),
618+
..
619+
}) = a {
620+
// FIXME(const_generics): I'm unsure how this branch should actually be handled,
621+
// so this is probably not correct.
622+
self.infcx.super_combine_consts(self, a, b)
623+
} else {
624+
debug!("consts(a={:?}, b={:?}, variance={:?})", a, b, self.ambient_variance);
625+
relate::super_relate_consts(self, a, b)
626+
}
627+
}
628+
611629
fn binders<T>(
612630
&mut self,
613631
a: &ty::Binder<T>,
@@ -853,7 +871,7 @@ where
853871
fn tys(&mut self, a: Ty<'tcx>, _: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
854872
use crate::infer::type_variable::TypeVariableValue;
855873

856-
debug!("TypeGeneralizer::tys(a={:?})", a,);
874+
debug!("TypeGeneralizer::tys(a={:?})", a);
857875

858876
match a.sty {
859877
ty::Infer(ty::TyVar(_)) | ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_))
@@ -934,7 +952,7 @@ where
934952
a: ty::Region<'tcx>,
935953
_: ty::Region<'tcx>,
936954
) -> RelateResult<'tcx, ty::Region<'tcx>> {
937-
debug!("TypeGeneralizer::regions(a={:?})", a,);
955+
debug!("TypeGeneralizer::regions(a={:?})", a);
938956

939957
if let ty::ReLateBound(debruijn, _) = a {
940958
if *debruijn < self.first_free_index {
@@ -963,6 +981,26 @@ where
963981
Ok(replacement_region_vid)
964982
}
965983

984+
fn consts(
985+
&mut self,
986+
a: &'tcx ty::LazyConst<'tcx>,
987+
_: &'tcx ty::LazyConst<'tcx>,
988+
) -> RelateResult<'tcx, &'tcx ty::LazyConst<'tcx>> {
989+
debug!("TypeGeneralizer::consts(a={:?})", a);
990+
991+
if let ty::LazyConst::Evaluated(ty::Const {
992+
val: ConstValue::Infer(InferConst::Canonical(_, _)),
993+
..
994+
}) = a {
995+
bug!(
996+
"unexpected inference variable encountered in NLL generalization: {:?}",
997+
a
998+
);
999+
} else {
1000+
relate::super_relate_consts(self, a, a)
1001+
}
1002+
}
1003+
9661004
fn binders<T>(
9671005
&mut self,
9681006
a: &ty::Binder<T>,
@@ -971,7 +1009,7 @@ where
9711009
where
9721010
T: Relate<'tcx>,
9731011
{
974-
debug!("TypeGeneralizer::binders(a={:?})", a,);
1012+
debug!("TypeGeneralizer::binders(a={:?})", a);
9751013

9761014
self.first_free_index.shift_in(1);
9771015
let result = self.relate(a.skip_binder(), a.skip_binder())?;

src/librustc/infer/sub.rs

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
use super::SubregionOrigin;
2-
use super::combine::{CombineFields, RelationDir};
2+
use super::combine::{CombineFields, RelationDir, const_unification_error};
33

44
use crate::traits::Obligation;
5-
use crate::ty::{self, Ty, TyCtxt};
5+
use crate::ty::{self, Ty, TyCtxt, InferConst};
66
use crate::ty::TyVar;
77
use crate::ty::fold::TypeFoldable;
88
use crate::ty::relate::{Cause, Relate, RelateResult, TypeRelation};
9+
use crate::mir::interpret::ConstValue;
910
use std::mem;
1011

1112
/// Ensures `a` is made a subtype of `b`. Returns `a` on success.
@@ -133,6 +134,50 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
133134
Ok(a)
134135
}
135136

137+
fn consts(
138+
&mut self,
139+
a: &'tcx ty::LazyConst<'tcx>,
140+
b: &'tcx ty::LazyConst<'tcx>,
141+
) -> RelateResult<'tcx, &'tcx ty::LazyConst<'tcx>> {
142+
debug!("{}.consts({:?}, {:?})", self.tag(), a, b);
143+
if a == b { return Ok(a); }
144+
145+
let infcx = self.fields.infcx;
146+
let a = infcx.const_unification_table.borrow_mut().replace_if_possible(a);
147+
let b = infcx.const_unification_table.borrow_mut().replace_if_possible(b);
148+
149+
// Consts can only be equal or unequal to each other: there's no subtyping
150+
// relation, so we're just going to perform equating here instead.
151+
let a_is_expected = self.a_is_expected();
152+
if let (&ty::LazyConst::Evaluated(a_eval), &ty::LazyConst::Evaluated(b_eval)) = (a, b) {
153+
match (a_eval.val, b_eval.val) {
154+
(ConstValue::Infer(InferConst::Var(a_vid)),
155+
ConstValue::Infer(InferConst::Var(b_vid))) => {
156+
infcx.const_unification_table
157+
.borrow_mut()
158+
.unify_var_var(a_vid, b_vid)
159+
.map_err(|e| const_unification_error(a_is_expected, e))?;
160+
return Ok(a);
161+
}
162+
163+
(ConstValue::Infer(InferConst::Var(a_id)), _) => {
164+
self.fields.infcx.unify_const_variable(a_is_expected, a_id, b)?;
165+
return Ok(a);
166+
}
167+
168+
(_, ConstValue::Infer(InferConst::Var(b_id))) => {
169+
self.fields.infcx.unify_const_variable(!a_is_expected, b_id, a)?;
170+
return Ok(a);
171+
}
172+
173+
_ => {}
174+
}
175+
}
176+
177+
self.fields.infcx.super_combine_consts(self, a, b)?;
178+
Ok(a)
179+
}
180+
136181
fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
137182
-> RelateResult<'tcx, ty::Binder<T>>
138183
where T: Relate<'tcx>

0 commit comments

Comments
 (0)