diff --git a/Cargo.lock b/Cargo.lock index 284a1ba548262..d01feb99a3eb3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2492,6 +2492,7 @@ dependencies = [ name = "panic_abort" version = "0.0.0" dependencies = [ + "alloc", "cfg-if 0.1.10", "compiler_builtins", "core", diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index c27b39a9d62ff..2bce1ac3c0a21 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -493,7 +493,7 @@ impl DiagnosticSpanLine { h_end: usize, ) -> DiagnosticSpanLine { DiagnosticSpanLine { - text: sf.get_line(index).map_or(String::new(), |l| l.into_owned()), + text: sf.get_line(index).map_or_else(String::new, |l| l.into_owned()), highlight_start: h_start, highlight_end: h_end, } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index f61b6946985e5..a753c4ab6ce96 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -216,9 +216,10 @@ impl<'tcx> InstanceDef<'tcx> { // drops of `Option::None` before LTO. We also respect the intent of // `#[inline]` on `Drop::drop` implementations. return ty.ty_adt_def().map_or(true, |adt_def| { - adt_def.destructor(tcx).map_or(adt_def.is_enum(), |dtor| { - tcx.codegen_fn_attrs(dtor.did).requests_inline() - }) + adt_def.destructor(tcx).map_or_else( + || adt_def.is_enum(), + |dtor| tcx.codegen_fn_attrs(dtor.did).requests_inline(), + ) }); } tcx.codegen_fn_attrs(self.def_id()).requests_inline() diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs index ff11314d2ffd1..416199b384000 100644 --- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs @@ -525,7 +525,7 @@ impl<'sess> OnDiskCache<'sess> { ) { let mut current_diagnostics = self.current_diagnostics.borrow_mut(); - let x = current_diagnostics.entry(dep_node_index).or_insert(Vec::new()); + let x = current_diagnostics.entry(dep_node_index).or_default(); x.extend(Into::>::into(diagnostics)); } diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/outlives_suggestion.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/outlives_suggestion.rs index 7505e6e2dd11e..3629c813bc7a0 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/outlives_suggestion.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/outlives_suggestion.rs @@ -157,7 +157,7 @@ impl OutlivesSuggestionBuilder { debug!("Collected {:?}: {:?}", fr, outlived_fr); // Add to set of constraints for final help note. - self.constraints_to_add.entry(fr).or_insert(Vec::new()).push(outlived_fr); + self.constraints_to_add.entry(fr).or_default().push(outlived_fr); } /// Emit an intermediate note on the given `Diagnostic` if the involved regions are diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index a5fdf064e949b..50db69f420991 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -213,11 +213,13 @@ impl<'a> Iterator for Parser<'a> { Some(String(self.string(pos + 1))) } else { let arg = self.argument(); - if let Some(end) = self.must_consume('}') { - let start = self.to_span_index(pos); - let end = self.to_span_index(end + 1); + if let Some(rbrace_byte_idx) = self.must_consume('}') { + let lbrace_inner_offset = self.to_span_index(pos); + let rbrace_inner_offset = self.to_span_index(rbrace_byte_idx); if self.is_literal { - self.arg_places.push(start.to(end)); + self.arg_places.push( + lbrace_inner_offset.to(InnerOffset(rbrace_inner_offset.0 + 1)), + ); } } Some(NextArgument(arg)) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index f9f33492a1ec3..1377bb781d008 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2327,7 +2327,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ExprKind::Call(ref callee, ref arguments) => { self.resolve_expr(callee, Some(expr)); - let const_args = self.r.legacy_const_generic_args(callee).unwrap_or(Vec::new()); + let const_args = self.r.legacy_const_generic_args(callee).unwrap_or_default(); for (idx, argument) in arguments.iter().enumerate() { // Constant arguments need to be treated as AnonConst since // that is how they will be later lowered to HIR. diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index e85d78db22c56..4c0df2701f5e3 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -184,7 +184,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { PathResult::Module(ModuleOrUniformRoot::Module(module)) => module.res(), _ => None, } - .map_or(String::new(), |res| format!("{} ", res.descr())); + .map_or_else(String::new, |res| format!("{} ", res.descr())); (mod_prefix, format!("`{}`", Segment::names_to_string(mod_path))) }; ( @@ -1042,10 +1042,10 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { if let Some(span) = self.def_span(def_id) { err.span_label(span, &format!("`{}` defined here", path_str)); } - let fields = - self.r.field_names.get(&def_id).map_or("/* fields */".to_string(), |fields| { - vec!["_"; fields.len()].join(", ") - }); + let fields = self.r.field_names.get(&def_id).map_or_else( + || "/* fields */".to_string(), + |fields| vec!["_"; fields.len()].join(", "), + ); err.span_suggestion( span, "use the tuple variant pattern syntax instead", diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index cecdcc9789609..49ebca0502c08 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -163,61 +163,65 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { flags.push((sym::from_desugaring, None)); flags.push((sym::from_desugaring, Some(format!("{:?}", k)))); } - let generics = self.tcx.generics_of(def_id); - let self_ty = trait_ref.self_ty(); - // This is also included through the generics list as `Self`, - // but the parser won't allow you to use it - flags.push((sym::_Self, Some(self_ty.to_string()))); - if let Some(def) = self_ty.ty_adt_def() { - // We also want to be able to select self's original - // signature with no type arguments resolved - flags.push((sym::_Self, Some(self.tcx.type_of(def.did).to_string()))); - } - for param in generics.params.iter() { - let value = match param.kind { - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { - trait_ref.substs[param.index as usize].to_string() - } - GenericParamDefKind::Lifetime => continue, - }; - let name = param.name; - flags.push((name, Some(value))); - } + // Add all types without trimmed paths. + ty::print::with_no_trimmed_paths(|| { + let generics = self.tcx.generics_of(def_id); + let self_ty = trait_ref.self_ty(); + // This is also included through the generics list as `Self`, + // but the parser won't allow you to use it + flags.push((sym::_Self, Some(self_ty.to_string()))); + if let Some(def) = self_ty.ty_adt_def() { + // We also want to be able to select self's original + // signature with no type arguments resolved + flags.push((sym::_Self, Some(self.tcx.type_of(def.did).to_string()))); + } - if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) { - flags.push((sym::crate_local, None)); - } + for param in generics.params.iter() { + let value = match param.kind { + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { + trait_ref.substs[param.index as usize].to_string() + } + GenericParamDefKind::Lifetime => continue, + }; + let name = param.name; + flags.push((name, Some(value))); + } - // Allow targeting all integers using `{integral}`, even if the exact type was resolved - if self_ty.is_integral() { - flags.push((sym::_Self, Some("{integral}".to_owned()))); - } + if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) { + flags.push((sym::crate_local, None)); + } - if let ty::Array(aty, len) = self_ty.kind() { - flags.push((sym::_Self, Some("[]".to_owned()))); - flags.push((sym::_Self, Some(format!("[{}]", aty)))); - if let Some(def) = aty.ty_adt_def() { - // We also want to be able to select the array's type's original - // signature with no type arguments resolved - let type_string = self.tcx.type_of(def.did).to_string(); - flags.push((sym::_Self, Some(format!("[{}]", type_string)))); + // Allow targeting all integers using `{integral}`, even if the exact type was resolved + if self_ty.is_integral() { + flags.push((sym::_Self, Some("{integral}".to_owned()))); + } - let len = len.val.try_to_value().and_then(|v| v.try_to_machine_usize(self.tcx)); - let string = match len { - Some(n) => format!("[{}; {}]", type_string, n), - None => format!("[{}; _]", type_string), - }; - flags.push((sym::_Self, Some(string))); + if let ty::Array(aty, len) = self_ty.kind() { + flags.push((sym::_Self, Some("[]".to_owned()))); + flags.push((sym::_Self, Some(format!("[{}]", aty)))); + if let Some(def) = aty.ty_adt_def() { + // We also want to be able to select the array's type's original + // signature with no type arguments resolved + let type_string = self.tcx.type_of(def.did).to_string(); + flags.push((sym::_Self, Some(format!("[{}]", type_string)))); + + let len = len.val.try_to_value().and_then(|v| v.try_to_machine_usize(self.tcx)); + let string = match len { + Some(n) => format!("[{}; {}]", type_string, n), + None => format!("[{}; _]", type_string), + }; + flags.push((sym::_Self, Some(string))); + } } - } - if let ty::Dynamic(traits, _) = self_ty.kind() { - for t in traits.iter() { - if let ty::ExistentialPredicate::Trait(trait_ref) = t.skip_binder() { - flags.push((sym::_Self, Some(self.tcx.def_path_str(trait_ref.def_id)))) + if let ty::Dynamic(traits, _) = self_ty.kind() { + for t in traits.iter() { + if let ty::ExistentialPredicate::Trait(trait_ref) = t.skip_binder() { + flags.push((sym::_Self, Some(self.tcx.def_path_str(trait_ref.def_id)))) + } } } - } + }); if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, trait_ref.def_id, def_id) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 46e1a3a4aa2fe..e75a36477188c 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -81,8 +81,8 @@ fn _assert_is_object_safe(_: &dyn Iterator) {} ), on( _Self = "[]", - label = "borrow the array with `&` or call `.iter()` on it to iterate over it", - note = "arrays are not iterators, but slices like the following are: `&[1, 2, 3]`" + label = "arrays do not yet implement `IntoIterator`; try using `std::array::IntoIter::new(arr)`", + note = "see for more details" ), on( _Self = "{integral}", diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index f0bd976ba83d5..6032dc9a2d371 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -2,6 +2,7 @@ #![stable(feature = "rust1", since = "1.0.0")] +use crate::ascii; use crate::intrinsics; use crate::mem; use crate::str::FromStr; @@ -661,6 +662,31 @@ impl u8 { pub const fn is_ascii_control(&self) -> bool { matches!(*self, b'\0'..=b'\x1F' | b'\x7F') } + + /// Returns an iterator that produces an escaped version of a `u8`, + /// treating it as an ASCII character. + /// + /// The behavior is identical to [`ascii::escape_default`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(inherent_ascii_escape)] + /// + /// assert_eq!("0", b'0'.escape_ascii().to_string()); + /// assert_eq!("\\t", b'\t'.escape_ascii().to_string()); + /// assert_eq!("\\r", b'\r'.escape_ascii().to_string()); + /// assert_eq!("\\n", b'\n'.escape_ascii().to_string()); + /// assert_eq!("\\'", b'\''.escape_ascii().to_string()); + /// assert_eq!("\\\"", b'"'.escape_ascii().to_string()); + /// assert_eq!("\\\\", b'\\'.escape_ascii().to_string()); + /// assert_eq!("\\x9d", b'\x9d'.escape_ascii().to_string()); + /// ``` + #[unstable(feature = "inherent_ascii_escape", issue = "77174")] + #[inline] + pub fn escape_ascii(&self) -> ascii::EscapeDefault { + ascii::escape_default(*self) + } } #[lang = "u16"] diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 42032bc9035bc..6d46765d7a2c1 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -1,6 +1,10 @@ //! Operations on ASCII `[u8]`. +use crate::ascii; +use crate::fmt::{self, Write}; +use crate::iter; use crate::mem; +use crate::ops; #[lang = "slice_u8"] #[cfg(not(test))] @@ -55,6 +59,95 @@ impl [u8] { byte.make_ascii_lowercase(); } } + + /// Returns an iterator that produces an escaped version of this slice, + /// treating it as an ASCII string. + /// + /// # Examples + /// + /// ``` + /// #![feature(inherent_ascii_escape)] + /// + /// let s = b"0\t\r\n'\"\\\x9d"; + /// let escaped = s.escape_ascii().to_string(); + /// assert_eq!(escaped, "0\\t\\r\\n\\'\\\"\\\\\\x9d"); + /// ``` + #[unstable(feature = "inherent_ascii_escape", issue = "77174")] + pub fn escape_ascii(&self) -> EscapeAscii<'_> { + EscapeAscii { inner: self.iter().flat_map(EscapeByte) } + } +} + +impl_fn_for_zst! { + #[derive(Clone)] + struct EscapeByte impl Fn = |byte: &u8| -> ascii::EscapeDefault { + ascii::escape_default(*byte) + }; +} + +/// An iterator over the escaped version of a byte slice. +/// +/// This `struct` is created by the [`slice::escape_ascii`] method. See its +/// documentation for more information. +#[unstable(feature = "inherent_ascii_escape", issue = "77174")] +#[derive(Clone)] +pub struct EscapeAscii<'a> { + inner: iter::FlatMap, ascii::EscapeDefault, EscapeByte>, +} + +#[unstable(feature = "inherent_ascii_escape", issue = "77174")] +impl<'a> iter::Iterator for EscapeAscii<'a> { + type Item = u8; + #[inline] + fn next(&mut self) -> Option { + self.inner.next() + } + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + #[inline] + fn try_fold(&mut self, init: Acc, fold: Fold) -> R + where + Fold: FnMut(Acc, Self::Item) -> R, + R: ops::Try, + { + self.inner.try_fold(init, fold) + } + #[inline] + fn fold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.inner.fold(init, fold) + } + #[inline] + fn last(mut self) -> Option { + self.next_back() + } +} + +#[unstable(feature = "inherent_ascii_escape", issue = "77174")] +impl<'a> iter::DoubleEndedIterator for EscapeAscii<'a> { + fn next_back(&mut self) -> Option { + self.inner.next_back() + } +} +#[unstable(feature = "inherent_ascii_escape", issue = "77174")] +impl<'a> iter::ExactSizeIterator for EscapeAscii<'a> {} +#[unstable(feature = "inherent_ascii_escape", issue = "77174")] +impl<'a> iter::FusedIterator for EscapeAscii<'a> {} +#[unstable(feature = "inherent_ascii_escape", issue = "77174")] +impl<'a> fmt::Display for EscapeAscii<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.clone().try_for_each(|b| f.write_char(b as char)) + } +} +#[unstable(feature = "inherent_ascii_escape", issue = "77174")] +impl<'a> fmt::Debug for EscapeAscii<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad("EscapeAscii { .. }") + } } /// Returns `true` if any byte in the word `v` is nonascii (>= 128). Snarfed diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 1e9e9c24a4550..ebaa1043cf81e 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -81,6 +81,9 @@ pub use index::SliceIndex; #[unstable(feature = "slice_range", issue = "76393")] pub use index::range; +#[unstable(feature = "inherent_ascii_escape", issue = "77174")] +pub use ascii::EscapeAscii; + #[lang = "slice"] #[cfg(not(test))] impl [T] { diff --git a/library/panic_abort/Cargo.toml b/library/panic_abort/Cargo.toml index caa89aa30d0bb..bdab664cd64fc 100644 --- a/library/panic_abort/Cargo.toml +++ b/library/panic_abort/Cargo.toml @@ -13,6 +13,7 @@ bench = false doc = false [dependencies] +alloc = { path = "../alloc" } cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] } core = { path = "../core" } libc = { version = "0.2", default-features = false } diff --git a/library/panic_abort/src/android.rs b/library/panic_abort/src/android.rs new file mode 100644 index 0000000000000..6c9135e6610ac --- /dev/null +++ b/library/panic_abort/src/android.rs @@ -0,0 +1,44 @@ +use alloc::string::String; +use alloc::vec::Vec; +use core::mem::transmute; +use core::panic::BoxMeUp; + +const ANDROID_SET_ABORT_MESSAGE: &[u8] = b"android_set_abort_message\0"; +type SetAbortMessageType = unsafe extern "C" fn(*const libc::c_char) -> (); + +// Forward the abort message to libc's android_set_abort_message. The fallible allocator is used +// to avoid panicking, as this function may already be called as part of a failed allocation. +// +// Weakly resolve the symbol for android_set_abort_message. This function is only available +// for API >= 21. +pub(crate) unsafe fn android_set_abort_message(payload: *mut &mut dyn BoxMeUp) { + let func_addr = + libc::dlsym(libc::RTLD_DEFAULT, ANDROID_SET_ABORT_MESSAGE.as_ptr() as *const libc::c_char) + as usize; + if func_addr == 0 { + return; + } + + let payload = (*payload).get(); + let msg = match payload.downcast_ref::<&'static str>() { + Some(msg) => msg.as_bytes(), + None => match payload.downcast_ref::() { + Some(msg) => msg.as_bytes(), + None => &[], + }, + }; + if msg.is_empty() { + return; + } + + let size = msg.len() + 1; + let mut v = Vec::new(); + if v.try_reserve(size).is_err() { + return; + } + + v.extend(msg); + v.push(0); + let func = transmute::(func_addr); + func(v.as_ptr() as *const libc::c_char); +} diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index eb2277d8baacd..64491474f664c 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -18,6 +18,9 @@ #![feature(staged_api)] #![feature(rustc_attrs)] #![feature(asm)] +#![cfg_attr(target_os = "android", feature(try_reserve))] +#[cfg(target_os = "android")] +mod android; use core::any::Any; use core::panic::BoxMeUp; @@ -31,6 +34,10 @@ pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Sen // "Leak" the payload and shim to the relevant abort on the platform in question. #[rustc_std_internal_symbol] pub unsafe extern "C" fn __rust_start_panic(_payload: *mut &mut dyn BoxMeUp) -> u32 { + // Android has the ability to attach a message as part of the abort. + #[cfg(target_os = "android")] + android::android_set_abort_message(_payload); + abort(); cfg_if::cfg_if! { diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 01f1318fe8078..53916cb9abdea 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -535,7 +535,7 @@ impl From for ExitStatus { impl fmt::Display for ExitStatus { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(code) = self.code() { - write!(f, "exit code: {}", code) + write!(f, "exit status: {}", code) } else if let Some(signal) = self.signal() { if self.core_dumped() { write!(f, "signal: {} (core dumped)", signal) diff --git a/library/std/src/sys/unix/process/process_unix/tests.rs b/library/std/src/sys/unix/process/process_unix/tests.rs index 5819d2c2a5a26..02c469fbcdfd8 100644 --- a/library/std/src/sys/unix/process/process_unix/tests.rs +++ b/library/std/src/sys/unix/process/process_unix/tests.rs @@ -9,8 +9,8 @@ fn exitstatus_display_tests() { t(0x0000f, "signal: 15"); t(0x0008b, "signal: 11 (core dumped)"); - t(0x00000, "exit code: 0"); - t(0x0ff00, "exit code: 255"); + t(0x00000, "exit status: 0"); + t(0x0ff00, "exit status: 255"); // On MacOS, 0x0137f is WIFCONTINUED, not WIFSTOPPED. Probably *BSD is similar. // https://github.com/rust-lang/rust/pull/82749#issuecomment-790525956 diff --git a/library/test/src/helpers/exit_code.rs b/library/test/src/helpers/exit_code.rs index 31e234d981800..50bb260762a70 100644 --- a/library/test/src/helpers/exit_code.rs +++ b/library/test/src/helpers/exit_code.rs @@ -4,7 +4,7 @@ use std::process::ExitStatus; #[cfg(not(unix))] pub fn get_exit_code(status: ExitStatus) -> Result { - status.code().ok_or("received no exit code from child process".into()) + status.code().ok_or_else(|| "received no exit code from child process".into()) } #[cfg(unix)] diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 86d940cd733da..03799a302982d 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1156,6 +1156,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the hostflags.push(format!("-Lnative={}", builder.test_helpers_out(compiler.host).display())); if builder.is_fuse_ld_lld(compiler.host) { hostflags.push("-Clink-args=-fuse-ld=lld".to_string()); + hostflags.push("-Clink-arg=-Wl,--threads=1".to_string()); } cmd.arg("--host-rustcflags").arg(hostflags.join(" ")); @@ -1163,6 +1164,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display())); if builder.is_fuse_ld_lld(target) { targetflags.push("-Clink-args=-fuse-ld=lld".to_string()); + targetflags.push("-Clink-arg=-Wl,--threads=1".to_string()); } cmd.arg("--target-rustcflags").arg(targetflags.join(" ")); diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 1b6a82fed1170..001c8b090448b 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -54,12 +54,10 @@ impl DocFolder for SourceCollector<'_, '_> { self.scx.include_sources = match self.emit_source(&filename) { Ok(()) => true, Err(e) => { - println!( - "warning: source code was requested to be rendered, \ - but processing `{}` had an error: {}", - filename, e + self.scx.tcx.sess.span_err( + item.span.inner(), + &format!("failed to render source code for `{}`: {}", filename, e), ); - println!(" skipping rendering of source code"); false } }; diff --git a/src/test/ui/asm/sym.rs b/src/test/ui/asm/sym.rs index 634ef010e6fea..05cc9b296515a 100644 --- a/src/test/ui/asm/sym.rs +++ b/src/test/ui/asm/sym.rs @@ -1,4 +1,5 @@ // min-llvm-version: 10.0.1 +// compile-flags: -C codegen-units=2 // only-x86_64 // only-linux // run-pass diff --git a/src/test/ui/issues/issue-69225-SCEVAddExpr-wrap-flag.rs b/src/test/ui/issues/issue-69225-SCEVAddExpr-wrap-flag.rs index 6e030f1cc4875..e04dec24e445e 100644 --- a/src/test/ui/issues/issue-69225-SCEVAddExpr-wrap-flag.rs +++ b/src/test/ui/issues/issue-69225-SCEVAddExpr-wrap-flag.rs @@ -1,5 +1,6 @@ // run-fail // compile-flags: -C opt-level=3 +// min-llvm-version: 11.0 // error-pattern: index out of bounds: the len is 0 but the index is 16777216 // ignore-wasm no panic or subprocess support // ignore-emscripten no panic or subprocess support diff --git a/src/test/ui/iterators/array-of-ranges.stderr b/src/test/ui/iterators/array-of-ranges.stderr index 601983a6153fd..7d58eb948ea81 100644 --- a/src/test/ui/iterators/array-of-ranges.stderr +++ b/src/test/ui/iterators/array-of-ranges.stderr @@ -13,10 +13,10 @@ error[E0277]: `[RangeInclusive<{integer}>; 1]` is not an iterator --> $DIR/array-of-ranges.rs:4:14 | LL | for _ in [0..=1] {} - | ^^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it + | ^^^^^^^ if you meant to iterate between two values, remove the square brackets | = help: the trait `Iterator` is not implemented for `[RangeInclusive<{integer}>; 1]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: `[start..=end]` is an array of one `RangeInclusive`; you might have meant to have a `RangeInclusive` without the brackets: `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `[RangeInclusive<{integer}>; 1]` = note: required by `into_iter` @@ -24,10 +24,10 @@ error[E0277]: `[RangeFrom<{integer}>; 1]` is not an iterator --> $DIR/array-of-ranges.rs:6:14 | LL | for _ in [0..] {} - | ^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it + | ^^^^^ if you meant to iterate from a value onwards, remove the square brackets | = help: the trait `Iterator` is not implemented for `[RangeFrom<{integer}>; 1]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: `[start..]` is an array of one `RangeFrom`; you might have meant to have a `RangeFrom` without the brackets: `start..`, keeping in mind that iterating over an unbounded iterator will run forever unless you `break` or `return` from within the loop = note: required because of the requirements on the impl of `IntoIterator` for `[RangeFrom<{integer}>; 1]` = note: required by `into_iter` @@ -35,10 +35,10 @@ error[E0277]: `[RangeTo<{integer}>; 1]` is not an iterator --> $DIR/array-of-ranges.rs:8:14 | LL | for _ in [..1] {} - | ^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it + | ^^^^^ if you meant to iterate until a value, remove the square brackets and add a starting value | = help: the trait `Iterator` is not implemented for `[RangeTo<{integer}>; 1]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: `[..end]` is an array of one `RangeTo`; you might have meant to have a bounded `Range` without the brackets: `0..end` = note: required because of the requirements on the impl of `IntoIterator` for `[RangeTo<{integer}>; 1]` = note: required by `into_iter` @@ -46,10 +46,10 @@ error[E0277]: `[RangeToInclusive<{integer}>; 1]` is not an iterator --> $DIR/array-of-ranges.rs:10:14 | LL | for _ in [..=1] {} - | ^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it + | ^^^^^^ if you meant to iterate until a value (including it), remove the square brackets and add a starting value | = help: the trait `Iterator` is not implemented for `[RangeToInclusive<{integer}>; 1]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: `[..=end]` is an array of one `RangeToInclusive`; you might have meant to have a bounded `RangeInclusive` without the brackets: `0..=end` = note: required because of the requirements on the impl of `IntoIterator` for `[RangeToInclusive<{integer}>; 1]` = note: required by `into_iter` @@ -79,10 +79,10 @@ error[E0277]: `[std::ops::Range<{integer}>; 2]` is not an iterator --> $DIR/array-of-ranges.rs:19:14 | LL | for _ in [0..1, 2..3] {} - | ^^^^^^^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it + | ^^^^^^^^^^^^ arrays do not yet implement `IntoIterator`; try using `std::array::IntoIter::new(arr)` | = help: the trait `Iterator` is not implemented for `[std::ops::Range<{integer}>; 2]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: see for more details = note: required because of the requirements on the impl of `IntoIterator` for `[std::ops::Range<{integer}>; 2]` = note: required by `into_iter` @@ -90,10 +90,10 @@ error[E0277]: `[RangeInclusive<{integer}>; 1]` is not an iterator --> $DIR/array-of-ranges.rs:21:14 | LL | for _ in [0..=1] {} - | ^^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it + | ^^^^^^^ if you meant to iterate between two values, remove the square brackets | = help: the trait `Iterator` is not implemented for `[RangeInclusive<{integer}>; 1]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: `[start..=end]` is an array of one `RangeInclusive`; you might have meant to have a `RangeInclusive` without the brackets: `start..=end` = note: required because of the requirements on the impl of `IntoIterator` for `[RangeInclusive<{integer}>; 1]` = note: required by `into_iter` diff --git a/src/test/ui/iterators/array.stderr b/src/test/ui/iterators/array.stderr index 68c6de5493f13..7e2b600fb7af2 100644 --- a/src/test/ui/iterators/array.stderr +++ b/src/test/ui/iterators/array.stderr @@ -2,10 +2,10 @@ error[E0277]: `[{integer}; 2]` is not an iterator --> $DIR/array.rs:2:14 | LL | for _ in [1, 2] {} - | ^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it + | ^^^^^^ arrays do not yet implement `IntoIterator`; try using `std::array::IntoIter::new(arr)` | = help: the trait `Iterator` is not implemented for `[{integer}; 2]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: see for more details = note: required because of the requirements on the impl of `IntoIterator` for `[{integer}; 2]` = note: required by `into_iter` @@ -13,10 +13,10 @@ error[E0277]: `[{integer}; 2]` is not an iterator --> $DIR/array.rs:5:14 | LL | for _ in x {} - | ^ borrow the array with `&` or call `.iter()` on it to iterate over it + | ^ arrays do not yet implement `IntoIterator`; try using `std::array::IntoIter::new(arr)` | = help: the trait `Iterator` is not implemented for `[{integer}; 2]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: see for more details = note: required because of the requirements on the impl of `IntoIterator` for `[{integer}; 2]` = note: required by `into_iter` @@ -24,10 +24,10 @@ error[E0277]: `[{float}; 2]` is not an iterator --> $DIR/array.rs:7:14 | LL | for _ in [1.0, 2.0] {} - | ^^^^^^^^^^ borrow the array with `&` or call `.iter()` on it to iterate over it + | ^^^^^^^^^^ arrays do not yet implement `IntoIterator`; try using `std::array::IntoIter::new(arr)` | = help: the trait `Iterator` is not implemented for `[{float}; 2]` - = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: see for more details = note: required because of the requirements on the impl of `IntoIterator` for `[{float}; 2]` = note: required by `into_iter` diff --git a/src/test/ui/iterators/ranges.stderr b/src/test/ui/iterators/ranges.stderr index 4678bafd196b5..73844329e361d 100644 --- a/src/test/ui/iterators/ranges.stderr +++ b/src/test/ui/iterators/ranges.stderr @@ -2,9 +2,10 @@ error[E0277]: `RangeTo<{integer}>` is not an iterator --> $DIR/ranges.rs:2:14 | LL | for _ in ..10 {} - | ^^^^ `RangeTo<{integer}>` is not an iterator + | ^^^^ if you meant to iterate until a value, add a starting value | = help: the trait `Iterator` is not implemented for `RangeTo<{integer}>` + = note: `..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a bounded `Range`: `0..end` = note: required because of the requirements on the impl of `IntoIterator` for `RangeTo<{integer}>` = note: required by `into_iter` @@ -12,9 +13,10 @@ error[E0277]: `RangeToInclusive<{integer}>` is not an iterator --> $DIR/ranges.rs:4:14 | LL | for _ in ..=10 {} - | ^^^^^ `RangeToInclusive<{integer}>` is not an iterator + | ^^^^^ if you meant to iterate until a value (including it), add a starting value | = help: the trait `Iterator` is not implemented for `RangeToInclusive<{integer}>` + = note: `..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant to have a bounded `RangeInclusive`: `0..=end` = note: required because of the requirements on the impl of `IntoIterator` for `RangeToInclusive<{integer}>` = note: required by `into_iter` diff --git a/src/test/ui/iterators/string.stderr b/src/test/ui/iterators/string.stderr index 1653006682427..1d77bcb753630 100644 --- a/src/test/ui/iterators/string.stderr +++ b/src/test/ui/iterators/string.stderr @@ -2,7 +2,7 @@ error[E0277]: `String` is not an iterator --> $DIR/string.rs:2:14 | LL | for _ in "".to_owned() {} - | ^^^^^^^^^^^^^ `String` is not an iterator + | ^^^^^^^^^^^^^ `String` is not an iterator; try calling `.chars()` or `.bytes()` | = help: the trait `Iterator` is not implemented for `String` = note: required because of the requirements on the impl of `IntoIterator` for `String` diff --git a/src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs b/src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs index 7b2f5365acaa3..f36f109aa2d1d 100644 --- a/src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs +++ b/src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs @@ -4,6 +4,7 @@ // build-fail // aux-build:def_colliding_external.rs +// compile-flags: -Ccodegen-units=2 extern crate def_colliding_external as dep1; diff --git a/src/test/ui/macros/issue-83344.rs b/src/test/ui/macros/issue-83344.rs new file mode 100644 index 0000000000000..c5f7f72358780 --- /dev/null +++ b/src/test/ui/macros/issue-83344.rs @@ -0,0 +1,6 @@ +// check-fail + +fn main() { + println!("{}\ +"); //~^ ERROR: 1 positional argument in format string, but no arguments were given +} diff --git a/src/test/ui/macros/issue-83344.stderr b/src/test/ui/macros/issue-83344.stderr new file mode 100644 index 0000000000000..1ef70f87a1fb4 --- /dev/null +++ b/src/test/ui/macros/issue-83344.stderr @@ -0,0 +1,8 @@ +error: 1 positional argument in format string, but no arguments were given + --> $DIR/issue-83344.rs:4:15 + | +LL | println!("{}\ + | ^^ + +error: aborting due to previous error + diff --git a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr index 32961b7f87be0..3786457fb1ae3 100644 --- a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr +++ b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr @@ -46,6 +46,7 @@ error[E0277]: `dyn Future + Send` cannot be unpinned LL | Pin::new(x) | ^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future + Send` | + = note: consider using `Box::pin` = note: required by `Pin::

::new` error[E0277]: `dyn Future + Send` cannot be unpinned @@ -54,6 +55,7 @@ error[E0277]: `dyn Future + Send` cannot be unpinned LL | Pin::new(Box::new(x)) | ^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future + Send` | + = note: consider using `Box::pin` = note: required by `Pin::

::new` error[E0308]: mismatched types diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr index 2854b830ba822..26efd50bb8fd3 100644 --- a/src/test/ui/suggestions/into-str.stderr +++ b/src/test/ui/suggestions/into-str.stderr @@ -7,6 +7,7 @@ LL | fn foo<'a, T>(_t: T) where T: Into<&'a str> {} LL | foo(String::new()); | ^^^ the trait `From` is not implemented for `&str` | + = note: to coerce a `String` into a `&str`, use `&*` as a prefix = note: required because of the requirements on the impl of `Into<&str>` for `String` error: aborting due to previous error diff --git a/src/test/ui/suggestions/path-display.stderr b/src/test/ui/suggestions/path-display.stderr index b08e22eaab7bb..3ee2860b4ffc7 100644 --- a/src/test/ui/suggestions/path-display.stderr +++ b/src/test/ui/suggestions/path-display.stderr @@ -2,10 +2,10 @@ error[E0277]: `Path` doesn't implement `std::fmt::Display` --> $DIR/path-display.rs:5:20 | LL | println!("{}", path); - | ^^^^ `Path` cannot be formatted with the default formatter + | ^^^^ `Path` cannot be formatted with the default formatter; call `.display()` on it | = help: the trait `std::fmt::Display` is not implemented for `Path` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data = note: required because of the requirements on the impl of `std::fmt::Display` for `&Path` = note: required by `std::fmt::Display::fmt` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/tools/clippy/tests/ui/write_literal_2.stderr b/src/tools/clippy/tests/ui/write_literal_2.stderr index 5b4883580111b..0aa1b55e58c56 100644 --- a/src/tools/clippy/tests/ui/write_literal_2.stderr +++ b/src/tools/clippy/tests/ui/write_literal_2.stderr @@ -75,8 +75,9 @@ LL | "1", "2", "3", | help: try this | -LL | "some 1{} / {}", "2", "3", - | ^ -- +LL | "some 1/ +LL | {} / {}", "2", "3", + | error: literal with an empty format string --> $DIR/write_literal_2.rs:25:14 diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 7aa3d4ab09e41..d0f61a8c595ea 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1952,6 +1952,7 @@ impl<'test> TestCx<'test> { if !self.props.compile_flags.iter().any(|s| s.starts_with("--error-format")) { rustc.args(&["--error-format", "json"]); } + rustc.arg("-Ccodegen-units=1"); rustc.arg("-Zui-testing"); rustc.arg("-Zdeduplicate-diagnostics=no"); rustc.arg("-Zemit-future-incompat-report");