From 79a942bb395557b578cd1d9062306e191c7f62df Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 19 Jan 2019 12:21:07 -0700 Subject: [PATCH 01/41] Update beta to released compiler --- src/stage0.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/stage0.txt b/src/stage0.txt index 0983add49ca77..af36860643d48 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,7 +12,7 @@ # source tarball for a stable release you'll likely see `1.x.0` for rustc and # `0.x.0` for Cargo where they were released on `date`. -date: 2019-01-16 +date: 2019-01-17 rustc: 1.32.0 cargo: 0.33.0 @@ -34,4 +34,4 @@ cargo: 0.33.0 # looking at a beta source tarball and it's uncommented we'll shortly comment it # out. -dev: 1 +#dev: 1 From ad5d12b3b1cedde5ce8dae4027815f4e88519190 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Sun, 20 Jan 2019 00:56:03 +0100 Subject: [PATCH 02/41] beta: Update RLS version to 1.33 --- Cargo.lock | 2 +- src/tools/rls | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d659e0c19a8f0..9f2bba28303eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1955,7 +1955,7 @@ dependencies = [ [[package]] name = "rls" -version = "1.31.6" +version = "1.33.0" dependencies = [ "cargo 0.34.0", "cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/tools/rls b/src/tools/rls index 1a6361bd399a9..9f3c906296796 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 1a6361bd399a9466deba9b42ff2ff2ae365c5d0e +Subproject commit 9f3c9062967968e9fdb8373927c424e4a91d0d69 From f9b492f2d03f5fba106b0c9f7d5e723406269f3e Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 23 Jan 2019 11:21:24 +0100 Subject: [PATCH 03/41] make sure to accept all android licenses --- src/ci/docker/scripts/android-sdk.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/scripts/android-sdk.sh b/src/ci/docker/scripts/android-sdk.sh index e06c57fbab90c..179f63fc830a6 100644 --- a/src/ci/docker/scripts/android-sdk.sh +++ b/src/ci/docker/scripts/android-sdk.sh @@ -20,7 +20,7 @@ download_sysimage() { # The output from sdkmanager is so noisy that it will occupy all of the 4 MB # log extremely quickly. Thus we must silence all output. yes | sdkmanager --licenses > /dev/null - sdkmanager platform-tools emulator \ + yes | sdkmanager platform-tools emulator \ "platforms;android-$api" \ "system-images;android-$api;default;$abi" > /dev/null } From dc52f0f8ab6172b13e5e6eb9a210b120cf5b8d3f Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Tue, 22 Jan 2019 11:13:53 -0700 Subject: [PATCH 04/41] Fix issue 57762 Issue 57762 points out a compiler crash when the compiler was built using a stock LLVM 7. LLVM 7 was released without a necessary fix for a bug in the DWARF discriminant code. This patch changes rustc to use the fallback mode on (non-Rust) LLVM 7. Closes #57762 --- src/librustc_codegen_llvm/debuginfo/metadata.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 6deedd0b5ea33..a354eef6887ae 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -1164,7 +1164,11 @@ fn use_enum_fallback(cx: &CodegenCx) -> bool { // On MSVC we have to use the fallback mode, because LLVM doesn't // lower variant parts to PDB. return cx.sess().target.target.options.is_like_msvc - || llvm_util::get_major_version() < 7; + || llvm_util::get_major_version() < 7 + // LLVM version 7 did not release with an important bug fix; + // but the required patch is in the equivalent Rust LLVM. + // See https://github.com/rust-lang/rust/issues/57762. + || (llvm_util::get_major_version() == 7 && unsafe { !llvm::LLVMRustIsRustLLVM() }); } // Describes the members of an enum value: An enum is described as a union of From 676ade5dd9bf026660316bd96d3f8512bde4f025 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Tue, 22 Jan 2019 11:44:23 -0700 Subject: [PATCH 05/41] Simplify the version check Address the review comments by simplifying the version check to just "< 8". --- src/librustc_codegen_llvm/debuginfo/metadata.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index a354eef6887ae..9f63038c3623b 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -1164,11 +1164,10 @@ fn use_enum_fallback(cx: &CodegenCx) -> bool { // On MSVC we have to use the fallback mode, because LLVM doesn't // lower variant parts to PDB. return cx.sess().target.target.options.is_like_msvc - || llvm_util::get_major_version() < 7 // LLVM version 7 did not release with an important bug fix; - // but the required patch is in the equivalent Rust LLVM. - // See https://github.com/rust-lang/rust/issues/57762. - || (llvm_util::get_major_version() == 7 && unsafe { !llvm::LLVMRustIsRustLLVM() }); + // but the required patch is in the LLVM 8. Rust LLVM reports + // 8 as well. + || llvm_util::get_major_version() < 8; } // Describes the members of an enum value: An enum is described as a union of From 1652c7df2386f2e8ec523d13da6948ba2ea97aef Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 17 Jan 2019 15:32:05 +0100 Subject: [PATCH 06/41] Fix typo bug in DepGraph::try_mark_green(). --- src/librustc/dep_graph/graph.rs | 2 +- .../incremental/change_name_of_static_in_fn.rs | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/test/incremental/change_name_of_static_in_fn.rs diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 501ef01d74c6e..7384af108edbb 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -600,7 +600,7 @@ impl DepGraph { DepKind::Hir | DepKind::HirBody | DepKind::CrateMetadata => { - if dep_node.extract_def_id(tcx).is_none() { + if dep_dep_node.extract_def_id(tcx).is_none() { // If the node does not exist anymore, we // just fail to mark green. return None diff --git a/src/test/incremental/change_name_of_static_in_fn.rs b/src/test/incremental/change_name_of_static_in_fn.rs new file mode 100644 index 0000000000000..5b27b6808ead2 --- /dev/null +++ b/src/test/incremental/change_name_of_static_in_fn.rs @@ -0,0 +1,17 @@ + +// revisions:rpass1 rpass2 rpass3 + +// See issue #57692. + +#![allow(warnings)] + +fn main() { + #[cfg(rpass1)] + { + static map: u64 = 0; + } + #[cfg(not(rpass1))] + { + static MAP: u64 = 0; + } +} From 2cccf5962f3036bf79fbb0829015df009ae9ef4e Mon Sep 17 00:00:00 2001 From: Marc-Antoine Perennou Date: Wed, 30 Jan 2019 09:43:56 +0100 Subject: [PATCH 07/41] rustbuild: fix build with rust 1.33 Fixes #57262 Signed-off-by: Marc-Antoine Perennou --- src/bootstrap/dist.rs | 2 +- src/bootstrap/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index df34dfe4544ae..0c6e21311093e 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -226,7 +226,7 @@ fn make_win_dist( let trim_chars: &[_] = &[' ', '=']; let value = line[(idx + 1)..] - .trim_left_matches(trim_chars) + .trim_start_matches(trim_chars) .split(';') .map(PathBuf::from); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index bddc6362389ad..7491385af7929 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -423,7 +423,7 @@ impl Build { Command::new(&build.initial_rustc).arg("--version").arg("--verbose")); let local_release = local_version_verbose .lines().filter(|x| x.starts_with("release:")) - .next().unwrap().trim_left_matches("release:").trim(); + .next().unwrap().trim_start_matches("release:").trim(); let my_version = channel::CFG_RELEASE_NUM; if local_release.split('.').take(2).eq(my_version.split('.').take(2)) { build.verbose(&format!("auto-detected local-rebuild {}", local_release)); From b8527abef3893c0584a225ed8405a9f6f01114bf Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 30 Jan 2019 19:49:31 +0000 Subject: [PATCH 08/41] Pass correct arguments to places_conflict The borrow place *must* be a place that we track borrows for, otherwise we will likely ICE. --- src/librustc_mir/dataflow/impls/borrows.rs | 2 +- src/test/ui/nll/issue-57989.rs | 12 +++++++++++ src/test/ui/nll/issue-57989.stderr | 24 ++++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/nll/issue-57989.rs create mode 100644 src/test/ui/nll/issue-57989.stderr diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 0ceff4aa04898..72218e29cfd20 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -215,8 +215,8 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { if places_conflict::places_conflict( self.tcx, self.mir, - place, &borrow_data.borrowed_place, + place, places_conflict::PlaceConflictBias::NoOverlap, ) { debug!( diff --git a/src/test/ui/nll/issue-57989.rs b/src/test/ui/nll/issue-57989.rs new file mode 100644 index 0000000000000..4f21cca97cc09 --- /dev/null +++ b/src/test/ui/nll/issue-57989.rs @@ -0,0 +1,12 @@ +// Test for ICE from issue 57989 + +#![feature(nll)] + +fn f(x: &i32) { + let g = &x; + *x = 0; //~ ERROR cannot assign to `*x` which is behind a `&` reference + //~| ERROR cannot assign to `*x` because it is borrowed + g; +} + +fn main() {} diff --git a/src/test/ui/nll/issue-57989.stderr b/src/test/ui/nll/issue-57989.stderr new file mode 100644 index 0000000000000..4561c99096f14 --- /dev/null +++ b/src/test/ui/nll/issue-57989.stderr @@ -0,0 +1,24 @@ +error[E0594]: cannot assign to `*x` which is behind a `&` reference + --> $DIR/issue-57989.rs:7:5 + | +LL | fn f(x: &i32) { + | ---- help: consider changing this to be a mutable reference: `&mut i32` +LL | let g = &x; +LL | *x = 0; //~ ERROR cannot assign to `*x` which is behind a `&` reference + | ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written + +error[E0506]: cannot assign to `*x` because it is borrowed + --> $DIR/issue-57989.rs:7:5 + | +LL | let g = &x; + | -- borrow of `*x` occurs here +LL | *x = 0; //~ ERROR cannot assign to `*x` which is behind a `&` reference + | ^^^^^^ assignment to borrowed `*x` occurs here +LL | //~| ERROR cannot assign to `*x` because it is borrowed +LL | g; + | - borrow later used here + +error: aborting due to 2 previous errors + +Some errors occurred: E0506, E0594. +For more information about an error, try `rustc --explain E0506`. From 1983205b73cfff221af131bb38ab422ec0f7d6f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 30 Jan 2019 11:39:56 -0800 Subject: [PATCH 09/41] Don't panic when accessing enum variant ctor using `Self` in match --- src/librustc_typeck/check/_match.rs | 3 ++- src/test/ui/issues/issue-58006.rs | 15 +++++++++++++++ src/test/ui/issues/issue-58006.stderr | 9 +++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/issues/issue-58006.rs create mode 100644 src/test/ui/issues/issue-58006.stderr diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 1767af4870d3b..bc31cf1160b35 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -783,7 +783,8 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); report_unexpected_variant_def(tcx, &def, pat.span, qpath); return tcx.types.err; } - Def::VariantCtor(_, CtorKind::Fictive) => { + Def::VariantCtor(_, CtorKind::Fictive) | + Def::VariantCtor(_, CtorKind::Fn) => { report_unexpected_variant_def(tcx, &def, pat.span, qpath); return tcx.types.err; } diff --git a/src/test/ui/issues/issue-58006.rs b/src/test/ui/issues/issue-58006.rs new file mode 100644 index 0000000000000..1fb5fefa7596d --- /dev/null +++ b/src/test/ui/issues/issue-58006.rs @@ -0,0 +1,15 @@ +#![feature(type_alias_enum_variants)] +pub enum Enum { + A(usize), +} + +impl Enum { + fn foo(&self) -> () { + match self { + Self::A => (), + //~^ ERROR expected unit struct/variant or constant, found tuple variant + } + } +} + +fn main() {} diff --git a/src/test/ui/issues/issue-58006.stderr b/src/test/ui/issues/issue-58006.stderr new file mode 100644 index 0000000000000..c65e3e2777fae --- /dev/null +++ b/src/test/ui/issues/issue-58006.stderr @@ -0,0 +1,9 @@ +error[E0533]: expected unit struct/variant or constant, found tuple variant `::A` + --> $DIR/issue-58006.rs:9:13 + | +LL | Self::A => (), + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0533`. From 872c966692b707e676f0767d10947313a33a9e18 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 1 Feb 2019 20:02:21 +0000 Subject: [PATCH 10/41] Fix bug in integer range matching --- src/librustc_mir/build/matches/simplify.rs | 21 ++++++++++++------- .../ui/match-on-negative-integer-ranges.rs | 7 +++++++ 2 files changed, 21 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/match-on-negative-integer-ranges.rs diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index 22bc3506803f2..c219fd2218223 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -106,27 +106,34 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } PatternKind::Range(PatternRange { lo, hi, ty, end }) => { - let range = match ty.sty { + let (range, bias) = match ty.sty { ty::Char => { - Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32))) + (Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32))), 0) } ty::Int(ity) => { // FIXME(49937): refactor these bit manipulations into interpret. let size = Integer::from_attr(&tcx, SignedInt(ity)).size(); - let min = 1u128 << (size.bits() - 1); - let max = (1u128 << (size.bits() - 1)) - 1; - Some((min, max, size)) + let max = !0u128 >> (128 - size.bits()); + let bias = 1u128 << (size.bits() - 1); + (Some((0, max, size)), bias) } ty::Uint(uty) => { // FIXME(49937): refactor these bit manipulations into interpret. let size = Integer::from_attr(&tcx, UnsignedInt(uty)).size(); let max = !0u128 >> (128 - size.bits()); - Some((0, max, size)) + (Some((0, max, size)), 0) } - _ => None, + _ => (None, 0), }; if let Some((min, max, sz)) = range { if let (Some(lo), Some(hi)) = (lo.val.try_to_bits(sz), hi.val.try_to_bits(sz)) { + // We want to compare ranges numerically, but the order of the bitwise + // representation of signed integers does not match their numeric order. + // Thus, to correct the ordering, we need to shift the range of signed + // integers to correct the comparison. This is achieved by XORing with a + // bias (see pattern/_match.rs for another pertinent example of this + // pattern). + let (lo, hi) = (lo ^ bias, hi ^ bias); if lo <= min && (hi > max || hi == max && end == RangeEnd::Included) { // Irrefutable pattern match. return Ok(()); diff --git a/src/test/ui/match-on-negative-integer-ranges.rs b/src/test/ui/match-on-negative-integer-ranges.rs new file mode 100644 index 0000000000000..53e9ea9a5775b --- /dev/null +++ b/src/test/ui/match-on-negative-integer-ranges.rs @@ -0,0 +1,7 @@ +// run-pass + +fn main() { + assert_eq!(false, match -50_i8 { -128i8..=-101i8 => true, _ => false, }); + + assert_eq!(false, if let -128i8..=-101i8 = -50_i8 { true } else { false }); +} From edb41d838cb6092bde203c22f75e67f3f5b6a12d Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Mon, 28 Jan 2019 11:46:41 +0200 Subject: [PATCH 11/41] Build the standard library for thumbv7neon-unknown-linux-gnueabihf in CI Closes #57030. --- src/ci/docker/dist-various-1/Dockerfile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/ci/docker/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile index 76cdd367987b2..ab2dd5a399280 100644 --- a/src/ci/docker/dist-various-1/Dockerfile +++ b/src/ci/docker/dist-various-1/Dockerfile @@ -116,13 +116,17 @@ ENV TARGETS=$TARGETS,armebv7r-none-eabi ENV TARGETS=$TARGETS,armebv7r-none-eabihf ENV TARGETS=$TARGETS,armv7r-none-eabi ENV TARGETS=$TARGETS,armv7r-none-eabihf +ENV TARGETS=$TARGETS,thumbv7neon-unknown-linux-gnueabihf ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \ CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc \ CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc \ CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc \ - CC_armebv7r_none_eabi=arm-none-eabi-gcc - + CC_armebv7r_none_eabi=arm-none-eabi-gcc \ + CC_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-gcc \ + AR_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-ar \ + CXX_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-g++ + ENV RUST_CONFIGURE_ARGS \ --musl-root-armv5te=/musl-armv5te \ --musl-root-arm=/musl-arm \ From 13542d8f205507a1dae1c483b5ea8c6ef114b890 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Wed, 16 Jan 2019 11:36:38 +0530 Subject: [PATCH 12/41] Fix release manifest generation --- src/tools/build-manifest/src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 8c1baa55bcdca..4ca285b9b1db1 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -95,6 +95,7 @@ static TARGETS: &'static [&'static str] = &[ "wasm32-unknown-unknown", "x86_64-apple-darwin", "x86_64-apple-ios", + "x86_64-fortanix-unknown-sgx", "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-gnu", From 81571bfac1e38af642a026b7ca033bc8a695e418 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 13 Feb 2019 00:07:22 +0100 Subject: [PATCH 13/41] libpanic_unwind => 2018: fix ICEs. --- src/librustc_typeck/check/method/suggest.rs | 5 ++--- src/librustdoc/visit_lib.rs | 8 +++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 23bcd88d6afb5..59902aff7ac81 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -750,12 +750,11 @@ fn compute_all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Vec traits: &mut Vec, external_mods: &mut FxHashSet, def: Def) { - let def_id = def.def_id(); match def { - Def::Trait(..) => { + Def::Trait(def_id) => { traits.push(def_id); } - Def::Mod(..) => { + Def::Mod(def_id) => { if !external_mods.insert(def_id) { return; } diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index 7413a917f0563..bd5cae861e93b 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -60,9 +60,11 @@ impl<'a, 'tcx, 'rcx> LibEmbargoVisitor<'a, 'tcx, 'rcx> { } for item in self.cx.tcx.item_children(def_id).iter() { - if self.cx.tcx.def_key(item.def.def_id()).parent.map_or(false, |d| d == def_id.index) || - item.vis == Visibility::Public { - self.visit_item(item.def); + if let Some(def_id) = item.def.opt_def_id() { + if self.cx.tcx.def_key(def_id).parent.map_or(false, |d| d == def_id.index) || + item.vis == Visibility::Public { + self.visit_item(item.def); + } } } } From 119335efb1e1765896f2eaca6e89263455890647 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 16 Feb 2019 12:55:00 -0800 Subject: [PATCH 14/41] [BETA] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 9b5d4b755617d..f099fe94b66f0 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 9b5d4b755617d60dd841912b354be8a6b6b3849a +Subproject commit f099fe94b66f0a2f80370be8f2d3db2a55b97050 From 94ca417f8a3a07bc17ab5657a90ce02f7dc3a9eb Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 6 Feb 2019 11:57:11 +1100 Subject: [PATCH 15/41] Make `intern_lazy_const` actually intern its argument. Currently it just unconditionally allocates it in the arena. For a "Clean Check" build of the the `packed-simd` benchmark, this change reduces both the `max-rss` and `faults` counts by 59%; it slightly (~3%) increases the instruction counts but the `wall-time` is unchanged. For the same builds of a few other benchmarks, `max-rss` and `faults` drop by 1--5%, but instruction counts and `wall-time` changes are in the noise. Fixes #57432, fixes #57829. --- src/librustc/mir/mod.rs | 2 +- src/librustc/traits/project.rs | 4 ++-- src/librustc/traits/query/normalize.rs | 4 ++-- src/librustc/ty/codec.rs | 2 +- src/librustc/ty/context.rs | 22 ++++++++++--------- src/librustc/ty/structural_impls.rs | 2 +- src/librustc_mir/build/expr/as_rvalue.rs | 2 +- src/librustc_mir/build/matches/test.rs | 2 +- src/librustc_mir/build/misc.rs | 2 +- src/librustc_mir/hair/cx/expr.rs | 12 +++++----- src/librustc_mir/hair/cx/mod.rs | 6 ++--- src/librustc_mir/shim.rs | 6 ++--- src/librustc_mir/transform/elaborate_drops.rs | 2 +- src/librustc_mir/transform/generator.rs | 4 ++-- src/librustc_mir/util/elaborate_drops.rs | 2 +- src/librustc_typeck/astconv.rs | 2 +- src/librustc_typeck/check/mod.rs | 2 +- 17 files changed, 40 insertions(+), 38 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index a1a6e890b1292..10015efa42232 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2154,7 +2154,7 @@ impl<'tcx> Operand<'tcx> { span, ty, user_ty: None, - literal: tcx.intern_lazy_const( + literal: tcx.mk_lazy_const( ty::LazyConst::Evaluated(ty::Const::zero_sized(ty)), ), }) diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index bec45046cb93e..21151276e7299 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -408,7 +408,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { let substs = tcx.lift_to_global(&substs).unwrap(); let evaluated = evaluated.subst(tcx, substs); - return tcx.intern_lazy_const(ty::LazyConst::Evaluated(evaluated)); + return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated)); } } } else { @@ -420,7 +420,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, promoted: None }; if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { - return tcx.intern_lazy_const(ty::LazyConst::Evaluated(evaluated)); + return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated)); } } } diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs index be05445cfc61a..9f55bb95d259b 100644 --- a/src/librustc/traits/query/normalize.rs +++ b/src/librustc/traits/query/normalize.rs @@ -203,7 +203,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { let substs = tcx.lift_to_global(&substs).unwrap(); let evaluated = evaluated.subst(tcx, substs); - return tcx.intern_lazy_const(ty::LazyConst::Evaluated(evaluated)); + return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated)); } } } else { @@ -215,7 +215,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx promoted: None, }; if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { - return tcx.intern_lazy_const(ty::LazyConst::Evaluated(evaluated)); + return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated)); } } } diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs index e0e4d9c362a6c..a4a2471852739 100644 --- a/src/librustc/ty/codec.rs +++ b/src/librustc/ty/codec.rs @@ -252,7 +252,7 @@ pub fn decode_lazy_const<'a, 'tcx, D>(decoder: &mut D) where D: TyDecoder<'a, 'tcx>, 'tcx: 'a, { - Ok(decoder.tcx().intern_lazy_const(Decodable::decode(decoder)?)) + Ok(decoder.tcx().mk_lazy_const(Decodable::decode(decoder)?)) } #[inline] diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index d69219efbd884..56c9a475bdb93 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -127,6 +127,7 @@ pub struct CtxtInterners<'tcx> { goal: InternedSet<'tcx, GoalKind<'tcx>>, goal_list: InternedSet<'tcx, List>>, projs: InternedSet<'tcx, List>>, + lazy_const: InternedSet<'tcx, LazyConst<'tcx>>, } impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { @@ -144,6 +145,7 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { goal: Default::default(), goal_list: Default::default(), projs: Default::default(), + lazy_const: Default::default(), } } @@ -1072,10 +1074,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.global_arenas.adt_def.alloc(def) } - pub fn intern_const_alloc( - self, - alloc: Allocation, - ) -> &'gcx Allocation { + pub fn intern_const_alloc(self, alloc: Allocation) -> &'gcx Allocation { self.allocation_interner.borrow_mut().intern(alloc, |alloc| { self.global_arenas.const_allocs.alloc(alloc) }) @@ -1095,10 +1094,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { }) } - pub fn intern_lazy_const(self, c: ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> { - self.global_interners.arena.alloc(c) - } - pub fn intern_layout(self, layout: LayoutDetails) -> &'gcx LayoutDetails { self.layout_interner.borrow_mut().intern(layout, |layout| { self.global_arenas.layout.alloc(layout) @@ -2238,6 +2233,12 @@ impl<'tcx: 'lcx, 'lcx> Borrow> for Interned<'tcx, GoalKind<'tcx>> } } +impl<'tcx: 'lcx, 'lcx> Borrow> for Interned<'tcx, LazyConst<'tcx>> { + fn borrow<'a>(&'a self) -> &'a LazyConst<'lcx> { + &self.0 + } +} + impl<'tcx: 'lcx, 'lcx> Borrow<[ExistentialPredicate<'lcx>]> for Interned<'tcx, List>> { fn borrow<'a>(&'a self) -> &'a [ExistentialPredicate<'lcx>] { @@ -2344,7 +2345,8 @@ pub fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool { direct_interners!('tcx, region: mk_region(|r: &RegionKind| r.keep_in_local_tcx()) -> RegionKind, - goal: mk_goal(|c: &GoalKind<'_>| keep_local(c)) -> GoalKind<'tcx> + goal: mk_goal(|c: &GoalKind<'_>| keep_local(c)) -> GoalKind<'tcx>, + lazy_const: mk_lazy_const(|c: &LazyConst<'_>| keep_local(&c)) -> LazyConst<'tcx> ); macro_rules! slice_interners { @@ -2529,7 +2531,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { #[inline] pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> { - self.mk_ty(Array(ty, self.intern_lazy_const( + self.mk_ty(Array(ty, self.mk_lazy_const( ty::LazyConst::Evaluated(ty::Const::from_usize(self.global_tcx(), n)) ))) } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 258470bf6f860..dd9ffd08a4ef5 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -1042,7 +1042,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::LazyConst<'tcx> { ty::LazyConst::Unevaluated(*def_id, substs.fold_with(folder)) } }; - folder.tcx().intern_lazy_const(new) + folder.tcx().mk_lazy_const(new) } fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index e0fc90931696e..d408883c16c69 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -268,7 +268,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { span: expr_span, ty: this.hir.tcx().types.u32, user_ty: None, - literal: this.hir.tcx().intern_lazy_const(ty::LazyConst::Evaluated( + literal: this.hir.tcx().mk_lazy_const(ty::LazyConst::Evaluated( ty::Const::from_bits( this.hir.tcx(), 0, diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 696c173b048ad..6e836f7059b83 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -302,7 +302,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } let eq_def_id = self.hir.tcx().lang_items().eq_trait().unwrap(); let (mty, method) = self.hir.trait_method(eq_def_id, "eq", ty, &[ty.into()]); - let method = self.hir.tcx().intern_lazy_const(ty::LazyConst::Evaluated(method)); + let method = self.hir.tcx().mk_lazy_const(ty::LazyConst::Evaluated(method)); let re_erased = self.hir.tcx().types.re_erased; // take the argument by reference diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs index c849c02242840..a7b201fc0dbc6 100644 --- a/src/librustc_mir/build/misc.rs +++ b/src/librustc_mir/build/misc.rs @@ -33,7 +33,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { span, ty, user_ty: None, - literal: self.hir.tcx().intern_lazy_const(ty::LazyConst::Evaluated(literal)), + literal: self.hir.tcx().mk_lazy_const(ty::LazyConst::Evaluated(literal)), }; Operand::Constant(constant) } diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index eb536fbcf69bb..aa754888fcb31 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -342,7 +342,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprKind::Lit(ref lit) => ExprKind::Literal { - literal: cx.tcx.intern_lazy_const(ty::LazyConst::Evaluated( + literal: cx.tcx.mk_lazy_const(ty::LazyConst::Evaluated( cx.const_eval_literal(&lit.node, expr_ty, lit.span, false) )), user_ty: None, @@ -442,7 +442,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } else { if let hir::ExprKind::Lit(ref lit) = arg.node { ExprKind::Literal { - literal: cx.tcx.intern_lazy_const(ty::LazyConst::Evaluated( + literal: cx.tcx.mk_lazy_const(ty::LazyConst::Evaluated( cx.const_eval_literal(&lit.node, expr_ty, lit.span, true) )), user_ty: None, @@ -702,7 +702,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, ty: var_ty, span: expr.span, kind: ExprKind::Literal { - literal: cx.tcx.intern_lazy_const(literal), + literal: cx.tcx.mk_lazy_const(literal), user_ty: None }, }.to_ref(); @@ -856,7 +856,7 @@ fn method_callee<'a, 'gcx, 'tcx>( ty, span, kind: ExprKind::Literal { - literal: cx.tcx().intern_lazy_const(ty::LazyConst::Evaluated( + literal: cx.tcx().mk_lazy_const(ty::LazyConst::Evaluated( ty::Const::zero_sized(ty) )), user_ty, @@ -918,7 +918,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def); debug!("convert_path_expr: user_ty={:?}", user_ty); ExprKind::Literal { - literal: cx.tcx.intern_lazy_const(ty::LazyConst::Evaluated(ty::Const::zero_sized( + literal: cx.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::zero_sized( cx.tables().node_id_to_type(expr.hir_id), ))), user_ty, @@ -930,7 +930,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def); debug!("convert_path_expr: (const) user_ty={:?}", user_ty); ExprKind::Literal { - literal: cx.tcx.intern_lazy_const(ty::LazyConst::Unevaluated(def_id, substs)), + literal: cx.tcx.mk_lazy_const(ty::LazyConst::Unevaluated(def_id, substs)), user_ty, } }, diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 6113d88e09591..ae0c493e77b8a 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -109,7 +109,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { } pub fn usize_literal(&mut self, value: u64) -> &'tcx ty::LazyConst<'tcx> { - self.tcx.intern_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_usize(self.tcx, value))) + self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_usize(self.tcx, value))) } pub fn bool_ty(&mut self) -> Ty<'tcx> { @@ -121,11 +121,11 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { } pub fn true_literal(&mut self) -> &'tcx ty::LazyConst<'tcx> { - self.tcx.intern_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bool(self.tcx, true))) + self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bool(self.tcx, true))) } pub fn false_literal(&mut self) -> &'tcx ty::LazyConst<'tcx> { - self.tcx.intern_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bool(self.tcx, false))) + self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bool(self.tcx, false))) } pub fn const_eval_literal( diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 751815eab287b..15796186063de 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -459,7 +459,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { span: self.span, ty: func_ty, user_ty: None, - literal: tcx.intern_lazy_const(ty::LazyConst::Evaluated( + literal: tcx.mk_lazy_const(ty::LazyConst::Evaluated( ty::Const::zero_sized(func_ty), )), }); @@ -521,7 +521,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { span: self.span, ty: self.tcx.types.usize, user_ty: None, - literal: self.tcx.intern_lazy_const(ty::LazyConst::Evaluated( + literal: self.tcx.mk_lazy_const(ty::LazyConst::Evaluated( ty::Const::from_usize(self.tcx, value), )), } @@ -759,7 +759,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span, ty, user_ty: None, - literal: tcx.intern_lazy_const(ty::LazyConst::Evaluated( + literal: tcx.mk_lazy_const(ty::LazyConst::Evaluated( ty::Const::zero_sized(ty) )), }), diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 06e16de8b43bc..9b75a70ff41d2 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -533,7 +533,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { span, ty: self.tcx.types.bool, user_ty: None, - literal: self.tcx.intern_lazy_const(ty::LazyConst::Evaluated( + literal: self.tcx.mk_lazy_const(ty::LazyConst::Evaluated( ty::Const::from_bool(self.tcx, val), )), }))) diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index ec0c118634d0f..4b7e89130cd2c 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -171,7 +171,7 @@ impl<'a, 'tcx> TransformVisitor<'a, 'tcx> { span: source_info.span, ty: self.tcx.types.u32, user_ty: None, - literal: self.tcx.intern_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bits( + literal: self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bits( self.tcx, state_disc.into(), ty::ParamEnv::empty().and(self.tcx.types.u32) @@ -687,7 +687,7 @@ fn insert_panic_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: mir.span, ty: tcx.types.bool, user_ty: None, - literal: tcx.intern_lazy_const(ty::LazyConst::Evaluated( + literal: tcx.mk_lazy_const(ty::LazyConst::Evaluated( ty::Const::from_bool(tcx, false), )), }), diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 8b55a4424ae29..eedc42927c126 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -963,7 +963,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> span: self.source_info.span, ty: self.tcx().types.usize, user_ty: None, - literal: self.tcx().intern_lazy_const(ty::LazyConst::Evaluated( + literal: self.tcx().mk_lazy_const(ty::LazyConst::Evaluated( ty::Const::from_usize(self.tcx(), val.into()) )), }) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 8e5eaa18b9de0..b4d44168a05f8 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1779,7 +1779,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { let length_def_id = tcx.hir().local_def_id(length.id); let substs = Substs::identity_for_item(tcx, length_def_id); let length = ty::LazyConst::Unevaluated(length_def_id, substs); - let length = tcx.intern_lazy_const(length); + let length = tcx.mk_lazy_const(length); let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(&ty), length)); self.normalize_ty(ast_ty.span, array_ty) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1b07385d4d1f4..5163ae9b7747c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4592,7 +4592,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if element_ty.references_error() { tcx.types.err } else if let Ok(count) = count { - tcx.mk_ty(ty::Array(t, tcx.intern_lazy_const(ty::LazyConst::Evaluated(count)))) + tcx.mk_ty(ty::Array(t, tcx.mk_lazy_const(ty::LazyConst::Evaluated(count)))) } else { tcx.types.err } From 04d6d7b974ba2bf573e31cce1b3176baa69d554a Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 4 Feb 2019 19:12:46 +0100 Subject: [PATCH 16/41] Lower constant patterns with ascribed types. This commit fixes a bug introduced by #55937 which started checking user type annotations for associated type patterns. Where lowering a associated constant expression would previously return a `PatternKind::Constant`, it now returns a `PatternKind::AscribeUserType` with a `PatternKind::Constant` inside, this commit unwraps that to access the constant pattern inside and behaves as before. --- src/librustc_mir/hair/pattern/mod.rs | 33 ++++++++++++++++++++--- src/test/ui/nll/issue-57960.rs | 39 ++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/nll/issue-57960.rs diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 8991a90737c7e..680831782a01f 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -164,6 +164,17 @@ pub enum PatternKind<'tcx> { }, } +impl<'tcx> PatternKind<'tcx> { + /// If this is a `PatternKind::AscribeUserType` then return the subpattern kind, otherwise + /// return this pattern kind. + fn with_user_type_ascription_subpattern(self) -> Self { + match self { + PatternKind::AscribeUserType { subpattern: Pattern { box kind, .. }, .. } => kind, + kind => kind, + } + } +} + #[derive(Clone, Copy, Debug, PartialEq)] pub struct PatternRange<'tcx> { pub lo: ty::Const<'tcx>, @@ -400,9 +411,15 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { PatKind::Lit(ref value) => self.lower_lit(value), PatKind::Range(ref lo_expr, ref hi_expr, end) => { - match (self.lower_lit(lo_expr), self.lower_lit(hi_expr)) { - (PatternKind::Constant { value: lo }, - PatternKind::Constant { value: hi }) => { + match ( + // Look for `PatternKind::Constant` patterns inside of any + // `PatternKind::AscribeUserType` patterns. Type ascriptions can be safely + // ignored for the purposes of lowering a range correctly - these are checked + // elsewhere for well-formedness. + self.lower_lit(lo_expr).with_user_type_ascription_subpattern(), + self.lower_lit(hi_expr).with_user_type_ascription_subpattern(), + ) { + (PatternKind::Constant { value: lo }, PatternKind::Constant { value: hi }) => { use std::cmp::Ordering; let cmp = compare_const_vals( self.tcx, @@ -451,7 +468,15 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } } } - _ => PatternKind::Wild + ref pats => { + self.tcx.sess.delay_span_bug( + pat.span, + &format!("found bad range pattern `{:?}` outside of error recovery", + pats), + ); + + PatternKind::Wild + } } } diff --git a/src/test/ui/nll/issue-57960.rs b/src/test/ui/nll/issue-57960.rs new file mode 100644 index 0000000000000..0b52e46c45989 --- /dev/null +++ b/src/test/ui/nll/issue-57960.rs @@ -0,0 +1,39 @@ +// run-pass + +#![allow(dead_code)] + +trait Range { + const FIRST: u8; + const LAST: u8; +} + +struct OneDigit; +impl Range for OneDigit { + const FIRST: u8 = 0; + const LAST: u8 = 9; +} + +struct TwoDigits; +impl Range for TwoDigits { + const FIRST: u8 = 10; + const LAST: u8 = 99; +} + +struct ThreeDigits; +impl Range for ThreeDigits { + const FIRST: u8 = 100; + const LAST: u8 = 255; +} + +fn digits(x: u8) -> u32 { + match x { + OneDigit::FIRST...OneDigit::LAST => 1, + TwoDigits::FIRST...TwoDigits::LAST => 2, + ThreeDigits::FIRST...ThreeDigits::LAST => 3, + _ => unreachable!(), + } +} + +fn main() { + assert_eq!(digits(100), 3); +} From 8a1b7da0cf8f5a5bd3a37e545e20159d339d046c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Mockers?= Date: Tue, 18 Dec 2018 02:22:08 +0100 Subject: [PATCH 17/41] #56411 do not suggest a fix for a import conflict in a macro --- src/librustc_resolve/lib.rs | 4 +++- src/test/ui/issues/issue-56411.rs | 17 +++++++++++++++ src/test/ui/issues/issue-56411.stderr | 31 +++++++++++++++++++++++++++ src/test/ui/issues/issue_56411.rs | 5 +++++ 4 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/issues/issue-56411.rs create mode 100644 src/test/ui/issues/issue-56411.stderr create mode 100644 src/test/ui/issues/issue_56411.rs diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index a25009ccfb49c..ea50d8e18a0e7 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -5103,11 +5103,13 @@ impl<'a> Resolver<'a> { if let ( Ok(snippet), NameBindingKind::Import { directive, ..}, - _dummy @ false, + false, + false, ) = ( cm.span_to_snippet(binding.span), binding.kind.clone(), binding.span.is_dummy(), + binding.span.ctxt().outer().expn_info().is_some(), ) { let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() { format!("Other{}", name) diff --git a/src/test/ui/issues/issue-56411.rs b/src/test/ui/issues/issue-56411.rs new file mode 100644 index 0000000000000..599f277123cc8 --- /dev/null +++ b/src/test/ui/issues/issue-56411.rs @@ -0,0 +1,17 @@ +macro_rules! import { + ( $($name:ident),* ) => { + $( + mod $name; + pub use self::$name; + //~^ ERROR the name `issue_56411` is defined multiple times + //~| ERROR `issue_56411` is private, and cannot be re-exported + + )* + } +} + +import!(issue_56411); + +fn main() { + println!("Hello, world!"); +} diff --git a/src/test/ui/issues/issue-56411.stderr b/src/test/ui/issues/issue-56411.stderr new file mode 100644 index 0000000000000..842d86f4a3a9c --- /dev/null +++ b/src/test/ui/issues/issue-56411.stderr @@ -0,0 +1,31 @@ +error[E0255]: the name `issue_56411` is defined multiple times + --> $DIR/issue-56411.rs:5:21 + | +LL | mod $name; + | ---------- previous definition of the module `issue_56411` here +LL | pub use self::$name; + | ^^^^^^^^^^^ + | | + | `issue_56411` reimported here + | you can use `as` to change the binding name of the import +... +LL | import!(issue_56411); + | --------------------- in this macro invocation + | + = note: `issue_56411` must be defined only once in the type namespace of this module + +error[E0365]: `issue_56411` is private, and cannot be re-exported + --> $DIR/issue-56411.rs:5:21 + | +LL | pub use self::$name; + | ^^^^^^^^^^^ re-export of private `issue_56411` +... +LL | import!(issue_56411); + | --------------------- in this macro invocation + | + = note: consider declaring type or module `issue_56411` with `pub` + +error: aborting due to 2 previous errors + +Some errors occurred: E0255, E0365. +For more information about an error, try `rustc --explain E0255`. diff --git a/src/test/ui/issues/issue_56411.rs b/src/test/ui/issues/issue_56411.rs new file mode 100644 index 0000000000000..bd689e913aba6 --- /dev/null +++ b/src/test/ui/issues/issue_56411.rs @@ -0,0 +1,5 @@ +// compile-pass + +struct T {} + +fn main() {} From e4120ee67864524c503ee2f59b357ce93a43980b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 26 Jan 2019 00:36:50 +0300 Subject: [PATCH 18/41] Address review comments and cleanup code --- src/librustc_resolve/lib.rs | 93 +++++++++---------- src/test/ui/issues/issue-56411.rs | 6 +- src/test/ui/issues/issue-56411.stderr | 22 ++--- .../{issue_56411.rs => issue_56411_aux.rs} | 0 4 files changed, 59 insertions(+), 62 deletions(-) rename src/test/ui/issues/{issue_56411.rs => issue_56411_aux.rs} (100%) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index ea50d8e18a0e7..c231e71e582cb 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -5090,62 +5090,59 @@ impl<'a> Resolver<'a> { } // See https://github.com/rust-lang/rust/issues/32354 - if old_binding.is_import() || new_binding.is_import() { - let binding = if new_binding.is_import() && !new_binding.span.is_dummy() { - new_binding + let directive = match (&new_binding.kind, &old_binding.kind) { + (NameBindingKind::Import { directive, .. }, _) if !new_binding.span.is_dummy() => + Some((directive, new_binding.span)), + (_, NameBindingKind::Import { directive, .. }) if !old_binding.span.is_dummy() => + Some((directive, old_binding.span)), + _ => None, + }; + if let Some((directive, binding_span)) = directive { + let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() { + format!("Other{}", name) } else { - old_binding + format!("other_{}", name) }; - let cm = self.session.source_map(); - let rename_msg = "you can use `as` to change the binding name of the import"; - - if let ( - Ok(snippet), - NameBindingKind::Import { directive, ..}, - false, - false, - ) = ( - cm.span_to_snippet(binding.span), - binding.kind.clone(), - binding.span.is_dummy(), - binding.span.ctxt().outer().expn_info().is_some(), - ) { - let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() { - format!("Other{}", name) - } else { - format!("other_{}", name) - }; + let mut suggestion = None; + match directive.subclass { + ImportDirectiveSubclass::SingleImport { type_ns_only: true, .. } => + suggestion = Some(format!("self as {}", suggested_name)), + ImportDirectiveSubclass::SingleImport { source, .. } => { + if let Some(pos) = source.span.hi().0.checked_sub(binding_span.lo().0) + .map(|pos| pos as usize) { + if let Ok(snippet) = self.session.source_map() + .span_to_snippet(binding_span) { + if pos <= snippet.len() { + suggestion = Some(format!( + "{} as {}{}", + &snippet[..pos], + suggested_name, + if snippet.ends_with(";") { ";" } else { "" } + )) + } + } + } + } + ImportDirectiveSubclass::ExternCrate { source, target, .. } => + suggestion = Some(format!( + "extern crate {} as {};", + source.unwrap_or(target.name), + suggested_name, + )), + _ => unreachable!(), + } + let rename_msg = "you can use `as` to change the binding name of the import"; + if let Some(suggestion) = suggestion { err.span_suggestion_with_applicability( - binding.span, - &rename_msg, - match directive.subclass { - ImportDirectiveSubclass::SingleImport { type_ns_only: true, .. } => - format!("self as {}", suggested_name), - ImportDirectiveSubclass::SingleImport { source, .. } => - format!( - "{} as {}{}", - &snippet[..((source.span.hi().0 - binding.span.lo().0) as usize)], - suggested_name, - if snippet.ends_with(";") { - ";" - } else { - "" - } - ), - ImportDirectiveSubclass::ExternCrate { source, target, .. } => - format!( - "extern crate {} as {};", - source.unwrap_or(target.name), - suggested_name, - ), - _ => unreachable!(), - }, + binding_span, + rename_msg, + suggestion, Applicability::MaybeIncorrect, ); } else { - err.span_label(binding.span, rename_msg); + err.span_label(binding_span, rename_msg); } } diff --git a/src/test/ui/issues/issue-56411.rs b/src/test/ui/issues/issue-56411.rs index 599f277123cc8..3561c21cc7ee3 100644 --- a/src/test/ui/issues/issue-56411.rs +++ b/src/test/ui/issues/issue-56411.rs @@ -3,14 +3,14 @@ macro_rules! import { $( mod $name; pub use self::$name; - //~^ ERROR the name `issue_56411` is defined multiple times - //~| ERROR `issue_56411` is private, and cannot be re-exported + //~^ ERROR the name `issue_56411_aux` is defined multiple times + //~| ERROR `issue_56411_aux` is private, and cannot be re-exported )* } } -import!(issue_56411); +import!(issue_56411_aux); fn main() { println!("Hello, world!"); diff --git a/src/test/ui/issues/issue-56411.stderr b/src/test/ui/issues/issue-56411.stderr index 842d86f4a3a9c..dd05852c09159 100644 --- a/src/test/ui/issues/issue-56411.stderr +++ b/src/test/ui/issues/issue-56411.stderr @@ -1,29 +1,29 @@ -error[E0255]: the name `issue_56411` is defined multiple times +error[E0255]: the name `issue_56411_aux` is defined multiple times --> $DIR/issue-56411.rs:5:21 | LL | mod $name; - | ---------- previous definition of the module `issue_56411` here + | ---------- previous definition of the module `issue_56411_aux` here LL | pub use self::$name; | ^^^^^^^^^^^ | | - | `issue_56411` reimported here + | `issue_56411_aux` reimported here | you can use `as` to change the binding name of the import ... -LL | import!(issue_56411); - | --------------------- in this macro invocation +LL | import!(issue_56411_aux); + | ------------------------- in this macro invocation | - = note: `issue_56411` must be defined only once in the type namespace of this module + = note: `issue_56411_aux` must be defined only once in the type namespace of this module -error[E0365]: `issue_56411` is private, and cannot be re-exported +error[E0365]: `issue_56411_aux` is private, and cannot be re-exported --> $DIR/issue-56411.rs:5:21 | LL | pub use self::$name; - | ^^^^^^^^^^^ re-export of private `issue_56411` + | ^^^^^^^^^^^ re-export of private `issue_56411_aux` ... -LL | import!(issue_56411); - | --------------------- in this macro invocation +LL | import!(issue_56411_aux); + | ------------------------- in this macro invocation | - = note: consider declaring type or module `issue_56411` with `pub` + = note: consider declaring type or module `issue_56411_aux` with `pub` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue_56411.rs b/src/test/ui/issues/issue_56411_aux.rs similarity index 100% rename from src/test/ui/issues/issue_56411.rs rename to src/test/ui/issues/issue_56411_aux.rs From 5f39bc716c0cad7dafe64ecc4311fd7bdbbb09cd Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 22 Jan 2019 13:51:30 +0100 Subject: [PATCH 19/41] Do not initiate nested probe within `assemble_probe`. In particular, the table entries (associated with type-variables created during the probe) must persist as long as the candidates assembled during the probe. If you make a nested probe without creating a nested `ProbeContext`, the table entries are popped at the end of the nested probe, while the type-variables would leak out via the assembled candidates attached to `self` (the outer `ProbeContext`). This causes an ICE (*if you are lucky*)! --- src/librustc_typeck/check/method/probe.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 9a828ce01775c..b849be52a9223 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -506,15 +506,13 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { match self_ty.value.value.sty { ty::Dynamic(ref data, ..) => { if let Some(p) = data.principal() { - self.fcx.probe(|_| { - let InferOk { value: self_ty, obligations: _ } = - self.fcx.probe_instantiate_query_response( - self.span, &self.orig_steps_var_values, self_ty) - .unwrap_or_else(|_| { - span_bug!(self.span, "{:?} was applicable but now isn't?", self_ty) - }); - self.assemble_inherent_candidates_from_object(self_ty); - }); + let InferOk { value: instantiated_self_ty, obligations: _ } = + self.fcx.probe_instantiate_query_response( + self.span, &self.orig_steps_var_values, self_ty) + .unwrap_or_else(|_| { + span_bug!(self.span, "{:?} was applicable but now isn't?", self_ty) + }); + self.assemble_inherent_candidates_from_object(instantiated_self_ty); self.assemble_inherent_impl_candidates_for_type(p.def_id()); } } From d820e217e501c10389a35f35bd47f777b2fa3511 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 22 Jan 2019 14:49:18 +0100 Subject: [PATCH 20/41] unit test for issue 57673. --- .../issue-57673-ice-on-deref-of-boxed-trait.rs | 7 +++++++ .../issue-57673-ice-on-deref-of-boxed-trait.stderr | 14 ++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.rs create mode 100644 src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr diff --git a/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.rs b/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.rs new file mode 100644 index 0000000000000..0a4e7da2bff50 --- /dev/null +++ b/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.rs @@ -0,0 +1,7 @@ +//extern crate has_assoc_type; + +//fn ice(x: Box>) { +fn ice(x: Box>) { + *x //~ ERROR mismatched types [E0308] +} +fn main() {} diff --git a/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr b/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr new file mode 100644 index 0000000000000..bb63917fc0860 --- /dev/null +++ b/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-57673-ice-on-deref-of-boxed-trait.rs:5:5 + | +LL | fn ice(x: Box>) { + | - possibly return type missing here? +LL | *x //~ ERROR mismatched types [E0308] + | ^^ expected (), found trait std::iter::Iterator + | + = note: expected type `()` + found type `(dyn std::iter::Iterator + 'static)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From d30f5bef0d5da8cdb5de23b83ded616e1dc28dfb Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 29 Jan 2019 00:59:13 +0200 Subject: [PATCH 21/41] add some comments to method::probe::Candidate --- src/librustc_typeck/check/method/probe.rs | 31 +++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index b849be52a9223..03a0f6233a75e 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -85,6 +85,37 @@ impl<'a, 'gcx, 'tcx> Deref for ProbeContext<'a, 'gcx, 'tcx> { #[derive(Debug)] struct Candidate<'tcx> { + // Candidates are (I'm not quite sure, but they are mostly) basically + // some metadata on top of a `ty::AssociatedItem` (without substs). + // + // However, method probing wants to be able to evaluate the predicates + // for a function with the substs applied - for example, if a function + // has `where Self: Sized`, we don't want to consider it unless `Self` + // is actually `Sized`, and similarly, return-type suggestions want + // to consider the "actual" return type. + // + // The way this is handled is through `xform_self_ty`. It contains + // the receiver type of this candidate, but `xform_self_ty`, + // `xform_ret_ty` and `kind` (which contains the predicates) have the + // generic parameters of this candidate substituted with the *same set* + // of inference variables, which acts as some weird sort of "query". + // + // When we check out a candidate, we require `xform_self_ty` to be + // a subtype of the passed-in self-type, and this equates the type + // variables in the rest of the fields. + // + // For example, if we have this candidate: + // ``` + // trait Foo { + // fn foo(&self) where Self: Sized; + // } + // ``` + // + // Then `xform_self_ty` will be `&'erased ?X` and `kind` will contain + // the predicate `?X: Sized`, so if we are evaluating `Foo` for a + // the receiver `&T`, we'll do the subtyping which will make `?X` + // get the right value, then when we evaluate the predicate we'll check + // if `T: Sized`. xform_self_ty: Ty<'tcx>, xform_ret_ty: Option>, item: ty::AssociatedItem, From 552e2fa4e5c74a1323c0c5fd0b59912f6f727820 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 29 Jan 2019 00:59:30 +0200 Subject: [PATCH 22/41] add tests to a few edge cases in method lookup These aren't fixed by this PR, but were broken in a few older attempts at it. Make sure they don't regress. --- ...-same-trait-object-with-separate-params.rs | 177 ++++++++++++++++++ ...e-trait-object-with-separate-params.stderr | 72 +++++++ .../methods/method-trait-object-with-hrtb.rs | 41 ++++ 3 files changed, 290 insertions(+) create mode 100644 src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs create mode 100644 src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr create mode 100644 src/test/ui/methods/method-trait-object-with-hrtb.rs diff --git a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs new file mode 100644 index 0000000000000..a5dae1c71cdaa --- /dev/null +++ b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs @@ -0,0 +1,177 @@ +#![feature(arbitrary_self_types, coerce_unsized, dispatch_from_dyn, unsize, unsized_locals)] + +// This tests a few edge-cases around `arbitrary_self_types`. Most specifically, +// it checks that the `ObjectCandidate` you get from method matching can't +// match a trait with the same DefId as a supertrait but a bad type parameter. + +use std::marker::PhantomData; + +mod internal { + use std::ops::{CoerceUnsized, Deref, DispatchFromDyn}; + use std::marker::{PhantomData, Unsize}; + + pub struct Smaht(pub Box, pub PhantomData); + + impl Deref for Smaht { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + impl, U: ?Sized, MISC> CoerceUnsized> + for Smaht + {} + impl, U: ?Sized, MISC> DispatchFromDyn> + for Smaht + {} + + pub trait Foo: X {} + pub trait X { + fn foo(self: Smaht) -> T; + } + + impl X for () { + fn foo(self: Smaht) -> u32 { + 0 + } + } + + pub trait Marker {} + impl Marker for dyn Foo {} + impl X for T { + fn foo(self: Smaht) -> u64 { + 1 + } + } + + impl Deref for dyn Foo { + type Target = (); + fn deref(&self) -> &() { &() } + } + + impl Foo for () {} +} + +pub trait FinalFoo { + fn foo(&self) -> u8; +} + +impl FinalFoo for () { + fn foo(&self) -> u8 { 0 } +} + +mod nuisance_foo { + pub trait NuisanceFoo { + fn foo(self); + } + + impl NuisanceFoo for T { + fn foo(self) {} + } +} + + +fn objectcandidate_impl() { + let x: internal::Smaht<(), u32> = internal::Smaht(Box::new(()), PhantomData); + let x: internal::Smaht = x; + + // This picks `>::foo` via `ObjectCandidate`. + // + // The `TraitCandidate` is not relevant because `X` is not in scope. + let z = x.foo(); + + // Observe the type of `z` is `u32` + let _seetype: () = z; //~ ERROR mismatched types + //~| expected (), found u32 +} + +fn traitcandidate_impl() { + use internal::X; + + let x: internal::Smaht<(), u64> = internal::Smaht(Box::new(()), PhantomData); + let x: internal::Smaht = x; + + // This picks `>::foo` via `TraitCandidate`. + // + // The `ObjectCandidate` does not apply, as it only applies to + // `X` (and not `X`). + let z = x.foo(); + + // Observe the type of `z` is `u64` + let _seetype: () = z; //~ ERROR mismatched types + //~| expected (), found u64 +} + +fn traitcandidate_impl_with_nuisance() { + use internal::X; + use nuisance_foo::NuisanceFoo; + + let x: internal::Smaht<(), u64> = internal::Smaht(Box::new(()), PhantomData); + let x: internal::Smaht = x; + + // This picks `>::foo` via `TraitCandidate`. + // + // The `ObjectCandidate` does not apply, as it only applies to + // `X` (and not `X`). + // + // The NuisanceFoo impl has the same priority as the `X` impl, + // so we get a conflict. + let z = x.foo(); //~ ERROR multiple applicable items in scope +} + + +fn neither_impl() { + let x: internal::Smaht<(), u64> = internal::Smaht(Box::new(()), PhantomData); + let x: internal::Smaht = x; + + // This can't pick the `TraitCandidate` impl, because `Foo` is not + // imported. However, this also can't pick the `ObjectCandidate` + // impl, because it only applies to `X` (and not `X`). + // + // Therefore, neither of the candidates is applicable, and we pick + // the `FinalFoo` impl after another deref, which will return `u8`. + let z = x.foo(); + + // Observe the type of `z` is `u8` + let _seetype: () = z; //~ ERROR mismatched types + //~| expected (), found u8 +} + +fn both_impls() { + use internal::X; + + let x: internal::Smaht<(), u32> = internal::Smaht(Box::new(()), PhantomData); + let x: internal::Smaht = x; + + // This can pick both the `TraitCandidate` and the `ObjectCandidate` impl. + // + // However, the `ObjectCandidate` is considered an "inherent candidate", + // and therefore has priority over both the `TraitCandidate` as well as + // any other "nuisance" candidate" (if present). + let z = x.foo(); + + // Observe the type of `z` is `u32` + let _seetype: () = z; //~ ERROR mismatched types + //~| expected (), found u32 +} + + +fn both_impls_with_nuisance() { + // Similar to the `both_impls` example, except with a nuisance impl to + // make sure the `ObjectCandidate` indeed has a higher priority. + + use internal::X; + use nuisance_foo::NuisanceFoo; + + let x: internal::Smaht<(), u32> = internal::Smaht(Box::new(()), PhantomData); + let x: internal::Smaht = x; + let z = x.foo(); + + // Observe the type of `z` is `u32` + let _seetype: () = z; //~ ERROR mismatched types + //~| expected (), found u32 +} + +fn main() { +} diff --git a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr new file mode 100644 index 0000000000000..2d8449b96de41 --- /dev/null +++ b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr @@ -0,0 +1,72 @@ +error[E0308]: mismatched types + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:85:24 + | +LL | let _seetype: () = z; //~ ERROR mismatched types + | ^ expected (), found u32 + | + = note: expected type `()` + found type `u32` + +error[E0308]: mismatched types + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:102:24 + | +LL | let _seetype: () = z; //~ ERROR mismatched types + | ^ expected (), found u64 + | + = note: expected type `()` + found type `u64` + +error[E0034]: multiple applicable items in scope + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:120:15 + | +LL | let z = x.foo(); //~ ERROR multiple applicable items in scope + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in an impl of the trait `internal::X` for the type `_` + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:43:9 + | +LL | fn foo(self: Smaht) -> u64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `nuisance_foo::NuisanceFoo` for the type `_` + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:70:9 + | +LL | fn foo(self) {} + | ^^^^^^^^^^^^ +note: candidate #3 is defined in the trait `FinalFoo` + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:57:5 + | +LL | fn foo(&self) -> u8; + | ^^^^^^^^^^^^^^^^^^^^ + = help: to disambiguate the method call, write `FinalFoo::foo(x)` instead + +error[E0308]: mismatched types + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:137:24 + | +LL | let _seetype: () = z; //~ ERROR mismatched types + | ^ expected (), found u8 + | + = note: expected type `()` + found type `u8` + +error[E0308]: mismatched types + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:155:24 + | +LL | let _seetype: () = z; //~ ERROR mismatched types + | ^ expected (), found u32 + | + = note: expected type `()` + found type `u32` + +error[E0308]: mismatched types + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:172:24 + | +LL | let _seetype: () = z; //~ ERROR mismatched types + | ^ expected (), found u32 + | + = note: expected type `()` + found type `u32` + +error: aborting due to 6 previous errors + +Some errors occurred: E0034, E0308. +For more information about an error, try `rustc --explain E0034`. diff --git a/src/test/ui/methods/method-trait-object-with-hrtb.rs b/src/test/ui/methods/method-trait-object-with-hrtb.rs new file mode 100644 index 0000000000000..da2f13f5a2f8a --- /dev/null +++ b/src/test/ui/methods/method-trait-object-with-hrtb.rs @@ -0,0 +1,41 @@ +// compile-pass + +// Check that method probing ObjectCandidate works in the presence of +// auto traits and/or HRTBs. + +mod internal { + pub trait MyObject<'a> { + type Output; + + fn foo(&self) -> Self::Output; + } + + impl<'a> MyObject<'a> for () { + type Output = &'a u32; + + fn foo(&self) -> Self::Output { &4 } + } +} + +fn t1(d: &dyn for<'a> internal::MyObject<'a, Output=&'a u32>) { + d.foo(); +} + +fn t2(d: &dyn internal::MyObject<'static, Output=&'static u32>) { + d.foo(); +} + +fn t3(d: &(dyn for<'a> internal::MyObject<'a, Output=&'a u32> + Sync)) { + d.foo(); +} + +fn t4(d: &(dyn internal::MyObject<'static, Output=&'static u32> + Sync)) { + d.foo(); +} + +fn main() { + t1(&()); + t2(&()); + t3(&()); + t4(&()); +} From 062e817ab2c129c07b70c183686e8fa1ef2c9b06 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 29 Jan 2019 01:00:42 +0200 Subject: [PATCH 23/41] avoid committing to autoderef in object method probing --- src/librustc_typeck/check/method/probe.rs | 29 ++++++--- .../method-probe-no-guessing-dyn-trait.rs | 59 +++++++++++++++++++ 2 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 src/test/run-pass/methods/method-probe-no-guessing-dyn-trait.rs diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 03a0f6233a75e..be6a2ffa3eb7f 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -537,13 +537,28 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { match self_ty.value.value.sty { ty::Dynamic(ref data, ..) => { if let Some(p) = data.principal() { - let InferOk { value: instantiated_self_ty, obligations: _ } = - self.fcx.probe_instantiate_query_response( - self.span, &self.orig_steps_var_values, self_ty) - .unwrap_or_else(|_| { - span_bug!(self.span, "{:?} was applicable but now isn't?", self_ty) - }); - self.assemble_inherent_candidates_from_object(instantiated_self_ty); + // Subtle: we can't use `instantiate_query_response` here: using it will + // commit to all of the type equalities assumed by inference going through + // autoderef (see the `method-probe-no-guessing` test). + // + // However, in this code, it is OK if we end up with an object type that is + // "more general" than the object type that we are evaluating. For *every* + // object type `MY_OBJECT`, a function call that goes through a trait-ref + // of the form `::func` is a valid + // `ObjectCandidate`, and it should be discoverable "exactly" through one + // of the iterations in the autoderef loop, so there is no problem with it + // being discoverable in another one of these iterations. + // + // Using `instantiate_canonical_with_fresh_inference_vars` on our + // `Canonical>>` and then *throwing away* the + // `CanonicalVarValues` will exactly give us such a generalization - it + // will still match the original object type, but it won't pollute our + // type variables in any form, so just do that! + let (QueryResponse { value: generalized_self_ty, .. }, _ignored_var_values) = + self.fcx.instantiate_canonical_with_fresh_inference_vars( + self.span, &self_ty); + + self.assemble_inherent_candidates_from_object(generalized_self_ty); self.assemble_inherent_impl_candidates_for_type(p.def_id()); } } diff --git a/src/test/run-pass/methods/method-probe-no-guessing-dyn-trait.rs b/src/test/run-pass/methods/method-probe-no-guessing-dyn-trait.rs new file mode 100644 index 0000000000000..8c8165a100449 --- /dev/null +++ b/src/test/run-pass/methods/method-probe-no-guessing-dyn-trait.rs @@ -0,0 +1,59 @@ +// Check that method matching does not make "guesses" depending on +// Deref impls that don't eventually end up being picked. + +use std::ops::Deref; + +// An impl with less derefs will get called over an impl with more derefs, +// so `(t: Foo<_>).my_fn()` will use ` as MyTrait1>::my_fn(t)`, +// and does *not* force the `_` to equal `()`, because the Deref impl +// was *not* used. + +trait MyTrait1 { + fn my_fn(&self) {} +} + +impl MyTrait1 for Foo {} + +struct Foo(T); + +impl Deref for Foo<()> { + type Target = dyn MyTrait1 + 'static; + fn deref(&self) -> &(dyn MyTrait1 + 'static) { + panic!() + } +} + +// ...but if there is no impl with less derefs, the "guess" will be +// forced, so `(t: Bar<_>).my_fn2()` is `::my_fn2(*t)`, +// and because the deref impl is used, the `_` is forced to equal `u8`. + +trait MyTrait2 { + fn my_fn2(&self) {} +} + +impl MyTrait2 for u32 {} +struct Bar(T, u32); +impl Deref for Bar { + type Target = dyn MyTrait2 + 'static; + fn deref(&self) -> &(dyn MyTrait2 + 'static) { + &self.1 + } +} + +// actually invoke things + +fn main() { + let mut foo: Option> = None; + let mut bar: Option> = None; + let mut first_iter = true; + loop { + if !first_iter { + foo.as_ref().unwrap().my_fn(); + bar.as_ref().unwrap().my_fn2(); + break; + } + foo = Some(Foo(0)); + bar = Some(Bar(Default::default(), 0)); + first_iter = false; + } +} From e583c6244d09358ec1c143b90e6da3212d605faa Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 15 Jan 2019 23:21:10 +0100 Subject: [PATCH 24/41] Fixes text becoming invisible when element targetted --- src/librustdoc/html/static/themes/dark.css | 8 +------- src/librustdoc/html/static/themes/light.css | 8 +------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 1390be700634d..52a30967a2310 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -82,12 +82,6 @@ pre { border-bottom-color: #ddd; } -:target { background: #494a3d; } - -:target > .in-band { - background: #494a3d; -} - .content .method .where, .content .fn .where, .content .where.fmt-newline { @@ -252,7 +246,7 @@ a.test-arrow:hover{ color: #999; } -:target > code { +:target > code, :target > .in-band { background-color: #494a3d; } diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index 2b04dd2388d45..d20fea666e61d 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -84,12 +84,6 @@ pre { border-bottom-color: #ddd; } -:target { background: #FDFFD3; } - -:target > .in-band { - background: #FDFFD3; -} - .content .method .where, .content .fn .where, .content .where.fmt-newline { @@ -247,7 +241,7 @@ a.test-arrow:hover{ color: #999; } -:target > code { +:target > code, :target > .in-band { background: #FDFFD3; } From f22755f4cfe522213d8c75925054ff74b31cf47d Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 22 Feb 2019 13:40:21 +0100 Subject: [PATCH 25/41] Fix #57979 by allowing a legitimate type error to take precedence over an ICE. --- src/librustc/infer/canonical/canonicalizer.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index 408cba42ae04b..5a2686718185c 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -191,7 +191,16 @@ impl CanonicalizeRegionMode for CanonicalizeQueryResponse { // response should be executing in a fully // canonicalized environment, so there shouldn't be // any other region names it can come up. - bug!("unexpected region in query response: `{:?}`", r) + // + // rust-lang/rust#57464: `impl Trait` can leak local + // scopes (in manner violating typeck). Therefore, use + // `delay_span_bug` to allow type error over an ICE. + ty::tls::with_context(|c| { + c.tcx.sess.delay_span_bug( + syntax_pos::DUMMY_SP, + &format!("unexpected region in query response: `{:?}`", r)); + }); + r } } } From 687c44977ab66a433d8c9dec8f3a2f643f27e5c6 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 1 Feb 2019 10:41:08 -0500 Subject: [PATCH 26/41] make generalization code create new variables in correct universe In our type inference system, when we "generalize" a type T to become a suitable value for a type variable V, we sometimes wind up creating new inference variables. So, for example, if we are making V be some subtype of `&'X u32`, then we might instantiate V with `&'Y u32`. This generalized type is then related `&'Y u32 <: &'X u32`, resulting in a region constriant `'Y: 'X`. Previously, however, we were making these fresh variables like `'Y` in the "current universe", but they should be created in the universe of V. Moreover, we sometimes cheat in an invariant context and avoid creating fresh variables if we know the result must be equal -- we can only do that when the universes work out. --- src/librustc/infer/combine.rs | 71 +++++++++++++------ src/librustc/infer/mod.rs | 12 ++++ src/librustc/infer/region_constraints/mod.rs | 2 +- ...project-fn-ret-invariant.krisskross.stderr | 14 ++-- .../cache/project-fn-ret-invariant.rs | 4 +- .../project-fn-ret-invariant.transmute.stderr | 2 +- .../higher-ranked-projection.bad.stderr | 4 +- .../ui/hrtb/hrtb-perfect-forwarding.stderr | 4 +- src/test/ui/issues/issue-57843.rs | 24 +++++++ src/test/ui/issues/issue-57843.stderr | 12 ++++ 10 files changed, 114 insertions(+), 35 deletions(-) create mode 100644 src/test/ui/issues/issue-57843.rs create mode 100644 src/test/ui/issues/issue-57843.stderr diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index 40c11695d51e2..97f9c2ceba005 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -255,10 +255,24 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> { RelationDir::SupertypeOf => ty::Contravariant, }; + debug!("generalize: ambient_variance = {:?}", ambient_variance); + + let for_universe = match self.infcx.type_variables.borrow_mut().probe(for_vid) { + v @ TypeVariableValue::Known { .. } => panic!( + "instantiating {:?} which has a known value {:?}", + for_vid, + v, + ), + TypeVariableValue::Unknown { universe } => universe, + }; + + debug!("generalize: for_universe = {:?}", for_universe); + let mut generalize = Generalizer { infcx: self.infcx, span: self.trace.cause.span, for_vid_sub_root: self.infcx.type_variables.borrow_mut().sub_root_var(for_vid), + for_universe, ambient_variance, needs_wf: false, root_ty: ty, @@ -288,6 +302,11 @@ struct Generalizer<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> { /// that means we would have created a cyclic type. for_vid_sub_root: ty::TyVid, + /// The universe of the type variable that is in the process of + /// being instantiated. Any fresh variables that we create in this + /// process should be in that same universe. + for_universe: ty::UniverseIndex, + /// Track the variance as we descend into the type. ambient_variance: ty::Variance, @@ -386,6 +405,8 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { assert_eq!(t, t2); // we are abusing TypeRelation here; both LHS and RHS ought to be == + debug!("generalize: t={:?}", t); + // Check to see whether the type we are genealizing references // any other type variable related to `vid` via // subtyping. This is basically our "occurs check", preventing @@ -403,12 +424,17 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' match variables.probe(vid) { TypeVariableValue::Known { value: u } => { drop(variables); + debug!("generalize: known value {:?}", u); self.relate(&u, &u) } TypeVariableValue::Unknown { universe } => { match self.ambient_variance { // Invariant: no need to make a fresh type variable. - ty::Invariant => return Ok(t), + ty::Invariant => { + if self.for_universe.can_name(universe) { + return Ok(t); + } + } // Bivariant: make a fresh var, but we // may need a WF predicate. See @@ -422,7 +448,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' } let origin = *variables.var_origin(vid); - let new_var_id = variables.new_var(universe, false, origin); + let new_var_id = variables.new_var(self.for_universe, false, origin); let u = self.tcx().mk_var(new_var_id); debug!("generalize: replacing original vid={:?} with new={:?}", vid, u); @@ -448,6 +474,8 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' -> RelateResult<'tcx, ty::Region<'tcx>> { assert_eq!(r, r2); // we are abusing TypeRelation here; both LHS and RHS ought to be == + debug!("generalize: regions r={:?}", r); + match *r { // Never make variables for regions bound within the type itself, // nor for erased regions. @@ -456,37 +484,40 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' return Ok(r); } - // Always make a fresh region variable for placeholder - // regions; the higher-ranked decision procedures rely on - // this. - ty::RePlaceholder(..) => { } + ty::ReClosureBound(..) => { + span_bug!( + self.span, + "encountered unexpected ReClosureBound: {:?}", + r, + ); + } - // For anything else, we make a region variable, unless we - // are *equating*, in which case it's just wasteful. + ty::RePlaceholder(..) | + ty::ReVar(..) | ty::ReEmpty | ty::ReStatic | ty::ReScope(..) | - ty::ReVar(..) | ty::ReEarlyBound(..) | ty::ReFree(..) => { - match self.ambient_variance { - ty::Invariant => return Ok(r), - ty::Bivariant | ty::Covariant | ty::Contravariant => (), - } + // see common code below } + } - ty::ReClosureBound(..) => { - span_bug!( - self.span, - "encountered unexpected ReClosureBound: {:?}", - r, - ); + // If we are in an invariant context, we can re-use the region + // as is, unless it happens to be in some universe that we + // can't name. (In the case of a region *variable*, we could + // use it if we promoted it into our universe, but we don't + // bother.) + if let ty::Invariant = self.ambient_variance { + let r_universe = self.infcx.universe_of_region(r); + if self.for_universe.can_name(r_universe) { + return Ok(r); } } // FIXME: This is non-ideal because we don't give a // very descriptive origin for this region variable. - Ok(self.infcx.next_region_var(MiscVariable(self.span))) + Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.span), self.for_universe)) } } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 958982545750f..1e2faaf506926 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1016,6 +1016,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.tcx.mk_region(ty::ReVar(region_var)) } + /// Return the universe that the region `r` was created in. For + /// most regions (e.g., `'static`, named regions from the user, + /// etc) this is the root universe U0. For inference variables or + /// placeholders, however, it will return the universe which which + /// they are associated. + fn universe_of_region( + &self, + r: ty::Region<'tcx>, + ) -> ty::UniverseIndex { + self.borrow_region_constraints().universe(r) + } + /// Number of region variables created so far. pub fn num_region_vars(&self) -> usize { self.borrow_region_constraints().num_region_vars() diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index 56ae850226c91..deae1e2357a49 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -814,7 +814,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { new_r } - fn universe(&self, region: Region<'tcx>) -> ty::UniverseIndex { + pub fn universe(&self, region: Region<'tcx>) -> ty::UniverseIndex { match *region { ty::ReScope(..) | ty::ReStatic diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr index 46901b44c4b6d..fa831ea81dcfb 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr @@ -9,15 +9,15 @@ LL | let a = bar(foo, y); //[krisskross]~ ERROR E0623 | ^ ...but data from `x` is returned here error[E0623]: lifetime mismatch - --> $DIR/project-fn-ret-invariant.rs:55:8 + --> $DIR/project-fn-ret-invariant.rs:54:21 | LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { - | -------- -------------------- - | | - | this parameter and the return type are declared with different lifetimes... -... -LL | (a, b) //[krisskross]~ ERROR E0623 - | ^ ...but data from `x` is returned here + | -------- -------------------- + | | + | this parameter and the return type are declared with different lifetimes... +LL | let a = bar(foo, y); //[krisskross]~ ERROR E0623 +LL | let b = bar(foo, x); //[krisskross]~ ERROR E0623 + | ^ ...but data from `y` is returned here error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs index dfcf31b3b1f26..54b6e3642c2ea 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs @@ -51,8 +51,8 @@ fn baz<'a,'b>(x: Type<'a>) -> Type<'static> { #[cfg(krisskross)] // two instantiations, mixing and matching: BAD fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { let a = bar(foo, y); //[krisskross]~ ERROR E0623 - let b = bar(foo, x); - (a, b) //[krisskross]~ ERROR E0623 + let b = bar(foo, x); //[krisskross]~ ERROR E0623 + (a, b) } #[rustc_error] diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr index 947844c45c408..dd1212eaac91d 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr @@ -1,4 +1,4 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements +error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements --> $DIR/project-fn-ret-invariant.rs:48:8 | LL | bar(foo, x) //[transmute]~ ERROR E0495 diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr index e4704494e1492..811c9a8f5e12b 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | foo(()); | ^^^ one type is more general than the other | - = note: expected type `Mirror` - found type `Mirror` + = note: expected type `&'a ()` + found type `&()` error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr index ec3bf8a1a1be3..439a5ffcff59d 100644 --- a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr +++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | foo_hrtb_bar_not(&mut t); //~ ERROR E0308 | ^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: expected type `Foo<&'a isize>` - found type `Foo<&isize>` + = note: expected type `Bar<&'a isize>` + found type `Bar<&'b isize>` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-57843.rs b/src/test/ui/issues/issue-57843.rs new file mode 100644 index 0000000000000..466082552667b --- /dev/null +++ b/src/test/ui/issues/issue-57843.rs @@ -0,0 +1,24 @@ +// Regression test for an ICE that occurred with the universes code: +// +// The signature of the closure `|_|` was being inferred to +// `exists<'r> fn(&'r u8)`. This should result in a type error since +// the signature `for<'r> fn(&'r u8)` is required. However, due to a +// bug in the type variable generalization code, the placeholder for +// `'r` was leaking out into the writeback phase, causing an ICE. + +trait ClonableFn { + fn clone(&self) -> Box; +} + +impl ClonableFn for F +where F: Fn(T) + Clone { + fn clone(&self) -> Box { + Box::new(self.clone()) + } +} + +struct Foo(Box ClonableFn<&'a bool>>); + +fn main() { + Foo(Box::new(|_| ())); //~ ERROR mismatched types +} diff --git a/src/test/ui/issues/issue-57843.stderr b/src/test/ui/issues/issue-57843.stderr new file mode 100644 index 0000000000000..4ef884cb3f589 --- /dev/null +++ b/src/test/ui/issues/issue-57843.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/issue-57843.rs:23:9 + | +LL | Foo(Box::new(|_| ())); //~ ERROR mismatched types + | ^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `std::ops::FnOnce<(&'a bool,)>` + found type `std::ops::FnOnce<(&bool,)>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From f599ab6e0f6da00e42ea24b66e3f75f7e335cbd5 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 20 Feb 2019 04:57:32 -0500 Subject: [PATCH 27/41] s/skol_/placeholder_/ --- src/librustc/traits/select.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 6db6fe31fba70..a87571d123638 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1639,15 +1639,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ) -> bool { let poly_trait_predicate = self.infcx() .resolve_type_vars_if_possible(&obligation.predicate); - let (skol_trait_predicate, _) = self.infcx() + let (placeholder_trait_predicate, _) = self.infcx() .replace_bound_vars_with_placeholders(&poly_trait_predicate); debug!( "match_projection_obligation_against_definition_bounds: \ - skol_trait_predicate={:?}", - skol_trait_predicate, + placeholder_trait_predicate={:?}", + placeholder_trait_predicate, ); - let (def_id, substs) = match skol_trait_predicate.trait_ref.self_ty().sty { + let (def_id, substs) = match placeholder_trait_predicate.trait_ref.self_ty().sty { ty::Projection(ref data) => (data.trait_ref(self.tcx()).def_id, data.substs), ty::Opaque(def_id, substs) => (def_id, substs), _ => { @@ -1655,7 +1655,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation.cause.span, "match_projection_obligation_against_definition_bounds() called \ but self-ty is not a projection: {:?}", - skol_trait_predicate.trait_ref.self_ty() + placeholder_trait_predicate.trait_ref.self_ty() ); } }; @@ -1680,7 +1680,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { self.match_projection( obligation, bound.clone(), - skol_trait_predicate.trait_ref.clone(), + placeholder_trait_predicate.trait_ref.clone(), ) }) }); @@ -1697,7 +1697,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let result = self.match_projection( obligation, bound, - skol_trait_predicate.trait_ref.clone(), + placeholder_trait_predicate.trait_ref.clone(), ); assert!(result); @@ -1710,12 +1710,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, trait_bound: ty::PolyTraitRef<'tcx>, - skol_trait_ref: ty::TraitRef<'tcx>, + placeholder_trait_ref: ty::TraitRef<'tcx>, ) -> bool { - debug_assert!(!skol_trait_ref.has_escaping_bound_vars()); + debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars()); self.infcx .at(&obligation.cause, obligation.param_env) - .sup(ty::Binder::dummy(skol_trait_ref), trait_bound) + .sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound) .is_ok() } From 4916c8fdbd0d88341909dcd593321267272fd907 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 19 Feb 2019 18:38:42 -0500 Subject: [PATCH 28/41] reintroduce `commit_if_ok` call into `higher_ranked_sub` --- src/librustc/infer/higher_ranked/mod.rs | 47 ++++++++++++++----------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index 709e8c0ba9b24..ff3ffd8ce499c 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -29,27 +29,29 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { let span = self.trace.cause.span; - // First, we instantiate each bound region in the supertype with a - // fresh placeholder region. - let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(b); + return self.infcx.commit_if_ok(|_snapshot| { + // First, we instantiate each bound region in the supertype with a + // fresh placeholder region. + let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(b); - // Next, we instantiate each bound region in the subtype - // with a fresh region variable. These region variables -- - // but no other pre-existing region variables -- can name - // the placeholders. - let (a_prime, _) = - self.infcx - .replace_bound_vars_with_fresh_vars(span, HigherRankedType, a); + // Next, we instantiate each bound region in the subtype + // with a fresh region variable. These region variables -- + // but no other pre-existing region variables -- can name + // the placeholders. + let (a_prime, _) = + self.infcx + .replace_bound_vars_with_fresh_vars(span, HigherRankedType, a); - debug!("a_prime={:?}", a_prime); - debug!("b_prime={:?}", b_prime); + debug!("a_prime={:?}", a_prime); + debug!("b_prime={:?}", b_prime); - // Compare types now that bound regions have been replaced. - let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?; + // Compare types now that bound regions have been replaced. + let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?; - debug!("higher_ranked_sub: OK result={:?}", result); + debug!("higher_ranked_sub: OK result={:?}", result); - Ok(ty::Binder::bind(result)) + Ok(ty::Binder::bind(result)) + }); } } @@ -72,10 +74,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/hrtb.html pub fn replace_bound_vars_with_placeholders( &self, - binder: &ty::Binder + binder: &ty::Binder, ) -> (T, PlaceholderMap<'tcx>) where - T: TypeFoldable<'tcx> + T: TypeFoldable<'tcx>, { let next_universe = self.create_next_universe(); @@ -96,10 +98,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let (result, map) = self.tcx.replace_bound_vars(binder, fld_r, fld_t); debug!( - "replace_bound_vars_with_placeholders(binder={:?}, result={:?}, map={:?})", + "replace_bound_vars_with_placeholders(\ + next_universe={:?}, \ + binder={:?}, \ + result={:?}, \ + map={:?})", + next_universe, binder, result, - map + map, ); (result, map) From 2a8c36c949d4594f4cb91092f3f5b0276474f41f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 19 Feb 2019 18:48:29 -0500 Subject: [PATCH 29/41] reintroduce `commit_if_ok` calls to `subtype_predicate` --- src/librustc/infer/mod.rs | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 1e2faaf506926..fa89eb3bddf85 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -935,20 +935,22 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { return None; } - let ( - ty::SubtypePredicate { - a_is_expected, - a, - b, - }, - _, - ) = self.replace_bound_vars_with_placeholders(predicate); - - Some( - self.at(cause, param_env) - .sub_exp(a_is_expected, a, b) - .map(|ok| ok.unit()), - ) + Some(self.commit_if_ok(|_snapshot| { + let ( + ty::SubtypePredicate { + a_is_expected, + a, + b, + }, + _, + ) = self.replace_bound_vars_with_placeholders(predicate); + + Ok( + self.at(cause, param_env) + .sub_exp(a_is_expected, a, b)? + .unit(), + ) + })) } pub fn region_outlives_predicate( From 3693f1844e0414ed69a8f84569b1b1f0c346ee3c Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 20 Feb 2019 05:22:23 -0500 Subject: [PATCH 30/41] introduce a dummy leak check and invoke it in all the right places This set of diffs was produced by combing through b68fad670bb3612cac26e50751e4fd9150e59977 and seeing where the `leak_check` used to be invoked and how. --- src/librustc/infer/higher_ranked/mod.rs | 26 ++++++++++++-- src/librustc/infer/mod.rs | 33 +++++++++++------- src/librustc/traits/auto_trait.rs | 8 ++++- src/librustc/traits/error_reporting.rs | 11 ++++-- src/librustc/traits/fulfill.rs | 6 ++-- src/librustc/traits/project.rs | 14 ++++---- src/librustc/traits/select.rs | 46 ++++++++++++++++++------- 7 files changed, 105 insertions(+), 39 deletions(-) diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index ff3ffd8ce499c..aed6a5673d526 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -4,6 +4,7 @@ use super::combine::CombineFields; use super::{HigherRankedType, InferCtxt, PlaceholderMap}; +use infer::CombinedSnapshot; use ty::relate::{Relate, RelateResult, TypeRelation}; use ty::{self, Binder, TypeFoldable}; @@ -29,10 +30,10 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { let span = self.trace.cause.span; - return self.infcx.commit_if_ok(|_snapshot| { + return self.infcx.commit_if_ok(|snapshot| { // First, we instantiate each bound region in the supertype with a // fresh placeholder region. - let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(b); + let (b_prime, placeholder_map) = self.infcx.replace_bound_vars_with_placeholders(b); // Next, we instantiate each bound region in the subtype // with a fresh region variable. These region variables -- @@ -48,6 +49,9 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { // Compare types now that bound regions have been replaced. let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?; + self.infcx + .leak_check(!a_is_expected, &placeholder_map, snapshot)?; + debug!("higher_ranked_sub: OK result={:?}", result); Ok(ty::Binder::bind(result)) @@ -111,4 +115,22 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { (result, map) } + + /// Searches region constraints created since `snapshot` that + /// affect one of the placeholders in `placeholder_map`, returning + /// an error if any of the placeholders are related to another + /// placeholder or would have to escape into some parent universe + /// that cannot name them. + /// + /// This is a temporary backwards compatibility measure to try and + /// retain the older (arguably incorrect) behavior of the + /// compiler. + pub fn leak_check( + &self, + _overly_polymorphic: bool, + _placeholder_map: &PlaceholderMap<'tcx>, + _snapshot: &CombinedSnapshot<'_, 'tcx>, + ) -> RelateResult<'tcx, ()> { + Ok(()) + } } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index fa89eb3bddf85..a831c46ce7245 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -935,21 +935,22 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { return None; } - Some(self.commit_if_ok(|_snapshot| { + Some(self.commit_if_ok(|snapshot| { let ( ty::SubtypePredicate { a_is_expected, a, b, }, - _, + placeholder_map, ) = self.replace_bound_vars_with_placeholders(predicate); - Ok( - self.at(cause, param_env) - .sub_exp(a_is_expected, a, b)? - .unit(), - ) + let ok = self.at(cause, param_env) + .sub_exp(a_is_expected, a, b)?; + + self.leak_check(false, &placeholder_map, snapshot)?; + + Ok(ok.unit()) })) } @@ -957,12 +958,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { &self, cause: &traits::ObligationCause<'tcx>, predicate: &ty::PolyRegionOutlivesPredicate<'tcx>, - ) { - let (ty::OutlivesPredicate(r_a, r_b), _) = - self.replace_bound_vars_with_placeholders(predicate); - let origin = - SubregionOrigin::from_obligation_cause(cause, || RelateRegionParamBound(cause.span)); - self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` + ) -> UnitResult<'tcx> { + self.commit_if_ok(|snapshot| { + let (ty::OutlivesPredicate(r_a, r_b), placeholder_map) = + self.replace_bound_vars_with_placeholders(predicate); + let origin = SubregionOrigin::from_obligation_cause( + cause, + || RelateRegionParamBound(cause.span), + ); + self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` + self.leak_check(false, &placeholder_map, snapshot)?; + Ok(()) + }) } pub fn next_ty_var_id(&self, diverging: bool, origin: TypeVariableOrigin) -> TyVid { diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index 92004ece26d00..f96c4e9014b36 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -771,7 +771,13 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { } } &ty::Predicate::RegionOutlives(ref binder) => { - let () = select.infcx().region_outlives_predicate(&dummy_cause, binder); + if select + .infcx() + .region_outlives_predicate(&dummy_cause, binder) + .is_err() + { + return false; + } } &ty::Predicate::TypeOutlives(ref binder) => { match ( diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 367a7eacdfcaf..c40af035c7273 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -726,9 +726,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } ty::Predicate::RegionOutlives(ref predicate) => { - // These errors should show up as region - // inference failures. - panic!("region outlives {:?} failed", predicate); + let predicate = self.resolve_type_vars_if_possible(predicate); + let err = self.region_outlives_predicate(&obligation.cause, + &predicate).err().unwrap(); + struct_span_err!( + self.tcx.sess, span, E0279, + "the requirement `{}` is not satisfied (`{}`)", + predicate, err, + ) } ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => { diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 2e00d4d4b7c3b..219e971b3c927 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -331,8 +331,10 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx, } ty::Predicate::RegionOutlives(ref binder) => { - let () = self.selcx.infcx().region_outlives_predicate(&obligation.cause, binder); - ProcessResult::Changed(vec![]) + match self.selcx.infcx().region_outlives_predicate(&obligation.cause, binder) { + Ok(()) => ProcessResult::Changed(vec![]), + Err(_) => ProcessResult::Error(CodeSelectionError(Unimplemented)), + } } ty::Predicate::TypeOutlives(ref binder) => { diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 21151276e7299..39b2d118fddfd 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -191,12 +191,15 @@ pub fn poly_project_and_unify_type<'cx, 'gcx, 'tcx>( obligation); let infcx = selcx.infcx(); - infcx.commit_if_ok(|_| { - let (placeholder_predicate, _) = + infcx.commit_if_ok(|snapshot| { + let (placeholder_predicate, placeholder_map) = infcx.replace_bound_vars_with_placeholders(&obligation.predicate); let placeholder_obligation = obligation.with(placeholder_predicate); - project_and_unify_type(selcx, &placeholder_obligation) + let result = project_and_unify_type(selcx, &placeholder_obligation)?; + infcx.leak_check(false, &placeholder_map, snapshot) + .map_err(|err| MismatchedProjectionTypes { err })?; + Ok(result) }) } @@ -1427,9 +1430,8 @@ fn confirm_callable_candidate<'cx, 'gcx, 'tcx>( fn confirm_param_env_candidate<'cx, 'gcx, 'tcx>( selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - poly_cache_entry: ty::PolyProjectionPredicate<'tcx>) - -> Progress<'tcx> -{ + poly_cache_entry: ty::PolyProjectionPredicate<'tcx>, +) -> Progress<'tcx> { let infcx = selcx.infcx(); let cause = &obligation.cause; let param_env = obligation.param_env; diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index a87571d123638..20d95de60b312 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -29,7 +29,7 @@ use super::{ use dep_graph::{DepKind, DepNodeIndex}; use hir::def_id::DefId; -use infer::{InferCtxt, InferOk, TypeFreshener}; +use infer::{CombinedSnapshot, InferCtxt, InferOk, PlaceholderMap, TypeFreshener}; use middle::lang_items; use mir::interpret::GlobalId; use ty::fast_reject; @@ -1624,8 +1624,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { _ => return, } - let result = self.infcx.probe(|_| { - self.match_projection_obligation_against_definition_bounds(obligation) + let result = self.infcx.probe(|snapshot| { + self.match_projection_obligation_against_definition_bounds( + obligation, + snapshot, + ) }); if result { @@ -1636,10 +1639,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn match_projection_obligation_against_definition_bounds( &mut self, obligation: &TraitObligation<'tcx>, + snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> bool { let poly_trait_predicate = self.infcx() .resolve_type_vars_if_possible(&obligation.predicate); - let (placeholder_trait_predicate, _) = self.infcx() + let (placeholder_trait_predicate, placeholder_map) = self.infcx() .replace_bound_vars_with_placeholders(&poly_trait_predicate); debug!( "match_projection_obligation_against_definition_bounds: \ @@ -1681,6 +1685,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation, bound.clone(), placeholder_trait_predicate.trait_ref.clone(), + &placeholder_map, + snapshot, ) }) }); @@ -1698,6 +1704,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation, bound, placeholder_trait_predicate.trait_ref.clone(), + &placeholder_map, + snapshot, ); assert!(result); @@ -1711,12 +1719,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation: &TraitObligation<'tcx>, trait_bound: ty::PolyTraitRef<'tcx>, placeholder_trait_ref: ty::TraitRef<'tcx>, + placeholder_map: &PlaceholderMap<'tcx>, + snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> bool { debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars()); self.infcx .at(&obligation.cause, obligation.param_env) .sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound) .is_ok() + && + self.infcx.leak_check(false, placeholder_map, snapshot).is_ok() } /// Given an obligation like ``, search the obligations that the caller @@ -1917,8 +1929,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation.predicate.def_id(), obligation.predicate.skip_binder().trait_ref.self_ty(), |impl_def_id| { - self.infcx.probe(|_| { - if let Ok(_substs) = self.match_impl(impl_def_id, obligation) + self.infcx.probe(|snapshot| { + if let Ok(_substs) = self.match_impl(impl_def_id, obligation, snapshot) { candidates.vec.push(ImplCandidate(impl_def_id)); } @@ -2697,9 +2709,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) { - self.infcx.in_snapshot(|_| { + self.infcx.in_snapshot(|snapshot| { let result = - self.match_projection_obligation_against_definition_bounds(obligation); + self.match_projection_obligation_against_definition_bounds( + obligation, + snapshot, + ); assert!(result); }) } @@ -2851,8 +2866,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // First, create the substitutions by matching the impl again, // this time not in a probe. - self.infcx.in_snapshot(|_| { - let substs = self.rematch_impl(impl_def_id, obligation); + self.infcx.in_snapshot(|snapshot| { + let substs = self.rematch_impl(impl_def_id, obligation, snapshot); debug!("confirm_impl_candidate: substs={:?}", substs); let cause = obligation.derived_cause(ImplDerivedObligation); self.vtable_impl( @@ -3443,8 +3458,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { &mut self, impl_def_id: DefId, obligation: &TraitObligation<'tcx>, + snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> Normalized<'tcx, &'tcx Substs<'tcx>> { - match self.match_impl(impl_def_id, obligation) { + match self.match_impl(impl_def_id, obligation, snapshot) { Ok(substs) => substs, Err(()) => { bug!( @@ -3460,6 +3476,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { &mut self, impl_def_id: DefId, obligation: &TraitObligation<'tcx>, + snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> Result>, ()> { let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap(); @@ -3470,7 +3487,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { return Err(()); } - let (skol_obligation, _) = self.infcx() + let (skol_obligation, placeholder_map) = self.infcx() .replace_bound_vars_with_placeholders(&obligation.predicate); let skol_obligation_trait_ref = skol_obligation.trait_ref; @@ -3502,6 +3519,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { .map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?; nested_obligations.extend(obligations); + if let Err(e) = self.infcx.leak_check(false, &placeholder_map, snapshot) { + debug!("match_impl: failed leak check due to `{}`", e); + return Err(()); + } + debug!("match_impl: success impl_substs={:?}", impl_substs); Ok(Normalized { value: impl_substs, From 85a24b1a7d3dbbce905457494a151d4502a15a39 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 20 Feb 2019 05:39:04 -0500 Subject: [PATCH 31/41] restore the actual leak-check --- src/librustc/infer/higher_ranked/mod.rs | 19 +- .../infer/region_constraints/leak_check.rs | 162 ++++++++++++++++++ src/librustc/infer/region_constraints/mod.rs | 2 + src/librustc/ty/error.rs | 16 +- src/librustc/ty/structural_impls.rs | 8 + src/test/ui/hrtb/issue-46989.rs | 42 +++++ src/test/ui/hrtb/issue-57639.rs | 29 ++++ src/test/ui/hrtb/issue-58451.rs | 13 ++ 8 files changed, 277 insertions(+), 14 deletions(-) create mode 100644 src/librustc/infer/region_constraints/leak_check.rs create mode 100644 src/test/ui/hrtb/issue-46989.rs create mode 100644 src/test/ui/hrtb/issue-57639.rs create mode 100644 src/test/ui/hrtb/issue-58451.rs diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index aed6a5673d526..70ab5a9b3c05e 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -116,21 +116,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { (result, map) } - /// Searches region constraints created since `snapshot` that - /// affect one of the placeholders in `placeholder_map`, returning - /// an error if any of the placeholders are related to another - /// placeholder or would have to escape into some parent universe - /// that cannot name them. - /// - /// This is a temporary backwards compatibility measure to try and - /// retain the older (arguably incorrect) behavior of the - /// compiler. + /// See `infer::region_constraints::RegionConstraintCollector::leak_check`. pub fn leak_check( &self, - _overly_polymorphic: bool, - _placeholder_map: &PlaceholderMap<'tcx>, - _snapshot: &CombinedSnapshot<'_, 'tcx>, + overly_polymorphic: bool, + placeholder_map: &PlaceholderMap<'tcx>, + snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> RelateResult<'tcx, ()> { - Ok(()) + self.borrow_region_constraints() + .leak_check(self.tcx, overly_polymorphic, placeholder_map, snapshot) } } diff --git a/src/librustc/infer/region_constraints/leak_check.rs b/src/librustc/infer/region_constraints/leak_check.rs new file mode 100644 index 0000000000000..4056b9e2d83bc --- /dev/null +++ b/src/librustc/infer/region_constraints/leak_check.rs @@ -0,0 +1,162 @@ +use super::*; +use crate::infer::{CombinedSnapshot, PlaceholderMap}; +use crate::ty::error::TypeError; +use crate::ty::relate::RelateResult; + +impl<'tcx> RegionConstraintCollector<'tcx> { + /// Searches region constraints created since `snapshot` that + /// affect one of the placeholders in `placeholder_map`, returning + /// an error if any of the placeholders are related to another + /// placeholder or would have to escape into some parent universe + /// that cannot name them. + /// + /// This is a temporary backwards compatibility measure to try and + /// retain the older (arguably incorrect) behavior of the + /// compiler. + /// + /// NB. The use of snapshot here is mostly an efficiency thing -- + /// we could search *all* region constraints, but that'd be a + /// bigger set and the data structures are not setup for that. If + /// we wind up keeping some form of this check long term, it would + /// probably be better to remove the snapshot parameter and to + /// refactor the constraint set. + pub fn leak_check( + &mut self, + tcx: TyCtxt<'_, '_, 'tcx>, + overly_polymorphic: bool, + placeholder_map: &PlaceholderMap<'tcx>, + _snapshot: &CombinedSnapshot<'_, 'tcx>, + ) -> RelateResult<'tcx, ()> { + debug!("leak_check(placeholders={:?})", placeholder_map); + + assert!(self.in_snapshot()); + + // Go through each placeholder that we created. + for (_, &placeholder_region) in placeholder_map { + // Find the universe this placeholder inhabits. + let placeholder = match placeholder_region { + ty::RePlaceholder(p) => p, + _ => bug!( + "leak_check: expected placeholder found {:?}", + placeholder_region, + ), + }; + + // Find all regions that are related to this placeholder + // in some way. This means any region that either outlives + // or is outlived by a placeholder. + let mut taint_set = TaintSet::new( + TaintDirections::both(), + placeholder_region, + ); + taint_set.fixed_point(tcx, &self.undo_log, &self.data.verifys); + let tainted_regions = taint_set.into_set(); + + // Report an error if two placeholders in the same universe + // are related to one another, or if a placeholder is related + // to something from a parent universe. + for &tainted_region in &tainted_regions { + if let ty::RePlaceholder(_) = tainted_region { + // Two placeholders cannot be related: + if tainted_region == placeholder_region { + continue; + } + } else if self.universe(tainted_region).can_name(placeholder.universe) { + continue; + } + + return Err(if overly_polymorphic { + debug!("Overly polymorphic!"); + TypeError::RegionsOverlyPolymorphic(placeholder.name, tainted_region) + } else { + debug!("Not as polymorphic!"); + TypeError::RegionsInsufficientlyPolymorphic(placeholder.name, tainted_region) + }); + } + } + + Ok(()) + } +} + +#[derive(Debug)] +struct TaintSet<'tcx> { + directions: TaintDirections, + regions: FxHashSet>, +} + +impl<'tcx> TaintSet<'tcx> { + fn new(directions: TaintDirections, initial_region: ty::Region<'tcx>) -> Self { + let mut regions = FxHashSet::default(); + regions.insert(initial_region); + TaintSet { + directions: directions, + regions: regions, + } + } + + fn fixed_point( + &mut self, + tcx: TyCtxt<'_, '_, 'tcx>, + undo_log: &[UndoLog<'tcx>], + verifys: &[Verify<'tcx>], + ) { + let mut prev_len = 0; + while prev_len < self.len() { + debug!( + "tainted: prev_len = {:?} new_len = {:?}", + prev_len, + self.len() + ); + + prev_len = self.len(); + + for undo_entry in undo_log { + match undo_entry { + &AddConstraint(Constraint::VarSubVar(a, b)) => { + self.add_edge(tcx.mk_region(ReVar(a)), tcx.mk_region(ReVar(b))); + } + &AddConstraint(Constraint::RegSubVar(a, b)) => { + self.add_edge(a, tcx.mk_region(ReVar(b))); + } + &AddConstraint(Constraint::VarSubReg(a, b)) => { + self.add_edge(tcx.mk_region(ReVar(a)), b); + } + &AddConstraint(Constraint::RegSubReg(a, b)) => { + self.add_edge(a, b); + } + &AddGiven(a, b) => { + self.add_edge(a, tcx.mk_region(ReVar(b))); + } + &AddVerify(i) => span_bug!( + verifys[i].origin.span(), + "we never add verifications while doing higher-ranked things", + ), + &Purged | &AddCombination(..) | &AddVar(..) => {} + } + } + } + } + + fn into_set(self) -> FxHashSet> { + self.regions + } + + fn len(&self) -> usize { + self.regions.len() + } + + fn add_edge(&mut self, source: ty::Region<'tcx>, target: ty::Region<'tcx>) { + if self.directions.incoming { + if self.regions.contains(&target) { + self.regions.insert(source); + } + } + + if self.directions.outgoing { + if self.regions.contains(&source) { + self.regions.insert(target); + } + } + } +} diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index deae1e2357a49..07a676a86d3d7 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -17,6 +17,8 @@ use ty::{Region, RegionVid}; use std::collections::BTreeMap; use std::{cmp, fmt, mem, u32}; +mod leak_check; + #[derive(Default)] pub struct RegionConstraintCollector<'tcx> { /// For each `RegionVid`, the corresponding `RegionVariableOrigin`. diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 834b541d4c01b..774c538500b2d 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -1,5 +1,5 @@ use hir::def_id::DefId; -use ty::{self, Region, Ty, TyCtxt}; +use ty::{self, BoundRegion, Region, Ty, TyCtxt}; use std::borrow::Cow; use std::fmt; use rustc_target::spec::abi; @@ -27,6 +27,8 @@ pub enum TypeError<'tcx> { ArgCount, RegionsDoesNotOutlive(Region<'tcx>, Region<'tcx>), + RegionsInsufficientlyPolymorphic(BoundRegion, Region<'tcx>), + RegionsOverlyPolymorphic(BoundRegion, Region<'tcx>), RegionsPlaceholderMismatch, Sorts(ExpectedFound>), @@ -101,6 +103,18 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { RegionsDoesNotOutlive(..) => { write!(f, "lifetime mismatch") } + RegionsInsufficientlyPolymorphic(br, _) => { + write!(f, + "expected bound lifetime parameter{}{}, found concrete lifetime", + if br.is_named() { " " } else { "" }, + br) + } + RegionsOverlyPolymorphic(br, _) => { + write!(f, + "expected concrete lifetime, found bound lifetime parameter{}{}", + if br.is_named() { " " } else { "" }, + br) + } RegionsPlaceholderMismatch => { write!(f, "one type is more general than the other") } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index dd9ffd08a4ef5..b09437813bd03 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -434,6 +434,12 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { RegionsDoesNotOutlive(a, b) => { return tcx.lift(&(a, b)).map(|(a, b)| RegionsDoesNotOutlive(a, b)) } + RegionsInsufficientlyPolymorphic(a, b) => { + return tcx.lift(&b).map(|b| RegionsInsufficientlyPolymorphic(a, b)) + } + RegionsOverlyPolymorphic(a, b) => { + return tcx.lift(&b).map(|b| RegionsOverlyPolymorphic(a, b)) + } RegionsPlaceholderMismatch => RegionsPlaceholderMismatch, IntMismatch(x) => IntMismatch(x), FloatMismatch(x) => FloatMismatch(x), @@ -1021,6 +1027,8 @@ EnumTypeFoldableImpl! { (ty::error::TypeError::FixedArraySize)(x), (ty::error::TypeError::ArgCount), (ty::error::TypeError::RegionsDoesNotOutlive)(a, b), + (ty::error::TypeError::RegionsInsufficientlyPolymorphic)(a, b), + (ty::error::TypeError::RegionsOverlyPolymorphic)(a, b), (ty::error::TypeError::RegionsPlaceholderMismatch), (ty::error::TypeError::IntMismatch)(x), (ty::error::TypeError::FloatMismatch)(x), diff --git a/src/test/ui/hrtb/issue-46989.rs b/src/test/ui/hrtb/issue-46989.rs new file mode 100644 index 0000000000000..2c85905545807 --- /dev/null +++ b/src/test/ui/hrtb/issue-46989.rs @@ -0,0 +1,42 @@ +// Regression test for #46989: +// +// In the move to universes, this test started passing. +// It is not necessarily WRONG to do so, but it was a bit +// surprising. The reason that it passed is that when we were +// asked to prove that +// +// for<'a> fn(&'a i32): Foo +// +// we were able to use the impl below to prove +// +// fn(&'empty i32): Foo +// +// and then we were able to prove that +// +// fn(&'empty i32) = for<'a> fn(&'a i32) +// +// This last fact is somewhat surprising, but essentially "falls out" +// from handling variance correctly. In particular, consider the subtyping +// relations. First: +// +// fn(&'empty i32) <: for<'a> fn(&'a i32) +// +// This holds because -- intuitively -- a fn that takes a reference but doesn't use +// it can be given a reference with any lifetime. Similarly, the opposite direction: +// +// for<'a> fn(&'a i32) <: fn(&'empty i32) +// +// holds because 'a can be instantiated to 'empty. + +trait Foo { + +} + +impl Foo for fn(A) { } + +fn assert_foo() {} + +fn main() { + assert_foo::(); + //~^ ERROR the trait bound `for<'r> fn(&'r i32): Foo` is not satisfied +} diff --git a/src/test/ui/hrtb/issue-57639.rs b/src/test/ui/hrtb/issue-57639.rs new file mode 100644 index 0000000000000..4bcaef3616bd5 --- /dev/null +++ b/src/test/ui/hrtb/issue-57639.rs @@ -0,0 +1,29 @@ +// Regression test for #57639: +// +// In the move to universes, this test stopped working. The problem +// was that when the trait solver was asked to prove `for<'a> T::Item: +// Foo<'a>` as part of WF checking, it wound up "eagerly committing" +// to the where clause, which says that `T::Item: Foo<'a>`, but it +// should instead have been using the bound found in the trait +// declaration. Pre-universe, this used to work out ok because we got +// "eager errors" due to the leak check. +// +// See [this comment on GitHub][c] for more details. +// +// run-pass +// +// [c]: https://github.com/rust-lang/rust/issues/57639#issuecomment-455685861 + +trait Foo<'a> {} + +trait Bar { + type Item: for<'a> Foo<'a>; +} + +fn foo<'a, T>(_: T) +where + T: Bar, + T::Item: Foo<'a>, +{} + +fn main() { } diff --git a/src/test/ui/hrtb/issue-58451.rs b/src/test/ui/hrtb/issue-58451.rs new file mode 100644 index 0000000000000..7ca6914d2ea96 --- /dev/null +++ b/src/test/ui/hrtb/issue-58451.rs @@ -0,0 +1,13 @@ +// Regression test for #58451: +// +// Error reporting here encountered an ICE in the shift to universes. + +fn f(i: I) +where + I: IntoIterator, + I::Item: for<'a> Into<&'a ()>, +{} + +fn main() { + f(&[f()]); +} From 542ad5e2a017f542784ee0bcd7c44583389bb897 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 20 Feb 2019 12:52:23 -0500 Subject: [PATCH 32/41] update test files to reflect new output One surprise: old-lub-glb-object.rs, may indicate a bug --- .../infer/region_constraints/leak_check.rs | 12 ++ .../ui/anonymous-higher-ranked-lifetime.rs | 11 + .../anonymous-higher-ranked-lifetime.stderr | 196 ++++++++++++++++-- .../associated-types-eq-hr.rs | 8 +- .../associated-types-eq-hr.stderr | 95 +++++++-- .../higher-ranked-projection.bad.stderr | 15 +- .../higher-ranked-projection.good.stderr | 2 +- .../higher-ranked-projection.rs | 2 +- .../expect-fn-supply-fn.rs | 6 +- .../expect-fn-supply-fn.stderr | 57 +++-- .../coherence/coherence-subtyping.old.stderr | 14 -- .../coherence/coherence-subtyping.re.stderr | 14 -- src/test/ui/coherence/coherence-subtyping.rs | 6 +- ...pe.bound_a_b_ret_a_vs_bound_a_ret_a.stderr | 2 +- .../hr-subtype.bound_a_b_vs_bound_a.stderr | 22 +- .../hr-subtype.bound_a_vs_bound_a.stderr | 6 +- .../hr-subtype.bound_a_vs_bound_b.stderr | 6 +- .../hr-subtype.bound_a_vs_free_x.stderr | 2 +- ...-subtype.bound_co_a_b_vs_bound_co_a.stderr | 22 +- ...ubtype.bound_co_a_co_b_ret_contra_a.stderr | 22 +- ...hr-subtype.bound_co_a_vs_bound_co_b.stderr | 6 +- ...pe.bound_contra_a_contra_b_ret_co_a.stderr | 22 +- ...ubtype.bound_inv_a_b_vs_bound_inv_a.stderr | 2 +- ...-subtype.bound_inv_a_vs_bound_inv_b.stderr | 6 +- .../hr-subtype.free_x_vs_free_x.stderr | 6 +- src/test/ui/hr-subtype/hr-subtype.rs | 8 +- src/test/ui/hrtb/hrtb-conflate-regions.stderr | 18 +- src/test/ui/hrtb/hrtb-exists-forall-fn.stderr | 2 +- .../hrtb-exists-forall-trait-contravariant.rs | 7 +- ...b-exists-forall-trait-contravariant.stderr | 21 ++ .../hrtb-exists-forall-trait-covariant.rs | 7 +- .../hrtb-exists-forall-trait-covariant.stderr | 21 ++ .../hrtb-exists-forall-trait-invariant.rs | 2 +- .../hrtb-exists-forall-trait-invariant.stderr | 21 +- ...igher-ranker-supertraits-transitive.stderr | 17 +- .../ui/hrtb/hrtb-higher-ranker-supertraits.rs | 4 +- .../hrtb-higher-ranker-supertraits.stderr | 41 +++- src/test/ui/hrtb/hrtb-just-for-static.stderr | 35 +++- src/test/ui/hrtb/issue-46989.stderr | 17 ++ src/test/ui/hrtb/issue-58451.rs | 2 +- src/test/ui/hrtb/issue-58451.stderr | 16 ++ src/test/ui/issues/issue-40000.stderr | 6 +- src/test/ui/lub-glb/old-lub-glb-hr.rs | 5 +- src/test/ui/lub-glb/old-lub-glb-hr.stderr | 17 ++ src/test/ui/lub-glb/old-lub-glb-object.rs | 6 +- src/test/ui/lub-glb/old-lub-glb-object.stderr | 16 -- .../closure-arg-type-mismatch.rs | 4 +- .../closure-arg-type-mismatch.stderr | 33 +-- .../ui/mismatched_types/closure-mismatch.rs | 3 +- .../mismatched_types/closure-mismatch.stderr | 34 ++- src/test/ui/mismatched_types/issue-36053-2.rs | 1 + .../ui/mismatched_types/issue-36053-2.stderr | 10 +- ...regions-fn-subtyping-return-static-fail.rs | 4 +- ...ons-fn-subtyping-return-static-fail.stderr | 17 +- ...lifetime-bounds-on-fns-where-clause.stderr | 4 +- ...lifetime-bounds-on-fns-where-clause.stderr | 4 +- .../regions-fn-subtyping-return-static.rs | 4 +- .../regions-fn-subtyping-return-static.stderr | 12 ++ .../regions-lifetime-bounds-on-fns.stderr | 4 +- .../unboxed-closures-unsafe-extern-fn.rs | 2 + .../unboxed-closures-unsafe-extern-fn.stderr | 34 ++- .../unboxed-closures-wrong-abi.rs | 2 + .../unboxed-closures-wrong-abi.stderr | 34 ++- ...boxed-closures-wrong-arg-type-extern-fn.rs | 2 + ...d-closures-wrong-arg-type-extern-fn.stderr | 34 ++- src/test/ui/where-clauses/where-for-self-2.rs | 2 +- .../ui/where-clauses/where-for-self-2.stderr | 19 +- 67 files changed, 826 insertions(+), 288 deletions(-) delete mode 100644 src/test/ui/coherence/coherence-subtyping.old.stderr delete mode 100644 src/test/ui/coherence/coherence-subtyping.re.stderr create mode 100644 src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr create mode 100644 src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr create mode 100644 src/test/ui/hrtb/issue-46989.stderr create mode 100644 src/test/ui/hrtb/issue-58451.stderr create mode 100644 src/test/ui/lub-glb/old-lub-glb-hr.stderr delete mode 100644 src/test/ui/lub-glb/old-lub-glb-object.stderr create mode 100644 src/test/ui/regions/regions-fn-subtyping-return-static.stderr diff --git a/src/librustc/infer/region_constraints/leak_check.rs b/src/librustc/infer/region_constraints/leak_check.rs index 4056b9e2d83bc..8085258610d84 100644 --- a/src/librustc/infer/region_constraints/leak_check.rs +++ b/src/librustc/infer/region_constraints/leak_check.rs @@ -31,6 +31,18 @@ impl<'tcx> RegionConstraintCollector<'tcx> { assert!(self.in_snapshot()); + // If the user gave `-Zno-leak-check`, then skip the leak + // check completely. This is wildly unsound and also not + // unlikely to cause an ICE or two. It is intended for use + // only during a transition period, in which the MIR typeck + // uses the "universe-style" check, and the rest of typeck + // uses the more conservative leak check. Since the leak + // check is more conservative, we can't test the + // universe-style check without disabling it. + if tcx.sess.opts.debugging_opts.no_leak_check { + return Ok(()); + } + // Go through each placeholder that we created. for (_, &placeholder_region) in placeholder_map { // Find the universe this placeholder inhabits. diff --git a/src/test/ui/anonymous-higher-ranked-lifetime.rs b/src/test/ui/anonymous-higher-ranked-lifetime.rs index 55b1667da50b1..2e2a124db9a5d 100644 --- a/src/test/ui/anonymous-higher-ranked-lifetime.rs +++ b/src/test/ui/anonymous-higher-ranked-lifetime.rs @@ -1,15 +1,26 @@ fn main() { f1(|_: (), _: ()| {}); //~ ERROR type mismatch + //~^ ERROR type mismatch f2(|_: (), _: ()| {}); //~ ERROR type mismatch + //~^ ERROR type mismatch f3(|_: (), _: ()| {}); //~ ERROR type mismatch + //~^ ERROR type mismatch f4(|_: (), _: ()| {}); //~ ERROR type mismatch + //~^ ERROR type mismatch f5(|_: (), _: ()| {}); //~ ERROR type mismatch + //~^ ERROR type mismatch g1(|_: (), _: ()| {}); //~ ERROR type mismatch + //~^ ERROR type mismatch g2(|_: (), _: ()| {}); //~ ERROR type mismatch + //~^ ERROR type mismatch g3(|_: (), _: ()| {}); //~ ERROR type mismatch + //~^ ERROR type mismatch g4(|_: (), _: ()| {}); //~ ERROR type mismatch + //~^ ERROR type mismatch h1(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch + //~^ ERROR type mismatch h2(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch + //~^ ERROR type mismatch } // Basic diff --git a/src/test/ui/anonymous-higher-ranked-lifetime.stderr b/src/test/ui/anonymous-higher-ranked-lifetime.stderr index d2c722e32b210..378f352cb9228 100644 --- a/src/test/ui/anonymous-higher-ranked-lifetime.stderr +++ b/src/test/ui/anonymous-higher-ranked-lifetime.stderr @@ -7,13 +7,27 @@ LL | f1(|_: (), _: ()| {}); //~ ERROR type mismatch | expected signature of `for<'r, 's> fn(&'r (), &'s ()) -> _` | note: required by `f1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:16:1 + --> $DIR/anonymous-higher-ranked-lifetime.rs:27:1 | LL | fn f1(_: F) where F: Fn(&(), &()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:3:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:2:5 + | +LL | f1(|_: (), _: ()| {}); //~ ERROR type mismatch + | ^^ -------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `fn(&(), &()) -> _` + | +note: required by `f1` + --> $DIR/anonymous-higher-ranked-lifetime.rs:27:1 + | +LL | fn f1(_: F) where F: Fn(&(), &()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5 | LL | f2(|_: (), _: ()| {}); //~ ERROR type mismatch | ^^ -------------- found signature of `fn((), ()) -> _` @@ -21,7 +35,7 @@ LL | f2(|_: (), _: ()| {}); //~ ERROR type mismatch | expected signature of `for<'a, 'r> fn(&'a (), &'r ()) -> _` | note: required by `f2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:17:1 + --> $DIR/anonymous-higher-ranked-lifetime.rs:28:1 | LL | fn f2(_: F) where F: for<'a> Fn(&'a (), &()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -29,19 +43,47 @@ LL | fn f2(_: F) where F: for<'a> Fn(&'a (), &()) {} error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5 | +LL | f2(|_: (), _: ()| {}); //~ ERROR type mismatch + | ^^ -------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `fn(&'a (), &()) -> _` + | +note: required by `f2` + --> $DIR/anonymous-higher-ranked-lifetime.rs:28:1 + | +LL | fn f2(_: F) where F: for<'a> Fn(&'a (), &()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5 + | LL | f3(|_: (), _: ()| {}); //~ ERROR type mismatch | ^^ -------------- found signature of `fn((), ()) -> _` | | | expected signature of `for<'r> fn(&(), &'r ()) -> _` | note: required by `f3` - --> $DIR/anonymous-higher-ranked-lifetime.rs:18:1 + --> $DIR/anonymous-higher-ranked-lifetime.rs:29:1 | LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:5:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5 + | +LL | f3(|_: (), _: ()| {}); //~ ERROR type mismatch + | ^^ -------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `fn(&(), &()) -> _` + | +note: required by `f3` + --> $DIR/anonymous-higher-ranked-lifetime.rs:29:1 + | +LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5 | LL | f4(|_: (), _: ()| {}); //~ ERROR type mismatch | ^^ -------------- found signature of `fn((), ()) -> _` @@ -49,13 +91,27 @@ LL | f4(|_: (), _: ()| {}); //~ ERROR type mismatch | expected signature of `for<'s, 'r> fn(&'s (), &'r ()) -> _` | note: required by `f4` - --> $DIR/anonymous-higher-ranked-lifetime.rs:19:1 + --> $DIR/anonymous-higher-ranked-lifetime.rs:30:1 | LL | fn f4(_: F) where F: for<'r> Fn(&(), &'r ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5 + | +LL | f4(|_: (), _: ()| {}); //~ ERROR type mismatch + | ^^ -------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `fn(&(), &'r ()) -> _` + | +note: required by `f4` + --> $DIR/anonymous-higher-ranked-lifetime.rs:30:1 + | +LL | fn f4(_: F) where F: for<'r> Fn(&(), &'r ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5 | LL | f5(|_: (), _: ()| {}); //~ ERROR type mismatch | ^^ -------------- found signature of `fn((), ()) -> _` @@ -63,13 +119,27 @@ LL | f5(|_: (), _: ()| {}); //~ ERROR type mismatch | expected signature of `for<'r> fn(&'r (), &'r ()) -> _` | note: required by `f5` - --> $DIR/anonymous-higher-ranked-lifetime.rs:20:1 + --> $DIR/anonymous-higher-ranked-lifetime.rs:31:1 | LL | fn f5(_: F) where F: for<'r> Fn(&'r (), &'r ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:7:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5 + | +LL | f5(|_: (), _: ()| {}); //~ ERROR type mismatch + | ^^ -------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `fn(&'r (), &'r ()) -> _` + | +note: required by `f5` + --> $DIR/anonymous-higher-ranked-lifetime.rs:31:1 + | +LL | fn f5(_: F) where F: for<'r> Fn(&'r (), &'r ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5 | LL | g1(|_: (), _: ()| {}); //~ ERROR type mismatch | ^^ -------------- found signature of `fn((), ()) -> _` @@ -77,13 +147,27 @@ LL | g1(|_: (), _: ()| {}); //~ ERROR type mismatch | expected signature of `for<'r> fn(&'r (), std::boxed::Box<(dyn for<'s> std::ops::Fn(&'s ()) + 'static)>) -> _` | note: required by `g1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:23:1 + --> $DIR/anonymous-higher-ranked-lifetime.rs:34:1 | LL | fn g1(_: F) where F: Fn(&(), Box) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5 + | +LL | g1(|_: (), _: ()| {}); //~ ERROR type mismatch + | ^^ -------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _` + | +note: required by `g1` + --> $DIR/anonymous-higher-ranked-lifetime.rs:34:1 + | +LL | fn g1(_: F) where F: Fn(&(), Box) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:14:5 | LL | g2(|_: (), _: ()| {}); //~ ERROR type mismatch | ^^ -------------- found signature of `fn((), ()) -> _` @@ -91,13 +175,27 @@ LL | g2(|_: (), _: ()| {}); //~ ERROR type mismatch | expected signature of `for<'r> fn(&'r (), for<'s> fn(&'s ())) -> _` | note: required by `g2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:24:1 + --> $DIR/anonymous-higher-ranked-lifetime.rs:35:1 | LL | fn g2(_: F) where F: Fn(&(), fn(&())) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:9:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:14:5 + | +LL | g2(|_: (), _: ()| {}); //~ ERROR type mismatch + | ^^ -------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `fn(&(), for<'r> fn(&'r ())) -> _` + | +note: required by `g2` + --> $DIR/anonymous-higher-ranked-lifetime.rs:35:1 + | +LL | fn g2(_: F) where F: Fn(&(), fn(&())) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:16:5 | LL | g3(|_: (), _: ()| {}); //~ ERROR type mismatch | ^^ -------------- found signature of `fn((), ()) -> _` @@ -105,13 +203,27 @@ LL | g3(|_: (), _: ()| {}); //~ ERROR type mismatch | expected signature of `for<'s> fn(&'s (), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _` | note: required by `g3` - --> $DIR/anonymous-higher-ranked-lifetime.rs:25:1 + --> $DIR/anonymous-higher-ranked-lifetime.rs:36:1 | LL | fn g3(_: F) where F: for<'s> Fn(&'s (), Box) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:16:5 + | +LL | g3(|_: (), _: ()| {}); //~ ERROR type mismatch + | ^^ -------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `fn(&'s (), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _` + | +note: required by `g3` + --> $DIR/anonymous-higher-ranked-lifetime.rs:36:1 + | +LL | fn g3(_: F) where F: for<'s> Fn(&'s (), Box) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:18:5 | LL | g4(|_: (), _: ()| {}); //~ ERROR type mismatch | ^^ -------------- found signature of `fn((), ()) -> _` @@ -119,13 +231,27 @@ LL | g4(|_: (), _: ()| {}); //~ ERROR type mismatch | expected signature of `for<'s> fn(&'s (), for<'r> fn(&'r ())) -> _` | note: required by `g4` - --> $DIR/anonymous-higher-ranked-lifetime.rs:26:1 + --> $DIR/anonymous-higher-ranked-lifetime.rs:37:1 + | +LL | fn g4(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:18:5 + | +LL | g4(|_: (), _: ()| {}); //~ ERROR type mismatch + | ^^ -------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `fn(&(), for<'r> fn(&'r ())) -> _` + | +note: required by `g4` + --> $DIR/anonymous-higher-ranked-lifetime.rs:37:1 | LL | fn g4(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:11:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:20:5 | LL | h1(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch | ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _` @@ -133,13 +259,27 @@ LL | h1(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch | expected signature of `for<'r, 's> fn(&'r (), std::boxed::Box<(dyn for<'t0> std::ops::Fn(&'t0 ()) + 'static)>, &'s (), for<'t0, 't1> fn(&'t0 (), &'t1 ())) -> _` | note: required by `h1` - --> $DIR/anonymous-higher-ranked-lifetime.rs:29:1 + --> $DIR/anonymous-higher-ranked-lifetime.rs:40:1 | LL | fn h1(_: F) where F: Fn(&(), Box, &(), fn(&(), &())) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:20:5 + | +LL | h1(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch + | ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _` + | | + | expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>, &(), for<'r, 's> fn(&'r (), &'s ())) -> _` + | +note: required by `h1` + --> $DIR/anonymous-higher-ranked-lifetime.rs:40:1 + | +LL | fn h1(_: F) where F: Fn(&(), Box, &(), fn(&(), &())) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:22:5 | LL | h2(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch | ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _` @@ -147,11 +287,25 @@ LL | h2(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch | expected signature of `for<'r, 't0> fn(&'r (), std::boxed::Box<(dyn for<'s> std::ops::Fn(&'s ()) + 'static)>, &'t0 (), for<'s, 't1> fn(&'s (), &'t1 ())) -> _` | note: required by `h2` - --> $DIR/anonymous-higher-ranked-lifetime.rs:30:1 + --> $DIR/anonymous-higher-ranked-lifetime.rs:41:1 + | +LL | fn h2(_: F) where F: for<'t0> Fn(&(), Box, &'t0 (), fn(&(), &())) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:22:5 + | +LL | h2(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch + | ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _` + | | + | expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>, &'t0 (), for<'r, 's> fn(&'r (), &'s ())) -> _` + | +note: required by `h2` + --> $DIR/anonymous-higher-ranked-lifetime.rs:41:1 | LL | fn h2(_: F) where F: for<'t0> Fn(&(), Box, &'t0 (), fn(&(), &())) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 11 previous errors +error: aborting due to 22 previous errors For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/associated-types/associated-types-eq-hr.rs b/src/test/ui/associated-types/associated-types-eq-hr.rs index 20fa1e7a48db1..e6afa3f71c2f0 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.rs +++ b/src/test/ui/associated-types/associated-types-eq-hr.rs @@ -89,12 +89,14 @@ pub fn call_bar() { pub fn call_tuple_one() { tuple_one::(); - //~^ ERROR not general enough + //~^ ERROR not satisfied + //~| ERROR type mismatch } pub fn call_tuple_two() { tuple_two::(); - //~^ ERROR not general enough + //~^ ERROR not satisfied + //~| ERROR type mismatch } pub fn call_tuple_three() { @@ -103,7 +105,7 @@ pub fn call_tuple_three() { pub fn call_tuple_four() { tuple_four::(); - //~^ ERROR not general enough + //~^ ERROR not satisfied } fn main() { } diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index d3eaa894b5043..3721b69898876 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -34,36 +34,93 @@ LL | | // ok for UintStruct, but not IntStruct LL | | } | |_^ -error: implementation of `TheTrait` is not general enough +error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied --> $DIR/associated-types-eq-hr.rs:91:5 | LL | tuple_one::(); - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` | - = note: Due to a where-clause on `tuple_one`, - = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1` - = note: but `Tuple` only implements `TheTrait<(&'2 isize, &'2 isize)>` for some lifetime `'2` + = help: the following implementations were found: + > +note: required by `tuple_one` + --> $DIR/associated-types-eq-hr.rs:56:1 + | +LL | / fn tuple_one() +LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> +LL | | { +LL | | // not ok for tuple, two lifetimes and we pick first +LL | | } + | |_^ -error: implementation of `TheTrait` is not general enough - --> $DIR/associated-types-eq-hr.rs:96:5 +error[E0271]: type mismatch resolving `for<'x, 'y> >::A == &'x isize` + --> $DIR/associated-types-eq-hr.rs:91:5 + | +LL | tuple_one::(); + | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime + | +note: required by `tuple_one` + --> $DIR/associated-types-eq-hr.rs:56:1 + | +LL | / fn tuple_one() +LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> +LL | | { +LL | | // not ok for tuple, two lifetimes and we pick first +LL | | } + | |_^ + +error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied + --> $DIR/associated-types-eq-hr.rs:97:5 | LL | tuple_two::(); - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` + | + = help: the following implementations were found: + > +note: required by `tuple_two` + --> $DIR/associated-types-eq-hr.rs:62:1 | - = note: Due to a where-clause on `tuple_two`, - = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1` - = note: but `Tuple` only implements `TheTrait<(&'2 isize, &'2 isize)>` for some lifetime `'2` +LL | / fn tuple_two() +LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> +LL | | { +LL | | // not ok for tuple, two lifetimes and we pick second +LL | | } + | |_^ + +error[E0271]: type mismatch resolving `for<'x, 'y> >::A == &'y isize` + --> $DIR/associated-types-eq-hr.rs:97:5 + | +LL | tuple_two::(); + | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime + | +note: required by `tuple_two` + --> $DIR/associated-types-eq-hr.rs:62:1 + | +LL | / fn tuple_two() +LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> +LL | | { +LL | | // not ok for tuple, two lifetimes and we pick second +LL | | } + | |_^ -error: implementation of `TheTrait` is not general enough - --> $DIR/associated-types-eq-hr.rs:105:5 +error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied + --> $DIR/associated-types-eq-hr.rs:107:5 | LL | tuple_four::(); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` + | + = help: the following implementations were found: + > +note: required by `tuple_four` + --> $DIR/associated-types-eq-hr.rs:74:1 | - = note: Due to a where-clause on `tuple_four`, - = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1` - = note: but `Tuple` only implements `TheTrait<(&'2 isize, &'2 isize)>` for some lifetime `'2` +LL | / fn tuple_four() +LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize)> +LL | | { +LL | | // not ok for tuple, two lifetimes, and lifetime matching is invariant +LL | | } + | |_^ -error: aborting due to 5 previous errors +error: aborting due to 7 previous errors -For more information about this error, try `rustc --explain E0271`. +Some errors occurred: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr index 811c9a8f5e12b..cc69e849fe144 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr @@ -1,12 +1,17 @@ -error[E0308]: mismatched types +error[E0271]: type mismatch resolving `for<'a> <&'a _ as Mirror>::Image == _` --> $DIR/higher-ranked-projection.rs:25:5 | LL | foo(()); - | ^^^ one type is more general than the other + | ^^^ expected bound lifetime parameter 'a, found concrete lifetime | - = note: expected type `&'a ()` - found type `&()` +note: required by `foo` + --> $DIR/higher-ranked-projection.rs:14:1 + | +LL | / fn foo(_t: T) +LL | | where for<'a> &'a T: Mirror +LL | | {} + | |__^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/associated-types/higher-ranked-projection.good.stderr b/src/test/ui/associated-types/higher-ranked-projection.good.stderr index db15ec51d87c6..165e5213e0d34 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.good.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.good.stderr @@ -3,7 +3,7 @@ error: compilation successful | LL | / fn main() { //[good]~ ERROR compilation successful LL | | foo(()); -LL | | //[bad]~^ ERROR E0308 +LL | | //[bad]~^ ERROR type mismatch LL | | } | |_^ diff --git a/src/test/ui/associated-types/higher-ranked-projection.rs b/src/test/ui/associated-types/higher-ranked-projection.rs index 5b380c982f041..a2ea6d8f206b6 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.rs +++ b/src/test/ui/associated-types/higher-ranked-projection.rs @@ -23,5 +23,5 @@ fn foo(_t: T) #[rustc_error] fn main() { //[good]~ ERROR compilation successful foo(()); - //[bad]~^ ERROR E0308 + //[bad]~^ ERROR type mismatch } diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs index 6977fd47a2e85..a4e43da91baf8 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs @@ -28,14 +28,14 @@ fn expect_free_supply_bound() { // Here, we are given a function whose region is bound at closure level, // but we expect one bound in the argument. Error results. with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); - //~^ ERROR mismatched types + //~^ ERROR type mismatch } fn expect_bound_supply_free_from_fn<'x>(x: &'x u32) { // Here, we are given a `fn(&u32)` but we expect a `fn(&'x // u32)`. In principle, this could be ok, but we demand equality. with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); - //~^ ERROR mismatched types + //~^ ERROR type mismatch } fn expect_bound_supply_free_from_closure() { @@ -44,7 +44,7 @@ fn expect_bound_supply_free_from_closure() { // the argument level. type Foo<'a> = fn(&'a u32); with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { - //~^ ERROR mismatched types + //~^ ERROR type mismatch }); } diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr index b1cfd6cef1022..ab35aeff697b7 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr @@ -36,33 +36,58 @@ note: ...does not necessarily outlive the anonymous lifetime #2 defined on the b LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | ^^^^^^^^^^^^^^^^^^^^^^ -error[E0308]: mismatched types - --> $DIR/expect-fn-supply-fn.rs:30:52 +error[E0631]: type mismatch in closure arguments + --> $DIR/expect-fn-supply-fn.rs:30:5 | LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); - | ^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _` + | | + | expected signature of `fn(fn(&'a u32), &i32) -> _` | - = note: expected type `fn(&u32)` - found type `for<'r> fn(&'r u32)` +note: required by `with_closure_expecting_fn_with_free_region` + --> $DIR/expect-fn-supply-fn.rs:1:1 + | +LL | / fn with_closure_expecting_fn_with_free_region(_: F) +LL | | where F: for<'a> FnOnce(fn(&'a u32), &i32) +LL | | { +LL | | } + | |_^ -error[E0308]: mismatched types - --> $DIR/expect-fn-supply-fn.rs:37:53 +error[E0631]: type mismatch in closure arguments + --> $DIR/expect-fn-supply-fn.rs:37:5 | LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); - | ^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _` + | | + | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` | - = note: expected type `for<'r> fn(&'r u32)` - found type `fn(&'x u32)` +note: required by `with_closure_expecting_fn_with_bound_region` + --> $DIR/expect-fn-supply-fn.rs:6:1 + | +LL | / fn with_closure_expecting_fn_with_bound_region(_: F) +LL | | where F: FnOnce(fn(&u32), &i32) +LL | | { +LL | | } + | |_^ -error[E0308]: mismatched types - --> $DIR/expect-fn-supply-fn.rs:46:53 +error[E0631]: type mismatch in closure arguments + --> $DIR/expect-fn-supply-fn.rs:46:5 | LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { - | ^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _` + | | + | expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _` + | +note: required by `with_closure_expecting_fn_with_bound_region` + --> $DIR/expect-fn-supply-fn.rs:6:1 | - = note: expected type `for<'r> fn(&'r u32)` - found type `fn(&u32)` +LL | / fn with_closure_expecting_fn_with_bound_region(_: F) +LL | | where F: FnOnce(fn(&u32), &i32) +LL | | { +LL | | } + | |_^ error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors occurred: E0308, E0631. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/coherence/coherence-subtyping.old.stderr b/src/test/ui/coherence/coherence-subtyping.old.stderr deleted file mode 100644 index db9f9f7665374..0000000000000 --- a/src/test/ui/coherence/coherence-subtyping.old.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0119]: conflicting implementations of trait `TheTrait` for type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`: - --> $DIR/coherence-subtyping.rs:15:1 - | -LL | impl TheTrait for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { - | --------------------------------------------------------- first implementation here -... -LL | impl TheTrait for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` - | - = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/coherence/coherence-subtyping.re.stderr b/src/test/ui/coherence/coherence-subtyping.re.stderr deleted file mode 100644 index db9f9f7665374..0000000000000 --- a/src/test/ui/coherence/coherence-subtyping.re.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0119]: conflicting implementations of trait `TheTrait` for type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`: - --> $DIR/coherence-subtyping.rs:15:1 - | -LL | impl TheTrait for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { - | --------------------------------------------------------- first implementation here -... -LL | impl TheTrait for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` - | - = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/coherence/coherence-subtyping.rs b/src/test/ui/coherence/coherence-subtyping.rs index f27e14eab63da..e74067578069e 100644 --- a/src/test/ui/coherence/coherence-subtyping.rs +++ b/src/test/ui/coherence/coherence-subtyping.rs @@ -1,7 +1,11 @@ // Test that two distinct impls which match subtypes of one another // yield coherence errors (or not) depending on the variance. +// +// Note: This scenario is currently accepted, but as part of the +// universe transition (#56105) may eventually become an error. // revisions: old re +// compile-pass #![cfg_attr(re, feature(re_rebalance_coherence))] @@ -13,8 +17,6 @@ impl TheTrait for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { } impl TheTrait for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { - //[old]~^ ERROR - //[re]~^^ ERROR } fn main() { } diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr index bdfabdabbebb7..8e2b0b8c60045 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/hr-subtype.rs:39:26 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a ... LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32, LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) } diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr index 25b74d855bb48..dbb5018139076 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr @@ -1,14 +1,16 @@ -error: compilation successful - --> $DIR/hr-subtype.rs:96:1 +error[E0308]: mismatched types + --> $DIR/hr-subtype.rs:39:26 | -LL | / fn main() { -LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful -LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful -LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -... | -LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful -LL | | } - | |_^ +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a +... +LL | / check! { bound_a_b_vs_bound_a: (for<'a,'b> fn(&'a u32, &'b u32), +LL | | for<'a> fn(&'a u32, &'a u32)) } + | |__________________________________________________________________- in this macro invocation + | + = note: expected type `std::option::Option fn(&'a u32, &'b u32)>` + found type `std::option::Option fn(&'a u32, &'a u32)>` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr index 25b74d855bb48..5fcb63e17bf31 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr @@ -1,12 +1,12 @@ error: compilation successful - --> $DIR/hr-subtype.rs:96:1 + --> $DIR/hr-subtype.rs:100:1 | LL | / fn main() { LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -... | -LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful +LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful +LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr index 25b74d855bb48..5fcb63e17bf31 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr @@ -1,12 +1,12 @@ error: compilation successful - --> $DIR/hr-subtype.rs:96:1 + --> $DIR/hr-subtype.rs:100:1 | LL | / fn main() { LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -... | -LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful +LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful +LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr index 74b8c89b6e86f..db9892b48a6f7 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/hr-subtype.rs:39:26 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a ... LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32), LL | | fn(&'x u32)) } diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr index 25b74d855bb48..e9fb73411bd39 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr @@ -1,14 +1,16 @@ -error: compilation successful - --> $DIR/hr-subtype.rs:96:1 +error[E0308]: mismatched types + --> $DIR/hr-subtype.rs:39:26 | -LL | / fn main() { -LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful -LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful -LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -... | -LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful -LL | | } - | |_^ +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a +... +LL | / check! { bound_co_a_b_vs_bound_co_a: (for<'a,'b> fn(Co<'a>, Co<'b>), +LL | | for<'a> fn(Co<'a>, Co<'a>)) } + | |______________________________________________________________________- in this macro invocation + | + = note: expected type `std::option::Option fn(Co<'a>, Co<'b>)>` + found type `std::option::Option fn(Co<'a>, Co<'a>)>` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr index 25b74d855bb48..d0e80faa68e8b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr @@ -1,14 +1,16 @@ -error: compilation successful - --> $DIR/hr-subtype.rs:96:1 +error[E0308]: mismatched types + --> $DIR/hr-subtype.rs:39:26 | -LL | / fn main() { -LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful -LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful -LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -... | -LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful -LL | | } - | |_^ +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a +... +LL | / check! { bound_co_a_co_b_ret_contra_a: (for<'a,'b> fn(Co<'a>, Co<'b>) -> Contra<'a>, +LL | | for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>) } + | |______________________________________________________________________________________- in this macro invocation + | + = note: expected type `std::option::Option fn(Co<'a>, Co<'b>) -> Contra<'a>>` + found type `std::option::Option fn(Co<'a>, Co<'a>) -> Contra<'a>>` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr index 25b74d855bb48..5fcb63e17bf31 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr @@ -1,12 +1,12 @@ error: compilation successful - --> $DIR/hr-subtype.rs:96:1 + --> $DIR/hr-subtype.rs:100:1 | LL | / fn main() { LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -... | -LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful +LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful +LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr index 25b74d855bb48..3605ecf4f8667 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr @@ -1,14 +1,16 @@ -error: compilation successful - --> $DIR/hr-subtype.rs:96:1 +error[E0308]: mismatched types + --> $DIR/hr-subtype.rs:39:26 | -LL | / fn main() { -LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful -LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful -LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -... | -LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful -LL | | } - | |_^ +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a +... +LL | / check! { bound_contra_a_contra_b_ret_co_a: (for<'a,'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>, +LL | | for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>) } + | |______________________________________________________________________________________________- in this macro invocation + | + = note: expected type `std::option::Option fn(Contra<'a>, Contra<'b>) -> Co<'a>>` + found type `std::option::Option fn(Contra<'a>, Contra<'a>) -> Co<'a>>` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr index 8168941e2777c..fae6e9b5c89ca 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/hr-subtype.rs:39:26 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a ... LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>), LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr index 25b74d855bb48..5fcb63e17bf31 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr @@ -1,12 +1,12 @@ error: compilation successful - --> $DIR/hr-subtype.rs:96:1 + --> $DIR/hr-subtype.rs:100:1 | LL | / fn main() { LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -... | -LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful +LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful +LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr index 25b74d855bb48..5fcb63e17bf31 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr @@ -1,12 +1,12 @@ error: compilation successful - --> $DIR/hr-subtype.rs:96:1 + --> $DIR/hr-subtype.rs:100:1 | LL | / fn main() { LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -... | -LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful +LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful +LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.rs b/src/test/ui/hr-subtype/hr-subtype.rs index ad4f39f840528..2f7c1e6fd8c0d 100644 --- a/src/test/ui/hr-subtype/hr-subtype.rs +++ b/src/test/ui/hr-subtype/hr-subtype.rs @@ -42,6 +42,10 @@ macro_rules! check { //[bound_inv_a_b_vs_bound_inv_a]~^^^ ERROR //[bound_a_b_ret_a_vs_bound_a_ret_a]~^^^^ ERROR //[free_inv_x_vs_free_inv_y]~^^^^^ ERROR + //[bound_a_b_vs_bound_a]~^^^^^^ ERROR mismatched types + //[bound_co_a_co_b_ret_contra_a]~^^^^^^^ ERROR + //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^ ERROR + //[bound_co_a_b_vs_bound_co_a]~^^^^^^^^^ ERROR } } } @@ -99,8 +103,4 @@ fn main() { //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful //[free_x_vs_free_x]~^^^^^ ERROR compilation successful -//[bound_a_b_vs_bound_a]~^^^^^^ ERROR compilation successful -//[bound_co_a_co_b_ret_contra_a]~^^^^^^^ ERROR compilation successful -//[bound_co_a_b_vs_bound_co_a]~^^^^^^^^ ERROR compilation successful -//[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful } diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.stderr index 2ee398e3dd3b2..50e1af8f14231 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.stderr +++ b/src/test/ui/hrtb/hrtb-conflate-regions.stderr @@ -1,12 +1,20 @@ -error: implementation of `Foo` is not general enough +error[E0277]: the trait bound `for<'a, 'b> SomeStruct: Foo<(&'a isize, &'b isize)>` is not satisfied --> $DIR/hrtb-conflate-regions.rs:28:10 | LL | fn b() { want_foo2::(); } //~ ERROR - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a, 'b> Foo<(&'a isize, &'b isize)>` is not implemented for `SomeStruct` | - = note: Due to a where-clause on `want_foo2`, - = note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1` - = note: but `SomeStruct` only implements `Foo<(&'2 isize, &'2 isize)>` for some lifetime `'2` + = help: the following implementations were found: + > +note: required by `want_foo2` + --> $DIR/hrtb-conflate-regions.rs:8:1 + | +LL | / fn want_foo2() +LL | | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> +LL | | { +LL | | } + | |_^ error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr index 6301ed45ac277..8e8892552b701 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/hrtb-exists-forall-fn.rs:17:34 | LL | let _: for<'b> fn(&'b u32) = foo(); //~ ERROR mismatched types - | ^^^^^ one type is more general than the other + | ^^^^^ expected concrete lifetime, found bound lifetime parameter 'b | = note: expected type `for<'b> fn(&'b u32)` found type `fn(&u32)` diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs index 8801760056ecb..4c1d4d28a09b0 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs @@ -1,9 +1,7 @@ -// Test a `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile! +// Test a case where variance and higher-ranked types interact in surprising ways. // // In particular, we test this pattern in trait solving, where it is not connected // to any part of the source code. -// -// compile-pass trait Trait {} @@ -30,6 +28,9 @@ fn main() { // - `?a: ?b` -- solveable if `?b` is also inferred to `'empty` // - So the subtyping check succeeds, somewhat surprisingly. // This is because we can use `'empty`. + // + // NB. *However*, the reinstated leak-check gives an error here. foo::<()>(); + //~^ ERROR not satisfied } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr new file mode 100644 index 0000000000000..7f2ca037f0f49 --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `(): Trait fn(&'b u32)>` is not satisfied + --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5 + | +LL | foo::<()>(); + | ^^^^^^^^^ the trait `Trait fn(&'b u32)>` is not implemented for `()` + | + = help: the following implementations were found: + <() as Trait> +note: required by `foo` + --> $DIR/hrtb-exists-forall-trait-contravariant.rs:8:1 + | +LL | / fn foo() +LL | | where +LL | | T: Trait fn(&'b u32)>, +LL | | { +LL | | } + | |_^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs index da1bb7cd5fd0b..95b57d6c5bb5e 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs @@ -1,9 +1,7 @@ -// Test a `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile! +// Test a case where variance and higher-ranked types interact in surprising ways. // // In particular, we test this pattern in trait solving, where it is not connected // to any part of the source code. -// -// compile-pass trait Trait {} @@ -32,6 +30,9 @@ fn main() { // - `?b: ?a` -- solveable if `?b` is inferred to `'static` // - So the subtyping check succeeds, somewhat surprisingly. // This is because we can use `'static`. + // + // NB. *However*, the reinstated leak-check gives an error here. foo::<()>(); + //~^ ERROR not satisfied } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr new file mode 100644 index 0000000000000..cd5982e7588a7 --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `(): Trait fn(fn(&'b u32))>` is not satisfied + --> $DIR/hrtb-exists-forall-trait-covariant.rs:36:5 + | +LL | foo::<()>(); + | ^^^^^^^^^ the trait `Trait fn(fn(&'b u32))>` is not implemented for `()` + | + = help: the following implementations were found: + <() as Trait> +note: required by `foo` + --> $DIR/hrtb-exists-forall-trait-covariant.rs:8:1 + | +LL | / fn foo() +LL | | where +LL | | T: Trait fn(fn(&'b u32))>, +LL | | { +LL | | } + | |_^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs index da3f8ad1b8957..827a68beee8bd 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs @@ -25,5 +25,5 @@ fn main() { // yielding `fn(&!b u32)`, in a fresh universe U1 // - So we get `?a = !b` but the universe U0 assigned to `?a` cannot name `!b`. - foo::<()>(); //~ ERROR not general enough + foo::<()>(); //~ ERROR not satisfied } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr index 6a61181e2407c..f56b81759fede 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr @@ -1,12 +1,21 @@ -error: implementation of `Trait` is not general enough +error[E0277]: the trait bound `(): Trait fn(std::cell::Cell<&'b u32>)>` is not satisfied --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5 | -LL | foo::<()>(); //~ ERROR not general enough - | ^^^^^^^^^ +LL | foo::<()>(); //~ ERROR not satisfied + | ^^^^^^^^^ the trait `Trait fn(std::cell::Cell<&'b u32>)>` is not implemented for `()` | - = note: Due to a where-clause on `foo`, - = note: `()` must implement `Trait fn(std::cell::Cell<&'b u32>)>` - = note: but `()` only implements `Trait)>` for some lifetime `'0` + = help: the following implementations were found: + <() as Trait)>> +note: required by `foo` + --> $DIR/hrtb-exists-forall-trait-invariant.rs:10:1 + | +LL | / fn foo() +LL | | where +LL | | T: Trait fn(Cell<&'b u32>)>, +LL | | { +LL | | } + | |_^ error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr index 0d7b5cbf82348..77c1789852e52 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr @@ -1,12 +1,19 @@ -error[E0308]: mismatched types +error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:5 | LL | want_bar_for_any_ccx(b); //~ ERROR - | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` | - = note: expected type `for<'ccx> Bar<'ccx>` - found type `Bar<'static>` + = help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound +note: required by `want_bar_for_any_ccx` + --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:31:1 + | +LL | / fn want_bar_for_any_ccx(b: &B) +LL | | where B : for<'ccx> Bar<'ccx> +LL | | { +LL | | } + | |_^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs index 3d2d403462d8b..48ebe5017aa62 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs @@ -15,7 +15,7 @@ fn want_foo_for_some_tcx<'x,F>(f: &'x F) where F : Foo<'x> { want_foo_for_some_tcx(f); - want_foo_for_any_tcx(f); //~ ERROR E0308 + want_foo_for_any_tcx(f); //~ ERROR not satisfied } fn want_foo_for_any_tcx(f: &F) @@ -32,7 +32,7 @@ fn want_bar_for_some_ccx<'x,B>(b: &B) want_foo_for_any_tcx(b); want_bar_for_some_ccx(b); - want_bar_for_any_ccx(b); //~ ERROR E0308 + want_bar_for_any_ccx(b); //~ ERROR not satisfied } fn want_bar_for_any_ccx(b: &B) diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr index 31dbeec2a551b..5914cb3eaa494 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr @@ -1,21 +1,40 @@ -error[E0308]: mismatched types +error[E0277]: the trait bound `for<'tcx> F: Foo<'tcx>` is not satisfied --> $DIR/hrtb-higher-ranker-supertraits.rs:18:5 | -LL | want_foo_for_any_tcx(f); //~ ERROR E0308 - | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other +LL | want_foo_for_any_tcx(f); //~ ERROR not satisfied + | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F` | - = note: expected type `for<'tcx> Foo<'tcx>` - found type `Foo<'x>` + = help: consider adding a `where for<'tcx> F: Foo<'tcx>` bound +note: required by `want_foo_for_any_tcx` + --> $DIR/hrtb-higher-ranker-supertraits.rs:21:1 + | +LL | / fn want_foo_for_any_tcx(f: &F) +LL | | where F : for<'tcx> Foo<'tcx> +LL | | { +LL | | want_foo_for_some_tcx(f); +LL | | want_foo_for_any_tcx(f); +LL | | } + | |_^ -error[E0308]: mismatched types +error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied --> $DIR/hrtb-higher-ranker-supertraits.rs:35:5 | -LL | want_bar_for_any_ccx(b); //~ ERROR E0308 - | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other +LL | want_bar_for_any_ccx(b); //~ ERROR not satisfied + | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` + | + = help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound +note: required by `want_bar_for_any_ccx` + --> $DIR/hrtb-higher-ranker-supertraits.rs:38:1 | - = note: expected type `for<'ccx> Bar<'ccx>` - found type `Bar<'x>` +LL | / fn want_bar_for_any_ccx(b: &B) +LL | | where B : for<'ccx> Bar<'ccx> +LL | | { +LL | | want_foo_for_some_tcx(b); +... | +LL | | want_bar_for_any_ccx(b); +LL | | } + | |_^ error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr index 094c449802415..fe2bc1f222504 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.stderr +++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr @@ -1,22 +1,37 @@ -error: implementation of `Foo` is not general enough +error[E0277]: the trait bound `for<'a> StaticInt: Foo<&'a isize>` is not satisfied --> $DIR/hrtb-just-for-static.rs:24:5 | LL | want_hrtb::() //~ ERROR - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `StaticInt` | - = note: Due to a where-clause on `want_hrtb`, - = note: `StaticInt` must implement `Foo<&'0 isize>` for any lifetime `'0` - = note: but `StaticInt` only implements `Foo<&'1 isize>` for some lifetime `'1` + = help: the following implementations were found: + > +note: required by `want_hrtb` + --> $DIR/hrtb-just-for-static.rs:8:1 + | +LL | / fn want_hrtb() +LL | | where T : for<'a> Foo<&'a isize> +LL | | { +LL | | } + | |_^ -error: implementation of `Foo` is not general enough +error[E0277]: the trait bound `for<'a> &'a u32: Foo<&'a isize>` is not satisfied --> $DIR/hrtb-just-for-static.rs:30:5 | LL | want_hrtb::<&'a u32>() //~ ERROR - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `&'a u32` + | + = help: the following implementations were found: + <&'a u32 as Foo<&'a isize>> +note: required by `want_hrtb` + --> $DIR/hrtb-just-for-static.rs:8:1 | - = note: Due to a where-clause on `want_hrtb`, - = note: `&'a u32` must implement `Foo<&'0 isize>` for any lifetime `'0` - = note: but `&'1 u32` only implements `Foo<&'1 isize>` for the lifetime `'1` +LL | / fn want_hrtb() +LL | | where T : for<'a> Foo<&'a isize> +LL | | { +LL | | } + | |_^ error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/issue-46989.stderr b/src/test/ui/hrtb/issue-46989.stderr new file mode 100644 index 0000000000000..b308291d5c0eb --- /dev/null +++ b/src/test/ui/hrtb/issue-46989.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `for<'r> fn(&'r i32): Foo` is not satisfied + --> $DIR/issue-46989.rs:40:5 + | +LL | assert_foo::(); + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `for<'r> fn(&'r i32)` + | + = help: the following implementations were found: + +note: required by `assert_foo` + --> $DIR/issue-46989.rs:37:1 + | +LL | fn assert_foo() {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/issue-58451.rs b/src/test/ui/hrtb/issue-58451.rs index 7ca6914d2ea96..229e505767879 100644 --- a/src/test/ui/hrtb/issue-58451.rs +++ b/src/test/ui/hrtb/issue-58451.rs @@ -9,5 +9,5 @@ where {} fn main() { - f(&[f()]); + f(&[f()]); //~ ERROR this function takes 1 parameter } diff --git a/src/test/ui/hrtb/issue-58451.stderr b/src/test/ui/hrtb/issue-58451.stderr new file mode 100644 index 0000000000000..79c24855dc96c --- /dev/null +++ b/src/test/ui/hrtb/issue-58451.stderr @@ -0,0 +1,16 @@ +error[E0061]: this function takes 1 parameter but 0 parameters were supplied + --> $DIR/issue-58451.rs:12:9 + | +LL | / fn f(i: I) +LL | | where +LL | | I: IntoIterator, +LL | | I::Item: for<'a> Into<&'a ()>, +LL | | {} + | |__- defined here +... +LL | f(&[f()]); //~ ERROR this function takes 1 parameter + | ^^^ expected 1 parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. diff --git a/src/test/ui/issues/issue-40000.stderr b/src/test/ui/issues/issue-40000.stderr index d7966cea52bb0..ce0c44c147563 100644 --- a/src/test/ui/issues/issue-40000.stderr +++ b/src/test/ui/issues/issue-40000.stderr @@ -2,10 +2,10 @@ error[E0308]: mismatched types --> $DIR/issue-40000.rs:6:9 | LL | foo(bar); //~ ERROR E0308 - | ^^^ one type is more general than the other + | ^^^ expected concrete lifetime, found bound lifetime parameter | - = note: expected type `dyn for<'r> std::ops::Fn(&'r i32)` - found type `dyn std::ops::Fn(&i32)` + = note: expected type `std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r i32) + 'static)>` + found type `std::boxed::Box` error: aborting due to previous error diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.rs b/src/test/ui/lub-glb/old-lub-glb-hr.rs index 324dc86bd92b8..0ce87bf6ffe64 100644 --- a/src/test/ui/lub-glb/old-lub-glb-hr.rs +++ b/src/test/ui/lub-glb/old-lub-glb-hr.rs @@ -4,13 +4,14 @@ // longer get an error, because we recognize these two types as // equivalent! // -// compile-pass +// Whoops -- now that we reinstituted the leak-check, we get an error +// again. fn foo( x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8), ) { - let z = match 22 { + let z = match 22 { //~ ERROR match arms have incompatible types 0 => x, _ => y, }; diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.stderr b/src/test/ui/lub-glb/old-lub-glb-hr.stderr new file mode 100644 index 0000000000000..28a366bca014c --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-hr.stderr @@ -0,0 +1,17 @@ +error[E0308]: match arms have incompatible types + --> $DIR/old-lub-glb-hr.rs:14:13 + | +LL | let z = match 22 { //~ ERROR match arms have incompatible types + | _____________^ +LL | | 0 => x, +LL | | _ => y, + | | - match arm with an incompatible type +LL | | }; + | |_____^ expected bound lifetime parameter, found concrete lifetime + | + = note: expected type `for<'r, 's> fn(&'r u8, &'s u8)` + found type `for<'a> fn(&'a u8, &'a u8)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/lub-glb/old-lub-glb-object.rs b/src/test/ui/lub-glb/old-lub-glb-object.rs index 9be7a813603d4..3e95a7111e0cd 100644 --- a/src/test/ui/lub-glb/old-lub-glb-object.rs +++ b/src/test/ui/lub-glb/old-lub-glb-object.rs @@ -1,5 +1,9 @@ // Test that we give a note when the old LUB/GLB algorithm would have // succeeded but the new code (which is stricter) gives an error. +// +// compile-pass +// +// TODO -- why does this test pass? trait Foo { } @@ -7,7 +11,7 @@ fn foo( x: &for<'a, 'b> Foo<&'a u8, &'b u8>, y: &for<'a> Foo<&'a u8, &'a u8>, ) { - let z = match 22 { //~ ERROR E0308 + let z = match 22 { 0 => x, _ => y, }; diff --git a/src/test/ui/lub-glb/old-lub-glb-object.stderr b/src/test/ui/lub-glb/old-lub-glb-object.stderr deleted file mode 100644 index 17d3648156b51..0000000000000 --- a/src/test/ui/lub-glb/old-lub-glb-object.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/old-lub-glb-object.rs:10:13 - | -LL | let z = match 22 { //~ ERROR E0308 - | _____________^ -LL | | 0 => x, -LL | | _ => y, -LL | | }; - | |_____^ one type is more general than the other - | - = note: expected type `dyn for<'a, 'b> Foo<&'a u8, &'b u8>` - found type `dyn for<'a> Foo<&'a u8, &'a u8>` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs index 437150666be0c..521bd3695dfe5 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs @@ -7,6 +7,6 @@ fn main() { fn baz(_: F) {} fn _test<'a>(f: fn(*mut &'a u32)) { - baz(f); //~ ERROR mismatched types - //~| ERROR mismatched types + baz(f); //~ ERROR type mismatch + //~| ERROR type mismatch } diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr index a6628006587c1..5dd6887005e83 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -22,25 +22,34 @@ LL | a.iter().map(|_: (u16, u16)| 45); //~ ERROR type mismatch | | | expected signature of `fn(&(u32, u32)) -> _` -error[E0308]: mismatched types +error[E0631]: type mismatch in function arguments --> $DIR/closure-arg-type-mismatch.rs:10:5 | -LL | baz(f); //~ ERROR mismatched types - | ^^^ one type is more general than the other +LL | baz(f); //~ ERROR type mismatch + | ^^^ + | | + | expected signature of `for<'r> fn(*mut &'r u32) -> _` + | found signature of `fn(*mut &'a u32) -> _` | - = note: expected type `for<'r> std::ops::Fn<(*mut &'r u32,)>` - found type `std::ops::Fn<(*mut &'a u32,)>` +note: required by `baz` + --> $DIR/closure-arg-type-mismatch.rs:8:1 + | +LL | fn baz(_: F) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0308]: mismatched types +error[E0271]: type mismatch resolving `for<'r> >::Output == ()` --> $DIR/closure-arg-type-mismatch.rs:10:5 | -LL | baz(f); //~ ERROR mismatched types - | ^^^ one type is more general than the other +LL | baz(f); //~ ERROR type mismatch + | ^^^ expected bound lifetime parameter, found concrete lifetime + | +note: required by `baz` + --> $DIR/closure-arg-type-mismatch.rs:8:1 | - = note: expected type `std::ops::FnOnce<(*mut &u32,)>` - found type `std::ops::FnOnce<(*mut &'a u32,)>` +LL | fn baz(_: F) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors -Some errors occurred: E0308, E0631. -For more information about an error, try `rustc --explain E0308`. +Some errors occurred: E0271, E0631. +For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/mismatched_types/closure-mismatch.rs b/src/test/ui/mismatched_types/closure-mismatch.rs index 152a525493732..40a4641fe7196 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.rs +++ b/src/test/ui/mismatched_types/closure-mismatch.rs @@ -5,5 +5,6 @@ impl Foo for T {} fn baz(_: T) {} fn main() { - baz(|_| ()); //~ ERROR E0308 + baz(|_| ()); //~ ERROR type mismatch + //~^ ERROR type mismatch } diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr index 0d87bc228755f..e55047e96c297 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.stderr @@ -1,12 +1,32 @@ -error[E0308]: mismatched types +error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/closure-mismatch.rs:8:9: 8:15] as std::ops::FnOnce<(&'r (),)>>::Output == ()` --> $DIR/closure-mismatch.rs:8:5 | -LL | baz(|_| ()); //~ ERROR E0308 - | ^^^ one type is more general than the other +LL | baz(|_| ()); //~ ERROR type mismatch + | ^^^ expected bound lifetime parameter, found concrete lifetime | - = note: expected type `for<'r> std::ops::Fn<(&'r (),)>` - found type `std::ops::Fn<(&(),)>` + = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]` +note: required by `baz` + --> $DIR/closure-mismatch.rs:5:1 + | +LL | fn baz(_: T) {} + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-mismatch.rs:8:5 + | +LL | baz(|_| ()); //~ ERROR type mismatch + | ^^^ ------ found signature of `fn(_) -> _` + | | + | expected signature of `for<'r> fn(&'r ()) -> _` + | + = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]` +note: required by `baz` + --> $DIR/closure-mismatch.rs:5:1 + | +LL | fn baz(_: T) {} + | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors occurred: E0271, E0631. +For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/mismatched_types/issue-36053-2.rs b/src/test/ui/mismatched_types/issue-36053-2.rs index 9035e3380b0c5..9edfebcd49471 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.rs +++ b/src/test/ui/mismatched_types/issue-36053-2.rs @@ -7,4 +7,5 @@ fn main() { once::<&str>("str").fuse().filter(|a: &str| true).count(); //~^ ERROR no method named `count` //~| ERROR type mismatch in closure arguments + //~| ERROR type mismatch in closure arguments } diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index e53e8c520e0c4..c5c67e6bd9bd9 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -16,7 +16,15 @@ LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); | | | expected signature of `for<'r> fn(&'r &str) -> _` -error: aborting due to 2 previous errors +error[E0631]: type mismatch in closure arguments + --> $DIR/issue-36053-2.rs:7:32 + | +LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); + | ^^^^^^ -------------- found signature of `for<'r> fn(&'r str) -> _` + | | + | expected signature of `fn(&&str) -> _` + +error: aborting due to 3 previous errors Some errors occurred: E0599, E0631. For more information about an error, try `rustc --explain E0599`. diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.rs b/src/test/ui/regions-fn-subtyping-return-static-fail.rs index 242119cc201da..2dd0c9796e258 100644 --- a/src/test/ui/regions-fn-subtyping-return-static-fail.rs +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.rs @@ -37,7 +37,7 @@ fn baz(x: &S) -> &S { fn supply_F() { want_F(foo); - want_F(bar); + want_F(bar); //~ ERROR mismatched types want_F(baz); } @@ -45,7 +45,7 @@ fn supply_F() { fn supply_G() { want_G(foo); want_G(bar); - want_G(baz); //~ ERROR + want_G(baz); //~ ERROR mismatched types } pub fn main() { diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr index a9234e43191ea..66e6a615b33bc 100644 --- a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr @@ -1,12 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/regions-fn-subtyping-return-static-fail.rs:40:12 + | +LL | want_F(bar); //~ ERROR mismatched types + | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx + | + = note: expected type `for<'cx> fn(&'cx S) -> &'cx S` + found type `for<'a> fn(&'a S) -> &S {bar::<'_>}` + error[E0308]: mismatched types --> $DIR/regions-fn-subtyping-return-static-fail.rs:48:12 | -LL | want_G(baz); //~ ERROR - | ^^^ one type is more general than the other +LL | want_G(baz); //~ ERROR mismatched types + | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx | = note: expected type `for<'cx> fn(&'cx S) -> &'static S` - found type `for<'r> fn(&'r S) -> &'r S` + found type `for<'r> fn(&'r S) -> &'r S {baz}` -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr index 47e1d0efdc77b..5c8b3d3ba6922 100644 --- a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr +++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr @@ -20,10 +20,10 @@ error[E0308]: mismatched types --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43 | LL | let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR mismatched types - | ^ one type is more general than the other + | ^ expected concrete lifetime, found bound lifetime parameter | = note: expected type `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found type `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)` + found type `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` error: aborting due to 3 previous errors diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr index 1e7b99053f77f..f36885f7aeb99 100644 --- a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr +++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr @@ -31,10 +31,10 @@ error[E0308]: mismatched types --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56 | LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; //~ ERROR E0308 - | ^ one type is more general than the other + | ^ expected concrete lifetime, found bound lifetime parameter | = note: expected type `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)` - found type `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize)` + found type `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize) {a::<'_, '_, '_>}` error: aborting due to 4 previous errors diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static.rs b/src/test/ui/regions/regions-fn-subtyping-return-static.rs index 9010770f1dc82..fa2cc37d05b2b 100644 --- a/src/test/ui/regions/regions-fn-subtyping-return-static.rs +++ b/src/test/ui/regions/regions-fn-subtyping-return-static.rs @@ -5,8 +5,6 @@ // *ANY* lifetime and returns a reference with the 'static lifetime. // This can safely be considered to be an instance of `F` because all // lifetimes are sublifetimes of 'static. -// -// compile-pass #![allow(dead_code)] #![allow(unused_variables)] @@ -40,7 +38,7 @@ fn baz(x: &S) -> &S { fn supply_F() { want_F(foo); - want_F(bar); + want_F(bar); //~ ERROR mismatched types want_F(baz); } diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static.stderr b/src/test/ui/regions/regions-fn-subtyping-return-static.stderr new file mode 100644 index 0000000000000..42a5a7c806e08 --- /dev/null +++ b/src/test/ui/regions/regions-fn-subtyping-return-static.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/regions-fn-subtyping-return-static.rs:41:12 + | +LL | want_F(bar); //~ ERROR mismatched types + | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx + | + = note: expected type `for<'cx> fn(&'cx S) -> &'cx S` + found type `for<'a> fn(&'a S) -> &S {bar::<'_>}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr index a43ee7ec3ace0..99d85e9e4b5a6 100644 --- a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr +++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr @@ -20,10 +20,10 @@ error[E0308]: mismatched types --> $DIR/regions-lifetime-bounds-on-fns.rs:20:43 | LL | let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR E0308 - | ^ one type is more general than the other + | ^ expected concrete lifetime, found bound lifetime parameter | = note: expected type `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found type `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)` + found type `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` error: aborting due to 3 previous errors diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs index 12626fe69cb14..a6e26614a6a50 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs @@ -11,11 +11,13 @@ fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 + //~| ERROR expected } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 + //~| ERROR expected } fn c() { diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr index 29f276711c745..ca0298283661f 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr @@ -11,8 +11,21 @@ note: required by `call_it` LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:13 + | +LL | let x = call_it(&square, 22); + | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` + | + = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` +note: required by `call_it` + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:7:1 + | +LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:17:13 + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:18:13 | LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` @@ -25,18 +38,31 @@ LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:22:13 + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:18:13 + | +LL | let y = call_it_mut(&mut square, 22); + | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` + | + = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` +note: required by `call_it_mut` + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:8:1 + | +LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:24:13 | LL | let z = call_it_once(square, 22); | ^^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` | - = help: the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` + = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` note: required by `call_it_once` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:9:1 | LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs index 7c3152c87c461..dd3b1afc39f31 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs @@ -11,11 +11,13 @@ fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 + //~| ERROR expected } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 + //~| ERROR expected } fn c() { diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr index e382457860579..0abc58aeebfe5 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr @@ -11,8 +11,21 @@ note: required by `call_it` LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` + --> $DIR/unboxed-closures-wrong-abi.rs:12:13 + | +LL | let x = call_it(&square, 22); + | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` + | + = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` +note: required by `call_it` + --> $DIR/unboxed-closures-wrong-abi.rs:7:1 + | +LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:17:13 + --> $DIR/unboxed-closures-wrong-abi.rs:18:13 | LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` @@ -25,18 +38,31 @@ LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:22:13 + --> $DIR/unboxed-closures-wrong-abi.rs:18:13 + | +LL | let y = call_it_mut(&mut square, 22); + | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` + | + = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` +note: required by `call_it_mut` + --> $DIR/unboxed-closures-wrong-abi.rs:8:1 + | +LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` + --> $DIR/unboxed-closures-wrong-abi.rs:24:13 | LL | let z = call_it_once(square, 22); | ^^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` | - = help: the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` + = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` note: required by `call_it_once` --> $DIR/unboxed-closures-wrong-abi.rs:9:1 | LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs index 61d46869cbbf2..c689d79266187 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs @@ -12,11 +12,13 @@ fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 + //~| ERROR expected } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 + //~| ERROR expected } fn c() { diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr index da511f091bf6a..19b87ad171a51 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr @@ -11,8 +11,21 @@ note: required by `call_it` LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:13 + | +LL | let x = call_it(&square, 22); + | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + | + = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` +note: required by `call_it` + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:8:1 + | +LL | fn call_itisize>(_: &F, _: isize) -> isize { 0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:18:13 + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:19:13 | LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` @@ -25,18 +38,31 @@ LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:23:13 + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:19:13 + | +LL | let y = call_it_mut(&mut square, 22); + | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + | + = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` +note: required by `call_it_mut` + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:9:1 + | +LL | fn call_it_mutisize>(_: &mut F, _: isize) -> isize { 0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:25:13 | LL | let z = call_it_once(square, 22); | ^^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` | - = help: the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` + = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` note: required by `call_it_once` --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:10:1 | LL | fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/where-clauses/where-for-self-2.rs b/src/test/ui/where-clauses/where-for-self-2.rs index 0ce38e69f6b0f..31174fd4cf163 100644 --- a/src/test/ui/where-clauses/where-for-self-2.rs +++ b/src/test/ui/where-clauses/where-for-self-2.rs @@ -18,5 +18,5 @@ fn foo(x: &T) {} fn main() { - foo(&X); //~ ERROR implementation of `Bar` is not general enough + foo(&X); //~ ERROR trait bound } diff --git a/src/test/ui/where-clauses/where-for-self-2.stderr b/src/test/ui/where-clauses/where-for-self-2.stderr index afc80bf4d8ee6..bbcb61a856d8d 100644 --- a/src/test/ui/where-clauses/where-for-self-2.stderr +++ b/src/test/ui/where-clauses/where-for-self-2.stderr @@ -1,12 +1,19 @@ -error: implementation of `Bar` is not general enough +error[E0277]: the trait bound `for<'a> &'a _: Bar` is not satisfied --> $DIR/where-for-self-2.rs:21:5 | -LL | foo(&X); //~ ERROR implementation of `Bar` is not general enough - | ^^^ +LL | foo(&X); //~ ERROR trait bound + | ^^^ the trait `for<'a> Bar` is not implemented for `&'a _` | - = note: Due to a where-clause on `foo`, - = note: `&'0 _` must implement `Bar` for any lifetime `'0` - = note: but `&'1 u32` only implements `Bar` for the lifetime `'1` + = help: the following implementations were found: + <&'static u32 as Bar> +note: required by `foo` + --> $DIR/where-for-self-2.rs:16:1 + | +LL | / fn foo(x: &T) +LL | | where for<'a> &'a T: Bar +LL | | {} + | |__^ error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`. From 551aafc407e5240cb9d14a612c1e9a1d11d53775 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 21 Feb 2019 12:14:30 -0500 Subject: [PATCH 33/41] partially revert 904a0bde93f0348f69914ee90b1f8b6e4e0d7cbc This preserves the error you currently get on stable for the old-lub-glb-object.rs test. --- src/librustc/traits/select.rs | 20 ++++++++++++++++++- src/test/ui/lub-glb/old-lub-glb-object.rs | 6 +----- src/test/ui/lub-glb/old-lub-glb-object.stderr | 17 ++++++++++++++++ 3 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/lub-glb/old-lub-glb-object.stderr diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 20d95de60b312..1c84603e9da07 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -3254,9 +3254,27 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { tcx.mk_existential_predicates(iter) }); let source_trait = tcx.mk_dynamic(existential_predicates, r_b); + + // Require that the traits involved in this upcast are **equal**; + // only the **lifetime bound** is changed. + // + // FIXME: This condition is arguably too strong -- it + // would suffice for the source trait to be a + // *subtype* of the target trait. In particular + // changing from something like `for<'a, 'b> Foo<'a, + // 'b>` to `for<'a> Foo<'a, 'a>` should be + // permitted. And, indeed, in the in commit + // 904a0bde93f0348f69914ee90b1f8b6e4e0d7cbc, this + // condition was loosened. However, when the leak check was added + // back, using subtype here actually guies the coercion code in + // such a way that it accepts `old-lub-glb-object.rs`. This is probably + // a good thing, but I've modified this to `.eq` because I want + // to continue rejecting that test (as we have done for quite some time) + // before we are firmly comfortable with what our behavior + // should be there. -nikomatsakis let InferOk { obligations, .. } = self.infcx .at(&obligation.cause, obligation.param_env) - .sup(target, source_trait) + .eq(target, source_trait) // FIXME -- see below .map_err(|_| Unimplemented)?; nested.extend(obligations); diff --git a/src/test/ui/lub-glb/old-lub-glb-object.rs b/src/test/ui/lub-glb/old-lub-glb-object.rs index 3e95a7111e0cd..f45696bcaad70 100644 --- a/src/test/ui/lub-glb/old-lub-glb-object.rs +++ b/src/test/ui/lub-glb/old-lub-glb-object.rs @@ -1,9 +1,5 @@ // Test that we give a note when the old LUB/GLB algorithm would have // succeeded but the new code (which is stricter) gives an error. -// -// compile-pass -// -// TODO -- why does this test pass? trait Foo { } @@ -11,7 +7,7 @@ fn foo( x: &for<'a, 'b> Foo<&'a u8, &'b u8>, y: &for<'a> Foo<&'a u8, &'a u8>, ) { - let z = match 22 { + let z = match 22 { //~ ERROR match arms have incompatible types 0 => x, _ => y, }; diff --git a/src/test/ui/lub-glb/old-lub-glb-object.stderr b/src/test/ui/lub-glb/old-lub-glb-object.stderr new file mode 100644 index 0000000000000..a31cd6f7a1900 --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-object.stderr @@ -0,0 +1,17 @@ +error[E0308]: match arms have incompatible types + --> $DIR/old-lub-glb-object.rs:10:13 + | +LL | let z = match 22 { //~ ERROR match arms have incompatible types + | _____________^ +LL | | 0 => x, +LL | | _ => y, + | | - match arm with an incompatible type +LL | | }; + | |_____^ expected bound lifetime parameter 'a, found concrete lifetime + | + = note: expected type `&dyn for<'a, 'b> Foo<&'a u8, &'b u8>` + found type `&dyn for<'a> Foo<&'a u8, &'a u8>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 600ca1ecb09a3811d083366c418169d9f07a6668 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 22 Feb 2019 04:11:23 +0000 Subject: [PATCH 34/41] improve Pin documentation Incorporates a bunch of the documentation-related comments that came up when discussing `Pin` stabilization. --- src/libcore/marker.rs | 27 ++-- src/libcore/pin.rs | 336 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 312 insertions(+), 51 deletions(-) diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 65752ba032104..4fd386c16d96d 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -597,34 +597,43 @@ unsafe impl Freeze for &mut T {} /// Types which can be safely moved after being pinned. /// -/// Since Rust itself has no notion of immovable types, and will consider moves to always be safe, +/// Since Rust itself has no notion of immovable types, and considers moves +/// (e.g. through assignment or [`mem::replace`]) to always be safe, /// this trait cannot prevent types from moving by itself. /// -/// Instead it can be used to prevent moves through the type system, -/// by controlling the behavior of pointers wrapped in the [`Pin`] wrapper, +/// Instead it is used to prevent moves through the type system, +/// by controlling the behavior of pointers `P` wrapped in the [`Pin

