Auto merge of #83308 - Dylan-DPC:rollup-p2j6sy8, r=Dylan-DPC

Rollup of 8 pull requests

Successful merges:

 - #79986 (Only build help popup when it's really needed)
 - #82570 (Add `as_str` method for split whitespace str iterators)
 - #83244 (Fix overflowing length in Vec<ZST> to VecDeque)
 - #83254 (Include output stream in `panic!()` documentation)
 - #83269 (Revert the second deprecation of collections::Bound)
 - #83277 (Mark early otherwise optimization unsound)
 - #83285 (Update LLVM to bring in SIMD updates for WebAssembly)
 - #83297 (Do not ICE on ty::Error as an error must already have been reported)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-03-19 23:53:02 +00:00
commit 6bfbf0c33a
18 changed files with 210 additions and 49 deletions

View File

@ -10,6 +10,7 @@ use crate::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc_hir as ast; use rustc_hir as ast;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_span::DUMMY_SP;
use rustc_target::spec::abi; use rustc_target::spec::abi;
use std::iter; use std::iter;
@ -499,11 +500,14 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
// FIXME(oli-obk): once const generics can have generic types, this assertion // FIXME(oli-obk): once const generics can have generic types, this assertion
// will likely get triggered. Move to `normalize_erasing_regions` at that point. // will likely get triggered. Move to `normalize_erasing_regions` at that point.
assert_eq!( let a_ty = tcx.erase_regions(a.ty);
tcx.erase_regions(a.ty), let b_ty = tcx.erase_regions(b.ty);
tcx.erase_regions(b.ty), if a_ty != b_ty {
"cannot relate constants of different types" relation.tcx().sess.delay_span_bug(
); DUMMY_SP,
&format!("cannot relate constants of different types: {} != {}", a_ty, b_ty),
);
}
let eagerly_eval = |x: &'tcx ty::Const<'tcx>| x.eval(tcx, relation.param_env()); let eagerly_eval = |x: &'tcx ty::Const<'tcx>| x.eval(tcx, relation.param_env());
let a = eagerly_eval(a); let a = eagerly_eval(a);

View File

@ -26,6 +26,11 @@ pub struct EarlyOtherwiseBranch;
impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch { impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// FIXME(#78496)
if !tcx.sess.opts.debugging_opts.unsound_mir_opts {
return;
}
if tcx.sess.mir_opt_level() < 3 { if tcx.sess.mir_opt_level() < 3 {
return; return;
} }

View File

@ -2783,27 +2783,26 @@ impl<T> From<Vec<T>> for VecDeque<T> {
/// This avoids reallocating where possible, but the conditions for that are /// This avoids reallocating where possible, but the conditions for that are
/// strict, and subject to change, and so shouldn't be relied upon unless the /// strict, and subject to change, and so shouldn't be relied upon unless the
/// `Vec<T>` came from `From<VecDeque<T>>` and hasn't been reallocated. /// `Vec<T>` came from `From<VecDeque<T>>` and hasn't been reallocated.
fn from(other: Vec<T>) -> Self { fn from(mut other: Vec<T>) -> Self {
unsafe { let len = other.len();
let mut other = ManuallyDrop::new(other); if mem::size_of::<T>() == 0 {
let other_buf = other.as_mut_ptr(); // There's no actual allocation for ZSTs to worry about capacity,
let mut buf = RawVec::from_raw_parts(other_buf, other.capacity()); // but `VecDeque` can't handle as much length as `Vec`.
let len = other.len(); assert!(len < MAXIMUM_ZST_CAPACITY, "capacity overflow");
} else {
// We need to extend the buf if it's not a power of two, too small // We need to resize if the capacity is not a power of two, too small or
// or doesn't have at least one free space. // doesn't have at least one free space. We do this while it's still in
// We check if `T` is a ZST in the first condition, // the `Vec` so the items will drop on panic.
// because `usize::MAX` (the capacity returned by `capacity()` for ZST) let min_cap = cmp::max(MINIMUM_CAPACITY, len) + 1;
// is not a power of two and thus it'll always try let cap = cmp::max(min_cap, other.capacity()).next_power_of_two();
// to reserve more memory which will panic for ZST (rust-lang/rust#78532) if other.capacity() != cap {
if (!buf.capacity().is_power_of_two() && mem::size_of::<T>() != 0) other.reserve_exact(cap - len);
|| (buf.capacity() < (MINIMUM_CAPACITY + 1))
|| (buf.capacity() == len)
{
let cap = cmp::max(buf.capacity() + 1, MINIMUM_CAPACITY + 1).next_power_of_two();
buf.reserve_exact(len, cap - len);
} }
}
unsafe {
let (other_buf, len, capacity) = other.into_raw_parts();
let buf = RawVec::from_raw_parts(other_buf, capacity);
VecDeque { tail: 0, head: len, buf } VecDeque { tail: 0, head: len, buf }
} }
} }

View File

@ -457,6 +457,21 @@ fn test_from_vec() {
assert!(vd.into_iter().eq(vec)); assert!(vd.into_iter().eq(vec));
} }
} }
let vec = Vec::from([(); MAXIMUM_ZST_CAPACITY - 1]);
let vd = VecDeque::from(vec.clone());
assert!(vd.cap().is_power_of_two());
assert_eq!(vd.len(), vec.len());
}
#[test]
#[should_panic = "capacity overflow"]
fn test_from_vec_zst_overflow() {
use crate::vec::Vec;
let vec = Vec::from([(); MAXIMUM_ZST_CAPACITY]);
let vd = VecDeque::from(vec.clone()); // no room for +1
assert!(vd.cap().is_power_of_two());
assert_eq!(vd.len(), vec.len());
} }
#[test] #[test]

