From 0b781b04cb1168095807f86e3b0dfadebf3a1ed2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 20 May 2022 15:55:55 +0200 Subject: [PATCH 01/10] Ensure we never consider the null pointer dereferencable --- compiler/rustc_const_eval/src/interpret/memory.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 33162a01ed201..5dcd209a8fb30 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -441,6 +441,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { msg, }) } + // Ensure we never consider the null pointer dereferencable. + if M::PointerTag::OFFSET_IS_ADDR { + assert_ne!(ptr.addr(), Size::ZERO); + } // Test align. Check this last; if both bounds and alignment are violated // we want the error to be about the bounds. if let Some(align) = align { From 1b4714f587e9e364714c9a4b771e6e7fe6697152 Mon Sep 17 00:00:00 2001 From: SparrowLii Date: Wed, 25 May 2022 21:09:04 +0800 Subject: [PATCH 02/10] simplify code of finding arg index --- compiler/rustc_typeck/src/collect/type_of.rs | 47 +++++++------------- 1 file changed, 16 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 4b6f80ce57a83..7e3fefe4502d2 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -161,38 +161,23 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< // We've encountered an `AnonConst` in some path, so we need to // figure out which generic parameter it corresponds to and return // the relevant type. - let filtered = path.segments.iter().find_map(|seg| { - seg.args? - .args + let Some((arg_index, segment)) = path.segments.iter().find_map(|seg| { + let args = seg.args?; + args.args + .iter() + .filter(|arg| arg.is_ty_or_const()) + .position(|arg| arg.id() == hir_id) + .map(|index| (index, seg)).or_else(|| args.bindings .iter() - .filter(|arg| arg.is_ty_or_const()) - .position(|arg| arg.id() == hir_id) - .map(|index| (index, seg)) - }); - - // FIXME(associated_const_generics): can we blend this with iteration above? - let (arg_index, segment) = match filtered { - None => { - let binding_filtered = path.segments.iter().find_map(|seg| { - seg.args? - .bindings - .iter() - .filter_map(TypeBinding::opt_const) - .position(|ct| ct.hir_id == hir_id) - .map(|idx| (idx, seg)) - }); - match binding_filtered { - Some(inner) => inner, - None => { - tcx.sess.delay_span_bug( - tcx.def_span(def_id), - "no arg matching AnonConst in path", - ); - return None; - } - } - } - Some(inner) => inner, + .filter_map(TypeBinding::opt_const) + .position(|ct| ct.hir_id == hir_id) + .map(|idx| (idx, seg))) + }) else { + tcx.sess.delay_span_bug( + tcx.def_span(def_id), + "no arg matching AnonConst in path", + ); + return None; }; // Try to use the segment resolution if it is valid, otherwise we From e4d48c38c50789b55d24f1cc188d6affe0b6207d Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 27 May 2022 16:36:55 -0700 Subject: [PATCH 03/10] rustdoc: add test case for email that looks like intra-doc link --- src/test/rustdoc/intra-doc/email-address.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/rustdoc/intra-doc/email-address.rs b/src/test/rustdoc/intra-doc/email-address.rs index ae74fbbc892bb..24161c3bb4858 100644 --- a/src/test/rustdoc/intra-doc/email-address.rs +++ b/src/test/rustdoc/intra-doc/email-address.rs @@ -1,8 +1,10 @@ -#![allow(rustdoc::broken_intra_doc_links)] +#![forbid(rustdoc::broken_intra_doc_links)] //! Email me at . //! Email me at . -//! Email me at (this warns but will still become a link). +//! Email me at . +//! Email me at . // @has email_address/index.html '//a[@href="mailto:hello@example.com"]' 'hello@example.com' // @has email_address/index.html '//a[@href="mailto:hello-world@example.com"]' 'hello-world@example.com' // @has email_address/index.html '//a[@href="mailto:hello@localhost"]' 'hello@localhost' +// @has email_address/index.html '//a[@href="mailto:prim@i32"]' 'prim@i32' From 5d86305ffddb24db85bf7ea29333f2c5358bbc92 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 27 May 2022 17:41:20 -0700 Subject: [PATCH 04/10] rustdoc: add test case for the implementors JS file placement --- .../auxiliary/implementors_inline.rs | 18 +++++++++++++ .../rustdoc/inline_cross/implementors-js.rs | 25 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 src/test/rustdoc/inline_cross/auxiliary/implementors_inline.rs create mode 100644 src/test/rustdoc/inline_cross/implementors-js.rs diff --git a/src/test/rustdoc/inline_cross/auxiliary/implementors_inline.rs b/src/test/rustdoc/inline_cross/auxiliary/implementors_inline.rs new file mode 100644 index 0000000000000..b003fb357d0f9 --- /dev/null +++ b/src/test/rustdoc/inline_cross/auxiliary/implementors_inline.rs @@ -0,0 +1,18 @@ +pub mod my_trait { + pub trait MyTrait { + fn my_fn(&self) -> Self; + } +} + +pub mod prelude { + #[doc(inline)] + pub use crate::my_trait::MyTrait; +} + +pub struct SomeStruct; + +impl my_trait::MyTrait for SomeStruct { + fn my_fn(&self) -> SomeStruct { + SomeStruct + } +} diff --git a/src/test/rustdoc/inline_cross/implementors-js.rs b/src/test/rustdoc/inline_cross/implementors-js.rs new file mode 100644 index 0000000000000..c79f05d8d3c9b --- /dev/null +++ b/src/test/rustdoc/inline_cross/implementors-js.rs @@ -0,0 +1,25 @@ +// aux-build:implementors_inline.rs +// build-aux-docs +// ignore-cross-compile + +extern crate implementors_inline; + +// @!has implementors/implementors_js/trait.MyTrait.js +// @has implementors/implementors_inline/my_trait/trait.MyTrait.js +// @!has implementors/implementors_inline/prelude/trait.MyTrait.js +// @has implementors_inline/my_trait/trait.MyTrait.html +// @has - '//script/@src' '../../implementors/implementors_inline/my_trait/trait.MyTrait.js' +// @has implementors_js/trait.MyTrait.html +// @has - '//script/@src' '../implementors/implementors_inline/my_trait/trait.MyTrait.js' +/// When re-exporting this trait, the HTML will be inlined, +/// but, vitally, the JavaScript will be located only at the +/// one canonical path. +pub use implementors_inline::prelude::MyTrait; + +pub struct OtherStruct; + +impl MyTrait for OtherStruct { + fn my_fn(&self) -> OtherStruct { + OtherStruct + } +} From 0484cfb6a91d1236809cfe4c536aa29b498e518d Mon Sep 17 00:00:00 2001 From: Isaac Chen <79286236+ijchen@users.noreply.github.com> Date: Sat, 28 May 2022 18:24:34 -0400 Subject: [PATCH 05/10] Corrected EBNF grammar for from_str Previously, the `Number` part of the EBNF grammar had an option for `'.' Digit*`, which would include the string "." (a single decimal point). This is not valid, and does not return an Ok as stated. The corrected version removes this, and still allows for the `'.' Digit+` case with the already existing `Digit* '.' Digit+` case. --- library/core/src/num/dec2flt/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/core/src/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs index df0e7431f1f5f..a888ced49b376 100644 --- a/library/core/src/num/dec2flt/mod.rs +++ b/library/core/src/num/dec2flt/mod.rs @@ -126,7 +126,6 @@ macro_rules! from_str_float_impl { /// ```txt /// Float ::= Sign? ( 'inf' | 'infinity' | 'nan' | Number ) /// Number ::= ( Digit+ | - /// '.' Digit* | /// Digit+ '.' Digit* | /// Digit* '.' Digit+ ) Exp? /// Exp ::= 'e' Sign? Digit+ From c00d9bf3249142915eabc49fc1d96dda1ee3fc1c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 30 May 2022 14:36:12 -0700 Subject: [PATCH 06/10] Fix comment in poly_project_and_unify_type --- .../src/traits/project.rs | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index a71621a4d52c0..641b915f37362 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -145,15 +145,28 @@ impl<'tcx> ProjectionCandidateSet<'tcx> { } } -/// Takes the place of a +/// States returned from `poly_project_and_unify_type`. Takes the place +/// of the old return type, which was: +/// ```ignore (not-rust) /// Result< /// Result>>, InProgress>, /// MismatchedProjectionTypes<'tcx>, /// > +/// ``` pub(super) enum ProjectAndUnifyResult<'tcx> { + /// The projection bound holds subject to the given obligations. If the + /// projection cannot be normalized because the required trait bound does + /// not hold, this is returned, with `obligations` being a predicate that + /// cannot be proven. Holds(Vec>), + /// The projection cannot be normalized due to ambiguity. Resolving some + /// inference variables in the projection may fix this. FailedNormalization, + /// The project cannot be normalized because `poly_project_and_unify_type` + /// is called recursively while normalizing the same projection. Recursive, + // the projection can be normalized, but is not equal to the expected type. + // Returns the type error that arose from the mismatch. MismatchedProjectionTypes(MismatchedProjectionTypes<'tcx>), } @@ -163,19 +176,6 @@ pub(super) enum ProjectAndUnifyResult<'tcx> { /// ``` /// If successful, this may result in additional obligations. Also returns /// the projection cache key used to track these additional obligations. -/// -/// ## Returns -/// -/// - `Err(_)`: the projection can be normalized, but is not equal to the -/// expected type. -/// - `Ok(Err(InProgress))`: this is called recursively while normalizing -/// the same projection. -/// - `Ok(Ok(None))`: The projection cannot be normalized due to ambiguity -/// (resolving some inference variables in the projection may fix this). -/// - `Ok(Ok(Some(obligations)))`: The projection bound holds subject to -/// the given obligations. If the projection cannot be normalized because -/// the required trait bound doesn't hold this returned with `obligations` -/// being a predicate that cannot be proven. #[instrument(level = "debug", skip(selcx))] pub(super) fn poly_project_and_unify_type<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, From 0a6001b5a03481a323048ef387e31033080ee18f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20BRANSTETT?= Date: Sat, 5 Mar 2022 18:32:33 +0100 Subject: [PATCH 07/10] Expose get_many_mut and get_many_unchecked_mut to HashMap --- library/std/src/collections/hash/map.rs | 113 ++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 969f5dde4f05d..a49dd0102bb7e 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -895,6 +895,119 @@ where self.base.get_key_value(k) } + /// Attempts to get mutable references to `N` values in the map at once. + /// + /// Returns an array of length `N` with the results of each query. For soundness, at most one + /// mutable reference will be returned to any value. `None` will be returned if any of the + /// keys are duplicates or missing. + /// + /// # Examples + /// + /// ``` + /// #![feature(map_many_mut)] + /// use std::collections::HashMap; + /// + /// let mut libraries = HashMap::new(); + /// libraries.insert("Bodleian Library".to_string(), 1602); + /// libraries.insert("Athenæum".to_string(), 1807); + /// libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691); + /// libraries.insert("Library of Congress".to_string(), 1800); + /// + /// let got = libraries.get_many_mut([ + /// "Athenæum", + /// "Library of Congress", + /// ]); + /// assert_eq!( + /// got, + /// Some([ + /// &mut 1807, + /// &mut 1800, + /// ]), + /// ); + /// + /// // Missing keys result in None + /// let got = libraries.get_many_mut([ + /// "Athenæum", + /// "New York Public Library", + /// ]); + /// assert_eq!(got, None); + /// + /// // Duplicate keys result in None + /// let got = libraries.get_many_mut([ + /// "Athenæum", + /// "Athenæum", + /// ]); + /// assert_eq!(got, None); + /// ``` + #[inline] + #[unstable(feature = "map_many_mut", issue = "97601")] + pub fn get_many_mut(&mut self, ks: [&Q; N]) -> Option<[&'_ mut V; N]> + where + K: Borrow, + Q: Hash + Eq, + { + self.base.get_many_mut(ks) + } + + /// Attempts to get mutable references to `N` values in the map at once, without validating that + /// the values are unique. + /// + /// Returns an array of length `N` with the results of each query. `None` will be returned if + /// any of the keys are missing. + /// + /// For a safe alternative see [`get_many_mut`](Self::get_many_mut). + /// + /// # Safety + /// + /// Calling this method with overlapping keys is *[undefined behavior]* even if the resulting + /// references are not used. + /// + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + /// + /// # Examples + /// + /// ``` + /// #![feature(map_many_mut)] + /// use std::collections::HashMap; + /// + /// let mut libraries = HashMap::new(); + /// libraries.insert("Bodleian Library".to_string(), 1602); + /// libraries.insert("Athenæum".to_string(), 1807); + /// libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691); + /// libraries.insert("Library of Congress".to_string(), 1800); + /// + /// let got = libraries.get_many_mut([ + /// "Athenæum", + /// "Library of Congress", + /// ]); + /// assert_eq!( + /// got, + /// Some([ + /// &mut 1807, + /// &mut 1800, + /// ]), + /// ); + /// + /// // Missing keys result in None + /// let got = libraries.get_many_mut([ + /// "Athenæum", + /// "New York Public Library", + /// ]); + /// assert_eq!(got, None); + /// ``` + #[inline] + #[unstable(feature = "map_many_mut", issue = "97601")] + pub unsafe fn get_many_unchecked_mut( + &mut self, + ks: [&Q; N], + ) -> Option<[&'_ mut V; N]> + where + K: Borrow, + Q: Hash + Eq, + { + self.base.get_many_unchecked_mut(ks) + } + /// Returns `true` if the map contains a value for the specified key. /// /// The key may be any borrowed form of the map's key type, but From b02146a370e8e07186d4bd2c264699300ca925df Mon Sep 17 00:00:00 2001 From: Ariel Davis Date: Tue, 31 May 2022 22:08:14 -0700 Subject: [PATCH 08/10] Tweak insert docs --- compiler/rustc_data_structures/src/sso/set.rs | 5 +++-- library/alloc/src/collections/btree/set.rs | 10 +++++++--- library/std/src/collections/hash/set.rs | 5 +++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_data_structures/src/sso/set.rs b/compiler/rustc_data_structures/src/sso/set.rs index f71522d37148a..4fda3adb7b878 100644 --- a/compiler/rustc_data_structures/src/sso/set.rs +++ b/compiler/rustc_data_structures/src/sso/set.rs @@ -126,9 +126,10 @@ impl SsoHashSet { /// Adds a value to the set. /// - /// If the set did not have this value present, `true` is returned. + /// Returns whether the value was newly inserted. That is: /// - /// If the set did have this value present, `false` is returned. + /// - If the set did not previously contain this value, `true` is returned. + /// - If the set already contained this value, `false` is returned. #[inline] pub fn insert(&mut self, elem: T) -> bool { self.map.insert(elem, ()).is_none() diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 20ef834eaeef3..caa629cf4e65e 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -770,10 +770,14 @@ impl BTreeSet { /// Adds a value to the set. /// - /// If the set did not have an equal element present, `true` is returned. + /// Returns whether the value was newly inserted. That is: /// - /// If the set did have an equal element present, `false` is returned, and - /// the entry is not updated. See the [module-level documentation] for more. + /// - If the set did not previously contain an equal value, `true` is + /// returned. + /// - If the set already contained an equal value, `false` is returned, and + /// the entry is not updated. + /// + /// See the [module-level documentation] for more. /// /// [module-level documentation]: index.html#insert-and-complex-keys /// diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index da0572047eca8..19428fe9a2339 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -858,9 +858,10 @@ where /// Adds a value to the set. /// - /// If the set did not have this value present, `true` is returned. + /// Returns whether the value was newly inserted. That is: /// - /// If the set did have this value present, `false` is returned. + /// - If the set did not previously contain this value, `true` is returned. + /// - If the set already contained this value, `false` is returned. /// /// # Examples /// From 8d007aa06d01353f7154d5dc681ba5db7c52514f Mon Sep 17 00:00:00 2001 From: Takayuki Maeda <41065217+TaKO8Ki@users.noreply.github.com> Date: Wed, 1 Jun 2022 17:06:07 +0900 Subject: [PATCH 09/10] remove an unnecessary `Option` --- compiler/rustc_trait_selection/src/traits/wf.rs | 13 ++++++++++--- compiler/rustc_typeck/src/check/wfcheck.rs | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 0379b16334cdc..2ce2a44d3db76 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -81,10 +81,17 @@ pub fn trait_obligations<'a, 'tcx>( body_id: hir::HirId, trait_ref: &ty::TraitRef<'tcx>, span: Span, - item: Option<&'tcx hir::Item<'tcx>>, + item: &'tcx hir::Item<'tcx>, ) -> Vec> { - let mut wf = - WfPredicates { infcx, param_env, body_id, span, out: vec![], recursion_depth: 0, item }; + let mut wf = WfPredicates { + infcx, + param_env, + body_id, + span, + out: vec![], + recursion_depth: 0, + item: Some(item), + }; wf.compute_trait_ref(trait_ref, Elaborate::All); debug!(obligations = ?wf.out); wf.normalize() diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index a6c7573b787c6..20ef97c085f18 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -1228,7 +1228,7 @@ fn check_impl<'tcx>( fcx.body_id, &trait_ref, ast_trait_ref.path.span, - Some(item), + item, ); debug!(?obligations); for obligation in obligations { From ea50d773e3f75855ca8a40ca72ad8f8c67153474 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Tue, 31 May 2022 20:35:41 +0900 Subject: [PATCH 10/10] Add regression test for #71546 --- src/test/ui/borrowck/issue-71546.rs | 19 +++++++++++++++++++ src/test/ui/borrowck/issue-71546.stderr | 20 ++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 src/test/ui/borrowck/issue-71546.rs create mode 100644 src/test/ui/borrowck/issue-71546.stderr diff --git a/src/test/ui/borrowck/issue-71546.rs b/src/test/ui/borrowck/issue-71546.rs new file mode 100644 index 0000000000000..943f7f86e5524 --- /dev/null +++ b/src/test/ui/borrowck/issue-71546.rs @@ -0,0 +1,19 @@ +// Regression test for #71546. + +// ignore-compare-mode-nll +// NLL stderr is different from the original one. + +pub fn serialize_as_csv(value: &V) -> Result +where + V: 'static, + for<'a> &'a V: IntoIterator, + for<'a> <&'a V as IntoIterator>::Item: ToString + 'static, +{ + let csv_str: String = value //~ ERROR: the associated type `<&'a V as IntoIterator>::Item` may not live long enough + .into_iter() + .map(|elem| elem.to_string()) + .collect::(); + Ok(csv_str) +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-71546.stderr b/src/test/ui/borrowck/issue-71546.stderr new file mode 100644 index 0000000000000..d479ca8f1d8b9 --- /dev/null +++ b/src/test/ui/borrowck/issue-71546.stderr @@ -0,0 +1,20 @@ +error[E0310]: the associated type `<&'a V as IntoIterator>::Item` may not live long enough + --> $DIR/issue-71546.rs:12:27 + | +LL | let csv_str: String = value + | ___________________________^ +LL | | .into_iter() +LL | | .map(|elem| elem.to_string()) + | |_____________________________________^ + | + = help: consider adding an explicit lifetime bound `<&'a V as IntoIterator>::Item: 'static`... + = note: ...so that the type `<&'a V as IntoIterator>::Item` will meet its required lifetime bounds... +note: ...that is required by this bound + --> $DIR/issue-71546.rs:10:55 + | +LL | for<'a> <&'a V as IntoIterator>::Item: ToString + 'static, + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`.