`] wrapper, /// which "pin" the type in place by not allowing it to be moved out of them. /// See the [`pin module`] documentation for more information on pinning. /// /// Implementing this trait lifts the restrictions of pinning off a type, -/// which then allows it to move out with functions such as [`replace`]. +/// which then allows it to move out with functions such as [`mem::replace`]. +/// +/// `Unpin` has no consequence at all for non-pinned data. In particular, +/// [`mem::replace`] happily moves `!Unpin` data (it works for any `&mut T`, not +/// just when `T: Unpin`). However, you cannot use +/// [`mem::replace`] on data wrapped inside a [`Pin

`] because you cannot get the +/// `&mut T` you need for that, and *that* is what makes this system work. /// /// So this, for example, can only be done on types implementing `Unpin`: /// /// ```rust -/// use std::mem::replace; +/// use std::mem; /// use std::pin::Pin; /// /// let mut string = "this".to_string(); /// let mut pinned_string = Pin::new(&mut string); /// -/// // dereferencing the pointer mutably is only possible because String implements Unpin -/// replace(&mut *pinned_string, "other".to_string()); +/// // We need a mutable reference to call `mem::replace`. +/// // We can obtain such a reference by (implicitly) invoking `Pin::deref_mut`, +/// // but that is only possible because `String` implements `Unpin`. +/// mem::replace(&mut *pinned_string, "other".to_string()); /// ``` /// /// This trait is automatically implemented for almost every type. /// -/// [`replace`]: ../../std/mem/fn.replace.html -/// [`Pin`]: ../pin/struct.Pin.html +/// [`mem::replace`]: ../../std/mem/fn.replace.html +/// [`Pin

