Skip to content

Commit 7d71a1c

Browse files
varkoryodaldevoid
andcommitted
Add const generics to unification tables
Co-Authored-By: Gabriel Smith <[email protected]>
1 parent b9b9994 commit 7d71a1c

File tree

1 file changed

+128
-42
lines changed

1 file changed

+128
-42
lines changed

src/librustc/infer/mod.rs

Lines changed: 128 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,15 @@ use crate::infer::canonical::{Canonical, CanonicalVarValues};
1313
use crate::middle::free_region::RegionRelations;
1414
use crate::middle::lang_items;
1515
use crate::middle::region;
16+
use crate::mir::interpret::ConstValue;
1617
use crate::session::config::BorrowckMode;
1718
use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine};
1819
use crate::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
1920
use crate::ty::fold::TypeFoldable;
2021
use crate::ty::relate::RelateResult;
2122
use crate::ty::subst::{Kind, InternalSubsts, SubstsRef};
22-
use crate::ty::{self, GenericParamDefKind, Ty, TyCtxt, CtxtInterners};
23-
use crate::ty::{FloatVid, IntVid, TyVid};
23+
use crate::ty::{self, GenericParamDefKind, Ty, TyCtxt, CtxtInterners, InferConst};
24+
use crate::ty::{FloatVid, IntVid, TyVid, ConstVid};
2425
use crate::util::nodemap::FxHashMap;
2526

2627
use arena::SyncDroplessArena;
@@ -34,6 +35,7 @@ use syntax_pos::symbol::InternedString;
3435
use syntax_pos::Span;
3536

3637
use self::combine::CombineFields;
38+
use self::const_variable::ConstVariableOrigin;
3739
use self::lexical_region_resolve::LexicalRegionResolutions;
3840
use self::outlives::env::OutlivesEnvironment;
3941
use self::region_constraints::{GenericKind, RegionConstraintData, VarInfos, VerifyBound};
@@ -60,6 +62,7 @@ pub mod region_constraints;
6062
pub mod resolve;
6163
mod sub;
6264
pub mod type_variable;
65+
pub mod const_variable;
6366
pub mod unify_key;
6467

6568
#[must_use]
@@ -72,7 +75,7 @@ pub type InferResult<'tcx, T> = Result<InferOk<'tcx, T>, TypeError<'tcx>>;
7275

7376
pub type Bound<T> = Option<T>;
7477
pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result"
75-
pub type FixupResult<T> = Result<T, FixupError>; // "fixup result"
78+
pub type FixupResult<'tcx, T> = Result<T, FixupError<'tcx>>; // "fixup result"
7679

7780
/// A flag that is used to suppress region errors. This is normally
7881
/// false, but sometimes -- when we are doing region checks that the
@@ -122,7 +125,10 @@ pub struct InferCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
122125
/// order, represented by its upper and lower bounds.
123126
pub type_variables: RefCell<type_variable::TypeVariableTable<'tcx>>,
124127

125-
/// Map from integral variable to the kind of integer it represents
128+
/// Map from const parameter variable to the kind of const it represents.
129+
const_unification_table: RefCell<const_variable::ConstVariableTable<'tcx>>,
130+
131+
/// Map from integral variable to the kind of integer it represents.
126132
int_unification_table: RefCell<ut::UnificationTable<ut::InPlace<ty::IntVid>>>,
127133

128134
/// Map from floating variable to the kind of float it represents
@@ -422,10 +428,11 @@ impl NLLRegionVariableOrigin {
422428
}
423429

424430
#[derive(Copy, Clone, Debug)]
425-
pub enum FixupError {
431+
pub enum FixupError<'tcx> {
426432
UnresolvedIntTy(IntVid),
427433
UnresolvedFloatTy(FloatVid),
428434
UnresolvedTy(TyVid),
435+
UnresolvedConst(ConstVid<'tcx>),
429436
}
430437

431438
/// See the `region_obligations` field for more information.
@@ -436,7 +443,7 @@ pub struct RegionObligation<'tcx> {
436443
pub origin: SubregionOrigin<'tcx>,
437444
}
438445

