Skip to content

Commit

Permalink
Rollup merge of rust-lang#36002 - eddyb:abstract-kindness, r=nikomats…
Browse files Browse the repository at this point in the history
…akis

Combine types and regions in Substs into one interleaved list.

Previously, `Substs` would contain types and regions, in two separate vectors, for example:
```rust
<X as Trait<'a, 'b, A, B>>::method::<'p, 'q, T, U>
/* corresponds to */
Substs { regions: ['a, 'b, 'p, 'q], types: [X, A, B, T, U] }
```

This PR continues the work started in rust-lang#35605 by further removing the distinction.
A new abstraction over types and regions is introduced in the compiler, `Kind`.
Each `Kind` is a pointer (`&TyS` or `&Region`), with the lowest two bits used as a tag.
Two bits were used instead of just one (type = `0`, region = `1`) to allow adding more kinds.

`Substs` contain only a `Vec<Kind>`, with `Self` first, followed by regions and types (in the definition order):
```rust
Substs { params: [X, 'a, 'b, A, B, 'p, 'q, T, U] }
```
The resulting interleaved list has the property of being the concatenation of parameters for the (potentially) nested generic items it describes, and can be sliced back into those components:
```rust
params[0..5] = [X, 'a, 'b, A, B] // <X as Trait<'a, 'b, A, B>>
params[5..9] = ['p, 'q, T, U] // <_>::method::<'p, 'q, T, U>
```

r? @nikomatsakis
  • Loading branch information
Manishearth authored Aug 27, 2016
2 parents 1385feb + 7a8d482 commit 7a2a381
Show file tree
Hide file tree
Showing 117 changed files with 1,416 additions and 1,225 deletions.
3 changes: 2 additions & 1 deletion src/librustc/infer/bivariate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
}
}

fn regions(&mut self, a: ty::Region, _: ty::Region) -> RelateResult<'tcx, ty::Region> {
fn regions(&mut self, a: &'tcx ty::Region, _: &'tcx ty::Region)
-> RelateResult<'tcx, &'tcx ty::Region> {
Ok(a)
}

Expand Down
4 changes: 2 additions & 2 deletions src/librustc/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,8 @@ impl<'cx, 'gcx, 'tcx> ty::fold::TypeFolder<'gcx, 'tcx> for Generalizer<'cx, 'gcx
}
}