`]: ../pin/struct.Pin.html /// [`pin module`]: ../../std/pin/index.html #[stable(feature = "pin", since = "1.33.0")] pub auto trait Unpin {} diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 762e07549a52a..b68b2f39d6bd9 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -2,45 +2,63 @@ //! //! It is sometimes useful to have objects that are guaranteed to not move, //! in the sense that their placement in memory does not change, and can thus be relied upon. -//! //! A prime example of such a scenario would be building self-referential structs, //! since moving an object with pointers to itself will invalidate them, //! which could cause undefined behavior. //! +//! A [`Pin

`] ensures that the pointee of any pointer type `P` has a stable location in memory, +//! meaning it cannot be moved elsewhere and its memory cannot be deallocated +//! until it gets dropped. We say that the pointee is "pinned". +//! //! By default, all types in Rust are movable. Rust allows passing all types by-value, -//! and common smart-pointer types such as `Box`, `Rc`, and `&mut` allow replacing and -//! moving the values they contain. In order to prevent objects from moving, they must -//! be pinned by wrapping a pointer to the data in the [`Pin`] type. -//! Doing this prohibits moving the value behind the pointer. -//! For example, `Pin>` functions much like a regular `Box`, -//! but doesn't allow moving `T`. The pointer value itself (the `Box`) can still be moved, -//! but the value behind it cannot. -//! -//! Since data can be moved out of `&mut` and `Box` with functions such as [`swap`], -//! changing the location of the underlying data, [`Pin`] prohibits accessing the -//! underlying pointer type (the `&mut` or `Box`) directly, and provides its own set of -//! APIs for accessing and using the value. [`Pin`] also guarantees that no other -//! functions will move the pointed-to value. This allows for the creation of -//! self-references and other special behaviors that are only possible for unmovable -//! values. +//! and common smart-pointer types such as `Box` and `&mut T` allow replacing and +//! moving the values they contain: you can move out of a `Box`, or you can use [`mem::swap`]. +//! [`Pin

