Skip to content

Commit bfbf837

Browse files
committed
Auto merge of #52488 - nikomatsakis:nll-issue-48071-universe-and-sub, r=pnkfelix
introduce universes to NLL type check This branch aims to fix #48071 and also advance chalk integration a bit at the same time. It re-implements the subtyping/type-equating check so that NLL doesn't "piggy back" on the subtyping code of the old type checker. This new code uses the "universe-based" approach to handling higher-ranked lifetimes, which sidesteps some of the limitations of the current "leak-based" scheme. This avoids the ICE in #48071. At the same time, I aim for this to potentially be a kind of optimization. This NLL code is (currently) not cached, but it also generates constraints without doing as much instantiation, substitution, and folding. Right now, though, it still piggy backs on the `relate_tys` trait, which is a bit unfortunate -- it means we are doing more hashing and things than we have to. I want to measure the see the perf. Refactoring that trait is something I'd prefer to leave for follow-up work. r? @pnkfelix -- but I want to measure perf etc first
2 parents fefe816 + ce576ac commit bfbf837

File tree

79 files changed

+2044
-766
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+2044
-766
lines changed

src/Cargo.lock

+7-7
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ dependencies = [
8787

8888
[[package]]
8989
name = "atty"
90-
version = "0.2.11"
90+
version = "0.2.10"
9191
source = "registry+https://github.com/rust-lang/crates.io-index"
9292
dependencies = [
9393
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -187,7 +187,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
187187
name = "cargo"
188188
version = "0.30.0"
189189
dependencies = [
190-
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
190+
"atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
191191
"bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
192192
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
193193
"core-foundation 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -303,7 +303,7 @@ version = "2.32.0"
303303
source = "registry+https://github.com/rust-lang/crates.io-index"
304304
dependencies = [
305305
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
306-
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
306+
"atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
307307
"bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
308308
"strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
309309
"textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -622,7 +622,7 @@ name = "env_logger"
622622
version = "0.5.10"
623623
source = "registry+https://github.com/rust-lang/crates.io-index"
624624
dependencies = [
625-
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
625+
"atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
626626
"humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
627627
"log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
628628
"regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1844,7 +1844,7 @@ name = "rustc-ap-rustc_errors"
18441844
version = "182.0.0"
18451845
source = "registry+https://github.com/rust-lang/crates.io-index"
18461846
dependencies = [
1847-
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
1847+
"atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
18481848
"rustc-ap-rustc_data_structures 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
18491849
"rustc-ap-serialize 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
18501850
"rustc-ap-syntax_pos 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2097,7 +2097,7 @@ dependencies = [
20972097
name = "rustc_errors"
20982098
version = "0.0.0"
20992099
dependencies = [
2100-
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
2100+
"atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
21012101
"rustc_data_structures 0.0.0",
21022102
"serialize 0.0.0",
21032103
"syntax_pos 0.0.0",
@@ -3056,7 +3056,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
30563056
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
30573057
"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
30583058
"checksum assert_cli 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98589b0e465a6c510d95fceebd365bb79bedece7f6e18a480897f2015f85ec51"
3059-
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
3059+
"checksum atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2fc4a1aa4c24c0718a250f0681885c1af91419d242f29eb8f2ab28502d80dbd1"
30603060
"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a"
30613061
"checksum backtrace-sys 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "bff67d0c06556c0b8e6b5f090f0eac52d950d9dfd1d35ba04e4ca3543eaf6a7e"
30623062
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"

src/librustc/dep_graph/graph.rs

-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ pub struct DepGraph {
3939
fingerprints: Lrc<Lock<IndexVec<DepNodeIndex, Fingerprint>>>
4040
}
4141

42-
4342
newtype_index!(DepNodeIndex);
4443

4544
impl DepNodeIndex {

src/librustc/infer/higher_ranked/mod.rs

+12
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
617617
debug!("leak_check: skol_map={:?}",
618618
skol_map);
619619

620+
// If the user gave `-Zno-leak-check`, then skip the leak
621+
// check completely. This is wildly unsound and also not
622+
// unlikely to cause an ICE or two. It is intended for use
623+
// only during a transition period, in which the MIR typeck
624+
// uses the "universe-style" check, and the rest of typeck
625+
// uses the more conservative leak check. Since the leak
626+
// check is more conservative, we can't test the
627+
// universe-style check without disabling it.
628+
if self.tcx.sess.opts.debugging_opts.no_leak_check {
629+
return Ok(());
630+
}
631+
620632
let new_vars = self.region_vars_confined_to_snapshot(snapshot);
621633
for (&skol_br, &skol) in skol_map {
622634
// The inputs to a skolemized variable can only

src/librustc/infer/mod.rs

+28-1
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,23 @@ pub enum NLLRegionVariableOrigin {
377377
// elsewhere. This origin indices we've got one of those.
378378
FreeRegion,
379379

380-
Inferred(::mir::visit::TyContext),
380+
BoundRegion(ty::UniverseIndex),
381+
382+
Existential,
383+
}
384+
385+
impl NLLRegionVariableOrigin {
386+
pub fn is_universal(self) -> bool {
387+
match self {
388+
NLLRegionVariableOrigin::FreeRegion => true,
389+
NLLRegionVariableOrigin::BoundRegion(..) => true,
390+
NLLRegionVariableOrigin::Existential => false,
391+
}
392+
}
393+
394+
pub fn is_existential(self) -> bool {
395+
!self.is_universal()
396+
}
381397
}
382398

383399
#[derive(Copy, Clone, Debug)]
@@ -1381,6 +1397,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
13811397
fn universe(&self) -> ty::UniverseIndex {
13821398
self.universe.get()
13831399
}
1400+
1401+
/// Create and return a new subunivese of the current universe;
1402+
/// update `self.universe` to that new subuniverse. At present,
1403+
/// used only in the NLL subtyping code, which uses the new
1404+
/// universe-based scheme instead of the more limited leak-check
1405+
/// scheme.
1406+
pub fn create_subuniverse(&self) -> ty::UniverseIndex {
1407+
let u = self.universe.get().subuniverse();
1408+
self.universe.set(u);
1409+
u
1410+
}
13841411
}
13851412

13861413
impl<'a, 'gcx, 'tcx> TypeTrace<'tcx> {

src/librustc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
#![feature(trusted_len)]
7070
#![feature(vec_remove_item)]
7171
#![feature(catch_expr)]
72+
#![feature(step_trait)]
7273
#![feature(integer_atomics)]
7374
#![feature(test)]
7475
#![feature(in_band_lifetimes)]

src/librustc/mir/traversal.rs

+6-7
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
// except according to those terms.
1010

1111
use rustc_data_structures::bitvec::BitVector;
12-
use rustc_data_structures::indexed_vec::Idx;
1312

1413
use super::*;
1514

@@ -33,7 +32,7 @@ use super::*;
3332
#[derive(Clone)]
3433
pub struct Preorder<'a, 'tcx: 'a> {
3534
mir: &'a Mir<'tcx>,
36-
visited: BitVector,
35+
visited: BitVector<BasicBlock>,
3736
worklist: Vec<BasicBlock>,
3837
}
3938

@@ -58,7 +57,7 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> {
5857

5958
fn next(&mut self) -> Option<(BasicBlock, &'a BasicBlockData<'tcx>)> {
6059
while let Some(idx) = self.worklist.pop() {
61-
if !self.visited.insert(idx.index()) {
60+
if !self.visited.insert(idx) {
6261
continue;
6362
}
6463

@@ -107,7 +106,7 @@ impl<'a, 'tcx> ExactSizeIterator for Preorder<'a, 'tcx> {}
107106
/// A Postorder traversal of this graph is `D B C A` or `D C B A`
108107
pub struct Postorder<'a, 'tcx: 'a> {
109108
mir: &'a Mir<'tcx>,
110-
visited: BitVector,
109+
visited: BitVector<BasicBlock>,
111110
visit_stack: Vec<(BasicBlock, Successors<'a>)>
112111
}
113112

@@ -123,7 +122,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
123122
let data = &po.mir[root];
124123

125124
if let Some(ref term) = data.terminator {
126-
po.visited.insert(root.index());
125+
po.visited.insert(root);
127126
po.visit_stack.push((root, term.successors()));
128127
po.traverse_successor();
129128
}
@@ -190,8 +189,8 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
190189
break;
191190
};
192191

193-
if self.visited.insert(bb.index()) {
194-
if let Some(ref term) = self.mir[bb].terminator {
192+
if self.visited.insert(bb) {
193+
if let Some(term) = &self.mir[bb].terminator {
195194
self.visit_stack.push((bb, term.successors()));
196195
}
197196
}

src/librustc/session/config.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1353,6 +1353,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
13531353
"generate build artifacts that are compatible with linker-based LTO."),
13541354
no_parallel_llvm: bool = (false, parse_bool, [UNTRACKED],
13551355
"don't run LLVM in parallel (while keeping codegen-units and ThinLTO)"),
1356+
no_leak_check: bool = (false, parse_bool, [UNTRACKED],
1357+
"disables the 'leak check' for subtyping; unsound, but useful for tests"),
13561358
}
13571359

13581360
pub fn default_lib_output() -> CrateType {

src/librustc/ty/mod.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -1481,14 +1481,27 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
14811481
/// type name in a non-zero universe is a skolemized type -- an
14821482
/// idealized representative of "types in general" that we use for
14831483
/// checking generic functions.
1484-
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
1484+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
14851485
pub struct UniverseIndex(u32);
14861486

14871487
impl UniverseIndex {
14881488
/// The root universe, where things that the user defined are
14891489
/// visible.
14901490
pub const ROOT: Self = UniverseIndex(0);
14911491

1492+
/// The "max universe" -- this isn't really a valid universe, but
1493+
/// it's useful sometimes as a "starting value" when you are
1494+
/// taking the minimum of a (non-empty!) set of universes.
1495+
pub const MAX: Self = UniverseIndex(::std::u32::MAX);
1496+
1497+
/// Creates a universe index from the given integer. Not to be
1498+
/// used lightly lest you pick a bad value. But sometimes we
1499+
/// convert universe indicies into integers and back for various
1500+
/// reasons.
1501+
pub fn from_u32(index: u32) -> Self {
1502+
UniverseIndex(index)
1503+
}
1504+
14921505
/// A "subuniverse" corresponds to being inside a `forall` quantifier.
14931506
/// So, for example, suppose we have this type in universe `U`:
14941507
///
@@ -1504,6 +1517,11 @@ impl UniverseIndex {
15041517
UniverseIndex(self.0.checked_add(1).unwrap())
15051518
}
15061519

1520+
/// True if the names in this universe are a subset of the names in `other`.
1521+
pub fn is_subset_of(self, other: UniverseIndex) -> bool {
1522+
self.0 <= other.0
1523+
}
1524+
15071525
pub fn as_u32(&self) -> u32 {
15081526
self.0
15091527
}
@@ -1513,6 +1531,12 @@ impl UniverseIndex {
15131531
}
15141532
}
15151533

1534+
impl fmt::Debug for UniverseIndex {
1535+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1536+
write!(fmt, "U{}", self.as_u32())
1537+
}
1538+
}
1539+
15161540
impl From<u32> for UniverseIndex {
15171541
fn from(index: u32) -> Self {
15181542
UniverseIndex(index)

src/librustc_codegen_llvm/debuginfo/create_scope_map.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ pub fn create_mir_scopes(cx: &CodegenCx, mir: &Mir, debug_context: &FunctionDebu
6565
let mut has_variables = BitVector::new(mir.source_scopes.len());
6666
for var in mir.vars_iter() {
6767
let decl = &mir.local_decls[var];
68-
has_variables.insert(decl.visibility_scope.index());
68+
has_variables.insert(decl.visibility_scope);
6969
}
7070

7171
// Instantiate all scopes.
@@ -79,7 +79,7 @@ pub fn create_mir_scopes(cx: &CodegenCx, mir: &Mir, debug_context: &FunctionDebu
7979

8080
fn make_mir_scope(cx: &CodegenCx,
8181
mir: &Mir,
82-
has_variables: &BitVector,
82+
has_variables: &BitVector<SourceScope>,
8383
debug_context: &FunctionDebugContextData,
8484
scope: SourceScope,
8585
scopes: &mut IndexVec<SourceScope, MirDebugScope>) {
@@ -102,7 +102,7 @@ fn make_mir_scope(cx: &CodegenCx,
102102
return;
103103
};
104104

105-
if !has_variables.contains(scope.index()) {
105+
if !has_variables.contains(scope) {
106106
// Do not create a DIScope if there are no variables
107107
// defined in this MIR Scope, to avoid debuginfo bloat.
108108

src/librustc_codegen_llvm/mir/analyze.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use rustc::ty::layout::LayoutOf;
2222
use type_of::LayoutLlvmExt;
2323
use super::FunctionCx;
2424

25-
pub fn non_ssa_locals<'a, 'tcx>(fx: &FunctionCx<'a, 'tcx>) -> BitVector {
25+
pub fn non_ssa_locals<'a, 'tcx>(fx: &FunctionCx<'a, 'tcx>) -> BitVector<mir::Local> {
2626
let mir = fx.mir;
2727
let mut analyzer = LocalAnalyzer::new(fx);
2828

@@ -54,7 +54,7 @@ pub fn non_ssa_locals<'a, 'tcx>(fx: &FunctionCx<'a, 'tcx>) -> BitVector {
5454
struct LocalAnalyzer<'mir, 'a: 'mir, 'tcx: 'a> {
5555
fx: &'mir FunctionCx<'a, 'tcx>,
5656
dominators: Dominators<mir::BasicBlock>,
57-
non_ssa_locals: BitVector,
57+
non_ssa_locals: BitVector<mir::Local>,
5858
// The location of the first visited direct assignment to each
5959
// local, or an invalid location (out of bounds `block` index).
6060
first_assignment: IndexVec<mir::Local, Location>
@@ -90,7 +90,7 @@ impl<'mir, 'a, 'tcx> LocalAnalyzer<'mir, 'a, 'tcx> {
9090

9191
fn not_ssa(&mut self, local: mir::Local) {
9292
debug!("marking {:?} as non-SSA", local);
93-
self.non_ssa_locals.insert(local.index());
93+
self.non_ssa_locals.insert(local);
9494
}
9595

9696
fn assign(&mut self, local: mir::Local, location: Location) {

src/librustc_codegen_llvm/mir/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ pub fn codegen_mir<'a, 'tcx: 'a>(
268268
let debug_scope = fx.scopes[decl.visibility_scope];
269269
let dbg = debug_scope.is_valid() && bx.sess().opts.debuginfo == FullDebugInfo;
270270

271-
if !memory_locals.contains(local.index()) && !dbg {
271+
if !memory_locals.contains(local) && !dbg {
272272
debug!("alloc: {:?} ({}) -> operand", local, name);
273273
return LocalRef::new_operand(bx.cx, layout);
274274
}
@@ -291,7 +291,7 @@ pub fn codegen_mir<'a, 'tcx: 'a>(
291291
debug!("alloc: {:?} (return place) -> place", local);
292292
let llretptr = llvm::get_param(llfn, 0);
293293
LocalRef::Place(PlaceRef::new_sized(llretptr, layout, layout.align))
294-
} else if memory_locals.contains(local.index()) {
294+
} else if memory_locals.contains(local) {
295295
debug!("alloc: {:?} -> place", local);
296296
LocalRef::Place(PlaceRef::alloca(&bx, layout, &format!("{:?}", local)))
297297
} else {
@@ -415,7 +415,7 @@ fn create_funclets<'a, 'tcx>(
415415
fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
416416
fx: &FunctionCx<'a, 'tcx>,
417417
scopes: &IndexVec<mir::SourceScope, debuginfo::MirDebugScope>,
418-
memory_locals: &BitVector)
418+
memory_locals: &BitVector<mir::Local>)
419419
-> Vec<LocalRef<'tcx>> {
420420
let mir = fx.mir;
421421
let tcx = bx.tcx();
@@ -487,7 +487,7 @@ fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
487487
llarg_idx += 1;
488488
}
489489

490-
if arg_scope.is_none() && !memory_locals.contains(local.index()) {
490+
if arg_scope.is_none() && !memory_locals.contains(local) {
491491
// We don't have to cast or keep the argument in the alloca.
492492
// FIXME(eddyb): We should figure out how to use llvm.dbg.value instead
493493
// of putting everything in allocas just so we can use llvm.dbg.declare.

0 commit comments

Comments
 (0)