summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock31
-rw-r--r--src/bootstrap/test.rs82
m---------src/doc/book0
m---------src/doc/edition-guide0
m---------src/doc/embedded-book0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
-rw-r--r--src/doc/rustdoc/book.toml4
-rw-r--r--src/libcore/fmt/num.rs163
-rw-r--r--src/libcore/tests/fmt/num.rs80
-rw-r--r--src/librustc/arena.rs3
-rw-r--r--src/librustc/infer/error_reporting/mod.rs6
-rw-r--r--src/librustc/infer/lexical_region_resolve/mod.rs11
-rw-r--r--src/librustc/infer/opaque_types/mod.rs132
-rw-r--r--src/librustc/mir/query.rs8
-rw-r--r--src/librustc/query/mod.rs22
-rw-r--r--src/librustc/traits/fulfill.rs9
-rw-r--r--src/librustc/ty/flags.rs2
-rw-r--r--src/librustc/ty/fold.rs7
-rw-r--r--src/librustc/ty/instance.rs143
-rw-r--r--src/librustc/ty/mod.rs16
-rw-r--r--src/librustc/ty/sty.rs4
-rw-r--r--src/librustc/ty/util.rs2
-rw-r--r--src/librustc_ast_lowering/item.rs14
-rw-r--r--src/librustc_ast_lowering/lib.rs54
-rw-r--r--src/librustc_ast_lowering/pat.rs17
-rw-r--r--src/librustc_data_structures/obligation_forest/graphviz.rs2
-rw-r--r--src/librustc_data_structures/obligation_forest/mod.rs29
-rw-r--r--src/librustc_data_structures/obligation_forest/tests.rs4
-rw-r--r--src/librustc_expand/mbe/macro_rules.rs32
-rw-r--r--src/librustc_hir/hir.rs2
-rw-r--r--src/librustc_interface/callbacks.rs1
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/region_errors.rs23
-rw-r--r--src/librustc_mir/borrow_check/mod.rs51
-rw-r--r--src/librustc_mir/borrow_check/nll.rs52
-rw-r--r--src/librustc_mir/borrow_check/region_infer/mod.rs60
-rw-r--r--src/librustc_mir/borrow_check/region_infer/opaque_types.rs149
-rw-r--r--src/librustc_mir/borrow_check/region_infer/reverse_sccs.rs68
-rw-r--r--src/librustc_mir/borrow_check/type_check/mod.rs142
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs45
-rw-r--r--src/librustc_mir/transform/simplify_try.rs3
-rw-r--r--src/librustc_mir_build/build/mod.rs47
-rw-r--r--src/librustc_ty/Cargo.toml1
-rw-r--r--src/librustc_ty/instance.rs136
-rw-r--r--src/librustc_ty/lib.rs1
-rw-r--r--src/librustc_typeck/check/op.rs41
-rw-r--r--src/librustc_typeck/check/pat.rs113
-rw-r--r--src/librustc_typeck/check/writeback.rs5
-rw-r--r--src/librustc_typeck/collect.rs613
-rw-r--r--src/librustc_typeck/collect/type_of.rs661
-rw-r--r--src/librustc_typeck/impl_wf_check.rs21
-rw-r--r--src/librustdoc/Cargo.toml2
-rw-r--r--src/librustdoc/html/markdown.rs170
-rw-r--r--src/libstd/ffi/c_str.rs27
-rw-r--r--src/libstd/future.rs3
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/libstd/sys/wasi/fs.rs10
-rw-r--r--src/test/ui/array-slice-vec/issue-69103-extra-binding-subslice.rs18
-rw-r--r--src/test/ui/array-slice-vec/issue-69103-extra-binding-subslice.stderr26
-rw-r--r--src/test/ui/async-await/issues/issue-63388-1.nll.stderr11
-rw-r--r--src/test/ui/async-await/no-const-async.rs1
-rw-r--r--src/test/ui/async-await/no-const-async.stderr12
-rw-r--r--src/test/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.rs14
-rw-r--r--src/test/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.stderr16
-rw-r--r--src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs26
-rw-r--r--src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr61
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn.rs3
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn.stderr34
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.rs9
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.stderr21
-rw-r--r--src/test/ui/feature-gates/feature-gate-member-constraints.rs5
-rw-r--r--src/test/ui/feature-gates/feature-gate-member-constraints.stderr10
-rw-r--r--src/test/ui/impl-trait/auto-trait-leak.stderr150
-rw-r--r--src/test/ui/impl-trait/equal-hidden-lifetimes.rs49
-rw-r--r--src/test/ui/impl-trait/equal-hidden-lifetimes.stderr8
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs29
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr15
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs13
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr17
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.nll.stderr2
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.nll.stderr2
-rw-r--r--src/test/ui/impl-trait/nested-return-type.rs16
-rw-r--r--src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs5
-rw-r--r--src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr2
-rw-r--r--src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs65
-rw-r--r--src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr42
-rw-r--r--src/test/ui/impl-trait/unsafety-checking-cycle.rs32
-rw-r--r--src/test/ui/inference/infer-binary-operand-behind-reference.rs30
-rw-r--r--src/test/ui/lint/lint-unused-mut-variables.rs52
-rw-r--r--src/test/ui/lint/lint-unused-mut-variables.stderr68
-rw-r--r--src/test/ui/macros/issue-68060.rs16
-rw-r--r--src/test/ui/macros/issue-68060.stderr24
-rw-r--r--src/test/ui/or-patterns/or-pattern-mismatch.rs4
-rw-r--r--src/test/ui/or-patterns/or-pattern-mismatch.stderr9
-rw-r--r--src/test/ui/or-patterns/or-patterns-binding-type-mismatch.rs68
-rw-r--r--src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr183
-rw-r--r--src/test/ui/or-patterns/or-patterns-default-binding-modes.rs132
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr19
-rw-r--r--src/test/ui/self/elision/lt-ref-self-async.nll.stderr51
-rw-r--r--src/test/ui/self/elision/ref-mut-self-async.nll.stderr51
-rw-r--r--src/test/ui/self/elision/ref-mut-struct-async.nll.stderr43
-rw-r--r--src/test/ui/self/elision/ref-struct-async.nll.stderr43
-rw-r--r--src/test/ui/type-alias-impl-trait/assoc-type-const.rs12
-rw-r--r--src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs26
-rw-r--r--src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr9
-rw-r--r--src/test/ui/type-alias-impl-trait/assoc-type-lifetime.rs6
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs6
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr18
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-60564.rs2
m---------src/tools/miri0
-rw-r--r--src/tools/rustbook/src/main.rs34
-rw-r--r--src/tools/tidy/src/lib.rs1
114 files changed, 3284 insertions, 1668 deletions
diff --git a/Cargo.lock b/Cargo.lock
index f44644c..2847e3c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1564,7 +1564,7 @@ dependencies = [
1564 "rand_xoshiro", 1564 "rand_xoshiro",
1565 "sized-chunks", 1565 "sized-chunks",
1566 "typenum", 1566 "typenum",
1567 "version_check 0.9.1", 1567 "version_check",
1568] 1568]
1569 1569
1570[[package]] 1570[[package]]
@@ -2014,9 +2014,9 @@ dependencies = [
2014 2014
2015[[package]] 2015[[package]]
2016name = "memchr" 2016name = "memchr"
2017version = "2.2.0" 2017version = "2.3.2"
2018source = "registry+https://github.com/rust-lang/crates.io-index" 2018source = "registry+https://github.com/rust-lang/crates.io-index"
2019checksum = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" 2019checksum = "53445de381a1f436797497c61d851644d0e8e88e6140f22872ad33a704933978"
2020 2020
2021[[package]] 2021[[package]]
2022name = "memmap" 2022name = "memmap"
@@ -2604,23 +2604,23 @@ dependencies = [
2604 2604
2605[[package]] 2605[[package]]
2606name = "pulldown-cmark" 2606name = "pulldown-cmark"
2607version = "0.5.3" 2607version = "0.6.1"
2608source = "registry+https://github.com/rust-lang/crates.io-index" 2608source = "registry+https://github.com/rust-lang/crates.io-index"
2609checksum = "77043da1282374688ee212dc44b3f37ff929431de9c9adc3053bd3cee5630357" 2609checksum = "1c205cc82214f3594e2d50686730314f817c67ffa80fe800cf0db78c3c2b9d9e"
2610dependencies = [ 2610dependencies = [
2611 "bitflags", 2611 "bitflags",
2612 "getopts",
2612 "memchr", 2613 "memchr",
2613 "unicase", 2614 "unicase",
2614] 2615]
2615 2616
2616[[package]] 2617[[package]]
2617name = "pulldown-cmark" 2618name = "pulldown-cmark"
2618version = "0.6.1" 2619version = "0.7.0"
2619source = "registry+https://github.com/rust-lang/crates.io-index" 2620source = "registry+https://github.com/rust-lang/crates.io-index"
2620checksum = "1c205cc82214f3594e2d50686730314f817c67ffa80fe800cf0db78c3c2b9d9e" 2621checksum = "2c2d7fd131800e0d63df52aff46201acaab70b431a4a1ec6f0343fe8e64f35a4"
2621dependencies = [ 2622dependencies = [
2622 "bitflags", 2623 "bitflags",
2623 "getopts",
2624 "memchr", 2624 "memchr",
2625 "unicase", 2625 "unicase",
2626] 2626]
@@ -4124,6 +4124,7 @@ dependencies = [
4124 "rustc_data_structures", 4124 "rustc_data_structures",
4125 "rustc_hir", 4125 "rustc_hir",
4126 "rustc_span", 4126 "rustc_span",
4127 "rustc_target",
4127] 4128]
4128 4129
4129[[package]] 4130[[package]]
@@ -4159,7 +4160,7 @@ version = "0.0.0"
4159dependencies = [ 4160dependencies = [
4160 "itertools 0.8.0", 4161 "itertools 0.8.0",
4161 "minifier", 4162 "minifier",
4162 "pulldown-cmark 0.5.3", 4163 "pulldown-cmark 0.7.0",
4163 "rustc-rayon", 4164 "rustc-rayon",
4164 "serde", 4165 "serde",
4165 "serde_json", 4166 "serde_json",
@@ -5159,11 +5160,11 @@ checksum = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
5159 5160
5160[[package]] 5161[[package]]
5161name = "unicase" 5162name = "unicase"
5162version = "2.5.1" 5163version = "2.6.0"
5163source = "registry+https://github.com/rust-lang/crates.io-index" 5164source = "registry+https://github.com/rust-lang/crates.io-index"
5164checksum = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" 5165checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
5165dependencies = [ 5166dependencies = [
5166 "version_check 0.1.5", 5167 "version_check",
5167] 5168]
5168 5169
5169[[package]] 5170[[package]]
@@ -5335,12 +5336,6 @@ dependencies = [
5335 5336
5336[[package]] 5337[[package]]
5337name = "version_check" 5338name = "version_check"
5338version = "0.1.5"
5339source = "registry+https://github.com/rust-lang/crates.io-index"
5340checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
5341
5342[[package]]
5343name = "version_check"
5344version = "0.9.1" 5339version = "0.9.1"
5345source = "registry+https://github.com/rust-lang/crates.io-index" 5340source = "registry+https://github.com/rust-lang/crates.io-index"
5346checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" 5341checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce"
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 1580091..43561fa 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1264,15 +1264,15 @@ impl Step for Compiletest {
1264 } 1264 }
1265} 1265}
1266 1266
1267#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 1267#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1268struct DocTest { 1268struct BookTest {
1269 compiler: Compiler, 1269 compiler: Compiler,
1270 path: &'static str, 1270 path: PathBuf,
1271 name: &'static str, 1271 name: &'static str,
1272 is_ext_doc: bool, 1272 is_ext_doc: bool,
1273} 1273}
1274 1274
1275impl Step for DocTest { 1275impl Step for BookTest {
1276 type Output = (); 1276 type Output = ();
1277 const ONLY_HOSTS: bool = true; 1277 const ONLY_HOSTS: bool = true;
1278 1278
@@ -1280,12 +1280,59 @@ impl Step for DocTest {
1280 run.never() 1280 run.never()
1281 } 1281 }
1282 1282
1283 /// Runs `rustdoc --test` for all documentation in `src/doc`. 1283 /// Runs the documentation tests for a book in `src/doc`.
1284 /// 1284 ///
1285 /// This will run all tests in our markdown documentation (e.g., the book) 1285 /// This uses the `rustdoc` that sits next to `compiler`.
1286 /// located in `src/doc`. The `rustdoc` that's run is the one that sits next to
1287 /// `compiler`.
1288 fn run(self, builder: &Builder<'_>) { 1286 fn run(self, builder: &Builder<'_>) {
1287 // External docs are different from local because:
1288 // - Some books need pre-processing by mdbook before being tested.
1289 // - They need to save their state to toolstate.
1290 // - They are only tested on the "checktools" builders.
1291 //
1292 // The local docs are tested by default, and we don't want to pay the
1293 // cost of building mdbook, so they use `rustdoc --test` directly.
1294 // Also, the unstable book is special because SUMMARY.md is generated,
1295 // so it is easier to just run `rustdoc` on its files.
1296 if self.is_ext_doc {
1297 self.run_ext_doc(builder);
1298 } else {
1299 self.run_local_doc(builder);
1300 }
1301 }
1302}
1303
1304impl BookTest {
1305 /// This runs the equivalent of `mdbook test` (via the rustbook wrapper)
1306 /// which in turn runs `rustdoc --test` on each file in the book.
1307 fn run_ext_doc(self, builder: &Builder<'_>) {
1308 let compiler = self.compiler;
1309
1310 builder.ensure(compile::Std { compiler, target: compiler.host });
1311
1312 // mdbook just executes a binary named "rustdoc", so we need to update
1313 // PATH so that it points to our rustdoc.
1314 let mut rustdoc_path = builder.rustdoc(compiler);
1315 rustdoc_path.pop();
1316 let old_path = env::var_os("PATH").unwrap_or_default();
1317 let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path)))
1318 .expect("could not add rustdoc to PATH");
1319
1320 let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
1321 let path = builder.src.join(&self.path);
1322 rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
1323 builder.add_rust_test_threads(&mut rustbook_cmd);
1324 builder.info(&format!("Testing rustbook {}", self.path.display()));
1325 let _time = util::timeit(&builder);
1326 let toolstate = if try_run(builder, &mut rustbook_cmd) {
1327 ToolState::TestPass
1328 } else {
1329 ToolState::TestFail
1330 };
1331 builder.save_toolstate(self.name, toolstate);
1332 }
1333
1334 /// This runs `rustdoc --test` on all `.md` files in the path.
1335 fn run_local_doc(self, builder: &Builder<'_>) {
1289 let compiler = self.compiler; 1336 let compiler = self.compiler;
1290 1337
1291 builder.ensure(compile::Std { compiler, target: compiler.host }); 1338 builder.ensure(compile::Std { compiler, target: compiler.host });
@@ -1294,7 +1341,6 @@ impl Step for DocTest {
1294 // tests for all files that end in `*.md` 1341 // tests for all files that end in `*.md`
1295 let mut stack = vec![builder.src.join(self.path)]; 1342 let mut stack = vec![builder.src.join(self.path)];
1296 let _time = util::timeit(&builder); 1343 let _time = util::timeit(&builder);
1297
1298 let mut files = Vec::new(); 1344 let mut files = Vec::new();
1299 while let Some(p) = stack.pop() { 1345 while let Some(p) = stack.pop() {
1300 if p.is_dir() { 1346 if p.is_dir() {
@@ -1306,25 +1352,13 @@ impl Step for DocTest {
1306 continue; 1352 continue;
1307 } 1353 }
1308 1354
1309 // The nostarch directory in the book is for no starch, and so isn't
1310 // guaranteed to builder. We don't care if it doesn't build, so skip it.
1311 if p.to_str().map_or(false, |p| p.contains("nostarch")) {
1312 continue;
1313 }
1314
1315 files.push(p); 1355 files.push(p);
1316 } 1356 }
1317 1357
1318 files.sort(); 1358 files.sort();
1319 1359
1320 let mut toolstate = ToolState::TestPass;
1321 for file in files { 1360 for file in files {
1322 if !markdown_test(builder, compiler, &file) { 1361 markdown_test(builder, compiler, &file);
1323 toolstate = ToolState::TestFail;
1324 }
1325 }
1326 if self.is_ext_doc {
1327 builder.save_toolstate(self.name, toolstate);
1328 } 1362 }
1329 } 1363 }
1330} 1364}
@@ -1353,9 +1387,9 @@ macro_rules! test_book {
1353 } 1387 }
1354 1388
1355 fn run(self, builder: &Builder<'_>) { 1389 fn run(self, builder: &Builder<'_>) {
1356 builder.ensure(DocTest { 1390 builder.ensure(BookTest {
1357 compiler: self.compiler, 1391 compiler: self.compiler,
1358 path: $path, 1392 path: PathBuf::from($path),
1359 name: $book_name, 1393 name: $book_name,
1360 is_ext_doc: !$default, 1394 is_ext_doc: !$default,
1361 }); 1395 });
diff --git a/src/doc/book b/src/doc/book
Subproject 87dd6843678575f8dda962f239d14ef4be14b35 Subproject 6fb3705e5230311b096d47f7e2c91f9ce24393d
diff --git a/src/doc/edition-guide b/src/doc/edition-guide
Subproject 1a2390247ad6d08160e0dd74f40a01a9578659c Subproject 37f9e6848411188a1062ead1bd8ebe4b8aa1689
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
Subproject 4d78994915af1bde9a95c04a8c27d8dca066232 Subproject b2e1092bf67bd4d7686c4553f186edbb7f5f92d
diff --git a/src/doc/reference b/src/doc/reference
Subproject 11e893fc1357bc688418ddf1087c2b7aa25d154 Subproject 64239df6d173562b9deb4f012e4c3e6e960c475
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
Subproject 1c2bd024d13f8011307e13386cf1fea2180352b Subproject 32facd5522ddbbf37baf01e4e4b6562bc55c071
diff --git a/src/doc/rustdoc/book.toml b/src/doc/rustdoc/book.toml
new file mode 100644
index 0000000..ba30c10
--- /dev/null
+++ b/src/doc/rustdoc/book.toml
@@ -0,0 +1,4 @@
1[book]
2authors = ["The Rust Project Developers"]
3src = "src"
4title = "The rustdoc book"
diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs
index d562639..c187471 100644
--- a/src/libcore/fmt/num.rs
+++ b/src/libcore/fmt/num.rs
@@ -4,6 +4,7 @@
4 4
5use crate::fmt; 5use crate::fmt;
6use crate::mem::MaybeUninit; 6use crate::mem::MaybeUninit;
7use crate::num::flt2dec;
7use crate::ops::{Div, Rem, Sub}; 8use crate::ops::{Div, Rem, Sub};
8use crate::ptr; 9use crate::ptr;
9use crate::slice; 10use crate::slice;
@@ -256,6 +257,161 @@ macro_rules! impl_Display {
256 }; 257 };
257} 258}
258 259
260macro_rules! impl_Exp {
261 ($($t:ident),* as $u:ident via $conv_fn:ident named $name:ident) => {
262 fn $name(
263 mut n: $u,
264 is_nonnegative: bool,
265 upper: bool,
266 f: &mut fmt::Formatter<'_>
267 ) -> fmt::Result {
268 let (mut n, mut exponent, trailing_zeros, added_precision) = {
269 let mut exponent = 0;
270 // count and remove trailing decimal zeroes
271 while n % 10 == 0 && n >= 10 {
272 n /= 10;
273 exponent += 1;
274 }
275 let trailing_zeros = exponent;
276
277 let (added_precision, subtracted_precision) = match f.precision() {
278 Some(fmt_prec) => {
279 // number of decimal digits minus 1
280 let mut tmp = n;
281 let mut prec = 0;
282 while tmp >= 10 {
283 tmp /= 10;
284 prec += 1;
285 }
286 (fmt_prec.saturating_sub(prec), prec.saturating_sub(fmt_prec))
287 }
288 None => (0,0)
289 };
290 for _ in 1..subtracted_precision {
291 n/=10;
292 exponent += 1;
293 }
294 if subtracted_precision != 0 {
295 let rem = n % 10;
296 n /= 10;
297 exponent += 1;
298 // round up last digit
299 if rem >= 5 {
300 n += 1;
301 }
302 }
303 (n, exponent, trailing_zeros, added_precision)
304 };
305
306 // 39 digits (worst case u128) + . = 40
307 let mut buf = [MaybeUninit::<u8>::uninit(); 40];
308 let mut curr = buf.len() as isize; //index for buf
309 let buf_ptr = MaybeUninit::first_ptr_mut(&mut buf);
310 let lut_ptr = DEC_DIGITS_LUT.as_ptr();
311
312 // decode 2 chars at a time
313 while n >= 100 {
314 let d1 = ((n % 100) as isize) << 1;
315 curr -= 2;
316 unsafe {
317 ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
318 }
319 n /= 100;
320 exponent += 2;
321 }
322 // n is <= 99, so at most 2 chars long
323 let mut n = n as isize; // possibly reduce 64bit math
324 // decode second-to-last character
325 if n >= 10 {
326 curr -= 1;
327 unsafe {
328 *buf_ptr.offset(curr) = (n as u8 % 10_u8) + b'0';
329 }
330 n /= 10;
331 exponent += 1;
332 }
333 // add decimal point iff >1 mantissa digit will be printed
334 if exponent != trailing_zeros || added_precision != 0 {
335 curr -= 1;
336 unsafe {
337 *buf_ptr.offset(curr) = b'.';
338 }
339 }
340
341 let buf_slice = unsafe {
342 // decode last character
343 curr -= 1;
344 *buf_ptr.offset(curr) = (n as u8) + b'0';
345
346 let len = buf.len() - curr as usize;
347 slice::from_raw_parts(buf_ptr.offset(curr), len)
348 };
349
350 // stores 'e' (or 'E') and the up to 2-digit exponent
351 let mut exp_buf = [MaybeUninit::<u8>::uninit(); 3];
352 let exp_ptr = MaybeUninit::first_ptr_mut(&mut exp_buf);
353 let exp_slice = unsafe {
354 *exp_ptr.offset(0) = if upper {b'E'} else {b'e'};
355 let len = if exponent < 10 {
356 *exp_ptr.offset(1) = (exponent as u8) + b'0';
357 2
358 } else {
359 let off = exponent << 1;
360 ptr::copy_nonoverlapping(lut_ptr.offset(off), exp_ptr.offset(1), 2);
361 3
362 };
363 slice::from_raw_parts(exp_ptr, len)
364 };
365
366 let parts = &[
367 flt2dec::Part::Copy(buf_slice),
368 flt2dec::Part::Zero(added_precision),
369 flt2dec::Part::Copy(exp_slice)
370 ];
371 let sign = if !is_nonnegative {
372 &b"-"[..]
373 } else if f.sign_plus() {
374 &b"+"[..]
375 } else {
376 &b""[..]
377 };
378 let formatted = flt2dec::Formatted{sign, parts};
379 f.pad_formatted_parts(&formatted)
380 }
381
382 $(
383 #[stable(feature = "integer_exp_format", since = "1.42.0")]
384 impl fmt::LowerExp for $t {
385 #[allow(unused_comparisons)]
386 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
387 let is_nonnegative = *self >= 0;
388 let n = if is_nonnegative {
389 self.$conv_fn()
390 } else {
391 // convert the negative num to positive by summing 1 to it's 2 complement
392 (!self.$conv_fn()).wrapping_add(1)
393 };
394 $name(n, is_nonnegative, false, f)
395 }
396 })*
397 $(
398 #[stable(feature = "integer_exp_format", since = "1.42.0")]
399 impl fmt::UpperExp for $t {
400 #[allow(unused_comparisons)]
401 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
402 let is_nonnegative = *self >= 0;
403 let n = if is_nonnegative {
404 self.$conv_fn()
405 } else {
406 // convert the negative num to positive by summing 1 to it's 2 complement
407 (!self.$conv_fn()).wrapping_add(1)
408 };
409 $name(n, is_nonnegative, true, f)
410 }
411 })*
412 };
413}
414
259// Include wasm32 in here since it doesn't reflect the native pointer size, and 415// Include wasm32 in here since it doesn't reflect the native pointer size, and
260// often cares strongly about getting a smaller code size. 416// often cares strongly about getting a smaller code size.
261#[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))] 417#[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))]
@@ -265,6 +421,10 @@ mod imp {
265 i8, u8, i16, u16, i32, u32, i64, u64, usize, isize 421 i8, u8, i16, u16, i32, u32, i64, u64, usize, isize
266 as u64 via to_u64 named fmt_u64 422 as u64 via to_u64 named fmt_u64
267 ); 423 );
424 impl_Exp!(
425 i8, u8, i16, u16, i32, u32, i64, u64, usize, isize
426 as u64 via to_u64 named exp_u64
427 );
268} 428}
269 429
270#[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))] 430#[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))]
@@ -272,6 +432,9 @@ mod imp {
272 use super::*; 432 use super::*;
273 impl_Display!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named fmt_u32); 433 impl_Display!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named fmt_u32);
274 impl_Display!(i64, u64 as u64 via to_u64 named fmt_u64); 434 impl_Display!(i64, u64 as u64 via to_u64 named fmt_u64);
435 impl_Exp!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named exp_u32);
436 impl_Exp!(i64, u64 as u64 via to_u64 named exp_u64);
275} 437}
276 438
277impl_Display!(i128, u128 as u128 via to_u128 named fmt_u128); 439impl_Display!(i128, u128 as u128 via to_u128 named fmt_u128);
440impl_Exp!(i128, u128 as u128 via to_u128 named exp_u128);
diff --git a/src/libcore/tests/fmt/num.rs b/src/libcore/tests/fmt/num.rs
index 10fcf8b..a50c2b4 100644
--- a/src/libcore/tests/fmt/num.rs
+++ b/src/libcore/tests/fmt/num.rs
@@ -38,6 +38,16 @@ fn test_format_int() {
38 assert_eq!(format!("{:o}", 1i16), "1"); 38 assert_eq!(format!("{:o}", 1i16), "1");
39 assert_eq!(format!("{:o}", 1i32), "1"); 39 assert_eq!(format!("{:o}", 1i32), "1");
40 assert_eq!(format!("{:o}", 1i64), "1"); 40 assert_eq!(format!("{:o}", 1i64), "1");
41 assert_eq!(format!("{:e}", 1isize), "1e0");
42 assert_eq!(format!("{:e}", 1i8), "1e0");
43 assert_eq!(format!("{:e}", 1i16), "1e0");
44 assert_eq!(format!("{:e}", 1i32), "1e0");
45 assert_eq!(format!("{:e}", 1i64), "1e0");
46 assert_eq!(format!("{:E}", 1isize), "1E0");
47 assert_eq!(format!("{:E}", 1i8), "1E0");
48 assert_eq!(format!("{:E}", 1i16), "1E0");
49 assert_eq!(format!("{:E}", 1i32), "1E0");
50 assert_eq!(format!("{:E}", 1i64), "1E0");
41 51
42 assert_eq!(format!("{}", 1usize), "1"); 52 assert_eq!(format!("{}", 1usize), "1");
43 assert_eq!(format!("{}", 1u8), "1"); 53 assert_eq!(format!("{}", 1u8), "1");
@@ -69,6 +79,14 @@ fn test_format_int() {
69 assert_eq!(format!("{:o}", 1u16), "1"); 79 assert_eq!(format!("{:o}", 1u16), "1");
70 assert_eq!(format!("{:o}", 1u32), "1"); 80 assert_eq!(format!("{:o}", 1u32), "1");
71 assert_eq!(format!("{:o}", 1u64), "1"); 81 assert_eq!(format!("{:o}", 1u64), "1");
82 assert_eq!(format!("{:e}", 1u8), "1e0");
83 assert_eq!(format!("{:e}", 1u16), "1e0");
84 assert_eq!(format!("{:e}", 1u32), "1e0");
85 assert_eq!(format!("{:e}", 1u64), "1e0");
86 assert_eq!(format!("{:E}", 1u8), "1E0");
87 assert_eq!(format!("{:E}", 1u16), "1E0");
88 assert_eq!(format!("{:E}", 1u32), "1E0");
89 assert_eq!(format!("{:E}", 1u64), "1E0");
72 90
73 // Test a larger number 91 // Test a larger number
74 assert_eq!(format!("{:b}", 55), "110111"); 92 assert_eq!(format!("{:b}", 55), "110111");
@@ -76,6 +94,64 @@ fn test_format_int() {
76 assert_eq!(format!("{}", 55), "55"); 94 assert_eq!(format!("{}", 55), "55");
77 assert_eq!(format!("{:x}", 55), "37"); 95 assert_eq!(format!("{:x}", 55), "37");
78 assert_eq!(format!("{:X}", 55), "37"); 96 assert_eq!(format!("{:X}", 55), "37");
97 assert_eq!(format!("{:e}", 55), "5.5e1");
98 assert_eq!(format!("{:E}", 55), "5.5E1");
99 assert_eq!(format!("{:e}", 10000000000u64), "1e10");
100 assert_eq!(format!("{:E}", 10000000000u64), "1E10");
101 assert_eq!(format!("{:e}", 10000000001u64), "1.0000000001e10");
102 assert_eq!(format!("{:E}", 10000000001u64), "1.0000000001E10");
103}
104
105#[test]
106fn test_format_int_exp_limits() {
107 use core::{i128, i16, i32, i64, i8, u128, u16, u32, u64, u8};
108 assert_eq!(format!("{:e}", i8::MIN), "-1.28e2");
109 assert_eq!(format!("{:e}", i8::MAX), "1.27e2");
110 assert_eq!(format!("{:e}", i16::MIN), "-3.2768e4");
111 assert_eq!(format!("{:e}", i16::MAX), "3.2767e4");
112 assert_eq!(format!("{:e}", i32::MIN), "-2.147483648e9");
113 assert_eq!(format!("{:e}", i32::MAX), "2.147483647e9");
114 assert_eq!(format!("{:e}", i64::MIN), "-9.223372036854775808e18");
115 assert_eq!(format!("{:e}", i64::MAX), "9.223372036854775807e18");
116 assert_eq!(format!("{:e}", i128::MIN), "-1.70141183460469231731687303715884105728e38");
117 assert_eq!(format!("{:e}", i128::MAX), "1.70141183460469231731687303715884105727e38");
118
119 assert_eq!(format!("{:e}", u8::MAX), "2.55e2");
120 assert_eq!(format!("{:e}", u16::MAX), "6.5535e4");
121 assert_eq!(format!("{:e}", u32::MAX), "4.294967295e9");
122 assert_eq!(format!("{:e}", u64::MAX), "1.8446744073709551615e19");
123 assert_eq!(format!("{:e}", u128::MAX), "3.40282366920938463463374607431768211455e38");
124}
125
126#[test]
127fn test_format_int_exp_precision() {
128 use core::{i128, i16, i32, i64, i8};
129
130 //test that float and integer match
131 let big_int: u32 = 314_159_265;
132 assert_eq!(format!("{:.1e}", big_int), format!("{:.1e}", f64::from(big_int)));
133
134 //test adding precision
135 assert_eq!(format!("{:.10e}", i8::MIN), "-1.2800000000e2");
136 assert_eq!(format!("{:.10e}", i16::MIN), "-3.2768000000e4");
137 assert_eq!(format!("{:.10e}", i32::MIN), "-2.1474836480e9");
138 assert_eq!(format!("{:.20e}", i64::MIN), "-9.22337203685477580800e18");
139 assert_eq!(format!("{:.40e}", i128::MIN), "-1.7014118346046923173168730371588410572800e38");
140
141 //test rounding
142 assert_eq!(format!("{:.1e}", i8::MIN), "-1.3e2");
143 assert_eq!(format!("{:.1e}", i16::MIN), "-3.3e4");
144 assert_eq!(format!("{:.1e}", i32::MIN), "-2.1e9");
145 assert_eq!(format!("{:.1e}", i64::MIN), "-9.2e18");
146 assert_eq!(format!("{:.1e}", i128::MIN), "-1.7e38");
147
148 //test huge precision
149 assert_eq!(format!("{:.1000e}", 1), format!("1.{}e0", "0".repeat(1000)));
150 //test zero precision
151 assert_eq!(format!("{:.0e}", 1), format!("1e0",));
152
153 //test padding with precision (and sign)
154 assert_eq!(format!("{:+10.3e}", 1), " +1.000e0");
79} 155}
80 156
81#[test] 157#[test]
@@ -86,6 +162,8 @@ fn test_format_int_zero() {
86 assert_eq!(format!("{:o}", 0), "0"); 162 assert_eq!(format!("{:o}", 0), "0");
87 assert_eq!(format!("{:x}", 0), "0"); 163 assert_eq!(format!("{:x}", 0), "0");
88 assert_eq!(format!("{:X}", 0), "0"); 164 assert_eq!(format!("{:X}", 0), "0");
165 assert_eq!(format!("{:e}", 0), "0e0");
166 assert_eq!(format!("{:E}", 0), "0E0");
89 167
90 assert_eq!(format!("{}", 0u32), "0"); 168 assert_eq!(format!("{}", 0u32), "0");
91 assert_eq!(format!("{:?}", 0u32), "0"); 169 assert_eq!(format!("{:?}", 0u32), "0");
@@ -93,6 +171,8 @@ fn test_format_int_zero() {
93 assert_eq!(format!("{:o}", 0u32), "0"); 171 assert_eq!(format!("{:o}", 0u32), "0");
94 assert_eq!(format!("{:x}", 0u32), "0"); 172 assert_eq!(format!("{:x}", 0u32), "0");
95 assert_eq!(format!("{:X}", 0u32), "0"); 173 assert_eq!(format!("{:X}", 0u32), "0");
174 assert_eq!(format!("{:e}", 0u32), "0e0");
175 assert_eq!(format!("{:E}", 0u32), "0E0");
96} 176}
97 177
98#[test] 178#[test]
diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs
index dd24268..33cbf6e 100644
--- a/src/librustc/arena.rs
+++ b/src/librustc/arena.rs
@@ -35,7 +35,8 @@ macro_rules! arena_types {
35 rustc::mir::Promoted, 35 rustc::mir::Promoted,
36 rustc::mir::BodyAndCache<$tcx> 36 rustc::mir::BodyAndCache<$tcx>
37 >, 37 >,
38 [] tables: rustc::ty::TypeckTables<$tcx>, 38 [decode] tables: rustc::ty::TypeckTables<$tcx>,
39 [decode] borrowck_result: rustc::mir::BorrowCheckResult<$tcx>,
39 [] const_allocs: rustc::mir::interpret::Allocation, 40 [] const_allocs: rustc::mir::interpret::Allocation,
40 [] vtable_method: Option<( 41 [] vtable_method: Option<(
41 rustc_hir::def_id::DefId, 42 rustc_hir::def_id::DefId,
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 01390f2..327e1da 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -405,17 +405,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
405 } 405 }
406 406
407 RegionResolutionError::MemberConstraintFailure { 407 RegionResolutionError::MemberConstraintFailure {
408 opaque_type_def_id,
409 hidden_ty, 408 hidden_ty,
410 member_region, 409 member_region,
411 span: _, 410 span,
412 choice_regions: _,
413 } => { 411 } => {
414 let hidden_ty = self.resolve_vars_if_possible(&hidden_ty); 412 let hidden_ty = self.resolve_vars_if_possible(&hidden_ty);
415 opaque_types::unexpected_hidden_region_diagnostic( 413 opaque_types::unexpected_hidden_region_diagnostic(
416 self.tcx, 414 self.tcx,
417 Some(region_scope_tree), 415 Some(region_scope_tree),
418 opaque_type_def_id, 416 span,
419 hidden_ty, 417 hidden_ty,
420 member_region, 418 member_region,
421 ) 419 )
diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs
index e0a8c3b..1b204e5 100644
--- a/src/librustc/infer/lexical_region_resolve/mod.rs
+++ b/src/librustc/infer/lexical_region_resolve/mod.rs
@@ -18,7 +18,6 @@ use rustc_data_structures::fx::FxHashSet;
18use rustc_data_structures::graph::implementation::{ 18use rustc_data_structures::graph::implementation::{
19 Direction, Graph, NodeIndex, INCOMING, OUTGOING, 19 Direction, Graph, NodeIndex, INCOMING, OUTGOING,
20}; 20};
21use rustc_hir::def_id::DefId;
22use rustc_index::vec::{Idx, IndexVec}; 21use rustc_index::vec::{Idx, IndexVec};
23use rustc_span::Span; 22use rustc_span::Span;
24use std::fmt; 23use std::fmt;
@@ -95,13 +94,7 @@ pub enum RegionResolutionError<'tcx> {
95 /// Indicates a failure of a `MemberConstraint`. These arise during 94 /// Indicates a failure of a `MemberConstraint`. These arise during
96 /// impl trait processing explicitly -- basically, the impl trait's hidden type 95 /// impl trait processing explicitly -- basically, the impl trait's hidden type
97 /// included some region that it was not supposed to. 96 /// included some region that it was not supposed to.
98 MemberConstraintFailure { 97 MemberConstraintFailure { span: Span, hidden_ty: Ty<'tcx>, member_region: Region<'tcx> },
99 span: Span,
100 opaque_type_def_id: DefId,
101 hidden_ty: Ty<'tcx>,
102 member_region: Region<'tcx>,
103 choice_regions: Vec<Region<'tcx>>,
104 },
105} 98}
106 99
107struct RegionAndOrigin<'tcx> { 100struct RegionAndOrigin<'tcx> {
@@ -656,10 +649,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
656 let span = self.tcx().def_span(member_constraint.opaque_type_def_id); 649 let span = self.tcx().def_span(member_constraint.opaque_type_def_id);
657 errors.push(RegionResolutionError::MemberConstraintFailure { 650 errors.push(RegionResolutionError::MemberConstraintFailure {
658 span, 651 span,
659 opaque_type_def_id: member_constraint.opaque_type_def_id,
660 hidden_ty: member_constraint.hidden_ty, 652 hidden_ty: member_constraint.hidden_ty,
661 member_region, 653 member_region,
662 choice_regions: choice_regions.collect(),
663 }); 654 });
664 } 655 }
665 } 656 }
diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs
index 7fef9d2..5ecd03e 100644
--- a/src/librustc/infer/opaque_types/mod.rs
+++ b/src/librustc/infer/opaque_types/mod.rs
@@ -93,6 +93,18 @@ pub struct OpaqueTypeDecl<'tcx> {
93 pub origin: hir::OpaqueTyOrigin, 93 pub origin: hir::OpaqueTyOrigin,
94} 94}
95 95
96/// Whether member constraints should be generated for all opaque types
97pub enum GenerateMemberConstraints {
98 /// The default, used by typeck
99 WhenRequired,
100 /// The borrow checker needs member constraints in any case where we don't
101 /// have a `'static` bound. This is because the borrow checker has more
102 /// flexibility in the values of regions. For example, given `f<'a, 'b>`
103 /// the borrow checker can have an inference variable outlive `'a` and `'b`,
104 /// but not be equal to `'static`.
105 IfNoStaticBound,
106}
107
96impl<'a, 'tcx> InferCtxt<'a, 'tcx> { 108impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
97 /// Replaces all opaque types in `value` with fresh inference variables 109 /// Replaces all opaque types in `value` with fresh inference variables
98 /// and creates appropriate obligations. For example, given the input: 110 /// and creates appropriate obligations. For example, given the input:
@@ -315,7 +327,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
315 debug!("constrain_opaque_types()"); 327 debug!("constrain_opaque_types()");
316 328
317 for (&def_id, opaque_defn) in opaque_types { 329 for (&def_id, opaque_defn) in opaque_types {
318 self.constrain_opaque_type(def_id, opaque_defn, free_region_relations); 330 self.constrain_opaque_type(
331 def_id,
332 opaque_defn,
333 GenerateMemberConstraints::WhenRequired,
334 free_region_relations,
335 );
319 } 336 }
320 } 337 }
321 338
@@ -324,6 +341,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
324 &self, 341 &self,
325 def_id: DefId, 342 def_id: DefId,
326 opaque_defn: &OpaqueTypeDecl<'tcx>, 343 opaque_defn: &OpaqueTypeDecl<'tcx>,
344 mode: GenerateMemberConstraints,
327 free_region_relations: &FRR, 345 free_region_relations: &FRR,
328 ) { 346 ) {
329 debug!("constrain_opaque_type()"); 347 debug!("constrain_opaque_type()");
@@ -358,6 +376,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
358 op: |r| self.sub_regions(infer::CallReturn(span), required_region, r), 376 op: |r| self.sub_regions(infer::CallReturn(span), required_region, r),
359 }); 377 });
360 } 378 }
379 if let GenerateMemberConstraints::IfNoStaticBound = mode {
380 self.generate_member_constraint(
381 concrete_ty,
382 opaque_type_generics,
383 opaque_defn,
384 def_id,
385 );
386 }
361 return; 387 return;
362 } 388 }
363 389
@@ -398,13 +424,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
398 // we will create a "in bound" like `'r in 424 // we will create a "in bound" like `'r in
399 // ['a, 'b, 'c]`, where `'a..'c` are the 425 // ['a, 'b, 'c]`, where `'a..'c` are the
400 // regions that appear in the impl trait. 426 // regions that appear in the impl trait.
427
428 // For now, enforce a feature gate outside of async functions.
429 self.member_constraint_feature_gate(opaque_defn, def_id, lr, subst_arg);
430
401 return self.generate_member_constraint( 431 return self.generate_member_constraint(
402 concrete_ty, 432 concrete_ty,
403 opaque_type_generics, 433 opaque_type_generics,
404 opaque_defn, 434 opaque_defn,
405 def_id, 435 def_id,
406 lr,
407 subst_arg,
408 ); 436 );
409 } 437 }
410 } 438 }
@@ -414,6 +442,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
414 let least_region = least_region.unwrap_or(tcx.lifetimes.re_static); 442 let least_region = least_region.unwrap_or(tcx.lifetimes.re_static);
415 debug!("constrain_opaque_types: least_region={:?}", least_region); 443 debug!("constrain_opaque_types: least_region={:?}", least_region);
416 444
445 if let GenerateMemberConstraints::IfNoStaticBound = mode {
446 if least_region != tcx.lifetimes.re_static {
447 self.generate_member_constraint(
448 concrete_ty,
449 opaque_type_generics,
450 opaque_defn,
451 def_id,
452 );
453 }
454 }
417 concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { 455 concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
418 tcx: self.tcx, 456 tcx: self.tcx,
419 op: |r| self.sub_regions(infer::CallReturn(span), least_region, r), 457 op: |r| self.sub_regions(infer::CallReturn(span), least_region, r),
@@ -434,19 +472,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
434 opaque_type_generics: &ty::Generics, 472 opaque_type_generics: &ty::Generics,
435 opaque_defn: &OpaqueTypeDecl<'tcx>, 473 opaque_defn: &OpaqueTypeDecl<'tcx>,
436 opaque_type_def_id: DefId, 474 opaque_type_def_id: DefId,
437 conflict1: ty::Region<'tcx>,
438 conflict2: ty::Region<'tcx>,
439 ) { 475 ) {
440 // For now, enforce a feature gate outside of async functions.
441 if self.member_constraint_feature_gate(
442 opaque_defn,
443 opaque_type_def_id,
444 conflict1,
445 conflict2,
446 ) {
447 return;
448 }
449
450 // Create the set of choice regions: each region in the hidden 476 // Create the set of choice regions: each region in the hidden
451 // type can be equal to any of the region parameters of the 477 // type can be equal to any of the region parameters of the
452 // opaque type definition. 478 // opaque type definition.
@@ -500,8 +526,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
500 hir::OpaqueTyOrigin::AsyncFn => return false, 526 hir::OpaqueTyOrigin::AsyncFn => return false,
501 527
502 // Otherwise, generate the label we'll use in the error message. 528 // Otherwise, generate the label we'll use in the error message.
503 hir::OpaqueTyOrigin::TypeAlias => "impl Trait", 529 hir::OpaqueTyOrigin::TypeAlias
504 hir::OpaqueTyOrigin::FnReturn => "impl Trait", 530 | hir::OpaqueTyOrigin::FnReturn
531 | hir::OpaqueTyOrigin::Misc => "impl Trait",
505 }; 532 };
506 let msg = format!("ambiguous lifetime bound in `{}`", context_name); 533 let msg = format!("ambiguous lifetime bound in `{}`", context_name);
507 let mut err = self.tcx.sess.struct_span_err(span, &msg); 534 let mut err = self.tcx.sess.struct_span_err(span, &msg);
@@ -549,13 +576,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
549 /// # Parameters 576 /// # Parameters
550 /// 577 ///
551 /// - `def_id`, the `impl Trait` type 578 /// - `def_id`, the `impl Trait` type
552 /// - `opaque_defn`, the opaque definition created in `instantiate_opaque_types` 579 /// - `substs`, the substs used to instantiate this opaque type
553 /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of 580 /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of
554 /// `opaque_defn.concrete_ty` 581 /// `opaque_defn.concrete_ty`
555 pub fn infer_opaque_definition_from_instantiation( 582 pub fn infer_opaque_definition_from_instantiation(
556 &self, 583 &self,
557 def_id: DefId, 584 def_id: DefId,
558 opaque_defn: &OpaqueTypeDecl<'tcx>, 585 substs: SubstsRef<'tcx>,
559 instantiated_ty: Ty<'tcx>, 586 instantiated_ty: Ty<'tcx>,
560 span: Span, 587 span: Span,
561 ) -> Ty<'tcx> { 588 ) -> Ty<'tcx> {
@@ -571,12 +598,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
571 // `impl Trait` return type, resulting in the parameters 598 // `impl Trait` return type, resulting in the parameters
572 // shifting. 599 // shifting.
573 let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id); 600 let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id);
574 let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> = opaque_defn 601 let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> =
575 .substs 602 substs.iter().enumerate().map(|(index, subst)| (*subst, id_substs[index])).collect();
576 .iter()
577 .enumerate()
578 .map(|(index, subst)| (*subst, id_substs[index]))
579 .collect();
580 603
581 // Convert the type from the function into a type valid outside 604 // Convert the type from the function into a type valid outside
582 // the function, by replacing invalid regions with 'static, 605 // the function, by replacing invalid regions with 'static,
@@ -598,11 +621,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
598pub fn unexpected_hidden_region_diagnostic( 621pub fn unexpected_hidden_region_diagnostic(
599 tcx: TyCtxt<'tcx>, 622 tcx: TyCtxt<'tcx>,
600 region_scope_tree: Option<&region::ScopeTree>, 623 region_scope_tree: Option<&region::ScopeTree>,
601 opaque_type_def_id: DefId, 624 span: Span,
602 hidden_ty: Ty<'tcx>, 625 hidden_ty: Ty<'tcx>,
603 hidden_region: ty::Region<'tcx>, 626 hidden_region: ty::Region<'tcx>,
604) -> DiagnosticBuilder<'tcx> { 627) -> DiagnosticBuilder<'tcx> {
605 let span = tcx.def_span(opaque_type_def_id);
606 let mut err = struct_span_err!( 628 let mut err = struct_span_err!(
607 tcx.sess, 629 tcx.sess,
608 span, 630 span,
@@ -817,32 +839,48 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
817 839
818 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { 840 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
819 match r { 841 match r {
820 // ignore bound regions that appear in the type (e.g., this 842 // Ignore bound regions and `'static` regions that appear in the
821 // would ignore `'r` in a type like `for<'r> fn(&'r u32)`. 843 // type, we only need to remap regions that reference lifetimes
822 ty::ReLateBound(..) | 844 // from the function declaraion.
823 845 // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
824 // ignore `'static`, as that can appear anywhere 846 ty::ReLateBound(..) | ty::ReStatic => return r,
825 ty::ReStatic => return r, 847
826 848 // If regions have been erased (by writeback), don't try to unerase
827 _ => { } 849 // them.
850 ty::ReErased => return r,
851
852 // The regions that we expect from borrow checking.
853 ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {}
854
855 ty::ReEmpty(_)
856 | ty::RePlaceholder(_)
857 | ty::ReVar(_)
858 | ty::ReScope(_)
859 | ty::ReClosureBound(_) => {
860 // All of the regions in the type should either have been
861 // erased by writeback, or mapped back to named regions by
862 // borrow checking.
863 bug!("unexpected region kind in opaque type: {:?}", r);
864 }
828 } 865 }
829 866
830 let generics = self.tcx().generics_of(self.opaque_type_def_id); 867 let generics = self.tcx().generics_of(self.opaque_type_def_id);
831 match self.map.get(&r.into()).map(|k| k.unpack()) { 868 match self.map.get(&r.into()).map(|k| k.unpack()) {
832 Some(GenericArgKind::Lifetime(r1)) => r1, 869 Some(GenericArgKind::Lifetime(r1)) => r1,
833 Some(u) => panic!("region mapped to unexpected kind: {:?}", u), 870 Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
871 None if self.map_missing_regions_to_empty || self.tainted_by_errors => {
872 self.tcx.lifetimes.re_root_empty
873 }
834 None if generics.parent.is_some() => { 874 None if generics.parent.is_some() => {
835 if !self.map_missing_regions_to_empty && !self.tainted_by_errors { 875 if let Some(hidden_ty) = self.hidden_ty.take() {
836 if let Some(hidden_ty) = self.hidden_ty.take() { 876 unexpected_hidden_region_diagnostic(
837 unexpected_hidden_region_diagnostic( 877 self.tcx,
838 self.tcx, 878 None,
839 None, 879 self.tcx.def_span(self.opaque_type_def_id),
840 self.opaque_type_def_id, 880 hidden_ty,
841 hidden_ty, 881 r,
842 r, 882 )
843 ) 883 .emit();
844 .emit();
845 }
846 } 884 }
847 self.tcx.lifetimes.re_root_empty 885 self.tcx.lifetimes.re_root_empty
848 } 886 }
@@ -860,7 +898,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
860 ) 898 )
861 .emit(); 899 .emit();
862 900
863 self.tcx().mk_region(ty::ReStatic) 901 self.tcx().lifetimes.re_static
864 } 902 }
865 } 903 }
866 } 904 }
diff --git a/src/librustc/mir/query.rs b/src/librustc/mir/query.rs
index 34f58ab..824cdfe 100644
--- a/src/librustc/mir/query.rs
+++ b/src/librustc/mir/query.rs
@@ -1,8 +1,10 @@
1//! Values computed by queries that use MIR. 1//! Values computed by queries that use MIR.
2 2
3use crate::ty::{self, Ty}; 3use crate::ty::{self, Ty};
4use rustc_data_structures::fx::FxHashMap;
4use rustc_data_structures::sync::Lrc; 5use rustc_data_structures::sync::Lrc;
5use rustc_hir as hir; 6use rustc_hir as hir;
7use rustc_hir::def_id::DefId;
6use rustc_index::bit_set::BitMatrix; 8use rustc_index::bit_set::BitMatrix;
7use rustc_index::vec::IndexVec; 9use rustc_index::vec::IndexVec;
8use rustc_span::{Span, Symbol}; 10use rustc_span::{Span, Symbol};
@@ -59,8 +61,12 @@ pub struct GeneratorLayout<'tcx> {
59 pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>, 61 pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
60} 62}
61 63
62#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] 64#[derive(Debug, RustcEncodable, RustcDecodable, HashStable)]
63pub struct BorrowCheckResult<'tcx> { 65pub struct BorrowCheckResult<'tcx> {
66 /// All the opaque types that are restricted to concrete types
67 /// by this function. Unlike the value in `TypeckTables`, this has
68 /// unerased regions.
69 pub concrete_opaque_types: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
64 pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>, 70 pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
65 pub used_mut_upvars: SmallVec<[Field; 8]>, 71 pub used_mut_upvars: SmallVec<[Field; 8]>,
66} 72}
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index 11b0798..5e27997 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -125,7 +125,9 @@ rustc_queries! {
125 125
126 /// Fetch the MIR for a given `DefId` right after it's built - this includes 126 /// Fetch the MIR for a given `DefId` right after it's built - this includes
127 /// unreachable code. 127 /// unreachable code.
128 query mir_built(_: DefId) -> &'tcx Steal<mir::BodyAndCache<'tcx>> {} 128 query mir_built(_: DefId) -> &'tcx Steal<mir::BodyAndCache<'tcx>> {
129 desc { "building MIR for" }
130 }
129 131
130 /// Fetch the MIR for a given `DefId` up till the point where it is 132 /// Fetch the MIR for a given `DefId` up till the point where it is
131 /// ready for const evaluation. 133 /// ready for const evaluation.
@@ -345,6 +347,7 @@ rustc_queries! {
345 TypeChecking { 347 TypeChecking {
346 /// The result of unsafety-checking this `DefId`. 348 /// The result of unsafety-checking this `DefId`.
347 query unsafety_check_result(key: DefId) -> mir::UnsafetyCheckResult { 349 query unsafety_check_result(key: DefId) -> mir::UnsafetyCheckResult {
350 desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key) }
348 cache_on_disk_if { key.is_local() } 351 cache_on_disk_if { key.is_local() }
349 } 352 }
350 353
@@ -414,14 +417,8 @@ rustc_queries! {
414 } 417 }
415 418
416 query typeck_tables_of(key: DefId) -> &'tcx ty::TypeckTables<'tcx> { 419 query typeck_tables_of(key: DefId) -> &'tcx ty::TypeckTables<'tcx> {
420 desc { |tcx| "type-checking `{}`", tcx.def_path_str(key) }
417 cache_on_disk_if { key.is_local() } 421 cache_on_disk_if { key.is_local() }
418 load_cached(tcx, id) {
419 let typeck_tables: Option<ty::TypeckTables<'tcx>> = tcx
420 .queries.on_disk_cache
421 .try_load_query_result(tcx, id);
422
423 typeck_tables.map(|tables| &*tcx.arena.alloc(tables))
424 }
425 } 422 }
426 query diagnostic_only_typeck_tables_of(key: DefId) -> &'tcx ty::TypeckTables<'tcx> { 423 query diagnostic_only_typeck_tables_of(key: DefId) -> &'tcx ty::TypeckTables<'tcx> {
427 cache_on_disk_if { key.is_local() } 424 cache_on_disk_if { key.is_local() }
@@ -452,8 +449,13 @@ rustc_queries! {
452 BorrowChecking { 449 BorrowChecking {
453 /// Borrow-checks the function body. If this is a closure, returns 450 /// Borrow-checks the function body. If this is a closure, returns
454 /// additional requirements that the closure's creator must verify. 451 /// additional requirements that the closure's creator must verify.
455 query mir_borrowck(key: DefId) -> mir::BorrowCheckResult<'tcx> { 452 query mir_borrowck(key: DefId) -> &'tcx mir::BorrowCheckResult<'tcx> {
456 cache_on_disk_if(tcx, _) { key.is_local() && tcx.is_closure(key) } 453 desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key) }
454 cache_on_disk_if(tcx, opt_result) {
455 key.is_local()
456 && (tcx.is_closure(key)
457 || opt_result.map_or(false, |r| !r.concrete_opaque_types.is_empty()))
458 }
457 } 459 }
458 } 460 }
459 461
diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs
index 0aac6fb..07352a3 100644
--- a/src/librustc/traits/fulfill.rs
+++ b/src/librustc/traits/fulfill.rs
@@ -18,10 +18,13 @@ use super::{FulfillmentError, FulfillmentErrorCode};
18use super::{ObligationCause, PredicateObligation}; 18use super::{ObligationCause, PredicateObligation};
19 19
20impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> { 20impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> {
21 type Predicate = ty::Predicate<'tcx>; 21 /// Note that we include both the `ParamEnv` and the `Predicate`,
22 /// as the `ParamEnv` can influence whether fulfillment succeeds
23 /// or fails.
24 type CacheKey = ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>;
22 25
23 fn as_predicate(&self) -> &Self::Predicate { 26 fn as_cache_key(&self) -> Self::CacheKey {
24 &self.obligation.predicate 27 self.obligation.param_env.and(self.obligation.predicate)
25 } 28 }
26} 29}
27 30
diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs
index 4a4280b..4546ead 100644
--- a/src/librustc/ty/flags.rs
+++ b/src/librustc/ty/flags.rs
@@ -138,7 +138,7 @@ impl FlagComputation {
138 } 138 }
139 139
140 &ty::Opaque(_, substs) => { 140 &ty::Opaque(_, substs) => {
141 self.add_flags(TypeFlags::HAS_PROJECTION); 141 self.add_flags(TypeFlags::HAS_PROJECTION | TypeFlags::HAS_TY_OPAQUE);
142 self.add_substs(substs); 142 self.add_substs(substs);
143 } 143 }
144 144
diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs
index 1f007b9..3212bc7 100644
--- a/src/librustc/ty/fold.rs
+++ b/src/librustc/ty/fold.rs
@@ -78,6 +78,9 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
78 fn has_projections(&self) -> bool { 78 fn has_projections(&self) -> bool {
79 self.has_type_flags(TypeFlags::HAS_PROJECTION) 79 self.has_type_flags(TypeFlags::HAS_PROJECTION)
80 } 80 }
81 fn has_opaque_types(&self) -> bool {
82 self.has_type_flags(TypeFlags::HAS_TY_OPAQUE)
83 }
81 fn references_error(&self) -> bool { 84 fn references_error(&self) -> bool {
82 self.has_type_flags(TypeFlags::HAS_TY_ERR) 85 self.has_type_flags(TypeFlags::HAS_TY_ERR)
83 } 86 }
@@ -120,6 +123,10 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
120 self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) 123 self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
121 } 124 }
122 125
126 fn has_erased_regions(&self) -> bool {
127 self.has_type_flags(TypeFlags::HAS_RE_ERASED)
128 }
129
123 /// True if there are any un-erased free regions. 130 /// True if there are any un-erased free regions.
124 fn has_erasable_regions(&self) -> bool { 131 fn has_erasable_regions(&self) -> bool {
125 self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) 132 self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 335953f..332fd0b 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -1,12 +1,11 @@
1use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; 1use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
2use crate::middle::lang_items::DropInPlaceFnLangItem; 2use crate::middle::lang_items::DropInPlaceFnLangItem;
3use crate::traits;
4use crate::ty::print::{FmtPrinter, Printer}; 3use crate::ty::print::{FmtPrinter, Printer};
5use crate::ty::{self, SubstsRef, Ty, TyCtxt, TypeFoldable}; 4use crate::ty::{self, SubstsRef, Ty, TyCtxt, TypeFoldable};
5use rustc_data_structures::AtomicRef;
6use rustc_hir::def::Namespace; 6use rustc_hir::def::Namespace;
7use rustc_hir::def_id::{CrateNum, DefId}; 7use rustc_hir::def_id::{CrateNum, DefId};
8use rustc_macros::HashStable; 8use rustc_macros::HashStable;
9use rustc_target::spec::abi::Abi;
10 9
11use std::fmt; 10use std::fmt;
12 11
@@ -263,45 +262,7 @@ impl<'tcx> Instance<'tcx> {
263 def_id: DefId, 262 def_id: DefId,
264 substs: SubstsRef<'tcx>, 263 substs: SubstsRef<'tcx>,
265 ) -> Option<Instance<'tcx>> { 264 ) -> Option<Instance<'tcx>> {
266 debug!("resolve(def_id={:?}, substs={:?})", def_id, substs); 265 (*RESOLVE_INSTANCE)(tcx, param_env, def_id, substs)
267 let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) {
268 debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
269 let item = tcx.associated_item(def_id);
270 resolve_associated_item(tcx, &item, param_env, trait_def_id, substs)
271 } else {
272 let ty = tcx.type_of(def_id);
273 let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, &ty);
274
275 let def = match item_type.kind {
276 ty::FnDef(..)
277 if {
278 let f = item_type.fn_sig(tcx);
279 f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic
280 } =>
281 {
282 debug!(" => intrinsic");
283 ty::InstanceDef::Intrinsic(def_id)
284 }
285 _ => {
286 if Some(def_id) == tcx.lang_items().drop_in_place_fn() {
287 let ty = substs.type_at(0);
288 if ty.needs_drop(tcx, param_env.with_reveal_all()) {
289 debug!(" => nontrivial drop glue");
290 ty::InstanceDef::DropGlue(def_id, Some(ty))
291 } else {
292 debug!(" => trivial drop glue");
293 ty::InstanceDef::DropGlue(def_id, None)
294 }
295 } else {
296 debug!(" => free item");
297 ty::InstanceDef::Item(def_id)
298 }
299 }
300 };
301 Some(Instance { def: def, substs: substs })
302 };
303 debug!("resolve(def_id={:?}, substs={:?}) = {:?}", def_id, substs, result);
304 result
305 } 266 }
306 267
307 pub fn resolve_for_fn_ptr( 268 pub fn resolve_for_fn_ptr(
@@ -398,88 +359,6 @@ impl<'tcx> Instance<'tcx> {
398 } 359 }
399} 360}
400 361
401fn resolve_associated_item<'tcx>(
402 tcx: TyCtxt<'tcx>,
403 trait_item: &ty::AssocItem,
404 param_env: ty::ParamEnv<'tcx>,
405 trait_id: DefId,
406 rcvr_substs: SubstsRef<'tcx>,
407) -> Option<Instance<'tcx>> {
408 let def_id = trait_item.def_id;
409 debug!(
410 "resolve_associated_item(trait_item={:?}, \
411 param_env={:?}, \
412 trait_id={:?}, \
413 rcvr_substs={:?})",
414 def_id, param_env, trait_id, rcvr_substs
415 );
416
417 let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
418 let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref)));
419
420 // Now that we know which impl is being used, we can dispatch to
421 // the actual function:
422 match vtbl {
423 traits::VtableImpl(impl_data) => {
424 let (def_id, substs) =
425 traits::find_associated_item(tcx, param_env, trait_item, rcvr_substs, &impl_data);
426
427 let resolved_item = tcx.associated_item(def_id);
428
429 // Since this is a trait item, we need to see if the item is either a trait default item
430 // or a specialization because we can't resolve those unless we can `Reveal::All`.
431 // NOTE: This should be kept in sync with the similar code in
432 // `rustc::traits::project::assemble_candidates_from_impls()`.
433 let eligible = if !resolved_item.defaultness.is_default() {
434 true
435 } else if param_env.reveal == traits::Reveal::All {
436 !trait_ref.needs_subst()
437 } else {
438 false
439 };
440
441 if !eligible {
442 return None;
443 }
444
445 let substs = tcx.erase_regions(&substs);
446 Some(ty::Instance::new(def_id, substs))
447 }
448 traits::VtableGenerator(generator_data) => Some(Instance {
449 def: ty::InstanceDef::Item(generator_data.generator_def_id),
450 substs: generator_data.substs,
451 }),
452 traits::VtableClosure(closure_data) => {
453 let trait_closure_kind = tcx.fn_trait_kind_from_lang_item(trait_id).unwrap();
454 Some(Instance::resolve_closure(
455 tcx,
456 closure_data.closure_def_id,
457 closure_data.substs,
458 trait_closure_kind,
459 ))
460 }
461 traits::VtableFnPointer(ref data) => Some(Instance {
462 def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty),
463 substs: rcvr_substs,
464 }),
465 traits::VtableObject(ref data) => {
466 let index = traits::get_vtable_index_of_object_method(tcx, data, def_id);
467 Some(Instance { def: ty::InstanceDef::Virtual(def_id, index), substs: rcvr_substs })
468 }
469 traits::VtableBuiltin(..) => {
470 if tcx.lang_items().clone_trait().is_some() {
471 Some(Instance {
472 def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()),
473 substs: rcvr_substs,
474 })
475 } else {
476 None
477 }
478 }
479 traits::VtableAutoImpl(..) | traits::VtableParam(..) | traits::VtableTraitAlias(..) => None,
480 }
481}
482
483fn needs_fn_once_adapter_shim( 362fn needs_fn_once_adapter_shim(
484 actual_closure_kind: ty::ClosureKind, 363 actual_closure_kind: ty::ClosureKind,
485 trait_closure_kind: ty::ClosureKind, 364 trait_closure_kind: ty::ClosureKind,
@@ -512,3 +391,21 @@ fn needs_fn_once_adapter_shim(
512 (ty::ClosureKind::FnMut, _) | (ty::ClosureKind::FnOnce, _) => Err(()), 391 (ty::ClosureKind::FnMut, _) | (ty::ClosureKind::FnOnce, _) => Err(()),
513 } 392 }
514} 393}
394
395fn resolve_instance_default(
396 _tcx: TyCtxt<'tcx>,
397 _param_env: ty::ParamEnv<'tcx>,
398 _def_id: DefId,
399 _substs: SubstsRef<'tcx>,
400) -> Option<Instance<'tcx>> {
401 unimplemented!()
402}
403
404pub static RESOLVE_INSTANCE: AtomicRef<
405 for<'tcx> fn(
406 TyCtxt<'tcx>,
407 ty::ParamEnv<'tcx>,
408 DefId,
409 SubstsRef<'tcx>,
410 ) -> Option<Instance<'tcx>>,
411> = AtomicRef::new(&(resolve_instance_default as _));
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index ad51c60..45ea05e 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -83,6 +83,7 @@ pub use self::context::{
83 CtxtInterners, GeneratorInteriorTypeCause, GlobalCtxt, Lift, TypeckTables, 83 CtxtInterners, GeneratorInteriorTypeCause, GlobalCtxt, Lift, TypeckTables,
84}; 84};
85 85
86pub use self::instance::RESOLVE_INSTANCE;
86pub use self::instance::{Instance, InstanceDef}; 87pub use self::instance::{Instance, InstanceDef};
87 88
88pub use self::trait_def::TraitDef; 89pub use self::trait_def::TraitDef;
@@ -473,10 +474,15 @@ bitflags! {
473 /// if a global bound is safe to evaluate. 474 /// if a global bound is safe to evaluate.
474 const HAS_RE_LATE_BOUND = 1 << 11; 475 const HAS_RE_LATE_BOUND = 1 << 11;
475 476
476 const HAS_TY_PLACEHOLDER = 1 << 12; 477 /// Does this have any `ReErased` regions?
478 const HAS_RE_ERASED = 1 << 12;
477 479
478 const HAS_CT_INFER = 1 << 13; 480 const HAS_TY_PLACEHOLDER = 1 << 13;
479 const HAS_CT_PLACEHOLDER = 1 << 14; 481
482 const HAS_CT_INFER = 1 << 14;
483 const HAS_CT_PLACEHOLDER = 1 << 15;
484 /// Does this have any [Opaque] types.
485 const HAS_TY_OPAQUE = 1 << 16;
480 486
481 const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits | 487 const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits |
482 TypeFlags::HAS_RE_EARLY_BOUND.bits; 488 TypeFlags::HAS_RE_EARLY_BOUND.bits;
@@ -496,9 +502,11 @@ bitflags! {
496 TypeFlags::HAS_FREE_LOCAL_NAMES.bits | 502 TypeFlags::HAS_FREE_LOCAL_NAMES.bits |
497 TypeFlags::KEEP_IN_LOCAL_TCX.bits | 503 TypeFlags::KEEP_IN_LOCAL_TCX.bits |
498 TypeFlags::HAS_RE_LATE_BOUND.bits | 504 TypeFlags::HAS_RE_LATE_BOUND.bits |
505 TypeFlags::HAS_RE_ERASED.bits |
499 TypeFlags::HAS_TY_PLACEHOLDER.bits | 506 TypeFlags::HAS_TY_PLACEHOLDER.bits |
500 TypeFlags::HAS_CT_INFER.bits | 507 TypeFlags::HAS_CT_INFER.bits |
501 TypeFlags::HAS_CT_PLACEHOLDER.bits; 508 TypeFlags::HAS_CT_PLACEHOLDER.bits |
509 TypeFlags::HAS_TY_OPAQUE.bits;
502 } 510 }
503} 511}
504 512
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 0718853..02abac9 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -1777,7 +1777,9 @@ impl RegionKind {
1777 ty::ReEmpty(_) | ty::ReStatic | ty::ReFree { .. } | ty::ReScope { .. } => { 1777 ty::ReEmpty(_) | ty::ReStatic | ty::ReFree { .. } | ty::ReScope { .. } => {
1778 flags = flags | TypeFlags::HAS_FREE_REGIONS; 1778 flags = flags | TypeFlags::HAS_FREE_REGIONS;
1779 } 1779 }
1780 ty::ReErased => {} 1780 ty::ReErased => {
1781 flags = flags | TypeFlags::HAS_RE_ERASED;
1782 }
1781 ty::ReClosureBound(..) => { 1783 ty::ReClosureBound(..) => {
1782 flags = flags | TypeFlags::HAS_FREE_REGIONS; 1784 flags = flags | TypeFlags::HAS_FREE_REGIONS;
1783 } 1785 }
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index db7b8d8..f3c3d04 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -615,7 +615,7 @@ impl<'tcx> TyCtxt<'tcx> {
615 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { 615 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
616 if let ty::Opaque(def_id, substs) = t.kind { 616 if let ty::Opaque(def_id, substs) = t.kind {
617 self.expand_opaque_ty(def_id, substs).unwrap_or(t) 617 self.expand_opaque_ty(def_id, substs).unwrap_or(t)
618 } else if t.has_projections() { 618 } else if t.has_opaque_types() {
619 t.super_fold_with(self) 619 t.super_fold_with(self)
620 } else { 620 } else {
621 t 621 t
diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs
index 73a2562..426659f 100644
--- a/src/librustc_ast_lowering/item.rs
+++ b/src/librustc_ast_lowering/item.rs
@@ -272,7 +272,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
272 let ty = self.lower_ty( 272 let ty = self.lower_ty(
273 t, 273 t,
274 if self.sess.features_untracked().impl_trait_in_bindings { 274 if self.sess.features_untracked().impl_trait_in_bindings {
275 ImplTraitContext::OpaqueTy(None) 275 ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc)
276 } else { 276 } else {
277 ImplTraitContext::Disallowed(ImplTraitPosition::Binding) 277 ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
278 }, 278 },
@@ -283,7 +283,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
283 let ty = self.lower_ty( 283 let ty = self.lower_ty(
284 t, 284 t,
285 if self.sess.features_untracked().impl_trait_in_bindings { 285 if self.sess.features_untracked().impl_trait_in_bindings {
286 ImplTraitContext::OpaqueTy(None) 286 ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc)
287 } else { 287 } else {
288 ImplTraitContext::Disallowed(ImplTraitPosition::Binding) 288 ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
289 }, 289 },
@@ -327,8 +327,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
327 } 327 }
328 Some(bounds) => { 328 Some(bounds) => {
329 let ty = hir::OpaqueTy { 329 let ty = hir::OpaqueTy {
330 generics: self.lower_generics(generics, ImplTraitContext::OpaqueTy(None)), 330 generics: self.lower_generics(
331 bounds: self.lower_param_bounds(bounds, ImplTraitContext::OpaqueTy(None)), 331 generics,
332 ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc),
333 ),
334 bounds: self.lower_param_bounds(
335 bounds,
336 ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc),
337 ),
332 impl_trait_fn: None, 338 impl_trait_fn: None,
333 origin: hir::OpaqueTyOrigin::TypeAlias, 339 origin: hir::OpaqueTyOrigin::TypeAlias,
334 }; 340 };
diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs
index 618b1e79..99de4b8 100644
--- a/src/librustc_ast_lowering/lib.rs
+++ b/src/librustc_ast_lowering/lib.rs
@@ -222,7 +222,7 @@ enum ImplTraitContext<'b, 'a> {
222 /// We optionally store a `DefId` for the parent item here so we can look up necessary 222 /// We optionally store a `DefId` for the parent item here so we can look up necessary
223 /// information later. It is `None` when no information about the context should be stored 223 /// information later. It is `None` when no information about the context should be stored
224 /// (e.g., for consts and statics). 224 /// (e.g., for consts and statics).
225 OpaqueTy(Option<DefId> /* fn def-ID */), 225 OpaqueTy(Option<DefId> /* fn def-ID */, hir::OpaqueTyOrigin),
226 226
227 /// `impl Trait` is not accepted in this position. 227 /// `impl Trait` is not accepted in this position.
228 Disallowed(ImplTraitPosition), 228 Disallowed(ImplTraitPosition),
@@ -248,7 +248,7 @@ impl<'a> ImplTraitContext<'_, 'a> {
248 use self::ImplTraitContext::*; 248 use self::ImplTraitContext::*;
249 match self { 249 match self {
250 Universal(params) => Universal(params), 250 Universal(params) => Universal(params),
251 OpaqueTy(fn_def_id) => OpaqueTy(*fn_def_id), 251 OpaqueTy(fn_def_id, origin) => OpaqueTy(*fn_def_id, *origin),
252 Disallowed(pos) => Disallowed(*pos), 252 Disallowed(pos) => Disallowed(*pos),
253 } 253 }
254 } 254 }
@@ -1010,7 +1010,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1010 // so desugar to 1010 // so desugar to
1011 // 1011 //
1012 // fn foo() -> impl Iterator<Item = impl Debug> 1012 // fn foo() -> impl Iterator<Item = impl Debug>
1013 ImplTraitContext::OpaqueTy(_) => (true, itctx), 1013 ImplTraitContext::OpaqueTy(..) => (true, itctx),
1014 1014
1015 // We are in the argument position, but within a dyn type: 1015 // We are in the argument position, but within a dyn type:
1016 // 1016 //
@@ -1019,7 +1019,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1019 // so desugar to 1019 // so desugar to
1020 // 1020 //
1021 // fn foo(x: dyn Iterator<Item = impl Debug>) 1021 // fn foo(x: dyn Iterator<Item = impl Debug>)
1022 ImplTraitContext::Universal(_) if self.is_in_dyn_type => (true, itctx), 1022 ImplTraitContext::Universal(..) if self.is_in_dyn_type => (true, itctx),
1023 1023
1024 // In `type Foo = dyn Iterator<Item: Debug>` we desugar to 1024 // In `type Foo = dyn Iterator<Item: Debug>` we desugar to
1025 // `type Foo = dyn Iterator<Item = impl Debug>` but we have to override the 1025 // `type Foo = dyn Iterator<Item = impl Debug>` but we have to override the
@@ -1028,7 +1028,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1028 // 1028 //
1029 // FIXME: this is only needed until `impl Trait` is allowed in type aliases. 1029 // FIXME: this is only needed until `impl Trait` is allowed in type aliases.
1030 ImplTraitContext::Disallowed(_) if self.is_in_dyn_type => { 1030 ImplTraitContext::Disallowed(_) if self.is_in_dyn_type => {
1031 (true, ImplTraitContext::OpaqueTy(None)) 1031 (true, ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc))
1032 } 1032 }
1033 1033
1034 // We are in the parameter position, but not within a dyn type: 1034 // We are in the parameter position, but not within a dyn type:
@@ -1269,8 +1269,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1269 TyKind::ImplTrait(def_node_id, ref bounds) => { 1269 TyKind::ImplTrait(def_node_id, ref bounds) => {
1270 let span = t.span; 1270 let span = t.span;
1271 match itctx { 1271 match itctx {
1272 ImplTraitContext::OpaqueTy(fn_def_id) => { 1272 ImplTraitContext::OpaqueTy(fn_def_id, origin) => {
1273 self.lower_opaque_impl_trait(span, fn_def_id, def_node_id, |this| { 1273 self.lower_opaque_impl_trait(span, fn_def_id, origin, def_node_id, |this| {
1274 this.lower_param_bounds(bounds, itctx) 1274 this.lower_param_bounds(bounds, itctx)
1275 }) 1275 })
1276 } 1276 }
@@ -1349,6 +1349,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1349 &mut self, 1349 &mut self,
1350 span: Span, 1350 span: Span,
1351 fn_def_id: Option<DefId>, 1351 fn_def_id: Option<DefId>,
1352 origin: hir::OpaqueTyOrigin,
1352 opaque_ty_node_id: NodeId, 1353 opaque_ty_node_id: NodeId,
1353 lower_bounds: impl FnOnce(&mut Self) -> hir::GenericBounds<'hir>, 1354 lower_bounds: impl FnOnce(&mut Self) -> hir::GenericBounds<'hir>,
1354 ) -> hir::TyKind<'hir> { 1355 ) -> hir::TyKind<'hir> {
@@ -1390,7 +1391,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1390 }, 1391 },
1391 bounds: hir_bounds, 1392 bounds: hir_bounds,
1392 impl_trait_fn: fn_def_id, 1393 impl_trait_fn: fn_def_id,
1393 origin: hir::OpaqueTyOrigin::FnReturn, 1394 origin,
1394 }; 1395 };
1395 1396
1396 trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_index); 1397 trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_index);
@@ -1622,7 +1623,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1622 self.lower_ty( 1623 self.lower_ty(
1623 t, 1624 t,
1624 if self.sess.features_untracked().impl_trait_in_bindings { 1625 if self.sess.features_untracked().impl_trait_in_bindings {
1625 ImplTraitContext::OpaqueTy(Some(parent_def_id)) 1626 ImplTraitContext::OpaqueTy(Some(parent_def_id), hir::OpaqueTyOrigin::Misc)
1626 } else { 1627 } else {
1627 ImplTraitContext::Disallowed(ImplTraitPosition::Binding) 1628 ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
1628 }, 1629 },
@@ -1722,14 +1723,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1722 ) 1723 )
1723 } else { 1724 } else {
1724 match decl.output { 1725 match decl.output {
1725 FunctionRetTy::Ty(ref ty) => match in_band_ty_params { 1726 FunctionRetTy::Ty(ref ty) => {
1726 Some((def_id, _)) if impl_trait_return_allow => hir::FunctionRetTy::Return( 1727 let context = match in_band_ty_params {
1727 self.lower_ty(ty, ImplTraitContext::OpaqueTy(Some(def_id))), 1728 Some((def_id, _)) if impl_trait_return_allow => {
1728 ), 1729 ImplTraitContext::OpaqueTy(Some(def_id), hir::OpaqueTyOrigin::FnReturn)
1729 _ => hir::FunctionRetTy::Return( 1730 }
1730 self.lower_ty(ty, ImplTraitContext::disallowed()), 1731 _ => ImplTraitContext::disallowed(),
1731 ), 1732 };
1732 }, 1733 hir::FunctionRetTy::Return(self.lower_ty(ty, context))
1734 }
1733 FunctionRetTy::Default(span) => hir::FunctionRetTy::DefaultReturn(span), 1735 FunctionRetTy::Default(span) => hir::FunctionRetTy::DefaultReturn(span),
1734 } 1736 }
1735 }; 1737 };
@@ -1957,7 +1959,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
1957 ) -> hir::GenericBound<'hir> { 1959 ) -> hir::GenericBound<'hir> {
1958 // Compute the `T` in `Future<Output = T>` from the return type. 1960 // Compute the `T` in `Future<Output = T>` from the return type.
1959 let output_ty = match output { 1961 let output_ty = match output {
1960 FunctionRetTy::Ty(ty) => self.lower_ty(ty, ImplTraitContext::OpaqueTy(Some(fn_def_id))), 1962 FunctionRetTy::Ty(ty) => {
1963 // Not `OpaqueTyOrigin::AsyncFn`: that's only used for the
1964 // `impl Future` opaque type that `async fn` implicitly
1965 // generates.
1966 let context =
1967 ImplTraitContext::OpaqueTy(Some(fn_def_id), hir::OpaqueTyOrigin::FnReturn);
1968 self.lower_ty(ty, context)
1969 }
1961 FunctionRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])), 1970 FunctionRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])),
1962 }; 1971 };
1963 1972
@@ -2102,9 +2111,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
2102 } 2111 }
2103 2112
2104 let kind = hir::GenericParamKind::Type { 2113 let kind = hir::GenericParamKind::Type {
2105 default: default 2114 default: default.as_ref().map(|x| {
2106 .as_ref() 2115 self.lower_ty(
2107 .map(|x| self.lower_ty(x, ImplTraitContext::OpaqueTy(None))), 2116 x,
2117 ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc),
2118 )
2119 }),
2108 synthetic: param 2120 synthetic: param
2109 .attrs 2121 .attrs
2110 .iter() 2122 .iter()
diff --git a/src/librustc_ast_lowering/pat.rs b/src/librustc_ast_lowering/pat.rs
index 4c3c4dd..b42b12c 100644
--- a/src/librustc_ast_lowering/pat.rs
+++ b/src/librustc_ast_lowering/pat.rs
@@ -128,6 +128,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
128 let mut slice = None; 128 let mut slice = None;
129 let mut prev_rest_span = None; 129 let mut prev_rest_span = None;
130 130
131 // Lowers `$bm $ident @ ..` to `$bm $ident @ _`.
132 let lower_rest_sub = |this: &mut Self, pat, bm, ident, sub| {
133 let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub));
134 let node = this.lower_pat_ident(pat, bm, ident, lower_sub);
135 this.pat_with_node_id_of(pat, node)
136 };
137
131 let mut iter = pats.iter(); 138 let mut iter = pats.iter();
132 // Lower all the patterns until the first occurrence of a sub-slice pattern. 139 // Lower all the patterns until the first occurrence of a sub-slice pattern.
133 for pat in iter.by_ref() { 140 for pat in iter.by_ref() {
@@ -142,9 +149,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
142 // Record, lower it to `$binding_mode $ident @ _`, and stop here. 149 // Record, lower it to `$binding_mode $ident @ _`, and stop here.
143 PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => { 150 PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
144 prev_rest_span = Some(sub.span); 151 prev_rest_span = Some(sub.span);
145 let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub)); 152 slice = Some(lower_rest_sub(self, pat, bm, ident, sub));
146 let node = self.lower_pat_ident(pat, bm, ident, lower_sub);
147 slice = Some(self.pat_with_node_id_of(pat, node));
148 break; 153 break;
149 } 154 }
150 // It was not a subslice pattern so lower it normally. 155 // It was not a subslice pattern so lower it normally.
@@ -157,9 +162,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
157 // There was a previous subslice pattern; make sure we don't allow more. 162 // There was a previous subslice pattern; make sure we don't allow more.
158 let rest_span = match pat.kind { 163 let rest_span = match pat.kind {
159 PatKind::Rest => Some(pat.span), 164 PatKind::Rest => Some(pat.span),
160 PatKind::Ident(.., Some(ref sub)) if sub.is_rest() => { 165 PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
161 // The `HirValidator` is merciless; add a `_` pattern to avoid ICEs. 166 // #69103: Lower into `binding @ _` as above to avoid ICEs.
162 after.push(self.pat_wild_with_node_id_of(pat)); 167 after.push(lower_rest_sub(self, pat, bm, ident, sub));
163 Some(sub.span) 168 Some(sub.span)
164 } 169 }
165 _ => None, 170 _ => None,
diff --git a/src/librustc_data_structures/obligation_forest/graphviz.rs b/src/librustc_data_structures/obligation_forest/graphviz.rs
index 0fd83da..e1784f4 100644
--- a/src/librustc_data_structures/obligation_forest/graphviz.rs
+++ b/src/librustc_data_structures/obligation_forest/graphviz.rs
@@ -52,7 +52,7 @@ impl<'a, O: ForestObligation + 'a> dot::Labeller<'a> for &'a ObligationForest<O>
52 52
53 fn node_label(&self, index: &Self::Node) -> dot::LabelText<'_> { 53 fn node_label(&self, index: &Self::Node) -> dot::LabelText<'_> {
54 let node = &self.nodes[*index]; 54 let node = &self.nodes[*index];
55 let label = format!("{:?} ({:?})", node.obligation.as_predicate(), node.state.get()); 55 let label = format!("{:?} ({:?})", node.obligation.as_cache_key(), node.state.get());
56 56
57 dot::LabelText::LabelStr(label.into()) 57 dot::LabelText::LabelStr(label.into())
58 } 58 }
diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs
index 0384776..334dadd 100644
--- a/src/librustc_data_structures/obligation_forest/mod.rs
+++ b/src/librustc_data_structures/obligation_forest/mod.rs
@@ -86,9 +86,13 @@ mod graphviz;
86mod tests; 86mod tests;
87 87
88pub trait ForestObligation: Clone + Debug { 88pub trait ForestObligation: Clone + Debug {
89 type Predicate: Clone + hash::Hash + Eq + Debug; 89 type CacheKey: Clone + hash::Hash + Eq + Debug;
90 90
91 fn as_predicate(&self) -> &Self::Predicate; 91 /// Converts this `ForestObligation` suitable for use as a cache key.
92 /// If two distinct `ForestObligations`s return the same cache key,
93 /// then it must be sound to use the result of processing one obligation
94 /// (e.g. success for error) for the other obligation
95 fn as_cache_key(&self) -> Self::CacheKey;
92} 96}
93 97
94pub trait ObligationProcessor { 98pub trait ObligationProcessor {
@@ -138,12 +142,12 @@ pub struct ObligationForest<O: ForestObligation> {
138 nodes: Vec<Node<O>>, 142 nodes: Vec<Node<O>>,
139 143
140 /// A cache of predicates that have been successfully completed. 144 /// A cache of predicates that have been successfully completed.
141 done_cache: FxHashSet<O::Predicate>, 145 done_cache: FxHashSet<O::CacheKey>,
142 146
143 /// A cache of the nodes in `nodes`, indexed by predicate. Unfortunately, 147 /// A cache of the nodes in `nodes`, indexed by predicate. Unfortunately,
144 /// its contents are not guaranteed to match those of `nodes`. See the 148 /// its contents are not guaranteed to match those of `nodes`. See the
145 /// comments in `process_obligation` for details. 149 /// comments in `process_obligation` for details.
146 active_cache: FxHashMap<O::Predicate, usize>, 150 active_cache: FxHashMap<O::CacheKey, usize>,
147 151
148 /// A vector reused in compress(), to avoid allocating new vectors. 152 /// A vector reused in compress(), to avoid allocating new vectors.
149 node_rewrites: Vec<usize>, 153 node_rewrites: Vec<usize>,
@@ -157,7 +161,7 @@ pub struct ObligationForest<O: ForestObligation> {
157 /// See [this][details] for details. 161 /// See [this][details] for details.
158 /// 162 ///
159 /// [details]: https://github.com/rust-lang/rust/pull/53255#issuecomment-421184780 163 /// [details]: https://github.com/rust-lang/rust/pull/53255#issuecomment-421184780
160 error_cache: FxHashMap<ObligationTreeId, FxHashSet<O::Predicate>>, 164 error_cache: FxHashMap<ObligationTreeId, FxHashSet<O::CacheKey>>,
161} 165}
162 166
163#[derive(Debug)] 167#[derive(Debug)]
@@ -305,11 +309,12 @@ impl<O: ForestObligation> ObligationForest<O> {
305 309
306 // Returns Err(()) if we already know this obligation failed. 310 // Returns Err(()) if we already know this obligation failed.
307 fn register_obligation_at(&mut self, obligation: O, parent: Option<usize>) -> Result<(), ()> { 311 fn register_obligation_at(&mut self, obligation: O, parent: Option<usize>) -> Result<(), ()> {
308 if self.done_cache.contains(obligation.as_predicate()) { 312 if self.done_cache.contains(&obligation.as_cache_key()) {
313 debug!("register_obligation_at: ignoring already done obligation: {:?}", obligation);
309 return Ok(()); 314 return Ok(());
310 } 315 }
311 316
312 match self.active_cache.entry(obligation.as_predicate().clone()) { 317 match self.active_cache.entry(obligation.as_cache_key().clone()) {
313 Entry::Occupied(o) => { 318 Entry::Occupied(o) => {
314 let node = &mut self.nodes[*o.get()]; 319 let node = &mut self.nodes[*o.get()];
315 if let Some(parent_index) = parent { 320 if let Some(parent_index) = parent {
@@ -333,7 +338,7 @@ impl<O: ForestObligation> ObligationForest<O> {
333 && self 338 && self
334 .error_cache 339 .error_cache
335 .get(&obligation_tree_id) 340 .get(&obligation_tree_id)
336 .map(|errors| errors.contains(obligation.as_predicate())) 341 .map(|errors| errors.contains(&obligation.as_cache_key()))
337 .unwrap_or(false); 342 .unwrap_or(false);
338 343
339 if already_failed { 344 if already_failed {
@@ -380,7 +385,7 @@ impl<O: ForestObligation> ObligationForest<O> {
380 self.error_cache 385 self.error_cache
381 .entry(node.obligation_tree_id) 386 .entry(node.obligation_tree_id)
382 .or_default() 387 .or_default()
383 .insert(node.obligation.as_predicate().clone()); 388 .insert(node.obligation.as_cache_key().clone());
384 } 389 }
385 390
386 /// Performs a pass through the obligation list. This must 391 /// Performs a pass through the obligation list. This must
@@ -618,11 +623,11 @@ impl<O: ForestObligation> ObligationForest<O> {
618 // `self.nodes`. See the comment in `process_obligation` 623 // `self.nodes`. See the comment in `process_obligation`
619 // for more details. 624 // for more details.
620 if let Some((predicate, _)) = 625 if let Some((predicate, _)) =
621 self.active_cache.remove_entry(node.obligation.as_predicate()) 626 self.active_cache.remove_entry(&node.obligation.as_cache_key())
622 { 627 {
623 self.done_cache.insert(predicate); 628 self.done_cache.insert(predicate);
624 } else { 629 } else {
625 self.done_cache.insert(node.obligation.as_predicate().clone()); 630 self.done_cache.insert(node.obligation.as_cache_key().clone());
626 } 631 }
627 if do_completed == DoCompleted::Yes { 632 if do_completed == DoCompleted::Yes {
628 // Extract the success stories. 633 // Extract the success stories.
@@ -635,7 +640,7 @@ impl<O: ForestObligation> ObligationForest<O> {
635 // We *intentionally* remove the node from the cache at this point. Otherwise 640 // We *intentionally* remove the node from the cache at this point. Otherwise
636 // tests must come up with a different type on every type error they 641 // tests must come up with a different type on every type error they
637 // check against. 642 // check against.
638 self.active_cache.remove(node.obligation.as_predicate()); 643 self.active_cache.remove(&node.obligation.as_cache_key());
639 self.insert_into_error_cache(index); 644 self.insert_into_error_cache(index);
640 node_rewrites[index] = orig_nodes_len; 645 node_rewrites[index] = orig_nodes_len;
641 dead_nodes += 1; 646 dead_nodes += 1;
diff --git a/src/librustc_data_structures/obligation_forest/tests.rs b/src/librustc_data_structures/obligation_forest/tests.rs
index e29335a..0165246 100644
--- a/src/librustc_data_structures/obligation_forest/tests.rs
+++ b/src/librustc_data_structures/obligation_forest/tests.rs
@@ -4,9 +4,9 @@ use std::fmt;
4use std::marker::PhantomData; 4use std::marker::PhantomData;
5 5
6impl<'a> super::ForestObligation for &'a str { 6impl<'a> super::ForestObligation for &'a str {
7 type Predicate = &'a str; 7 type CacheKey = &'a str;
8 8
9 fn as_predicate(&self) -> &Self::Predicate { 9 fn as_cache_key(&self) -> Self::CacheKey {
10 self 10 self
11 } 11 }
12} 12}
diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs
index 9e6edee..f6abcce 100644
--- a/src/librustc_expand/mbe/macro_rules.rs
+++ b/src/librustc_expand/mbe/macro_rules.rs
@@ -191,9 +191,9 @@ fn generic_extension<'cx>(
191 let mut best_failure: Option<(Token, &str)> = None; 191 let mut best_failure: Option<(Token, &str)> = None;
192 192
193 // We create a base parser that can be used for the "black box" parts. 193 // We create a base parser that can be used for the "black box" parts.
194 // Every iteration needs a fresh copy of that base parser. However, the 194 // Every iteration needs a fresh copy of that parser. However, the parser
195 // parser is not mutated on many of the iterations, particularly when 195 // is not mutated on many of the iterations, particularly when dealing with
196 // dealing with macros like this: 196 // macros like this:
197 // 197 //
198 // macro_rules! foo { 198 // macro_rules! foo {
199 // ("a") => (A); 199 // ("a") => (A);
@@ -209,11 +209,9 @@ fn generic_extension<'cx>(
209 // hacky, but speeds up the `html5ever` benchmark significantly. (Issue 209 // hacky, but speeds up the `html5ever` benchmark significantly. (Issue
210 // 68836 suggests a more comprehensive but more complex change to deal with 210 // 68836 suggests a more comprehensive but more complex change to deal with
211 // this situation.) 211 // this situation.)
212 let base_parser = base_parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone()); 212 let parser = parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone());
213 213
214 for (i, lhs) in lhses.iter().enumerate() { 214 for (i, lhs) in lhses.iter().enumerate() {
215 let mut parser = Cow::Borrowed(&base_parser);
216
217 // try each arm's matchers 215 // try each arm's matchers
218 let lhs_tt = match *lhs { 216 let lhs_tt = match *lhs {
219 mbe::TokenTree::Delimited(_, ref delim) => &delim.tts[..], 217 mbe::TokenTree::Delimited(_, ref delim) => &delim.tts[..],
@@ -224,13 +222,14 @@ fn generic_extension<'cx>(
224 // This is used so that if a matcher is not `Success(..)`ful, 222 // This is used so that if a matcher is not `Success(..)`ful,
225 // then the spans which became gated when parsing the unsuccessful matcher 223 // then the spans which became gated when parsing the unsuccessful matcher
226 // are not recorded. On the first `Success(..)`ful matcher, the spans are merged. 224 // are not recorded. On the first `Success(..)`ful matcher, the spans are merged.
227 let mut gated_spans_snaphot = mem::take(&mut *cx.parse_sess.gated_spans.spans.borrow_mut()); 225 let mut gated_spans_snapshot =
226 mem::take(&mut *cx.parse_sess.gated_spans.spans.borrow_mut());
228 227
229 match parse_tt(&mut parser, lhs_tt) { 228 match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt) {
230 Success(named_matches) => { 229 Success(named_matches) => {
231 // The matcher was `Success(..)`ful. 230 // The matcher was `Success(..)`ful.
232 // Merge the gated spans from parsing the matcher with the pre-existing ones. 231 // Merge the gated spans from parsing the matcher with the pre-existing ones.
233 cx.parse_sess.gated_spans.merge(gated_spans_snaphot); 232 cx.parse_sess.gated_spans.merge(gated_spans_snapshot);
234 233
235 let rhs = match rhses[i] { 234 let rhs = match rhses[i] {
236 // ignore delimiters 235 // ignore delimiters
@@ -291,9 +290,9 @@ fn generic_extension<'cx>(
291 290
292 // The matcher was not `Success(..)`ful. 291 // The matcher was not `Success(..)`ful.
293 // Restore to the state before snapshotting and maybe try again. 292 // Restore to the state before snapshotting and maybe try again.
294 mem::swap(&mut gated_spans_snaphot, &mut cx.parse_sess.gated_spans.spans.borrow_mut()); 293 mem::swap(&mut gated_spans_snapshot, &mut cx.parse_sess.gated_spans.spans.borrow_mut());
295 } 294 }
296 drop(base_parser); 295 drop(parser);
297 296
298 let (token, label) = best_failure.expect("ran no matchers"); 297 let (token, label) = best_failure.expect("ran no matchers");
299 let span = token.span.substitute_dummy(sp); 298 let span = token.span.substitute_dummy(sp);
@@ -311,9 +310,8 @@ fn generic_extension<'cx>(
311 mbe::TokenTree::Delimited(_, ref delim) => &delim.tts[..], 310 mbe::TokenTree::Delimited(_, ref delim) => &delim.tts[..],
312 _ => continue, 311 _ => continue,
313 }; 312 };
314 let base_parser = 313 let parser = parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone());
315 base_parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone()); 314 match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt) {
316 match parse_tt(&mut Cow::Borrowed(&base_parser), lhs_tt) {
317 Success(_) => { 315 Success(_) => {
318 if comma_span.is_dummy() { 316 if comma_span.is_dummy() {
319 err.note("you might be missing a comma"); 317 err.note("you might be missing a comma");
@@ -395,8 +393,8 @@ pub fn compile_declarative_macro(
395 ), 393 ),
396 ]; 394 ];
397 395
398 let base_parser = Parser::new(sess, body, None, true, true, rustc_parse::MACRO_ARGUMENTS); 396 let parser = Parser::new(sess, body, None, true, true, rustc_parse::MACRO_ARGUMENTS);
399 let argument_map = match parse_tt(&mut Cow::Borrowed(&base_parser), &argument_gram) { 397 let argument_map = match parse_tt(&mut Cow::Borrowed(&parser), &argument_gram) {
400 Success(m) => m, 398 Success(m) => m,
401 Failure(token, msg) => { 399 Failure(token, msg) => {
402 let s = parse_failure_msg(&token); 400 let s = parse_failure_msg(&token);
@@ -1212,7 +1210,7 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String {
1212 } 1210 }
1213} 1211}
1214 1212
1215fn base_parser_from_cx<'cx>( 1213fn parser_from_cx<'cx>(
1216 current_expansion: &'cx ExpansionData, 1214 current_expansion: &'cx ExpansionData,
1217 sess: &'cx ParseSess, 1215 sess: &'cx ParseSess,
1218 tts: TokenStream, 1216 tts: TokenStream,
diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs
index 80b3792..07a2c48 100644
--- a/src/librustc_hir/hir.rs
+++ b/src/librustc_hir/hir.rs
@@ -1990,6 +1990,8 @@ pub enum OpaqueTyOrigin {
1990 FnReturn, 1990 FnReturn,
1991 /// `async fn` 1991 /// `async fn`
1992 AsyncFn, 1992 AsyncFn,
1993 /// Impl trait in bindings, consts, statics, bounds.
1994 Misc,
1993} 1995}
1994 1996
1995/// The various kinds of types recognized by the compiler. 1997/// The various kinds of types recognized by the compiler.
diff --git a/src/librustc_interface/callbacks.rs b/src/librustc_interface/callbacks.rs
index 803e895..7c8e682 100644
--- a/src/librustc_interface/callbacks.rs
+++ b/src/librustc_interface/callbacks.rs
@@ -58,4 +58,5 @@ pub fn setup_callbacks() {
58 rustc_span::SPAN_DEBUG.swap(&(span_debug as fn(_, &mut fmt::Formatter<'_>) -> _)); 58 rustc_span::SPAN_DEBUG.swap(&(span_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
59 rustc_hir::def_id::DEF_ID_DEBUG.swap(&(def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _)); 59 rustc_hir::def_id::DEF_ID_DEBUG.swap(&(def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
60 TRACK_DIAGNOSTICS.swap(&(track_diagnostic as fn(&_))); 60 TRACK_DIAGNOSTICS.swap(&(track_diagnostic as fn(&_)));
61 rustc::ty::RESOLVE_INSTANCE.swap(&(rustc_ty::instance::resolve_instance as _));
61} 62}
diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
index 0e040ec..b393d4b 100644
--- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
@@ -6,7 +6,6 @@ use rustc::infer::{
6use rustc::mir::ConstraintCategory; 6use rustc::mir::ConstraintCategory;
7use rustc::ty::{self, RegionVid, Ty}; 7use rustc::ty::{self, RegionVid, Ty};
8use rustc_errors::{Applicability, DiagnosticBuilder}; 8use rustc_errors::{Applicability, DiagnosticBuilder};
9use rustc_hir::def_id::DefId;
10use rustc_span::symbol::kw; 9use rustc_span::symbol::kw;
11use rustc_span::Span; 10use rustc_span::Span;
12 11
@@ -58,8 +57,8 @@ crate enum RegionErrorKind<'tcx> {
58 57
59 /// An unexpected hidden region for an opaque type. 58 /// An unexpected hidden region for an opaque type.
60 UnexpectedHiddenRegion { 59 UnexpectedHiddenRegion {
61 /// The def id of the opaque type. 60 /// The span for the member constraint.
62 opaque_type_def_id: DefId, 61 span: Span,
63 /// The hidden type. 62 /// The hidden type.
64 hidden_ty: Ty<'tcx>, 63 hidden_ty: Ty<'tcx>,
65 /// The unexpected region. 64 /// The unexpected region.
@@ -194,18 +193,16 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
194 } 193 }
195 } 194 }
196 195
197 RegionErrorKind::UnexpectedHiddenRegion { 196 RegionErrorKind::UnexpectedHiddenRegion { span, hidden_ty, member_region } => {
198 opaque_type_def_id,
199 hidden_ty,
200 member_region,
201 } => {
202 let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id); 197 let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id);
198 let named_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty);
199 let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
203 opaque_types::unexpected_hidden_region_diagnostic( 200 opaque_types::unexpected_hidden_region_diagnostic(
204 self.infcx.tcx, 201 self.infcx.tcx,
205 Some(region_scope_tree), 202 Some(region_scope_tree),
206 opaque_type_def_id, 203 span,
207 hidden_ty, 204 named_ty,
208 member_region, 205 named_region,
209 ) 206 )
210 .buffer(&mut self.errors_buffer); 207 .buffer(&mut self.errors_buffer);
211 } 208 }
@@ -588,6 +585,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
588 { 585 {
589 found = true; 586 found = true;
590 break; 587 break;
588 } else {
589 // If there's already a lifetime bound, don't
590 // suggest anything.
591 return;
591 } 592 }
592 } 593 }
593 } 594 }
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 941534e..f9db62e 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -90,7 +90,7 @@ pub fn provide(providers: &mut Providers<'_>) {
90 *providers = Providers { mir_borrowck, ..*providers }; 90 *providers = Providers { mir_borrowck, ..*providers };
91} 91}
92 92
93fn mir_borrowck(tcx: TyCtxt<'_>, def_id: DefId) -> BorrowCheckResult<'_> { 93fn mir_borrowck(tcx: TyCtxt<'_>, def_id: DefId) -> &BorrowCheckResult<'_> {
94 let (input_body, promoted) = tcx.mir_validated(def_id); 94 let (input_body, promoted) = tcx.mir_validated(def_id);
95 debug!("run query mir_borrowck: {}", tcx.def_path_str(def_id)); 95 debug!("run query mir_borrowck: {}", tcx.def_path_str(def_id));
96 96
@@ -101,7 +101,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def_id: DefId) -> BorrowCheckResult<'_> {
101 }); 101 });
102 debug!("mir_borrowck done"); 102 debug!("mir_borrowck done");
103 103
104 opt_closure_req 104 tcx.arena.alloc(opt_closure_req)
105} 105}
106 106
107fn do_mir_borrowck<'a, 'tcx>( 107fn do_mir_borrowck<'a, 'tcx>(
@@ -136,6 +136,9 @@ fn do_mir_borrowck<'a, 'tcx>(
136 136
137 // Gather the upvars of a closure, if any. 137 // Gather the upvars of a closure, if any.
138 let tables = tcx.typeck_tables_of(def_id); 138 let tables = tcx.typeck_tables_of(def_id);
139 if tables.tainted_by_errors {
140 infcx.set_tainted_by_errors();
141 }
139 let upvars: Vec<_> = tables 142 let upvars: Vec<_> = tables
140 .upvar_list 143 .upvar_list
141 .get(&def_id) 144 .get(&def_id)
@@ -195,27 +198,40 @@ fn do_mir_borrowck<'a, 'tcx>(
195 Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data)); 198 Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data));
196 199
197 // Compute non-lexical lifetimes. 200 // Compute non-lexical lifetimes.
198 let nll::NllOutput { regioncx, polonius_output, opt_closure_req, nll_errors } = 201 let nll::NllOutput {
199 nll::compute_regions( 202 regioncx,
200 infcx, 203 opaque_type_values,
201 def_id, 204 polonius_output,
202 free_regions, 205 opt_closure_req,
203 body, 206 nll_errors,
204 &promoted, 207 } = nll::compute_regions(
205 location_table, 208 infcx,
206 param_env, 209 def_id,
207 &mut flow_inits, 210 free_regions,
208 &mdpe.move_data, 211 body,
209 &borrow_set, 212 &promoted,
210 ); 213 location_table,
214 param_env,
215 &mut flow_inits,
216 &mdpe.move_data,
217 &borrow_set,
218 );
211 219
212 // Dump MIR results into a file, if that is enabled. This let us 220 // Dump MIR results into a file, if that is enabled. This let us
213 // write unit-tests, as well as helping with debugging. 221 // write unit-tests, as well as helping with debugging.
214 nll::dump_mir_results(infcx, MirSource::item(def_id), &body, &regioncx, &opt_closure_req); 222 nll::dump_mir_results(infcx, MirSource::item(def_id), &body, &regioncx, &opt_closure_req);
215 223
216 // We also have a `#[rustc_nll]` annotation that causes us to dump 224 // We also have a `#[rustc_regions]` annotation that causes us to dump
217 // information. 225 // information.
218 nll::dump_annotation(infcx, &body, def_id, &regioncx, &opt_closure_req, &mut errors_buffer); 226 nll::dump_annotation(
227 infcx,
228 &body,
229 def_id,
230 &regioncx,
231 &opt_closure_req,
232 &opaque_type_values,
233 &mut errors_buffer,
234 );
219 235
220 // The various `flow_*` structures can be large. We drop `flow_inits` here 236 // The various `flow_*` structures can be large. We drop `flow_inits` here
221 // so it doesn't overlap with the others below. This reduces peak memory 237 // so it doesn't overlap with the others below. This reduces peak memory
@@ -389,6 +405,7 @@ fn do_mir_borrowck<'a, 'tcx>(
389 } 405 }
390 406
391 let result = BorrowCheckResult { 407 let result = BorrowCheckResult {
408 concrete_opaque_types: opaque_type_values,
392 closure_requirements: opt_closure_req, 409 closure_requirements: opt_closure_req,
393 used_mut_upvars: mbcx.used_mut_upvars, 410 used_mut_upvars: mbcx.used_mut_upvars,
394 }; 411 };
diff --git a/src/librustc_mir/borrow_check/nll.rs b/src/librustc_mir/borrow_check/nll.rs
index a71dfc9..101d185 100644
--- a/src/librustc_mir/borrow_check/nll.rs
+++ b/src/librustc_mir/borrow_check/nll.rs
@@ -6,6 +6,7 @@ use rustc::mir::{
6 Location, Promoted, ReadOnlyBodyAndCache, 6 Location, Promoted, ReadOnlyBodyAndCache,
7}; 7};
8use rustc::ty::{self, RegionKind, RegionVid}; 8use rustc::ty::{self, RegionKind, RegionVid};
9use rustc_data_structures::fx::FxHashMap;
9use rustc_errors::Diagnostic; 10use rustc_errors::Diagnostic;
10use rustc_hir::def_id::DefId; 11use rustc_hir::def_id::DefId;
11use rustc_index::vec::IndexVec; 12use rustc_index::vec::IndexVec;
@@ -46,6 +47,7 @@ crate type PoloniusOutput = Output<RustcFacts>;
46/// closure requirements to propagate, and any generated errors. 47/// closure requirements to propagate, and any generated errors.
47crate struct NllOutput<'tcx> { 48crate struct NllOutput<'tcx> {
48 pub regioncx: RegionInferenceContext<'tcx>, 49 pub regioncx: RegionInferenceContext<'tcx>,
50 pub opaque_type_values: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
49 pub polonius_output: Option<Rc<PoloniusOutput>>, 51 pub polonius_output: Option<Rc<PoloniusOutput>>,
50 pub opt_closure_req: Option<ClosureRegionRequirements<'tcx>>, 52 pub opt_closure_req: Option<ClosureRegionRequirements<'tcx>>,
51 pub nll_errors: RegionErrors<'tcx>, 53 pub nll_errors: RegionErrors<'tcx>,
@@ -160,20 +162,21 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
160 let elements = &Rc::new(RegionValueElements::new(&body)); 162 let elements = &Rc::new(RegionValueElements::new(&body));
161 163
162 // Run the MIR type-checker. 164 // Run the MIR type-checker.
163 let MirTypeckResults { constraints, universal_region_relations } = type_check::type_check( 165 let MirTypeckResults { constraints, universal_region_relations, opaque_type_values } =
164 infcx, 166 type_check::type_check(
165 param_env, 167 infcx,
166 body, 168 param_env,
167 promoted, 169 body,
168 def_id, 170 promoted,
169 &universal_regions, 171 def_id,
170 location_table, 172 &universal_regions,
171 borrow_set, 173 location_table,
172 &mut all_facts, 174 borrow_set,
173 flow_inits, 175 &mut all_facts,
174 move_data, 176 flow_inits,
175 elements, 177 move_data,
176 ); 178 elements,
179 );
177 180
178 if let Some(all_facts) = &mut all_facts { 181 if let Some(all_facts) = &mut all_facts {
179 let _prof_timer = infcx.tcx.prof.generic_activity("polonius_fact_generation"); 182 let _prof_timer = infcx.tcx.prof.generic_activity("polonius_fact_generation");
@@ -279,8 +282,16 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
279 let (closure_region_requirements, nll_errors) = 282 let (closure_region_requirements, nll_errors) =
280 regioncx.solve(infcx, &body, def_id, polonius_output.clone()); 283 regioncx.solve(infcx, &body, def_id, polonius_output.clone());
281 284
285 if !nll_errors.is_empty() {
286 // Suppress unhelpful extra errors in `infer_opaque_types`.
287 infcx.set_tainted_by_errors();
288 }
289
290 let remapped_opaque_tys = regioncx.infer_opaque_types(&infcx, opaque_type_values, body.span);
291
282 NllOutput { 292 NllOutput {
283 regioncx, 293 regioncx,
294 opaque_type_values: remapped_opaque_tys,
284 polonius_output, 295 polonius_output,
285 opt_closure_req: closure_region_requirements, 296 opt_closure_req: closure_region_requirements,
286 nll_errors, 297 nll_errors,
@@ -344,6 +355,7 @@ pub(super) fn dump_annotation<'a, 'tcx>(
344 mir_def_id: DefId, 355 mir_def_id: DefId,
345 regioncx: &RegionInferenceContext<'tcx>, 356 regioncx: &RegionInferenceContext<'tcx>,
346 closure_region_requirements: &Option<ClosureRegionRequirements<'_>>, 357 closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
358 opaque_type_values: &FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
347 errors_buffer: &mut Vec<Diagnostic>, 359 errors_buffer: &mut Vec<Diagnostic>,
348) { 360) {
349 let tcx = infcx.tcx; 361 let tcx = infcx.tcx;
@@ -359,7 +371,7 @@ pub(super) fn dump_annotation<'a, 'tcx>(
359 // viewing the intraprocedural state, the -Zdump-mir output is 371 // viewing the intraprocedural state, the -Zdump-mir output is
360 // better. 372 // better.
361 373
362 if let Some(closure_region_requirements) = closure_region_requirements { 374 let mut err = if let Some(closure_region_requirements) = closure_region_requirements {
363 let mut err = tcx.sess.diagnostic().span_note_diag(body.span, "external requirements"); 375 let mut err = tcx.sess.diagnostic().span_note_diag(body.span, "external requirements");
364 376
365 regioncx.annotate(tcx, &mut err); 377 regioncx.annotate(tcx, &mut err);
@@ -377,13 +389,19 @@ pub(super) fn dump_annotation<'a, 'tcx>(
377 }) 389 })
378 .unwrap(); 390 .unwrap();
379 391
380 err.buffer(errors_buffer); 392 err
381 } else { 393 } else {
382 let mut err = tcx.sess.diagnostic().span_note_diag(body.span, "no external requirements"); 394 let mut err = tcx.sess.diagnostic().span_note_diag(body.span, "no external requirements");
383 regioncx.annotate(tcx, &mut err); 395 regioncx.annotate(tcx, &mut err);
384 396
385 err.buffer(errors_buffer); 397 err
398 };
399
400 if !opaque_type_values.is_empty() {
401 err.note(&format!("Inferred opaque type values:\n{:#?}", opaque_type_values));
386 } 402 }
403
404 err.buffer(errors_buffer);
387} 405}
388 406
389fn for_each_region_constraint( 407fn for_each_region_constraint(
diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs
index 6abca48..192e470 100644
--- a/src/librustc_mir/borrow_check/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/region_infer/mod.rs
@@ -12,8 +12,6 @@ use rustc::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable};
12use rustc_data_structures::binary_search_util; 12use rustc_data_structures::binary_search_util;
13use rustc_data_structures::fx::{FxHashMap, FxHashSet}; 13use rustc_data_structures::fx::{FxHashMap, FxHashSet};
14use rustc_data_structures::graph::scc::Sccs; 14use rustc_data_structures::graph::scc::Sccs;
15use rustc_data_structures::graph::vec_graph::VecGraph;
16use rustc_data_structures::graph::WithSuccessors;
17use rustc_hir::def_id::DefId; 15use rustc_hir::def_id::DefId;
18use rustc_index::bit_set::BitSet; 16use rustc_index::bit_set::BitSet;
19use rustc_index::vec::IndexVec; 17use rustc_index::vec::IndexVec;
@@ -26,6 +24,7 @@ use crate::borrow_check::{
26 diagnostics::{RegionErrorKind, RegionErrors}, 24 diagnostics::{RegionErrorKind, RegionErrors},
27 member_constraints::{MemberConstraintSet, NllMemberConstraintIndex}, 25 member_constraints::{MemberConstraintSet, NllMemberConstraintIndex},
28 nll::{PoloniusOutput, ToRegionVid}, 26 nll::{PoloniusOutput, ToRegionVid},
27 region_infer::reverse_sccs::ReverseSccGraph,
29 region_infer::values::{ 28 region_infer::values::{
30 LivenessValues, PlaceholderIndices, RegionElement, RegionValueElements, RegionValues, 29 LivenessValues, PlaceholderIndices, RegionElement, RegionValueElements, RegionValues,
31 ToElementIndex, 30 ToElementIndex,
@@ -36,6 +35,8 @@ use crate::borrow_check::{
36 35
37mod dump_mir; 36mod dump_mir;
38mod graphviz; 37mod graphviz;
38mod opaque_types;
39mod reverse_sccs;
39 40
40pub mod values; 41pub mod values;
41 42
@@ -65,9 +66,10 @@ pub struct RegionInferenceContext<'tcx> {
65 /// compute the values of each region. 66 /// compute the values of each region.
66 constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>, 67 constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
67 68
68 /// Reverse of the SCC constraint graph -- i.e., an edge `A -> B` 69 /// Reverse of the SCC constraint graph -- i.e., an edge `A -> B` exists if
69 /// exists if `B: A`. Computed lazilly. 70 /// `B: A`. This is used to compute the universal regions that are required
70 rev_constraint_graph: Option<Rc<VecGraph<ConstraintSccIndex>>>, 71 /// to outlive a given SCC. Computed lazily.
72 rev_scc_graph: Option<Rc<ReverseSccGraph>>,
71 73
72 /// The "R0 member of [R1..Rn]" constraints, indexed by SCC. 74 /// The "R0 member of [R1..Rn]" constraints, indexed by SCC.
73 member_constraints: Rc<MemberConstraintSet<'tcx, ConstraintSccIndex>>, 75 member_constraints: Rc<MemberConstraintSet<'tcx, ConstraintSccIndex>>,
@@ -287,7 +289,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
287 constraints, 289 constraints,
288 constraint_graph, 290 constraint_graph,
289 constraint_sccs, 291 constraint_sccs,
290 rev_constraint_graph: None, 292 rev_scc_graph: None,
291 member_constraints, 293 member_constraints,
292 member_constraints_applied: Vec::new(), 294 member_constraints_applied: Vec::new(),
293 closure_bounds_mapping, 295 closure_bounds_mapping,
@@ -510,7 +512,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
510 self.check_universal_regions(body, outlives_requirements.as_mut(), &mut errors_buffer); 512 self.check_universal_regions(body, outlives_requirements.as_mut(), &mut errors_buffer);
511 } 513 }
512 514
513 self.check_member_constraints(infcx, &mut errors_buffer); 515 if errors_buffer.is_empty() {
516 self.check_member_constraints(infcx, &mut errors_buffer);
517 }
514 518
515 let outlives_requirements = outlives_requirements.unwrap_or(vec![]); 519 let outlives_requirements = outlives_requirements.unwrap_or(vec![]);
516 520
@@ -677,15 +681,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
677 // free region that must outlive the member region `R0` (`UB: 681 // free region that must outlive the member region `R0` (`UB:
678 // R0`). Therefore, we need only keep an option `O` if `UB: O` 682 // R0`). Therefore, we need only keep an option `O` if `UB: O`
679 // for all UB. 683 // for all UB.
680 if choice_regions.len() > 1 { 684 let rev_scc_graph = self.reverse_scc_graph();
681 let universal_region_relations = self.universal_region_relations.clone(); 685 let universal_region_relations = &self.universal_region_relations;
682 let rev_constraint_graph = self.rev_constraint_graph(); 686 for ub in rev_scc_graph.upper_bounds(scc) {
683 for ub in self.upper_bounds(scc, &rev_constraint_graph) { 687 debug!("apply_member_constraint: ub={:?}", ub);
684 debug!("apply_member_constraint: ub={:?}", ub); 688 choice_regions.retain(|&o_r| universal_region_relations.outlives(ub, o_r));
685 choice_regions.retain(|&o_r| universal_region_relations.outlives(ub, o_r));
686 }
687 debug!("apply_member_constraint: after ub, choice_regions={:?}", choice_regions);
688 } 689 }
690 debug!("apply_member_constraint: after ub, choice_regions={:?}", choice_regions);
689 691
690 // If we ruled everything out, we're done. 692 // If we ruled everything out, we're done.
691 if choice_regions.is_empty() { 693 if choice_regions.is_empty() {
@@ -741,32 +743,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
741 } 743 }
742 } 744 }
743 745
744 /// Compute and return the reverse SCC-based constraint graph (lazilly).
745 fn upper_bounds(
746 &'a mut self,
747 scc0: ConstraintSccIndex,
748 rev_constraint_graph: &'a VecGraph<ConstraintSccIndex>,
749 ) -> impl Iterator<Item = RegionVid> + 'a {
750 let scc_values = &self.scc_values;
751 let mut duplicates = FxHashSet::default();
752 rev_constraint_graph
753 .depth_first_search(scc0)
754 .skip(1)
755 .flat_map(move |scc1| scc_values.universal_regions_outlived_by(scc1))
756 .filter(move |&r| duplicates.insert(r))
757 }
758
759 /// Compute and return the reverse SCC-based constraint graph (lazilly).
760 fn rev_constraint_graph(&mut self) -> Rc<VecGraph<ConstraintSccIndex>> {
761 if let Some(g) = &self.rev_constraint_graph {
762 return g.clone();
763 }
764
765 let rev_graph = Rc::new(self.constraint_sccs.reverse());
766 self.rev_constraint_graph = Some(rev_graph.clone());
767 rev_graph
768 }
769
770 /// Returns `true` if all the elements in the value of `scc_b` are nameable 746 /// Returns `true` if all the elements in the value of `scc_b` are nameable
771 /// in `scc_a`. Used during constraint propagation, and only once 747 /// in `scc_a`. Used during constraint propagation, and only once
772 /// the value of `scc_b` has been computed. 748 /// the value of `scc_b` has been computed.
@@ -1603,7 +1579,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1603 // If not, report an error. 1579 // If not, report an error.
1604 let member_region = infcx.tcx.mk_region(ty::ReVar(member_region_vid)); 1580 let member_region = infcx.tcx.mk_region(ty::ReVar(member_region_vid));
1605 errors_buffer.push(RegionErrorKind::UnexpectedHiddenRegion { 1581 errors_buffer.push(RegionErrorKind::UnexpectedHiddenRegion {
1606 opaque_type_def_id: m_c.opaque_type_def_id, 1582 span: m_c.definition_span,
1607 hidden_ty: m_c.hidden_ty, 1583 hidden_ty: m_c.hidden_ty,
1608 member_region, 1584 member_region,
1609 }); 1585 });
diff --git a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs
new file mode 100644
index 0000000..52d54f7
--- /dev/null
+++ b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs
@@ -0,0 +1,149 @@
1use rustc::infer::InferCtxt;
2use rustc::ty::{self, TyCtxt, TypeFoldable};
3use rustc_data_structures::fx::FxHashMap;
4use rustc_hir::def_id::DefId;
5use rustc_span::Span;
6
7use super::RegionInferenceContext;
8
9impl<'tcx> RegionInferenceContext<'tcx> {
10 /// Resolve any opaque types that were encountered while borrow checking
11 /// this item. This is then used to get the type in the `type_of` query.
12 ///
13 /// For example consider `fn f<'a>(x: &'a i32) -> impl Sized + 'a { x }`.
14 /// This is lowered to give HIR something like
15 ///
16 /// type f<'a>::_Return<'_a> = impl Sized + '_a;
17 /// fn f<'a>(x: &'a i32) -> f<'static>::_Return<'a> { x }
18 ///
19 /// When checking the return type record the type from the return and the
20 /// type used in the return value. In this case they might be `_Return<'1>`
21 /// and `&'2 i32` respectively.
22 ///
23 /// Once we to this method, we have completed region inference and want to
24 /// call `infer_opaque_definition_from_instantiation` to get the inferred
25 /// type of `_Return<'_a>`. `infer_opaque_definition_from_instantiation`
26 /// compares lifetimes directly, so we need to map the inference variables
27 /// back to concrete lifetimes: `'static`, `ReEarlyBound` or `ReFree`.
28 ///
29 /// First we map all the lifetimes in the concrete type to an equal
30 /// universal region that occurs in the concrete type's substs, in this case
31 /// this would result in `&'1 i32`. We only consider regions in the substs
32 /// in case there is an equal region that does not. For example, this should
33 /// be allowed:
34 /// `fn f<'a: 'b, 'b: 'a>(x: *mut &'b i32) -> impl Sized + 'a { x }`
35 ///
36 /// Then we map the regions in both the type and the subst to their
37 /// `external_name` giving `concrete_type = &'a i32`,
38 /// `substs = ['static, 'a]`. This will then allow
39 /// `infer_opaque_definition_from_instantiation` to determine that
40 /// `_Return<'_a> = &'_a i32`.
41 ///
42 /// There's a slight complication around closures. Given
43 /// `fn f<'a: 'a>() { || {} }` the closure's type is something like
44 /// `f::<'a>::{{closure}}`. The region parameter from f is essentially
45 /// ignored by type checking so ends up being inferred to an empty region.
46 /// Calling `universal_upper_bound` for such a region gives `fr_fn_body`,
47 /// which has no `external_name` in which case we use `'empty` as the
48 /// region to pass to `infer_opaque_definition_from_instantiation`.
49 pub(in crate::borrow_check) fn infer_opaque_types(
50 &self,
51 infcx: &InferCtxt<'_, 'tcx>,
52 opaque_ty_decls: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
53 span: Span,
54 ) -> FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>> {
55 opaque_ty_decls
56 .into_iter()
57 .map(|(opaque_def_id, ty::ResolvedOpaqueTy { concrete_type, substs })| {
58 debug!(
59 "infer_opaque_types(concrete_type = {:?}, substs = {:?})",
60 concrete_type, substs
61 );
62
63 let mut subst_regions = vec![self.universal_regions.fr_static];
64 let universal_substs =
65 infcx.tcx.fold_regions(&substs, &mut false, |region, _| match *region {
66 ty::ReVar(vid) => {
67 subst_regions.push(vid);
68 self.definitions[vid].external_name.unwrap_or_else(|| {
69 infcx.tcx.sess.delay_span_bug(
70 span,
71 "opaque type with non-universal region substs",
72 );
73 infcx.tcx.lifetimes.re_static
74 })
75 }
76 // We don't fold regions in the predicates of opaque
77 // types to `ReVar`s. This means that in a case like
78 //
79 // fn f<'a: 'a>() -> impl Iterator<Item = impl Sized>
80 //
81 // The inner opaque type has `'static` in its substs.
82 ty::ReStatic => region,
83 _ => {
84 infcx.tcx.sess.delay_span_bug(
85 span,
86 &format!("unexpected concrete region in borrowck: {:?}", region),
87 );
88 region
89 }
90 });
91
92 subst_regions.sort();
93 subst_regions.dedup();
94
95 let universal_concrete_type =
96 infcx.tcx.fold_regions(&concrete_type, &mut false, |region, _| match *region {
97 ty::ReVar(vid) => subst_regions
98 .iter()
99 .find(|ur_vid| self.eval_equal(vid, **ur_vid))
100 .and_then(|ur_vid| self.definitions[*ur_vid].external_name)
101 .unwrap_or(infcx.tcx.lifetimes.re_root_empty),
102 ty::ReLateBound(..) => region,
103 _ => {
104 infcx.tcx.sess.delay_span_bug(
105 span,
106 &format!("unexpected concrete region in borrowck: {:?}", region),
107 );
108 region
109 }
110 });
111
112 debug!(
113 "infer_opaque_types(universal_concrete_type = {:?}, universal_substs = {:?})",
114 universal_concrete_type, universal_substs
115 );
116
117 let remapped_type = infcx.infer_opaque_definition_from_instantiation(
118 opaque_def_id,
119 universal_substs,
120 universal_concrete_type,
121 span,
122 );
123 (
124 opaque_def_id,
125 ty::ResolvedOpaqueTy { concrete_type: remapped_type, substs: universal_substs },
126 )
127 })
128 .collect()
129 }
130
131 /// Map the regions in the type to named regions. This is similar to what
132 /// `infer_opaque_types` does, but can infer any universal region, not only
133 /// ones from the substs for the opaque type. It also doesn't double check
134 /// that the regions produced are in fact equal to the named region they are
135 /// replaced with. This is fine because this function is only to improve the
136 /// region names in error messages.
137 pub(in crate::borrow_check) fn name_regions<T>(&self, tcx: TyCtxt<'tcx>, ty: T) -> T
138 where
139 T: TypeFoldable<'tcx>,
140 {
141 tcx.fold_regions(&ty, &mut false, |region, _| match *region {
142 ty::ReVar(vid) => {
143 let upper_bound = self.universal_upper_bound(vid);
144 self.definitions[upper_bound].external_name.unwrap_or(region)
145 }
146 _ => region,
147 })
148 }
149}
diff --git a/src/librustc_mir/borrow_check/region_infer/reverse_sccs.rs b/src/librustc_mir/borrow_check/region_infer/reverse_sccs.rs
new file mode 100644
index 0000000..4b8357b
--- /dev/null
+++ b/src/librustc_mir/borrow_check/region_infer/reverse_sccs.rs
@@ -0,0 +1,68 @@
1use crate::borrow_check::constraints::ConstraintSccIndex;
2use crate::borrow_check::RegionInferenceContext;
3use itertools::Itertools;
4use rustc::ty::RegionVid;
5use rustc_data_structures::fx::{FxHashMap, FxHashSet};
6use rustc_data_structures::graph::vec_graph::VecGraph;
7use rustc_data_structures::graph::WithSuccessors;
8use std::ops::Range;
9use std::rc::Rc;
10
11crate struct ReverseSccGraph {
12 graph: VecGraph<ConstraintSccIndex>,
13 /// For each SCC, the range of `universal_regions` that use that SCC as
14 /// their value.
15 scc_regions: FxHashMap<ConstraintSccIndex, Range<usize>>,
16 /// All of the universal regions, in grouped so that `scc_regions` can
17 /// index into here.
18 universal_regions: Vec<RegionVid>,
19}
20
21impl ReverseSccGraph {
22 /// Find all universal regions that are required to outlive the given SCC.
23 pub(super) fn upper_bounds<'a>(
24 &'a self,
25 scc0: ConstraintSccIndex,
26 ) -> impl Iterator<Item = RegionVid> + 'a {
27 let mut duplicates = FxHashSet::default();
28 self.graph
29 .depth_first_search(scc0)
30 .flat_map(move |scc1| {
31 self.scc_regions
32 .get(&scc1)
33 .map_or(&[][..], |range| &self.universal_regions[range.clone()])
34 })
35 .copied()
36 .filter(move |r| duplicates.insert(*r))
37 }
38}
39
40impl RegionInferenceContext<'_> {
41 /// Compute and return the reverse SCC-based constraint graph (lazily).
42 pub(super) fn reverse_scc_graph(&mut self) -> Rc<ReverseSccGraph> {
43 if let Some(g) = &self.rev_scc_graph {
44 return g.clone();
45 }
46
47 let graph = self.constraint_sccs.reverse();
48 let mut paired_scc_regions = self
49 .universal_regions
50 .universal_regions()
51 .map(|region| (self.constraint_sccs.scc(region), region))
52 .collect_vec();
53 paired_scc_regions.sort();
54 let universal_regions = paired_scc_regions.iter().map(|&(_, region)| region).collect();
55
56 let mut scc_regions = FxHashMap::default();
57 let mut start = 0;
58 for (scc, group) in &paired_scc_regions.into_iter().group_by(|(scc, _)| *scc) {
59 let group_size = group.into_iter().count();
60 scc_regions.insert(scc, start..start + group_size);
61 start += group_size;
62 }
63
64 let rev_graph = Rc::new(ReverseSccGraph { graph, scc_regions, universal_regions });
65 self.rev_scc_graph = Some(rev_graph.clone());
66 rev_graph
67 }
68}
diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs
index 5dab064..88fe6d1 100644
--- a/src/librustc_mir/borrow_check/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/type_check/mod.rs
@@ -6,6 +6,7 @@ use std::{fmt, iter, mem};
6use either::Either; 6use either::Either;
7 7
8use rustc::infer::canonical::QueryRegionConstraints; 8use rustc::infer::canonical::QueryRegionConstraints;
9use rustc::infer::opaque_types::GenerateMemberConstraints;
9use rustc::infer::outlives::env::RegionBoundPairs; 10use rustc::infer::outlives::env::RegionBoundPairs;
10use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; 11use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
11use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin}; 12use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
@@ -158,7 +159,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
158 constraints: &mut constraints, 159 constraints: &mut constraints,
159 }; 160 };
160 161
161 type_check_internal( 162 let opaque_type_values = type_check_internal(
162 infcx, 163 infcx,
163 mir_def_id, 164 mir_def_id,
164 param_env, 165 param_env,
@@ -173,10 +174,11 @@ pub(crate) fn type_check<'mir, 'tcx>(
173 liveness::generate(&mut cx, body, elements, flow_inits, move_data, location_table); 174 liveness::generate(&mut cx, body, elements, flow_inits, move_data, location_table);
174 175
175 translate_outlives_facts(&mut cx); 176 translate_outlives_facts(&mut cx);
177 cx.opaque_type_values
176 }, 178 },
177 ); 179 );
178 180
179 MirTypeckResults { constraints, universal_region_relations } 181 MirTypeckResults { constraints, universal_region_relations, opaque_type_values }
180} 182}
181 183
182fn type_check_internal<'a, 'tcx, R>( 184fn type_check_internal<'a, 'tcx, R>(
@@ -189,7 +191,7 @@ fn type_check_internal<'a, 'tcx, R>(
189 implicit_region_bound: ty::Region<'tcx>, 191 implicit_region_bound: ty::Region<'tcx>,
190 borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, 192 borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
191 universal_region_relations: &'a UniversalRegionRelations<'tcx>, 193 universal_region_relations: &'a UniversalRegionRelations<'tcx>,
192 mut extra: impl FnMut(&mut TypeChecker<'a, 'tcx>) -> R, 194 extra: impl FnOnce(TypeChecker<'a, 'tcx>) -> R,
193) -> R { 195) -> R {
194 let mut checker = TypeChecker::new( 196 let mut checker = TypeChecker::new(
195 infcx, 197 infcx,
@@ -212,7 +214,7 @@ fn type_check_internal<'a, 'tcx, R>(
212 checker.typeck_mir(body); 214 checker.typeck_mir(body);
213 } 215 }
214 216
215 extra(&mut checker) 217 extra(checker)
216} 218}
217 219
218fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) { 220fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) {
@@ -799,6 +801,7 @@ struct TypeChecker<'a, 'tcx> {
799 reported_errors: FxHashSet<(Ty<'tcx>, Span)>, 801 reported_errors: FxHashSet<(Ty<'tcx>, Span)>,
800 borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, 802 borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
801 universal_region_relations: &'a UniversalRegionRelations<'tcx>, 803 universal_region_relations: &'a UniversalRegionRelations<'tcx>,
804 opaque_type_values: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
802} 805}
803 806
804struct BorrowCheckContext<'a, 'tcx> { 807struct BorrowCheckContext<'a, 'tcx> {
@@ -812,6 +815,7 @@ struct BorrowCheckContext<'a, 'tcx> {
812crate struct MirTypeckResults<'tcx> { 815crate struct MirTypeckResults<'tcx> {
813 crate constraints: MirTypeckRegionConstraints<'tcx>, 816 crate constraints: MirTypeckRegionConstraints<'tcx>,
814 crate universal_region_relations: Rc<UniversalRegionRelations<'tcx>>, 817 crate universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
818 crate opaque_type_values: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
815} 819}
816 820
817/// A collection of region constraints that must be satisfied for the 821/// A collection of region constraints that must be satisfied for the
@@ -958,6 +962,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
958 borrowck_context, 962 borrowck_context,
959 reported_errors: Default::default(), 963 reported_errors: Default::default(),
960 universal_region_relations, 964 universal_region_relations,
965 opaque_type_values: FxHashMap::default(),
961 }; 966 };
962 checker.check_user_type_annotations(); 967 checker.check_user_type_annotations();
963 checker 968 checker
@@ -1191,10 +1196,29 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1191 anon_ty={:?})", 1196 anon_ty={:?})",
1192 revealed_ty, anon_ty 1197 revealed_ty, anon_ty
1193 ); 1198 );
1199
1200 // Fast path for the common case.
1201 if !anon_ty.has_opaque_types() {
1202 if let Err(terr) = self.eq_types(anon_ty, revealed_ty, locations, category) {
1203 span_mirbug!(
1204 self,
1205 locations,
1206 "eq_opaque_type_and_type: `{:?}=={:?}` failed with `{:?}`",
1207 revealed_ty,
1208 anon_ty,
1209 terr
1210 );
1211 }
1212 return Ok(());
1213 }
1214
1194 let infcx = self.infcx; 1215 let infcx = self.infcx;
1195 let tcx = infcx.tcx; 1216 let tcx = infcx.tcx;
1196 let param_env = self.param_env; 1217 let param_env = self.param_env;
1197 let body = self.body; 1218 let body = self.body;
1219 let concrete_opaque_types = &tcx.typeck_tables_of(anon_owner_def_id).concrete_opaque_types;
1220 let mut opaque_type_values = Vec::new();
1221
1198 debug!("eq_opaque_type_and_type: mir_def_id={:?}", self.mir_def_id); 1222 debug!("eq_opaque_type_and_type: mir_def_id={:?}", self.mir_def_id);
1199 let opaque_type_map = self.fully_perform_op( 1223 let opaque_type_map = self.fully_perform_op(
1200 locations, 1224 locations,
@@ -1219,6 +1243,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1219 revealed_ty={:?}", 1243 revealed_ty={:?}",
1220 output_ty, opaque_type_map, revealed_ty 1244 output_ty, opaque_type_map, revealed_ty
1221 ); 1245 );
1246 // Make sure that the inferred types are well-formed. I'm
1247 // not entirely sure this is needed (the HIR type check
1248 // didn't do this) but it seems sensible to prevent opaque
1249 // types hiding ill-formed types.
1250 obligations.obligations.push(traits::Obligation::new(
1251 ObligationCause::dummy(),
1252 param_env,
1253 ty::Predicate::WellFormed(revealed_ty),
1254 ));
1222 obligations.add( 1255 obligations.add(
1223 infcx 1256 infcx
1224 .at(&ObligationCause::dummy(), param_env) 1257 .at(&ObligationCause::dummy(), param_env)
@@ -1226,47 +1259,76 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1226 ); 1259 );
1227 1260
1228 for (&opaque_def_id, opaque_decl) in &opaque_type_map { 1261 for (&opaque_def_id, opaque_decl) in &opaque_type_map {
1229 let opaque_defn_ty = tcx.type_of(opaque_def_id); 1262 let resolved_ty = infcx.resolve_vars_if_possible(&opaque_decl.concrete_ty);
1230 let opaque_defn_ty = opaque_defn_ty.subst(tcx, opaque_decl.substs); 1263 let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind {
1231 let opaque_defn_ty = renumber::renumber_regions(infcx, &opaque_defn_ty); 1264 def_id == opaque_def_id
1232 let concrete_is_opaque = infcx 1265 } else {
1233 .resolve_vars_if_possible(&opaque_decl.concrete_ty) 1266 false
1234 .is_impl_trait(); 1267 };
1268 let opaque_defn_ty = match concrete_opaque_types.get(&opaque_def_id) {
1269 None => {
1270 if !concrete_is_opaque {
1271 tcx.sess.delay_span_bug(
1272 body.span,
1273 &format!(
1274 "Non-defining use of {:?} with revealed type",
1275 opaque_def_id,
1276 ),
1277 );
1278 }
1279 continue;
1280 }
1281 Some(opaque_defn_ty) => opaque_defn_ty,
1282 };
1283 debug!("opaque_defn_ty = {:?}", opaque_defn_ty);
1284 let subst_opaque_defn_ty =
1285 opaque_defn_ty.concrete_type.subst(tcx, opaque_decl.substs);
1286 let renumbered_opaque_defn_ty =
1287 renumber::renumber_regions(infcx, &subst_opaque_defn_ty);
1235 1288
1236 debug!( 1289 debug!(
1237 "eq_opaque_type_and_type: concrete_ty={:?}={:?} opaque_defn_ty={:?} \ 1290 "eq_opaque_type_and_type: concrete_ty={:?}={:?} opaque_defn_ty={:?}",
1238 concrete_is_opaque={}", 1291 opaque_decl.concrete_ty, resolved_ty, renumbered_opaque_defn_ty,
1239 opaque_decl.concrete_ty,
1240 infcx.resolve_vars_if_possible(&opaque_decl.concrete_ty),
1241 opaque_defn_ty,
1242 concrete_is_opaque
1243 ); 1292 );
1244 1293
1245 // concrete_is_opaque is `true` when we're using an opaque `impl Trait`
1246 // type without 'revealing' it. For example, code like this:
1247 //
1248 // type Foo = impl Debug;
1249 // fn foo1() -> Foo { ... }
1250 // fn foo2() -> Foo { foo1() }
1251 //
1252 // In `foo2`, we're not revealing the type of `Foo` - we're
1253 // just treating it as the opaque type.
1254 //
1255 // When this occurs, we do *not* want to try to equate
1256 // the concrete type with the underlying defining type
1257 // of the opaque type - this will always fail, since
1258 // the defining type of an opaque type is always
1259 // some other type (e.g. not itself)
1260 // Essentially, none of the normal obligations apply here -
1261 // we're just passing around some unknown opaque type,
1262 // without actually looking at the underlying type it
1263 // gets 'revealed' into
1264
1265 if !concrete_is_opaque { 1294 if !concrete_is_opaque {
1295 // Equate concrete_ty (an inference variable) with
1296 // the renumbered type from typeck.
1266 obligations.add( 1297 obligations.add(
1267 infcx 1298 infcx
1268 .at(&ObligationCause::dummy(), param_env) 1299 .at(&ObligationCause::dummy(), param_env)
1269 .eq(opaque_decl.concrete_ty, opaque_defn_ty)?, 1300 .eq(opaque_decl.concrete_ty, renumbered_opaque_defn_ty)?,
1301 );
1302 opaque_type_values.push((
1303 opaque_def_id,
1304 ty::ResolvedOpaqueTy {
1305 concrete_type: renumbered_opaque_defn_ty,
1306 substs: opaque_decl.substs,
1307 },
1308 ));
1309 } else {
1310 // We're using an opaque `impl Trait` type without
1311 // 'revealing' it. For example, code like this:
1312 //
1313 // type Foo = impl Debug;
1314 // fn foo1() -> Foo { ... }
1315 // fn foo2() -> Foo { foo1() }
1316 //
1317 // In `foo2`, we're not revealing the type of `Foo` - we're
1318 // just treating it as the opaque type.
1319 //
1320 // When this occurs, we do *not* want to try to equate
1321 // the concrete type with the underlying defining type
1322 // of the opaque type - this will always fail, since
1323 // the defining type of an opaque type is always
1324 // some other type (e.g. not itself)
1325 // Essentially, none of the normal obligations apply here -
1326 // we're just passing around some unknown opaque type,
1327 // without actually looking at the underlying type it
1328 // gets 'revealed' into
1329 debug!(
1330 "eq_opaque_type_and_type: non-defining use of {:?}",
1331 opaque_def_id,
1270 ); 1332 );
1271 } 1333 }
1272 } 1334 }
@@ -1282,6 +1344,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1282 ), 1344 ),
1283 )?; 1345 )?;
1284 1346
1347 self.opaque_type_values.extend(opaque_type_values);
1348
1285 let universal_region_relations = self.universal_region_relations; 1349 let universal_region_relations = self.universal_region_relations;
1286 1350
1287 // Finally, if we instantiated the anon types successfully, we 1351 // Finally, if we instantiated the anon types successfully, we
@@ -1298,6 +1362,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1298 infcx.constrain_opaque_type( 1362 infcx.constrain_opaque_type(
1299 opaque_def_id, 1363 opaque_def_id,
1300 &opaque_decl, 1364 &opaque_decl,
1365 GenerateMemberConstraints::IfNoStaticBound,
1301 universal_region_relations, 1366 universal_region_relations,
1302 ); 1367 );
1303 Ok(InferOk { value: (), obligations: vec![] }) 1368 Ok(InferOk { value: (), obligations: vec![] })
@@ -2512,7 +2577,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
2512 substs: SubstsRef<'tcx>, 2577 substs: SubstsRef<'tcx>,
2513 location: Location, 2578 location: Location,
2514 ) -> ty::InstantiatedPredicates<'tcx> { 2579 ) -> ty::InstantiatedPredicates<'tcx> {
2515 if let Some(closure_region_requirements) = tcx.mir_borrowck(def_id).closure_requirements { 2580 if let Some(ref closure_region_requirements) = tcx.mir_borrowck(def_id).closure_requirements
2581 {
2516 let closure_constraints = QueryRegionConstraints { 2582 let closure_constraints = QueryRegionConstraints {
2517 outlives: closure_region_requirements.apply_requirements(tcx, def_id, substs), 2583 outlives: closure_region_requirements.apply_requirements(tcx, def_id, substs),
2518 2584
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 6e80338..fab5501 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -178,6 +178,16 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
178 } 178 }
179 179
180 fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { 180 fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
181 // prevent
182 // * `&mut x.field`
183 // * `x.field = y;`
184 // * `&x.field` if `field`'s type has interior mutability
185 // because either of these would allow modifying the layout constrained field and
186 // insert values that violate the layout constraints.
187 if context.is_mutating_use() || context.is_borrow() {
188 self.check_mut_borrowing_layout_constrained_field(place, context.is_mutating_use());
189 }
190
181 for (i, elem) in place.projection.iter().enumerate() { 191 for (i, elem) in place.projection.iter().enumerate() {
182 let proj_base = &place.projection[..i]; 192 let proj_base = &place.projection[..i];
183 193
@@ -198,24 +208,9 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
198 ); 208 );
199 } 209 }
200 } 210 }
201 let is_borrow_of_interior_mut = context.is_borrow()
202 && !Place::ty_from(place.local, proj_base, self.body, self.tcx).ty.is_freeze(
203 self.tcx,
204 self.param_env,
205 self.source_info.span,
206 );
207 // prevent
208 // * `&mut x.field`
209 // * `x.field = y;`
210 // * `&x.field` if `field`'s type has interior mutability
211 // because either of these would allow modifying the layout constrained field and
212 // insert values that violate the layout constraints.
213 if context.is_mutating_use() || is_borrow_of_interior_mut {
214 self.check_mut_borrowing_layout_constrained_field(place, context.is_mutating_use());
215 }
216 let old_source_info = self.source_info; 211 let old_source_info = self.source_info;
217 if let (local, []) = (&place.local, proj_base) { 212 if let [] = proj_base {
218 let decl = &self.body.local_decls[*local]; 213 let decl = &self.body.local_decls[place.local];
219 if decl.internal { 214 if decl.internal {
220 if let LocalInfo::StaticRef { def_id, .. } = decl.local_info { 215 if let LocalInfo::StaticRef { def_id, .. } = decl.local_info {
221 if self.tcx.is_mutable_static(def_id) { 216 if self.tcx.is_mutable_static(def_id) {
@@ -240,7 +235,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
240 // Internal locals are used in the `move_val_init` desugaring. 235 // Internal locals are used in the `move_val_init` desugaring.
241 // We want to check unsafety against the source info of the 236 // We want to check unsafety against the source info of the
242 // desugaring, rather than the source info of the RHS. 237 // desugaring, rather than the source info of the RHS.
243 self.source_info = self.body.local_decls[*local].source_info; 238 self.source_info = self.body.local_decls[place.local].source_info;
244 } 239 }
245 } 240 }
246 } 241 }
@@ -396,6 +391,9 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
396 cursor = proj_base; 391 cursor = proj_base;
397 392
398 match elem { 393 match elem {
394 // Modifications behind a dereference don't affect the value of
395 // the pointer.
396 ProjectionElem::Deref => return,
399 ProjectionElem::Field(..) => { 397 ProjectionElem::Field(..) => {
400 let ty = 398 let ty =
401 Place::ty_from(place.local, proj_base, &self.body.local_decls, self.tcx).ty; 399 Place::ty_from(place.local, proj_base, &self.body.local_decls, self.tcx).ty;
@@ -409,7 +407,14 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
409 "mutating layout constrained fields cannot statically be \ 407 "mutating layout constrained fields cannot statically be \
410 checked for valid values", 408 checked for valid values",
411 ) 409 )
412 } else { 410
411 // Check `is_freeze` as late as possible to avoid cycle errors
412 // with opaque types.
413 } else if !place.ty(self.body, self.tcx).ty.is_freeze(
414 self.tcx,
415 self.param_env,
416 self.source_info.span,
417 ) {
413 ( 418 (
414 "borrow of layout constrained field with interior \ 419 "borrow of layout constrained field with interior \
415 mutability", 420 mutability",
@@ -417,6 +422,8 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
417 lose the constraints. Coupled with interior mutability, \ 422 lose the constraints. Coupled with interior mutability, \
418 the field can be changed to invalid values", 423 the field can be changed to invalid values",
419 ) 424 )
425 } else {
426 continue;
420 }; 427 };
421 self.require_unsafe( 428 self.require_unsafe(
422 description, 429 description,
diff --git a/src/librustc_mir/transform/simplify_try.rs b/src/librustc_mir/transform/simplify_try.rs
index bd66119..3f28f03 100644
--- a/src/librustc_mir/transform/simplify_try.rs
+++ b/src/librustc_mir/transform/simplify_try.rs
@@ -52,6 +52,8 @@ impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity {
52 Some(x) => x, 52 Some(x) => x,
53 }; 53 };
54 if local_tmp_s0 != local_tmp_s1 54 if local_tmp_s0 != local_tmp_s1
55 // Avoid moving into ourselves.
56 || local_0 == local_1
55 // The field-and-variant information match up. 57 // The field-and-variant information match up.
56 || vf_s0 != vf_s1 58 || vf_s0 != vf_s1
57 // Source and target locals have the same type. 59 // Source and target locals have the same type.
@@ -64,6 +66,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity {
64 } 66 }
65 67
66 // Right shape; transform! 68 // Right shape; transform!
69 s0.source_info = s2.source_info;
67 match &mut s0.kind { 70 match &mut s0.kind {
68 StatementKind::Assign(box (place, rvalue)) => { 71 StatementKind::Assign(box (place, rvalue)) => {
69 *place = local_0.into(); 72 *place = local_0.into();
diff --git a/src/librustc_mir_build/build/mod.rs b/src/librustc_mir_build/build/mod.rs
index 32b1f2b..5f8c0b0 100644
--- a/src/librustc_mir_build/build/mod.rs
+++ b/src/librustc_mir_build/build/mod.rs
@@ -670,14 +670,51 @@ fn construct_const<'a, 'tcx>(
670 builder.finish() 670 builder.finish()
671} 671}
672 672
673/// Construct MIR for a item that has had errors in type checking.
674///
675/// This is required because we may still want to run MIR passes on an item
676/// with type errors, but normal MIR construction can't handle that in general.
673fn construct_error<'a, 'tcx>(hir: Cx<'a, 'tcx>, body_id: hir::BodyId) -> Body<'tcx> { 677fn construct_error<'a, 'tcx>(hir: Cx<'a, 'tcx>, body_id: hir::BodyId) -> Body<'tcx> {
674 let owner_id = hir.tcx().hir().body_owner(body_id); 678 let tcx = hir.tcx();
675 let span = hir.tcx().hir().span(owner_id); 679 let owner_id = tcx.hir().body_owner(body_id);
676 let ty = hir.tcx().types.err; 680 let span = tcx.hir().span(owner_id);
677 let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, span, None); 681 let ty = tcx.types.err;
682 let num_params = match hir.body_owner_kind {
683 hir::BodyOwnerKind::Fn => tcx.hir().fn_decl_by_hir_id(owner_id).unwrap().inputs.len(),
684 hir::BodyOwnerKind::Closure => {
685 if tcx.hir().body(body_id).generator_kind().is_some() {
686 // Generators have an implicit `self` parameter *and* a possibly
687 // implicit resume parameter.
688 2
689 } else {
690 // The implicit self parameter adds another local in MIR.
691 1 + tcx.hir().fn_decl_by_hir_id(owner_id).unwrap().inputs.len()
692 }
693 }
694 hir::BodyOwnerKind::Const => 0,
695 hir::BodyOwnerKind::Static(_) => 0,
696 };
697 let mut builder = Builder::new(hir, span, num_params, Safety::Safe, ty, span, None);
678 let source_info = builder.source_info(span); 698 let source_info = builder.source_info(span);
699 // Some MIR passes will expect the number of parameters to match the
700 // function declaration.
701 for _ in 0..num_params {
702 builder.local_decls.push(LocalDecl {
703 mutability: Mutability::Mut,
704 ty,
705 user_ty: UserTypeProjections::none(),
706 source_info,
707 internal: false,
708 local_info: LocalInfo::Other,
709 is_block_tail: None,
710 });
711 }
679 builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable); 712 builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
680 builder.finish() 713 let mut body = builder.finish();
714 if tcx.hir().body(body_id).generator_kind.is_some() {
715 body.yield_ty = Some(ty);
716 }
717 body
681} 718}
682 719
683impl<'a, 'tcx> Builder<'a, 'tcx> { 720impl<'a, 'tcx> Builder<'a, 'tcx> {
diff --git a/src/librustc_ty/Cargo.toml b/src/librustc_ty/Cargo.toml
index fb0d93f..52606e5 100644
--- a/src/librustc_ty/Cargo.toml
+++ b/src/librustc_ty/Cargo.toml
@@ -14,3 +14,4 @@ rustc = { path = "../librustc" }
14rustc_data_structures = { path = "../librustc_data_structures" } 14rustc_data_structures = { path = "../librustc_data_structures" }
15rustc_hir = { path = "../librustc_hir" } 15rustc_hir = { path = "../librustc_hir" }
16rustc_span = { path = "../librustc_span" } 16rustc_span = { path = "../librustc_span" }
17rustc_target = { path = "../librustc_target" }
diff --git a/src/librustc_ty/instance.rs b/src/librustc_ty/instance.rs
new file mode 100644
index 0000000..66f189a
--- /dev/null
+++ b/src/librustc_ty/instance.rs
@@ -0,0 +1,136 @@
1use rustc::traits;
2use rustc::ty::subst::SubstsRef;
3use rustc::ty::{self, Instance, TyCtxt, TypeFoldable};
4use rustc_hir::def_id::DefId;
5use rustc_target::spec::abi::Abi;
6
7use log::debug;
8
9pub fn resolve_instance<'tcx>(
10 tcx: TyCtxt<'tcx>,
11 param_env: ty::ParamEnv<'tcx>,
12 def_id: DefId,
13 substs: SubstsRef<'tcx>,
14) -> Option<Instance<'tcx>> {
15 debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
16 let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) {
17 debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
18 let item = tcx.associated_item(def_id);
19 resolve_associated_item(tcx, &item, param_env, trait_def_id, substs)
20 } else {
21 let ty = tcx.type_of(def_id);
22 let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, &ty);
23
24 let def = match item_type.kind {
25 ty::FnDef(..)
26 if {
27 let f = item_type.fn_sig(tcx);
28 f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic
29 } =>
30 {
31 debug!(" => intrinsic");
32 ty::InstanceDef::Intrinsic(def_id)
33 }
34 _ => {
35 if Some(def_id) == tcx.lang_items().drop_in_place_fn() {
36 let ty = substs.type_at(0);
37 if ty.needs_drop(tcx, param_env.with_reveal_all()) {
38 debug!(" => nontrivial drop glue");
39 ty::InstanceDef::DropGlue(def_id, Some(ty))
40 } else {
41 debug!(" => trivial drop glue");
42 ty::InstanceDef::DropGlue(def_id, None)
43 }
44 } else {
45 debug!(" => free item");
46 ty::InstanceDef::Item(def_id)
47 }
48 }
49 };
50 Some(Instance { def: def, substs: substs })
51 };
52 debug!("resolve(def_id={:?}, substs={:?}) = {:?}", def_id, substs, result);
53 result
54}
55
56fn resolve_associated_item<'tcx>(
57 tcx: TyCtxt<'tcx>,
58 trait_item: &ty::AssocItem,
59 param_env: ty::ParamEnv<'tcx>,
60 trait_id: DefId,
61 rcvr_substs: SubstsRef<'tcx>,
62) -> Option<Instance<'tcx>> {
63 let def_id = trait_item.def_id;
64 debug!(
65 "resolve_associated_item(trait_item={:?}, \
66 param_env={:?}, \
67 trait_id={:?}, \
68 rcvr_substs={:?})",
69 def_id, param_env, trait_id, rcvr_substs
70 );
71
72 let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
73 let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref)));
74
75 // Now that we know which impl is being used, we can dispatch to
76 // the actual function:
77 match vtbl {
78 traits::VtableImpl(impl_data) => {
79 let (def_id, substs) =
80 traits::find_associated_item(tcx, param_env, trait_item, rcvr_substs, &impl_data);
81
82 let resolved_item = tcx.associated_item(def_id);
83
84 // Since this is a trait item, we need to see if the item is either a trait default item
85 // or a specialization because we can't resolve those unless we can `Reveal::All`.
86 // NOTE: This should be kept in sync with the similar code in
87 // `rustc::traits::project::assemble_candidates_from_impls()`.
88 let eligible = if !resolved_item.defaultness.is_default() {
89 true
90 } else if param_env.reveal == traits::Reveal::All {
91 !trait_ref.needs_subst()
92 } else {
93 false
94 };
95
96 if !eligible {
97 return None;
98 }
99
100 let substs = tcx.erase_regions(&substs);
101 Some(ty::Instance::new(def_id, substs))
102 }
103 traits::VtableGenerator(generator_data) => Some(Instance {
104 def: ty::InstanceDef::Item(generator_data.generator_def_id),
105 substs: generator_data.substs,
106 }),
107 traits::VtableClosure(closure_data) => {
108 let trait_closure_kind = tcx.fn_trait_kind_from_lang_item(trait_id).unwrap();
109 Some(Instance::resolve_closure(
110 tcx,
111 closure_data.closure_def_id,
112 closure_data.substs,
113 trait_closure_kind,
114 ))
115 }
116 traits::VtableFnPointer(ref data) => Some(Instance {
117 def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty),
118 substs: rcvr_substs,
119 }),
120 traits::VtableObject(ref data) => {
121 let index = traits::get_vtable_index_of_object_method(tcx, data, def_id);
122 Some(Instance { def: ty::InstanceDef::Virtual(def_id, index), substs: rcvr_substs })
123 }
124 traits::VtableBuiltin(..) => {
125 if tcx.lang_items().clone_trait().is_some() {
126 Some(Instance {
127 def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()),
128 substs: rcvr_substs,
129 })
130 } else {
131 None
132 }
133 }
134 traits::VtableAutoImpl(..) | traits::VtableParam(..) | traits::VtableTraitAlias(..) => None,
135 }
136}
diff --git a/src/librustc_ty/lib.rs b/src/librustc_ty/lib.rs
index 7eef19b..f9ee4e2 100644
--- a/src/librustc_ty/lib.rs
+++ b/src/librustc_ty/lib.rs
@@ -17,6 +17,7 @@ extern crate log;
17use rustc::ty::query::Providers; 17use rustc::ty::query::Providers;
18 18
19mod common_traits; 19mod common_traits;
20pub mod instance;
20mod needs_drop; 21mod needs_drop;
21mod ty; 22mod ty;
22 23
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index 028c39b..0c1557a 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -25,7 +25,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25 25
26 let ty = 26 let ty =
27 if !lhs_ty.is_ty_var() && !rhs_ty.is_ty_var() && is_builtin_binop(lhs_ty, rhs_ty, op) { 27 if !lhs_ty.is_ty_var() && !rhs_ty.is_ty_var() && is_builtin_binop(lhs_ty, rhs_ty, op) {
28 self.enforce_builtin_binop_types(lhs, lhs_ty, rhs, rhs_ty, op); 28 self.enforce_builtin_binop_types(&lhs.span, lhs_ty, &rhs.span, rhs_ty, op);
29 self.tcx.mk_unit() 29 self.tcx.mk_unit()
30 } else { 30 } else {
31 return_ty 31 return_ty
@@ -86,8 +86,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
86 && !rhs_ty.is_ty_var() 86 && !rhs_ty.is_ty_var()
87 && is_builtin_binop(lhs_ty, rhs_ty, op) 87 && is_builtin_binop(lhs_ty, rhs_ty, op)
88 { 88 {
89 let builtin_return_ty = 89 let builtin_return_ty = self.enforce_builtin_binop_types(
90 self.enforce_builtin_binop_types(lhs_expr, lhs_ty, rhs_expr, rhs_ty, op); 90 &lhs_expr.span,
91 lhs_ty,
92 &rhs_expr.span,
93 rhs_ty,
94 op,
95 );
91 self.demand_suptype(expr.span, builtin_return_ty, return_ty); 96 self.demand_suptype(expr.span, builtin_return_ty, return_ty);
92 } 97 }
93 98
@@ -98,19 +103,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
98 103
99 fn enforce_builtin_binop_types( 104 fn enforce_builtin_binop_types(
100 &self, 105 &self,
101 lhs_expr: &'tcx hir::Expr<'tcx>, 106 lhs_span: &Span,
102 lhs_ty: Ty<'tcx>, 107 lhs_ty: Ty<'tcx>,
103 rhs_expr: &'tcx hir::Expr<'tcx>, 108 rhs_span: &Span,
104 rhs_ty: Ty<'tcx>, 109 rhs_ty: Ty<'tcx>,
105 op: hir::BinOp, 110 op: hir::BinOp,
106 ) -> Ty<'tcx> { 111 ) -> Ty<'tcx> {
107 debug_assert!(is_builtin_binop(lhs_ty, rhs_ty, op)); 112 debug_assert!(is_builtin_binop(lhs_ty, rhs_ty, op));
108 113
114 // Special-case a single layer of referencing, so that things like `5.0 + &6.0f32` work.
115 // (See https://github.com/rust-lang/rust/issues/57447.)
116 let (lhs_ty, rhs_ty) = (deref_ty_if_possible(lhs_ty), deref_ty_if_possible(rhs_ty));
117
109 let tcx = self.tcx; 118 let tcx = self.tcx;
110 match BinOpCategory::from(op) { 119 match BinOpCategory::from(op) {
111 BinOpCategory::Shortcircuit => { 120 BinOpCategory::Shortcircuit => {
112 self.demand_suptype(lhs_expr.span, tcx.mk_bool(), lhs_ty); 121 self.demand_suptype(*lhs_span, tcx.mk_bool(), lhs_ty);
113 self.demand_suptype(rhs_expr.span, tcx.mk_bool(), rhs_ty); 122 self.demand_suptype(*rhs_span, tcx.mk_bool(), rhs_ty);
114 tcx.mk_bool() 123 tcx.mk_bool()
115 } 124 }
116 125
@@ -121,13 +130,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
121 130
122 BinOpCategory::Math | BinOpCategory::Bitwise => { 131 BinOpCategory::Math | BinOpCategory::Bitwise => {
123 // both LHS and RHS and result will have the same type 132 // both LHS and RHS and result will have the same type
124 self.demand_suptype(rhs_expr.span, lhs_ty, rhs_ty); 133 self.demand_suptype(*rhs_span, lhs_ty, rhs_ty);
125 lhs_ty 134 lhs_ty
126 } 135 }
127 136
128 BinOpCategory::Comparison => { 137 BinOpCategory::Comparison => {
129 // both LHS and RHS and result will have the same type 138 // both LHS and RHS and result will have the same type
130 self.demand_suptype(rhs_expr.span, lhs_ty, rhs_ty); 139 self.demand_suptype(*rhs_span, lhs_ty, rhs_ty);
131 tcx.mk_bool() 140 tcx.mk_bool()
132 } 141 }
133 } 142 }
@@ -862,6 +871,14 @@ enum Op {
862 Unary(hir::UnOp, Span), 871 Unary(hir::UnOp, Span),
863} 872}
864 873
874/// Dereferences a single level of immutable referencing.
875fn deref_ty_if_possible<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
876 match ty.kind {
877 ty::Ref(_, ty, hir::Mutability::Not) => ty,
878 _ => ty,
879 }
880}
881
865/// Returns `true` if this is a built-in arithmetic operation (e.g., u32 882/// Returns `true` if this is a built-in arithmetic operation (e.g., u32
866/// + u32, i16x4 == i16x4) and false if these types would have to be 883/// + u32, i16x4 == i16x4) and false if these types would have to be
867/// overloaded to be legal. There are two reasons that we distinguish 884/// overloaded to be legal. There are two reasons that we distinguish
@@ -878,7 +895,11 @@ enum Op {
878/// Reason #2 is the killer. I tried for a while to always use 895/// Reason #2 is the killer. I tried for a while to always use
879/// overloaded logic and just check the types in constants/codegen after 896/// overloaded logic and just check the types in constants/codegen after
880/// the fact, and it worked fine, except for SIMD types. -nmatsakis 897/// the fact, and it worked fine, except for SIMD types. -nmatsakis
881fn is_builtin_binop(lhs: Ty<'_>, rhs: Ty<'_>, op: hir::BinOp) -> bool { 898fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, op: hir::BinOp) -> bool {
899 // Special-case a single layer of referencing, so that things like `5.0 + &6.0f32` work.
900 // (See https://github.com/rust-lang/rust/issues/57447.)
901 let (lhs, rhs) = (deref_ty_if_possible(lhs), deref_ty_if_possible(rhs));
902
882 match BinOpCategory::from(op) { 903 match BinOpCategory::from(op) {
883 BinOpCategory::Shortcircuit => true, 904 BinOpCategory::Shortcircuit => true,
884 905
diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs
index 47baae6..72a2d56 100644
--- a/src/librustc_typeck/check/pat.rs
+++ b/src/librustc_typeck/check/pat.rs
@@ -89,6 +89,18 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
89 } 89 }
90} 90}
91 91
92const INITIAL_BM: BindingMode = BindingMode::BindByValue(hir::Mutability::Not);
93
94/// Mode for adjusting the expected type and binding mode.
95enum AdjustMode {
96 /// Peel off all immediate reference types.
97 Peel,
98 /// Reset binding mode to the inital mode.