`] wraps a pointer type `P`, so `Pin>` functions much like a regular `Box`: +//! when a `Pin>` gets dropped, so do its contents, and the memory gets deallocated. +//! Similarily, `Pin<&mut T>` is a lot like `&mut T`. However, [`Pin

`] does not let clients +//! actually obtain a `Box` or `&mut T` to pinned data, which implies that you cannot use +//! operations such as [`mem::swap`]: +//! ``` +//! use std::pin::Pin; +//! fn swap_pins(x: Pin<&mut T>, y: Pin<&mut T>) { +//! // `mem::swap` needs `&mut T`, but we cannot get it. +//! // We are stuck, we cannot swap the contents of these references. +//! // We could use `Pin::get_unchecked_mut`, but that is unsafe for a reason: +//! // we are not allowed to use it for moving things out of the `Pin`. +//! } +//! ``` //! -//! However, these restrictions are usually not necessary. Many types are always freely -//! movable. These types implement the [`Unpin`] auto-trait, which nullifies the effect -//! of [`Pin`]. For `T: Unpin`, `Pin>` and `Box` function identically, as do -//! `Pin<&mut T>` and `&mut T`. +//! It is worth reiterating that [`Pin

`] does *not* change the fact that a Rust compiler +//! considers all types movable. [`mem::swap`] remains callable for any `T`. Instead, `Pin

