Commit fe07ece9 authored by bors's avatar bors

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
parents cfb6114b 5d1d94e7
......@@ -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(&note);
}
RegionNameSource::CannotMatchHirTy(span, type_name) => {
RegionNameSource::AnonRegionFromArgument(RegionNameHighlight::CannotMatchHirTy(
span,
type_name,
)) => {
diag.span_label(*span, format!("has type `{}`", type_name));