Skip to content

Commit 0887456

Browse files
committed
extend NLL universe code to have >1 placeholder within one universe
1 parent 4c2fc33 commit 0887456

File tree

11 files changed

+226
-124
lines changed

11 files changed

+226
-124
lines changed

src/librustc/infer/higher_ranked/mod.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -586,15 +586,20 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
586586
/// the [rustc guide].
587587
///
588588
/// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/hrtb.html
589-
pub fn replace_late_bound_regions_with_placeholders<T>(&self,
590-
binder: &ty::Binder<T>)
591-
-> (T, PlaceholderMap<'tcx>)
592-
where T : TypeFoldable<'tcx>
589+
pub fn replace_late_bound_regions_with_placeholders<T>(
590+
&self,
591+
binder: &ty::Binder<T>,
592+
) -> (T, PlaceholderMap<'tcx>)
593+
where
594+
T : TypeFoldable<'tcx>,
593595
{
594596
let new_universe = self.create_subuniverse();
595597

596598
let (result, map) = self.tcx.replace_late_bound_regions(binder, |br| {
597-
self.tcx.mk_region(ty::RePlaceholder(new_universe, br))
599+
self.tcx.mk_region(ty::RePlaceholder(ty::Placeholder {
600+
universe: new_universe,
601+
name: br,
602+
}))
598603
});
599604

600605
debug!("skolemize_bound_regions(binder={:?}, result={:?}, map={:?})",
@@ -758,7 +763,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
758763
assert!(
759764
match *r {
760765
ty::ReVar(_) => true,
761-
ty::RePlaceholder(_, ref br1) => br == br1,
766+
ty::RePlaceholder(index) => index.name == *br,
762767
_ => false,
763768
},
764769
"leak-check would have us replace {:?} with {:?}",

src/librustc/infer/mod.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -406,12 +406,14 @@ pub enum RegionVariableOrigin {
406406

407407
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
408408
pub enum NLLRegionVariableOrigin {
409-
// During NLL region processing, we create variables for free
410-
// regions that we encounter in the function signature and
411-
// elsewhere. This origin indices we've got one of those.
409+
/// During NLL region processing, we create variables for free
410+
/// regions that we encounter in the function signature and
411+
/// elsewhere. This origin indices we've got one of those.
412412
FreeRegion,
413413

414-
BoundRegion(ty::UniverseIndex),
414+
/// "Universal" instantiation of a higher-ranked region (e.g.,
415+
/// from a `for<'a> T` binder). Meant to represent "any region".
416+
Placeholder(ty::Placeholder),
415417

416418
Existential,
417419
}
@@ -420,7 +422,7 @@ impl NLLRegionVariableOrigin {
420422
pub fn is_universal(self) -> bool {
421423
match self {
422424
NLLRegionVariableOrigin::FreeRegion => true,
423-
NLLRegionVariableOrigin::BoundRegion(..) => true,
425+
NLLRegionVariableOrigin::Placeholder(..) => true,
424426
NLLRegionVariableOrigin::Existential => false,
425427
}
426428
}

src/librustc/infer/region_constraints/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -830,7 +830,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
830830
| ty::ReErased
831831
| ty::ReFree(..)
832832
| ty::ReEarlyBound(..) => ty::UniverseIndex::ROOT,
833-
ty::RePlaceholder(universe, _) => universe,
833+
ty::RePlaceholder(placeholder) => placeholder.universe,
834834
ty::ReClosureBound(vid) | ty::ReVar(vid) => self.var_universe(vid),
835835
ty::ReLateBound(..) => bug!("universe(): encountered bound region {:?}", region),
836836
ty::ReCanonical(..) => bug!(

src/librustc/traits/select.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1980,15 +1980,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
19801980
obligation.predicate.def_id(),
19811981
obligation.predicate.skip_binder().trait_ref.self_ty(),
19821982
|impl_def_id| {
1983-
self.probe(|this, snapshot| /* [1] */
1984-
if let Ok(placeholder_map) = this.match_impl(impl_def_id, obligation, snapshot) {
1983+
self.probe(|this, snapshot| {
1984+
if let Ok(placeholder_map) = this.match_impl(impl_def_id, obligation, snapshot)
1985+
{
19851986
candidates.vec.push(ImplCandidate(impl_def_id));
19861987

19871988
// NB: we can safely drop the placeholder map
1988-
// since we are in a probe [1]
1989+
// since we are in a probe.
19891990
mem::drop(placeholder_map);
19901991
}
1991-
);
1992+
});
19921993
},
19931994
);
19941995

src/librustc/ty/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1553,6 +1553,18 @@ impl From<u32> for UniverseIndex {
15531553
}
15541554
}
15551555

1556+
/// The "placeholder index" fully defines a placeholder region.
1557+
/// Placeholder regions are identified by both a **universe** as well
1558+
/// as a "bound-region" within that universe. The `bound_region` is
1559+
/// basically a name -- distinct bound regions within the same
1560+
/// universe are just two regions with an unknown relationship to one
1561+
/// another.
1562+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
1563+
pub struct Placeholder {
1564+
pub universe: UniverseIndex,
1565+
pub name: BoundRegion,
1566+
}
1567+
15561568
/// When type checking, we use the `ParamEnv` to track
15571569
/// details about the set of where-clauses that are in scope at this
15581570
/// particular point.

src/librustc/ty/sty.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,7 +1134,7 @@ pub enum RegionKind {
11341134

11351135
/// A placeholder region - basically the higher-ranked version of ReFree.
11361136
/// Should not exist after typeck.
1137-
RePlaceholder(ty::UniverseIndex, BoundRegion),
1137+
RePlaceholder(ty::Placeholder),
11381138

11391139
/// Empty lifetime is for data that is never accessed.
11401140
/// Bottom in the region lattice. We treat ReEmpty somewhat
@@ -1338,7 +1338,7 @@ impl RegionKind {
13381338
RegionKind::ReScope(..) => false,
13391339
RegionKind::ReStatic => true,
13401340
RegionKind::ReVar(..) => false,
1341-
RegionKind::RePlaceholder(_, br) => br.is_named(),
1341+
RegionKind::RePlaceholder(placeholder) => placeholder.name.is_named(),
13421342
RegionKind::ReEmpty => false,
13431343
RegionKind::ReErased => false,
13441344
RegionKind::ReClosureBound(..) => false,

src/librustc/util/ppaux.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -803,7 +803,7 @@ define_print! {
803803
}
804804
ty::ReLateBound(_, br) |
805805
ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
806-
ty::RePlaceholder(_, br) => {
806+
ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
807807
write!(f, "{}", br)
808808
}
809809
ty::ReScope(scope) if cx.identify_regions => {
@@ -872,8 +872,8 @@ define_print! {
872872
write!(f, "'?{}", c.index())
873873
}
874874

875-
ty::RePlaceholder(universe, ref bound_region) => {
876-
write!(f, "RePlaceholder({:?}, {:?})", universe, bound_region)
875+
ty::RePlaceholder(placeholder) => {
876+
write!(f, "RePlaceholder({:?})", placeholder)
877877
}
878878

879879
ty::ReEmpty => write!(f, "ReEmpty"),

src/librustc_mir/borrow_check/error_reporting.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1780,9 +1780,11 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
17801780
// lifetimes without names with the value `'0`.
17811781
match ty.sty {
17821782
ty::TyKind::Ref(ty::RegionKind::ReLateBound(_, br), _, _)
1783-
| ty::TyKind::Ref(ty::RegionKind::RePlaceholder(_, br), _, _) => {
1784-
with_highlight_region_for_bound_region(*br, counter, || format!("{}", ty))
1785-
}
1783+
| ty::TyKind::Ref(
1784+
ty::RegionKind::RePlaceholder(ty::Placeholder { name: br, .. }),
1785+
_,
1786+
_,
1787+
) => with_highlight_region_for_bound_region(*br, counter, || format!("{}", ty)),
17861788
_ => format!("{}", ty),
17871789
}
17881790
}
@@ -1792,7 +1794,8 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
17921794
fn get_region_name_for_ty(&self, ty: ty::Ty<'tcx>, counter: usize) -> String {
17931795
match ty.sty {
17941796
ty::TyKind::Ref(region, _, _) => match region {
1795-
ty::RegionKind::ReLateBound(_, br) | ty::RegionKind::RePlaceholder(_, br) => {
1797+
ty::RegionKind::ReLateBound(_, br)
1798+
| ty::RegionKind::RePlaceholder(ty::Placeholder { name: br, .. }) => {
17961799
with_highlight_region_for_bound_region(*br, counter, || format!("{}", region))
17971800
}
17981801
_ => format!("{}", region),

src/librustc_mir/borrow_check/nll/region_infer/mod.rs

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use super::universal_regions::UniversalRegions;
1212
use borrow_check::nll::constraints::graph::NormalConstraintGraph;
1313
use borrow_check::nll::constraints::{ConstraintSccIndex, ConstraintSet, OutlivesConstraint};
14-
use borrow_check::nll::region_infer::values::{RegionElement, ToElementIndex};
14+
use borrow_check::nll::region_infer::values::{PlaceholderIndices, RegionElement, ToElementIndex};
1515
use borrow_check::nll::type_check::free_region_relations::UniversalRegionRelations;
1616
use borrow_check::nll::type_check::Locations;
1717
use rustc::hir::def_id::DefId;
@@ -197,18 +197,21 @@ impl<'tcx> RegionInferenceContext<'tcx> {
197197
.collect();
198198

199199
// Compute the max universe used anywhere amongst the regions.
200-
let max_universe = definitions
200+
let placeholder_indices: PlaceholderIndices = definitions
201201
.iter()
202-
.map(|d| d.universe)
203-
.max()
204-
.unwrap_or(ty::UniverseIndex::ROOT);
202+
.filter_map(|d| match d.origin {
203+
NLLRegionVariableOrigin::Placeholder(placeholder) => Some(placeholder),
204+
_ => None,
205+
})
206+
.collect();
205207

206208
let constraints = Rc::new(outlives_constraints); // freeze constraints
207209
let constraint_graph = Rc::new(constraints.graph(definitions.len()));
208210
let fr_static = universal_regions.fr_static;
209211
let constraint_sccs = Rc::new(constraints.compute_sccs(&constraint_graph, fr_static));
210212

211-
let mut scc_values = RegionValues::new(elements, universal_regions.len(), max_universe);
213+
let mut scc_values =
214+
RegionValues::new(elements, universal_regions.len(), placeholder_indices);
212215

213216
for region in liveness_constraints.rows() {
214217
let scc = constraint_sccs.scc(region);
@@ -329,17 +332,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
329332
self.scc_values.add_element(scc, variable);
330333
}
331334

332-
NLLRegionVariableOrigin::BoundRegion(ui) => {
333-
// Each placeholder region X outlives its
334-
// associated universe but nothing else. Every
335-
// placeholder region is always in a universe that
336-
// contains `ui` -- but when placeholder regions
337-
// are placed into an SCC, that SCC may include
338-
// things from other universes that do not include
339-
// `ui`.
335+
NLLRegionVariableOrigin::Placeholder(placeholder) => {
336+
// Each placeholder region is only visible from
337+
// its universe `ui` and its superuniverses. So we
338+
// can't just add it into `scc` unless the
339+
// universe of the scc can name this region.
340340
let scc_universe = self.scc_universes[scc];
341-
if ui.is_subset_of(scc_universe) {
342-
self.scc_values.add_element(scc, ui);
341+
if placeholder.universe.is_subset_of(scc_universe) {
342+
self.scc_values.add_element(scc, placeholder);
343343
} else {
344344
self.add_incompatible_universe(scc);
345345
}
@@ -544,8 +544,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
544544
// B's value, and check whether all of them are nameable
545545
// from universe_a
546546
self.scc_values
547-
.subuniverses_contained_in(scc_b)
548-
.all(|u| u.is_subset_of(universe_a))
547+
.placeholders_contained_in(scc_b)
548+
.all(|p| p.universe.is_subset_of(universe_a))
549549
}
550550

551551
/// Extend `scc` so that it can outlive some placeholder region
@@ -1076,8 +1076,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
10761076
);
10771077
}
10781078

1079-
NLLRegionVariableOrigin::BoundRegion(universe) => {
1080-
self.check_bound_universal_region(infcx, mir, mir_def_id, fr, universe);
1079+
NLLRegionVariableOrigin::Placeholder(placeholder) => {
1080+
self.check_bound_universal_region(infcx, mir, mir_def_id, fr, placeholder);
10811081
}
10821082

10831083
NLLRegionVariableOrigin::Existential => {
@@ -1113,7 +1113,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
11131113
assert!(self.scc_universes[longer_fr_scc] == ty::UniverseIndex::ROOT);
11141114
debug_assert!(
11151115
self.scc_values
1116-
.subuniverses_contained_in(longer_fr_scc)
1116+
.placeholders_contained_in(longer_fr_scc)
11171117
.next()
11181118
.is_none()
11191119
);
@@ -1181,9 +1181,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
11811181
mir: &Mir<'tcx>,
11821182
_mir_def_id: DefId,
11831183
longer_fr: RegionVid,
1184-
universe: ty::UniverseIndex,
1184+
placeholder: ty::Placeholder,
11851185
) {
1186-
debug!("check_bound_universal_region(fr={:?})", longer_fr);
1186+
debug!(
1187+
"check_bound_universal_region(fr={:?}, placeholder={:?})",
1188+
longer_fr, placeholder,
1189+
);
11871190

11881191
let longer_fr_scc = self.constraint_sccs.scc(longer_fr);
11891192

@@ -1196,7 +1199,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
11961199
.find(|element| match element {
11971200
RegionElement::Location(_) => true,
11981201
RegionElement::RootUniversalRegion(_) => true,
1199-
RegionElement::SubUniversalRegion(ui) => *ui != universe,
1202+
RegionElement::PlaceholderRegion(placeholder1) => placeholder != *placeholder1,
12001203
})
12011204
} {
12021205
Some(v) => v,
@@ -1207,10 +1210,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
12071210
let error_region = match error_element {
12081211
RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l),
12091212
RegionElement::RootUniversalRegion(r) => r,
1210-
RegionElement::SubUniversalRegion(error_ui) => self.definitions
1213+
RegionElement::PlaceholderRegion(error_placeholder) => self.definitions
12111214
.iter_enumerated()
12121215
.filter_map(|(r, definition)| match definition.origin {
1213-
NLLRegionVariableOrigin::BoundRegion(ui) if error_ui == ui => Some(r),
1216+
NLLRegionVariableOrigin::Placeholder(p) if p == error_placeholder => Some(r),
12141217
_ => None,
12151218
})
12161219
.next()

0 commit comments

Comments
 (0)