` +//! prevents certain *values* (pointed to by pointers wrapped in `Pin

`) from being +//! moved by making it impossible to call methods that require `&mut T` on them +//! (like [`mem::swap`]). //! -//! Note that pinning and `Unpin` only affect the pointed-to type. For example, whether -//! or not `Box` is `Unpin` has no affect on the behavior of `Pin>`. Similarly, -//! `Pin>` and `Pin<&mut T>` are always `Unpin` themselves, even though the -//! `T` underneath them isn't, because the pointers in `Pin>` and `Pin<&mut _>` -//! are always freely movable, even if the data they point to isn't. +//! [`Pin

`] can be used to wrap any pointer type `P`, and as such it interacts with +//! [`Deref`] and [`DerefMut`]. A `Pin

` where `P: Deref` should be considered +//! as a "`P`-style pointer" to a pinned `P::Target` -- so, a `Pin>` is +//! an owned pointer to a pinned `T`, and a `Pin>` is a reference-counted +//! pointer to a pinned `T`. +//! For correctness, [`Pin

`] relies on the [`Deref`] and [`DerefMut`] implementations +//! to not move out of their `self` parameter, and to only ever return a pointer +//! to pinned data when they are called on a pinned pointer. //! -//! [`Pin`]: struct.Pin.html -//! [`Unpin`]: ../../std/marker/trait.Unpin.html -//! [`swap`]: ../../std/mem/fn.swap.html -//! [`Box`]: ../../std/boxed/struct.Box.html +//! # `Unpin` +//! +//! However, these restrictions are usually not necessary. Many types are always freely +//! movable, even when pinned, because they do not rely on having a stable address. +//! This includes all the basic types (like `bool`, `i32`, references) +//! as well as types consisting solely of these types. +//! Types that do not care about pinning implement the [`Unpin`] auto-trait, which +//! cancels the effect of [`Pin