439-
impl fmt::Display for FixupError {
446+
impl<'tcx> fmt::Display for FixupError<'tcx> {
440447
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
441448
use self::FixupError::*;
442449

@@ -452,6 +459,7 @@ impl fmt::Display for FixupError {
452459
add a suffix to specify the type explicitly"
453460
),
454461
UnresolvedTy(_) => write!(f, "unconstrained type"),
462+
UnresolvedConst(_) => write!(f, "unconstrained const value"),
455463
}
456464
}
457465
}
@@ -524,6 +532,7 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
524532
in_progress_tables,
525533
projection_cache: Default::default(),
526534
type_variables: RefCell::new(type_variable::TypeVariableTable::new()),
535+
const_unification_table: RefCell::new(const_variable::ConstVariableTable::new()),
527536
int_unification_table: RefCell::new(ut::UnificationTable::new()),
528537
float_unification_table: RefCell::new(ut::UnificationTable::new()),
529538
region_constraints: RefCell::new(Some(RegionConstraintCollector::new())),
@@ -589,6 +598,7 @@ impl<'tcx> InferOk<'tcx, ()> {
589598
pub struct CombinedSnapshot<'a, 'tcx: 'a> {
590599
projection_cache_snapshot: traits::ProjectionCacheSnapshot,
591600
type_snapshot: type_variable::Snapshot<'tcx>,
601+
const_snapshot: const_variable::Snapshot<'tcx>,
592602
int_snapshot: ut::Snapshot<ut::InPlace<ty::IntVid>>,
593603
float_snapshot: ut::Snapshot<ut::InPlace<ty::FloatVid>>,
594604
region_constraints_snapshot: RegionSnapshot,
@@ -652,6 +662,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
652662
let mut type_variables = self.type_variables.borrow_mut();
653663
let mut int_unification_table = self.int_unification_table.borrow_mut();
654664
let mut float_unification_table = self.float_unification_table.borrow_mut();
665+
// FIXME(const_generics): should there be an equivalent function for const variables?
655666

656667
type_variables
657668
.unsolved_variables()
@@ -722,6 +733,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
722733
CombinedSnapshot {
723734
projection_cache_snapshot: self.projection_cache.borrow_mut().snapshot(),
724735
type_snapshot: self.type_variables.borrow_mut().snapshot(),
736+
const_snapshot: self.const_unification_table.borrow_mut().snapshot(),
725737
int_snapshot: self.int_unification_table.borrow_mut().snapshot(),
726738
float_snapshot: self.float_unification_table.borrow_mut().snapshot(),
727739
region_constraints_snapshot: self.borrow_region_constraints().start_snapshot(),
@@ -739,6 +751,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
739751
let CombinedSnapshot {
740752
projection_cache_snapshot,
741753
type_snapshot,
754+
const_snapshot,
742755
int_snapshot,
743756
float_snapshot,
744757
region_constraints_snapshot,
@@ -751,28 +764,21 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
751764
self.in_snapshot.set(was_in_snapshot);
752765
self.universe.set(universe);
753766

754-
self.projection_cache
755-
.borrow_mut()
756-
.rollback_to(projection_cache_snapshot);
767+
self.projection_cache.borrow_mut().rollback_to(projection_cache_snapshot);
757768
self.type_variables.borrow_mut().rollback_to(type_snapshot);
758-
self.int_unification_table
759-
.borrow_mut()
760-
.rollback_to(int_snapshot);
761-
self.float_unification_table
762-
.borrow_mut()
763-
.rollback_to(float_snapshot);
764-
self.region_obligations
765-
.borrow_mut()
766-
.truncate(region_obligations_snapshot);
767-
self.borrow_region_constraints()
768-
.rollback_to(region_constraints_snapshot);
769+
self.const_unification_table.borrow_mut().rollback_to(const_snapshot);
770+
self.int_unification_table.borrow_mut().rollback_to(int_snapshot);
771+
self.float_unification_table.borrow_mut().rollback_to(float_snapshot);
772+
self.region_obligations.borrow_mut().truncate(region_obligations_snapshot);
773+
self.borrow_region_constraints().rollback_to(region_constraints_snapshot);
769774
}
770775

771776
fn commit_from(&self, snapshot: CombinedSnapshot<'a, 'tcx>) {
772777
debug!("commit_from()");
773778
let CombinedSnapshot {
774779
projection_cache_snapshot,
775780
type_snapshot,
781+
const_snapshot,
776782
int_snapshot,
777783
float_snapshot,
778784
region_constraints_snapshot,
@@ -784,16 +790,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
784790

785791
self.in_snapshot.set(was_in_snapshot);
786792

787-
self.projection_cache
788-
.borrow_mut()
789-
.commit(projection_cache_snapshot);
793+
self.projection_cache.borrow_mut().commit(projection_cache_snapshot);
790794
self.type_variables.borrow_mut().commit(type_snapshot);
795+
self.const_unification_table.borrow_mut().commit(const_snapshot);
791796
self.int_unification_table.borrow_mut().commit(int_snapshot);
792-
self.float_unification_table
793-
.borrow_mut()
794-
.commit(float_snapshot);
795-
self.borrow_region_constraints()
796-
.commit(region_constraints_snapshot);
797+
self.float_unification_table.borrow_mut().commit(float_snapshot);
798+
self.borrow_region_constraints().commit(region_constraints_snapshot);
797799
}
798800

799801
/// Executes `f` and commit the bindings.
@@ -918,17 +920,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
918920
predicate: &ty::PolySubtypePredicate<'tcx>,
919921
) -> Option<InferResult<'tcx, ()>> {
920922
// Subtle: it's ok to skip the binder here and resolve because
921-
// `shallow_resolve` just ignores anything that is not a type
923+
// `shallow_resolve_type` just ignores anything that is not a type
922924
// variable, and because type variable's can't (at present, at
923925
// least) capture any of the things bound by this binder.
924926
//
925927
// Really, there is no *particular* reason to do this
926-
// `shallow_resolve` here except as a
928+
// `shallow_resolve_type` here except as a
927929
// micro-optimization. Naturally I could not
928930
// resist. -nmatsakis
929931
let two_unbound_type_vars = {
930-
let a = self.shallow_resolve(predicate.skip_binder().a);
931-
let b = self.shallow_resolve(predicate.skip_binder().b);
932+
let a = self.shallow_resolve_type(predicate.skip_binder().a);
933+
let b = self.shallow_resolve_type(predicate.skip_binder().b);
932934
a.is_ty_var() && b.is_ty_var()
933935
};
934936

@@ -999,6 +1001,32 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
9991001
self.tcx.mk_ty_var(self.next_ty_var_id(true, origin))
10001002
}
10011003

1004+
pub fn next_const_var(
1005+
&self,
1006+
ty: Ty<'tcx>,
1007+
origin: ConstVariableOrigin
1008+
) -> &'tcx ty::LazyConst<'tcx> {
1009+
self.tcx.mk_const_var(self.next_const_var_id(origin), ty)
1010+
}
1011+
1012+
pub fn next_const_var_in_universe(
1013+
&self,
1014+
ty: Ty<'tcx>,
1015+
origin: ConstVariableOrigin,
1016+
universe: ty::UniverseIndex,
1017+
) -> &'tcx ty::LazyConst<'tcx> {
1018+
let vid = self.const_unification_table
1019+
.borrow_mut()
1020+
.new_var(universe, origin);
1021+
self.tcx.mk_const_var(vid, ty)
1022+
}
1023+
1024+
pub fn next_const_var_id(&self, origin: ConstVariableOrigin) -> ConstVid<'tcx> {
1025+
self.const_unification_table
1026+
.borrow_mut()
1027+
.new_var(self.universe(), origin)
1028+
}
1029+
10021030
fn next_int_var_id(&self) -> IntVid {
10031031
self.int_unification_table.borrow_mut().new_key(None)
10041032
}
@@ -1092,7 +1120,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
10921120
self.tcx.mk_ty_var(ty_var_id).into()
10931121
}
10941122
GenericParamDefKind::Const { .. } => {
1095-
unimplemented!() // FIXME(const_generics)
1123+
let const_var_id =
1124+
self.const_unification_table
1125+
.borrow_mut()
1126+
.new_var(
1127+
self.universe(),
1128+
ConstVariableOrigin::ConstParameterDefinition(span, param.name),
1129+
);
1130+
self.tcx.mk_const_var(const_var_id, self.tcx.type_of(param.def_id)).into()
10961131
}
10971132
}
10981133
}
@@ -1233,11 +1268,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
12331268
self.resolve_type_vars_if_possible(t).to_string()
12341269
}
12351270

