Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add const generics to infer (and transitive dependencies) #59008

Merged
merged 47 commits into from
May 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
f1c83de
Add `consts` to `TypeRelation`
varkor Mar 8, 2019
cafa10d
Define `super_relate_consts`
varkor Mar 8, 2019
2254727
Add `ConstError`
varkor Mar 8, 2019
77447de
Add const_variable.rs
varkor Mar 8, 2019
d7fdeff
Add generic consts to `BottomUpFolder`
varkor Mar 8, 2019
0728b62
Add `ct_err`
varkor Mar 8, 2019
14f906f
Define `canonicalize_const_var`
varkor Mar 8, 2019
d4e0951
Add `CanonicalVarKind::Const`
varkor Mar 8, 2019
05ac3ac
Define `super_combine_consts`
varkor Mar 8, 2019
b9b9994
Define `const_unification_error`
varkor Mar 8, 2019
7d71a1c
Add const generics to unification tables
varkor Mar 8, 2019
bfc39b9
Implement TypeRelation::consts
varkor Mar 8, 2019
69423b3
Add stubs for `fold_const`
varkor Mar 8, 2019
d113ff8
Handle generic consts in relate and infer
varkor Mar 8, 2019
3f675ab
Drive-by comment fixes
varkor Mar 8, 2019
ed3dae4
Rename *shallow_resolve to *shallow_resolve_type
varkor Mar 8, 2019
ef1b2ac
Remove `fold_const` override for `ReverseMapper`
varkor Mar 8, 2019
7bf175f
impl fold_const for RegionFudger
yodaldevoid Mar 1, 2019
bd2fa22
Rename mk_infer to mk_ty_infer
yodaldevoid Mar 1, 2019
e965b75
impl mk_const_infer
yodaldevoid Mar 1, 2019
c13aa09
impl fold_const for TypeFreshener
yodaldevoid Mar 1, 2019
57d3a5a
impl visit_const for HasEscapingVarsVisitor
yodaldevoid Mar 1, 2019
fa394c2
impl fold_const for Shifter
yodaldevoid Mar 1, 2019
cf1a719
Implement fold_const for BoundVarReplacer
varkor Mar 9, 2019
245a474
Inline ConstError into TypeError
varkor Mar 12, 2019
f5712d2
Add `ConstValue::Placeholder`
varkor Mar 12, 2019
e70797b
Add `PlaceholderConst`
varkor Mar 12, 2019
2308d2d
Handle `ConstValue::Placeholder` in `canonicalizer`
varkor Mar 12, 2019
c888af5
Replace ConstVariableTable with UnificationTable
varkor Mar 13, 2019
fc16b0a
Fix rebase from LazyConst removal
varkor Mar 18, 2019
d8b9387
Take ConstValue::Placeholder into account in new locations
varkor Mar 18, 2019
f241693
Fix missing parenthesis
varkor Mar 18, 2019
972e254
Implement const generics for `InferenceFudger`
varkor Mar 27, 2019
5cf45bc
Fix rebase issue
varkor Apr 17, 2019
67176f7
Add `const-types` test
varkor Apr 17, 2019
97c0c66
Remove spurious assertion
varkor Apr 17, 2019
b872e63
Fix known-known const unification case
varkor Apr 17, 2019
d8b1ddb
Fix unused variable warning
varkor Apr 17, 2019
388f823
Correct name of constrained_generic_params alias
varkor Apr 22, 2019
beb2f84
Resolve FIXME in probe.rs
varkor Apr 22, 2019
a29eca5
Fix issue with const params in operand.rs
varkor Apr 22, 2019
c7deb5b
Add a test for const arguments
varkor Apr 22, 2019
16d6ee3
Fold const in writeback
varkor Apr 23, 2019
a188850
Add a test for incorrect numbers of const args
varkor Apr 23, 2019
1369132
Add a test for const args that cannot be inferred
varkor Apr 23, 2019
541de81
Create ShallowResolver
varkor Apr 30, 2019
a68ed06
Split `ct_err` out into `CommonConsts`
varkor May 1, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 86 additions & 3 deletions src/librustc/infer/canonical/canonicalizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ use crate::infer::canonical::{
OriginalQueryValues,
};
use crate::infer::InferCtxt;
use crate::mir::interpret::ConstValue;
use std::sync::atomic::Ordering;
use crate::ty::fold::{TypeFoldable, TypeFolder};
use crate::ty::subst::Kind;
use crate::ty::{self, BoundVar, Lift, List, Ty, TyCtxt, TypeFlags};
use crate::ty::{self, BoundVar, InferConst, Lift, List, Ty, TyCtxt, TypeFlags};
use crate::ty::flags::FlagComputation;

use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::indexed_vec::Idx;
Expand Down Expand Up @@ -432,6 +434,61 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
}
}
}

fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
match ct.val {
ConstValue::Infer(InferConst::Var(vid)) => {
debug!("canonical: const var found with vid {:?}", vid);
match self.infcx.unwrap().probe_const_var(vid) {
Ok(c) => {
debug!("(resolved to {:?})", c);
return self.fold_const(c);
}

// `ConstVar(vid)` is unresolved, track its universe index in the
// canonicalized result
Err(mut ui) => {
if !self.infcx.unwrap().tcx.sess.opts.debugging_opts.chalk {
// FIXME: perf problem described in #55921.
ui = ty::UniverseIndex::ROOT;
}
return self.canonicalize_const_var(
CanonicalVarInfo {
kind: CanonicalVarKind::Const(ui),
},
ct,
);
}
}
}
ConstValue::Infer(InferConst::Fresh(_)) => {
bug!("encountered a fresh const during canonicalization")
}
ConstValue::Infer(InferConst::Canonical(debruijn, _)) => {
if debruijn >= self.binder_index {
bug!("escaping bound type during canonicalization")
} else {
return ct;
}
}
ConstValue::Placeholder(placeholder) => {
return self.canonicalize_const_var(
CanonicalVarInfo {
kind: CanonicalVarKind::PlaceholderConst(placeholder),
},
ct,
);
}
_ => {}
}

let flags = FlagComputation::for_const(ct);
if flags.intersects(self.needs_canonical_flags) {
ct.super_fold_with(self)
} else {
ct
}
}
}

impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
Expand All @@ -450,11 +507,13 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
let needs_canonical_flags = if canonicalize_region_mode.any() {
TypeFlags::KEEP_IN_LOCAL_TCX |
TypeFlags::HAS_FREE_REGIONS | // `HAS_RE_PLACEHOLDER` implies `HAS_FREE_REGIONS`
TypeFlags::HAS_TY_PLACEHOLDER
TypeFlags::HAS_TY_PLACEHOLDER |
TypeFlags::HAS_CT_PLACEHOLDER
} else {
TypeFlags::KEEP_IN_LOCAL_TCX |
TypeFlags::HAS_RE_PLACEHOLDER |
TypeFlags::HAS_TY_PLACEHOLDER
TypeFlags::HAS_TY_PLACEHOLDER |
TypeFlags::HAS_CT_PLACEHOLDER
};

let gcx = tcx.global_tcx();
Expand Down Expand Up @@ -633,4 +692,28 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
self.tcx().mk_ty(ty::Bound(self.binder_index, var.into()))
}
}

/// Given a type variable `const_var` of the given kind, first check
/// if `const_var` is bound to anything; if so, canonicalize
/// *that*. Otherwise, create a new canonical variable for
/// `const_var`.
fn canonicalize_const_var(
&mut self,
info: CanonicalVarInfo,
const_var: &'tcx ty::Const<'tcx>
) -> &'tcx ty::Const<'tcx> {
let infcx = self.infcx.expect("encountered const-var without infcx");
let bound_to = infcx.resolve_const_var(const_var);
if bound_to != const_var {
self.fold_const(bound_to)
} else {
let var = self.canonical_var(info, const_var.into());
self.tcx().mk_const(
ty::Const {
val: ConstValue::Infer(InferConst::Canonical(self.binder_index, var.into())),
ty: const_var.ty,
}
)
}
}
}
51 changes: 47 additions & 4 deletions src/librustc/infer/canonical/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
//!
//! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html

use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin};
use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin, ConstVariableOrigin};
use crate::mir::interpret::ConstValue;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc_macros::HashStable;
use serialize::UseSpecializedDecodable;
Expand All @@ -30,7 +31,7 @@ use std::ops::Index;
use syntax::source_map::Span;
use crate::ty::fold::TypeFoldable;
use crate::ty::subst::Kind;
use crate::ty::{self, BoundVar, Lift, List, Region, TyCtxt};
use crate::ty::{self, BoundVar, InferConst, Lift, List, Region, TyCtxt};

mod canonicalizer;

Expand Down Expand Up @@ -115,6 +116,8 @@ impl CanonicalVarInfo {
CanonicalVarKind::PlaceholderTy(_) => false,
CanonicalVarKind::Region(_) => true,
CanonicalVarKind::PlaceholderRegion(..) => false,
CanonicalVarKind::Const(_) => true,
CanonicalVarKind::PlaceholderConst(_) => false,
}
}
}
Expand All @@ -137,6 +140,12 @@ pub enum CanonicalVarKind {
/// are solving a goal like `for<'a> T: Foo<'a>` to represent the
/// bound region `'a`.
PlaceholderRegion(ty::PlaceholderRegion),

/// Some kind of const inference variable.
Const(ty::UniverseIndex),
varkor marked this conversation as resolved.
Show resolved Hide resolved

/// A "placeholder" that represents "any const".
PlaceholderConst(ty::PlaceholderConst),
}