`]. For `T: Unpin`, `Pin>` and `Box` function +//! identically, as do `Pin<&mut T>` and `&mut T`. +//! +//! Note that pinning and `Unpin` only affect the pointed-to type `P::Target`, not the pointer +//! type `P` itself that got wrapped in `Pin

`. For example, whether or not `Box` is +//! `Unpin` has no effect on the behavior of `Pin>` (here, `T` is the +//! pointed-to type). //! -//! # Examples +//! # Example: self-referential struct //! //! ```rust //! use std::pin::Pin; @@ -94,6 +112,150 @@ //! // let new_unmoved = Unmovable::new("world".to_string()); //! // std::mem::swap(&mut *still_unmoved, &mut *new_unmoved); //! ``` +//! +//! # Example: intrusive doubly-linked list +//! +//! In an intrusive doubly-linked list, the collection does not actually allocate +//! the memory for the elements itself. Allocation is controlled by the clients, +//! and elements can live on a stack frame that lives shorter than the collection does. +//! +//! To make this work, every element has pointers to its predecessor and successor in +//! the list. Elements can only be added when they are pinned, because moving the elements +//! around would invalidate the pointers. Moreover, the `Drop` implementation of a linked +//! list element will patch the pointers of its predecessor and successor to remove itself +//! from the list. +//! +//! Crucially, we have to be able to rely on `drop` being called. If an element +//! could be deallocated or otherwise invalidated without calling `drop`, the pointers into it +//! from its neighbouring elements would become invalid, which would break the data structure. +//! +//! Therefore, pinning also comes with a `drop`-related guarantee. +//! +//! # `Drop` guarantee +//! +//! The purpose of pinning is to be able to rely on the placement of some data in memory. +//! To make this work, not just moving the data is restricted; deallocating, repurposing, or +//! otherwise invalidating the memory used to store the data is restricted, too. +//! Concretely, for pinned data you have to maintain the invariant +//! that *its memory will not get invalidated from the moment it gets pinned until +//! when `drop` is called*. Memory can be invalidated by deallocation, but also by +//! replacing a [`Some(v)`] by [`None`], or calling [`Vec::set_len`] to "kill" some elements +//! off of a vector. +//! +//! This is exactly the kind of guarantee that the intrusive linked list from the previous +//! section needs to function correctly. +//! +//! Notice that this guarantee does *not* mean that memory does not leak! It is still +//! completely okay not to ever call `drop` on a pinned element (e.g., you can still +//! call [`mem::forget`] on a `Pin>`). In the example of the doubly-linked +//! list, that element would just stay in the list. However you may not free or reuse the storage +//! *without calling `drop`*. +//! +//! # `Drop` implementation +//! +//! If your type uses pinning (such as the two examples above), you have to be careful +//! when implementing `Drop`. The `drop` function takes `&mut self`, but this +//! is called *even if your type was previously pinned*! It is as if the +//! compiler automatically called `get_unchecked_mut`. +//! +//! This can never cause a problem in safe code because implementing a type that relies on pinning +//! requires unsafe code, but be aware that deciding to make use of pinning +//! in your type (for example by implementing some operation on `Pin<&[mut] Self>`) +//! has consequences for your `Drop` implementation as well: if an element +//! of your type could have been pinned, you must treat Drop as implicitly taking +//! `Pin<&mut Self>`. +//! +//! In particular, if your type is `#[repr(packed)]`, the compiler will automatically +//! move fields around to be able to drop them. As a consequence, you cannot use +//! pinning with a `#[repr(packed)]` type. +//! +//! # Projections and Structural Pinning +//! +//! One interesting question arises when considering the interaction of pinning and +//! the fields of a struct. When can a struct have a "pinning projection", i.e., +//! an operation with type `fn(Pin<&[mut] Struct>) -> Pin<&[mut] Field>`? +//! In a similar vein, when can a generic wrapper type (such as `Vec`, `Box`, or `RefCell`) +//! have an operation with type `fn(Pin<&[mut] Wrapper>) -> Pin<&[mut] T>`? +//! +//! Having a pinning projection for some field means that pinning is "structural": +//! when the wrapper is pinned, the field must be considered pinned, too. +//! After all, the pinning projection lets us get a `Pin<&[mut] Field>`. +//! +//! However, structural pinning comes with a few extra requirements, so not all +//! wrappers can be structural and hence not all wrappers can offer pinning projections: +//! +//! 1. The wrapper must only be [`Unpin`] if all the structural fields are +//! `Unpin`. This is the default, but `Unpin` is a safe trait, so as the author of +//! the wrapper it is your responsibility *not* to add something like +//! `impl Unpin for Wrapper`. (Notice that adding a projection operation +//! requires unsafe code, so the fact that `Unpin` is a safe trait does not break +//! the principle that you only have to worry about any of this if you use `unsafe`.) +//! 2. The destructor of the wrapper must not move structural fields out of its argument. This +//! is the exact point that was raised in the [previous section][drop-impl]: `drop` takes +//! `&mut self`, but the wrapper (and hence its fields) might have been pinned before. +//! You have to guarantee that you do not move a field inside your `Drop` implementation. +//! In particular, as explained previously, this means that your wrapper type must *not* +//! be `#[repr(packed)]`. +//! 3. You must make sure that you uphold the [`Drop` guarantee][drop-guarantee]: +//! once your wrapper is pinned, the memory that contains the +//! content is not overwritten or deallocated without calling the content's destructors. +//! This can be tricky, as witnessed by `VecDeque`: the destructor of `VecDeque` can fail +//! to call `drop` on all elements if one of the destructors panics. This violates the +//! `Drop` guarantee, because it can lead to elements being deallocated without +//! their destructor being called. (`VecDeque` has no pinning projections, so this +//! does not cause unsoundness.) +//! 4. You must not offer any other operations that could lead to data being moved out of +//! the fields when your type is pinned. For example, if the wrapper contains an +//! `Option` and there is a `take`-like operation with type +//! `fn(Pin<&mut Wrapper>) -> Option`, +//! that operation can be used to move a `T` out of a pinned `Wrapper` -- which means +//! pinning cannot be structural. +//! +//! For a more complex example of moving data out of a pinned type, imagine if `RefCell` +//! had a method `fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T>`. +//! Then we could do the following: +//! ```compile_fail +//! fn exploit_ref_cell(rc: Pin<&mut RefCell) { +//! { let p = rc.as_mut().get_pin_mut(); } // Here we get pinned access to the `T`. +//! let rc_shr: &RefCell = rc.into_ref().get_ref(); +//! let b = rc_shr.borrow_mut(); +//! let content = &mut *b; // And here we have `&mut T` to the same data. +//! } +//! ``` +//! This is catastrophic, it means we can first pin the content of the `RefCell` +//! (using `RefCell::get_pin_mut`) and then move that content using the mutable +//! reference we got later. +//! +//! For a type like `Vec`, both possibilites (structural pinning or not) make sense, +//! and the choice is up to the author. A `Vec` with structural pinning could +//! have `get_pin`/`get_pin_mut` projections. However, it could *not* allow calling +//! `pop` on a pinned `Vec` because that would move the (structurally pinned) contents! +//! Nor could it allow `push`, which might reallocate and thus also move the contents. +//! A `Vec` without structural pinning could `impl Unpin for Vec`, because the contents +//! are never pinned and the `Vec` itself is fine with being moved as well. +//! +//! In the standard library, pointer types generally do not have structural pinning, +//! and thus they do not offer pinning projections. This is why `Box: Unpin` holds for all `T`. +//! It makes sense to do this for pointer types, because moving the `Box` +//! does not actually move the `T`: the `Box` can be freely movable (aka `Unpin`) even if the `T` +//! is not. In fact, even `Pin>` and `Pin<&mut T>` are always `Unpin` themselves, +//! for the same reason: their contents (the `T`) are pinned, but the pointers themselves +//! can be moved without moving the pinned data. For both `Box` and `Pin>`, +//! whether the content is pinned is entirely independent of whether the pointer is +//! pinned, meaning pinning is *not* structural. +//! +//! [`Pin

