From 90722811c8818b1ce4c7819dac41f22837fa98c6 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 1 Apr 2022 18:51:57 -0700 Subject: [PATCH 01/20] Deprecate the `ptr_to_from_bits` feature The strict provenance APIs are a better version of these, and things like `.addr()` work for the "that cast looks sketchy" case even if the full strict provenance stuff never happens. So I think it's fine to move away from these, and encourage the others instead. --- library/core/src/ptr/const_ptr.rs | 5 +++++ library/core/src/ptr/mut_ptr.rs | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index af64fbc8e9e..e460a7f3b1e 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -119,6 +119,7 @@ pub const fn cast_mut(self) -> *mut T { /// assert_eq!(p1.to_bits() - p0.to_bits(), 4); /// ``` #[unstable(feature = "ptr_to_from_bits", issue = "91126")] + #[rustc_deprecated(since = "1.62", reason = "replaced by the `addr` method")] pub fn to_bits(self) -> usize where T: Sized, @@ -140,6 +141,10 @@ pub fn to_bits(self) -> usize /// assert_eq!(<*const u8>::from_bits(1), dangling); /// ``` #[unstable(feature = "ptr_to_from_bits", issue = "91126")] + #[rustc_deprecated( + since = "1.62", + reason = "replaced by the `with_addr` method or the `ptr::invalid` function" + )] #[allow(fuzzy_provenance_casts)] // this is an unstable and semi-deprecated cast function pub fn from_bits(bits: usize) -> Self where diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index d6872ba1c20..351012e6ffc 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -125,6 +125,7 @@ pub const fn cast_const(self) -> *const T { /// assert_eq!(p1.to_bits() - p0.to_bits(), 4); /// ``` #[unstable(feature = "ptr_to_from_bits", issue = "91126")] + #[rustc_deprecated(since = "1.62", reason = "replaced by the `addr` method")] pub fn to_bits(self) -> usize where T: Sized, @@ -146,6 +147,10 @@ pub fn to_bits(self) -> usize /// assert_eq!(<*mut u8>::from_bits(1), dangling); /// ``` #[unstable(feature = "ptr_to_from_bits", issue = "91126")] + #[rustc_deprecated( + since = "1.62", + reason = "replaced by the `with_addr` method or the `ptr::invalid_mut` function" + )] #[allow(fuzzy_provenance_casts)] // this is an unstable and semi-deprecated cast function pub fn from_bits(bits: usize) -> Self where From 4d37d1f4226bd92bf6c129977357afd50993cf0a Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 3 Apr 2022 13:19:30 -0700 Subject: [PATCH 02/20] Refer to the `exposed` versions of the methods instead Changing to those doesn't introduce any new unsoundness over the existing ones, so they're the better "if you won't want to think about it" replacement. But also mention the strict provenance APIs, as that's what we'd rather they use instead. --- library/core/src/ptr/const_ptr.rs | 9 +++++++-- library/core/src/ptr/mut_ptr.rs | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index e460a7f3b1e..2c371f635ab 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -119,7 +119,11 @@ pub const fn cast_mut(self) -> *mut T { /// assert_eq!(p1.to_bits() - p0.to_bits(), 4); /// ``` #[unstable(feature = "ptr_to_from_bits", issue = "91126")] - #[rustc_deprecated(since = "1.62", reason = "replaced by the `addr` method")] + #[rustc_deprecated( + since = "1.62", + reason = "replaced by the `exposed_addr` method, or update your code \ + to follow the strict provenance rules using its APIs" + )] pub fn to_bits(self) -> usize where T: Sized, @@ -143,7 +147,8 @@ pub fn to_bits(self) -> usize #[unstable(feature = "ptr_to_from_bits", issue = "91126")] #[rustc_deprecated( since = "1.62", - reason = "replaced by the `with_addr` method or the `ptr::invalid` function" + reason = "replaced by the `ptr::from_exposed_addr` function, or update \ + your code to follow the strict provenance rules using its APIs" )] #[allow(fuzzy_provenance_casts)] // this is an unstable and semi-deprecated cast function pub fn from_bits(bits: usize) -> Self diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 351012e6ffc..79682531562 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -125,7 +125,11 @@ pub const fn cast_const(self) -> *const T { /// assert_eq!(p1.to_bits() - p0.to_bits(), 4); /// ``` #[unstable(feature = "ptr_to_from_bits", issue = "91126")] - #[rustc_deprecated(since = "1.62", reason = "replaced by the `addr` method")] + #[rustc_deprecated( + since = "1.62", + reason = "replaced by the `exposed_addr` method, or update your code \ + to follow the strict provenance rules using its APIs" + )] pub fn to_bits(self) -> usize where T: Sized, @@ -149,7 +153,8 @@ pub fn to_bits(self) -> usize #[unstable(feature = "ptr_to_from_bits", issue = "91126")] #[rustc_deprecated( since = "1.62", - reason = "replaced by the `with_addr` method or the `ptr::invalid_mut` function" + reason = "replaced by the `ptr::from_exposed_addr_mut` function, or \ + update your code to follow the strict provenance rules using its APIs" )] #[allow(fuzzy_provenance_casts)] // this is an unstable and semi-deprecated cast function pub fn from_bits(bits: usize) -> Self From f613bd6d3af8a28f9ea8a499b4524decaf67f198 Mon Sep 17 00:00:00 2001 From: Stefan Schindler Date: Sat, 10 Sep 2022 16:24:05 +0200 Subject: [PATCH 03/20] Make the one-liner more descriptive --- library/alloc/src/boxed.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 65e323c9e00..00c922f3ae9 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -1,4 +1,4 @@ -//! The `Box` type for heap allocation. +//! The pointer type for heap allocation for an owned value of type `T`. //! //! [`Box`], casually referred to as a 'box', provides the simplest form of //! heap allocation in Rust. Boxes provide ownership for this allocation, and @@ -187,7 +187,7 @@ mod thin; -/// A pointer type for heap allocation. +/// A pointer type for heap allocation for an owned value of type `T`. /// /// See the [module-level documentation](../../std/boxed/index.html) for more. #[lang = "owned_box"] From df5d035f5199eab85dac327cbbd30a3ddfe29abd Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Tue, 18 Oct 2022 14:11:02 +0000 Subject: [PATCH 04/20] mark sys_common::once::generic::Once::new const-stable --- library/std/src/sys_common/once/generic.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/src/sys_common/once/generic.rs b/library/std/src/sys_common/once/generic.rs index acf5f247164..d953a674592 100644 --- a/library/std/src/sys_common/once/generic.rs +++ b/library/std/src/sys_common/once/generic.rs @@ -107,6 +107,7 @@ struct WaiterQueue<'a> { impl Once { #[inline] + #[rustc_const_stable(feature = "const_once_new", since = "1.32.0")] pub const fn new() -> Once { Once { state_and_queue: AtomicPtr::new(ptr::invalid_mut(INCOMPLETE)) } } From cdb6907893da1d025eba2d8cd396db4e84bca98c Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Thu, 17 Nov 2022 22:11:39 -0500 Subject: [PATCH 05/20] Update compiler_builtins to 0.1.84 --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index acffaaff4d3..73256018078 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -792,9 +792,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.82" +version = "0.1.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18cd7635fea7bb481ea543b392789844c1ad581299da70184c7175ce3af76603" +checksum = "989b2c1ca6e90ad06fdc69d1d1862fa28d27a977be6d92ae2fa762cf61fe0b10" dependencies = [ "cc", "rustc-std-workspace-core", From eafe61d6bd9d983535a90b29ef5497b0a6e42019 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 20 Nov 2022 00:03:10 +0000 Subject: [PATCH 06/20] dist-various-2: Use clang for the UEFI targets This fixes an issue where the C and asm sources built by compiler_builtins were being compiled as ELF objects instead of PE objects. This wasn't noticed before because it doesn't cause compiler_builtins or rustc to fail to build. You only see a failure when a program is built that references one of the symbols in an ELF object. Compiling with clang fixes this because the `cc` crate converts the UEFI targets into Windows targets that clang understands, causing it to produce PE objects. Note that this requires compiler_builtins >= 0.1.84. Fixes https://github.com/rust-lang/rust/issues/104326 --- src/ci/docker/host-x86_64/dist-various-2/Dockerfile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index e1adabaac9b..93ef7dfcbf5 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -61,6 +61,12 @@ ENV \ AR_i686_unknown_freebsd=i686-unknown-freebsd12-ar \ CC_i686_unknown_freebsd=i686-unknown-freebsd12-clang \ CXX_i686_unknown_freebsd=i686-unknown-freebsd12-clang++ \ + CC_aarch64_unknown_uefi=clang-11 \ + CXX_aarch64_unknown_uefi=clang++-11 \ + CC_i686_unknown_uefi=clang-11 \ + CXX_i686_unknown_uefi=clang++-11 \ + CC_x86_64_unknown_uefi=clang-11 \ + CXX_x86_64_unknown_uefi=clang++-11 \ CC=gcc-8 \ CXX=g++-8 From a1e5fea13610ba651b6eec034b85377ead87eb7c Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 20 Nov 2022 13:06:44 +0100 Subject: [PATCH 07/20] Move macro_rules diagnostics to diagnostics module --- compiler/rustc_expand/src/expand.rs | 2 +- compiler/rustc_expand/src/mbe.rs | 1 + compiler/rustc_expand/src/mbe/diagnostics.rs | 257 +++++++++++++++++++ compiler/rustc_expand/src/mbe/macro_rules.rs | 245 +----------------- 4 files changed, 268 insertions(+), 237 deletions(-) create mode 100644 compiler/rustc_expand/src/mbe/diagnostics.rs diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 3d37e2c6568..f7f3075e19b 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1,7 +1,7 @@ use crate::base::*; use crate::config::StripUnconfigured; use crate::hygiene::SyntaxContext; -use crate::mbe::macro_rules::annotate_err_with_kind; +use crate::mbe::diagnostics::annotate_err_with_kind; use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod}; use crate::placeholders::{placeholder, PlaceholderExpander}; diff --git a/compiler/rustc_expand/src/mbe.rs b/compiler/rustc_expand/src/mbe.rs index 63bafd7b046..a43b2a00188 100644 --- a/compiler/rustc_expand/src/mbe.rs +++ b/compiler/rustc_expand/src/mbe.rs @@ -3,6 +3,7 @@ //! why we call this module `mbe`. For external documentation, prefer the //! official terminology: "declarative macros". +pub(crate) mod diagnostics; pub(crate) mod macro_check; pub(crate) mod macro_parser; pub(crate) mod macro_rules; diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs new file mode 100644 index 00000000000..197f056917f --- /dev/null +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -0,0 +1,257 @@ +use std::borrow::Cow; + +use crate::base::{DummyResult, ExtCtxt, MacResult}; +use crate::expand::{parse_ast_fragment, AstFragmentKind}; +use crate::mbe::{ + macro_parser::{MatcherLoc, NamedParseResult, ParseResult::*, TtParser}, + macro_rules::{try_match_macro, Tracker}, +}; +use rustc_ast::token::{self, Token}; +use rustc_ast::tokenstream::TokenStream; +use rustc_ast_pretty::pprust; +use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage}; +use rustc_parse::parser::{Parser, Recovery}; +use rustc_span::source_map::SourceMap; +use rustc_span::symbol::Ident; +use rustc_span::Span; + +use super::macro_rules::{parser_from_cx, NoopTracker}; + +pub(super) fn failed_to_match_macro<'cx>( + cx: &'cx mut ExtCtxt<'_>, + sp: Span, + def_span: Span, + name: Ident, + arg: TokenStream, + lhses: &[Vec], +) -> Box { + let sess = &cx.sess.parse_sess; + + // An error occurred, try the expansion again, tracking the expansion closely for better diagnostics. + let mut tracker = CollectTrackerAndEmitter::new(cx, sp); + + let try_success_result = try_match_macro(sess, name, &arg, lhses, &mut tracker); + + if try_success_result.is_ok() { + // Nonterminal parser recovery might turn failed matches into successful ones, + // but for that it must have emitted an error already + tracker.cx.sess.delay_span_bug(sp, "Macro matching returned a success on the second try"); + } + + if let Some(result) = tracker.result { + // An irrecoverable error occurred and has been emitted. + return result; + } + + let Some((token, label, remaining_matcher)) = tracker.best_failure else { + return DummyResult::any(sp); + }; + + let span = token.span.substitute_dummy(sp); + + let mut err = cx.struct_span_err(span, &parse_failure_msg(&token)); + err.span_label(span, label); + if !def_span.is_dummy() && !cx.source_map().is_imported(def_span) { + err.span_label(cx.source_map().guess_head_span(def_span), "when calling this macro"); + } + + annotate_doc_comment(&mut err, sess.source_map(), span); + + if let Some(span) = remaining_matcher.span() { + err.span_note(span, format!("while trying to match {remaining_matcher}")); + } else { + err.note(format!("while trying to match {remaining_matcher}")); + } + + // Check whether there's a missing comma in this macro call, like `println!("{}" a);` + if let Some((arg, comma_span)) = arg.add_comma() { + for lhs in lhses { + let parser = parser_from_cx(sess, arg.clone(), Recovery::Allowed); + let mut tt_parser = TtParser::new(name); + + if let Success(_) = + tt_parser.parse_tt(&mut Cow::Borrowed(&parser), lhs, &mut NoopTracker) + { + if comma_span.is_dummy() { + err.note("you might be missing a comma"); + } else { + err.span_suggestion_short( + comma_span, + "missing comma here", + ", ", + Applicability::MachineApplicable, + ); + } + } + } + } + err.emit(); + cx.trace_macros_diag(); + DummyResult::any(sp) +} + +/// The tracker used for the slow error path that collects useful info for diagnostics. +struct CollectTrackerAndEmitter<'a, 'cx, 'matcher> { + cx: &'a mut ExtCtxt<'cx>, + remaining_matcher: Option<&'matcher MatcherLoc>, + /// Which arm's failure should we report? (the one furthest along) + best_failure: Option<(Token, &'static str, MatcherLoc)>, + root_span: Span, + result: Option>, +} + +impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, 'matcher> { + fn before_match_loc(&mut self, parser: &TtParser, matcher: &'matcher MatcherLoc) { + if self.remaining_matcher.is_none() + || (parser.has_no_remaining_items_for_step() && *matcher != MatcherLoc::Eof) + { + self.remaining_matcher = Some(matcher); + } + } + + fn after_arm(&mut self, result: &NamedParseResult) { + match result { + Success(_) => { + // Nonterminal parser recovery might turn failed matches into successful ones, + // but for that it must have emitted an error already + self.cx.sess.delay_span_bug( + self.root_span, + "should not collect detailed info for successful macro match", + ); + } + Failure(token, msg) => match self.best_failure { + Some((ref best_token, _, _)) if best_token.span.lo() >= token.span.lo() => {} + _ => { + self.best_failure = Some(( + token.clone(), + msg, + self.remaining_matcher + .expect("must have collected matcher already") + .clone(), + )) + } + }, + Error(err_sp, msg) => { + let span = err_sp.substitute_dummy(self.root_span); + self.cx.struct_span_err(span, msg).emit(); + self.result = Some(DummyResult::any(span)); + } + ErrorReported(_) => self.result = Some(DummyResult::any(self.root_span)), + } + } + + fn description() -> &'static str { + "detailed" + } + + fn recovery() -> Recovery { + Recovery::Allowed + } +} + +impl<'a, 'cx> CollectTrackerAndEmitter<'a, 'cx, '_> { + fn new(cx: &'a mut ExtCtxt<'cx>, root_span: Span) -> Self { + Self { cx, remaining_matcher: None, best_failure: None, root_span, result: None } + } +} + +pub(super) fn emit_frag_parse_err( + mut e: DiagnosticBuilder<'_, rustc_errors::ErrorGuaranteed>, + parser: &Parser<'_>, + orig_parser: &mut Parser<'_>, + site_span: Span, + arm_span: Span, + kind: AstFragmentKind, +) { + // FIXME(davidtwco): avoid depending on the error message text + if parser.token == token::Eof + && let DiagnosticMessage::Str(message) = &e.message[0].0 + && message.ends_with(", found ``") + { + let msg = &e.message[0]; + e.message[0] = ( + DiagnosticMessage::Str(format!( + "macro expansion ends with an incomplete expression: {}", + message.replace(", found ``", ""), + )), + msg.1, + ); + if !e.span.is_dummy() { + // early end of macro arm (#52866) + e.replace_span_with(parser.token.span.shrink_to_hi()); + } + } + if e.span.is_dummy() { + // Get around lack of span in error (#30128) + e.replace_span_with(site_span); + if !parser.sess.source_map().is_imported(arm_span) { + e.span_label(arm_span, "in this macro arm"); + } + } else if parser.sess.source_map().is_imported(parser.token.span) { + e.span_label(site_span, "in this macro invocation"); + } + match kind { + // Try a statement if an expression is wanted but failed and suggest adding `;` to call. + AstFragmentKind::Expr => match parse_ast_fragment(orig_parser, AstFragmentKind::Stmts) { + Err(err) => err.cancel(), + Ok(_) => { + e.note( + "the macro call doesn't expand to an expression, but it can expand to a statement", + ); + e.span_suggestion_verbose( + site_span.shrink_to_hi(), + "add `;` to interpret the expansion as a statement", + ";", + Applicability::MaybeIncorrect, + ); + } + }, + _ => annotate_err_with_kind(&mut e, kind, site_span), + }; + e.emit(); +} + +pub(crate) fn annotate_err_with_kind(err: &mut Diagnostic, kind: AstFragmentKind, span: Span) { + match kind { + AstFragmentKind::Ty => { + err.span_label(span, "this macro call doesn't expand to a type"); + } + AstFragmentKind::Pat => { + err.span_label(span, "this macro call doesn't expand to a pattern"); + } + _ => {} + }; +} + +#[derive(Subdiagnostic)] +enum ExplainDocComment { + #[label(expand_explain_doc_comment_inner)] + Inner { + #[primary_span] + span: Span, + }, + #[label(expand_explain_doc_comment_outer)] + Outer { + #[primary_span] + span: Span, + }, +} + +pub(super) fn annotate_doc_comment(err: &mut Diagnostic, sm: &SourceMap, span: Span) { + if let Ok(src) = sm.span_to_snippet(span) { + if src.starts_with("///") || src.starts_with("/**") { + err.subdiagnostic(ExplainDocComment::Outer { span }); + } else if src.starts_with("//!") || src.starts_with("/*!") { + err.subdiagnostic(ExplainDocComment::Inner { span }); + } + } +} + +/// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For +/// other tokens, this is "unexpected token...". +pub(super) fn parse_failure_msg(tok: &Token) -> String { + match tok.kind { + token::Eof => "unexpected end of macro invocation".to_string(), + _ => format!("no rules expected the token `{}`", pprust::token_to_string(tok),), + } +} diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 6c7063ca28b..fc33974dd17 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -2,6 +2,7 @@ use crate::base::{SyntaxExtension, SyntaxExtensionKind}; use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstFragmentKind}; use crate::mbe; +use crate::mbe::diagnostics::{annotate_doc_comment, parse_failure_msg}; use crate::mbe::macro_check; use crate::mbe::macro_parser::{Error, ErrorReported, Failure, Success, TtParser}; use crate::mbe::macro_parser::{MatchedSeq, MatchedTokenTree, MatcherLoc}; @@ -14,9 +15,7 @@ use rustc_ast_pretty::pprust; use rustc_attr::{self as attr, TransparencyError}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; -use rustc_errors::{ - Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, -}; +use rustc_errors::{Applicability, ErrorGuaranteed}; use rustc_feature::Features; use rustc_lint_defs::builtin::{ RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, @@ -27,7 +26,6 @@ use rustc_session::Session; use rustc_span::edition::Edition; use rustc_span::hygiene::Transparency; -use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, sym, Ident, MacroRulesNormalizedIdent}; use rustc_span::Span; @@ -35,6 +33,7 @@ use std::collections::hash_map::Entry; use std::{mem, slice}; +use super::diagnostics; use super::macro_parser::{NamedMatches, NamedParseResult}; pub(crate) struct ParserAnyMacro<'a> { @@ -51,74 +50,6 @@ pub(crate) struct ParserAnyMacro<'a> { is_local: bool, } -pub(crate) fn annotate_err_with_kind(err: &mut Diagnostic, kind: AstFragmentKind, span: Span) { - match kind { - AstFragmentKind::Ty => { - err.span_label(span, "this macro call doesn't expand to a type"); - } - AstFragmentKind::Pat => { - err.span_label(span, "this macro call doesn't expand to a pattern"); - } - _ => {} - }; -} - -fn emit_frag_parse_err( - mut e: DiagnosticBuilder<'_, rustc_errors::ErrorGuaranteed>, - parser: &Parser<'_>, - orig_parser: &mut Parser<'_>, - site_span: Span, - arm_span: Span, - kind: AstFragmentKind, -) { - // FIXME(davidtwco): avoid depending on the error message text - if parser.token == token::Eof - && let DiagnosticMessage::Str(message) = &e.message[0].0 - && message.ends_with(", found ``") - { - let msg = &e.message[0]; - e.message[0] = ( - DiagnosticMessage::Str(format!( - "macro expansion ends with an incomplete expression: {}", - message.replace(", found ``", ""), - )), - msg.1, - ); - if !e.span.is_dummy() { - // early end of macro arm (#52866) - e.replace_span_with(parser.token.span.shrink_to_hi()); - } - } - if e.span.is_dummy() { - // Get around lack of span in error (#30128) - e.replace_span_with(site_span); - if !parser.sess.source_map().is_imported(arm_span) { - e.span_label(arm_span, "in this macro arm"); - } - } else if parser.sess.source_map().is_imported(parser.token.span) { - e.span_label(site_span, "in this macro invocation"); - } - match kind { - // Try a statement if an expression is wanted but failed and suggest adding `;` to call. - AstFragmentKind::Expr => match parse_ast_fragment(orig_parser, AstFragmentKind::Stmts) { - Err(err) => err.cancel(), - Ok(_) => { - e.note( - "the macro call doesn't expand to an expression, but it can expand to a statement", - ); - e.span_suggestion_verbose( - site_span.shrink_to_hi(), - "add `;` to interpret the expansion as a statement", - ";", - Applicability::MaybeIncorrect, - ); - } - }, - _ => annotate_err_with_kind(&mut e, kind, site_span), - }; - e.emit(); -} - impl<'a> ParserAnyMacro<'a> { pub(crate) fn make(mut self: Box>, kind: AstFragmentKind) -> AstFragment { let ParserAnyMacro { @@ -134,7 +65,7 @@ pub(crate) fn make(mut self: Box>, kind: AstFragmentKind) -> let fragment = match parse_ast_fragment(parser, kind) { Ok(f) => f, Err(err) => { - emit_frag_parse_err(err, parser, snapshot, site_span, arm_span, kind); + diagnostics::emit_frag_parse_err(err, parser, snapshot, site_span, arm_span, kind); return kind.dummy(site_span); } }; @@ -224,7 +155,7 @@ pub(super) trait Tracker<'matcher> { } /// A noop tracker that is used in the hot path of the expansion, has zero overhead thanks to monomorphization. -struct NoopTracker; +pub(super) struct NoopTracker; impl<'matcher> Tracker<'matcher> for NoopTracker { fn before_match_loc(&mut self, _: &TtParser, _: &'matcher MatcherLoc) {} @@ -331,135 +262,10 @@ fn expand_macro<'cx>( } } - // An error occurred, try the expansion again, tracking the expansion closely for better diagnostics. - let mut tracker = CollectTrackerAndEmitter::new(cx, sp); - - let try_success_result = try_match_macro(sess, name, &arg, lhses, &mut tracker); - - if try_success_result.is_ok() { - // Nonterminal parser recovery might turn failed matches into successful ones, - // but for that it must have emitted an error already - tracker.cx.sess.delay_span_bug(sp, "Macro matching returned a success on the second try"); - } - - if let Some(result) = tracker.result { - // An irrecoverable error occurred and has been emitted. - return result; - } - - let Some((token, label, remaining_matcher)) = tracker.best_failure else { - return DummyResult::any(sp); - }; - - let span = token.span.substitute_dummy(sp); - - let mut err = cx.struct_span_err(span, &parse_failure_msg(&token)); - err.span_label(span, label); - if !def_span.is_dummy() && !cx.source_map().is_imported(def_span) { - err.span_label(cx.source_map().guess_head_span(def_span), "when calling this macro"); - } - - annotate_doc_comment(&mut err, sess.source_map(), span); - - if let Some(span) = remaining_matcher.span() { - err.span_note(span, format!("while trying to match {remaining_matcher}")); - } else { - err.note(format!("while trying to match {remaining_matcher}")); - } - - // Check whether there's a missing comma in this macro call, like `println!("{}" a);` - if let Some((arg, comma_span)) = arg.add_comma() { - for lhs in lhses { - let parser = parser_from_cx(sess, arg.clone(), Recovery::Allowed); - let mut tt_parser = TtParser::new(name); - - if let Success(_) = - tt_parser.parse_tt(&mut Cow::Borrowed(&parser), lhs, &mut NoopTracker) - { - if comma_span.is_dummy() { - err.note("you might be missing a comma"); - } else { - err.span_suggestion_short( - comma_span, - "missing comma here", - ", ", - Applicability::MachineApplicable, - ); - } - } - } - } - err.emit(); - cx.trace_macros_diag(); - DummyResult::any(sp) + diagnostics::failed_to_match_macro(cx, sp, def_span, name, arg, lhses) } -/// The tracker used for the slow error path that collects useful info for diagnostics. -struct CollectTrackerAndEmitter<'a, 'cx, 'matcher> { - cx: &'a mut ExtCtxt<'cx>, - remaining_matcher: Option<&'matcher MatcherLoc>, - /// Which arm's failure should we report? (the one furthest along) - best_failure: Option<(Token, &'static str, MatcherLoc)>, - root_span: Span, - result: Option>, -} - -impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, 'matcher> { - fn before_match_loc(&mut self, parser: &TtParser, matcher: &'matcher MatcherLoc) { - if self.remaining_matcher.is_none() - || (parser.has_no_remaining_items_for_step() && *matcher != MatcherLoc::Eof) - { - self.remaining_matcher = Some(matcher); - } - } - - fn after_arm(&mut self, result: &NamedParseResult) { - match result { - Success(_) => { - // Nonterminal parser recovery might turn failed matches into successful ones, - // but for that it must have emitted an error already - self.cx.sess.delay_span_bug( - self.root_span, - "should not collect detailed info for successful macro match", - ); - } - Failure(token, msg) => match self.best_failure { - Some((ref best_token, _, _)) if best_token.span.lo() >= token.span.lo() => {} - _ => { - self.best_failure = Some(( - token.clone(), - msg, - self.remaining_matcher - .expect("must have collected matcher already") - .clone(), - )) - } - }, - Error(err_sp, msg) => { - let span = err_sp.substitute_dummy(self.root_span); - self.cx.struct_span_err(span, msg).emit(); - self.result = Some(DummyResult::any(span)); - } - ErrorReported(_) => self.result = Some(DummyResult::any(self.root_span)), - } - } - - fn description() -> &'static str { - "detailed" - } - - fn recovery() -> Recovery { - Recovery::Allowed - } -} - -impl<'a, 'cx> CollectTrackerAndEmitter<'a, 'cx, '_> { - fn new(cx: &'a mut ExtCtxt<'cx>, root_span: Span) -> Self { - Self { cx, remaining_matcher: None, best_failure: None, root_span, result: None } - } -} - -enum CanRetry { +pub(super) enum CanRetry { Yes, /// We are not allowed to retry macro expansion as a fatal error has been emitted already. No(ErrorGuaranteed), @@ -469,7 +275,7 @@ enum CanRetry { /// and nothing if it failed. On failure, it's the callers job to use `track` accordingly to record all errors /// correctly. #[instrument(level = "debug", skip(sess, arg, lhses, track), fields(tracking = %T::description()))] -fn try_match_macro<'matcher, T: Tracker<'matcher>>( +pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>( sess: &ParseSess, name: Ident, arg: &TokenStream, @@ -769,30 +575,6 @@ pub fn compile_declarative_macro( (mk_syn_ext(expander), rule_spans) } -#[derive(Subdiagnostic)] -enum ExplainDocComment { - #[label(expand_explain_doc_comment_inner)] - Inner { - #[primary_span] - span: Span, - }, - #[label(expand_explain_doc_comment_outer)] - Outer { - #[primary_span] - span: Span, - }, -} - -fn annotate_doc_comment(err: &mut Diagnostic, sm: &SourceMap, span: Span) { - if let Ok(src) = sm.span_to_snippet(span) { - if src.starts_with("///") || src.starts_with("/**") { - err.subdiagnostic(ExplainDocComment::Outer { span }); - } else if src.starts_with("//!") || src.starts_with("/*!") { - err.subdiagnostic(ExplainDocComment::Inner { span }); - } - } -} - fn check_lhs_nt_follows(sess: &ParseSess, def: &ast::Item, lhs: &mbe::TokenTree) -> bool { // lhs is going to be like TokenTree::Delimited(...), where the // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens. @@ -1577,15 +1359,6 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String { } } -fn parser_from_cx(sess: &ParseSess, tts: TokenStream, recovery: Recovery) -> Parser<'_> { +pub(super) fn parser_from_cx(sess: &ParseSess, tts: TokenStream, recovery: Recovery) -> Parser<'_> { Parser::new(sess, tts, true, rustc_parse::MACRO_ARGUMENTS).recovery(recovery) } - -/// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For -/// other tokens, this is "unexpected token...". -fn parse_failure_msg(tok: &Token) -> String { - match tok.kind { - token::Eof => "unexpected end of macro invocation".to_string(), - _ => format!("no rules expected the token `{}`", pprust::token_to_string(tok),), - } -} From 3fe37b8c6e02daa6a7c33a71bb7f44682e43d08d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20L=C3=B6bel?= Date: Sun, 28 Mar 2021 14:24:49 +0200 Subject: [PATCH 08/20] Add get_many_mut methods to slice --- library/core/src/error.rs | 3 + library/core/src/slice/mod.rs | 136 ++++++++++++++++++++++++++++++++++ library/core/tests/lib.rs | 1 + library/core/tests/slice.rs | 60 +++++++++++++++ library/std/src/lib.rs | 1 + 5 files changed, 201 insertions(+) diff --git a/library/core/src/error.rs b/library/core/src/error.rs index c9c7cdf4def..7152300abcb 100644 --- a/library/core/src/error.rs +++ b/library/core/src/error.rs @@ -506,3 +506,6 @@ fn description(&self) -> &str { #[unstable(feature = "cstr_from_bytes_until_nul", issue = "95027")] impl Error for crate::ffi::FromBytesUntilNulError {} + +#[unstable(feature = "get_many_mut", issue = "104642")] +impl Error for crate::slice::GetManyMutError {} diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index ad90e00b8a0..04486ed2d14 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -7,6 +7,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::cmp::Ordering::{self, Greater, Less}; +use crate::fmt; use crate::intrinsics::{assert_unsafe_precondition, exact_div}; use crate::marker::Copy; use crate::mem::{self, SizedTypeProperties}; @@ -4082,6 +4083,88 @@ pub fn take_last_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> { *self = rem; Some(last) } + + /// Returns mutable references to many indices at once, without doing any checks. + /// + /// For a safe alternative see [`get_many_mut`]. + /// + /// # Safety + /// + /// Calling this method with overlapping or out-of-bounds indices is *[undefined behavior]* + /// even if the resulting references are not used. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_many_mut)] + /// + /// let x = &mut [1, 2, 4]; + /// + /// unsafe { + /// let [a, b] = x.get_many_unchecked_mut([0, 2]); + /// *a *= 10; + /// *b *= 100; + /// } + /// assert_eq!(x, &[10, 2, 400]); + /// ``` + /// + /// [`get_many_mut`]: slice::get_many_mut + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + #[unstable(feature = "get_many_mut", issue = "104642")] + #[inline] + pub unsafe fn get_many_unchecked_mut( + &mut self, + indices: [usize; N], + ) -> [&mut T; N] { + // NB: This implementation is written as it is because any variation of + // `indices.map(|i| self.get_unchecked_mut(i))` would make miri unhappy, + // or generate worse code otherwise. This is also why we need to go + // through a raw pointer here. + let slice: *mut [T] = self; + let mut arr: mem::MaybeUninit<[&mut T; N]> = mem::MaybeUninit::uninit(); + let arr_ptr = arr.as_mut_ptr(); + + // SAFETY: We expect `indices` to contain disjunct values that are + // in bounds of `self`. + unsafe { + for i in 0..N { + let idx = *indices.get_unchecked(i); + *(*arr_ptr).get_unchecked_mut(i) = &mut *slice.get_unchecked_mut(idx); + } + arr.assume_init() + } + } + + /// Returns mutable references to many indices at once. + /// + /// Returns an error if any index is out-of-bounds, or if the same index was + /// passed more than once. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_many_mut)] + /// + /// let v = &mut [1, 2, 3]; + /// if let Ok([a, b]) = v.get_many_mut([0, 2]) { + /// *a = 413; + /// *b = 612; + /// } + /// assert_eq!(v, &[413, 2, 612]); + /// ``` + #[unstable(feature = "get_many_mut", issue = "104642")] + #[inline] + pub fn get_many_mut( + &mut self, + indices: [usize; N], + ) -> Result<[&mut T; N], GetManyMutError> { + if !get_many_check_valid(&indices, self.len()) { + return Err(GetManyMutError { _private: () }); + } + // SAFETY: The `get_many_check_valid()` call checked that all indices + // are disjunct and in bounds. + unsafe { Ok(self.get_many_unchecked_mut(indices)) } + } } impl [[T; N]] { @@ -4304,3 +4387,56 @@ fn as_slice(&self) -> &[Self::Item] { self } } + +/// This checks every index against each other, and against `len`. +/// +/// This will do `binomial(N + 1, 2) = N * (N + 1) / 2 = 0, 1, 3, 6, 10, ..` +/// comparison operations. +fn get_many_check_valid(indices: &[usize; N], len: usize) -> bool { + // NB: The optimzer should inline the loops into a sequence + // of instructions without additional branching. + let mut valid = true; + for (i, &idx) in indices.iter().enumerate() { + valid &= idx < len; + for &idx2 in &indices[..i] { + valid &= idx != idx2; + } + } + valid +} + +/// The error type returned by [`get_many_mut`][`slice::get_many_mut`]. +/// +/// It indicates one of two possible errors: +/// - An index is out-of-bounds. +/// - The same index appeared multiple times in the array. +/// +/// # Examples +/// +/// ``` +/// #![feature(get_many_mut)] +/// +/// let v = &mut [1, 2, 3]; +/// assert!(v.get_many_mut([0, 999]).is_err()); +/// assert!(v.get_many_mut([1, 1]).is_err()); +/// ``` +#[unstable(feature = "get_many_mut", issue = "104642")] +// NB: The N here is there to be forward-compatible with adding more details +// to the error type at a later point +pub struct GetManyMutError { + _private: (), +} + +#[unstable(feature = "get_many_mut", issue = "104642")] +impl fmt::Debug for GetManyMutError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("GetManyMutError").finish_non_exhaustive() + } +} + +#[unstable(feature = "get_many_mut", issue = "104642")] +impl fmt::Display for GetManyMutError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt("an index is out of bounds or appeared multiple times in the array", f) + } +} diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 4c0c0da652f..abbad96c4da 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -108,6 +108,7 @@ #![feature(provide_any)] #![feature(utf8_chunks)] #![feature(is_ascii_octdigit)] +#![feature(get_many_mut)] #![deny(unsafe_op_in_unsafe_fn)] extern crate test; diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 9e1fbea7914..4e06e0f4398 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -2595,3 +2595,63 @@ fn test_flatten_mut_size_overflow() { let x = &mut [[(); usize::MAX]; 2][..]; let _ = x.flatten_mut(); } + +#[test] +fn test_get_many_mut_normal_2() { + let mut v = vec![1, 2, 3, 4, 5]; + let [a, b] = v.get_many_mut([3, 0]).unwrap(); + *a += 10; + *b += 100; + assert_eq!(v, vec![101, 2, 3, 14, 5]); +} + +#[test] +fn test_get_many_mut_normal_3() { + let mut v = vec![1, 2, 3, 4, 5]; + let [a, b, c] = v.get_many_mut([0, 4, 2]).unwrap(); + *a += 10; + *b += 100; + *c += 1000; + assert_eq!(v, vec![11, 2, 1003, 4, 105]); +} + +#[test] +fn test_get_many_mut_empty() { + let mut v = vec![1, 2, 3, 4, 5]; + let [] = v.get_many_mut([]).unwrap(); + assert_eq!(v, vec![1, 2, 3, 4, 5]); +} + +#[test] +fn test_get_many_mut_single_first() { + let mut v = vec![1, 2, 3, 4, 5]; + let [a] = v.get_many_mut([0]).unwrap(); + *a += 10; + assert_eq!(v, vec![11, 2, 3, 4, 5]); +} + +#[test] +fn test_get_many_mut_single_last() { + let mut v = vec![1, 2, 3, 4, 5]; + let [a] = v.get_many_mut([4]).unwrap(); + *a += 10; + assert_eq!(v, vec![1, 2, 3, 4, 15]); +} + +#[test] +fn test_get_many_mut_oob_nonempty() { + let mut v = vec![1, 2, 3, 4, 5]; + assert!(v.get_many_mut([5]).is_err()); +} + +#[test] +fn test_get_many_mut_oob_empty() { + let mut v: Vec = vec![]; + assert!(v.get_many_mut([0]).is_err()); +} + +#[test] +fn test_get_many_mut_duplicate() { + let mut v = vec![1, 2, 3, 4, 5]; + assert!(v.get_many_mut([1, 3, 3, 4]).is_err()); +} diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 9334c833bb6..63ee6c521d7 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -347,6 +347,7 @@ #![feature(stdsimd)] #![feature(test)] #![feature(trace_macros)] +#![feature(get_many_mut)] // // Only used in tests/benchmarks: // From 01a2a546bea08e6b561f99fe09aa94df3f185bbc Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 20 Nov 2022 01:22:40 +0000 Subject: [PATCH 09/20] test-various: Use clang for the UEFI test This syncs it with how the UEFI targets are built in dist-various-2. --- src/ci/docker/host-x86_64/test-various/Dockerfile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ci/docker/host-x86_64/test-various/Dockerfile b/src/ci/docker/host-x86_64/test-various/Dockerfile index b0f35bcb9cc..0bddffa3436 100644 --- a/src/ci/docker/host-x86_64/test-various/Dockerfile +++ b/src/ci/docker/host-x86_64/test-various/Dockerfile @@ -1,6 +1,7 @@ FROM ubuntu:20.04 RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + clang-11 \ g++ \ make \ ninja-build \ @@ -67,7 +68,9 @@ ENV MUSL_TARGETS=x86_64-unknown-linux-musl \ ENV MUSL_SCRIPT python3 /checkout/x.py --stage 2 test --host='' --target $MUSL_TARGETS COPY host-x86_64/test-various/uefi_qemu_test /uefi_qemu_test -ENV UEFI_TARGETS=x86_64-unknown-uefi +ENV UEFI_TARGETS=x86_64-unknown-uefi \ + CC_x86_64_unknown_uefi=clang-11 \ + CXX_x86_64_unknown_uefi=clang++-11 ENV UEFI_SCRIPT python3 /checkout/x.py --stage 2 build --host='' --target $UEFI_TARGETS && \ python3 -u /uefi_qemu_test/run.py From 9f4b4e46a3ba5602916e96f8a4186eaf63d91682 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Fri, 23 Sep 2022 15:14:34 -0400 Subject: [PATCH 10/20] constify remaining layout methods Remove bad impl for Eq Update Cargo.lock and fix last ValidAlign --- library/core/src/alloc/layout.rs | 33 +++++++++++++++++++++---------- library/core/src/lib.rs | 3 +++ library/core/src/ptr/alignment.rs | 21 ++++++++++++++------ 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index f50d9a8e1bd..2c1911c350e 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -157,9 +157,10 @@ pub const fn new() -> Self { /// allocate backing structure for `T` (which could be a trait /// or other unsized type like a slice). #[stable(feature = "alloc_layout", since = "1.28.0")] + #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[must_use] #[inline] - pub fn for_value(t: &T) -> Self { + pub const fn for_value(t: &T) -> Self { let (size, align) = (mem::size_of_val(t), mem::align_of_val(t)); // SAFETY: see rationale in `new` for why this is using the unsafe variant unsafe { Layout::from_size_align_unchecked(size, align) } @@ -191,8 +192,9 @@ pub fn for_value(t: &T) -> Self { /// [trait object]: ../../book/ch17-02-trait-objects.html /// [extern type]: ../../unstable-book/language-features/extern-types.html #[unstable(feature = "layout_for_ptr", issue = "69835")] + #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[must_use] - pub unsafe fn for_value_raw(t: *const T) -> Self { + pub const unsafe fn for_value_raw(t: *const T) -> Self { // SAFETY: we pass along the prerequisites of these functions to the caller let (size, align) = unsafe { (mem::size_of_val_raw(t), mem::align_of_val_raw(t)) }; // SAFETY: see rationale in `new` for why this is using the unsafe variant @@ -229,8 +231,9 @@ pub const fn dangling(&self) -> NonNull { /// Returns an error if the combination of `self.size()` and the given /// `align` violates the conditions listed in [`Layout::from_size_align`]. #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] + #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[inline] - pub fn align_to(&self, align: usize) -> Result { + pub const fn align_to(&self, align: usize) -> Result { Layout::from_size_align(self.size(), cmp::max(self.align(), align)) } @@ -287,10 +290,11 @@ pub const fn padding_needed_for(&self, align: usize) -> usize { /// This is equivalent to adding the result of `padding_needed_for` /// to the layout's current size. #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] + #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[must_use = "this returns a new `Layout`, \ without modifying the original"] #[inline] - pub fn pad_to_align(&self) -> Layout { + pub const fn pad_to_align(&self) -> Layout { let pad = self.padding_needed_for(self.align()); // This cannot overflow. Quoting from the invariant of Layout: // > `size`, when rounded up to the nearest multiple of `align`, @@ -311,8 +315,9 @@ pub fn pad_to_align(&self) -> Layout { /// /// On arithmetic overflow, returns `LayoutError`. #[unstable(feature = "alloc_layout_extra", issue = "55724")] + #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[inline] - pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutError> { + pub const fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutError> { // This cannot overflow. Quoting from the invariant of Layout: // > `size`, when rounded up to the nearest multiple of `align`, // > must not overflow isize (i.e., the rounded value must be @@ -370,8 +375,9 @@ pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutError> { /// # assert_eq!(repr_c(&[u64, u32, u16, u32]), Ok((s, vec![0, 8, 12, 16]))); /// ``` #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] + #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[inline] - pub fn extend(&self, next: Self) -> Result<(Self, usize), LayoutError> { + pub const fn extend(&self, next: Self) -> Result<(Self, usize), LayoutError> { let new_align = cmp::max(self.align, next.align); let pad = self.padding_needed_for(next.align()); @@ -396,8 +402,9 @@ pub fn extend(&self, next: Self) -> Result<(Self, usize), LayoutError> { /// /// On arithmetic overflow, returns `LayoutError`. #[unstable(feature = "alloc_layout_extra", issue = "55724")] + #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[inline] - pub fn repeat_packed(&self, n: usize) -> Result { + pub const fn repeat_packed(&self, n: usize) -> Result { let size = self.size().checked_mul(n).ok_or(LayoutError)?; // The safe constructor is called here to enforce the isize size limit. Layout::from_size_alignment(size, self.align) @@ -410,8 +417,9 @@ pub fn repeat_packed(&self, n: usize) -> Result { /// /// On arithmetic overflow, returns `LayoutError`. #[unstable(feature = "alloc_layout_extra", issue = "55724")] + #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[inline] - pub fn extend_packed(&self, next: Self) -> Result { + pub const fn extend_packed(&self, next: Self) -> Result { let new_size = self.size().checked_add(next.size()).ok_or(LayoutError)?; // The safe constructor is called here to enforce the isize size limit. Layout::from_size_alignment(new_size, self.align) @@ -422,13 +430,18 @@ pub fn extend_packed(&self, next: Self) -> Result { /// On arithmetic overflow or when the total size would exceed /// `isize::MAX`, returns `LayoutError`. #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] + #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[inline] - pub fn array(n: usize) -> Result { + pub const fn array(n: usize) -> Result { // Reduce the amount of code we need to monomorphize per `T`. return inner(mem::size_of::(), Alignment::of::(), n); #[inline] - fn inner(element_size: usize, align: Alignment, n: usize) -> Result { + const fn inner( + element_size: usize, + align: Alignment, + n: usize, + ) -> Result { // We need to check two things about the size: // - That the total size won't overflow a `usize`, and // - That the total size still fits in an `isize`. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 848eccd7f29..459489942b1 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -98,6 +98,8 @@ // Library features: #![feature(const_align_offset)] #![feature(const_align_of_val)] +#![feature(const_align_of_val_raw)] +#![feature(const_alloc_layout)] #![feature(const_arguments_as_str)] #![feature(const_array_into_iter_constructors)] #![feature(const_bigint_helper_methods)] @@ -140,6 +142,7 @@ #![feature(const_ptr_write)] #![feature(const_raw_ptr_comparison)] #![feature(const_size_of_val)] +#![feature(const_size_of_val_raw)] #![feature(const_slice_from_raw_parts_mut)] #![feature(const_slice_ptr_len)] #![feature(const_slice_split_at_mut)] diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index 1390e09dd96..61eb23c7bca 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -9,7 +9,7 @@ /// Note that particularly large alignments, while representable in this type, /// are likely not to be supported by actual allocators and linkers. #[unstable(feature = "ptr_alignment_type", issue = "102070")] -#[derive(Copy, Clone, Eq, PartialEq)] +#[derive(Copy, Clone, Eq)] #[repr(transparent)] pub struct Alignment(AlignmentEnum); @@ -167,16 +167,25 @@ fn from(align: Alignment) -> usize { } } -#[unstable(feature = "ptr_alignment_type", issue = "102070")] -impl cmp::Ord for Alignment { +#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] +impl const cmp::PartialEq for Alignment { #[inline] - fn cmp(&self, other: &Self) -> cmp::Ordering { - self.as_nonzero().cmp(&other.as_nonzero()) + fn eq(&self, other: &Self) -> bool { + self.as_nonzero().get() == other.as_nonzero().get() } } +#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] +impl const cmp::Ord for Alignment { + #[inline] + fn cmp(&self, other: &Self) -> cmp::Ordering { + self.as_nonzero().get().cmp(&other.as_nonzero().get()) + } +} + +#[rustc_const_unstable(feature = "const_alloc_layout", issue = "87864")] #[unstable(feature = "ptr_alignment_type", issue = "102070")] -impl cmp::PartialOrd for Alignment { +impl const cmp::PartialOrd for Alignment { #[inline] fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) From 414e84a2f742b25f10edcfbf78be6779b4ea842b Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Mon, 17 Oct 2022 12:27:27 -0400 Subject: [PATCH 11/20] Add stability for alignment --- library/core/src/ptr/alignment.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index 61eb23c7bca..fd3e4326ac3 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -168,6 +168,7 @@ fn from(align: Alignment) -> usize { } #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] +#[unstable(feature = "ptr_alignment_type", issue = "102070")] impl const cmp::PartialEq for Alignment { #[inline] fn eq(&self, other: &Self) -> bool { @@ -176,6 +177,7 @@ fn eq(&self, other: &Self) -> bool { } #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] +#[unstable(feature = "ptr_alignment_type", issue = "102070")] impl const cmp::Ord for Alignment { #[inline] fn cmp(&self, other: &Self) -> cmp::Ordering { From 6f2dcac78b536ba66912346766059e52ff5e94a6 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Sat, 12 Nov 2022 14:21:18 -0500 Subject: [PATCH 12/20] Update with derive_const --- library/core/src/alloc/layout.rs | 5 ++++- library/core/src/ptr/alignment.rs | 23 +++++++++++------------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index 2c1911c350e..bea62779bf8 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -326,7 +326,10 @@ pub const fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutError> { let alloc_size = padded_size.checked_mul(n).ok_or(LayoutError)?; // The safe constructor is called here to enforce the isize size limit. - Layout::from_size_alignment(alloc_size, self.align).map(|layout| (layout, padded_size)) + match Layout::from_size_alignment(alloc_size, self.align) { + Ok(layout) => Ok((layout, padded_size)), + Err(e) => Err(e), + } } /// Creates a layout describing the record for `self` followed by diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index fd3e4326ac3..dea979265e6 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -10,6 +10,8 @@ /// are likely not to be supported by actual allocators and linkers. #[unstable(feature = "ptr_alignment_type", issue = "102070")] #[derive(Copy, Clone, Eq)] +#[cfg_attr(bootstrap, derive(PartialEq))] +#[cfg_attr(not(bootstrap), derive_const(PartialEq))] #[repr(transparent)] pub struct Alignment(AlignmentEnum); @@ -167,15 +169,6 @@ fn from(align: Alignment) -> usize { } } -#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] -#[unstable(feature = "ptr_alignment_type", issue = "102070")] -impl const cmp::PartialEq for Alignment { - #[inline] - fn eq(&self, other: &Self) -> bool { - self.as_nonzero().get() == other.as_nonzero().get() - } -} - #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[unstable(feature = "ptr_alignment_type", issue = "102070")] impl const cmp::Ord for Alignment { @@ -209,7 +202,9 @@ fn hash(&self, state: &mut H) { #[cfg(target_pointer_width = "64")] type AlignmentEnum = AlignmentEnum64; -#[derive(Copy, Clone, Eq, PartialEq)] +#[derive(Copy, Clone, Eq)] +#[cfg_attr(bootstrap, derive(PartialEq))] +#[cfg_attr(not(bootstrap), derive_const(PartialEq))] #[repr(u16)] enum AlignmentEnum16 { _Align1Shl0 = 1 << 0, @@ -230,7 +225,9 @@ enum AlignmentEnum16 { _Align1Shl15 = 1 << 15, } -#[derive(Copy, Clone, Eq, PartialEq)] +#[derive(Copy, Clone, Eq)] +#[cfg_attr(bootstrap, derive(PartialEq))] +#[cfg_attr(not(bootstrap), derive_const(PartialEq))] #[repr(u32)] enum AlignmentEnum32 { _Align1Shl0 = 1 << 0, @@ -267,7 +264,9 @@ enum AlignmentEnum32 { _Align1Shl31 = 1 << 31, } -#[derive(Copy, Clone, Eq, PartialEq)] +#[derive(Copy, Clone, Eq)] +#[cfg_attr(bootstrap, derive(PartialEq))] +#[cfg_attr(not(bootstrap), derive_const(PartialEq))] #[repr(u64)] enum AlignmentEnum64 { _Align1Shl0 = 1 << 0, From 7972b8aa3733f3d07f1794450fd1e28bf51eece4 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Sat, 12 Nov 2022 20:09:42 -0500 Subject: [PATCH 13/20] Add derive_const feature --- library/core/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 459489942b1..0d190e8a0d5 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -157,6 +157,7 @@ #![feature(const_unsafecell_get_mut)] #![feature(const_waker)] #![feature(core_panic)] +#![cfg_attr(not(bootstrap), feature(derive_const))] #![feature(duration_consts_float)] #![feature(maybe_uninit_uninit_array)] #![feature(ptr_alignment_type)] From a5fecc690562f23ffe95a0e167bf0a57eca725ad Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Sat, 12 Nov 2022 20:48:32 -0500 Subject: [PATCH 14/20] Fix issue number --- library/core/src/ptr/alignment.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index dea979265e6..64a5290c3a2 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -178,7 +178,7 @@ fn cmp(&self, other: &Self) -> cmp::Ordering { } } -#[rustc_const_unstable(feature = "const_alloc_layout", issue = "87864")] +#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[unstable(feature = "ptr_alignment_type", issue = "102070")] impl const cmp::PartialOrd for Alignment { #[inline] From 07911879d2bea1b28aee16451e4a532462d55b00 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Sun, 13 Nov 2022 11:13:32 -0500 Subject: [PATCH 15/20] Use ? instead of match --- library/core/src/alloc/layout.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index bea62779bf8..ac3d84718d5 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -326,10 +326,8 @@ pub const fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutError> { let alloc_size = padded_size.checked_mul(n).ok_or(LayoutError)?; // The safe constructor is called here to enforce the isize size limit. - match Layout::from_size_alignment(alloc_size, self.align) { - Ok(layout) => Ok((layout, padded_size)), - Err(e) => Err(e), - } + let layout = Layout::from_size_alignment(alloc_size, self.align)?; + Ok((layout, padded_size)) } /// Creates a layout describing the record for `self` followed by From 60546088bcfa9ce210a5b0f92079f7642f3b466b Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 20 Nov 2022 19:13:17 +0000 Subject: [PATCH 16/20] dist: Ensure UEFI rlibs are all COFF If clang isn't the C compiler used for the UEFI targets, or if the wrong `--target` is passed to clang, we will get ELF objects in some rlibs. This will cause problems at link time when trying to compile a UEFI program that uses any of those objects. Add a check to the dist step for UEFI targets that reads each rlib with the `object` crate and fails with an error if any non-COFF objects are found. --- src/bootstrap/Cargo.lock | 10 ++++++++++ src/bootstrap/Cargo.toml | 1 + src/bootstrap/dist.rs | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index e1a108cea95..acac9e7a03c 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -53,6 +53,7 @@ dependencies = [ "hex", "ignore", "libc", + "object", "once_cell", "opener", "pretty_assertions", @@ -400,6 +401,15 @@ dependencies = [ "libc", ] +[[package]] +name = "object" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.12.0" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index f74738437ea..4000d6cd477 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -42,6 +42,7 @@ getopts = "0.2.19" cc = "1.0.69" libc = "0.2" hex = "0.4" +object = { version = "0.29.0", default-features = false, features = ["archive", "coff", "read_core", "unaligned"] } serde = { version = "1.0.8", features = ["derive"] } serde_json = "1.0.2" sha2 = "0.10" diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index aacd2c7eab9..2fef7f65827 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -10,10 +10,14 @@ use std::collections::HashSet; use std::env; +use std::ffi::OsStr; use std::fs; use std::path::{Path, PathBuf}; use std::process::Command; +use object::read::archive::ArchiveFile; +use object::BinaryFormat; + use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; use crate::cache::{Interned, INTERNER}; use crate::channel; @@ -555,6 +559,39 @@ fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool { } } +/// Check that all objects in rlibs for UEFI targets are COFF. This +/// ensures that the C compiler isn't producing ELF objects, which would +/// not link correctly with the COFF objects. +fn verify_uefi_rlib_format(builder: &Builder<'_>, target: TargetSelection, stamp: &Path) { + if !target.ends_with("-uefi") { + return; + } + + for (path, _) in builder.read_stamp_file(stamp) { + if path.extension() != Some(OsStr::new("rlib")) { + continue; + } + + let data = t!(fs::read(&path)); + let data = data.as_slice(); + let archive = t!(ArchiveFile::parse(data)); + for member in archive.members() { + let member = t!(member); + let member_data = t!(member.data(data)); + + let is_coff = match object::File::parse(member_data) { + Ok(member_file) => member_file.format() == BinaryFormat::Coff, + Err(_) => false, + }; + + if !is_coff { + let member_name = String::from_utf8_lossy(member.name()); + panic!("member {} in {} is not COFF", member_name, path.display()); + } + } + } +} + /// Copy stamped files into an image's `target/lib` directory. fn copy_target_libs(builder: &Builder<'_>, target: TargetSelection, image: &Path, stamp: &Path) { let dst = image.join("lib/rustlib").join(target.triple).join("lib"); @@ -610,6 +647,7 @@ fn run(self, builder: &Builder<'_>) -> Option { let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); let stamp = compile::libstd_stamp(builder, compiler_to_use, target); + verify_uefi_rlib_format(builder, target, &stamp); copy_target_libs(builder, target, &tarball.image_dir(), &stamp); Some(tarball.generate()) From 8998711d9bbd75aad32ef4ade36fa042da7fde13 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Sun, 20 Nov 2022 17:10:47 -0500 Subject: [PATCH 17/20] Only one feature gate needed --- library/core/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 0d190e8a0d5..459489942b1 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -157,7 +157,6 @@ #![feature(const_unsafecell_get_mut)] #![feature(const_waker)] #![feature(core_panic)] -#![cfg_attr(not(bootstrap), feature(derive_const))] #![feature(duration_consts_float)] #![feature(maybe_uninit_uninit_array)] #![feature(ptr_alignment_type)] From a9e92be1f98605f343dfc6684107e236e6606947 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 21 Nov 2022 15:10:59 -0800 Subject: [PATCH 18/20] Bump ptr_to_from_bits deprecation to Rust 1.67 --- library/core/src/ptr/const_ptr.rs | 4 ++-- library/core/src/ptr/mut_ptr.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 2c371f635ab..e966e1bb466 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -120,7 +120,7 @@ pub const fn cast_mut(self) -> *mut T { /// ``` #[unstable(feature = "ptr_to_from_bits", issue = "91126")] #[rustc_deprecated( - since = "1.62", + since = "1.67", reason = "replaced by the `exposed_addr` method, or update your code \ to follow the strict provenance rules using its APIs" )] @@ -146,7 +146,7 @@ pub fn to_bits(self) -> usize /// ``` #[unstable(feature = "ptr_to_from_bits", issue = "91126")] #[rustc_deprecated( - since = "1.62", + since = "1.67", reason = "replaced by the `ptr::from_exposed_addr` function, or update \ your code to follow the strict provenance rules using its APIs" )] diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 79682531562..9507e8430c7 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -126,7 +126,7 @@ pub const fn cast_const(self) -> *const T { /// ``` #[unstable(feature = "ptr_to_from_bits", issue = "91126")] #[rustc_deprecated( - since = "1.62", + since = "1.67", reason = "replaced by the `exposed_addr` method, or update your code \ to follow the strict provenance rules using its APIs" )] @@ -152,7 +152,7 @@ pub fn to_bits(self) -> usize /// ``` #[unstable(feature = "ptr_to_from_bits", issue = "91126")] #[rustc_deprecated( - since = "1.62", + since = "1.67", reason = "replaced by the `ptr::from_exposed_addr_mut` function, or \ update your code to follow the strict provenance rules using its APIs" )] From 6d943af735a86cd7f77305b5723b9481d9bf1f71 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 21 Nov 2022 15:18:36 -0800 Subject: [PATCH 19/20] Rustc_deprecated attribute superseded by deprecated --- library/core/src/ptr/const_ptr.rs | 8 ++++---- library/core/src/ptr/mut_ptr.rs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index e966e1bb466..969029e262e 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -119,9 +119,9 @@ pub const fn cast_mut(self) -> *mut T { /// assert_eq!(p1.to_bits() - p0.to_bits(), 4); /// ``` #[unstable(feature = "ptr_to_from_bits", issue = "91126")] - #[rustc_deprecated( + #[deprecated( since = "1.67", - reason = "replaced by the `exposed_addr` method, or update your code \ + note = "replaced by the `exposed_addr` method, or update your code \ to follow the strict provenance rules using its APIs" )] pub fn to_bits(self) -> usize @@ -145,9 +145,9 @@ pub fn to_bits(self) -> usize /// assert_eq!(<*const u8>::from_bits(1), dangling); /// ``` #[unstable(feature = "ptr_to_from_bits", issue = "91126")] - #[rustc_deprecated( + #[deprecated( since = "1.67", - reason = "replaced by the `ptr::from_exposed_addr` function, or update \ + note = "replaced by the `ptr::from_exposed_addr` function, or update \ your code to follow the strict provenance rules using its APIs" )] #[allow(fuzzy_provenance_casts)] // this is an unstable and semi-deprecated cast function diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 9507e8430c7..d1b3a634433 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -125,9 +125,9 @@ pub const fn cast_const(self) -> *const T { /// assert_eq!(p1.to_bits() - p0.to_bits(), 4); /// ``` #[unstable(feature = "ptr_to_from_bits", issue = "91126")] - #[rustc_deprecated( + #[deprecated( since = "1.67", - reason = "replaced by the `exposed_addr` method, or update your code \ + note = "replaced by the `exposed_addr` method, or update your code \ to follow the strict provenance rules using its APIs" )] pub fn to_bits(self) -> usize @@ -151,9 +151,9 @@ pub fn to_bits(self) -> usize /// assert_eq!(<*mut u8>::from_bits(1), dangling); /// ``` #[unstable(feature = "ptr_to_from_bits", issue = "91126")] - #[rustc_deprecated( + #[deprecated( since = "1.67", - reason = "replaced by the `ptr::from_exposed_addr_mut` function, or \ + note = "replaced by the `ptr::from_exposed_addr_mut` function, or \ update your code to follow the strict provenance rules using its APIs" )] #[allow(fuzzy_provenance_casts)] // this is an unstable and semi-deprecated cast function From 70cee5af4b503948f778a4cf8627bbcb62f5d327 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 21 Nov 2022 15:28:41 -0800 Subject: [PATCH 20/20] Touch up Box one-liner --- library/alloc/src/boxed.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 00c922f3ae9..fc738cb68c3 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -1,4 +1,4 @@ -//! The pointer type for heap allocation for an owned value of type `T`. +//! The `Box` type for heap allocation. //! //! [`Box`], casually referred to as a 'box', provides the simplest form of //! heap allocation in Rust. Boxes provide ownership for this allocation, and @@ -187,7 +187,7 @@ mod thin; -/// A pointer type for heap allocation for an owned value of type `T`. +/// A pointer type that uniquely owns a heap allocation of type `T`. /// /// See the [module-level documentation](../../std/boxed/index.html) for more. #[lang = "owned_box"]