From c82353790a7f6198795a185f0fc16dbb7df5252a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Tue, 15 Nov 2022 20:54:04 +0100 Subject: [PATCH 01/13] Fix building of `aarch64-pc-windows-gnullvm` That change had been lost during rebase --- library/unwind/src/libunwind.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 {} From 658586c74aee3fa7f844dbd019f17355808967a9 Mon Sep 17 00:00:00 2001 From: klensy Date: Wed, 16 Nov 2022 14:49:54 +0300 Subject: [PATCH 02/13] update ntapi dep to remove future-incompat warning --- src/bootstrap/Cargo.lock | 8 ++++---- src/bootstrap/Cargo.toml | 2 +- src/bootstrap/metrics.rs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) 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); From bb0cb9ae9fb2dbebc62627a3f1f4326771338535 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 16 Nov 2022 19:10:38 +0000 Subject: [PATCH 03/13] Add a detailed note for missing comma in FRU syntax typo --- .../locales/en-US/hir_typeck.ftl | 8 +++ compiler/rustc_error_messages/src/lib.rs | 1 + compiler/rustc_errors/src/lib.rs | 3 ++ compiler/rustc_hir_typeck/src/errors.rs | 39 ++++++++++++++ compiler/rustc_hir_typeck/src/expr.rs | 51 ++++++++++++++----- .../ui/structs/multi-line-fru-suggestion.rs | 22 ++++++++ .../structs/multi-line-fru-suggestion.stderr | 25 +++++++++ .../ui/structs/struct-record-suggestion.fixed | 7 ++- .../ui/structs/struct-record-suggestion.rs | 3 +- .../structs/struct-record-suggestion.stderr | 27 +++++----- 10 files changed, 155 insertions(+), 31 deletions(-) create mode 100644 compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl create mode 100644 src/test/ui/structs/multi-line-fru-suggestion.rs create mode 100644 src/test/ui/structs/multi-line-fru-suggestion.stderr 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 0b1b75471a661..1dbea77ef706c 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 170d4341ae71b..ab518137342d7 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -466,6 +466,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 13a03b33de815..24c38ecc1906f 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, @@ -1614,10 +1615,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(); } } @@ -1875,19 +1882,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/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`. From 7db7cbd49f89ed38212cb062605eaaced2e1bc79 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 18 Nov 2022 11:04:53 -0700 Subject: [PATCH 04/13] rustdoc: remove unused JS IIFE from main.js This [IIFE] made sense when it was added in deaf5e200e79a75ac57d3f0952f6758a38168e52 and there was a local variable scoped to it, but now it calls a function, but declares nothing. [IIFE]: https://developer.mozilla.org/en-US/docs/Glossary/IIFE "immediately invoked function expression" --- src/librustdoc/html/static/js/main.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 874f130d7e23c..da08c33e27f05 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; From 96650fc7143dbacdbb3711e2d60f06401e727cea Mon Sep 17 00:00:00 2001 From: Zachary S Date: Fri, 2 Sep 2022 01:34:34 -0500 Subject: [PATCH 05/13] Clarify and restrict when `{Arc,Rc}::get_mut_unchecked` is allowed. --- library/alloc/src/rc.rs | 9 +++++---- library/alloc/src/sync.rs | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index f3cbfe27b3eed..1e9ed3889e84f 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 /// diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 37e07eb5998b3..2bb5030c51eb6 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1630,10 +1630,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 /// From 8c38cb77090af4c876f1c021b86d6c184c80cc4f Mon Sep 17 00:00:00 2001 From: Zachary S Date: Fri, 2 Sep 2022 00:47:15 -0500 Subject: [PATCH 06/13] Add examples to show when `{Arc,Rc}::get_mut_unchecked` is disallowed. --- library/alloc/src/rc.rs | 32 ++++++++++++++++++++++++++++++++ library/alloc/src/sync.rs | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 1e9ed3889e84f..8ac1b5b488ad9 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1110,6 +1110,38 @@ impl Rc { /// } /// assert_eq!(*x, "foo"); /// ``` + /// Other `Rc` pointers to the same allocation must be to the same type. + /// ```ignore + /// #![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); // Invliad UTF-8 in a str + /// ``` + /// Other `Rc` pointers to the same allocation must be to the exact same type, including lifetimes. + /// ```ignore + /// #![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 2bb5030c51eb6..e4d7bfdaeed69 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1649,6 +1649,38 @@ impl Arc { /// } /// assert_eq!(*x, "foo"); /// ``` + /// Other `Arc` pointers to the same allocation must be to the same type. + /// ```ignore + /// #![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); // Invliad UTF-8 in a str + /// ``` + /// Other `Arc` pointers to the same allocation must be to the exact same type, including lifetimes. + /// ```ignore + /// #![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 { From f542b068f24b4129ef99162f5bcf66e8290f9aac Mon Sep 17 00:00:00 2001 From: zachs18 <8355914+zachs18@users.noreply.github.com> Date: Fri, 2 Sep 2022 01:45:57 -0500 Subject: [PATCH 07/13] Apply suggestions from code review Fix spelling error. --- library/alloc/src/rc.rs | 2 +- library/alloc/src/sync.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 8ac1b5b488ad9..c1db035167b1e 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1122,7 +1122,7 @@ impl Rc { /// // 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); // Invliad UTF-8 in a str + /// println!("{}", &*x); // Invalid UTF-8 in a str /// ``` /// Other `Rc` pointers to the same allocation must be to the exact same type, including lifetimes. /// ```ignore diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index e4d7bfdaeed69..e32ce5a989172 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1661,7 +1661,7 @@ impl Arc { /// // 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); // Invliad UTF-8 in a str + /// println!("{}", &*x); // Invalid UTF-8 in a str /// ``` /// Other `Arc` pointers to the same allocation must be to the exact same type, including lifetimes. /// ```ignore From 734f7244723f579433b7defcd1fd1c2e66406737 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Fri, 2 Sep 2022 02:23:56 -0500 Subject: [PATCH 08/13] Change undefined-behavior doctests from ignore to no_run. --- library/alloc/src/rc.rs | 4 ++-- library/alloc/src/sync.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index c1db035167b1e..2f41ca689ba6c 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1111,7 +1111,7 @@ impl Rc { /// assert_eq!(*x, "foo"); /// ``` /// Other `Rc` pointers to the same allocation must be to the same type. - /// ```ignore + /// ```no_run /// #![feature(get_mut_unchecked)] /// /// use std::rc::Rc; @@ -1125,7 +1125,7 @@ impl Rc { /// println!("{}", &*x); // Invalid UTF-8 in a str /// ``` /// Other `Rc` pointers to the same allocation must be to the exact same type, including lifetimes. - /// ```ignore + /// ```no_run /// #![feature(get_mut_unchecked)] /// /// use std::rc::Rc; diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index e32ce5a989172..4ef3c528c4414 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1650,7 +1650,7 @@ impl Arc { /// assert_eq!(*x, "foo"); /// ``` /// Other `Arc` pointers to the same allocation must be to the same type. - /// ```ignore + /// ```no_run /// #![feature(get_mut_unchecked)] /// /// use std::sync::Arc; @@ -1664,7 +1664,7 @@ impl Arc { /// println!("{}", &*x); // Invalid UTF-8 in a str /// ``` /// Other `Arc` pointers to the same allocation must be to the exact same type, including lifetimes. - /// ```ignore + /// ```no_run /// #![feature(get_mut_unchecked)] /// /// use std::sync::Arc; From 2bb28c174bdc47ec5cb7e734ed925d1f37c4000b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 20 Nov 2022 09:58:29 +0100 Subject: [PATCH 09/13] avoid non-strict-provenance casts in libcore tests --- library/core/tests/ptr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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] From e19bc6eb8060395501c641c15f01d381a2818070 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 20 Nov 2022 10:27:38 +0100 Subject: [PATCH 10/13] move core::arch into separate file --- library/core/src/arch.rs | 30 ++++++++++++++++++++++++++++++ library/core/src/lib.rs | 32 +------------------------------- 2 files changed, 31 insertions(+), 31 deletions(-) create mode 100644 library/core/src/arch.rs 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..e1711d7f18bc4 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -392,38 +392,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. From 428ab59fb72e92358e3dad3e6a2817ffdfa7dec6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 20 Nov 2022 11:28:08 +0100 Subject: [PATCH 11/13] enable fuzzy_provenance_casts in libcore+tests --- library/core/src/lib.rs | 2 ++ library/core/src/ptr/const_ptr.rs | 1 + library/core/src/ptr/mod.rs | 2 ++ library/core/src/ptr/mut_ptr.rs | 1 + library/core/tests/lib.rs | 1 + 5 files changed, 7 insertions(+) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 848eccd7f2908..724adb7ad5dd7 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)] 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/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; From bebe5db5178a8444e4517e61f4ded9b612013fd3 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sun, 20 Nov 2022 17:28:34 +0200 Subject: [PATCH 12/13] replace unusual grammar --- library/alloc/src/collections/btree/map.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From 98993af828c15ae720506a1ce6b3845fc3d74b79 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Sun, 20 Nov 2022 11:43:23 -0500 Subject: [PATCH 13/13] add examples to chunks remainder methods. Also fixed some links to rchunk remainder methods. --- library/core/src/slice/iter.rs | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) 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")]