View File

@ -13,7 +13,8 @@ use crate::ops::Try;
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)] #[derive(Clone)]
pub struct Filter<I, P> { pub struct Filter<I, P> {
iter: I, // Used for `SplitWhitespace` and `SplitAsciiWhitespace` `as_str` methods
pub(crate) iter: I,
predicate: P, predicate: P,
} }
impl<I, P> Filter<I, P> { impl<I, P> Filter<I, P> {

View File

@ -57,7 +57,8 @@ use crate::ops::Try;
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)] #[derive(Clone)]
pub struct Map<I, F> { pub struct Map<I, F> {
iter: I, // Used for `SplitWhitespace` and `SplitAsciiWhitespace` `as_str` methods
pub(crate) iter: I,
f: F, f: F,
} }

View File

@ -9,11 +9,15 @@ tests. `panic!` is closely tied with the `unwrap` method of both
[`Option`][ounwrap] and [`Result`][runwrap] enums. Both implementations call [`Option`][ounwrap] and [`Result`][runwrap] enums. Both implementations call
`panic!` when they are set to [`None`] or [`Err`] variants. `panic!` when they are set to [`None`] or [`Err`] variants.
This macro is used to inject panic into a Rust thread, causing the thread to When using `panic!()` you can specify a string payload, that is built using
panic entirely. This macro panics with a string and uses the [`format!`] syntax the [`format!`] syntax. That payload is used when injecting the panic into
for building the message. the calling Rust thread, causing the thread to panic entirely.
Each thread's panic can be reaped as the [`Box`]`<`[`Any`]`>` type, The behavior of the default `std` hook, i.e. the code that runs directly
after the panic is invoked, is to print the message payload to
`stderr` along with the file/line/column information of the `panic!()`
call. You can override the panic hook using [`std::panic::set_hook()`].
Inside the hook a panic can be accessed as a `&dyn Any + Send`,
which contains either a `&str` or `String` for regular `panic!()` invocations. which contains either a `&str` or `String` for regular `panic!()` invocations.
To panic with a value of another other type, [`panic_any`] can be used. To panic with a value of another other type, [`panic_any`] can be used.
@ -26,6 +30,7 @@ See also the macro [`compile_error!`], for raising errors during compilation.
[ounwrap]: Option::unwrap [ounwrap]: Option::unwrap
[runwrap]: Result::unwrap [runwrap]: Result::unwrap
[`std::panic::set_hook()`]: ../std/panic/fn.set_hook.html
[`panic_any`]: ../std/panic/fn.panic_any.html [`panic_any`]: ../std/panic/fn.panic_any.html
[`Box`]: ../std/boxed/struct.Box.html [`Box`]: ../std/boxed/struct.Box.html
[`Any`]: crate::any::Any [`Any`]: crate::any::Any

View File