1236-
// We have this force-inlined variant of shallow_resolve() for the one
1271+
// We have this force-inlined variant of `shallow_resolve_type` for the one
12371272
// callsite that is extremely hot. All other callsites use the normal
12381273
// variant.
12391274
#[inline(always)]
1240-
pub fn inlined_shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
1275+
pub fn inlined_shallow_resolve_type(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
12411276
match typ.sty {
12421277
ty::Infer(ty::TyVar(v)) => {
12431278
// Not entirely obvious: if `typ` is a type variable,
@@ -1253,7 +1288,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
12531288
.borrow_mut()
12541289
.probe(v)
12551290
.known()
1256-
.map(|t| self.shallow_resolve(t))
1291+
.map(|t| self.shallow_resolve_type(t))
12571292
.unwrap_or(typ)
12581293
}
12591294

@@ -1284,8 +1319,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
12841319
}
12851320
}
12861321

1287-
pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
1288-
self.inlined_shallow_resolve(typ)
1322+
pub fn shallow_resolve_type(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
1323+
self.inlined_shallow_resolve_type(typ)
12891324
}
12901325

12911326
pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid {
@@ -1323,9 +1358,60 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
13231358
r.first_unresolved
13241359
}
13251360

1326-
pub fn fully_resolve<T: TypeFoldable<'tcx>>(&self, value: &T) -> FixupResult<T> {
1361+
pub fn probe_const_var(
1362+
&self,
1363+
vid: ty::ConstVid<'tcx>
1364+
) -> Result<&'tcx ty::LazyConst<'tcx>, ty::UniverseIndex> {
1365+
use self::const_variable::ConstVariableValue;
1366+
1367+
match self.const_unification_table.borrow_mut().probe(vid) {
1368+
ConstVariableValue::Known { value } => Ok(value),
1369+
ConstVariableValue::Unknown { universe } => Err(universe),
1370+
}
1371+
}
1372+
1373+
pub fn resolve_const_var(
1374+
&self,
1375+
ct: &'tcx ty::LazyConst<'tcx>
1376+
) -> &'tcx ty::LazyConst<'tcx> {
1377+
if let ty::LazyConst::Evaluated(ty::Const {
1378+
val: ConstValue::Infer(InferConst::Var(v)),
1379+
..
1380+
}) = ct {
1381+
self.const_unification_table
1382+
.borrow_mut()
1383+
.probe(*v)
1384+
.known()
1385+
.map(|c| self.resolve_const_var(c))
1386+
.unwrap_or(ct)
1387+
} else {
1388+
ct
1389+
}
1390+
}
1391+
1392+
pub fn shallow_resolve_const(
1393+
&self,
1394+
ct: &'tcx ty::LazyConst<'tcx>
1395+
) -> &'tcx ty::LazyConst<'tcx> {
1396+
match ct {
1397+
ty::LazyConst::Evaluated(ty::Const {
1398+
val: ConstValue::Infer(InferConst::Var(vid)),
1399+
..
1400+
}) => {
1401+
self.const_unification_table
1402+
.borrow_mut()
1403+
.probe(*vid)
1404+
.known()
1405+
.map(|c| self.shallow_resolve_const(c))
1406+
.unwrap_or(ct)
1407+
}
1408+
_ => ct,
1409+
}
1410+
}
1411+
1412+
pub fn fully_resolve<T: TypeFoldable<'tcx>>(&self, value: &T) -> FixupResult<'tcx, T> {
13271413
/*!
1328-
* Attempts to resolve all type/region variables in
1414+
* Attempts to resolve all type/region/const variables in
13291415
* `value`. Region inference must have been run already (e.g.,
13301416
* by calling `resolve_regions_and_report_errors`). If some
13311417
* variable was never unified, an `Err` results.
@@ -1441,7 +1527,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
14411527
closure_substs: ty::ClosureSubsts<'tcx>,
14421528
) -> Option<ty::ClosureKind> {
14431529
let closure_kind_ty = closure_substs.closure_kind_ty(closure_def_id, self.tcx);
1444-
let closure_kind_ty = self.shallow_resolve(&closure_kind_ty);
1530+
let closure_kind_ty = self.shallow_resolve_type(&closure_kind_ty);
14451531
closure_kind_ty.to_opt_closure_kind()
14461532
}
14471533

@@ -1455,7 +1541,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
14551541
substs: ty::ClosureSubsts<'tcx>,
14561542
) -> ty::PolyFnSig<'tcx> {
14571543
let closure_sig_ty = substs.closure_sig_ty(def_id, self.tcx);
1458-
let closure_sig_ty = self.shallow_resolve(&closure_sig_ty);
1544+
let closure_sig_ty = self.shallow_resolve_type(&closure_sig_ty);
14591545
closure_sig_ty.fn_sig(self.tcx)
14601546
}
14611547

0 commit comments

Comments
 (0)