`]: struct.Pin.html +//! [`Unpin`]: ../../std/marker/trait.Unpin.html +//! [`Deref`]: ../../std/ops/trait.Deref.html +//! [`DerefMut`]: ../../std/ops/trait.DerefMut.html +//! [`mem::swap`]: ../../std/mem/fn.swap.html +//! [`mem::forget`]: ../../std/mem/fn.forget.html +//! [`Box`]: ../../std/boxed/struct.Box.html +//! [`Vec::set_len`]: ../../std/vec/struct.Vec.html#method.set_len +//! [`None`]: ../../std/option/enum.Option.html#variant.None +//! [`Some(v)`]: ../../std/option/enum.Option.html#variant.Some +//! [drop-impl]: #drop-implementation +//! [drop-guarantee]: #drop-guarantee #![stable(feature = "pin", since = "1.33.0")] @@ -126,8 +288,13 @@ impl Pin

where P::Target: Unpin, { - /// Construct a new `Pin` around a pointer to some data of a type that - /// implements `Unpin`. + /// Construct a new `Pin

` around a pointer to some data of a type that + /// implements [`Unpin`]. + /// + /// Unlike `Pin::new_unchecked`, this method is safe because the pointer + /// `P` dereferences to an [`Unpin`] type, which cancels the pinning guarantees. + /// + /// [`Unpin`]: ../../std/marker/trait.Unpin.html #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn new(pointer: P) -> Pin

{ @@ -138,25 +305,83 @@ where } impl Pin

{ - /// Construct a new `Pin` around a reference to some data of a type that + /// Construct a new `Pin