@ -335,9 +335,11 @@ pub struct Split<'a, T: 'a, P>
where where
P: FnMut(&T) -> bool, P: FnMut(&T) -> bool,
{ {
v: &'a [T], // Used for `SplitWhitespace` and `SplitAsciiWhitespace` `as_str` methods
pub(crate) v: &'a [T],
pred: P, pred: P,
finished: bool, // Used for `SplitAsciiWhitespace` `as_str` method
pub(crate) finished: bool,
} }
impl<'a, T: 'a, P: FnMut(&T) -> bool> Split<'a, T, P> { impl<'a, T: 'a, P: FnMut(&T) -> bool> Split<'a, T, P> {

View File

@ -1200,6 +1200,30 @@ impl<'a> DoubleEndedIterator for SplitWhitespace<'a> {
#[stable(feature = "fused", since = "1.26.0")] #[stable(feature = "fused", since = "1.26.0")]
impl FusedIterator for SplitWhitespace<'_> {} impl FusedIterator for SplitWhitespace<'_> {}
impl<'a> SplitWhitespace<'a> {
/// Returns remainder of the splitted string
///
/// # Examples
///
/// ```
/// #![feature(str_split_whitespace_as_str)]
///
/// let mut split = "Mary had a little lamb".split_whitespace();
/// assert_eq!(split.as_str(), "Mary had a little lamb");
///
/// split.next();
/// assert_eq!(split.as_str(), "had a little lamb");
///
/// split.by_ref().for_each(drop);
/// assert_eq!(split.as_str(), "");
/// ```
#[inline]
#[unstable(feature = "str_split_whitespace_as_str", issue = "77998")]
pub fn as_str(&self) -> &'a str {
self.inner.iter.as_str()
}
}
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")] #[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
impl<'a> Iterator for SplitAsciiWhitespace<'a> { impl<'a> Iterator for SplitAsciiWhitespace<'a> {
type Item = &'a str; type Item = &'a str;
@ -1231,6 +1255,35 @@ impl<'a> DoubleEndedIterator for SplitAsciiWhitespace<'a> {
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")] #[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
impl FusedIterator for SplitAsciiWhitespace<'_> {} impl FusedIterator for SplitAsciiWhitespace<'_> {}
impl<'a> SplitAsciiWhitespace<'a> {
/// Returns remainder of the splitted string
///
/// # Examples
///
/// ```
/// #![feature(str_split_whitespace_as_str)]
///
/// let mut split = "Mary had a little lamb".split_ascii_whitespace();
/// assert_eq!(split.as_str(), "Mary had a little lamb");
///
/// split.next();
/// assert_eq!(split.as_str(), "had a little lamb");
///
/// split.by_ref().for_each(drop);
/// assert_eq!(split.as_str(), "");
/// ```
#[inline]
#[unstable(feature = "str_split_whitespace_as_str", issue = "77998")]
pub fn as_str(&self) -> &'a str {
if self.inner.iter.iter.finished {
return "";
}
// SAFETY: Slice is created from str.
unsafe { crate::str::from_utf8_unchecked(&self.inner.iter.iter.v) }
}
}
#[stable(feature = "split_inclusive", since = "1.51.0")] #[stable(feature = "split_inclusive", since = "1.51.0")]
impl<'a, P: Pattern<'a>> Iterator for SplitInclusive<'a, P> { impl<'a, P: Pattern<'a>> Iterator for SplitInclusive<'a, P> {
type Item = &'a str; type Item = &'a str;

View File

@ -401,9 +401,10 @@
#![stable(feature = "rust1", since = "1.0.0")] #![stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(reason = "moved to `std::ops::Bound`", since = "1.52.0")] // FIXME(#82080) The deprecation here is only theoretical, and does not actually produce a warning.
#[rustc_deprecated(reason = "moved to `std::ops::Bound`", since = "1.26.0")]
#[doc(hidden)] #[doc(hidden)]
pub type Bound<T> = crate::ops::Bound<T>; pub use crate::ops::Bound;
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use alloc_crate::collections::{binary_heap, btree_map, btree_set}; pub use alloc_crate::collections::{binary_heap, btree_map, btree_set};

View File

@ -1,3 +1,4 @@
// ignore-tidy-filelength
// Local js definitions: // Local js definitions:
/* global addClass, getSettingValue, hasClass */ /* global addClass, getSettingValue, hasClass */
/* global onEach, onEachLazy, hasOwnProperty, removeClass, updateLocalStorage */ /* global onEach, onEachLazy, hasOwnProperty, removeClass, updateLocalStorage */
@ -374,28 +375,35 @@ function defocusSearchBar() {
} }
} }
function getHelpElement() { function getHelpElement(build) {
buildHelperPopup(); if (build !== false) {
buildHelperPopup();
}
return document.getElementById("help"); return document.getElementById("help");
} }
function displayHelp(display, ev, help) { function displayHelp(display, ev, help) {
help = help ? help : getHelpElement();
if (display === true) { if (display === true) {
help = help ? help : getHelpElement(true);
if (hasClass(help, "hidden")) { if (hasClass(help, "hidden")) {
ev.preventDefault(); ev.preventDefault();
removeClass(help, "hidden"); removeClass(help, "hidden");
addClass(document.body, "blur"); addClass(document.body, "blur");
} }
} else if (hasClass(help, "hidden") === false) { } else {
ev.preventDefault(); // No need to build the help popup if we want to hide it in case it hasn't been
addClass(help, "hidden"); // built yet...
removeClass(document.body, "blur"); help = help ? help : getHelpElement(false);
if (help && hasClass(help, "hidden") === false) {
ev.preventDefault();
addClass(help, "hidden");
removeClass(document.body, "blur");
}
} }
} }
function handleEscape(ev) { function handleEscape(ev) {
var help = getHelpElement(); var help = getHelpElement(false);
var search = getSearchElement(); var search = getSearchElement();
if (hasClass(help, "hidden") === false) { if (hasClass(help, "hidden") === false) {
displayHelp(false, ev, help); displayHelp(false, ev, help);
@ -558,6 +566,7 @@ function defocusSearchBar() {
}()); }());
document.addEventListener("click", function(ev) { document.addEventListener("click", function(ev) {
var helpElem = getHelpElement(false);
if (hasClass(ev.target, "help-button")) { if (hasClass(ev.target, "help-button")) {
displayHelp(true, ev); displayHelp(true, ev);
} else if (hasClass(ev.target, "collapse-toggle")) { } else if (hasClass(ev.target, "collapse-toggle")) {
@ -566,11 +575,10 @@ function defocusSearchBar() {
collapseDocs(ev.target.parentNode, "toggle"); collapseDocs(ev.target.parentNode, "toggle");
} else if (ev.target.tagName === "SPAN" && hasClass(ev.target.parentNode, "line-numbers")) { } else if (ev.target.tagName === "SPAN" && hasClass(ev.target.parentNode, "line-numbers")) {
handleSourceHighlight(ev); handleSourceHighlight(ev);
} else if (hasClass(getHelpElement(), "hidden") === false) { } else if (helpElem && hasClass(helpElem, "hidden") === false) {
var help = getHelpElement(); var is_inside_help_popup = ev.target !== helpElem && helpElem.contains(ev.target);
var is_inside_help_popup = ev.target !== help && help.contains(ev.target);
if (is_inside_help_popup === false) { if (is_inside_help_popup === false) {
addClass(help, "hidden"); addClass(helpElem, "hidden");
removeClass(document.body, "blur"); removeClass(document.body, "blur");
} }
} else { } else {

@ -1 +1 @@
Subproject commit 62a1ddde22c267249eda72184520a21ad2052f0b Subproject commit c3a26cbf6e73f2c5f8d03cee1f151d90a266ef3c

View File

@ -1,4 +1,4 @@
// compile-flags: -Z mir-opt-level=4 // compile-flags: -Z mir-opt-level=4 -Z unsound-mir-opts
// EMIT_MIR early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff // EMIT_MIR early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff
fn opt1(x: Option<u32>, y: Option<u32>) -> u32 { fn opt1(x: Option<u32>, y: Option<u32>) -> u32 {
match (x, y) { match (x, y) {

View File

@ -1,4 +1,4 @@
// compile-flags: -Z mir-opt-level=4 // compile-flags: -Z mir-opt-level=4 -Z unsound-mir-opts
// EMIT_MIR early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff // EMIT_MIR early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
fn opt1(x: Option<u32>, y: Option<u32>, z: Option<u32>) -> u32 { fn opt1(x: Option<u32>, y: Option<u32>, z: Option<u32>) -> u32 {

View File

@ -0,0 +1,9 @@
fn foo<const N: usize>() -> [u8; N] {
bar::<N>() //~ ERROR mismatched types
}
fn bar<const N: u8>() -> [u8; N] {}
//~^ ERROR mismatched types
//~| ERROR mismatched types
fn main() {}

View File

@ -0,0 +1,23 @@
error[E0308]: mismatched types
--> $DIR/type_mismatch.rs:2:11
|
LL | bar::<N>()
| ^ expected `u8`, found `usize`
error[E0308]: mismatched types
--> $DIR/type_mismatch.rs:5:31
|
LL | fn bar<const N: u8>() -> [u8; N] {}
| ^ expected `usize`, found `u8`
error[E0308]: mismatched types
--> $DIR/type_mismatch.rs:5:26
|
LL | fn bar<const N: u8>() -> [u8; N] {}
| --- ^^^^^^^ expected array `[u8; N]`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0308`.

View File

@ -0,0 +1,11 @@
impl X {
//~^ ERROR cannot find type
fn getn<const N: usize>() -> [u8; N] {
getn::<N>()
}
}
fn getn<const N: cfg_attr>() -> [u8; N] {}
//~^ ERROR expected type, found built-in attribute `cfg_attr`
//~| ERROR mismatched types
fn main() {}

View File

@ -0,0 +1,24 @@
error[E0412]: cannot find type `X` in this scope
--> $DIR/type_not_in_scope.rs:1:6
|
LL | impl X {
| ^ not found in this scope
error[E0573]: expected type, found built-in attribute `cfg_attr`
--> $DIR/type_not_in_scope.rs:7:18
|
LL | fn getn<const N: cfg_attr>() -> [u8; N] {}
| ^^^^^^^^ not a type
error[E0308]: mismatched types
--> $DIR/type_not_in_scope.rs:7:33
|
LL | fn getn<const N: cfg_attr>() -> [u8; N] {}
| ---- ^^^^^^^ expected array `[u8; N]`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0308, E0412, E0573.
For more information about an error, try `rustc --explain E0308`.