impl CanonicalVarKind {
Expand All @@ -150,6 +159,8 @@ impl CanonicalVarKind {
CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe,
CanonicalVarKind::Region(ui) => ui,
CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe,
CanonicalVarKind::Const(ui) => ui,
CanonicalVarKind::PlaceholderConst(placeholder) => placeholder.universe,
}
}
}
Expand Down Expand Up @@ -388,6 +399,33 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
};
self.tcx.mk_region(ty::RePlaceholder(placeholder_mapped)).into()
}

CanonicalVarKind::Const(ui) => {
self.next_const_var_in_universe(
self.next_ty_var_in_universe(
TypeVariableOrigin::MiscVariable(span),
universe_map(ui),
),
ConstVariableOrigin::MiscVariable(span),
universe_map(ui),
).into()
}

CanonicalVarKind::PlaceholderConst(
ty::PlaceholderConst { universe, name },
) => {
let universe_mapped = universe_map(universe);
let placeholder_mapped = ty::PlaceholderConst {
universe: universe_mapped,
name,
};
self.tcx.mk_const(
ty::Const {
val: ConstValue::Placeholder(placeholder_mapped),
ty: self.tcx.types.err, // FIXME(const_generics)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like PlaceholderConst should contain the type.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it probably should. The reason I didn't do it earlier was it ended up propagating <'tcx> everywhere and I wanted to make sure it was definitely necessary before going down that route.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I attempted propagating <'tcx> around when originally adding CanonicalVarKind::Const and found it to be impossible because CanonicalVarInfos are allocated in the global arena.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sound like we need to bother @nikomatsakis.

But also, aren't const types supposed to be always be "global"?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK, types are only global after they have been lifted and their dependencies on type parameters and such are taken care of.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type parameters are "global" in this sense, only inference variables aren't.
I'm saying that I don't think we should ever have a constant value in the type system with an uninferred type.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. Something feels wrong here indeed. I'm trying too put my finger on what it is. I guess in short I don't like the idea of there being a type in the canonical-var-info -- I feel like types should in the canonicalized value.

I think what I would expect is that the placeholder doesn't replace the entire ty::Const, but rather just the ConstValue. In this way, it can be instantiated without needing the type.

(Similarly, in the existential case that appears above, you wouldn't make a "Fresh type variable" to represent its type -- that also seems wrong.)

}
).into()
}
}
}
}
Expand Down Expand Up @@ -443,8 +481,13 @@ impl<'tcx> CanonicalVarValues<'tcx> {
UnpackedKind::Lifetime(..) => tcx.mk_region(
ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(i))
).into(),
UnpackedKind::Const(..) => {
unimplemented!() // FIXME(const_generics)
UnpackedKind::Const(ct) => {
tcx.mk_const(ty::Const {
ty: ct.ty,
val: ConstValue::Infer(
InferConst::Canonical(ty::INNERMOST, ty::BoundVar::from_u32(i))
),
}).into()
}
})
.collect()
Expand Down
16 changes: 13 additions & 3 deletions src/librustc/infer/canonical/query_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::infer::canonical::{
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
use crate::infer::InferCtxtBuilder;
use crate::infer::{InferCtxt, InferOk, InferResult};
use crate::mir::interpret::ConstValue;
use rustc_data_structures::indexed_vec::Idx;
use rustc_data_structures::indexed_vec::IndexVec;
use std::fmt::Debug;
Expand All @@ -25,7 +26,7 @@ use crate::traits::TraitEngine;
use crate::traits::{Obligation, ObligationCause, PredicateObligation};
use crate::ty::fold::TypeFoldable;
use crate::ty::subst::{Kind, UnpackedKind};
use crate::ty::{self, BoundVar, Lift, Ty, TyCtxt};
use crate::ty::{self, BoundVar, InferConst, Lift, Ty, TyCtxt};
use crate::util::captures::Captures;

impl<'cx, 'gcx, 'tcx> InferCtxtBuilder<'cx, 'gcx, 'tcx> {
Expand Down Expand Up @@ -479,8 +480,17 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
opt_values[br.assert_bound_var()] = Some(*original_value);
}
}
UnpackedKind::Const(..) => {
unimplemented!() // FIXME(const_generics)
UnpackedKind::Const(result_value) => {
if let ty::Const {
val: ConstValue::Infer(InferConst::Canonical(debrujin, b)),
..
} = result_value {
// ...in which case we would set `canonical_vars[0]` to `Some(const X)`.

// We only allow a `ty::INNERMOST` index in substitutions.
assert_eq!(*debrujin, ty::INNERMOST);
opt_values[*b] = Some(*original_value);
}
}
}
}
Expand Down
9 changes: 8 additions & 1 deletion src/librustc/infer/canonical/substitute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ where
}
};

tcx.replace_escaping_bound_vars(value, fld_r, fld_t).0
let fld_c = |bound_ct: ty::BoundVar, _| {
match var_values.var_values[bound_ct].unpack() {
UnpackedKind::Const(ct) => ct,
c => bug!("{:?} is a const but value is {:?}", bound_ct, c),
}
};

tcx.replace_escaping_bound_vars(value, fld_r, fld_t, fld_c).0
}
}
Loading