diff --git a/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl b/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl new file mode 100644 index 0000000000000..2ce417a8c7864 --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl @@ -0,0 +1,8 @@ +hir_typeck_fru_note = this expression may have been misinterpreted as a `..` range expression +hir_typeck_fru_expr = this expression does not end in a comma... +hir_typeck_fru_expr2 = ... so this is interpreted as a `..` range expression, instead of functional record update syntax +hir_typeck_fru_suggestion = + to set the remaining fields{$expr -> + [NONE]{""} + *[other] {" "}from `{$expr}` + }, separate the last named field with a comma diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index d7f9148091ce4..1b35021db3d4b 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -51,6 +51,7 @@ fluent_messages! { errors => "../locales/en-US/errors.ftl", expand => "../locales/en-US/expand.ftl", hir_analysis => "../locales/en-US/hir_analysis.ftl", + hir_typeck => "../locales/en-US/hir_typeck.ftl", infer => "../locales/en-US/infer.ftl", interface => "../locales/en-US/interface.ftl", lint => "../locales/en-US/lint.ftl", diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index f3f1c7534b0a3..f8747386c0498 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -467,6 +467,9 @@ pub enum StashKey { /// When an invalid lifetime e.g. `'2` should be reinterpreted /// as a char literal in the parser LifetimeIsChar, + /// Maybe there was a typo where a comma was forgotten before + /// FRU syntax + MaybeFruTypo, } fn default_track_diagnostic(_: &Diagnostic) {} diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index afac6e7d94a81..32265bcca4534 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -1,4 +1,5 @@ //! Errors emitted by `rustc_hir_analysis`. +use rustc_errors::{AddToDiagnostic, Applicability, Diagnostic, MultiSpan, SubdiagnosticMessage}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::Ty; use rustc_span::{symbol::Ident, Span}; @@ -133,3 +134,41 @@ pub struct OpMethodGenericParams { pub span: Span, pub method_name: String, } + +pub struct TypeMismatchFruTypo { + /// Span of the LHS of the range + pub expr_span: Span, + /// Span of the `..RHS` part of the range + pub fru_span: Span, + /// Rendered expression of the RHS of the range + pub expr: Option, +} + +impl AddToDiagnostic for TypeMismatchFruTypo { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) + where + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, + { + diag.set_arg("expr", self.expr.as_deref().unwrap_or("NONE")); + + // Only explain that `a ..b` is a range if it's split up + if self.expr_span.between(self.fru_span).is_empty() { + diag.span_note( + self.expr_span.to(self.fru_span), + rustc_errors::fluent::hir_typeck_fru_note, + ); + } else { + let mut multispan: MultiSpan = vec![self.expr_span, self.fru_span].into(); + multispan.push_span_label(self.expr_span, rustc_errors::fluent::hir_typeck_fru_expr); + multispan.push_span_label(self.fru_span, rustc_errors::fluent::hir_typeck_fru_expr2); + diag.span_note(multispan, rustc_errors::fluent::hir_typeck_fru_note); + } + + diag.span_suggestion( + self.expr_span.shrink_to_hi(), + rustc_errors::fluent::hir_typeck_fru_suggestion, + ", ", + Applicability::MaybeIncorrect, + ); + } +} diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 752d2e0ff7858..2764de751b08b 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -5,6 +5,7 @@ use crate::cast; use crate::coercion::CoerceMany; use crate::coercion::DynamicCoerceMany; +use crate::errors::TypeMismatchFruTypo; use crate::errors::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive}; use crate::errors::{ FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct, @@ -1616,10 +1617,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.demand_coerce_diag(&field.expr, ty, field_type, None, AllowTwoPhase::No); if let Some(mut diag) = diag { - if idx == ast_fields.len() - 1 && remaining_fields.is_empty() { - self.suggest_fru_from_range(field, variant, substs, &mut diag); + if idx == ast_fields.len() - 1 { + if remaining_fields.is_empty() { + self.suggest_fru_from_range(field, variant, substs, &mut diag); + diag.emit(); + } else { + diag.stash(field.span, StashKey::MaybeFruTypo); + } + } else { + diag.emit(); } - diag.emit(); } } @@ -1877,19 +1884,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .map(|adt| adt.did()) != range_def_id { - let instead = self + // Suppress any range expr type mismatches + if let Some(mut diag) = self + .tcx + .sess + .diagnostic() + .steal_diagnostic(last_expr_field.span, StashKey::MaybeFruTypo) + { + diag.delay_as_bug(); + } + + // Use a (somewhat arbitrary) filtering heuristic to avoid printing + // expressions that are either too long, or have control character + //such as newlines in them. + let expr = self .tcx .sess .source_map() .span_to_snippet(range_end.expr.span) - .map(|s| format!(" from `{s}`")) - .unwrap_or_default(); - err.span_suggestion( - range_start.span.shrink_to_hi(), - &format!("to set the remaining fields{instead}, separate the last named field with a comma"), - ",", - Applicability::MaybeIncorrect, - ); + .ok() + .filter(|s| s.len() < 25 && !s.contains(|c: char| c.is_control())); + + let fru_span = self + .tcx + .sess + .source_map() + .span_extend_while(range_start.span, |c| c.is_whitespace()) + .unwrap_or(range_start.span).shrink_to_hi().to(range_end.span); + + err.subdiagnostic(TypeMismatchFruTypo { + expr_span: range_start.span, + fru_span, + expr, + }); } } diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 8a77193471234..1d9c4460ec92a 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -46,8 +46,8 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT; /// is done is *very* inefficient for modern computer architectures. In particular, every element /// is stored in its own individually heap-allocated node. This means that every single insertion /// triggers a heap-allocation, and every single comparison should be a cache-miss. Since these -/// are both notably expensive things to do in practice, we are forced to at very least reconsider -/// the BST strategy. +/// are both notably expensive things to do in practice, we are forced to, at the very least, +/// reconsider the BST strategy. /// /// A B-Tree instead makes each node contain B-1 to 2B-1 elements in a contiguous array. By doing /// this, we reduce the number of allocations by a factor of B, and improve cache efficiency in diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 5f307069d8076..38e31b1802a42 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1091,10 +1091,11 @@ impl Rc { /// /// # Safety /// - /// Any other `Rc` or [`Weak`] pointers to the same allocation must not be dereferenced - /// for the duration of the returned borrow. - /// This is trivially the case if no such pointers exist, - /// for example immediately after `Rc::new`. + /// If any other `Rc` or [`Weak`] pointers to the same allocation exist, then + /// they must be must not be dereferenced or have active borrows for the duration + /// of the returned borrow, and their inner type must be exactly the same as the + /// inner type of this Rc (including lifetimes). This is trivially the case if no + /// such pointers exist, for example immediately after `Rc::new`. /// /// # Examples /// @@ -1109,6 +1110,38 @@ impl Rc { /// } /// assert_eq!(*x, "foo"); /// ``` + /// Other `Rc` pointers to the same allocation must be to the same type. + /// ```no_run + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let x: Rc = Rc::from("Hello, world!"); + /// let mut y: Rc<[u8]> = x.clone().into(); + /// unsafe { + /// // this is Undefined Behavior, because x's inner type is str, not [u8] + /// Rc::get_mut_unchecked(&mut y).fill(0xff); // 0xff is invalid in UTF-8 + /// } + /// println!("{}", &*x); // Invalid UTF-8 in a str + /// ``` + /// Other `Rc` pointers to the same allocation must be to the exact same type, including lifetimes. + /// ```no_run + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let x: Rc<&str> = Rc::new("Hello, world!"); + /// { + /// let s = String::from("Oh, no!"); + /// let mut y: Rc<&str> = x.clone().into(); + /// unsafe { + /// // this is Undefined Behavior, because x's inner type + /// // is &'long str, not &'short str + /// *Rc::get_mut_unchecked(&mut y) = &s; + /// } + /// } + /// println!("{}", &*x); // Use-after-free + /// ``` #[inline] #[unstable(feature = "get_mut_unchecked", issue = "63292")] pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index b69f6b0311234..f7dc4d1094ca3 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1587,10 +1587,11 @@ impl Arc { /// /// # Safety /// - /// Any other `Arc` or [`Weak`] pointers to the same allocation must not be dereferenced - /// for the duration of the returned borrow. - /// This is trivially the case if no such pointers exist, - /// for example immediately after `Arc::new`. + /// If any other `Arc` or [`Weak`] pointers to the same allocation exist, then + /// they must be must not be dereferenced or have active borrows for the duration + /// of the returned borrow, and their inner type must be exactly the same as the + /// inner type of this Rc (including lifetimes). This is trivially the case if no + /// such pointers exist, for example immediately after `Arc::new`. /// /// # Examples /// @@ -1605,6 +1606,38 @@ impl Arc { /// } /// assert_eq!(*x, "foo"); /// ``` + /// Other `Arc` pointers to the same allocation must be to the same type. + /// ```no_run + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let x: Arc = Arc::from("Hello, world!"); + /// let mut y: Arc<[u8]> = x.clone().into(); + /// unsafe { + /// // this is Undefined Behavior, because x's inner type is str, not [u8] + /// Arc::get_mut_unchecked(&mut y).fill(0xff); // 0xff is invalid in UTF-8 + /// } + /// println!("{}", &*x); // Invalid UTF-8 in a str + /// ``` + /// Other `Arc` pointers to the same allocation must be to the exact same type, including lifetimes. + /// ```no_run + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let x: Arc<&str> = Arc::new("Hello, world!"); + /// { + /// let s = String::from("Oh, no!"); + /// let mut y: Arc<&str> = x.clone().into(); + /// unsafe { + /// // this is Undefined Behavior, because x's inner type + /// // is &'long str, not &'short str + /// *Arc::get_mut_unchecked(&mut y) = &s; + /// } + /// } + /// println!("{}", &*x); // Use-after-free + /// ``` #[inline] #[unstable(feature = "get_mut_unchecked", issue = "63292")] pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs new file mode 100644 index 0000000000000..fc2a5b89c1498 --- /dev/null +++ b/library/core/src/arch.rs @@ -0,0 +1,30 @@ +#![doc = include_str!("../../stdarch/crates/core_arch/src/core_arch_docs.md")] + +#[stable(feature = "simd_arch", since = "1.27.0")] +pub use crate::core_arch::arch::*; + +/// Inline assembly. +/// +/// Refer to [rust by example] for a usage guide and the [reference] for +/// detailed information about the syntax and available options. +/// +/// [rust by example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html +/// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html +#[stable(feature = "asm", since = "1.59.0")] +#[rustc_builtin_macro] +pub macro asm("assembly template", $(operands,)* $(options($(option),*))?) { + /* compiler built-in */ +} + +/// Module-level inline assembly. +/// +/// Refer to [rust by example] for a usage guide and the [reference] for +/// detailed information about the syntax and available options. +/// +/// [rust by example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html +/// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html +#[stable(feature = "global_asm", since = "1.59.0")] +#[rustc_builtin_macro] +pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))?) { + /* compiler built-in */ +} diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 848eccd7f2908..e7ea558a95534 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -89,6 +89,7 @@ // Lints: #![deny(rust_2021_incompatible_or_patterns)] #![deny(unsafe_op_in_unsafe_fn)] +#![deny(fuzzy_provenance_casts)] #![warn(deprecated_in_future)] #![warn(missing_debug_implementations)] #![warn(missing_docs)] @@ -162,6 +163,7 @@ #![feature(slice_ptr_get)] #![feature(slice_split_at_unchecked)] #![feature(str_internals)] +#![feature(strict_provenance)] #![feature(utf16_extra)] #![feature(utf16_extra_const)] #![feature(variant_count)] @@ -392,38 +394,8 @@ pub mod primitive; #[unstable(feature = "stdsimd", issue = "48556")] mod core_arch; -#[doc = include_str!("../../stdarch/crates/core_arch/src/core_arch_docs.md")] #[stable(feature = "simd_arch", since = "1.27.0")] -pub mod arch { - #[stable(feature = "simd_arch", since = "1.27.0")] - pub use crate::core_arch::arch::*; - - /// Inline assembly. - /// - /// Refer to [rust by example] for a usage guide and the [reference] for - /// detailed information about the syntax and available options. - /// - /// [rust by example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html - /// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html - #[stable(feature = "asm", since = "1.59.0")] - #[rustc_builtin_macro] - pub macro asm("assembly template", $(operands,)* $(options($(option),*))?) { - /* compiler built-in */ - } - - /// Module-level inline assembly. - /// - /// Refer to [rust by example] for a usage guide and the [reference] for - /// detailed information about the syntax and available options. - /// - /// [rust by example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html - /// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html - #[stable(feature = "global_asm", since = "1.59.0")] - #[rustc_builtin_macro] - pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))?) { - /* compiler built-in */ - } -} +pub mod arch; // Pull in the `core_simd` crate directly into libcore. The contents of // `core_simd` are in a different repository: rust-lang/portable-simd. diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 8a3eee0dc529f..af64fbc8e9eca 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -140,6 +140,7 @@ impl *const T { /// assert_eq!(<*const u8>::from_bits(1), dangling); /// ``` #[unstable(feature = "ptr_to_from_bits", issue = "91126")] + #[allow(fuzzy_provenance_casts)] // this is an unstable and semi-deprecated cast function pub fn from_bits(bits: usize) -> Self where T: Sized, diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 73923753a3020..89b11637ecabe 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -616,6 +616,7 @@ pub const fn invalid_mut(addr: usize) -> *mut T { #[inline] #[unstable(feature = "strict_provenance", issue = "95228")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +#[allow(fuzzy_provenance_casts)] // this *is* the strict provenance API one should use instead pub fn from_exposed_addr(addr: usize) -> *const T where T: Sized, @@ -653,6 +654,7 @@ where #[inline] #[unstable(feature = "strict_provenance", issue = "95228")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +#[allow(fuzzy_provenance_casts)] // this *is* the strict provenance API one should use instead pub fn from_exposed_addr_mut(addr: usize) -> *mut T where T: Sized, diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 8472b05ddbd40..d6872ba1c20f0 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -146,6 +146,7 @@ impl *mut T { /// assert_eq!(<*mut u8>::from_bits(1), dangling); /// ``` #[unstable(feature = "ptr_to_from_bits", issue = "91126")] + #[allow(fuzzy_provenance_casts)] // this is an unstable and semi-deprecated cast function pub fn from_bits(bits: usize) -> Self where T: Sized, diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 8a8962828e980..06228976719f5 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -1834,6 +1834,20 @@ impl<'a, T> ChunksExact<'a, T> { /// Returns the remainder of the original slice that is not going to be /// returned by the iterator. The returned slice has at most `chunk_size-1` /// elements. + /// + /// # Example + /// + /// ``` + /// let slice = ['l', 'o', 'r', 'e', 'm']; + /// let mut iter = slice.chunks_exact(2); + /// assert_eq!(iter.remainder(), &['m'][..]); + /// assert_eq!(iter.next(), Some(&['l', 'o'][..])); + /// assert_eq!(iter.remainder(), &['m'][..]); + /// assert_eq!(iter.next(), Some(&['r', 'e'][..])); + /// assert_eq!(iter.remainder(), &['m'][..]); + /// assert_eq!(iter.next(), None); + /// assert_eq!(iter.remainder(), &['m'][..]); + /// ``` #[must_use] #[stable(feature = "chunks_exact", since = "1.31.0")] pub fn remainder(&self) -> &'a [T] { @@ -2869,7 +2883,7 @@ unsafe impl Sync for RChunksMut<'_, T> where T: Sync {} /// ``` /// /// [`rchunks_exact`]: slice::rchunks_exact -/// [`remainder`]: ChunksExact::remainder +/// [`remainder`]: RChunksExact::remainder /// [slices]: slice #[derive(Debug)] #[stable(feature = "rchunks", since = "1.31.0")] @@ -2892,6 +2906,20 @@ impl<'a, T> RChunksExact<'a, T> { /// Returns the remainder of the original slice that is not going to be /// returned by the iterator. The returned slice has at most `chunk_size-1` /// elements. + /// + /// # Example + /// + /// ``` + /// let slice = ['l', 'o', 'r', 'e', 'm']; + /// let mut iter = slice.rchunks_exact(2); + /// assert_eq!(iter.remainder(), &['l'][..]); + /// assert_eq!(iter.next(), Some(&['e', 'm'][..])); + /// assert_eq!(iter.remainder(), &['l'][..]); + /// assert_eq!(iter.next(), Some(&['o', 'r'][..])); + /// assert_eq!(iter.remainder(), &['l'][..]); + /// assert_eq!(iter.next(), None); + /// assert_eq!(iter.remainder(), &['l'][..]); + /// ``` #[must_use] #[stable(feature = "rchunks", since = "1.31.0")] pub fn remainder(&self) -> &'a [T] { @@ -3031,7 +3059,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for RChunksExact<'a, T> { /// ``` /// /// [`rchunks_exact_mut`]: slice::rchunks_exact_mut -/// [`into_remainder`]: ChunksExactMut::into_remainder +/// [`into_remainder`]: RChunksExactMut::into_remainder /// [slices]: slice #[derive(Debug)] #[stable(feature = "rchunks", since = "1.31.0")] diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 4c0c0da652f95..68f7dcdd5d6aa 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -109,6 +109,7 @@ #![feature(utf8_chunks)] #![feature(is_ascii_octdigit)] #![deny(unsafe_op_in_unsafe_fn)] +#![deny(fuzzy_provenance_casts)] extern crate test; diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index 390148550a4b3..90bc83510803f 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -677,7 +677,7 @@ fn align_offset_issue_103361() { #[cfg(target_pointer_width = "16")] const SIZE: usize = 1 << 13; struct HugeSize([u8; SIZE - 1]); - let _ = (SIZE as *const HugeSize).align_offset(SIZE); + let _ = ptr::invalid::(SIZE).align_offset(SIZE); } #[test] diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs index 15500f7fd3543..a218910f0ec4d 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -275,7 +275,7 @@ if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] { } // cfg_if! cfg_if::cfg_if! { -if #[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))] { +if #[cfg(all(windows, any(target_arch = "aarch64", target_arch = "x86_64"), target_env = "gnu"))] { // We declare these as opaque types. This is fine since you just need to // pass them to _GCC_specific_handler and forget about them. pub enum EXCEPTION_RECORD {} diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index e1a108cea9574..a59dc4f87a68e 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -383,9 +383,9 @@ dependencies = [ [[package]] name = "ntapi" -version = "0.3.7" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" +checksum = "bc51db7b362b205941f71232e56c625156eb9a929f8cf74a428fd5bc094a4afc" dependencies = [ "winapi", ] @@ -607,9 +607,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.24.2" +version = "0.26.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2809487b962344ca55d9aea565f9ffbcb6929780802217acc82561f6746770" +checksum = "c375d5fd899e32847b8566e10598d6e9f1d9b55ec6de3cdf9e7da4bdc51371bc" dependencies = [ "cfg-if", "core-foundation-sys", diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index f74738437ea3a..813c807560599 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -54,7 +54,7 @@ xz2 = "0.1" walkdir = "2" # Dependencies needed by the build-metrics feature -sysinfo = { version = "0.24.1", optional = true } +sysinfo = { version = "0.26.0", optional = true } [target.'cfg(windows)'.dependencies.winapi] version = "0.3" diff --git a/src/bootstrap/metrics.rs b/src/bootstrap/metrics.rs index 451febddc88ce..c823dc7968465 100644 --- a/src/bootstrap/metrics.rs +++ b/src/bootstrap/metrics.rs @@ -97,7 +97,7 @@ impl BuildMetrics { cpu_threads_count: system.cpus().len(), cpu_model: system.cpus()[0].brand().into(), - memory_total_bytes: system.total_memory() * 1024, + memory_total_bytes: system.total_memory(), }; let steps = std::mem::take(&mut state.finished_steps); diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 75b3dce2eda86..2a109ffbc608d 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -723,12 +723,9 @@ function loadCss(cssUrl) { }); }; - (function() { - // To avoid checking on "rustdoc-line-numbers" value on every loop... - if (getSettingValue("line-numbers") === "true") { - window.rustdoc_add_line_numbers_to_examples(); - } - }()); + if (getSettingValue("line-numbers") === "true") { + window.rustdoc_add_line_numbers_to_examples(); + } let oldSidebarScrollPosition = null; diff --git a/src/test/ui/structs/multi-line-fru-suggestion.rs b/src/test/ui/structs/multi-line-fru-suggestion.rs new file mode 100644 index 0000000000000..7b2b139142e4c --- /dev/null +++ b/src/test/ui/structs/multi-line-fru-suggestion.rs @@ -0,0 +1,22 @@ +#[derive(Default)] +struct Inner { + a: u8, + b: u8, +} + +#[derive(Default)] +struct Outer { + inner: Inner, + defaulted: u8, +} + +fn main(){ + Outer { + //~^ ERROR missing field `defaulted` in initializer of `Outer` + inner: Inner { + a: 1, + b: 2, + } + ..Default::default() + }; +} diff --git a/src/test/ui/structs/multi-line-fru-suggestion.stderr b/src/test/ui/structs/multi-line-fru-suggestion.stderr new file mode 100644 index 0000000000000..8bbd3ace7d29e --- /dev/null +++ b/src/test/ui/structs/multi-line-fru-suggestion.stderr @@ -0,0 +1,25 @@ +error[E0063]: missing field `defaulted` in initializer of `Outer` + --> $DIR/multi-line-fru-suggestion.rs:14:5 + | +LL | Outer { + | ^^^^^ missing `defaulted` + | +note: this expression may have been misinterpreted as a `..` range expression + --> $DIR/multi-line-fru-suggestion.rs:16:16 + | +LL | inner: Inner { + | ________________^ +LL | | a: 1, +LL | | b: 2, +LL | | } + | |_________^ this expression does not end in a comma... +LL | ..Default::default() + | ^^^^^^^^^^^^^^^^^^^^ ... so this is interpreted as a `..` range expression, instead of functional record update syntax +help: to set the remaining fields from `Default::default()`, separate the last named field with a comma + | +LL | }, + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0063`. diff --git a/src/test/ui/structs/struct-record-suggestion.fixed b/src/test/ui/structs/struct-record-suggestion.fixed index 49e38b196deb2..d93a62185b3f1 100644 --- a/src/test/ui/structs/struct-record-suggestion.fixed +++ b/src/test/ui/structs/struct-record-suggestion.fixed @@ -7,9 +7,8 @@ struct A { } fn a() { - let q = A { c: 5,..Default::default() }; - //~^ ERROR mismatched types - //~| ERROR missing fields + let q = A { c: 5, ..Default::default() }; + //~^ ERROR missing fields //~| HELP separate the last named field with a comma let r = A { c: 5, ..Default::default() }; assert_eq!(q, r); @@ -21,7 +20,7 @@ struct B { } fn b() { - let q = B { b: 1,..Default::default() }; + let q = B { b: 1, ..Default::default() }; //~^ ERROR mismatched types //~| HELP separate the last named field with a comma let r = B { b: 1 }; diff --git a/src/test/ui/structs/struct-record-suggestion.rs b/src/test/ui/structs/struct-record-suggestion.rs index 901f310c8bdb2..f0fd1c94e9ab5 100644 --- a/src/test/ui/structs/struct-record-suggestion.rs +++ b/src/test/ui/structs/struct-record-suggestion.rs @@ -8,8 +8,7 @@ struct A { fn a() { let q = A { c: 5..Default::default() }; - //~^ ERROR mismatched types - //~| ERROR missing fields + //~^ ERROR missing fields //~| HELP separate the last named field with a comma let r = A { c: 5, ..Default::default() }; assert_eq!(q, r); diff --git a/src/test/ui/structs/struct-record-suggestion.stderr b/src/test/ui/structs/struct-record-suggestion.stderr index 66e9f021ed68f..f4fd655e698b0 100644 --- a/src/test/ui/structs/struct-record-suggestion.stderr +++ b/src/test/ui/structs/struct-record-suggestion.stderr @@ -1,37 +1,38 @@ -error[E0308]: mismatched types - --> $DIR/struct-record-suggestion.rs:10:20 - | -LL | let q = A { c: 5..Default::default() }; - | ^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found struct `std::ops::Range` - | - = note: expected type `u64` - found struct `std::ops::Range<{integer}>` - error[E0063]: missing fields `b` and `d` in initializer of `A` --> $DIR/struct-record-suggestion.rs:10:13 | LL | let q = A { c: 5..Default::default() }; | ^ missing `b` and `d` | +note: this expression may have been misinterpreted as a `..` range expression + --> $DIR/struct-record-suggestion.rs:10:20 + | +LL | let q = A { c: 5..Default::default() }; + | ^^^^^^^^^^^^^^^^^^^^^ help: to set the remaining fields from `Default::default()`, separate the last named field with a comma | -LL | let q = A { c: 5,..Default::default() }; +LL | let q = A { c: 5, ..Default::default() }; | + error[E0308]: mismatched types - --> $DIR/struct-record-suggestion.rs:24:20 + --> $DIR/struct-record-suggestion.rs:23:20 | LL | let q = B { b: 1..Default::default() }; | ^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found struct `std::ops::Range` | = note: expected type `u32` found struct `std::ops::Range<{integer}>` +note: this expression may have been misinterpreted as a `..` range expression + --> $DIR/struct-record-suggestion.rs:23:20 + | +LL | let q = B { b: 1..Default::default() }; + | ^^^^^^^^^^^^^^^^^^^^^ help: to set the remaining fields from `Default::default()`, separate the last named field with a comma | -LL | let q = B { b: 1,..Default::default() }; +LL | let q = B { b: 1, ..Default::default() }; | + -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0063, E0308. For more information about an error, try `rustc --explain E0063`.