diff --git a/Cargo.lock b/Cargo.lock index 8f110403eb842..d6fb659178764 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1242,9 +1242,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9586eedd4ce6b3c498bc3b4dd92fc9f11166aa908a914071953768066c67909" +checksum = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9" dependencies = [ "compiler_builtins", "libc", diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md index ff28f4f603c9d..1a1c1618da40d 100644 --- a/src/ci/docker/README.md +++ b/src/ci/docker/README.md @@ -238,7 +238,7 @@ For targets: `powerpc-unknown-linux-gnu` - Target options > Emit assembly for CPU = powerpc -- pure 32-bit PowerPC - Operating System > Target OS = linux - Operating System > Linux kernel version = 2.6.32.68 -- ~RHEL6 kernel -- C-library > glibc version = 2.12.2 -- ~RHEL6 glibc +- C-library > glibc version = 2.11.1 -- ~SLE11-SP4 glibc - C compiler > gcc version = 5.2.0 - C compiler > C++ = ENABLE -- to cross compile LLVM @@ -255,7 +255,7 @@ For targets: `powerpc64-unknown-linux-gnu` - Target options > Tune for CPU = power6 -- (+) - Operating System > Target OS = linux - Operating System > Linux kernel version = 2.6.32.68 -- ~RHEL6 kernel -- C-library > glibc version = 2.12.2 -- ~RHEL6 glibc +- C-library > glibc version = 2.11.1 -- ~SLE11-SP4 glibc - C compiler > gcc version = 5.2.0 - C compiler > C++ = ENABLE -- to cross compile LLVM @@ -272,7 +272,7 @@ For targets: `s390x-unknown-linux-gnu` - Target options > Bitness = 64-bit - Operating System > Target OS = linux - Operating System > Linux kernel version = 2.6.32.68 -- ~RHEL6 kernel -- C-library > glibc version = 2.12.2 -- ~RHEL6 glibc +- C-library > glibc version = 2.11.1 -- ~SLE11-SP4 glibc - C compiler > gcc version = 5.2.0 - C compiler > gcc extra config = --with-arch=z10 -- LLVM's minimum support - C compiler > C++ = ENABLE -- to cross compile LLVM diff --git a/src/ci/docker/host-x86_64/dist-powerpc-linux/patches/glibc/2.12.2/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch b/src/ci/docker/host-x86_64/dist-powerpc-linux/patches/glibc/2.11.1/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch similarity index 100% rename from src/ci/docker/host-x86_64/dist-powerpc-linux/patches/glibc/2.12.2/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch rename to src/ci/docker/host-x86_64/dist-powerpc-linux/patches/glibc/2.11.1/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch diff --git a/src/ci/docker/host-x86_64/dist-powerpc-linux/patches/glibc/2.12.2/002-newer-gcc.patch b/src/ci/docker/host-x86_64/dist-powerpc-linux/patches/glibc/2.11.1/002-newer-gcc.patch similarity index 100% rename from src/ci/docker/host-x86_64/dist-powerpc-linux/patches/glibc/2.12.2/002-newer-gcc.patch rename to src/ci/docker/host-x86_64/dist-powerpc-linux/patches/glibc/2.11.1/002-newer-gcc.patch diff --git a/src/ci/docker/host-x86_64/dist-powerpc-linux/powerpc-linux-gnu.config b/src/ci/docker/host-x86_64/dist-powerpc-linux/powerpc-linux-gnu.config index 7df41da2bf76e..b358dce3cdfe8 100644 --- a/src/ci/docker/host-x86_64/dist-powerpc-linux/powerpc-linux-gnu.config +++ b/src/ci/docker/host-x86_64/dist-powerpc-linux/powerpc-linux-gnu.config @@ -290,7 +290,7 @@ CT_BINUTILS_EXTRA_CONFIG_ARRAY="" # C-library # CT_LIBC="glibc" -CT_LIBC_VERSION="2.12.2" +CT_LIBC_VERSION="2.11.1" CT_LIBC_glibc=y # CT_LIBC_musl is not set # CT_LIBC_uClibc is not set @@ -309,9 +309,9 @@ CT_THREADS="nptl" # CT_LIBC_GLIBC_V_2_14_1 is not set # CT_LIBC_GLIBC_V_2_14 is not set # CT_LIBC_GLIBC_V_2_13 is not set -CT_LIBC_GLIBC_V_2_12_2=y +# CT_LIBC_GLIBC_V_2_12_2 is not set # CT_LIBC_GLIBC_V_2_12_1 is not set -# CT_LIBC_GLIBC_V_2_11_1 is not set +CT_LIBC_GLIBC_V_2_11_1=y # CT_LIBC_GLIBC_V_2_11 is not set # CT_LIBC_GLIBC_V_2_10_1 is not set # CT_LIBC_GLIBC_V_2_9 is not set diff --git a/src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.12.2/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch b/src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.11.1/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch similarity index 100% rename from src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.12.2/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch rename to src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.11.1/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch diff --git a/src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.12.2/002-Prevent-inlining-in-PPC64-initfini.s.patch b/src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.11.1/002-Prevent-inlining-in-PPC64-initfini.s.patch similarity index 100% rename from src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.12.2/002-Prevent-inlining-in-PPC64-initfini.s.patch rename to src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.11.1/002-Prevent-inlining-in-PPC64-initfini.s.patch diff --git a/src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.12.2/003-newer-gcc.patch b/src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.11.1/003-newer-gcc.patch similarity index 100% rename from src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.12.2/003-newer-gcc.patch rename to src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.11.1/003-newer-gcc.patch diff --git a/src/ci/docker/host-x86_64/dist-powerpc64-linux/powerpc64-linux-gnu.config b/src/ci/docker/host-x86_64/dist-powerpc64-linux/powerpc64-linux-gnu.config index 4aab4f4fd4445..aa13119d50c19 100644 --- a/src/ci/docker/host-x86_64/dist-powerpc64-linux/powerpc64-linux-gnu.config +++ b/src/ci/docker/host-x86_64/dist-powerpc64-linux/powerpc64-linux-gnu.config @@ -290,7 +290,7 @@ CT_BINUTILS_EXTRA_CONFIG_ARRAY="" # C-library # CT_LIBC="glibc" -CT_LIBC_VERSION="2.12.2" +CT_LIBC_VERSION="2.11.1" CT_LIBC_glibc=y # CT_LIBC_musl is not set # CT_LIBC_uClibc is not set @@ -309,9 +309,9 @@ CT_THREADS="nptl" # CT_LIBC_GLIBC_V_2_14_1 is not set # CT_LIBC_GLIBC_V_2_14 is not set # CT_LIBC_GLIBC_V_2_13 is not set -CT_LIBC_GLIBC_V_2_12_2=y +# CT_LIBC_GLIBC_V_2_12_2 is not set # CT_LIBC_GLIBC_V_2_12_1 is not set -# CT_LIBC_GLIBC_V_2_11_1 is not set +CT_LIBC_GLIBC_V_2_11_1=y # CT_LIBC_GLIBC_V_2_11 is not set # CT_LIBC_GLIBC_V_2_10_1 is not set # CT_LIBC_GLIBC_V_2_9 is not set diff --git a/src/ci/docker/host-x86_64/dist-s390x-linux/patches/glibc/2.12.2/001-Use-.machine-to-prevent-AS-from-complaining-about-z9.patch b/src/ci/docker/host-x86_64/dist-s390x-linux/patches/glibc/2.11.1/001-Use-.machine-to-prevent-AS-from-complaining-about-z9.patch similarity index 100% rename from src/ci/docker/host-x86_64/dist-s390x-linux/patches/glibc/2.12.2/001-Use-.machine-to-prevent-AS-from-complaining-about-z9.patch rename to src/ci/docker/host-x86_64/dist-s390x-linux/patches/glibc/2.11.1/001-Use-.machine-to-prevent-AS-from-complaining-about-z9.patch diff --git a/src/ci/docker/host-x86_64/dist-s390x-linux/patches/glibc/2.12.2/002-newer-gcc.patch b/src/ci/docker/host-x86_64/dist-s390x-linux/patches/glibc/2.11.1/002-newer-gcc.patch similarity index 100% rename from src/ci/docker/host-x86_64/dist-s390x-linux/patches/glibc/2.12.2/002-newer-gcc.patch rename to src/ci/docker/host-x86_64/dist-s390x-linux/patches/glibc/2.11.1/002-newer-gcc.patch diff --git a/src/ci/docker/host-x86_64/dist-s390x-linux/s390x-linux-gnu.config b/src/ci/docker/host-x86_64/dist-s390x-linux/s390x-linux-gnu.config index cd1c41b02e312..c9c141afad131 100644 --- a/src/ci/docker/host-x86_64/dist-s390x-linux/s390x-linux-gnu.config +++ b/src/ci/docker/host-x86_64/dist-s390x-linux/s390x-linux-gnu.config @@ -270,7 +270,7 @@ CT_BINUTILS_EXTRA_CONFIG_ARRAY="" # C-library # CT_LIBC="glibc" -CT_LIBC_VERSION="2.12.2" +CT_LIBC_VERSION="2.11.1" CT_LIBC_glibc=y # CT_LIBC_musl is not set # CT_LIBC_uClibc is not set @@ -289,9 +289,9 @@ CT_THREADS="nptl" # CT_LIBC_GLIBC_V_2_14_1 is not set # CT_LIBC_GLIBC_V_2_14 is not set # CT_LIBC_GLIBC_V_2_13 is not set -CT_LIBC_GLIBC_V_2_12_2=y +# CT_LIBC_GLIBC_V_2_12_2 is not set # CT_LIBC_GLIBC_V_2_12_1 is not set -# CT_LIBC_GLIBC_V_2_11_1 is not set +CT_LIBC_GLIBC_V_2_11_1=y # CT_LIBC_GLIBC_V_2_11 is not set # CT_LIBC_GLIBC_V_2_10_1 is not set # CT_LIBC_GLIBC_V_2_9 is not set diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 7392a678b0549..8e9a903522802 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1095,6 +1095,9 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn checked_pow(self, mut exp: u32) -> Option { + if exp == 0 { + return Some(1); + } let mut base = self; let mut acc: Self = 1; @@ -1105,15 +1108,11 @@ $EndFeature, " exp /= 2; base = try_opt!(base.checked_mul(base)); } - + // since exp!=0, finally the exp must be 1. // Deal with the final bit of the exponent separately, since // squaring the base afterwards is not necessary and may cause a // needless overflow. - if exp == 1 { - acc = try_opt!(acc.checked_mul(base)); - } - - Some(acc) + Some(try_opt!(acc.checked_mul(base))) } } @@ -1622,6 +1621,9 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_pow(self, mut exp: u32) -> Self { + if exp == 0 { + return 1; + } let mut base = self; let mut acc: Self = 1; @@ -1633,14 +1635,11 @@ $EndFeature, " base = base.wrapping_mul(base); } + // since exp!=0, finally the exp must be 1. // Deal with the final bit of the exponent separately, since // squaring the base afterwards is not necessary and may cause a // needless overflow. - if exp == 1 { - acc = acc.wrapping_mul(base); - } - - acc + acc.wrapping_mul(base) } } @@ -1989,6 +1988,9 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { + if exp == 0 { + return (1,false); + } let mut base = self; let mut acc: Self = 1; let mut overflown = false; @@ -2007,16 +2009,13 @@ $EndFeature, " overflown |= r.1; } + // since exp!=0, finally the exp must be 1. // Deal with the final bit of the exponent separately, since // squaring the base afterwards is not necessary and may cause a // needless overflow. - if exp == 1 { - r = acc.overflowing_mul(base); - acc = r.0; - overflown |= r.1; - } - - (acc, overflown) + r = acc.overflowing_mul(base); + r.1 |= overflown; + r } } @@ -2040,6 +2039,9 @@ $EndFeature, " #[inline] #[rustc_inherit_overflow_checks] pub const fn pow(self, mut exp: u32) -> Self { + if exp == 0 { + return 1; + } let mut base = self; let mut acc = 1; @@ -2051,14 +2053,11 @@ $EndFeature, " base = base * base; } + // since exp!=0, finally the exp must be 1. // Deal with the final bit of the exponent separately, since // squaring the base afterwards is not necessary and may cause a // needless overflow. - if exp == 1 { - acc = acc * base; - } - - acc + acc * base } } @@ -3295,6 +3294,9 @@ assert_eq!(", stringify!($SelfT), "::MAX.checked_pow(2), None);", $EndFeature, " without modifying the original"] #[inline] pub const fn checked_pow(self, mut exp: u32) -> Option { + if exp == 0 { + return Some(1); + } let mut base = self; let mut acc: Self = 1; @@ -3306,14 +3308,12 @@ assert_eq!(", stringify!($SelfT), "::MAX.checked_pow(2), None);", $EndFeature, " base = try_opt!(base.checked_mul(base)); } + // since exp!=0, finally the exp must be 1. // Deal with the final bit of the exponent separately, since // squaring the base afterwards is not necessary and may cause a // needless overflow. - if exp == 1 { - acc = try_opt!(acc.checked_mul(base)); - } - Some(acc) + Some(try_opt!(acc.checked_mul(base))) } } @@ -3704,6 +3704,9 @@ assert_eq!(3u8.wrapping_pow(6), 217);", $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_pow(self, mut exp: u32) -> Self { + if exp == 0 { + return 1; + } let mut base = self; let mut acc: Self = 1; @@ -3715,14 +3718,11 @@ assert_eq!(3u8.wrapping_pow(6), 217);", $EndFeature, " base = base.wrapping_mul(base); } + // since exp!=0, finally the exp must be 1. // Deal with the final bit of the exponent separately, since // squaring the base afterwards is not necessary and may cause a // needless overflow. - if exp == 1 { - acc = acc.wrapping_mul(base); - } - - acc + acc.wrapping_mul(base) } } @@ -4029,6 +4029,9 @@ assert_eq!(3u8.overflowing_pow(6), (217, true));", $EndFeature, " without modifying the original"] #[inline] pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { + if exp == 0{ + return (1,false); + } let mut base = self; let mut acc: Self = 1; let mut overflown = false; @@ -4047,16 +4050,14 @@ assert_eq!(3u8.overflowing_pow(6), (217, true));", $EndFeature, " overflown |= r.1; } + // since exp!=0, finally the exp must be 1. // Deal with the final bit of the exponent separately, since // squaring the base afterwards is not necessary and may cause a // needless overflow. - if exp == 1 { - r = acc.overflowing_mul(base); - acc = r.0; - overflown |= r.1; - } + r = acc.overflowing_mul(base); + r.1 |= overflown; - (acc, overflown) + r } } @@ -4077,6 +4078,9 @@ Basic usage: #[inline] #[rustc_inherit_overflow_checks] pub const fn pow(self, mut exp: u32) -> Self { + if exp == 0 { + return 1; + } let mut base = self; let mut acc = 1; @@ -4088,14 +4092,11 @@ Basic usage: base = base * base; } + // since exp!=0, finally the exp must be 1. // Deal with the final bit of the exponent separately, since // squaring the base afterwards is not necessary and may cause a // needless overflow. - if exp == 1 { - acc = acc * base; - } - - acc + acc * base } } diff --git a/src/libcore/tests/num/int_macros.rs b/src/libcore/tests/num/int_macros.rs index 8396a0dd62db9..58a585669122c 100644 --- a/src/libcore/tests/num/int_macros.rs +++ b/src/libcore/tests/num/int_macros.rs @@ -255,12 +255,43 @@ macro_rules! int_module { #[test] fn test_pow() { let mut r = 2 as $T; - assert_eq!(r.pow(2), 4 as $T); assert_eq!(r.pow(0), 1 as $T); + assert_eq!(r.wrapping_pow(2), 4 as $T); + assert_eq!(r.wrapping_pow(0), 1 as $T); + assert_eq!(r.checked_pow(2), Some(4 as $T)); + assert_eq!(r.checked_pow(0), Some(1 as $T)); + assert_eq!(r.overflowing_pow(2), (4 as $T, false)); + assert_eq!(r.overflowing_pow(0), (1 as $T, false)); + assert_eq!(r.saturating_pow(2), 4 as $T); + assert_eq!(r.saturating_pow(0), 1 as $T); + + r = MAX; + // use `^` to represent .pow() with no overflow. + // if itest::MAX == 2^j-1, then itest is a `j` bit int, + // so that `itest::MAX*itest::MAX == 2^(2*j)-2^(j+1)+1`, + // thussaturating_pow the overflowing result is exactly 1. + assert_eq!(r.wrapping_pow(2), 1 as $T); + assert_eq!(r.checked_pow(2), None); + assert_eq!(r.overflowing_pow(2), (1 as $T, true)); + assert_eq!(r.saturating_pow(2), MAX); + //test for negative exponent. r = -2 as $T; assert_eq!(r.pow(2), 4 as $T); assert_eq!(r.pow(3), -8 as $T); + assert_eq!(r.pow(0), 1 as $T); + assert_eq!(r.wrapping_pow(2), 4 as $T); + assert_eq!(r.wrapping_pow(3), -8 as $T); + assert_eq!(r.wrapping_pow(0), 1 as $T); + assert_eq!(r.checked_pow(2), Some(4 as $T)); + assert_eq!(r.checked_pow(3), Some(-8 as $T)); + assert_eq!(r.checked_pow(0), Some(1 as $T)); + assert_eq!(r.overflowing_pow(2), (4 as $T, false)); + assert_eq!(r.overflowing_pow(3), (-8 as $T, false)); + assert_eq!(r.overflowing_pow(0), (1 as $T, false)); + assert_eq!(r.saturating_pow(2), 4 as $T); + assert_eq!(r.saturating_pow(3), -8 as $T); + assert_eq!(r.saturating_pow(0), 1 as $T); } } }; diff --git a/src/libcore/tests/num/uint_macros.rs b/src/libcore/tests/num/uint_macros.rs index 8f1ca8e6fac2c..b84a8a7d9f88b 100644 --- a/src/libcore/tests/num/uint_macros.rs +++ b/src/libcore/tests/num/uint_macros.rs @@ -184,6 +184,31 @@ macro_rules! uint_module { assert_eq!($T::from_str_radix("Z", 10).ok(), None::<$T>); assert_eq!($T::from_str_radix("_", 2).ok(), None::<$T>); } + + #[test] + fn test_pow() { + let mut r = 2 as $T; + assert_eq!(r.pow(2), 4 as $T); + assert_eq!(r.pow(0), 1 as $T); + assert_eq!(r.wrapping_pow(2), 4 as $T); + assert_eq!(r.wrapping_pow(0), 1 as $T); + assert_eq!(r.checked_pow(2), Some(4 as $T)); + assert_eq!(r.checked_pow(0), Some(1 as $T)); + assert_eq!(r.overflowing_pow(2), (4 as $T, false)); + assert_eq!(r.overflowing_pow(0), (1 as $T, false)); + assert_eq!(r.saturating_pow(2), 4 as $T); + assert_eq!(r.saturating_pow(0), 1 as $T); + + r = MAX; + // use `^` to represent .pow() with no overflow. + // if itest::MAX == 2^j-1, then itest is a `j` bit int, + // so that `itest::MAX*itest::MAX == 2^(2*j)-2^(j+1)+1`, + // thussaturating_pow the overflowing result is exactly 1. + assert_eq!(r.wrapping_pow(2), 1 as $T); + assert_eq!(r.checked_pow(2), None); + assert_eq!(r.overflowing_pow(2), (1 as $T, true)); + assert_eq!(r.saturating_pow(2), MAX); + } } }; } diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index ff905faa95a9f..063246f79fe36 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -1402,8 +1402,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } debug!("note_type_err(diag={:?})", diag); + enum Mismatch<'a> { + Variable(ty::error::ExpectedFound>), + Fixed(&'static str), + } let (expected_found, exp_found, is_simple_error) = match values { - None => (None, None, false), + None => (None, Mismatch::Fixed("type"), false), Some(values) => { let (is_simple_error, exp_found) = match values { ValuePairs::Types(exp_found) => { @@ -1417,9 +1421,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ) .report(diag); - (is_simple_err, Some(exp_found)) + (is_simple_err, Mismatch::Variable(exp_found)) } - _ => (false, None), + ValuePairs::TraitRefs(_) => (false, Mismatch::Fixed("trait")), + _ => (false, Mismatch::Fixed("type")), }; let vals = match self.values_str(&values) { Some((expected, found)) => Some((expected, found)), @@ -1445,8 +1450,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } }; if let Some((expected, found)) = expected_found { - let expected_label = exp_found.map_or("type".into(), |ef| ef.expected.prefix_string()); - let found_label = exp_found.map_or("type".into(), |ef| ef.found.prefix_string()); + let expected_label = match exp_found { + Mismatch::Variable(ef) => ef.expected.prefix_string(), + Mismatch::Fixed(s) => s.into(), + }; + let found_label = match exp_found { + Mismatch::Variable(ef) => ef.found.prefix_string(), + Mismatch::Fixed(s) => s.into(), + }; + let exp_found = match exp_found { + Mismatch::Variable(exp_found) => Some(exp_found), + Mismatch::Fixed(_) => None, + }; match (&terr, expected == found) { (TypeError::Sorts(values), extra) => { let sort_string = |ty: Ty<'tcx>| match (extra, &ty.kind) { @@ -1499,6 +1514,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } } + let exp_found = match exp_found { + Mismatch::Variable(exp_found) => Some(exp_found), + Mismatch::Fixed(_) => None, + }; if let Some(exp_found) = exp_found { self.suggest_as_ref_where_appropriate(span, &exp_found, diag); } diff --git a/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs b/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs index dd970d800fba0..8521f900988e4 100644 --- a/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs +++ b/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs @@ -60,9 +60,7 @@ impl OutlivesSuggestionBuilder { // Don't give suggestions for upvars, closure return types, or other unnamable // regions. RegionNameSource::SynthesizedFreeEnvRegion(..) - | RegionNameSource::CannotMatchHirTy(..) - | RegionNameSource::MatchedHirTy(..) - | RegionNameSource::MatchedAdtAndSegment(..) + | RegionNameSource::AnonRegionFromArgument(..) | RegionNameSource::AnonRegionFromUpvar(..) | RegionNameSource::AnonRegionFromOutput(..) | RegionNameSource::AnonRegionFromYieldTy(..) diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs index 26c2aea41d5dc..cc8a5e0768cba 100644 --- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs @@ -19,7 +19,7 @@ use crate::borrow_check::{ MirBorrowckCtxt, }; -use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource}; +use super::{OutlivesSuggestionBuilder, RegionName}; impl ConstraintDescription for ConstraintCategory { fn description(&self) -> &'static str { @@ -396,18 +396,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { diag.span_label(upvar_span, "variable captured here"); } - match self.give_region_a_name(*outlived_fr).unwrap().source { - RegionNameSource::NamedEarlyBoundRegion(fr_span) - | RegionNameSource::NamedFreeRegion(fr_span) - | RegionNameSource::SynthesizedFreeEnvRegion(fr_span, _) - | RegionNameSource::CannotMatchHirTy(fr_span, _) - | RegionNameSource::MatchedHirTy(fr_span) - | RegionNameSource::MatchedAdtAndSegment(fr_span) - | RegionNameSource::AnonRegionFromUpvar(fr_span, _) - | RegionNameSource::AnonRegionFromOutput(fr_span, _, _) => { - diag.span_label(fr_span, "inferred to be a `FnMut` closure"); - } - _ => {} + if let Some(fr_span) = self.give_region_a_name(*outlived_fr).unwrap().span() { + diag.span_label(fr_span, "inferred to be a `FnMut` closure"); } diag.note( diff --git a/src/librustc_mir/borrow_check/diagnostics/region_name.rs b/src/librustc_mir/borrow_check/diagnostics/region_name.rs index 2240eb81e1fa7..32195adc60ef8 100644 --- a/src/librustc_mir/borrow_check/diagnostics/region_name.rs +++ b/src/librustc_mir/borrow_check/diagnostics/region_name.rs @@ -34,13 +34,8 @@ crate enum RegionNameSource { Static, /// The free region corresponding to the environment of a closure. SynthesizedFreeEnvRegion(Span, String), - /// The region name corresponds to a region where the type annotation is completely missing - /// from the code, e.g. in a closure arguments `|x| { ... }`, where `x` is a reference. - CannotMatchHirTy(Span, String), - /// The region name corresponds a reference that was found by traversing the type in the HIR. - MatchedHirTy(Span), - /// A region name from the generics list of a struct/enum/union. - MatchedAdtAndSegment(Span), + /// The region corresponding to an argument. + AnonRegionFromArgument(RegionNameHighlight), /// The region corresponding to a closure upvar. AnonRegionFromUpvar(Span, String), /// The region corresponding to the return type of a closure. @@ -51,6 +46,19 @@ crate enum RegionNameSource { AnonRegionFromAsyncFn(Span), } +/// Describes what to highlight to explain to the user that we're giving an anonymous region a +/// synthesized name, and how to highlight it. +#[derive(Debug, Clone)] +crate enum RegionNameHighlight { + /// The anonymous region corresponds to a reference that was found by traversing the type in the HIR. + MatchedHirTy(Span), + /// The anonymous region corresponds to a `'_` in the generics list of a struct/enum/union. + MatchedAdtAndSegment(Span), + /// The anonymous region corresponds to a region where the type annotation is completely missing + /// from the code, e.g. in a closure arguments `|x| { ... }`, where `x` is a reference. + CannotMatchHirTy(Span, String), +} + impl RegionName { crate fn was_named(&self) -> bool { match self.source { @@ -58,9 +66,7 @@ impl RegionName { | RegionNameSource::NamedFreeRegion(..) | RegionNameSource::Static => true, RegionNameSource::SynthesizedFreeEnvRegion(..) - | RegionNameSource::CannotMatchHirTy(..) - | RegionNameSource::MatchedHirTy(..) - | RegionNameSource::MatchedAdtAndSegment(..) + | RegionNameSource::AnonRegionFromArgument(..) | RegionNameSource::AnonRegionFromUpvar(..) | RegionNameSource::AnonRegionFromOutput(..) | RegionNameSource::AnonRegionFromYieldTy(..) @@ -68,6 +74,24 @@ impl RegionName { } } + crate fn span(&self) -> Option { + match self.source { + RegionNameSource::Static => None, + RegionNameSource::NamedEarlyBoundRegion(span) + | RegionNameSource::NamedFreeRegion(span) + | RegionNameSource::SynthesizedFreeEnvRegion(span, _) + | RegionNameSource::AnonRegionFromUpvar(span, _) + | RegionNameSource::AnonRegionFromOutput(span, _, _) + | RegionNameSource::AnonRegionFromYieldTy(span, _) + | RegionNameSource::AnonRegionFromAsyncFn(span) => Some(span), + RegionNameSource::AnonRegionFromArgument(ref highlight) => match *highlight { + RegionNameHighlight::MatchedHirTy(span) + | RegionNameHighlight::MatchedAdtAndSegment(span) + | RegionNameHighlight::CannotMatchHirTy(span, _) => Some(span), + }, + } + } + crate fn highlight_region_name(&self, diag: &mut DiagnosticBuilder<'_>) { match &self.source { RegionNameSource::NamedFreeRegion(span) @@ -81,17 +105,22 @@ impl RegionName { ); diag.note(¬e); } - RegionNameSource::CannotMatchHirTy(span, type_name) => { + RegionNameSource::AnonRegionFromArgument(RegionNameHighlight::CannotMatchHirTy( + span, + type_name, + )) => { diag.span_label(*span, format!("has type `{}`", type_name)); } - RegionNameSource::MatchedHirTy(span) + RegionNameSource::AnonRegionFromArgument(RegionNameHighlight::MatchedHirTy(span)) | RegionNameSource::AnonRegionFromAsyncFn(span) => { diag.span_label( *span, format!("let's call the lifetime of this reference `{}`", self), ); } - RegionNameSource::MatchedAdtAndSegment(span) => { + RegionNameSource::AnonRegionFromArgument( + RegionNameHighlight::MatchedAdtAndSegment(span), + ) => { diag.span_label(*span, format!("let's call this `{}`", self)); } RegionNameSource::AnonRegionFromUpvar(span, upvar_name) => { @@ -307,21 +336,31 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { let arg_ty = self.regioncx.universal_regions().unnormalized_input_tys [implicit_inputs + argument_index]; - if let Some(region_name) = - self.give_name_if_we_can_match_hir_ty_from_argument(fr, arg_ty, argument_index) - { - return Some(region_name); - } + let (_, span) = self.regioncx.get_argument_name_and_span_for_region( + &self.body, + &self.local_names, + argument_index, + ); - self.give_name_if_we_cannot_match_hir_ty(fr, arg_ty) + self.get_argument_hir_ty_for_highlighting(argument_index) + .and_then(|arg_hir_ty| self.highlight_if_we_can_match_hir_ty(fr, arg_ty, arg_hir_ty)) + .or_else(|| { + // `highlight_if_we_cannot_match_hir_ty` needs to know the number we will give to + // the anonymous region. If it succeeds, the `synthesize_region_name` call below + // will increment the counter, "reserving" the number we just used. + let counter = *self.next_region_name.try_borrow().unwrap(); + self.highlight_if_we_cannot_match_hir_ty(fr, arg_ty, span, counter) + }) + .map(|highlight| RegionName { + name: self.synthesize_region_name(), + source: RegionNameSource::AnonRegionFromArgument(highlight), + }) } - fn give_name_if_we_can_match_hir_ty_from_argument( + fn get_argument_hir_ty_for_highlighting( &self, - needle_fr: RegionVid, - argument_ty: Ty<'tcx>, argument_index: usize, - ) -> Option { + ) -> Option<&hir::Ty<'tcx>> { let mir_hir_id = self.infcx.tcx.hir().as_local_hir_id(self.mir_def_id); let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(mir_hir_id)?; let argument_hir_ty: &hir::Ty<'_> = fn_decl.inputs.get(argument_index)?; @@ -333,7 +372,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { // (`give_name_if_anonymous_region_appears_in_arguments`). hir::TyKind::Infer => None, - _ => self.give_name_if_we_can_match_hir_ty(needle_fr, argument_ty, argument_hir_ty), + _ => Some(argument_hir_ty), } } @@ -348,42 +387,28 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { /// | | has type `&'1 u32` /// | has type `&'2 u32` /// ``` - fn give_name_if_we_cannot_match_hir_ty( + fn highlight_if_we_cannot_match_hir_ty( &self, needle_fr: RegionVid, - argument_ty: Ty<'tcx>, - ) -> Option { - let counter = *self.next_region_name.try_borrow().unwrap(); + ty: Ty<'tcx>, + span: Span, + counter: usize, + ) -> Option { let mut highlight = RegionHighlightMode::default(); highlight.highlighting_region_vid(needle_fr, counter); - let type_name = self.infcx.extract_type_name(&argument_ty, Some(highlight)).0; + let type_name = self.infcx.extract_type_name(&ty, Some(highlight)).0; debug!( - "give_name_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}", + "highlight_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}", type_name, needle_fr ); - let assigned_region_name = if type_name.find(&format!("'{}", counter)).is_some() { + if type_name.find(&format!("'{}", counter)).is_some() { // Only add a label if we can confirm that a region was labelled. - let argument_index = - self.regioncx.get_argument_index_for_region(self.infcx.tcx, needle_fr)?; - let (_, span) = self.regioncx.get_argument_name_and_span_for_region( - &self.body, - &self.local_names, - argument_index, - ); - - Some(RegionName { - // This counter value will already have been used, so this function will increment - // it so the next value will be used next and return the region name that would - // have been used. - name: self.synthesize_region_name(), - source: RegionNameSource::CannotMatchHirTy(span, type_name), - }) + + Some(RegionNameHighlight::CannotMatchHirTy(span, type_name)) } else { None - }; - - assigned_region_name + } } /// Attempts to highlight the specific part of a type annotation @@ -395,9 +420,9 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { /// | - let's call the lifetime of this reference `'1` /// ``` /// - /// the way this works is that we match up `argument_ty`, which is + /// the way this works is that we match up `ty`, which is /// a `Ty<'tcx>` (the internal form of the type) with - /// `argument_hir_ty`, a `hir::Ty` (the syntax of the type + /// `hir_ty`, a `hir::Ty` (the syntax of the type /// annotation). We are descending through the types stepwise, /// looking in to find the region `needle_fr` in the internal /// type. Once we find that, we can use the span of the `hir::Ty` @@ -407,18 +432,17 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { /// keep track of the **closest** type we've found. If we fail to /// find the exact `&` or `'_` to highlight, then we may fall back /// to highlighting that closest type instead. - fn give_name_if_we_can_match_hir_ty( + fn highlight_if_we_can_match_hir_ty( &self, needle_fr: RegionVid, - argument_ty: Ty<'tcx>, - argument_hir_ty: &hir::Ty<'_>, - ) -> Option { - let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty<'_>)> = - &mut vec![(argument_ty, argument_hir_ty)]; + ty: Ty<'tcx>, + hir_ty: &hir::Ty<'_>, + ) -> Option { + let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty<'_>)> = &mut vec![(ty, hir_ty)]; while let Some((ty, hir_ty)) = search_stack.pop() { match (&ty.kind, &hir_ty.kind) { - // Check if the `argument_ty` is `&'X ..` where `'X` + // Check if the `ty` is `&'X ..` where `'X` // is the region we are looking for -- if so, and we have a `&T` // on the RHS, then we want to highlight the `&` like so: // @@ -429,16 +453,11 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { hir::TyKind::Rptr(_lifetime, referent_hir_ty), ) => { if region.to_region_vid() == needle_fr { - let region_name = self.synthesize_region_name(); - // Just grab the first character, the `&`. let source_map = self.infcx.tcx.sess.source_map(); let ampersand_span = source_map.start_point(hir_ty.span); - return Some(RegionName { - name: region_name, - source: RegionNameSource::MatchedHirTy(ampersand_span), - }); + return Some(RegionNameHighlight::MatchedHirTy(ampersand_span)); } // Otherwise, let's descend into the referent types. @@ -458,13 +477,13 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { Res::Def(DefKind::TyAlias, _) => (), _ => { if let Some(last_segment) = path.segments.last() { - if let Some(name) = self.match_adt_and_segment( + if let Some(highlight) = self.match_adt_and_segment( substs, needle_fr, last_segment, search_stack, ) { - return Some(name); + return Some(highlight); } } } @@ -507,7 +526,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { needle_fr: RegionVid, last_segment: &'hir hir::PathSegment<'hir>, search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty<'hir>)>, - ) -> Option { + ) -> Option { // Did the user give explicit arguments? (e.g., `Foo<..>`) let args = last_segment.args.as_ref()?; let lifetime = @@ -517,12 +536,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { | hir::LifetimeName::Error | hir::LifetimeName::Static | hir::LifetimeName::Underscore => { - let region_name = self.synthesize_region_name(); - let ampersand_span = lifetime.span; - Some(RegionName { - name: region_name, - source: RegionNameSource::MatchedAdtAndSegment(ampersand_span), - }) + let lifetime_span = lifetime.span; + Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime_span)) } hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Implicit => { diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 3073bf53afd78..b3dedd5b8223e 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -28,9 +28,9 @@ use rustc_trait_selection::traits; use crate::const_eval::error_to_const_error; use crate::interpret::{ - self, compile_time_machine, AllocId, Allocation, Frame, ImmTy, Immediate, InterpCx, LocalState, - LocalValue, MemPlace, Memory, MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, Pointer, - ScalarMaybeUninit, StackPopCleanup, + self, compile_time_machine, truncate, AllocId, Allocation, Frame, ImmTy, Immediate, InterpCx, + LocalState, LocalValue, MemPlace, Memory, MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, + Pointer, ScalarMaybeUninit, StackPopCleanup, }; use crate::transform::{MirPass, MirSource}; @@ -527,11 +527,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { right: &Operand<'tcx>, source_info: SourceInfo, ) -> Option<()> { - let r = - self.use_ecx(|this| this.ecx.read_immediate(this.ecx.eval_operand(right, None)?))?; + let r = self.use_ecx(|this| this.ecx.read_immediate(this.ecx.eval_operand(right, None)?)); let l = self.use_ecx(|this| this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)); // Check for exceeding shifts *even if* we cannot evaluate the LHS. if op == BinOp::Shr || op == BinOp::Shl { + let r = r?; // We need the type of the LHS. We cannot use `place_layout` as that is the type // of the result, which for checked binops is not the same! let left_ty = left.ty(&self.local_decls, self.tcx); @@ -564,21 +564,20 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } } - let l = l?; - - // The remaining operators are handled through `overflowing_binary_op`. - if self.use_ecx(|this| { - let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?; - Ok(overflow) - })? { - self.report_assert_as_lint( - lint::builtin::ARITHMETIC_OVERFLOW, - source_info, - "this arithmetic operation will overflow", - AssertKind::Overflow(op, l.to_const_int(), r.to_const_int()), - )?; + if let (Some(l), Some(r)) = (l, r) { + // The remaining operators are handled through `overflowing_binary_op`. + if self.use_ecx(|this| { + let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?; + Ok(overflow) + })? { + self.report_assert_as_lint( + lint::builtin::ARITHMETIC_OVERFLOW, + source_info, + "this arithmetic operation will overflow", + AssertKind::Overflow(op, l.to_const_int(), r.to_const_int()), + )?; + } } - Some(()) } @@ -659,9 +658,74 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { return None; } + if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 3 { + self.eval_rvalue_with_identities(rvalue, place) + } else { + self.use_ecx(|this| this.ecx.eval_rvalue_into_place(rvalue, place)) + } + } + + // Attempt to use albegraic identities to eliminate constant expressions + fn eval_rvalue_with_identities( + &mut self, + rvalue: &Rvalue<'tcx>, + place: Place<'tcx>, + ) -> Option<()> { self.use_ecx(|this| { - trace!("calling eval_rvalue_into_place(rvalue = {:?}, place = {:?})", rvalue, place); - this.ecx.eval_rvalue_into_place(rvalue, place)?; + match rvalue { + Rvalue::BinaryOp(op, left, right) | Rvalue::CheckedBinaryOp(op, left, right) => { + let l = this.ecx.eval_operand(left, None); + let r = this.ecx.eval_operand(right, None); + + let const_arg = match (l, r) { + (Ok(x), Err(_)) | (Err(_), Ok(x)) => this.ecx.read_immediate(x)?, + (Err(e), Err(_)) => return Err(e), + (Ok(_), Ok(_)) => { + this.ecx.eval_rvalue_into_place(rvalue, place)?; + return Ok(()); + } + }; + + let arg_value = + this.ecx.force_bits(const_arg.to_scalar()?, const_arg.layout.size)?; + let dest = this.ecx.eval_place(place)?; + + match op { + BinOp::BitAnd => { + if arg_value == 0 { + this.ecx.write_immediate(*const_arg, dest)?; + } + } + BinOp::BitOr => { + if arg_value == truncate(u128::MAX, const_arg.layout.size) + || (const_arg.layout.ty.is_bool() && arg_value == 1) + { + this.ecx.write_immediate(*const_arg, dest)?; + } + } + BinOp::Mul => { + if const_arg.layout.ty.is_integral() && arg_value == 0 { + if let Rvalue::CheckedBinaryOp(_, _, _) = rvalue { + let val = Immediate::ScalarPair( + const_arg.to_scalar()?.into(), + Scalar::from_bool(false).into(), + ); + this.ecx.write_immediate(val, dest)?; + } else { + this.ecx.write_immediate(*const_arg, dest)?; + } + } + } + _ => { + this.ecx.eval_rvalue_into_place(rvalue, place)?; + } + } + } + _ => { + this.ecx.eval_rvalue_into_place(rvalue, place)?; + } + } + Ok(()) }) } diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 261c2031364f6..4b5ab03df4327 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -1506,18 +1506,24 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { pat.walk(&mut |pat| { debug!("resolve_pattern pat={:?} node={:?}", pat, pat.kind); match pat.kind { - // In tuple struct patterns ignore the invalid `ident @ ...`. - // It will be handled as an error by the AST lowering. - PatKind::Ident(bmode, ident, ref sub) - if !(is_tuple_struct_pat && sub.as_ref().filter(|p| p.is_rest()).is_some()) => - { - // First try to resolve the identifier as some existing entity, - // then fall back to a fresh binding. - let has_sub = sub.is_some(); - let res = self - .try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub) - .unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings)); - self.r.record_partial_res(pat.id, PartialRes::new(res)); + PatKind::Ident(bmode, ident, ref sub) => { + if is_tuple_struct_pat && sub.as_ref().filter(|p| p.is_rest()).is_some() { + // In tuple struct patterns ignore the invalid `ident @ ...`. + // It will be handled as an error by the AST lowering. + self.r + .session + .delay_span_bug(ident.span, "ident in tuple pattern is invalid"); + } else { + // First try to resolve the identifier as some existing entity, + // then fall back to a fresh binding. + let has_sub = sub.is_some(); + let res = self + .try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub) + .unwrap_or_else(|| { + self.fresh_binding(ident, pat.id, pat_src, bindings) + }); + self.r.record_partial_res(pat.id, PartialRes::new(res)); + } } PatKind::TupleStruct(ref path, ..) => { self.smart_resolve_path(pat.id, None, path, PathSource::TupleStruct(pat.span)); diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 8138dfa580d80..2c1e71c64c4e5 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -40,7 +40,7 @@ dlmalloc = { version = "0.1", features = ['rustc-dep-of-std'] } fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] } [target.'cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_os = "hermit"))'.dependencies] -hermit-abi = { version = "0.1.14", features = ['rustc-dep-of-std'] } +hermit-abi = { version = "0.1.15", features = ['rustc-dep-of-std'] } [target.wasm32-wasi.dependencies] wasi = { version = "0.9.0", features = ['rustc-dep-of-std'], default-features = false } diff --git a/src/libstd/sys/hermit/condvar.rs b/src/libstd/sys/hermit/condvar.rs index 132e579b3a5cb..52c8c3b17e826 100644 --- a/src/libstd/sys/hermit/condvar.rs +++ b/src/libstd/sys/hermit/condvar.rs @@ -1,60 +1,64 @@ -use crate::cmp; +use crate::ffi::c_void; +use crate::ptr; +use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst}; use crate::sys::hermit::abi; use crate::sys::mutex::Mutex; use crate::time::Duration; +// The implementation is inspired by Andrew D. Birrell's paper +// "Implementing Condition Variables with Semaphores" + pub struct Condvar { - identifier: usize, + counter: AtomicUsize, + sem1: *const c_void, + sem2: *const c_void, } +unsafe impl Send for Condvar {} +unsafe impl Sync for Condvar {} + impl Condvar { pub const fn new() -> Condvar { - Condvar { identifier: 0 } + Condvar { counter: AtomicUsize::new(0), sem1: ptr::null(), sem2: ptr::null() } } pub unsafe fn init(&mut self) { - let _ = abi::init_queue(self.id()); + let _ = abi::sem_init(&mut self.sem1 as *mut *const c_void, 0); + let _ = abi::sem_init(&mut self.sem2 as *mut *const c_void, 0); } pub unsafe fn notify_one(&self) { - let _ = abi::notify(self.id(), 1); + if self.counter.load(SeqCst) > 0 { + self.counter.fetch_sub(1, SeqCst); + abi::sem_post(self.sem1); + abi::sem_timedwait(self.sem2, 0); + } } - #[inline] pub unsafe fn notify_all(&self) { - let _ = abi::notify(self.id(), -1 /* =all */); + let counter = self.counter.swap(0, SeqCst); + for _ in 0..counter { + abi::sem_post(self.sem1); + } + for _ in 0..counter { + abi::sem_timedwait(self.sem2, 0); + } } pub unsafe fn wait(&self, mutex: &Mutex) { - // add current task to the wait queue - let _ = abi::add_queue(self.id(), -1 /* no timeout */); + self.counter.fetch_add(1, SeqCst); mutex.unlock(); - let _ = abi::wait(self.id()); + abi::sem_timedwait(self.sem1, 0); + abi::sem_post(self.sem2); mutex.lock(); } - pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { - let nanos = dur.as_nanos(); - let nanos = cmp::min(i64::MAX as u128, nanos); - - // add current task to the wait queue - let _ = abi::add_queue(self.id(), nanos as i64); - - mutex.unlock(); - // If the return value is !0 then a timeout happened, so we return - // `false` as we weren't actually notified. - let ret = abi::wait(self.id()) == 0; - mutex.lock(); - - ret + pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool { + panic!("wait_timeout not supported on hermit"); } pub unsafe fn destroy(&self) { - let _ = abi::destroy_queue(self.id()); - } - - #[inline] - fn id(&self) -> usize { - &self.identifier as *const usize as usize + let _ = abi::sem_destroy(self.sem1); + let _ = abi::sem_destroy(self.sem2); } } diff --git a/src/libstd/sys/hermit/rwlock.rs b/src/libstd/sys/hermit/rwlock.rs index c19799af3c7ee..06442e925f4c8 100644 --- a/src/libstd/sys/hermit/rwlock.rs +++ b/src/libstd/sys/hermit/rwlock.rs @@ -1,49 +1,144 @@ -use super::mutex::Mutex; +use crate::cell::UnsafeCell; +use crate::sys::condvar::Condvar; +use crate::sys::mutex::Mutex; pub struct RWLock { - mutex: Mutex, + lock: Mutex, + cond: Condvar, + state: UnsafeCell, +} + +enum State { + Unlocked, + Reading(usize), + Writing, } unsafe impl Send for RWLock {} unsafe impl Sync for RWLock {} +// This rwlock implementation is a relatively simple implementation which has a +// condition variable for readers/writers as well as a mutex protecting the +// internal state of the lock. A current downside of the implementation is that +// unlocking the lock will notify *all* waiters rather than just readers or just +// writers. This can cause lots of "thundering stampede" problems. While +// hopefully correct this implementation is very likely to want to be changed in +// the future. + impl RWLock { pub const fn new() -> RWLock { - RWLock { mutex: Mutex::new() } + RWLock { lock: Mutex::new(), cond: Condvar::new(), state: UnsafeCell::new(State::Unlocked) } } #[inline] pub unsafe fn read(&self) { - self.mutex.lock(); + self.lock.lock(); + while !(*self.state.get()).inc_readers() { + self.cond.wait(&self.lock); + } + self.lock.unlock(); } #[inline] pub unsafe fn try_read(&self) -> bool { - self.mutex.try_lock() + self.lock.lock(); + let ok = (*self.state.get()).inc_readers(); + self.lock.unlock(); + return ok; } #[inline] pub unsafe fn write(&self) { - self.mutex.lock(); + self.lock.lock(); + while !(*self.state.get()).inc_writers() { + self.cond.wait(&self.lock); + } + self.lock.unlock(); } #[inline] pub unsafe fn try_write(&self) -> bool { - self.mutex.try_lock() + self.lock.lock(); + let ok = (*self.state.get()).inc_writers(); + self.lock.unlock(); + return ok; } #[inline] pub unsafe fn read_unlock(&self) { - self.mutex.unlock(); + self.lock.lock(); + let notify = (*self.state.get()).dec_readers(); + self.lock.unlock(); + if notify { + // FIXME: should only wake up one of these some of the time + self.cond.notify_all(); + } } #[inline] pub unsafe fn write_unlock(&self) { - self.mutex.unlock(); + self.lock.lock(); + (*self.state.get()).dec_writers(); + self.lock.unlock(); + // FIXME: should only wake up one of these some of the time + self.cond.notify_all(); } #[inline] pub unsafe fn destroy(&self) { - self.mutex.destroy(); + self.lock.destroy(); + self.cond.destroy(); + } +} + +impl State { + fn inc_readers(&mut self) -> bool { + match *self { + State::Unlocked => { + *self = State::Reading(1); + true + } + State::Reading(ref mut cnt) => { + *cnt += 1; + true + } + State::Writing => false, + } + } + + fn inc_writers(&mut self) -> bool { + match *self { + State::Unlocked => { + *self = State::Writing; + true + } + State::Reading(_) | State::Writing => false, + } + } + + fn dec_readers(&mut self) -> bool { + let zero = match *self { + State::Reading(ref mut cnt) => { + *cnt -= 1; + *cnt == 0 + } + State::Unlocked | State::Writing => invalid(), + }; + if zero { + *self = State::Unlocked; + } + zero } + + fn dec_writers(&mut self) { + match *self { + State::Writing => {} + State::Unlocked | State::Reading(_) => invalid(), + } + *self = State::Unlocked; + } +} + +fn invalid() -> ! { + panic!("inconsistent rwlock"); } diff --git a/src/test/mir-opt/const_prop/boolean_identities.rs b/src/test/mir-opt/const_prop/boolean_identities.rs new file mode 100644 index 0000000000000..4e09acbaa53b4 --- /dev/null +++ b/src/test/mir-opt/const_prop/boolean_identities.rs @@ -0,0 +1,10 @@ +// compile-flags: -O -Zmir-opt-level=3 + +// EMIT_MIR rustc.test.ConstProp.diff +pub fn test(x: bool, y: bool) -> bool { + (y | true) & (x & false) +} + +fn main() { + test(true, false); +} diff --git a/src/test/mir-opt/const_prop/boolean_identities/rustc.test.ConstProp.diff b/src/test/mir-opt/const_prop/boolean_identities/rustc.test.ConstProp.diff new file mode 100644 index 0000000000000..b8f0ad4d434cb --- /dev/null +++ b/src/test/mir-opt/const_prop/boolean_identities/rustc.test.ConstProp.diff @@ -0,0 +1,53 @@ +- // MIR for `test` before ConstProp ++ // MIR for `test` after ConstProp + + fn test(_1: bool, _2: bool) -> bool { + debug x => _1; // in scope 0 at $DIR/boolean_identities.rs:4:13: 4:14 + debug y => _2; // in scope 0 at $DIR/boolean_identities.rs:4:22: 4:23 + let mut _0: bool; // return place in scope 0 at $DIR/boolean_identities.rs:4:34: 4:38 + let mut _3: bool; // in scope 0 at $DIR/boolean_identities.rs:5:5: 5:15 + let mut _4: bool; // in scope 0 at $DIR/boolean_identities.rs:5:6: 5:7 + let mut _5: bool; // in scope 0 at $DIR/boolean_identities.rs:5:18: 5:29 + let mut _6: bool; // in scope 0 at $DIR/boolean_identities.rs:5:19: 5:20 + + bb0: { + StorageLive(_3); // scope 0 at $DIR/boolean_identities.rs:5:5: 5:15 + StorageLive(_4); // scope 0 at $DIR/boolean_identities.rs:5:6: 5:7 + _4 = _2; // scope 0 at $DIR/boolean_identities.rs:5:6: 5:7 +- _3 = BitOr(move _4, const true); // scope 0 at $DIR/boolean_identities.rs:5:5: 5:15 ++ _3 = const true; // scope 0 at $DIR/boolean_identities.rs:5:5: 5:15 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x01)) + // mir::Constant +- // + span: $DIR/boolean_identities.rs:5:10: 5:14 ++ // + span: $DIR/boolean_identities.rs:5:5: 5:15 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } + StorageDead(_4); // scope 0 at $DIR/boolean_identities.rs:5:14: 5:15 + StorageLive(_5); // scope 0 at $DIR/boolean_identities.rs:5:18: 5:29 + StorageLive(_6); // scope 0 at $DIR/boolean_identities.rs:5:19: 5:20 + _6 = _1; // scope 0 at $DIR/boolean_identities.rs:5:19: 5:20 +- _5 = BitAnd(move _6, const false); // scope 0 at $DIR/boolean_identities.rs:5:18: 5:29 ++ _5 = const false; // scope 0 at $DIR/boolean_identities.rs:5:18: 5:29 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x00)) + // mir::Constant +- // + span: $DIR/boolean_identities.rs:5:23: 5:28 ++ // + span: $DIR/boolean_identities.rs:5:18: 5:29 + // + literal: Const { ty: bool, val: Value(Scalar(0x00)) } + StorageDead(_6); // scope 0 at $DIR/boolean_identities.rs:5:28: 5:29 +- _0 = BitAnd(move _3, move _5); // scope 0 at $DIR/boolean_identities.rs:5:5: 5:29 ++ _0 = const false; // scope 0 at $DIR/boolean_identities.rs:5:5: 5:29 ++ // ty::Const ++ // + ty: bool ++ // + val: Value(Scalar(0x00)) ++ // mir::Constant ++ // + span: $DIR/boolean_identities.rs:5:5: 5:29 ++ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) } + StorageDead(_5); // scope 0 at $DIR/boolean_identities.rs:5:28: 5:29 + StorageDead(_3); // scope 0 at $DIR/boolean_identities.rs:5:28: 5:29 + return; // scope 0 at $DIR/boolean_identities.rs:6:2: 6:2 + } + } + diff --git a/src/test/mir-opt/const_prop/mult_by_zero.rs b/src/test/mir-opt/const_prop/mult_by_zero.rs new file mode 100644 index 0000000000000..f40faee3110ae --- /dev/null +++ b/src/test/mir-opt/const_prop/mult_by_zero.rs @@ -0,0 +1,10 @@ +// compile-flags: -O -Zmir-opt-level=3 + +// EMIT_MIR rustc.test.ConstProp.diff +fn test(x : i32) -> i32 { + x * 0 +} + +fn main() { + test(10); +} diff --git a/src/test/mir-opt/const_prop/mult_by_zero/rustc.test.ConstProp.diff b/src/test/mir-opt/const_prop/mult_by_zero/rustc.test.ConstProp.diff new file mode 100644 index 0000000000000..7b36669bf15b2 --- /dev/null +++ b/src/test/mir-opt/const_prop/mult_by_zero/rustc.test.ConstProp.diff @@ -0,0 +1,25 @@ +- // MIR for `test` before ConstProp ++ // MIR for `test` after ConstProp + + fn test(_1: i32) -> i32 { + debug x => _1; // in scope 0 at $DIR/mult_by_zero.rs:4:9: 4:10 + let mut _0: i32; // return place in scope 0 at $DIR/mult_by_zero.rs:4:21: 4:24 + let mut _2: i32; // in scope 0 at $DIR/mult_by_zero.rs:5:3: 5:4 + + bb0: { + StorageLive(_2); // scope 0 at $DIR/mult_by_zero.rs:5:3: 5:4 + _2 = _1; // scope 0 at $DIR/mult_by_zero.rs:5:3: 5:4 +- _0 = Mul(move _2, const 0_i32); // scope 0 at $DIR/mult_by_zero.rs:5:3: 5:8 ++ _0 = const 0_i32; // scope 0 at $DIR/mult_by_zero.rs:5:3: 5:8 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000000)) + // mir::Constant +- // + span: $DIR/mult_by_zero.rs:5:7: 5:8 ++ // + span: $DIR/mult_by_zero.rs:5:3: 5:8 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) } + StorageDead(_2); // scope 0 at $DIR/mult_by_zero.rs:5:7: 5:8 + return; // scope 0 at $DIR/mult_by_zero.rs:6:2: 6:2 + } + } + diff --git a/src/test/mir-opt/match-arm-scopes.rs b/src/test/mir-opt/match-arm-scopes.rs index 0e30a15671528..2c5816c51e3e2 100644 --- a/src/test/mir-opt/match-arm-scopes.rs +++ b/src/test/mir-opt/match-arm-scopes.rs @@ -9,8 +9,7 @@ // all of the bindings for that scope. // * No drop flags are used. -// EMIT_MIR rustc.complicated_match.SimplifyCfg-initial.after.mir -// EMIT_MIR rustc.complicated_match.ElaborateDrops.after.mir +// EMIT_MIR rustc.complicated_match SimplifyCfg-initial.after ElaborateDrops.after fn complicated_match(cond: bool, items: (bool, bool, String)) -> i32 { match items { (false, a, s) | (a, false, s) if if cond { return 3 } else { a } => 1, diff --git a/src/test/mir-opt/match-arm-scopes/rustc.complicated_match.ElaborateDrops.after.mir b/src/test/mir-opt/match-arm-scopes/rustc.complicated_match.ElaborateDrops.after.mir deleted file mode 100644 index df6a247bb5ff6..0000000000000 --- a/src/test/mir-opt/match-arm-scopes/rustc.complicated_match.ElaborateDrops.after.mir +++ /dev/null @@ -1,235 +0,0 @@ -// MIR for `complicated_match` after ElaborateDrops - -fn complicated_match(_1: bool, _2: (bool, bool, std::string::String)) -> i32 { - debug cond => _1; // in scope 0 at $DIR/match-arm-scopes.rs:14:22: 14:26 - debug items => _2; // in scope 0 at $DIR/match-arm-scopes.rs:14:34: 14:39 - let mut _0: i32; // return place in scope 0 at $DIR/match-arm-scopes.rs:14:66: 14:69 - let mut _3: &bool; // in scope 0 at $DIR/match-arm-scopes.rs:15:11: 15:16 - let mut _4: &bool; // in scope 0 at $DIR/match-arm-scopes.rs:15:11: 15:16 - let _5: bool; // in scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18 - let _6: &bool; // in scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18 - let _7: std::string::String; // in scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21 - let _8: &std::string::String; // in scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21 - let mut _9: bool; // in scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73 - let mut _10: bool; // in scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49 - let mut _11: !; // in scope 0 at $DIR/match-arm-scopes.rs:16:52: 16:60 - let mut _12: bool; // in scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73 - let mut _13: bool; // in scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49 - let mut _14: !; // in scope 0 at $DIR/match-arm-scopes.rs:16:52: 16:60 - let _15: bool; // in scope 0 at $DIR/match-arm-scopes.rs:17:16: 17:17 - let _16: std::string::String; // in scope 0 at $DIR/match-arm-scopes.rs:17:19: 17:20 - scope 1 { - debug a => _5; // in scope 1 at $DIR/match-arm-scopes.rs:16:17: 16:18 - debug a => _6; // in scope 1 at $DIR/match-arm-scopes.rs:16:17: 16:18 - debug s => _7; // in scope 1 at $DIR/match-arm-scopes.rs:16:20: 16:21 - debug s => _8; // in scope 1 at $DIR/match-arm-scopes.rs:16:20: 16:21 - } - scope 2 { - debug b => _15; // in scope 2 at $DIR/match-arm-scopes.rs:17:16: 17:17 - debug t => _16; // in scope 2 at $DIR/match-arm-scopes.rs:17:19: 17:20 - } - - bb0: { - switchInt((_2.0: bool)) -> [false: bb6, otherwise: bb2]; // scope 0 at $DIR/match-arm-scopes.rs:16:10: 16:15 - } - - bb1 (cleanup): { - resume; // scope 0 at $DIR/match-arm-scopes.rs:14:1: 19:2 - } - - bb2: { - switchInt((_2.1: bool)) -> [false: bb14, otherwise: bb3]; // scope 0 at $DIR/match-arm-scopes.rs:16:29: 16:34 - } - - bb3: { - switchInt((_2.0: bool)) -> [false: bb4, otherwise: bb21]; // scope 0 at $DIR/match-arm-scopes.rs:17:10: 17:14 - } - - bb4: { - StorageLive(_15); // scope 0 at $DIR/match-arm-scopes.rs:17:32: 17:33 - _15 = (_2.1: bool); // scope 0 at $DIR/match-arm-scopes.rs:17:32: 17:33 - StorageLive(_16); // scope 0 at $DIR/match-arm-scopes.rs:17:35: 17:36 - _16 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:17:35: 17:36 - goto -> bb20; // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6 - } - - bb5: { - _0 = const 1_i32; // scope 1 at $DIR/match-arm-scopes.rs:16:77: 16:78 - // ty::Const - // + ty: i32 - // + val: Value(Scalar(0x00000001)) - // mir::Constant - // + span: $DIR/match-arm-scopes.rs:16:77: 16:78 - // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } - drop(_7) -> [return: bb19, unwind: bb10]; // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - } - - bb6: { - StorageLive(_6); // scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18 - _6 = &(_2.1: bool); // scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18 - StorageLive(_8); // scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21 - _8 = &(_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21 - StorageLive(_9); // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73 - StorageLive(_10); // scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49 - _10 = _1; // scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49 - switchInt(_10) -> [false: bb7, otherwise: bb8]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73 - } - - bb7: { - _9 = (*_6); // scope 0 at $DIR/match-arm-scopes.rs:16:70: 16:71 - StorageDead(_10); // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73 - switchInt(move _9) -> [false: bb13, otherwise: bb12]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73 - } - - bb8: { - _0 = const 3_i32; // scope 0 at $DIR/match-arm-scopes.rs:16:59: 16:60 - // ty::Const - // + ty: i32 - // + val: Value(Scalar(0x00000003)) - // mir::Constant - // + span: $DIR/match-arm-scopes.rs:16:59: 16:60 - // + literal: Const { ty: i32, val: Value(Scalar(0x00000003)) } - StorageDead(_10); // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73 - StorageDead(_9); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageDead(_8); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageDead(_6); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - goto -> bb11; // scope 0 at $DIR/match-arm-scopes.rs:16:52: 16:60 - } - - bb9: { - return; // scope 0 at $DIR/match-arm-scopes.rs:19:2: 19:2 - } - - bb10 (cleanup): { - goto -> bb25; // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2 - } - - bb11: { - drop(_2) -> [return: bb9, unwind: bb1]; // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2 - } - - bb12: { - StorageDead(_9); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageLive(_5); // scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18 - _5 = (_2.1: bool); // scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18 - StorageLive(_7); // scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21 - _7 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21 - goto -> bb5; // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6 - } - - bb13: { - StorageDead(_9); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageDead(_8); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageDead(_6); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - goto -> bb2; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73 - } - - bb14: { - StorageLive(_6); // scope 0 at $DIR/match-arm-scopes.rs:16:26: 16:27 - _6 = &(_2.0: bool); // scope 0 at $DIR/match-arm-scopes.rs:16:26: 16:27 - StorageLive(_8); // scope 0 at $DIR/match-arm-scopes.rs:16:36: 16:37 - _8 = &(_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:16:36: 16:37 - StorageLive(_12); // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73 - StorageLive(_13); // scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49 - _13 = _1; // scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49 - switchInt(_13) -> [false: bb15, otherwise: bb16]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73 - } - - bb15: { - _12 = (*_6); // scope 0 at $DIR/match-arm-scopes.rs:16:70: 16:71 - StorageDead(_13); // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73 - switchInt(move _12) -> [false: bb18, otherwise: bb17]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73 - } - - bb16: { - _0 = const 3_i32; // scope 0 at $DIR/match-arm-scopes.rs:16:59: 16:60 - // ty::Const - // + ty: i32 - // + val: Value(Scalar(0x00000003)) - // mir::Constant - // + span: $DIR/match-arm-scopes.rs:16:59: 16:60 - // + literal: Const { ty: i32, val: Value(Scalar(0x00000003)) } - StorageDead(_13); // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73 - StorageDead(_12); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageDead(_8); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageDead(_6); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - goto -> bb11; // scope 0 at $DIR/match-arm-scopes.rs:16:52: 16:60 - } - - bb17: { - StorageDead(_12); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageLive(_5); // scope 0 at $DIR/match-arm-scopes.rs:16:26: 16:27 - _5 = (_2.0: bool); // scope 0 at $DIR/match-arm-scopes.rs:16:26: 16:27 - StorageLive(_7); // scope 0 at $DIR/match-arm-scopes.rs:16:36: 16:37 - _7 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:16:36: 16:37 - goto -> bb5; // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6 - } - - bb18: { - StorageDead(_12); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageDead(_8); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageDead(_6); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - goto -> bb3; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73 - } - - bb19: { - StorageDead(_7); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageDead(_5); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageDead(_8); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageDead(_6); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - goto -> bb23; // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6 - } - - bb20: { - _0 = const 2_i32; // scope 2 at $DIR/match-arm-scopes.rs:17:41: 17:42 - // ty::Const - // + ty: i32 - // + val: Value(Scalar(0x00000002)) - // mir::Constant - // + span: $DIR/match-arm-scopes.rs:17:41: 17:42 - // + literal: Const { ty: i32, val: Value(Scalar(0x00000002)) } - drop(_16) -> [return: bb22, unwind: bb10]; // scope 0 at $DIR/match-arm-scopes.rs:17:41: 17:42 - } - - bb21: { - StorageLive(_15); // scope 0 at $DIR/match-arm-scopes.rs:17:16: 17:17 - _15 = (_2.1: bool); // scope 0 at $DIR/match-arm-scopes.rs:17:16: 17:17 - StorageLive(_16); // scope 0 at $DIR/match-arm-scopes.rs:17:19: 17:20 - _16 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:17:19: 17:20 - goto -> bb20; // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6 - } - - bb22: { - StorageDead(_16); // scope 0 at $DIR/match-arm-scopes.rs:17:41: 17:42 - StorageDead(_15); // scope 0 at $DIR/match-arm-scopes.rs:17:41: 17:42 - goto -> bb23; // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6 - } - - bb23: { - goto -> bb29; // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2 - } - - bb24 (cleanup): { - goto -> bb1; // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2 - } - - bb25 (cleanup): { - goto -> bb24; // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2 - } - - bb26: { - goto -> bb9; // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2 - } - - bb27 (cleanup): { - goto -> bb1; // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2 - } - - bb28 (cleanup): { - goto -> bb27; // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2 - } - - bb29: { - goto -> bb26; // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2 - } -} diff --git a/src/test/mir-opt/match-arm-scopes/rustc.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/src/test/mir-opt/match-arm-scopes/rustc.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff new file mode 100644 index 0000000000000..58847e1bceee6 --- /dev/null +++ b/src/test/mir-opt/match-arm-scopes/rustc.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -0,0 +1,313 @@ +- // MIR for `complicated_match` after SimplifyCfg-initial ++ // MIR for `complicated_match` after ElaborateDrops + + fn complicated_match(_1: bool, _2: (bool, bool, std::string::String)) -> i32 { + debug cond => _1; // in scope 0 at $DIR/match-arm-scopes.rs:13:22: 13:26 + debug items => _2; // in scope 0 at $DIR/match-arm-scopes.rs:13:34: 13:39 + let mut _0: i32; // return place in scope 0 at $DIR/match-arm-scopes.rs:13:66: 13:69 + let mut _3: &bool; // in scope 0 at $DIR/match-arm-scopes.rs:14:11: 14:16 + let mut _4: &bool; // in scope 0 at $DIR/match-arm-scopes.rs:14:11: 14:16 + let _5: bool; // in scope 0 at $DIR/match-arm-scopes.rs:15:17: 15:18 + let _6: &bool; // in scope 0 at $DIR/match-arm-scopes.rs:15:17: 15:18 + let _7: std::string::String; // in scope 0 at $DIR/match-arm-scopes.rs:15:20: 15:21 + let _8: &std::string::String; // in scope 0 at $DIR/match-arm-scopes.rs:15:20: 15:21 + let mut _9: bool; // in scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73 + let mut _10: bool; // in scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49 + let mut _11: !; // in scope 0 at $DIR/match-arm-scopes.rs:15:52: 15:60 + let mut _12: bool; // in scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73 + let mut _13: bool; // in scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49 + let mut _14: !; // in scope 0 at $DIR/match-arm-scopes.rs:15:52: 15:60 + let _15: bool; // in scope 0 at $DIR/match-arm-scopes.rs:16:16: 16:17 + let _16: std::string::String; // in scope 0 at $DIR/match-arm-scopes.rs:16:19: 16:20 + scope 1 { + debug a => _5; // in scope 1 at $DIR/match-arm-scopes.rs:15:17: 15:18 + debug a => _6; // in scope 1 at $DIR/match-arm-scopes.rs:15:17: 15:18 + debug s => _7; // in scope 1 at $DIR/match-arm-scopes.rs:15:20: 15:21 + debug s => _8; // in scope 1 at $DIR/match-arm-scopes.rs:15:20: 15:21 + } + scope 2 { + debug b => _15; // in scope 2 at $DIR/match-arm-scopes.rs:16:16: 16:17 + debug t => _16; // in scope 2 at $DIR/match-arm-scopes.rs:16:19: 16:20 + } + + bb0: { +- FakeRead(ForMatchedPlace, _2); // scope 0 at $DIR/match-arm-scopes.rs:14:11: 14:16 +- switchInt((_2.0: bool)) -> [false: bb2, otherwise: bb3]; // scope 0 at $DIR/match-arm-scopes.rs:15:10: 15:15 ++ switchInt((_2.0: bool)) -> [false: bb6, otherwise: bb2]; // scope 0 at $DIR/match-arm-scopes.rs:15:10: 15:15 + } + + bb1 (cleanup): { + resume; // scope 0 at $DIR/match-arm-scopes.rs:13:1: 18:2 + } + + bb2: { +- falseEdge -> [real: bb9, imaginary: bb4]; // scope 0 at $DIR/match-arm-scopes.rs:15:9: 15:22 ++ switchInt((_2.1: bool)) -> [false: bb14, otherwise: bb3]; // scope 0 at $DIR/match-arm-scopes.rs:15:29: 15:34 + } + + bb3: { +- switchInt((_2.1: bool)) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/match-arm-scopes.rs:15:29: 15:34 ++ switchInt((_2.0: bool)) -> [false: bb4, otherwise: bb21]; // scope 0 at $DIR/match-arm-scopes.rs:16:10: 16:14 + } + + bb4: { +- falseEdge -> [real: bb18, imaginary: bb6]; // scope 0 at $DIR/match-arm-scopes.rs:15:25: 15:38 +- } +- +- bb5: { +- switchInt((_2.0: bool)) -> [false: bb7, otherwise: bb6]; // scope 0 at $DIR/match-arm-scopes.rs:16:10: 16:14 +- } +- +- bb6: { +- falseEdge -> [real: bb26, imaginary: bb7]; // scope 0 at $DIR/match-arm-scopes.rs:16:9: 16:21 +- } +- +- bb7: { + StorageLive(_15); // scope 0 at $DIR/match-arm-scopes.rs:16:32: 16:33 + _15 = (_2.1: bool); // scope 0 at $DIR/match-arm-scopes.rs:16:32: 16:33 + StorageLive(_16); // scope 0 at $DIR/match-arm-scopes.rs:16:35: 16:36 + _16 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:16:35: 16:36 +- goto -> bb25; // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6 ++ goto -> bb20; // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6 + } + +- bb8: { ++ bb5: { + _0 = const 1_i32; // scope 1 at $DIR/match-arm-scopes.rs:15:77: 15:78 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000001)) + // mir::Constant + // + span: $DIR/match-arm-scopes.rs:15:77: 15:78 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } +- drop(_7) -> [return: bb24, unwind: bb14]; // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78 ++ drop(_7) -> [return: bb19, unwind: bb10]; // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78 + } + +- bb9: { ++ bb6: { + StorageLive(_6); // scope 0 at $DIR/match-arm-scopes.rs:15:17: 15:18 + _6 = &(_2.1: bool); // scope 0 at $DIR/match-arm-scopes.rs:15:17: 15:18 + StorageLive(_8); // scope 0 at $DIR/match-arm-scopes.rs:15:20: 15:21 + _8 = &(_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:15:20: 15:21 +- _3 = &shallow (_2.0: bool); // scope 0 at $DIR/match-arm-scopes.rs:14:11: 14:16 +- _4 = &shallow (_2.1: bool); // scope 0 at $DIR/match-arm-scopes.rs:14:11: 14:16 + StorageLive(_9); // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73 + StorageLive(_10); // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49 + _10 = _1; // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49 +- FakeRead(ForMatchedPlace, _10); // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49 +- switchInt(_10) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73 ++ switchInt(_10) -> [false: bb7, otherwise: bb8]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73 + } + +- bb10: { +- falseEdge -> [real: bb12, imaginary: bb11]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73 +- } +- +- bb11: { ++ bb7: { + _9 = (*_6); // scope 0 at $DIR/match-arm-scopes.rs:15:70: 15:71 + StorageDead(_10); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73 +- switchInt(move _9) -> [false: bb17, otherwise: bb16]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73 ++ switchInt(move _9) -> [false: bb13, otherwise: bb12]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73 + } + +- bb12: { ++ bb8: { + _0 = const 3_i32; // scope 0 at $DIR/match-arm-scopes.rs:15:59: 15:60 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000003)) + // mir::Constant + // + span: $DIR/match-arm-scopes.rs:15:59: 15:60 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000003)) } + StorageDead(_10); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73 + StorageDead(_9); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78 + StorageDead(_8); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78 + StorageDead(_6); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78 +- goto -> bb15; // scope 0 at $DIR/match-arm-scopes.rs:15:52: 15:60 ++ goto -> bb11; // scope 0 at $DIR/match-arm-scopes.rs:15:52: 15:60 + } + +- bb13: { ++ bb9: { + return; // scope 0 at $DIR/match-arm-scopes.rs:18:2: 18:2 + } + +- bb14 (cleanup): { +- drop(_2) -> bb1; // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2 ++ bb10 (cleanup): { ++ goto -> bb25; // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2 + } + +- bb15: { +- drop(_2) -> [return: bb13, unwind: bb1]; // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2 ++ bb11: { ++ drop(_2) -> [return: bb9, unwind: bb1]; // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2 + } + +- bb16: { ++ bb12: { + StorageDead(_9); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78 +- FakeRead(ForMatchGuard, _3); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73 +- FakeRead(ForMatchGuard, _4); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73 +- FakeRead(ForGuardBinding, _6); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73 +- FakeRead(ForGuardBinding, _8); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73 + StorageLive(_5); // scope 0 at $DIR/match-arm-scopes.rs:15:17: 15:18 + _5 = (_2.1: bool); // scope 0 at $DIR/match-arm-scopes.rs:15:17: 15:18 + StorageLive(_7); // scope 0 at $DIR/match-arm-scopes.rs:15:20: 15:21 + _7 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:15:20: 15:21 +- goto -> bb8; // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6 ++ goto -> bb5; // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6 + } + +- bb17: { ++ bb13: { + StorageDead(_9); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78 + StorageDead(_8); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78 + StorageDead(_6); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78 +- falseEdge -> [real: bb3, imaginary: bb4]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73 ++ goto -> bb2; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73 + } + +- bb18: { ++ bb14: { + StorageLive(_6); // scope 0 at $DIR/match-arm-scopes.rs:15:26: 15:27 + _6 = &(_2.0: bool); // scope 0 at $DIR/match-arm-scopes.rs:15:26: 15:27 + StorageLive(_8); // scope 0 at $DIR/match-arm-scopes.rs:15:36: 15:37 + _8 = &(_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:15:36: 15:37 +- _3 = &shallow (_2.0: bool); // scope 0 at $DIR/match-arm-scopes.rs:14:11: 14:16 +- _4 = &shallow (_2.1: bool); // scope 0 at $DIR/match-arm-scopes.rs:14:11: 14:16 + StorageLive(_12); // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73 + StorageLive(_13); // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49 + _13 = _1; // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49 +- FakeRead(ForMatchedPlace, _13); // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49 +- switchInt(_13) -> [false: bb20, otherwise: bb19]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73 ++ switchInt(_13) -> [false: bb15, otherwise: bb16]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73 + } + +- bb19: { +- falseEdge -> [real: bb21, imaginary: bb20]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73 +- } +- +- bb20: { ++ bb15: { + _12 = (*_6); // scope 0 at $DIR/match-arm-scopes.rs:15:70: 15:71 + StorageDead(_13); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73 +- switchInt(move _12) -> [false: bb23, otherwise: bb22]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73 ++ switchInt(move _12) -> [false: bb18, otherwise: bb17]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73 + } + +- bb21: { ++ bb16: { + _0 = const 3_i32; // scope 0 at $DIR/match-arm-scopes.rs:15:59: 15:60 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000003)) + // mir::Constant + // + span: $DIR/match-arm-scopes.rs:15:59: 15:60 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000003)) } + StorageDead(_13); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73 + StorageDead(_12); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78 + StorageDead(_8); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78 + StorageDead(_6); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78 +- goto -> bb15; // scope 0 at $DIR/match-arm-scopes.rs:15:52: 15:60 ++ goto -> bb11; // scope 0 at $DIR/match-arm-scopes.rs:15:52: 15:60 + } + +- bb22: { ++ bb17: { + StorageDead(_12); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78 +- FakeRead(ForMatchGuard, _3); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73 +- FakeRead(ForMatchGuard, _4); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73 +- FakeRead(ForGuardBinding, _6); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73 +- FakeRead(ForGuardBinding, _8); // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73 + StorageLive(_5); // scope 0 at $DIR/match-arm-scopes.rs:15:26: 15:27 + _5 = (_2.0: bool); // scope 0 at $DIR/match-arm-scopes.rs:15:26: 15:27 + StorageLive(_7); // scope 0 at $DIR/match-arm-scopes.rs:15:36: 15:37 + _7 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:15:36: 15:37 +- goto -> bb8; // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6 ++ goto -> bb5; // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6 + } + +- bb23: { ++ bb18: { + StorageDead(_12); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78 + StorageDead(_8); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78 + StorageDead(_6); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78 +- falseEdge -> [real: bb5, imaginary: bb6]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73 ++ goto -> bb3; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73 + } + +- bb24: { ++ bb19: { + StorageDead(_7); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78 + StorageDead(_5); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78 + StorageDead(_8); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78 + StorageDead(_6); // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78 +- goto -> bb28; // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6 ++ goto -> bb23; // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6 + } + +- bb25: { ++ bb20: { + _0 = const 2_i32; // scope 2 at $DIR/match-arm-scopes.rs:16:41: 16:42 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000002)) + // mir::Constant + // + span: $DIR/match-arm-scopes.rs:16:41: 16:42 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000002)) } +- drop(_16) -> [return: bb27, unwind: bb14]; // scope 0 at $DIR/match-arm-scopes.rs:16:41: 16:42 ++ drop(_16) -> [return: bb22, unwind: bb10]; // scope 0 at $DIR/match-arm-scopes.rs:16:41: 16:42 + } + +- bb26: { ++ bb21: { + StorageLive(_15); // scope 0 at $DIR/match-arm-scopes.rs:16:16: 16:17 + _15 = (_2.1: bool); // scope 0 at $DIR/match-arm-scopes.rs:16:16: 16:17 + StorageLive(_16); // scope 0 at $DIR/match-arm-scopes.rs:16:19: 16:20 + _16 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:16:19: 16:20 +- goto -> bb25; // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6 ++ goto -> bb20; // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6 + } + +- bb27: { ++ bb22: { + StorageDead(_16); // scope 0 at $DIR/match-arm-scopes.rs:16:41: 16:42 + StorageDead(_15); // scope 0 at $DIR/match-arm-scopes.rs:16:41: 16:42 +- goto -> bb28; // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6 ++ goto -> bb23; // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6 + } + +- bb28: { +- drop(_2) -> [return: bb13, unwind: bb1]; // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2 ++ bb23: { ++ goto -> bb29; // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2 ++ } ++ ++ bb24 (cleanup): { ++ goto -> bb1; // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2 ++ } ++ ++ bb25 (cleanup): { ++ goto -> bb24; // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2 ++ } ++ ++ bb26: { ++ goto -> bb9; // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2 ++ } ++ ++ bb27 (cleanup): { ++ goto -> bb1; // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2 ++ } ++ ++ bb28 (cleanup): { ++ goto -> bb27; // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2 ++ } ++ ++ bb29: { ++ goto -> bb26; // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2 + } + } + diff --git a/src/test/mir-opt/match-arm-scopes/rustc.complicated_match.SimplifyCfg-initial.after.mir b/src/test/mir-opt/match-arm-scopes/rustc.complicated_match.SimplifyCfg-initial.after.mir deleted file mode 100644 index dadbc3668cb29..0000000000000 --- a/src/test/mir-opt/match-arm-scopes/rustc.complicated_match.SimplifyCfg-initial.after.mir +++ /dev/null @@ -1,246 +0,0 @@ -// MIR for `complicated_match` after SimplifyCfg-initial - -fn complicated_match(_1: bool, _2: (bool, bool, std::string::String)) -> i32 { - debug cond => _1; // in scope 0 at $DIR/match-arm-scopes.rs:14:22: 14:26 - debug items => _2; // in scope 0 at $DIR/match-arm-scopes.rs:14:34: 14:39 - let mut _0: i32; // return place in scope 0 at $DIR/match-arm-scopes.rs:14:66: 14:69 - let mut _3: &bool; // in scope 0 at $DIR/match-arm-scopes.rs:15:11: 15:16 - let mut _4: &bool; // in scope 0 at $DIR/match-arm-scopes.rs:15:11: 15:16 - let _5: bool; // in scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18 - let _6: &bool; // in scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18 - let _7: std::string::String; // in scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21 - let _8: &std::string::String; // in scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21 - let mut _9: bool; // in scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73 - let mut _10: bool; // in scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49 - let mut _11: !; // in scope 0 at $DIR/match-arm-scopes.rs:16:52: 16:60 - let mut _12: bool; // in scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73 - let mut _13: bool; // in scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49 - let mut _14: !; // in scope 0 at $DIR/match-arm-scopes.rs:16:52: 16:60 - let _15: bool; // in scope 0 at $DIR/match-arm-scopes.rs:17:16: 17:17 - let _16: std::string::String; // in scope 0 at $DIR/match-arm-scopes.rs:17:19: 17:20 - scope 1 { - debug a => _5; // in scope 1 at $DIR/match-arm-scopes.rs:16:17: 16:18 - debug a => _6; // in scope 1 at $DIR/match-arm-scopes.rs:16:17: 16:18 - debug s => _7; // in scope 1 at $DIR/match-arm-scopes.rs:16:20: 16:21 - debug s => _8; // in scope 1 at $DIR/match-arm-scopes.rs:16:20: 16:21 - } - scope 2 { - debug b => _15; // in scope 2 at $DIR/match-arm-scopes.rs:17:16: 17:17 - debug t => _16; // in scope 2 at $DIR/match-arm-scopes.rs:17:19: 17:20 - } - - bb0: { - FakeRead(ForMatchedPlace, _2); // scope 0 at $DIR/match-arm-scopes.rs:15:11: 15:16 - switchInt((_2.0: bool)) -> [false: bb2, otherwise: bb3]; // scope 0 at $DIR/match-arm-scopes.rs:16:10: 16:15 - } - - bb1 (cleanup): { - resume; // scope 0 at $DIR/match-arm-scopes.rs:14:1: 19:2 - } - - bb2: { - falseEdge -> [real: bb9, imaginary: bb4]; // scope 0 at $DIR/match-arm-scopes.rs:16:9: 16:22 - } - - bb3: { - switchInt((_2.1: bool)) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/match-arm-scopes.rs:16:29: 16:34 - } - - bb4: { - falseEdge -> [real: bb18, imaginary: bb6]; // scope 0 at $DIR/match-arm-scopes.rs:16:25: 16:38 - } - - bb5: { - switchInt((_2.0: bool)) -> [false: bb7, otherwise: bb6]; // scope 0 at $DIR/match-arm-scopes.rs:17:10: 17:14 - } - - bb6: { - falseEdge -> [real: bb26, imaginary: bb7]; // scope 0 at $DIR/match-arm-scopes.rs:17:9: 17:21 - } - - bb7: { - StorageLive(_15); // scope 0 at $DIR/match-arm-scopes.rs:17:32: 17:33 - _15 = (_2.1: bool); // scope 0 at $DIR/match-arm-scopes.rs:17:32: 17:33 - StorageLive(_16); // scope 0 at $DIR/match-arm-scopes.rs:17:35: 17:36 - _16 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:17:35: 17:36 - goto -> bb25; // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6 - } - - bb8: { - _0 = const 1_i32; // scope 1 at $DIR/match-arm-scopes.rs:16:77: 16:78 - // ty::Const - // + ty: i32 - // + val: Value(Scalar(0x00000001)) - // mir::Constant - // + span: $DIR/match-arm-scopes.rs:16:77: 16:78 - // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } - drop(_7) -> [return: bb24, unwind: bb14]; // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - } - - bb9: { - StorageLive(_6); // scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18 - _6 = &(_2.1: bool); // scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18 - StorageLive(_8); // scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21 - _8 = &(_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21 - _3 = &shallow (_2.0: bool); // scope 0 at $DIR/match-arm-scopes.rs:15:11: 15:16 - _4 = &shallow (_2.1: bool); // scope 0 at $DIR/match-arm-scopes.rs:15:11: 15:16 - StorageLive(_9); // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73 - StorageLive(_10); // scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49 - _10 = _1; // scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49 - FakeRead(ForMatchedPlace, _10); // scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49 - switchInt(_10) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73 - } - - bb10: { - falseEdge -> [real: bb12, imaginary: bb11]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73 - } - - bb11: { - _9 = (*_6); // scope 0 at $DIR/match-arm-scopes.rs:16:70: 16:71 - StorageDead(_10); // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73 - switchInt(move _9) -> [false: bb17, otherwise: bb16]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73 - } - - bb12: { - _0 = const 3_i32; // scope 0 at $DIR/match-arm-scopes.rs:16:59: 16:60 - // ty::Const - // + ty: i32 - // + val: Value(Scalar(0x00000003)) - // mir::Constant - // + span: $DIR/match-arm-scopes.rs:16:59: 16:60 - // + literal: Const { ty: i32, val: Value(Scalar(0x00000003)) } - StorageDead(_10); // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73 - StorageDead(_9); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageDead(_8); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageDead(_6); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - goto -> bb15; // scope 0 at $DIR/match-arm-scopes.rs:16:52: 16:60 - } - - bb13: { - return; // scope 0 at $DIR/match-arm-scopes.rs:19:2: 19:2 - } - - bb14 (cleanup): { - drop(_2) -> bb1; // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2 - } - - bb15: { - drop(_2) -> [return: bb13, unwind: bb1]; // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2 - } - - bb16: { - StorageDead(_9); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - FakeRead(ForMatchGuard, _3); // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73 - FakeRead(ForMatchGuard, _4); // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73 - FakeRead(ForGuardBinding, _6); // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73 - FakeRead(ForGuardBinding, _8); // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73 - StorageLive(_5); // scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18 - _5 = (_2.1: bool); // scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18 - StorageLive(_7); // scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21 - _7 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21 - goto -> bb8; // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6 - } - - bb17: { - StorageDead(_9); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageDead(_8); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageDead(_6); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - falseEdge -> [real: bb3, imaginary: bb4]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73 - } - - bb18: { - StorageLive(_6); // scope 0 at $DIR/match-arm-scopes.rs:16:26: 16:27 - _6 = &(_2.0: bool); // scope 0 at $DIR/match-arm-scopes.rs:16:26: 16:27 - StorageLive(_8); // scope 0 at $DIR/match-arm-scopes.rs:16:36: 16:37 - _8 = &(_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:16:36: 16:37 - _3 = &shallow (_2.0: bool); // scope 0 at $DIR/match-arm-scopes.rs:15:11: 15:16 - _4 = &shallow (_2.1: bool); // scope 0 at $DIR/match-arm-scopes.rs:15:11: 15:16 - StorageLive(_12); // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73 - StorageLive(_13); // scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49 - _13 = _1; // scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49 - FakeRead(ForMatchedPlace, _13); // scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49 - switchInt(_13) -> [false: bb20, otherwise: bb19]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73 - } - - bb19: { - falseEdge -> [real: bb21, imaginary: bb20]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73 - } - - bb20: { - _12 = (*_6); // scope 0 at $DIR/match-arm-scopes.rs:16:70: 16:71 - StorageDead(_13); // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73 - switchInt(move _12) -> [false: bb23, otherwise: bb22]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73 - } - - bb21: { - _0 = const 3_i32; // scope 0 at $DIR/match-arm-scopes.rs:16:59: 16:60 - // ty::Const - // + ty: i32 - // + val: Value(Scalar(0x00000003)) - // mir::Constant - // + span: $DIR/match-arm-scopes.rs:16:59: 16:60 - // + literal: Const { ty: i32, val: Value(Scalar(0x00000003)) } - StorageDead(_13); // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73 - StorageDead(_12); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageDead(_8); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageDead(_6); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - goto -> bb15; // scope 0 at $DIR/match-arm-scopes.rs:16:52: 16:60 - } - - bb22: { - StorageDead(_12); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - FakeRead(ForMatchGuard, _3); // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73 - FakeRead(ForMatchGuard, _4); // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73 - FakeRead(ForGuardBinding, _6); // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73 - FakeRead(ForGuardBinding, _8); // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73 - StorageLive(_5); // scope 0 at $DIR/match-arm-scopes.rs:16:26: 16:27 - _5 = (_2.0: bool); // scope 0 at $DIR/match-arm-scopes.rs:16:26: 16:27 - StorageLive(_7); // scope 0 at $DIR/match-arm-scopes.rs:16:36: 16:37 - _7 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:16:36: 16:37 - goto -> bb8; // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6 - } - - bb23: { - StorageDead(_12); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageDead(_8); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageDead(_6); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - falseEdge -> [real: bb5, imaginary: bb6]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73 - } - - bb24: { - StorageDead(_7); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageDead(_5); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageDead(_8); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - StorageDead(_6); // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78 - goto -> bb28; // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6 - } - - bb25: { - _0 = const 2_i32; // scope 2 at $DIR/match-arm-scopes.rs:17:41: 17:42 - // ty::Const - // + ty: i32 - // + val: Value(Scalar(0x00000002)) - // mir::Constant - // + span: $DIR/match-arm-scopes.rs:17:41: 17:42 - // + literal: Const { ty: i32, val: Value(Scalar(0x00000002)) } - drop(_16) -> [return: bb27, unwind: bb14]; // scope 0 at $DIR/match-arm-scopes.rs:17:41: 17:42 - } - - bb26: { - StorageLive(_15); // scope 0 at $DIR/match-arm-scopes.rs:17:16: 17:17 - _15 = (_2.1: bool); // scope 0 at $DIR/match-arm-scopes.rs:17:16: 17:17 - StorageLive(_16); // scope 0 at $DIR/match-arm-scopes.rs:17:19: 17:20 - _16 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:17:19: 17:20 - goto -> bb25; // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6 - } - - bb27: { - StorageDead(_16); // scope 0 at $DIR/match-arm-scopes.rs:17:41: 17:42 - StorageDead(_15); // scope 0 at $DIR/match-arm-scopes.rs:17:41: 17:42 - goto -> bb28; // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6 - } - - bb28: { - drop(_2) -> [return: bb13, unwind: bb1]; // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2 - } -} diff --git a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs index 2a983e426838c..795c5154f8155 100644 --- a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs +++ b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs @@ -1,7 +1,7 @@ // build-fail // Regression test for #66975 -#![warn(const_err)] +#![warn(const_err, unconditional_panic)] #![feature(never_type)] struct PrintName(T); @@ -9,6 +9,7 @@ struct PrintName(T); impl PrintName { const VOID: ! = { let x = 0 * std::mem::size_of::(); [][x] }; //~^ WARN any use of this value will cause an error + } fn f() { diff --git a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr index d78e0da00f5e1..33e60dd7c9138 100644 --- a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr +++ b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr @@ -9,11 +9,11 @@ LL | const VOID: ! = { let x = 0 * std::mem::size_of::(); [][x] }; note: the lint level is defined here --> $DIR/index-out-of-bounds-never-type.rs:4:9 | -LL | #![warn(const_err)] +LL | #![warn(const_err, unconditional_panic)] | ^^^^^^^^^ error: erroneous constant encountered - --> $DIR/index-out-of-bounds-never-type.rs:15:13 + --> $DIR/index-out-of-bounds-never-type.rs:16:13 | LL | let _ = PrintName::::VOID; | ^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/error-codes/E0308-2.rs b/src/test/ui/error-codes/E0308-2.rs new file mode 100644 index 0000000000000..157f992da9940 --- /dev/null +++ b/src/test/ui/error-codes/E0308-2.rs @@ -0,0 +1,12 @@ +trait DynEq {} + +impl<'a> PartialEq for &'a (dyn DynEq + 'static) { + fn eq(&self, _other: &Self) -> bool { + true + } +} + +impl Eq for &dyn DynEq {} //~ ERROR E0308 + +fn main() { +} diff --git a/src/test/ui/error-codes/E0308-2.stderr b/src/test/ui/error-codes/E0308-2.stderr new file mode 100644 index 0000000000000..e7c5e4b42405f --- /dev/null +++ b/src/test/ui/error-codes/E0308-2.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/E0308-2.rs:9:6 + | +LL | impl Eq for &dyn DynEq {} + | ^^ lifetime mismatch + | + = note: expected trait `std::cmp::PartialEq` + found trait `std::cmp::PartialEq` +note: the lifetime `'_` as defined on the impl at 9:13... + --> $DIR/E0308-2.rs:9:13 + | +LL | impl Eq for &dyn DynEq {} + | ^ + = note: ...does not necessarily outlive the static lifetime + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index f09f7621aa170..21fb7673ce061 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -3135,14 +3135,47 @@ impl<'test> TestCx<'test> { } for l in test_file_contents.lines() { if l.starts_with("// EMIT_MIR ") { - let test_name = l.trim_start_matches("// EMIT_MIR "); - let expected_file = test_dir.join(test_name); - - let dumped_string = if test_name.ends_with(".diff") { - let test_name = test_name.trim_end_matches(".diff"); - let before = format!("{}.before.mir", test_name); - let after = format!("{}.after.mir", test_name); - let before = self.get_mir_dump_dir().join(before); + let test_name = l.trim_start_matches("// EMIT_MIR ").trim(); + let mut test_names = test_name.split(' '); + // sometimes we specify two files so that we get a diff between the two files + let test_name = test_names.next().unwrap(); + let expected_file; + let from_file; + let to_file; + + if test_name.ends_with(".diff") { + let trimmed = test_name.trim_end_matches(".diff"); + let test_against = format!("{}.after.mir", trimmed); + from_file = format!("{}.before.mir", trimmed); + expected_file = test_name.to_string(); + assert!( + test_names.next().is_none(), + "two mir pass names specified for MIR diff" + ); + to_file = Some(test_against); + } else if let Some(first_pass) = test_names.next() { + let second_pass = test_names.next().unwrap(); + assert!( + test_names.next().is_none(), + "three mir pass names specified for MIR diff" + ); + expected_file = format!("{}.{}-{}.diff", test_name, first_pass, second_pass); + let second_file = format!("{}.{}.mir", test_name, second_pass); + from_file = format!("{}.{}.mir", test_name, first_pass); + to_file = Some(second_file); + } else { + expected_file = test_name.to_string(); + from_file = test_name.to_string(); + assert!( + test_names.next().is_none(), + "two mir pass names specified for MIR dump" + ); + to_file = None; + }; + let expected_file = test_dir.join(expected_file); + + let dumped_string = if let Some(after) = to_file { + let before = self.get_mir_dump_dir().join(from_file); let after = self.get_mir_dump_dir().join(after); debug!( "comparing the contents of: {} with {}", @@ -3166,7 +3199,7 @@ impl<'test> TestCx<'test> { } else { let mut output_file = PathBuf::new(); output_file.push(self.get_mir_dump_dir()); - output_file.push(test_name); + output_file.push(&from_file); debug!( "comparing the contents of: {} with {}", output_file.display(), @@ -3179,7 +3212,7 @@ impl<'test> TestCx<'test> { output_file.parent().unwrap().display() ); } - self.check_mir_test_timestamp(test_name, &output_file); + self.check_mir_test_timestamp(&from_file, &output_file); let dumped_string = fs::read_to_string(&output_file).unwrap(); self.normalize_output(&dumped_string, &[]) };