Auto merge of #74724 - Manishearth:rollup-plbt8fe, r=Manishearth
Rollup of 8 pull requests Successful merges: - #72954 (revise RwLock for HermitCore) - #74367 (Rearrange the pipeline of `pow` to gain efficiency) - #74491 (Optimize away BitAnd and BitOr when possible) - #74639 (Downgrade glibc to 2.11.1 for ppc, ppc64 and s390x) - #74661 (Refactor `region_name`: add `RegionNameHighlight`) - #74692 (delay_span_bug instead of silent ignore) - #74698 (fixed error reporting for mismatched traits) - #74715 (Add a system for creating diffs across multiple mir optimizations.) Failed merges: r? @ghost
This commit is contained in:
commit
fe07ece978
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1095,6 +1095,9 @@ $EndFeature, "
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
|
||||
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<Self> {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1402,8 +1402,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
debug!("note_type_err(diag={:?})", diag);
|
||||
enum Mismatch<'a> {
|
||||
Variable(ty::error::ExpectedFound<Ty<'a>>),
|
||||
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);
|
||||
}
|
||||
|
@ -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(..)
|
||||
|
@ -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(
|
||||
|
@ -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<Span> {
|
||||
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<RegionName> {
|
||||
) -> 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<RegionName> {
|
||||
let counter = *self.next_region_name.try_borrow().unwrap();
|
||||
ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
counter: usize,
|
||||
) -> Option<RegionNameHighlight> {
|
||||
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<RegionName> {
|
||||
let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty<'_>)> =
|
||||
&mut vec![(argument_ty, argument_hir_ty)];
|
||||
ty: Ty<'tcx>,
|
||||
hir_ty: &hir::Ty<'_>,
|
||||
) -> Option<RegionNameHighlight> {
|
||||
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<RegionName> {
|
||||
) -> Option<RegionNameHighlight> {
|
||||
// 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 => {
|
||||
|
@ -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(())
|
||||
})
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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 }
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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<State>,
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
10
src/test/mir-opt/const_prop/boolean_identities.rs
Normal file
10
src/test/mir-opt/const_prop/boolean_identities.rs
Normal file
@ -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);
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
|
10
src/test/mir-opt/const_prop/mult_by_zero.rs
Normal file
10
src/test/mir-opt/const_prop/mult_by_zero.rs
Normal file
@ -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);
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
// build-fail
|
||||
|
||||
// Regression test for #66975
|
||||
#![warn(const_err)]
|
||||
#![warn(const_err, unconditional_panic)]
|
||||
#![feature(never_type)]
|
||||
|
||||
struct PrintName<T>(T);
|
||||
@ -9,6 +9,7 @@ struct PrintName<T>(T);
|
||||
impl<T> PrintName<T> {
|
||||
const VOID: ! = { let x = 0 * std::mem::size_of::<T>(); [][x] };
|
||||
//~^ WARN any use of this value will cause an error
|
||||
|
||||
}
|
||||
|
||||
fn f<T>() {
|
||||
|
@ -9,11 +9,11 @@ LL | const VOID: ! = { let x = 0 * std::mem::size_of::<T>(); [][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::<T>::VOID;
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
12
src/test/ui/error-codes/E0308-2.rs
Normal file
12
src/test/ui/error-codes/E0308-2.rs
Normal file
@ -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() {
|
||||
}
|
18
src/test/ui/error-codes/E0308-2.stderr
Normal file
18
src/test/ui/error-codes/E0308-2.stderr
Normal file
@ -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`.
|
@ -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 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;
|
||||
|
||||
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);
|
||||
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, &[])
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user