` around a reference to some data of a type that /// may or may not implement `Unpin`. /// + /// If `pointer` dereferences to an `Unpin` type, `Pin::new` should be used + /// instead. + /// /// # Safety /// /// This constructor is unsafe because we cannot guarantee that the data - /// pointed to by `pointer` is pinned. If the constructed `Pin

` does - /// not guarantee that the data `P` points to is pinned, constructing a - /// `Pin

` is undefined behavior. + /// pointed to by `pointer` is pinned, meaning that the data will not be moved or + /// its storage invalidated until it gets dropped. If the constructed `Pin

` does + /// not guarantee that the data `P` points to is pinned, that is a violation of + /// the API contract and may lead to undefined behavior in later (safe) operations. /// - /// If `pointer` dereferences to an `Unpin` type, `Pin::new` should be used - /// instead. + /// By using this method, you are making a promise about the `P::Deref` and + /// `P::DerefMut` implementations, if they exist. Most importantly, they + /// must not move out of their `self` arguments: `Pin::as_mut` and `Pin::as_ref` + /// will call `DerefMut::deref_mut` and `Deref::deref` *on the pinned pointer* + /// and expect these methods to uphold the pinning invariants. + /// Moreover, by calling this method you promise that the reference `P` + /// dereferences to will not be moved out of again; in particular, it + /// must not be possible to obtain a `&mut P::Target` and then + /// move out of that reference (using, for example [`mem::swap`]). + /// + /// For example, calling `Pin::new_unchecked` on an `&'a mut T` is unsafe because + /// while you are able to pin it for the given lifetime `'a`, you have no control + /// over whether it is kept pinned once `'a` ends: + /// ``` + /// use std::mem; + /// use std::pin::Pin; + /// + /// fn move_pinned_ref(mut a: T, mut b: T) { + /// unsafe { + /// let p: Pin<&mut T> = Pin::new_unchecked(&mut a); + /// // This should mean the pointee `a` can never move again. + /// } + /// mem::swap(&mut a, &mut b); + /// // The address of `a` changed to `b`'s stack slot, so `a` got moved even + /// // though we have previously pinned it! We have violated the pinning API contract. + /// } + /// ``` + /// A value, once pinned, must remain pinned forever (unless its type implements `Unpin`). + /// + /// Similarily, calling `Pin::new_unchecked` on an `Rc` is unsafe because there could be + /// aliases to the same data that are not subject to the pinning restrictions: + /// ``` + /// use std::rc::Rc; + /// use std::pin::Pin; + /// + /// fn move_pinned_rc(mut x: Rc) { + /// let pinned = unsafe { Pin::new_unchecked(x.clone()) }; + /// { + /// let p: Pin<&T> = pinned.as_ref(); + /// // This should mean the pointee can never move again. + /// } + /// drop(pinned); + /// let content = Rc::get_mut(&mut x).unwrap(); + /// // Now, if `x` was the only reference, we have a mutable reference to + /// // data that we pinned above, which we could use to move it as we have + /// // seen in the previous example. We have violated the pinning API contract. + /// } + /// ``` + /// + /// [`mem::swap`]: ../../std/mem/fn.swap.html #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub unsafe fn new_unchecked(pointer: P) -> Pin

{ Pin { pointer } } - /// Get a pinned shared reference from this pinned pointer. + /// Gets a pinned shared reference from this pinned pointer. + /// + /// This is a generic method to go from `&Pin>` to `Pin<&T>`. + /// It is safe because, as part of the contract of `Pin::new_unchecked`, + /// the pointee cannot move after `Pin>` got created. + /// "Malicious" implementations of `Pointer::Deref` are likewise + /// ruled out by the contract of `Pin::new_unchecked`. #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn as_ref(self: &Pin

) -> Pin<&P::Target> { @@ -165,14 +390,23 @@ impl Pin

{ } impl Pin

{ - /// Get a pinned mutable reference from this pinned pointer. + /// Gets a pinned mutable reference from this pinned pointer. + /// + /// This is a generic method to go from `&mut Pin>` to `Pin<&mut T>`. + /// It is safe because, as part of the contract of `Pin::new_unchecked`, + /// the pointee cannot move after `Pin>` got created. + /// "Malicious" implementations of `Pointer::DerefMut` are likewise + /// ruled out by the contract of `Pin::new_unchecked`. #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn as_mut(self: &mut Pin

) -> Pin<&mut P::Target> { unsafe { Pin::new_unchecked(&mut *self.pointer) } } - /// Assign a new value to the memory behind the pinned reference. + /// Assigns a new value to the memory behind the pinned reference. + /// + /// This overwrites pinned data, but that is okay: its destructor gets + /// run before being overwritten, so no pinning guarantee is violated. #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn set(self: &mut Pin

, value: P::Target) @@ -184,10 +418,12 @@ impl Pin

{ } impl<'a, T: ?Sized> Pin<&'a T> { - /// Construct a new pin by mapping the interior value. + /// Constructs a new pin by mapping the interior value. /// /// For example, if you wanted to get a `Pin` of a field of something, /// you could use this to get access to that field in one line of code. + /// However, there are several gotchas with these "pinning projections"; + /// see the [`pin` module] documentation for further details on that topic. /// /// # Safety /// @@ -195,6 +431,8 @@ impl<'a, T: ?Sized> Pin<&'a T> { /// will not move so long as the argument value does not move (for example, /// because it is one of the fields of that value), and also that you do /// not move out of the argument you receive to the interior function. + /// + /// [`pin` module]: ../../std/pin/index.html#projections-and-structural-pinning #[stable(feature = "pin", since = "1.33.0")] pub unsafe fn map_unchecked(self: Pin<&'a T>, func: F) -> Pin<&'a U> where F: FnOnce(&T) -> &U, @@ -206,11 +444,21 @@ impl<'a, T: ?Sized> Pin<&'a T> { /// Get a shared reference out of a pin. /// + /// This is safe because it is not possible to move out of a shared reference. + /// It may seem like there is an issue here with interior mutability: in fact, + /// it *is* possible to move a `T` out of a `&RefCell`. However, this is + /// not a problem as long as there does not also exist a `Pin<&T>` pointing + /// to the same data, and `RefCell` does not let you create a pinned reference + /// to its contents. See the discussion on ["pinning projections"] for further + /// details. + /// /// Note: `Pin` also implements `Deref` to the target, which can be used /// to access the inner value. However, `Deref` only provides a reference /// that lives for as long as the borrow of the `Pin`, not the lifetime of /// the `Pin` itself. This method allows turning the `Pin` into a reference /// with the same lifetime as the original `Pin`. + /// + /// ["pinning projections"]: ../../std/pin/index.html#projections-and-structural-pinning #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn get_ref(self: Pin<&'a T>) -> &'a T { @@ -263,6 +511,8 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// /// For example, if you wanted to get a `Pin` of a field of something, /// you could use this to get access to that field in one line of code. + /// However, there are several gotchas with these "pinning projections"; + /// see the [`pin` module] documentation for further details on that topic. /// /// # Safety /// @@ -270,6 +520,8 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// will not move so long as the argument value does not move (for example, /// because it is one of the fields of that value), and also that you do /// not move out of the argument you receive to the interior function. + /// + /// [`pin` module]: ../../std/pin/index.html#projections-and-structural-pinning #[stable(feature = "pin", since = "1.33.0")] pub unsafe fn map_unchecked_mut(self: Pin<&'a mut T>, func: F) -> Pin<&'a mut U> where F: FnOnce(&mut T) -> &mut U, From fdd5467bccd5a6b9d251f714b199e041e8dd0ee8 Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Wed, 6 Feb 2019 15:42:21 +0100 Subject: [PATCH 35/41] Updated RELEASES.md for 1.33.0 Cherry-picked (and squashed) from #58227. --- RELEASES.md | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 83c44774da283..841467b69c986 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,151 @@ +Version 1.33.0 (2019-02-28) +========================== + +Language +-------- +- [You can now use the `cfg(target_vendor)` attribute.][57465] E.g. + `#[cfg(target_vendor="linux")] fn main() { println!("Hello Linux!"); }` +- [Integer patterns such as in a match expression can now be exhaustive.][56362] + E.g. You can have match statement on a `u8` that covers `0..=255` and + you would no longer be required to have a `_ => unreachable!()` case. +- [You can now have multiple patterns in `if let` and `while let` + expressions.][57532] You can do this with the same syntax as a `match` + expression. E.g. + ```rust + enum Creature { + Crab(String), + Lobster(String), + Person(String), + } + + fn main() { + let state = Creature::Crab("Ferris"); + + if let Creature::Crab(name) | Creature::Person(name) = state { + println!("This creature's name is: {}", name); + } + } + ``` +- [You can now have irrefutable `if let` and `while let` patterns.][57535] Using + this feature will by default produce a warning as this behaviour can be + unintuitive. E.g. `if let _ = 5 {}` +- [You can now use `let` bindings, assignments, expression statements, + and irrefutable pattern destructuring in const functions.][57175] +- [You can now call unsafe const functions.][57067] E.g. + ```rust + const unsafe fn foo() -> i32 { 5 } + const fn bar() -> i32 { + unsafe { foo() } + } + ``` +- [You can now specify multiple attributes in a `cfg_attr` attribute.][57332] + E.g. `#[cfg_attr(all(), must_use, optimize)]` +- [You can now specify a specific alignment with the `#[repr(packed)]` + attribute.][57049] E.g. `#[repr(packed(2))] struct Foo(i16, i32);` is a struct + with an alignment of 2 bytes and a size of 6 bytes. +- [You can now import an item from a module as an `_`.][56303] This allows you to + import a trait's impls, and not have the name in the namespace. E.g. + ```rust + use std::io::Read as _; + + // Allowed as there is only one `Read` in the module. + pub trait Read {} + ``` +- [`extern` functions will now abort by default when panicking.][55982] + This was previously undefined behaviour. + +Compiler +-------- +- [You can now set a linker flavor for `rustc` with the `-Clinker-flavor` + command line argument.][56351] +- [The mininum required LLVM version has been bumped to 6.0.][56642] +- [Added support for the PowerPC64 architecture on FreeBSD.][57615] +- [The `x86_64-fortanix-unknown-sgx` target support has been upgraded to + tier 2 support.][57130] Visit the [platform support][platform-support] page for + information on Rust's platform support. +- [Added support for the `thumbv7neon-linux-androideabi` and + `thumbv7neon-unknown-linux-gnueabihf` targets.][56947] +- [Added support for the `x86_64-unknown-uefi` target.][56769] + +Libraries +--------- +- [The methods `overflowing_{add, sub, mul, shl, shr}` are now `const` + functions for all numeric types.][57566] +- [The methods `rotate_left`, `rotate_right`, and `wrapping_{add, sub, mul, shl, shr}` + are now `const` functions for all numeric types.][57105] +- [The methods `is_positive` and `is_negative` are now `const` functions for + all signed numeric types.][57105] +- [The `get` method for all `NonZero` types is now `const`.][57167] +- [The methods `count_ones`, `count_zeros`, `leading_zeros`, `trailing_zeros`, + `swap_bytes`, `from_be`, `from_le`, `to_be`, `to_le` are now `const` for all + numeric types.][57234] +- [`Ipv4Addr::new` is now a `const` function][57234] + +Stabilized APIs +--------------- +- [`unix::FileExt::read_exact_at`] +- [`unix::FileExt::write_all_at`] +- [`Option::transpose`] +- [`Result::transpose`] +- [`convert::identity`] +- [`pin::Pin`] +- [`marker::Unpin`] +- [`marker::PhantomPinned`] +- [`Vec::resize_with`] +- [`VecDeque::resize_with`] +- [`Duration::as_millis`] +- [`Duration::as_micros`] +- [`Duration::as_nanos`] + + +Cargo +----- +- [Cargo should now rebuild a crate if a file was modified during the initial + build.][cargo/6484] + +Compatibility Notes +------------------- +- The methods `str::{trim_left, trim_right, trim_left_matches, trim_right_matches}` + are now deprecated in the standard library, and their usage will now produce a warning. + Please use the `str::{trim_start, trim_end, trim_start_matches, trim_end_matches}` + methods instead. + +[57615]: https://github.com/rust-lang/rust/pull/57615/ +[57465]: https://github.com/rust-lang/rust/pull/57465/ +[57532]: https://github.com/rust-lang/rust/pull/57532/ +[57535]: https://github.com/rust-lang/rust/pull/57535/ +[57566]: https://github.com/rust-lang/rust/pull/57566/ +[57130]: https://github.com/rust-lang/rust/pull/57130/ +[57167]: https://github.com/rust-lang/rust/pull/57167/ +[57175]: https://github.com/rust-lang/rust/pull/57175/ +[57234]: https://github.com/rust-lang/rust/pull/57234/ +[57332]: https://github.com/rust-lang/rust/pull/57332/ +[56947]: https://github.com/rust-lang/rust/pull/56947/ +[57049]: https://github.com/rust-lang/rust/pull/57049/ +[57067]: https://github.com/rust-lang/rust/pull/57067/ +[56769]: https://github.com/rust-lang/rust/pull/56769/ +[56642]: https://github.com/rust-lang/rust/pull/56642/ +[56303]: https://github.com/rust-lang/rust/pull/56303/ +[56351]: https://github.com/rust-lang/rust/pull/56351/ +[55982]: https://github.com/rust-lang/rust/pull/55982/ +[56362]: https://github.com/rust-lang/rust/pull/56362 +[57105]: https://github.com/rust-lang/rust/pull/57105 +[cargo/6484]: https://github.com/rust-lang/cargo/pull/6484/ +[`unix::FileExt::read_exact_at`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#method.read_exact_at +[`unix::FileExt::write_all_at`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#method.write_all_at +[`Option::transpose`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.transpose +[`Result::transpose`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.transpose +[`convert::identity`]: https://doc.rust-lang.org/std/convert/fn.identity.html +[`pin::Pin`]: https://doc.rust-lang.org/std/pin/struct.Pin.html +[`marker::Unpin`]: https://doc.rust-lang.org/stable/std/marker/trait.Unpin.html +[`marker::PhantomPinned`]: https://doc.rust-lang.org/nightly/std/marker/struct.PhantomPinned.html +[`Vec::resize_with`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.resize_with +[`VecDeque::resize_with`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.resize_with +[`Duration::as_millis`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_millis +[`Duration::as_micros`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_micros +[`Duration::as_nanos`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_nanos +[platform-support]: https://forge.rust-lang.org/platform-support.html + Version 1.32.0 (2019-01-17) ========================== From a63575c3abe1386277048c9c0fc3909f892750da Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 23 Jan 2019 12:05:00 +0100 Subject: [PATCH 36/41] Fix invalid background color --- src/librustdoc/html/static/themes/dark.css | 4 ---- src/librustdoc/html/static/themes/light.css | 4 ---- 2 files changed, 8 deletions(-) diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 52a30967a2310..6935ecde791f8 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -410,10 +410,6 @@ kbd { color: #ccc; } -.impl-items code { - background-color: rgba(0, 0, 0, 0); -} - #sidebar-toggle { background-color: #565656; } diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index d20fea666e61d..306e8dc15d893 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -405,10 +405,6 @@ kbd { color: #999; } -.impl-items code { - background-color: rgba(0, 0, 0, 0); -} - #sidebar-toggle { background-color: #F1F1F1; } From 5c6eb4e844abedcb179f390c62a8a30fc3df5e97 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 17 Jan 2019 21:28:23 +0100 Subject: [PATCH 37/41] Fix non-clickable urls --- src/librustdoc/html/static/rustdoc.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 8a8b7adcf7d4a..36765496ff4e9 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -391,10 +391,6 @@ h4 > code, h3 > code, .invisible > code { display: block; } -.in-band, code { - z-index: -5; -} - .invisible { width: 100%; display: inline-block; From ab4c12ac5a67d74514a636bc427d0a442f102a0b Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Mon, 25 Feb 2019 08:56:15 +0100 Subject: [PATCH 38/41] stable 1.33.0 release --- src/ci/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/run.sh b/src/ci/run.sh index b7e8176255997..8051a21ccf8c7 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -43,7 +43,7 @@ fi # # FIXME: need a scheme for changing this `nightly` value to `beta` and `stable` # either automatically or manually. -export RUST_RELEASE_CHANNEL=beta +export RUST_RELEASE_CHANNEL=stable if [ "$DEPLOY$DEPLOY_ALT" != "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=$RUST_RELEASE_CHANNEL" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp" From e48ffae3010d8b4af89ef4be324232fc287683bd Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Wed, 27 Feb 2019 17:09:32 -0700 Subject: [PATCH 39/41] Fix release note problems noticed after merging. --- RELEASES.md | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 841467b69c986..4cda02c5c2ebe 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -4,10 +4,10 @@ Version 1.33.0 (2019-02-28) Language -------- - [You can now use the `cfg(target_vendor)` attribute.][57465] E.g. - `#[cfg(target_vendor="linux")] fn main() { println!("Hello Linux!"); }` + `#[cfg(target_vendor="apple")] fn main() { println!("Hello Apple!"); }` - [Integer patterns such as in a match expression can now be exhaustive.][56362] E.g. You can have match statement on a `u8` that covers `0..=255` and - you would no longer be required to have a `_ => unreachable!()` case. + you would no longer be required to have a `_ => unreachable!()` case. - [You can now have multiple patterns in `if let` and `while let` expressions.][57532] You can do this with the same syntax as a `match` expression. E.g. @@ -51,8 +51,7 @@ Language // Allowed as there is only one `Read` in the module. pub trait Read {} ``` -- [`extern` functions will now abort by default when panicking.][55982] - This was previously undefined behaviour. +- [You may now use `Rc`, `Arc`, and `Pin` as method receivers][56805]. Compiler -------- @@ -109,27 +108,30 @@ Compatibility Notes are now deprecated in the standard library, and their usage will now produce a warning. Please use the `str::{trim_start, trim_end, trim_start_matches, trim_end_matches}` methods instead. +- The `Error::cause` method has been deprecated in favor of `Error::source` which supports + downcasting. -[57615]: https://github.com/rust-lang/rust/pull/57615/ -[57465]: https://github.com/rust-lang/rust/pull/57465/ -[57532]: https://github.com/rust-lang/rust/pull/57532/ -[57535]: https://github.com/rust-lang/rust/pull/57535/ -[57566]: https://github.com/rust-lang/rust/pull/57566/ +[55982]: https://github.com/rust-lang/rust/pull/55982/ +[56303]: https://github.com/rust-lang/rust/pull/56303/ +[56351]: https://github.com/rust-lang/rust/pull/56351/ +[56362]: https://github.com/rust-lang/rust/pull/56362 +[56642]: https://github.com/rust-lang/rust/pull/56642/ +[56769]: https://github.com/rust-lang/rust/pull/56769/ +[56805]: https://github.com/rust-lang/rust/pull/56805 +[56947]: https://github.com/rust-lang/rust/pull/56947/ +[57049]: https://github.com/rust-lang/rust/pull/57049/ +[57067]: https://github.com/rust-lang/rust/pull/57067/ +[57105]: https://github.com/rust-lang/rust/pull/57105 [57130]: https://github.com/rust-lang/rust/pull/57130/ [57167]: https://github.com/rust-lang/rust/pull/57167/ [57175]: https://github.com/rust-lang/rust/pull/57175/ [57234]: https://github.com/rust-lang/rust/pull/57234/ [57332]: https://github.com/rust-lang/rust/pull/57332/ -[56947]: https://github.com/rust-lang/rust/pull/56947/ -[57049]: https://github.com/rust-lang/rust/pull/57049/ -[57067]: https://github.com/rust-lang/rust/pull/57067/ -[56769]: https://github.com/rust-lang/rust/pull/56769/ -[56642]: https://github.com/rust-lang/rust/pull/56642/ -[56303]: https://github.com/rust-lang/rust/pull/56303/ -[56351]: https://github.com/rust-lang/rust/pull/56351/ -[55982]: https://github.com/rust-lang/rust/pull/55982/ -[56362]: https://github.com/rust-lang/rust/pull/56362 -[57105]: https://github.com/rust-lang/rust/pull/57105 +[57465]: https://github.com/rust-lang/rust/pull/57465/ +[57532]: https://github.com/rust-lang/rust/pull/57532/ +[57535]: https://github.com/rust-lang/rust/pull/57535/ +[57566]: https://github.com/rust-lang/rust/pull/57566/ +[57615]: https://github.com/rust-lang/rust/pull/57615/ [cargo/6484]: https://github.com/rust-lang/cargo/pull/6484/ [`unix::FileExt::read_exact_at`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#method.read_exact_at [`unix::FileExt::write_all_at`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#method.write_all_at @@ -170,7 +172,7 @@ Language - [You can now match against literals in macros with the `literal` specifier.][56072] This will match against a literal of any type. E.g. `1`, `'A'`, `"Hello World"` -- [Self can now be used as a constructor and pattern for unit and tuple structs.][56365] E.g. +- [Self can now be used as a constructor and pattern for unit and tuple structs.][56365] E.g. ```rust struct Point(i32, i32); @@ -460,7 +462,7 @@ Version 1.31.0 (2018-12-06) Language -------- -- 🎉 [This version marks the release of the 2018 edition of Rust.][54057] 🎉 +- 🎉 [This version marks the release of the 2018 edition of Rust.][54057] 🎉 - [New lifetime elision rules now allow for eliding lifetimes in functions and impl headers.][54778] E.g. `impl<'a> Reader for BufReader<'a> {}` can now be `impl Reader for BufReader<'_> {}`. Lifetimes are still required to be defined From bd1f0327eebce569680b1338e0814fde57a58971 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Wed, 27 Feb 2019 17:21:31 -0700 Subject: [PATCH 40/41] Permit unwinding through FFI by default See #58794 for context. --- src/librustc_mir/build/mod.rs | 2 +- src/test/run-pass/abort-on-c-abi.rs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 2bf2824d835cc..89542011aa693 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -611,7 +611,7 @@ fn should_abort_on_panic<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, // unwind anyway. Don't stop them. let attrs = &tcx.get_attrs(fn_def_id); match attr::find_unwind_attr(Some(tcx.sess.diagnostic()), attrs) { - None => true, + None => false, // FIXME(#58794) Some(UnwindAttr::Allowed) => false, Some(UnwindAttr::Aborts) => true, } diff --git a/src/test/run-pass/abort-on-c-abi.rs b/src/test/run-pass/abort-on-c-abi.rs index df94cd5718631..c3991bd2e59c8 100644 --- a/src/test/run-pass/abort-on-c-abi.rs +++ b/src/test/run-pass/abort-on-c-abi.rs @@ -1,4 +1,5 @@ #![allow(unused_must_use)] +#![feature(unwind_attributes)] // Since we mark some ABIs as "nounwind" to LLVM, we must make sure that // we never unwind through them. @@ -10,6 +11,7 @@ use std::io::prelude::*; use std::io; use std::process::{Command, Stdio}; +#[unwind(aborts)] // FIXME(#58794) extern "C" fn panic_in_ffi() { panic!("Test"); } From be89474c0c0740b119e6710695e11df960b3af84 Mon Sep 17 00:00:00 2001 From: Patrick McCarter Date: Sun, 24 Mar 2019 15:23:58 -0500 Subject: [PATCH 41/41] 58982 fix incorrect error diagnostic --- src/librustc_typeck/check/coercion.rs | 16 ++++++++++------ src/test/ui/liveness/liveness-forgot-ret.stderr | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index a82a0d3ce5232..f39a095a057e8 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -1224,17 +1224,21 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> cause.span, blk_id, ); - if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() { - if !sp.overlaps(cause.span) { - db.span_label(*sp, reason_label); + if let ty::Infer(..) = self.expected_ty.sty { + if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() { + if !sp.overlaps(cause.span) { + db.span_label(*sp, reason_label); + } } } } _ => { db = fcx.report_mismatched_types(cause, expected, found, err); - if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() { - if !sp.overlaps(cause.span) { - db.span_label(*sp, reason_label); + if let ty::Infer(..) = self.expected_ty.sty { + if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() { + if !sp.overlaps(cause.span) { + db.span_label(*sp, reason_label); + } } } } diff --git a/src/test/ui/liveness/liveness-forgot-ret.stderr b/src/test/ui/liveness/liveness-forgot-ret.stderr index bbcbbdbe8dd5b..a970b80fdbbd9 100644 --- a/src/test/ui/liveness/liveness-forgot-ret.stderr +++ b/src/test/ui/liveness/liveness-forgot-ret.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/liveness-forgot-ret.rs:3:19 | LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; } - | - ^^^^^ expected isize, found () - expected because of this statement + | - ^^^^^ expected isize, found () | | | this function's body doesn't return |