fn fold_region(&mut self, r: ty::Region) -> ty::Region {
match r {
fn fold_region(&mut self, r: &'tcx ty::Region) -> &'tcx ty::Region {
match *r {
// Never make variables for regions bound within the type itself,
// nor for erased regions.
ty::ReLateBound(..) |
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/infer/equate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
}
}

fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> {
fn regions(&mut self, a: &'tcx ty::Region, b: &'tcx ty::Region)
-> RelateResult<'tcx, &'tcx ty::Region> {
debug!("{}.regions({:?}, {:?})",
self.tag(),
a,
Expand Down
22 changes: 11 additions & 11 deletions src/librustc/infer/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
pub fn note_and_explain_region(self,
err: &mut DiagnosticBuilder,
prefix: &str,
region: ty::Region,
region: &'tcx ty::Region,
suffix: &str) {
fn item_scope_tag(item: &hir::Item) -> &'static str {
match item.node {
Expand All @@ -120,7 +120,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
Some(span))
}

let (description, span) = match region {
let (description, span) = match *region {
ty::ReScope(scope) => {
let new_string;
let unknown_scope = || {
Expand Down Expand Up @@ -405,12 +405,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}

fn free_regions_from_same_fn<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
sub: Region,
sup: Region)
sub: &'tcx Region,
sup: &'tcx Region)
-> Option<FreeRegionsFromSameFn> {
debug!("free_regions_from_same_fn(sub={:?}, sup={:?})", sub, sup);
let (scope_id, fr1, fr2) = match (sub, sup) {
(ReFree(fr1), ReFree(fr2)) => {
(&ReFree(fr1), &ReFree(fr2)) => {
if fr1.scope != fr2.scope {
return None
}
Expand Down Expand Up @@ -602,7 +602,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
fn report_generic_bound_failure(&self,
origin: SubregionOrigin<'tcx>,
bound_kind: GenericKind<'tcx>,
sub: Region)
sub: &'tcx Region)
{
// FIXME: it would be better to report the first error message
// with the span of the parameter itself, rather than the span
Expand All @@ -616,7 +616,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
format!("the associated type `{}`", p),
};

let mut err = match sub {
let mut err = match *sub {
ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => {
// Does the required lifetime have a nice name we can print?
let mut err = struct_span_err!(self.tcx.sess,
Expand Down Expand Up @@ -667,8 +667,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {

fn report_concrete_failure(&self,
origin: SubregionOrigin<'tcx>,
sub: Region,
sup: Region)
sub: &'tcx Region,
sup: &'tcx Region)
-> DiagnosticBuilder<'tcx> {
match origin {
infer::Subtype(trace) => {
Expand Down Expand Up @@ -939,9 +939,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
fn report_sub_sup_conflict(&self,
var_origin: RegionVariableOrigin,
sub_origin: SubregionOrigin<'tcx>,
sub_region: Region,
sub_region: &'tcx Region,
sup_origin: SubregionOrigin<'tcx>,
sup_region: Region) {
sup_region: &'tcx Region) {
let mut err = self.report_inference_failure(var_origin);

self.tcx.note_and_explain_region(&mut err,
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/infer/freshen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
self.infcx.tcx
}

fn fold_region(&mut self, r: ty::Region) -> ty::Region {
match r {
fn fold_region(&mut self, r: &'tcx ty::Region) -> &'tcx ty::Region {
match *r {
ty::ReEarlyBound(..) |
ty::ReLateBound(..) => {
// leave bound regions alone
Expand All @@ -99,7 +99,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
ty::ReEmpty |
ty::ReErased => {
// replace all free regions with 'erased
ty::ReErased
self.tcx().mk_region(ty::ReErased)
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/infer/glb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
lattice::super_lattice_tys(self, a, b)
}

fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> {
fn regions(&mut self, a: &'tcx ty::Region, b: &'tcx ty::Region)
-> RelateResult<'tcx, &'tcx ty::Region> {
debug!("{}.regions({:?}, {:?})",
self.tag(),
a,
Expand Down
66 changes: 36 additions & 30 deletions src/librustc/infer/higher_ranked/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
.map(|(&skol, &(br, ref regions))| {
let representative =
regions.iter()
.filter(|r| !skol_resolution_map.contains_key(r))
.filter(|&&r| !skol_resolution_map.contains_key(r))
.cloned()
.next()
.unwrap_or_else(|| { // [1]
Expand Down Expand Up @@ -268,9 +268,9 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
snapshot: &CombinedSnapshot,
debruijn: ty::DebruijnIndex,
new_vars: &[ty::RegionVid],
a_map: &FnvHashMap<ty::BoundRegion, ty::Region>,
r0: ty::Region)
-> ty::Region {
a_map: &FnvHashMap<ty::BoundRegion, &'tcx ty::Region>,
r0: &'tcx ty::Region)
-> &'tcx ty::Region {
// Regions that pre-dated the LUB computation stay as they are.
if !is_var_in_set(new_vars, r0) {
assert!(!r0.is_bound());
Expand Down Expand Up @@ -301,7 +301,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
debug!("generalize_region(r0={:?}): \
replacing with {:?}, tainted={:?}",
r0, *a_br, tainted);
return ty::ReLateBound(debruijn, *a_br);
return infcx.tcx.mk_region(ty::ReLateBound(debruijn, *a_br));
}
}

Expand Down Expand Up @@ -364,10 +364,12 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
snapshot: &CombinedSnapshot,
debruijn: ty::DebruijnIndex,
new_vars: &[ty::RegionVid],
a_map: &FnvHashMap<ty::BoundRegion, ty::Region>,
a_map: &FnvHashMap<ty::BoundRegion,
&'tcx ty::Region>,
a_vars: &[ty::RegionVid],
b_vars: &[ty::RegionVid],
r0: ty::Region) -> ty::Region {
r0: &'tcx ty::Region)
-> &'tcx ty::Region {
if !is_var_in_set(new_vars, r0) {
assert!(!r0.is_bound());
return r0;
Expand Down Expand Up @@ -419,7 +421,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {

if a_r.is_some() && b_r.is_some() && only_new_vars {
// Related to exactly one bound variable from each fn:
return rev_lookup(span, a_map, a_r.unwrap());
return rev_lookup(infcx, span, a_map, a_r.unwrap());
} else if a_r.is_none() && b_r.is_none() {
// Not related to bound variables from either fn:
assert!(!r0.is_bound());
Expand All @@ -430,13 +432,14 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
}
}

fn rev_lookup(span: Span,
a_map: &FnvHashMap<ty::BoundRegion, ty::Region>,
r: ty::Region) -> ty::Region
fn rev_lookup<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
span: Span,
a_map: &FnvHashMap<ty::BoundRegion, &'tcx ty::Region>,
r: &'tcx ty::Region) -> &'tcx ty::Region
{
for (a_br, a_r) in a_map {
if *a_r == r {
return ty::ReLateBound(ty::DebruijnIndex::new(1), *a_br);
return infcx.tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1), *a_br));
}
}
span_bug!(
Expand All @@ -445,19 +448,21 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
r);
}

fn fresh_bound_variable(infcx: &InferCtxt, debruijn: ty::DebruijnIndex) -> ty::Region {
fn fresh_bound_variable<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
debruijn: ty::DebruijnIndex)
-> &'tcx ty::Region {
infcx.region_vars.new_bound(debruijn)
}
}
}

fn var_ids<'a, 'gcx, 'tcx>(fields: &CombineFields<'a, 'gcx, 'tcx>,
map: &FnvHashMap<ty::BoundRegion, ty::Region>)
map: &FnvHashMap<ty::BoundRegion, &'tcx ty::Region>)
-> Vec<ty::RegionVid> {
map.iter()
.map(|(_, r)| match *r {
.map(|(_, &r)| match *r {
ty::ReVar(r) => { r }
r => {
_ => {
span_bug!(
fields.trace.origin.span(),
"found non-region-vid: {:?}",
Expand All @@ -467,8 +472,8 @@ fn var_ids<'a, 'gcx, 'tcx>(fields: &CombineFields<'a, 'gcx, 'tcx>,
.collect()
}

fn is_var_in_set(new_vars: &[ty::RegionVid], r: ty::Region) -> bool {
match r {
fn is_var_in_set(new_vars: &[ty::RegionVid], r: &ty::Region) -> bool {
match *r {
ty::ReVar(ref v) => new_vars.iter().any(|x| x == v),
_ => false
}
Expand All @@ -479,13 +484,13 @@ fn fold_regions_in<'a, 'gcx, 'tcx, T, F>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
mut fldr: F)
-> T
where T: TypeFoldable<'tcx>,
F: FnMut(ty::Region, ty::DebruijnIndex) -> ty::Region,
F: FnMut(&'tcx ty::Region, ty::DebruijnIndex) -> &'tcx ty::Region,
{
tcx.fold_regions(unbound_value, &mut false, |region, current_depth| {
// we should only be encountering "escaping" late-bound regions here,
// because the ones at the current level should have been replaced
// with fresh variables
assert!(match region {
assert!(match *region {
ty::ReLateBound(..) => false,
_ => true
});
Expand All @@ -497,9 +502,9 @@ fn fold_regions_in<'a, 'gcx, 'tcx, T, F>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
fn tainted_regions(&self,
snapshot: &CombinedSnapshot,
r: ty::Region,
r: &'tcx ty::Region,
directions: TaintDirections)
-> FnvHashSet<ty::Region> {
-> FnvHashSet<&'tcx ty::Region> {
self.region_vars.tainted(&snapshot.region_vars_snapshot, r, directions)
}

Expand Down Expand Up @@ -596,7 +601,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
pub fn skolemize_late_bound_regions<T>(&self,
binder: &ty::Binder<T>,
snapshot: &CombinedSnapshot)
-> (T, SkolemizationMap)
-> (T, SkolemizationMap<'tcx>)
where T : TypeFoldable<'tcx>
{
let (result, map) = self.tcx.replace_late_bound_regions(binder, |br| {
Expand All @@ -619,7 +624,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
pub fn leak_check(&self,
overly_polymorphic: bool,
span: Span,
skol_map: &SkolemizationMap,
skol_map: &SkolemizationMap<'tcx>,
snapshot: &CombinedSnapshot)
-> RelateResult<'tcx, ()>
{
Expand Down Expand Up @@ -673,7 +678,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
for &tainted_region in &incoming_taints {
// Each skolemized should only be relatable to itself
// or new variables:
match tainted_region {
match *tainted_region {
ty::ReVar(vid) => {
if new_vars.contains(&vid) {
warnings.extend(
Expand Down Expand Up @@ -742,7 +747,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
/// to the depth of the predicate, in this case 1, so that the final
/// predicate is `for<'a> &'a int : Clone`.
pub fn plug_leaks<T>(&self,
skol_map: SkolemizationMap,
skol_map: SkolemizationMap<'tcx>,
snapshot: &CombinedSnapshot,
value: &T) -> T
where T : TypeFoldable<'tcx>
Expand All @@ -755,7 +760,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
// region back to the `ty::BoundRegion` that it originally
// represented. Because `leak_check` passed, we know that
// these taint sets are mutually disjoint.
let inv_skol_map: FnvHashMap<ty::Region, ty::BoundRegion> =
let inv_skol_map: FnvHashMap<&'tcx ty::Region, ty::BoundRegion> =
skol_map
.iter()
.flat_map(|(&skol_br, &skol)| {
Expand Down Expand Up @@ -794,15 +799,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
// (which ought not to escape the snapshot, but we
// don't check that) or itself
assert!(
match r {
match *r {
ty::ReVar(_) => true,
ty::ReSkolemized(_, ref br1) => br == br1,
_ => false,
},
"leak-check would have us replace {:?} with {:?}",
r, br);

ty::ReLateBound(ty::DebruijnIndex::new(current_depth - 1), br.clone())
self.tcx.mk_region(ty::ReLateBound(
ty::DebruijnIndex::new(current_depth - 1), br.clone()))
}
}
});
Expand All @@ -826,7 +832,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
///
/// Note: popping also occurs implicitly as part of `leak_check`.
pub fn pop_skolemized(&self,
skol_map: SkolemizationMap,
skol_map: SkolemizationMap<'tcx>,
snapshot: &CombinedSnapshot)
{
debug!("pop_skolemized({:?})", skol_map);
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/infer/lub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
lattice::super_lattice_tys(self, a, b)
}

fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> {
fn regions(&mut self, a: &'tcx ty::Region, b: &'tcx ty::Region)
-> RelateResult<'tcx, &'tcx ty::Region> {
debug!("{}.regions({:?}, {:?})",
self.tag(),
a,
Expand Down
Loading

0 comments on commit 7a2a381

Please sign in to comment.