diff --git a/Cargo.lock b/Cargo.lock index b20c6e6a4fe9b..9c0978b92f73c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3234,9 +3234,9 @@ dependencies = [ [[package]] name = "rustc_apfloat" -version = "0.2.2+llvm-462a31f5a5ab" +version = "0.2.3+llvm-462a31f5a5ab" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121e2195ff969977a4e2b5c9965ea867fce7e4cb5aee5b09dee698a7932d574f" +checksum = "486c2179b4796f65bfe2ee33679acf0927ac83ecf583ad6c91c3b4570911b9ad" dependencies = [ "bitflags", "smallvec", diff --git a/bootstrap.example.toml b/bootstrap.example.toml index 1371fd6442f96..19cf360b0fb8b 100644 --- a/bootstrap.example.toml +++ b/bootstrap.example.toml @@ -381,6 +381,15 @@ # "miri", "cargo-miri" # for dev/nightly channels #] +# Specify build configuration specific for some tool, such as enabled features. +# This option has no effect on which tools are enabled: refer to the `tools` option for that. +# +# For example, to build Miri with tracing support, use `tool.miri.features = ["tracing"]` +# +# The default value for the `features` array is `[]`. However, please note that other flags in +# `bootstrap.toml` might influence the features enabled for some tools. +#tool.TOOL_NAME.features = [FEATURE1, FEATURE2] + # Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose, 3 == print environment variables on each rustc invocation #verbose = 0 diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index cf40c3f7f6f8e..bdd81e71e2510 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -97,12 +97,12 @@ pub struct Path { pub tokens: Option, } +// Succeeds if the path has a single segment that is arg-free and matches the given symbol. impl PartialEq for Path { #[inline] fn eq(&self, name: &Symbol) -> bool { if let [segment] = self.segments.as_ref() - && segment.args.is_none() - && segment.ident.name == *name + && segment == name { true } else { @@ -111,6 +111,15 @@ impl PartialEq for Path { } } +// Succeeds if the path has segments that are arg-free and match the given symbols. +impl PartialEq<&[Symbol]> for Path { + #[inline] + fn eq(&self, names: &&[Symbol]) -> bool { + self.segments.len() == names.len() + && self.segments.iter().zip(names.iter()).all(|(s1, s2)| s1 == s2) + } +} + impl HashStable for Path { fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { self.segments.len().hash_stable(hcx, hasher); @@ -166,6 +175,14 @@ pub struct PathSegment { pub args: Option>, } +// Succeeds if the path segment is arg-free and matches the given symbol. +impl PartialEq for PathSegment { + #[inline] + fn eq(&self, name: &Symbol) -> bool { + self.args.is_none() && self.ident.name == *name + } +} + impl PathSegment { pub fn from_ident(ident: Ident) -> Self { PathSegment { ident, id: DUMMY_NODE_ID, args: None } @@ -1441,11 +1458,15 @@ impl Expr { } } - ExprKind::Break(..) - | ExprKind::Ret(..) - | ExprKind::Yield(..) - | ExprKind::Yeet(..) - | ExprKind::Become(..) => ExprPrecedence::Jump, + ExprKind::Break(_ /*label*/, value) + | ExprKind::Ret(value) + | ExprKind::Yield(YieldKind::Prefix(value)) + | ExprKind::Yeet(value) => match value { + Some(_) => ExprPrecedence::Jump, + None => ExprPrecedence::Unambiguous, + }, + + ExprKind::Become(_) => ExprPrecedence::Jump, // `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to // parse, instead of parsing as `(x .. x) = x`. Giving `Range` a lower precedence @@ -1502,6 +1523,7 @@ impl Expr { | ExprKind::Underscore | ExprKind::UnsafeBinderCast(..) | ExprKind::While(..) + | ExprKind::Yield(YieldKind::Postfix(..)) | ExprKind::Err(_) | ExprKind::Dummy => ExprPrecedence::Unambiguous, } diff --git a/compiler/rustc_ast_pretty/src/pprust/mod.rs b/compiler/rustc_ast_pretty/src/pprust/mod.rs index a05e2bd6a5d72..a766e2006e593 100644 --- a/compiler/rustc_ast_pretty/src/pprust/mod.rs +++ b/compiler/rustc_ast_pretty/src/pprust/mod.rs @@ -53,6 +53,18 @@ pub fn item_to_string(i: &ast::Item) -> String { State::new().item_to_string(i) } +pub fn assoc_item_to_string(i: &ast::AssocItem) -> String { + State::new().assoc_item_to_string(i) +} + +pub fn foreign_item_to_string(i: &ast::ForeignItem) -> String { + State::new().foreign_item_to_string(i) +} + +pub fn stmt_to_string(s: &ast::Stmt) -> String { + State::new().stmt_to_string(s) +} + pub fn path_to_string(p: &ast::Path) -> String { State::new().path_to_string(p) } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 0990c9b27eb09..3d738fa31f2b3 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1063,6 +1063,14 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere Self::to_string(|s| s.print_item(i)) } + fn assoc_item_to_string(&self, i: &ast::AssocItem) -> String { + Self::to_string(|s| s.print_assoc_item(i)) + } + + fn foreign_item_to_string(&self, i: &ast::ForeignItem) -> String { + Self::to_string(|s| s.print_foreign_item(i)) + } + fn path_to_string(&self, p: &ast::Path) -> String { Self::to_string(|s| s.print_path(p, false, 0)) } diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index c9a7e2aebd01b..ee49246a4bbf3 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -7,8 +7,8 @@ use rustc_ast::util::classify; use rustc_ast::util::literal::escape_byte_str_symbol; use rustc_ast::util::parser::{self, ExprPrecedence, Fixity}; use rustc_ast::{ - self as ast, BlockCheckMode, FormatAlignment, FormatArgPosition, FormatArgsPiece, FormatCount, - FormatDebugHex, FormatSign, FormatTrait, YieldKind, token, + self as ast, BinOpKind, BlockCheckMode, FormatAlignment, FormatArgPosition, FormatArgsPiece, + FormatCount, FormatDebugHex, FormatSign, FormatTrait, YieldKind, token, }; use crate::pp::Breaks::Inconsistent; @@ -214,13 +214,6 @@ impl<'a> State<'a> { } fn print_expr_call(&mut self, func: &ast::Expr, args: &[P], fixup: FixupContext) { - let needs_paren = match func.kind { - // In order to call a named field, needs parens: `(self.fun)()` - // But not for an unnamed field: `self.0()` - ast::ExprKind::Field(_, name) => !name.is_numeric(), - _ => func.precedence() < ExprPrecedence::Unambiguous, - }; - // Independent of parenthesization related to precedence, we must // parenthesize `func` if this is a statement context in which without // parentheses, a statement boundary would occur inside `func` or @@ -237,8 +230,16 @@ impl<'a> State<'a> { // because the latter is valid syntax but with the incorrect meaning. // It's a match-expression followed by tuple-expression, not a function // call. - self.print_expr_cond_paren(func, needs_paren, fixup.leftmost_subexpression()); + let func_fixup = fixup.leftmost_subexpression_with_operator(true); + + let needs_paren = match func.kind { + // In order to call a named field, needs parens: `(self.fun)()` + // But not for an unnamed field: `self.0()` + ast::ExprKind::Field(_, name) => !name.is_numeric(), + _ => func_fixup.precedence(func) < ExprPrecedence::Unambiguous, + }; + self.print_expr_cond_paren(func, needs_paren, func_fixup); self.print_call_post(args) } @@ -281,9 +282,24 @@ impl<'a> State<'a> { rhs: &ast::Expr, fixup: FixupContext, ) { + let operator_can_begin_expr = match op { + | BinOpKind::Sub // -x + | BinOpKind::Mul // *x + | BinOpKind::And // &&x + | BinOpKind::Or // || x + | BinOpKind::BitAnd // &x + | BinOpKind::BitOr // |x| x + | BinOpKind::Shl // <::Type as Trait>::CONST + | BinOpKind::Lt // ::CONST + => true, + _ => false, + }; + + let left_fixup = fixup.leftmost_subexpression_with_operator(operator_can_begin_expr); + let binop_prec = op.precedence(); - let left_prec = lhs.precedence(); - let right_prec = rhs.precedence(); + let left_prec = left_fixup.precedence(lhs); + let right_prec = fixup.precedence(rhs); let (mut left_needs_paren, right_needs_paren) = match op.fixity() { Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec), @@ -312,18 +328,18 @@ impl<'a> State<'a> { _ => {} } - self.print_expr_cond_paren(lhs, left_needs_paren, fixup.leftmost_subexpression()); + self.print_expr_cond_paren(lhs, left_needs_paren, left_fixup); self.space(); self.word_space(op.as_str()); - self.print_expr_cond_paren(rhs, right_needs_paren, fixup.subsequent_subexpression()); + self.print_expr_cond_paren(rhs, right_needs_paren, fixup.rightmost_subexpression()); } fn print_expr_unary(&mut self, op: ast::UnOp, expr: &ast::Expr, fixup: FixupContext) { self.word(op.as_str()); self.print_expr_cond_paren( expr, - expr.precedence() < ExprPrecedence::Prefix, - fixup.subsequent_subexpression(), + fixup.precedence(expr) < ExprPrecedence::Prefix, + fixup.rightmost_subexpression(), ); } @@ -344,8 +360,8 @@ impl<'a> State<'a> { } self.print_expr_cond_paren( expr, - expr.precedence() < ExprPrecedence::Prefix, - fixup.subsequent_subexpression(), + fixup.precedence(expr) < ExprPrecedence::Prefix, + fixup.rightmost_subexpression(), ); } @@ -590,8 +606,8 @@ impl<'a> State<'a> { self.word_space("="); self.print_expr_cond_paren( rhs, - rhs.precedence() < ExprPrecedence::Assign, - fixup.subsequent_subexpression(), + fixup.precedence(rhs) < ExprPrecedence::Assign, + fixup.rightmost_subexpression(), ); } ast::ExprKind::AssignOp(op, lhs, rhs) => { @@ -604,8 +620,8 @@ impl<'a> State<'a> { self.word_space(op.node.as_str()); self.print_expr_cond_paren( rhs, - rhs.precedence() < ExprPrecedence::Assign, - fixup.subsequent_subexpression(), + fixup.precedence(rhs) < ExprPrecedence::Assign, + fixup.rightmost_subexpression(), ); } ast::ExprKind::Field(expr, ident) => { @@ -618,10 +634,11 @@ impl<'a> State<'a> { self.print_ident(*ident); } ast::ExprKind::Index(expr, index, _) => { + let expr_fixup = fixup.leftmost_subexpression_with_operator(true); self.print_expr_cond_paren( expr, - expr.precedence() < ExprPrecedence::Unambiguous, - fixup.leftmost_subexpression(), + expr_fixup.precedence(expr) < ExprPrecedence::Unambiguous, + expr_fixup, ); self.word("["); self.print_expr(index, FixupContext::default()); @@ -634,10 +651,11 @@ impl<'a> State<'a> { // a "normal" binop gets parenthesized. (`LOr` is the lowest-precedence binop.) let fake_prec = ExprPrecedence::LOr; if let Some(e) = start { + let start_fixup = fixup.leftmost_subexpression_with_operator(true); self.print_expr_cond_paren( e, - e.precedence() < fake_prec, - fixup.leftmost_subexpression(), + start_fixup.precedence(e) < fake_prec, + start_fixup, ); } match limits { @@ -647,8 +665,8 @@ impl<'a> State<'a> { if let Some(e) = end { self.print_expr_cond_paren( e, - e.precedence() < fake_prec, - fixup.subsequent_subexpression(), + fixup.precedence(e) < fake_prec, + fixup.rightmost_subexpression(), ); } } @@ -665,11 +683,10 @@ impl<'a> State<'a> { self.space(); self.print_expr_cond_paren( expr, - // Parenthesize if required by precedence, or in the - // case of `break 'inner: loop { break 'inner 1 } + 1` - expr.precedence() < ExprPrecedence::Jump - || (opt_label.is_none() && classify::leading_labeled_expr(expr)), - fixup.subsequent_subexpression(), + // Parenthesize `break 'inner: loop { break 'inner 1 } + 1` + // ^---------------------------------^ + opt_label.is_none() && classify::leading_labeled_expr(expr), + fixup.rightmost_subexpression(), ); } } @@ -684,11 +701,7 @@ impl<'a> State<'a> { self.word("return"); if let Some(expr) = result { self.word(" "); - self.print_expr_cond_paren( - expr, - expr.precedence() < ExprPrecedence::Jump, - fixup.subsequent_subexpression(), - ); + self.print_expr(expr, fixup.rightmost_subexpression()); } } ast::ExprKind::Yeet(result) => { @@ -697,21 +710,13 @@ impl<'a> State<'a> { self.word("yeet"); if let Some(expr) = result { self.word(" "); - self.print_expr_cond_paren( - expr, - expr.precedence() < ExprPrecedence::Jump, - fixup.subsequent_subexpression(), - ); + self.print_expr(expr, fixup.rightmost_subexpression()); } } ast::ExprKind::Become(result) => { self.word("become"); self.word(" "); - self.print_expr_cond_paren( - result, - result.precedence() < ExprPrecedence::Jump, - fixup.subsequent_subexpression(), - ); + self.print_expr(result, fixup.rightmost_subexpression()); } ast::ExprKind::InlineAsm(a) => { // FIXME: Print `builtin # asm` once macro `asm` uses `builtin_syntax`. @@ -761,11 +766,7 @@ impl<'a> State<'a> { if let Some(expr) = e { self.space(); - self.print_expr_cond_paren( - expr, - expr.precedence() < ExprPrecedence::Jump, - fixup.subsequent_subexpression(), - ); + self.print_expr(expr, fixup.rightmost_subexpression()); } } ast::ExprKind::Yield(YieldKind::Postfix(e)) => { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/fixup.rs b/compiler/rustc_ast_pretty/src/pprust/state/fixup.rs index 3ef21f5cb29eb..eb5ac8b78a83d 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/fixup.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/fixup.rs @@ -1,5 +1,6 @@ -use rustc_ast::Expr; -use rustc_ast::util::{classify, parser}; +use rustc_ast::util::classify; +use rustc_ast::util::parser::{self, ExprPrecedence}; +use rustc_ast::{Expr, ExprKind, YieldKind}; // The default amount of fixing is minimal fixing, so all fixups are set to `false` by `Default`. // Fixups should be turned on in a targeted fashion where needed. @@ -93,6 +94,24 @@ pub(crate) struct FixupContext { /// } /// ``` parenthesize_exterior_struct_lit: bool, + + /// This is the difference between: + /// + /// ```ignore (illustrative) + /// let _ = (return) - 1; // without paren, this would return -1 + /// + /// let _ = return + 1; // no paren because '+' cannot begin expr + /// ``` + next_operator_can_begin_expr: bool, + + /// This is the difference between: + /// + /// ```ignore (illustrative) + /// let _ = 1 + return 1; // no parens if rightmost subexpression + /// + /// let _ = 1 + (return 1) + 1; // needs parens + /// ``` + next_operator_can_continue_expr: bool, } impl FixupContext { @@ -134,6 +153,8 @@ impl FixupContext { match_arm: false, leftmost_subexpression_in_match_arm: self.match_arm || self.leftmost_subexpression_in_match_arm, + next_operator_can_begin_expr: false, + next_operator_can_continue_expr: true, ..self } } @@ -148,19 +169,34 @@ impl FixupContext { leftmost_subexpression_in_stmt: false, match_arm: self.match_arm || self.leftmost_subexpression_in_match_arm, leftmost_subexpression_in_match_arm: false, + next_operator_can_begin_expr: false, + next_operator_can_continue_expr: true, ..self } } - /// Transform this fixup into the one that should apply when printing any - /// subexpression that is neither a leftmost subexpression nor surrounded in - /// delimiters. + /// Transform this fixup into the one that should apply when printing a + /// leftmost subexpression followed by punctuation that is legal as the + /// first token of an expression. + pub(crate) fn leftmost_subexpression_with_operator( + self, + next_operator_can_begin_expr: bool, + ) -> Self { + FixupContext { next_operator_can_begin_expr, ..self.leftmost_subexpression() } + } + + /// Transform this fixup into the one that should apply when printing the + /// rightmost subexpression of the current expression. + /// + /// The rightmost subexpression is any subexpression that has a different + /// first token than the current expression, but has the same last token. + /// + /// For example in `$a + $b` and `-$b`, the subexpression `$b` is a + /// rightmost subexpression. /// - /// This is for any subexpression that has a different first token than the - /// current expression, and is not surrounded by a paren/bracket/brace. For - /// example the `$b` in `$a + $b` and `-$b`, but not the one in `[$b]` or - /// `$a.f($b)`. - pub(crate) fn subsequent_subexpression(self) -> Self { + /// Not every expression has a rightmost subexpression. For example neither + /// `[$b]` nor `$a.f($b)` have one. + pub(crate) fn rightmost_subexpression(self) -> Self { FixupContext { stmt: false, leftmost_subexpression_in_stmt: false, @@ -193,6 +229,39 @@ impl FixupContext { /// "let chain". pub(crate) fn needs_par_as_let_scrutinee(self, expr: &Expr) -> bool { self.parenthesize_exterior_struct_lit && parser::contains_exterior_struct_lit(expr) - || parser::needs_par_as_let_scrutinee(expr.precedence()) + || parser::needs_par_as_let_scrutinee(self.precedence(expr)) + } + + /// Determines the effective precedence of a subexpression. Some expressions + /// have higher or lower precedence when adjacent to particular operators. + pub(crate) fn precedence(self, expr: &Expr) -> ExprPrecedence { + if self.next_operator_can_begin_expr { + // Decrease precedence of value-less jumps when followed by an + // operator that would otherwise get interpreted as beginning a + // value for the jump. + if let ExprKind::Break(..) + | ExprKind::Ret(..) + | ExprKind::Yeet(..) + | ExprKind::Yield(YieldKind::Prefix(..)) = expr.kind + { + return ExprPrecedence::Jump; + } + } + + if !self.next_operator_can_continue_expr { + // Increase precedence of expressions that extend to the end of + // current statement or group. + if let ExprKind::Break(..) + | ExprKind::Closure(..) + | ExprKind::Ret(..) + | ExprKind::Yeet(..) + | ExprKind::Yield(YieldKind::Prefix(..)) + | ExprKind::Range(None, ..) = expr.kind + { + return ExprPrecedence::Prefix; + } + } + + expr.precedence() } } diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 3638eb31c6186..6c442553976e2 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -28,7 +28,7 @@ impl<'a> State<'a> { } } - fn print_foreign_item(&mut self, item: &ast::ForeignItem) { + pub(crate) fn print_foreign_item(&mut self, item: &ast::ForeignItem) { let ast::Item { id, span, ref attrs, ref kind, ref vis, tokens: _ } = *item; self.ann.pre(self, AnnNode::SubItem(id)); self.hardbreak_if_not_bol(); @@ -548,7 +548,7 @@ impl<'a> State<'a> { } } - fn print_assoc_item(&mut self, item: &ast::AssocItem) { + pub(crate) fn print_assoc_item(&mut self, item: &ast::AssocItem) { let ast::Item { id, span, ref attrs, ref kind, ref vis, tokens: _ } = *item; self.ann.pre(self, AnnNode::SubItem(id)); self.hardbreak_if_not_bol(); diff --git a/compiler/rustc_attr_data_structures/src/stability.rs b/compiler/rustc_attr_data_structures/src/stability.rs index c0ca08a60f8b3..218e771c745a8 100644 --- a/compiler/rustc_attr_data_structures/src/stability.rs +++ b/compiler/rustc_attr_data_structures/src/stability.rs @@ -132,6 +132,7 @@ pub enum StabilityLevel { /// fn foobar() {} /// ``` implied_by: Option, + old_name: Option, }, /// `#[stable]` Stable { diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index 3cbadd4c7ec22..6589a51db2b41 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -298,6 +298,7 @@ pub(crate) fn parse_unstability( let mut issue_num = None; let mut is_soft = false; let mut implied_by = None; + let mut old_name = None; for param in args.list()?.mixed() { let Some(param) = param.meta_item() else { cx.emit_err(session_diagnostics::UnsupportedLiteral { @@ -345,11 +346,12 @@ pub(crate) fn parse_unstability( Some(sym::implied_by) => { insert_value_into_option_or_error(cx, ¶m, &mut implied_by)? } + Some(sym::old_name) => insert_value_into_option_or_error(cx, ¶m, &mut old_name)?, _ => { cx.emit_err(session_diagnostics::UnknownMetaItem { span: param.span(), item: param.path().to_string(), - expected: &["feature", "reason", "issue", "soft", "implied_by"], + expected: &["feature", "reason", "issue", "soft", "implied_by", "old_name"], }); return None; } @@ -374,6 +376,7 @@ pub(crate) fn parse_unstability( issue: issue_num, is_soft, implied_by, + old_name, }; Some((feature, level)) } diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs index 1dc799c0aeea8..012e4dbc3ec9e 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs @@ -644,9 +644,9 @@ pub mod intrinsics { #[rustc_intrinsic] pub unsafe fn size_of_val(val: *const T) -> usize; #[rustc_intrinsic] - pub fn min_align_of() -> usize; + pub fn align_of() -> usize; #[rustc_intrinsic] - pub unsafe fn min_align_of_val(val: *const T) -> usize; + pub unsafe fn align_of_val(val: *const T) -> usize; #[rustc_intrinsic] pub unsafe fn copy(src: *const T, dst: *mut T, count: usize); #[rustc_intrinsic] diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs index 93ca2e0e42188..1499f948deb3c 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs @@ -204,11 +204,8 @@ fn main() { assert_eq!(intrinsics::size_of_val(a) as u8, 16); assert_eq!(intrinsics::size_of_val(&0u32) as u8, 4); - assert_eq!(intrinsics::min_align_of::() as u8, 2); - assert_eq!( - intrinsics::min_align_of_val(&a) as u8, - intrinsics::min_align_of::<&str>() as u8 - ); + assert_eq!(intrinsics::align_of::() as u8, 2); + assert_eq!(intrinsics::align_of_val(&a) as u8, intrinsics::align_of::<&str>() as u8); assert!(!intrinsics::needs_drop::()); assert!(!intrinsics::needs_drop::<[u8]>()); diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 1d1cf884e48b2..df5748c34d110 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -586,7 +586,7 @@ fn codegen_regular_intrinsic_call<'tcx>( let (size, _align) = crate::unsize::size_and_align_of(fx, layout, meta); ret.write_cvalue(fx, CValue::by_val(size, usize_layout)); } - sym::min_align_of_val => { + sym::align_of_val => { intrinsic_args!(fx, args => (ptr); intrinsic); let layout = fx.layout_of(generic_args.type_at(0)); @@ -613,7 +613,7 @@ fn codegen_regular_intrinsic_call<'tcx>( intrinsic_args!(fx, args => (vtable); intrinsic); let vtable = vtable.load_scalar(fx); - let align = crate::vtable::min_align_of_obj(fx, vtable); + let align = crate::vtable::align_of_obj(fx, vtable); ret.write_cvalue(fx, CValue::by_val(align, usize_layout)); } diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs index 662546e499988..df60b05c4636c 100644 --- a/compiler/rustc_codegen_cranelift/src/unsize.rs +++ b/compiler/rustc_codegen_cranelift/src/unsize.rs @@ -212,7 +212,7 @@ pub(crate) fn size_and_align_of<'tcx>( // load size/align from vtable ( crate::vtable::size_of_obj(fx, info.unwrap()), - crate::vtable::min_align_of_obj(fx, info.unwrap()), + crate::vtable::align_of_obj(fx, info.unwrap()), ) } ty::Slice(_) | ty::Str => { diff --git a/compiler/rustc_codegen_cranelift/src/vtable.rs b/compiler/rustc_codegen_cranelift/src/vtable.rs index 05a8e3c334216..1fae56949bc05 100644 --- a/compiler/rustc_codegen_cranelift/src/vtable.rs +++ b/compiler/rustc_codegen_cranelift/src/vtable.rs @@ -31,7 +31,7 @@ pub(crate) fn size_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) -> Val ) } -pub(crate) fn min_align_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) -> Value { +pub(crate) fn align_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) -> Value { let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize; fx.bcx.ins().load( fx.pointer_type, diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs index d1d8e8fd5bc45..aca1f0080efd8 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core.rs @@ -655,9 +655,9 @@ pub mod intrinsics { #[rustc_intrinsic] pub unsafe fn size_of_val(val: *const T) -> usize; #[rustc_intrinsic] - pub fn min_align_of() -> usize; + pub fn align_of() -> usize; #[rustc_intrinsic] - pub unsafe fn min_align_of_val(val: *const T) -> usize; + pub unsafe fn align_of_val(val: *const T) -> usize; #[rustc_intrinsic] pub unsafe fn copy(src: *const T, dst: *mut T, count: usize); #[rustc_intrinsic] diff --git a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs index 4cbe66c5e4c69..c3bd62e5897cc 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs @@ -153,7 +153,7 @@ fn main() { let slice = &[0, 1] as &[i32]; let slice_ptr = slice as *const [i32] as *const i32; - let align = intrinsics::min_align_of::<*const i32>(); + let align = intrinsics::align_of::<*const i32>(); assert_eq!(slice_ptr as usize % align, 0); //return; @@ -194,8 +194,8 @@ fn main() { assert_eq!(intrinsics::size_of_val(a) as u8, 8); assert_eq!(intrinsics::size_of_val(&0u32) as u8, 4); - assert_eq!(intrinsics::min_align_of::() as u8, 2); - assert_eq!(intrinsics::min_align_of_val(&a) as u8, intrinsics::min_align_of::<&str>() as u8); + assert_eq!(intrinsics::align_of::() as u8, 2); + assert_eq!(intrinsics::align_of_val(&a) as u8, intrinsics::align_of::<&str>() as u8); assert!(!intrinsics::needs_drop::()); assert!(!intrinsics::needs_drop::<[u8]>()); diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 168077260a699..18b76b3375766 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1065,11 +1065,11 @@ fn link_natively( match strip { Strip::Debuginfo => { // FIXME: AIX's strip utility only offers option to strip line number information. - strip_with_external_utility(sess, stripcmd, out_filename, &["-X32_64", "-l"]) + strip_with_external_utility(sess, stripcmd, temp_filename, &["-X32_64", "-l"]) } Strip::Symbols => { // Must be noted this option might remove symbol __aix_rust_metadata and thus removes .info section which contains metadata. - strip_with_external_utility(sess, stripcmd, out_filename, &["-X32_64", "-r"]) + strip_with_external_utility(sess, stripcmd, temp_filename, &["-X32_64", "-r"]) } Strip::None => {} } diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index e217c09939ea5..27fcab8ed2d6c 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -118,7 +118,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let (llsize, _) = size_of_val::size_and_align_of_dst(bx, tp_ty, meta); llsize } - sym::min_align_of_val => { + sym::align_of_val => { let tp_ty = fn_args.type_at(0); let (_, meta) = args[0].val.pointer_parts(); let (_, llalign) = size_of_val::size_and_align_of_dst(bx, tp_ty, meta); diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index ab27182c211a7..754b2ba0d760c 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -120,7 +120,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.copy_op(&val, dest)?; } - sym::min_align_of_val | sym::size_of_val => { + sym::align_of_val | sym::size_of_val => { // Avoid `deref_pointer` -- this is not a deref, the ptr does not have to be // dereferenceable! let place = self.ref_to_mplace(&self.read_immediate(&args[0])?)?; @@ -129,7 +129,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { .ok_or_else(|| err_unsup_format!("`extern type` does not have known layout"))?; let result = match intrinsic_name { - sym::min_align_of_val => align.bytes(), + sym::align_of_val => align.bytes(), sym::size_of_val => size.bytes(), _ => bug!(), }; diff --git a/compiler/rustc_data_structures/src/thousands/mod.rs b/compiler/rustc_data_structures/src/thousands/mod.rs index e7ab7ec2932df..b251ebe58f6b9 100644 --- a/compiler/rustc_data_structures/src/thousands/mod.rs +++ b/compiler/rustc_data_structures/src/thousands/mod.rs @@ -1,16 +1,37 @@ -//! This is an extremely bare-bones alternative to the `thousands` crate on -//! crates.io, for printing large numbers in a readable fashion. +//! This is a bare-bones alternative to the `thousands` crate on crates.io, for +//! printing large numbers in a readable fashion. #[cfg(test)] mod tests; -// Converts the number to a string, with underscores as the thousands separator. -pub fn format_with_underscores(n: usize) -> String { - let mut s = n.to_string(); - let mut i = s.len(); - while i > 3 { +fn format_with_underscores(mut s: String) -> String { + // Ignore a leading '-'. + let start = if s.starts_with('-') { 1 } else { 0 }; + + // Stop after the first non-digit, e.g. '.' or 'e' for floats. + let non_digit = s[start..].find(|c: char| !c.is_digit(10)); + let end = if let Some(non_digit) = non_digit { start + non_digit } else { s.len() }; + + // Insert underscores within `start..end`. + let mut i = end; + while i > start + 3 { i -= 3; s.insert(i, '_'); } s } + +/// Print a `usize` with underscore separators. +pub fn usize_with_underscores(n: usize) -> String { + format_with_underscores(format!("{n}")) +} + +/// Print an `isize` with underscore separators. +pub fn isize_with_underscores(n: isize) -> String { + format_with_underscores(format!("{n}")) +} + +/// Print an `f64` with precision 1 (one decimal place) and underscore separators. +pub fn f64p1_with_underscores(n: f64) -> String { + format_with_underscores(format!("{n:.1}")) +} diff --git a/compiler/rustc_data_structures/src/thousands/tests.rs b/compiler/rustc_data_structures/src/thousands/tests.rs index 906605d9a935d..0f9a648802b85 100644 --- a/compiler/rustc_data_structures/src/thousands/tests.rs +++ b/compiler/rustc_data_structures/src/thousands/tests.rs @@ -2,13 +2,51 @@ use super::*; #[test] fn test_format_with_underscores() { - assert_eq!("0", format_with_underscores(0)); - assert_eq!("1", format_with_underscores(1)); - assert_eq!("99", format_with_underscores(99)); - assert_eq!("345", format_with_underscores(345)); - assert_eq!("1_000", format_with_underscores(1_000)); - assert_eq!("12_001", format_with_underscores(12_001)); - assert_eq!("999_999", format_with_underscores(999_999)); - assert_eq!("1_000_000", format_with_underscores(1_000_000)); - assert_eq!("12_345_678", format_with_underscores(12_345_678)); + assert_eq!("", format_with_underscores("".to_string())); + assert_eq!("0", format_with_underscores("0".to_string())); + assert_eq!("12_345.67e14", format_with_underscores("12345.67e14".to_string())); + assert_eq!("-1_234.5678e10", format_with_underscores("-1234.5678e10".to_string())); + assert_eq!("------", format_with_underscores("------".to_string())); + assert_eq!("abcdefgh", format_with_underscores("abcdefgh".to_string())); + assert_eq!("-1b", format_with_underscores("-1b".to_string())); + assert_eq!("-3_456xyz", format_with_underscores("-3456xyz".to_string())); +} + +#[test] +fn test_usize_with_underscores() { + assert_eq!("0", usize_with_underscores(0)); + assert_eq!("1", usize_with_underscores(1)); + assert_eq!("99", usize_with_underscores(99)); + assert_eq!("345", usize_with_underscores(345)); + assert_eq!("1_000", usize_with_underscores(1_000)); + assert_eq!("12_001", usize_with_underscores(12_001)); + assert_eq!("999_999", usize_with_underscores(999_999)); + assert_eq!("1_000_000", usize_with_underscores(1_000_000)); + assert_eq!("12_345_678", usize_with_underscores(12_345_678)); +} + +#[test] +fn test_isize_with_underscores() { + assert_eq!("0", isize_with_underscores(0)); + assert_eq!("-1", isize_with_underscores(-1)); + assert_eq!("99", isize_with_underscores(99)); + assert_eq!("345", isize_with_underscores(345)); + assert_eq!("-1_000", isize_with_underscores(-1_000)); + assert_eq!("12_001", isize_with_underscores(12_001)); + assert_eq!("-999_999", isize_with_underscores(-999_999)); + assert_eq!("1_000_000", isize_with_underscores(1_000_000)); + assert_eq!("-12_345_678", isize_with_underscores(-12_345_678)); +} + +#[test] +fn test_f64p1_with_underscores() { + assert_eq!("0.0", f64p1_with_underscores(0f64)); + assert_eq!("0.0", f64p1_with_underscores(0.00000001)); + assert_eq!("-0.0", f64p1_with_underscores(-0.00000001)); + assert_eq!("1.0", f64p1_with_underscores(0.9999999)); + assert_eq!("-1.0", f64p1_with_underscores(-0.9999999)); + assert_eq!("345.5", f64p1_with_underscores(345.4999999)); + assert_eq!("-100_000.0", f64p1_with_underscores(-100_000f64)); + assert_eq!("123_456_789.1", f64p1_with_underscores(123456789.123456789)); + assert_eq!("-123_456_789.1", f64p1_with_underscores(-123456789.123456789)); } diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index c7b975d8f3e47..311dadb53c42e 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -12,7 +12,7 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast::visit::{AssocCtxt, Visitor}; use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind}; use rustc_attr_data_structures::{AttributeKind, Deprecation, Stability, find_attr}; -use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_data_structures::sync; use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, PResult}; use rustc_feature::Features; @@ -727,6 +727,7 @@ pub enum SyntaxExtensionKind { /// A trivial attribute "macro" that does nothing, /// only keeps the attribute and marks it as inert, /// thus making it ineligible for further expansion. + /// E.g. `#[default]`, `#[rustfmt::skip]`. NonMacroAttr, /// A token-based derive macro. @@ -1189,6 +1190,8 @@ pub struct ExtCtxt<'a> { /// in the AST, but insert it here so that we know /// not to expand it again. pub(super) expanded_inert_attrs: MarkedAttrs, + /// `-Zmacro-stats` data. + pub macro_stats: FxHashMap<(Symbol, MacroKind), crate::stats::MacroStat>, // njn: quals } impl<'a> ExtCtxt<'a> { @@ -1218,6 +1221,7 @@ impl<'a> ExtCtxt<'a> { expansions: FxIndexMap::default(), expanded_inert_attrs: MarkedAttrs::new(), buffered_early_lint: vec![], + macro_stats: Default::default(), } } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 569165a64e520..3cfeb01ea4771 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -42,13 +42,22 @@ use crate::module::{ DirOwnership, ParsedExternalMod, mod_dir_path, mod_file_path_from_attr, parse_external_mod, }; use crate::placeholders::{PlaceholderExpander, placeholder}; +use crate::stats::*; macro_rules! ast_fragments { ( $($Kind:ident($AstTy:ty) { $kind_name:expr; - $(one fn $mut_visit_ast:ident; fn $visit_ast:ident;)? - $(many fn $flat_map_ast_elt:ident; fn $visit_ast_elt:ident($($args:tt)*);)? + $(one + fn $mut_visit_ast:ident; + fn $visit_ast:ident; + fn $ast_to_string:path; + )? + $(many + fn $flat_map_ast_elt:ident; + fn $visit_ast_elt:ident($($args:tt)*); + fn $ast_to_string_elt:path; + )? fn $make_ast:ident; })* ) => { @@ -61,7 +70,7 @@ macro_rules! ast_fragments { } /// "Discriminant" of an AST fragment. - #[derive(Copy, Clone, PartialEq, Eq)] + #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum AstFragmentKind { OptExpr, MethodReceiverExpr, @@ -151,6 +160,21 @@ macro_rules! ast_fragments { } V::Result::output() } + + pub(crate) fn to_string(&self) -> String { + match self { + AstFragment::OptExpr(Some(expr)) => pprust::expr_to_string(expr), + AstFragment::OptExpr(None) => unreachable!(), + AstFragment::MethodReceiverExpr(expr) => pprust::expr_to_string(expr), + $($(AstFragment::$Kind(ast) => $ast_to_string(ast),)?)* + $($( + AstFragment::$Kind(ast) => { + // The closure unwraps a `P` if present, or does nothing otherwise. + elems_to_string(&*ast, |ast| $ast_to_string_elt(&*ast)) + } + )?)* + } + } } impl<'a> MacResult for crate::mbe::macro_rules::ParserAnyMacro<'a> { @@ -163,76 +187,98 @@ macro_rules! ast_fragments { } ast_fragments! { - Expr(P) { "expression"; one fn visit_expr; fn visit_expr; fn make_expr; } - Pat(P) { "pattern"; one fn visit_pat; fn visit_pat; fn make_pat; } - Ty(P) { "type"; one fn visit_ty; fn visit_ty; fn make_ty; } + Expr(P) { + "expression"; + one fn visit_expr; fn visit_expr; fn pprust::expr_to_string; + fn make_expr; + } + Pat(P) { + "pattern"; + one fn visit_pat; fn visit_pat; fn pprust::pat_to_string; + fn make_pat; + } + Ty(P) { + "type"; + one fn visit_ty; fn visit_ty; fn pprust::ty_to_string; + fn make_ty; + } Stmts(SmallVec<[ast::Stmt; 1]>) { - "statement"; many fn flat_map_stmt; fn visit_stmt(); fn make_stmts; + "statement"; + many fn flat_map_stmt; fn visit_stmt(); fn pprust::stmt_to_string; + fn make_stmts; } Items(SmallVec<[P; 1]>) { - "item"; many fn flat_map_item; fn visit_item(); fn make_items; + "item"; + many fn flat_map_item; fn visit_item(); fn pprust::item_to_string; + fn make_items; } TraitItems(SmallVec<[P; 1]>) { "trait item"; - many fn flat_map_assoc_item; - fn visit_assoc_item(AssocCtxt::Trait); + many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Trait); + fn pprust::assoc_item_to_string; fn make_trait_items; } ImplItems(SmallVec<[P; 1]>) { "impl item"; - many fn flat_map_assoc_item; - fn visit_assoc_item(AssocCtxt::Impl { of_trait: false }); + many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Impl { of_trait: false }); + fn pprust::assoc_item_to_string; fn make_impl_items; } TraitImplItems(SmallVec<[P; 1]>) { "impl item"; - many fn flat_map_assoc_item; - fn visit_assoc_item(AssocCtxt::Impl { of_trait: true }); + many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Impl { of_trait: true }); + fn pprust::assoc_item_to_string; fn make_trait_impl_items; } ForeignItems(SmallVec<[P; 1]>) { "foreign item"; - many fn flat_map_foreign_item; - fn visit_foreign_item(); + many fn flat_map_foreign_item; fn visit_foreign_item(); fn pprust::foreign_item_to_string; fn make_foreign_items; } Arms(SmallVec<[ast::Arm; 1]>) { - "match arm"; many fn flat_map_arm; fn visit_arm(); fn make_arms; + "match arm"; + many fn flat_map_arm; fn visit_arm(); fn unreachable_to_string; + fn make_arms; } ExprFields(SmallVec<[ast::ExprField; 1]>) { - "field expression"; many fn flat_map_expr_field; fn visit_expr_field(); fn make_expr_fields; + "field expression"; + many fn flat_map_expr_field; fn visit_expr_field(); fn unreachable_to_string; + fn make_expr_fields; } PatFields(SmallVec<[ast::PatField; 1]>) { "field pattern"; - many fn flat_map_pat_field; - fn visit_pat_field(); + many fn flat_map_pat_field; fn visit_pat_field(); fn unreachable_to_string; fn make_pat_fields; } GenericParams(SmallVec<[ast::GenericParam; 1]>) { "generic parameter"; - many fn flat_map_generic_param; - fn visit_generic_param(); + many fn flat_map_generic_param; fn visit_generic_param(); fn unreachable_to_string; fn make_generic_params; } Params(SmallVec<[ast::Param; 1]>) { - "function parameter"; many fn flat_map_param; fn visit_param(); fn make_params; + "function parameter"; + many fn flat_map_param; fn visit_param(); fn unreachable_to_string; + fn make_params; } FieldDefs(SmallVec<[ast::FieldDef; 1]>) { "field"; - many fn flat_map_field_def; - fn visit_field_def(); + many fn flat_map_field_def; fn visit_field_def(); fn unreachable_to_string; fn make_field_defs; } Variants(SmallVec<[ast::Variant; 1]>) { - "variant"; many fn flat_map_variant; fn visit_variant(); fn make_variants; + "variant"; many fn flat_map_variant; fn visit_variant(); fn unreachable_to_string; + fn make_variants; } WherePredicates(SmallVec<[ast::WherePredicate; 1]>) { "where predicate"; - many fn flat_map_where_predicate; - fn visit_where_predicate(); + many fn flat_map_where_predicate; fn visit_where_predicate(); fn unreachable_to_string; fn make_where_predicates; - } - Crate(ast::Crate) { "crate"; one fn visit_crate; fn visit_crate; fn make_crate; } + } + Crate(ast::Crate) { + "crate"; + one fn visit_crate; fn visit_crate; fn unreachable_to_string; + fn make_crate; + } } pub enum SupportsMacroExpansion { @@ -270,7 +316,7 @@ impl AstFragmentKind { } } - fn expect_from_annotatables>( + pub(crate) fn expect_from_annotatables>( self, items: I, ) -> AstFragment { @@ -686,13 +732,26 @@ impl<'a, 'b> MacroExpander<'a, 'b> { return ExpandResult::Ready(invoc.fragment_kind.dummy(invoc.span(), guar)); } + let macro_stats = self.cx.sess.opts.unstable_opts.macro_stats; + let (fragment_kind, span) = (invoc.fragment_kind, invoc.span()); ExpandResult::Ready(match invoc.kind { InvocationKind::Bang { mac, span } => match ext { SyntaxExtensionKind::Bang(expander) => { match expander.expand(self.cx, span, mac.args.tokens.clone()) { Ok(tok_result) => { - self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span) + let fragment = + self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span); + if macro_stats { + update_bang_macro_stats( + self.cx, + fragment_kind, + span, + mac, + &fragment, + ); + } + fragment } Err(guar) => return ExpandResult::Ready(fragment_kind.dummy(span, guar)), } @@ -708,13 +767,15 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }); } }; - let result = if let Some(result) = fragment_kind.make_from(tok_result) { - result + if let Some(fragment) = fragment_kind.make_from(tok_result) { + if macro_stats { + update_bang_macro_stats(self.cx, fragment_kind, span, mac, &fragment); + } + fragment } else { let guar = self.error_wrong_fragment_kind(fragment_kind, &mac, span); fragment_kind.dummy(span, guar) - }; - result + } } _ => unreachable!(), }, @@ -746,24 +807,39 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } _ => item.to_tokens(), }; - let attr_item = attr.unwrap_normal_item(); + let attr_item = attr.get_normal_item(); if let AttrArgs::Eq { .. } = attr_item.args { self.cx.dcx().emit_err(UnsupportedKeyValue { span }); } let inner_tokens = attr_item.args.inner_tokens(); match expander.expand(self.cx, span, inner_tokens, tokens) { - Ok(tok_result) => self.parse_ast_fragment( - tok_result, - fragment_kind, - &attr_item.path, - span, - ), + Ok(tok_result) => { + let fragment = self.parse_ast_fragment( + tok_result, + fragment_kind, + &attr_item.path, + span, + ); + if macro_stats { + update_attr_macro_stats( + self.cx, + fragment_kind, + span, + &attr_item.path, + &attr, + item, + &fragment, + ); + } + fragment + } Err(guar) => return ExpandResult::Ready(fragment_kind.dummy(span, guar)), } } SyntaxExtensionKind::LegacyAttr(expander) => { match validate_attr::parse_meta(&self.cx.sess.psess, &attr) { Ok(meta) => { + let item_clone = macro_stats.then(|| item.clone()); let items = match expander.expand(self.cx, span, &meta, item, false) { ExpandResult::Ready(items) => items, ExpandResult::Retry(item) => { @@ -782,7 +858,19 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let guar = self.cx.dcx().emit_err(RemoveExprNotSupported { span }); fragment_kind.dummy(span, guar) } else { - fragment_kind.expect_from_annotatables(items) + let fragment = fragment_kind.expect_from_annotatables(items); + if macro_stats { + update_attr_macro_stats( + self.cx, + fragment_kind, + span, + &meta.path, + &attr, + item_clone.unwrap(), + &fragment, + ); + } + fragment } } Err(err) => { @@ -792,6 +880,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } SyntaxExtensionKind::NonMacroAttr => { + // `-Zmacro-stats` ignores these because they don't do any real expansion. self.cx.expanded_inert_attrs.mark(&attr); item.visit_attrs(|attrs| attrs.insert(pos, attr)); fragment_kind.expect_from_annotatables(iter::once(item)) @@ -822,7 +911,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }); } }; - fragment_kind.expect_from_annotatables(items) + let fragment = fragment_kind.expect_from_annotatables(items); + if macro_stats { + update_derive_macro_stats( + self.cx, + fragment_kind, + span, + &meta.path, + &fragment, + ); + } + fragment } _ => unreachable!(), }, @@ -852,6 +951,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let single_delegations = build_single_delegations::( self.cx, deleg, &item, &suffixes, item.span, true, ); + // `-Zmacro-stats` ignores these because they don't seem important. fragment_kind.expect_from_annotatables( single_delegations .map(|item| Annotatable::AssocItem(P(item), AssocCtxt::Impl { of_trait })), diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 515d82296caf1..64be7649775f3 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -20,6 +20,7 @@ mod errors; mod mbe; mod placeholders; mod proc_macro_server; +mod stats; pub use mbe::macro_rules::compile_declarative_macro; pub mod base; diff --git a/compiler/rustc_expand/src/stats.rs b/compiler/rustc_expand/src/stats.rs new file mode 100644 index 0000000000000..6b2ad30dffd06 --- /dev/null +++ b/compiler/rustc_expand/src/stats.rs @@ -0,0 +1,171 @@ +use std::iter; + +use rustc_ast::ptr::P; +use rustc_ast::{self as ast, DUMMY_NODE_ID, Expr, ExprKind}; +use rustc_ast_pretty::pprust; +use rustc_span::hygiene::{ExpnKind, MacroKind}; +use rustc_span::{Span, Symbol, kw, sym}; +use smallvec::SmallVec; + +use crate::base::{Annotatable, ExtCtxt}; +use crate::expand::{AstFragment, AstFragmentKind}; + +#[derive(Default)] +pub struct MacroStat { + /// Number of uses of the macro. + pub uses: usize, + + /// Net increase in number of lines of code (when pretty-printed), i.e. + /// `lines(output) - lines(invocation)`. Can be negative because a macro + /// output may be smaller than the invocation. + pub lines: isize, + + /// Net increase in number of lines of code (when pretty-printed), i.e. + /// `bytes(output) - bytes(invocation)`. Can be negative because a macro + /// output may be smaller than the invocation. + pub bytes: isize, +} + +pub(crate) fn elems_to_string(elems: &SmallVec<[T; 1]>, f: impl Fn(&T) -> String) -> String { + let mut s = String::new(); + for (i, elem) in elems.iter().enumerate() { + if i > 0 { + s.push('\n'); + } + s.push_str(&f(elem)); + } + s +} + +pub(crate) fn unreachable_to_string(_: &T) -> String { + unreachable!() +} + +pub(crate) fn update_bang_macro_stats( + ecx: &mut ExtCtxt<'_>, + fragment_kind: AstFragmentKind, + span: Span, + mac: P, + fragment: &AstFragment, +) { + // Does this path match any of the include macros, e.g. `include!`? + // Ignore them. They would have large numbers but are entirely + // unsurprising and uninteresting. + let is_include_path = mac.path == sym::include + || mac.path == sym::include_bytes + || mac.path == sym::include_str + || mac.path == [sym::std, sym::include].as_slice() // std::include + || mac.path == [sym::std, sym::include_bytes].as_slice() // std::include_bytes + || mac.path == [sym::std, sym::include_str].as_slice(); // std::include_str + if is_include_path { + return; + } + + // The call itself (e.g. `println!("hi")`) is the input. Need to wrap + // `mac` in something printable; `ast::Expr` is as good as anything + // else. + let expr = Expr { + id: DUMMY_NODE_ID, + kind: ExprKind::MacCall(mac), + span: Default::default(), + attrs: Default::default(), + tokens: None, + }; + let input = pprust::expr_to_string(&expr); + + // Get `mac` back out of `expr`. + let ast::Expr { kind: ExprKind::MacCall(mac), .. } = expr else { unreachable!() }; + + update_macro_stats(ecx, MacroKind::Bang, fragment_kind, span, &mac.path, &input, fragment); +} + +pub(crate) fn update_attr_macro_stats( + ecx: &mut ExtCtxt<'_>, + fragment_kind: AstFragmentKind, + span: Span, + path: &ast::Path, + attr: &ast::Attribute, + item: Annotatable, + fragment: &AstFragment, +) { + // Does this path match `#[derive(...)]` in any of its forms? If so, + // ignore it because the individual derives will go through the + // `Invocation::Derive` handling separately. + let is_derive_path = *path == sym::derive + // ::core::prelude::v1::derive + || *path == [kw::PathRoot, sym::core, sym::prelude, sym::v1, sym::derive].as_slice(); + if is_derive_path { + return; + } + + // The attribute plus the item itself constitute the input, which we + // measure. + let input = format!( + "{}\n{}", + pprust::attribute_to_string(attr), + fragment_kind.expect_from_annotatables(iter::once(item)).to_string(), + ); + update_macro_stats(ecx, MacroKind::Attr, fragment_kind, span, path, &input, fragment); +} + +pub(crate) fn update_derive_macro_stats( + ecx: &mut ExtCtxt<'_>, + fragment_kind: AstFragmentKind, + span: Span, + path: &ast::Path, + fragment: &AstFragment, +) { + // Use something like `#[derive(Clone)]` for the measured input, even + // though it may have actually appeared in a multi-derive attribute + // like `#[derive(Clone, Copy, Debug)]`. + let input = format!("#[derive({})]", pprust::path_to_string(path)); + update_macro_stats(ecx, MacroKind::Derive, fragment_kind, span, path, &input, fragment); +} + +pub(crate) fn update_macro_stats( + ecx: &mut ExtCtxt<'_>, + macro_kind: MacroKind, + fragment_kind: AstFragmentKind, + span: Span, + path: &ast::Path, + input: &str, + fragment: &AstFragment, +) { + fn lines_and_bytes(s: &str) -> (usize, usize) { + (s.trim_end().split('\n').count(), s.len()) + } + + // Measure the size of the output by pretty-printing it and counting + // the lines and bytes. + let name = Symbol::intern(&pprust::path_to_string(path)); + let output = fragment.to_string(); + let (in_l, in_b) = lines_and_bytes(input); + let (out_l, out_b) = lines_and_bytes(&output); + + // This code is useful for debugging `-Zmacro-stats`. For every + // invocation it prints the full input and output. + if false { + let name = ExpnKind::Macro(macro_kind, name).descr(); + let crate_name = &ecx.ecfg.crate_name; + let span = ecx + .sess + .source_map() + .span_to_string(span, rustc_span::FileNameDisplayPreference::Local); + eprint!( + "\ + -------------------------------\n\ + {name}: [{crate_name}] ({fragment_kind:?}) {span}\n\ + -------------------------------\n\ + {input}\n\ + -- ({in_l} lines, {in_b} bytes) --> ({out_l} lines, {out_b} bytes) --\n\ + {output}\n\ + " + ); + } + + // The recorded size is the difference between the input and the output. + let entry = ecx.macro_stats.entry((name, macro_kind)).or_insert(MacroStat::default()); + entry.uses += 1; + entry.lines += out_l as isize - in_l as isize; + entry.bytes += out_b as isize - in_b as isize; +} diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 481cdaa4c6ca3..060fc51b7bda7 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -71,7 +71,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::box_new | sym::breakpoint | sym::size_of - | sym::min_align_of + | sym::align_of | sym::needs_drop | sym::caller_location | sym::add_with_overflow @@ -200,10 +200,8 @@ pub(crate) fn check_intrinsic_type( sym::abort => (0, 0, vec![], tcx.types.never), sym::unreachable => (0, 0, vec![], tcx.types.never), sym::breakpoint => (0, 0, vec![], tcx.types.unit), - sym::size_of | sym::pref_align_of | sym::min_align_of | sym::variant_count => { - (1, 0, vec![], tcx.types.usize) - } - sym::size_of_val | sym::min_align_of_val => { + sym::size_of | sym::align_of | sym::variant_count => (1, 0, vec![], tcx.types.usize), + sym::size_of_val | sym::align_of_val => { (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], tcx.types.usize) } sym::rustc_peek => (1, 0, vec![param(0)], param(0)), diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 99520a3fea304..0238d6a39475f 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -8,9 +8,9 @@ use std::{env, fs, iter}; use rustc_ast as ast; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::jobserver::Proxy; -use rustc_data_structures::parallel; use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, WorkerLocal}; +use rustc_data_structures::{parallel, thousands}; use rustc_expand::base::{ExtCtxt, LintStoreExpand}; use rustc_feature::Features; use rustc_fs_util::try_canonicalize; @@ -35,7 +35,8 @@ use rustc_session::parse::feature_err; use rustc_session::search_paths::PathKind; use rustc_session::{Limit, Session}; use rustc_span::{ - DUMMY_SP, ErrorGuaranteed, FileName, SourceFileHash, SourceFileHashAlgorithm, Span, Symbol, sym, + DUMMY_SP, ErrorGuaranteed, ExpnKind, FileName, SourceFileHash, SourceFileHashAlgorithm, Span, + Symbol, sym, }; use rustc_target::spec::PanicStrategy; use rustc_trait_selection::traits; @@ -205,7 +206,7 @@ fn configure_and_expand( // Expand macros now! let krate = sess.time("expand_crate", || ecx.monotonic_expander().expand_crate(krate)); - // The rest is error reporting + // The rest is error reporting and stats sess.psess.buffered_lints.with_lock(|buffered_lints: &mut Vec| { buffered_lints.append(&mut ecx.buffered_early_lint); @@ -228,6 +229,10 @@ fn configure_and_expand( } } + if ecx.sess.opts.unstable_opts.macro_stats { + print_macro_stats(&ecx); + } + krate }); @@ -288,6 +293,76 @@ fn configure_and_expand( krate } +fn print_macro_stats(ecx: &ExtCtxt<'_>) { + use std::fmt::Write; + + // No instability because we immediately sort the produced vector. + #[allow(rustc::potential_query_instability)] + let mut macro_stats: Vec<_> = ecx + .macro_stats + .iter() + .map(|((name, kind), stat)| { + // This gives the desired sort order: sort by bytes, then lines, etc. + (stat.bytes, stat.lines, stat.uses, name, *kind) + }) + .collect(); + macro_stats.sort_unstable(); + macro_stats.reverse(); // bigger items first + + let prefix = "macro-stats"; + let name_w = 32; + let uses_w = 7; + let lines_w = 11; + let avg_lines_w = 11; + let bytes_w = 11; + let avg_bytes_w = 11; + let banner_w = name_w + uses_w + lines_w + avg_lines_w + bytes_w + avg_bytes_w; + + // We write all the text into a string and print it with a single + // `eprint!`. This is an attempt to minimize interleaved text if multiple + // rustc processes are printing macro-stats at the same time (e.g. with + // `RUSTFLAGS='-Zmacro-stats' cargo build`). It still doesn't guarantee + // non-interleaving, though. + let mut s = String::new(); + _ = writeln!(s, "{prefix} {}", "=".repeat(banner_w)); + _ = writeln!(s, "{prefix} MACRO EXPANSION STATS: {}", ecx.ecfg.crate_name); + _ = writeln!( + s, + "{prefix} {:uses_w$}{:>lines_w$}{:>avg_lines_w$}{:>bytes_w$}{:>avg_bytes_w$}", + "Macro Name", "Uses", "Lines", "Avg Lines", "Bytes", "Avg Bytes", + ); + _ = writeln!(s, "{prefix} {}", "-".repeat(banner_w)); + // It's helpful to print something when there are no entries, otherwise it + // might look like something went wrong. + if macro_stats.is_empty() { + _ = writeln!(s, "{prefix} (none)"); + } + for (bytes, lines, uses, name, kind) in macro_stats { + let mut name = ExpnKind::Macro(kind, *name).descr(); + let avg_lines = lines as f64 / uses as f64; + let avg_bytes = bytes as f64 / uses as f64; + if name.len() >= name_w { + // If the name is long, print it on a line by itself, then + // set the name to empty and print things normally, to show the + // stats on the next line. + _ = writeln!(s, "{prefix} {:uses_w$}{:>lines_w$}{:>avg_lines_w$}{:>bytes_w$}{:>avg_bytes_w$}", + name, + thousands::usize_with_underscores(uses), + thousands::isize_with_underscores(lines), + thousands::f64p1_with_underscores(avg_lines), + thousands::isize_with_underscores(bytes), + thousands::f64p1_with_underscores(avg_bytes), + ); + } + _ = writeln!(s, "{prefix} {}", "=".repeat(banner_w)); + eprint!("{s}"); +} + fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { let sess = tcx.sess; let (resolver, krate) = &*tcx.resolver_for_lowering().borrow(); diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 558f13a832c43..5419d688caaee 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -709,6 +709,7 @@ fn test_unstable_options_tracking_hash() { untracked!(llvm_time_trace, true); untracked!(ls, vec!["all".to_owned()]); untracked!(macro_backtrace, true); + untracked!(macro_stats, true); untracked!(meta_stats, true); untracked!(mir_include_spans, MirIncludeSpans::On); untracked!(nll_facts, true); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 3ab989d2d3ba7..00bd32eb0eb3b 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -10,7 +10,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::memmap::{Mmap, MmapMut}; use rustc_data_structures::sync::{join, par_for_each_in}; use rustc_data_structures::temp_dir::MaybeTempDir; -use rustc_data_structures::thousands::format_with_underscores; +use rustc_data_structures::thousands::usize_with_underscores; use rustc_feature::Features; use rustc_hir as hir; use rustc_hir::def_id::{CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE, LocalDefId, LocalDefIdSet}; @@ -789,7 +789,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { "{} {:<23}{:>10} ({:4.1}%)", prefix, label, - format_with_underscores(size), + usize_with_underscores(size), perc(size) ); } @@ -798,7 +798,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { "{} {:<23}{:>10} (of which {:.1}% are zero bytes)", prefix, "Total", - format_with_underscores(total_bytes), + usize_with_underscores(total_bytes), perc(zero_bytes) ); eprintln!("{prefix}"); diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs index 4587dcaddc487..6ca1e6207042a 100644 --- a/compiler/rustc_middle/src/middle/mod.rs +++ b/compiler/rustc_middle/src/middle/mod.rs @@ -12,7 +12,7 @@ pub mod lib_features { #[derive(HashStable, TyEncodable, TyDecodable)] pub enum FeatureStability { AcceptedSince(Symbol), - Unstable, + Unstable { old_name: Option }, } #[derive(HashStable, Debug, Default)] diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 454ab8c107f0a..ab6a65ed52634 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -411,7 +411,7 @@ impl<'tcx> TyCtxt<'tcx> { match stability { Some(Stability { - level: attrs::StabilityLevel::Unstable { reason, issue, is_soft, implied_by }, + level: attrs::StabilityLevel::Unstable { reason, issue, is_soft, implied_by, .. }, feature, .. }) => { diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index 52f4c39c09bb1..fa29ab985b7be 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -150,12 +150,12 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { }); terminator.kind = TerminatorKind::Goto { target }; } - sym::size_of | sym::min_align_of => { + sym::size_of | sym::align_of => { let target = target.unwrap(); let tp_ty = generic_args.type_at(0); let null_op = match intrinsic.name { sym::size_of => NullOp::SizeOf, - sym::min_align_of => NullOp::AlignOf, + sym::align_of => NullOp::AlignOf, _ => bug!("unexpected intrinsic"), }; block.statements.push(Statement { diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 81c7b42b105b5..7c237d708c0ad 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -719,6 +719,9 @@ passes_unknown_external_lang_item = passes_unknown_feature = unknown feature `{$feature}` +passes_unknown_feature_alias = + feature `{$alias}` has been renamed to `{$feature}` + passes_unknown_lang_item = definition of an unknown lang item: `{$name}` .label = definition of unknown lang item `{$name}` diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 74c89f0c698b5..f0d4b610f6384 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1434,6 +1434,15 @@ pub(crate) struct UnknownFeature { pub feature: Symbol, } +#[derive(Diagnostic)] +#[diag(passes_unknown_feature_alias, code = E0635)] +pub(crate) struct RenamedFeature { + #[primary_span] + pub span: Span, + pub feature: Symbol, + pub alias: Symbol, +} + #[derive(Diagnostic)] #[diag(passes_implied_feature_not_exist)] pub(crate) struct ImpliedFeatureNotExist { diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index 6852153a2e769..46e6c0bf7da5b 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -5,7 +5,7 @@ use rustc_ast::visit::BoundKind; use rustc_ast::{self as ast, NodeId, visit as ast_visit}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::thousands::format_with_underscores; +use rustc_data_structures::thousands::usize_with_underscores; use rustc_hir::{self as hir, AmbigArg, HirId, intravisit as hir_visit}; use rustc_middle::ty::TyCtxt; use rustc_span::Span; @@ -140,10 +140,10 @@ impl<'k> StatCollector<'k> { "{} {:<18}{:>10} ({:4.1}%){:>14}{:>14}", prefix, label, - format_with_underscores(size), + usize_with_underscores(size), percent(size, total_size), - format_with_underscores(node.stats.count), - format_with_underscores(node.stats.size) + usize_with_underscores(node.stats.count), + usize_with_underscores(node.stats.size) ); if !node.subnodes.is_empty() { // We will soon sort, so the initial order does not matter. @@ -159,9 +159,9 @@ impl<'k> StatCollector<'k> { "{} - {:<18}{:>10} ({:4.1}%){:>14}", prefix, label, - format_with_underscores(size), + usize_with_underscores(size), percent(size, total_size), - format_with_underscores(subnode.count), + usize_with_underscores(subnode.count), ); } } @@ -171,8 +171,8 @@ impl<'k> StatCollector<'k> { "{} {:<18}{:>10} {:>14}", prefix, "Total", - format_with_underscores(total_size), - format_with_underscores(total_count), + usize_with_underscores(total_size), + usize_with_underscores(total_count), ); eprintln!("{prefix}"); } diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs index b3e6ee9512c85..127e0df133215 100644 --- a/compiler/rustc_passes/src/lib_features.rs +++ b/compiler/rustc_passes/src/lib_features.rs @@ -40,7 +40,7 @@ impl<'tcx> LibFeatureCollector<'tcx> { }; let feature_stability = match level { - StabilityLevel::Unstable { .. } => FeatureStability::Unstable, + StabilityLevel::Unstable { old_name, .. } => FeatureStability::Unstable { old_name }, StabilityLevel::Stable { since, .. } => FeatureStability::AcceptedSince(match since { StableSince::Version(v) => Symbol::intern(&v.to_string()), StableSince::Current => sym::env_CFG_RELEASE, @@ -71,7 +71,7 @@ impl<'tcx> LibFeatureCollector<'tcx> { }); } } - (FeatureStability::AcceptedSince(_), Some((FeatureStability::Unstable, _))) => { + (FeatureStability::AcceptedSince(_), Some((FeatureStability::Unstable { .. }, _))) => { self.tcx.dcx().emit_err(FeaturePreviouslyDeclared { span, feature, @@ -79,7 +79,7 @@ impl<'tcx> LibFeatureCollector<'tcx> { prev_declared: "unstable", }); } - (FeatureStability::Unstable, Some((FeatureStability::AcceptedSince(_), _))) => { + (FeatureStability::Unstable { .. }, Some((FeatureStability::AcceptedSince(_), _))) => { self.tcx.dcx().emit_err(FeaturePreviouslyDeclared { span, feature, @@ -88,7 +88,7 @@ impl<'tcx> LibFeatureCollector<'tcx> { }); } // duplicate `unstable` feature is ok. - (FeatureStability::Unstable, Some((FeatureStability::Unstable, _))) => {} + (FeatureStability::Unstable { .. }, Some((FeatureStability::Unstable { .. }, _))) => {} } } } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 45e26c8999a9f..56d9f5bf78577 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -718,6 +718,7 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index { issue: NonZero::new(27812), is_soft: false, implied_by: None, + old_name: None, }, feature: sym::rustc_private, }; @@ -1161,8 +1162,8 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { defined_features: &LibFeatures, all_implications: &UnordMap, ) { - for (feature, since) in defined_features.to_sorted_vec() { - if let FeatureStability::AcceptedSince(since) = since + for (feature, stability) in defined_features.to_sorted_vec() { + if let FeatureStability::AcceptedSince(since) = stability && let Some(span) = remaining_lib_features.get(&feature) { // Warn if the user has enabled an already-stable lib feature. @@ -1181,6 +1182,12 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { // implications from this crate. remaining_implications.remove(&feature); + if let FeatureStability::Unstable { old_name: Some(alias) } = stability { + if let Some(span) = remaining_lib_features.swap_remove(&alias) { + tcx.dcx().emit_err(errors::RenamedFeature { span, feature, alias }); + } + } + if remaining_lib_features.is_empty() && remaining_implications.is_empty() { break; } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index ee905065b966b..79a60b5a455b4 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -974,7 +974,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ) { let span = path.span; if let Some(stability) = &ext.stability { - if let StabilityLevel::Unstable { reason, issue, is_soft, implied_by } = stability.level + if let StabilityLevel::Unstable { reason, issue, is_soft, implied_by, .. } = + stability.level { let feature = stability.feature; diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 12fa05118caf5..a26d3bc40444b 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2305,6 +2305,8 @@ options! { (space separated)"), macro_backtrace: bool = (false, parse_bool, [UNTRACKED], "show macro backtraces (default: no)"), + macro_stats: bool = (false, parse_bool, [UNTRACKED], + "print some statistics about macro expansions (default: no)"), maximal_hir_to_mir_coverage: bool = (false, parse_bool, [TRACKED], "save as much information as possible about the correspondence between MIR and HIR \ as source scopes (default: no)"), diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index b621920d62ba6..315dedec10758 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -1135,7 +1135,7 @@ impl ExpnKind { } /// The kind of macro invocation or definition. -#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] pub enum MacroKind { /// A bang macro `foo!()`. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d66f98871b97d..3429d28e1d5c2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -429,6 +429,8 @@ symbols! { aggregate_raw_ptr, alias, align, + align_of, + align_of_val, alignment, all, alloc, @@ -1353,8 +1355,6 @@ symbols! { message, meta, metadata_type, - min_align_of, - min_align_of_val, min_const_fn, min_const_generics, min_const_unsafe_fn, @@ -1512,6 +1512,7 @@ symbols! { offset_of_nested, offset_of_slice, ok_or_else, + old_name, omit_gdb_pretty_printer_section, on, on_unimplemented, @@ -2288,6 +2289,7 @@ symbols! { usize_legacy_fn_max_value, usize_legacy_fn_min_value, usize_legacy_mod, + v1, v8plus, va_arg, va_copy, @@ -2675,7 +2677,7 @@ impl Interner { assert_eq!( strings.len(), init.len() + extra.len(), - "`init` or `extra` contain duplicate symbols", + "there are duplicate symbols in the rustc symbol list and the extra symbols added by the driver", ); Interner(Lock::new(InternerInner { arena: Default::default(), strings })) } diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index 8b448a18402c3..48849bf7536c0 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -714,6 +714,8 @@ impl ops::Deref for CString { } } +/// Delegates to the [`CStr`] implementation of [`fmt::Debug`], +/// showing invalid UTF-8 as hex escapes. #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for CString { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 595cc1fe025ec..f7a21072f5393 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -162,10 +162,12 @@ impl fmt::Display for FromBytesUntilNulError { } } +/// Shows the underlying bytes as a normal string, with invalid UTF-8 +/// presented as hex escape sequences. #[stable(feature = "cstr_debug", since = "1.3.0")] impl fmt::Debug for CStr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "\"{}\"", self.to_bytes().escape_ascii()) + fmt::Debug::fmt(crate::bstr::ByteStr::from_bytes(self.to_bytes()), f) } } diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 4434ceb49bca8..7ba48cc72683c 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -926,8 +926,7 @@ pub const unsafe fn slice_get_unchecked< pub fn ptr_mask(ptr: *const T, mask: usize) -> *const T; /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with -/// a size of `count` * `size_of::()` and an alignment of -/// `min_align_of::()` +/// a size of `count` * `size_of::()` and an alignment of `align_of::()`. /// /// This intrinsic does not have a stable counterpart. /// # Safety @@ -941,8 +940,7 @@ pub fn ptr_mask(ptr: *const T, mask: usize) -> *const T; #[rustc_nounwind] pub unsafe fn volatile_copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: usize); /// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with -/// a size of `count * size_of::()` and an alignment of -/// `min_align_of::()` +/// a size of `count * size_of::()` and an alignment of `align_of::()`. /// /// The volatile parameter is set to `true`, so it will not be optimized out /// unless size is equal to zero. @@ -952,8 +950,7 @@ pub unsafe fn volatile_copy_nonoverlapping_memory(dst: *mut T, src: *const T, #[rustc_nounwind] pub unsafe fn volatile_copy_memory(dst: *mut T, src: *const T, count: usize); /// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a -/// size of `count * size_of::()` and an alignment of -/// `min_align_of::()`. +/// size of `count * size_of::()` and an alignment of `align_of::()`. /// /// This intrinsic does not have a stable counterpart. /// # Safety @@ -2649,7 +2646,7 @@ pub const fn size_of() -> usize; #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] -pub const fn min_align_of() -> usize; +pub const fn align_of() -> usize; /// Returns the number of variants of the type `T` cast to a `usize`; /// if `T` has no variants, returns `0`. Uninhabited variants will be counted. @@ -2689,7 +2686,7 @@ pub const unsafe fn size_of_val(ptr: *const T) -> usize; #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] #[rustc_intrinsic_const_stable_indirect] -pub const unsafe fn min_align_of_val(ptr: *const T) -> usize; +pub const unsafe fn align_of_val(ptr: *const T) -> usize; /// Gets a static string slice containing the name of a type. /// diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 0a5f3ee35b105..6819face4c219 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -412,7 +412,7 @@ pub const unsafe fn size_of_val_raw(val: *const T) -> usize { #[stable(feature = "rust1", since = "1.0.0")] #[deprecated(note = "use `align_of` instead", since = "1.2.0", suggestion = "align_of")] pub fn min_align_of() -> usize { - intrinsics::min_align_of::() + intrinsics::align_of::() } /// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to in @@ -436,7 +436,7 @@ pub fn min_align_of() -> usize { #[deprecated(note = "use `align_of_val` instead", since = "1.2.0", suggestion = "align_of_val")] pub fn min_align_of_val(val: &T) -> usize { // SAFETY: val is a reference, so it's a valid raw pointer - unsafe { intrinsics::min_align_of_val(val) } + unsafe { intrinsics::align_of_val(val) } } /// Returns the [ABI]-required minimum alignment of a type in bytes. @@ -458,7 +458,7 @@ pub fn min_align_of_val(val: &T) -> usize { #[rustc_promotable] #[rustc_const_stable(feature = "const_align_of", since = "1.24.0")] pub const fn align_of() -> usize { - intrinsics::min_align_of::() + intrinsics::align_of::() } /// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to in @@ -477,10 +477,9 @@ pub const fn align_of() -> usize { #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_align_of_val", since = "1.85.0")] -#[allow(deprecated)] pub const fn align_of_val(val: &T) -> usize { // SAFETY: val is a reference, so it's a valid raw pointer - unsafe { intrinsics::min_align_of_val(val) } + unsafe { intrinsics::align_of_val(val) } } /// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to in @@ -527,7 +526,7 @@ pub const fn align_of_val(val: &T) -> usize { #[unstable(feature = "layout_for_ptr", issue = "69835")] pub const unsafe fn align_of_val_raw(val: *const T) -> usize { // SAFETY: the caller must provide a valid raw pointer - unsafe { intrinsics::min_align_of_val(val) } + unsafe { intrinsics::align_of_val(val) } } /// Returns `true` if dropping values of type `T` matters. @@ -637,8 +636,6 @@ pub const fn needs_drop() -> bool { #[inline(always)] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated_in_future)] -#[allow(deprecated)] #[rustc_diagnostic_item = "mem_zeroed"] #[track_caller] #[rustc_const_stable(feature = "const_mem_zeroed", since = "1.75.0")] @@ -677,8 +674,6 @@ pub const unsafe fn zeroed() -> T { #[must_use] #[deprecated(since = "1.39.0", note = "use `mem::MaybeUninit` instead")] #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated_in_future)] -#[allow(deprecated)] #[rustc_diagnostic_item = "mem_uninitialized"] #[track_caller] pub unsafe fn uninitialized() -> T { diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index ef7e6f9c2f491..26661b20c12d6 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -98,7 +98,7 @@ pub enum ControlFlow { // is a no-op conversion in the `Try` implementation. } -#[unstable(feature = "try_trait_v2", issue = "84277")] +#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] impl ops::Try for ControlFlow { type Output = C; type Residual = ControlFlow; @@ -117,7 +117,7 @@ impl ops::Try for ControlFlow { } } -#[unstable(feature = "try_trait_v2", issue = "84277")] +#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] // Note: manually specifying the residual type instead of using the default to work around // https://github.com/rust-lang/rust/issues/99940 impl ops::FromResidual> for ControlFlow { diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index 1658f0e5a3692..87dd873fdb57d 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -194,7 +194,7 @@ pub use self::try_trait::Residual; #[unstable(feature = "try_trait_v2_yeet", issue = "96374")] pub use self::try_trait::Yeet; pub(crate) use self::try_trait::{ChangeOutputType, NeverShortCircuit}; -#[unstable(feature = "try_trait_v2", issue = "84277")] +#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] pub use self::try_trait::{FromResidual, Try}; #[unstable(feature = "coerce_unsized", issue = "18598")] pub use self::unsize::CoerceUnsized; diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index bac8ffb074ba8..aebbddb4f1c07 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -112,7 +112,7 @@ use crate::ops::ControlFlow; /// R::from_output(accum) /// } /// ``` -#[unstable(feature = "try_trait_v2", issue = "84277")] +#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] #[rustc_on_unimplemented( on( all(from_desugaring = "TryBlock"), @@ -130,7 +130,7 @@ use crate::ops::ControlFlow; #[lang = "Try"] pub trait Try: FromResidual { /// The type of the value produced by `?` when *not* short-circuiting. - #[unstable(feature = "try_trait_v2", issue = "84277")] + #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] type Output; /// The type of the value passed to [`FromResidual::from_residual`] @@ -154,7 +154,7 @@ pub trait Try: FromResidual { /// then typically you can use `Foo` as its `Residual` /// type: that type will have a "hole" in the correct place, and will maintain the /// "foo-ness" of the residual so other types need to opt-in to interconversion. - #[unstable(feature = "try_trait_v2", issue = "84277")] + #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] type Residual; /// Constructs the type from its `Output` type. @@ -186,7 +186,7 @@ pub trait Try: FromResidual { /// assert_eq!(r, Some(4)); /// ``` #[lang = "from_output"] - #[unstable(feature = "try_trait_v2", issue = "84277")] + #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] fn from_output(output: Self::Output) -> Self; /// Used in `?` to decide whether the operator should produce a value @@ -213,7 +213,7 @@ pub trait Try: FromResidual { /// ); /// ``` #[lang = "branch"] - #[unstable(feature = "try_trait_v2", issue = "84277")] + #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] fn branch(self) -> ControlFlow; } @@ -303,7 +303,7 @@ pub trait Try: FromResidual { ), )] #[rustc_diagnostic_item = "FromResidual"] -#[unstable(feature = "try_trait_v2", issue = "84277")] +#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] pub trait FromResidual::Residual> { /// Constructs the type from a compatible `Residual` type. /// @@ -326,7 +326,7 @@ pub trait FromResidual::Residual> { /// ); /// ``` #[lang = "from_residual"] - #[unstable(feature = "try_trait_v2", issue = "84277")] + #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] fn from_residual(residual: R) -> Self; } diff --git a/library/core/src/option.rs b/library/core/src/option.rs index c04754848b4ff..f2a1e901188ff 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -2532,7 +2532,7 @@ impl> FromIterator> for Option { } } -#[unstable(feature = "try_trait_v2", issue = "84277")] +#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] impl ops::Try for Option { type Output = T; type Residual = Option; @@ -2551,7 +2551,7 @@ impl ops::Try for Option { } } -#[unstable(feature = "try_trait_v2", issue = "84277")] +#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] // Note: manually specifying the residual type instead of using the default to work around // https://github.com/rust-lang/rust/issues/99940 impl ops::FromResidual> for Option { diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 23e32c2e0f01d..3a84ea66ad4b2 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -2051,7 +2051,7 @@ impl> FromIterator> for Result { } } -#[unstable(feature = "try_trait_v2", issue = "84277")] +#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] impl ops::Try for Result { type Output = T; type Residual = Result; @@ -2070,7 +2070,7 @@ impl ops::Try for Result { } } -#[unstable(feature = "try_trait_v2", issue = "84277")] +#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] impl> ops::FromResidual> for Result { #[inline] #[track_caller] diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index 6aab22177ab9d..ca668361ef63b 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -229,7 +229,7 @@ impl From for Poll { } } -#[unstable(feature = "try_trait_v2", issue = "84277")] +#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] impl ops::Try for Poll> { type Output = Poll; type Residual = Result; @@ -249,7 +249,7 @@ impl ops::Try for Poll> { } } -#[unstable(feature = "try_trait_v2", issue = "84277")] +#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] impl> ops::FromResidual> for Poll> { #[inline] fn from_residual(x: Result) -> Self { @@ -259,7 +259,7 @@ impl> ops::FromResidual> for Pol } } -#[unstable(feature = "try_trait_v2", issue = "84277")] +#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] impl ops::Try for Poll>> { type Output = Poll>; type Residual = Result; @@ -280,7 +280,7 @@ impl ops::Try for Poll>> { } } -#[unstable(feature = "try_trait_v2", issue = "84277")] +#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] impl> ops::FromResidual> for Poll>> { diff --git a/library/coretests/tests/ffi/cstr.rs b/library/coretests/tests/ffi/cstr.rs index dc34240cd99d2..7d669cc1c3fff 100644 --- a/library/coretests/tests/ffi/cstr.rs +++ b/library/coretests/tests/ffi/cstr.rs @@ -17,7 +17,7 @@ fn compares_as_u8s() { #[test] fn debug() { let s = c"abc\x01\x02\n\xE2\x80\xA6\xFF"; - assert_eq!(format!("{s:?}"), r#""abc\x01\x02\n\xe2\x80\xa6\xff""#); + assert_eq!(format!("{s:?}"), r#""abc\x01\x02\n…\xff""#); } #[test] diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 680718f055299..f64d67341cfe2 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -136,6 +136,19 @@ impl Step for ToolBuild { _ => panic!("unexpected Mode for tool build"), } + // build.tool.TOOL_NAME.features in bootstrap.toml allows specifying which features to + // enable for a specific tool. `extra_features` instead is not controlled by the toml and + // provides features that are always enabled for a specific tool (e.g. "in-rust-tree" for + // rust-analyzer). Finally, `prepare_tool_cargo` might add more features to adapt the build + // to the chosen flags (e.g. "all-static" for cargo if `cargo_native_static` is true). + let mut features = builder + .config + .tool + .get(self.tool) + .and_then(|tool| tool.features.clone()) + .unwrap_or_default(); + features.extend(self.extra_features.clone()); + let mut cargo = prepare_tool_cargo( builder, self.compiler, @@ -144,7 +157,7 @@ impl Step for ToolBuild { Kind::Build, path, self.source_type, - &self.extra_features, + &features, ); // The stage0 compiler changes infrequently and does not directly depend on code diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 6aff376bde353..970a982dae42c 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -35,7 +35,7 @@ pub use crate::core::config::flags::Subcommand; use crate::core::config::flags::{Color, Flags}; use crate::core::config::target_selection::TargetSelectionList; use crate::core::config::toml::TomlConfig; -use crate::core::config::toml::build::Build; +use crate::core::config::toml::build::{Build, Tool}; use crate::core::config::toml::change_id::ChangeId; use crate::core::config::toml::rust::{ LldMode, RustOptimize, check_incompatible_options_for_ci_rustc, @@ -101,6 +101,9 @@ pub struct Config { pub bootstrap_cache_path: Option, pub extended: bool, pub tools: Option>, + /// Specify build configuration specific for some tool, such as enabled features, see [Tool]. + /// The key in the map is the name of the tool, and the value is tool-specific configuration. + pub tool: HashMap, pub sanitizers: bool, pub profiler: bool, pub omit_git_hash: bool, @@ -676,6 +679,7 @@ impl Config { bootstrap_cache_path, extended, tools, + tool, verbose, sanitizers, profiler, @@ -822,6 +826,7 @@ impl Config { set(&mut config.full_bootstrap, full_bootstrap); set(&mut config.extended, extended); config.tools = tools; + set(&mut config.tool, tool); set(&mut config.verbose, verbose); set(&mut config.sanitizers, sanitizers); set(&mut config.profiler, profiler); diff --git a/src/bootstrap/src/core/config/toml/build.rs b/src/bootstrap/src/core/config/toml/build.rs index 85ded3c87d916..98e1194de728b 100644 --- a/src/bootstrap/src/core/config/toml/build.rs +++ b/src/bootstrap/src/core/config/toml/build.rs @@ -6,6 +6,8 @@ //! various feature flags. These options apply across different stages and components //! unless specifically overridden by other configuration sections or command-line flags. +use std::collections::HashMap; + use serde::{Deserialize, Deserializer}; use crate::core::config::toml::ReplaceOpt; @@ -42,6 +44,7 @@ define_config! { bootstrap_cache_path: Option = "bootstrap-cache-path", extended: Option = "extended", tools: Option> = "tools", + tool: Option> = "tool", verbose: Option = "verbose", sanitizers: Option = "sanitizers", profiler: Option = "profiler", @@ -70,3 +73,11 @@ define_config! { exclude: Option> = "exclude", } } + +define_config! { + /// Configuration specific for some tool, e.g. which features to enable during build. + #[derive(Default, Clone)] + struct Tool { + features: Option> = "features", + } +} diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index e939a8362ada7..93e01a58077e0 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -421,4 +421,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Info, summary: "Added new bootstrap flag `--skip-std-check-if-no-download-rustc` that skips std checks when download-rustc is unavailable. Mainly intended for developers to reduce RA overhead.", }, + ChangeInfo { + change_id: 142379, + severity: ChangeSeverity::Info, + summary: "Added new option `tool.TOOL_NAME.features` to specify the features to compile a tool with", + }, ]; diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index c8721bb36001f..86d35b314983f 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -c31cccb7b5cc098b1a8c1794ed38d7fdbec0ccb0 +14346303d760027e53214e705109a62c0f00b214 diff --git a/src/doc/rustc-dev-guide/src/git.md b/src/doc/rustc-dev-guide/src/git.md index 8118ddff10c92..8726ddfce20cc 100644 --- a/src/doc/rustc-dev-guide/src/git.md +++ b/src/doc/rustc-dev-guide/src/git.md @@ -142,7 +142,8 @@ The most common cause is that you rebased after a change and ran `git add .` wit `x` to update the submodules. Alternatively, you might have run `cargo fmt` instead of `x fmt` and modified files in a submodule, then committed the changes. -To fix it, do the following things: +To fix it, do the following things (if you changed a submodule other than cargo, +replace `src/tools/cargo` with the path to that submodule): 1. See which commit has the accidental changes: `git log --stat -n1 src/tools/cargo` 2. Revert the changes to that commit: `git checkout ~ src/tools/cargo`. Type `~` diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index 20dd16c81df61..ded30234e70b6 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -115,7 +115,7 @@ default behavior without any commands is to: 2. Run `rustc -Zunpretty=normal` on the output of the previous step. 3. The output of the previous two steps should be the same. 4. Run `rustc -Zno-codegen` on the output to make sure that it can type check - (this is similar to running `cargo check`). + (similar to `cargo check`). If any of the commands above fail, then the test fails. diff --git a/src/doc/unstable-book/src/compiler-flags/macro-stats.md b/src/doc/unstable-book/src/compiler-flags/macro-stats.md new file mode 100644 index 0000000000000..b2622cff0570a --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/macro-stats.md @@ -0,0 +1,24 @@ +# `macro-stats` + +This feature is perma-unstable and has no tracking issue. + +---- + +Some macros, especially procedural macros, can generate a surprising amount of +code, which can slow down compile times. This is hard to detect because the +generated code is normally invisible to the programmer. + +This flag helps identify such cases. When enabled, the compiler measures the +effect on code size of all used macros and prints a table summarizing that +effect. For each distinct macro, it counts how many times it is used, and the +net effect on code size (in terms of lines of code, and bytes of code). The +code size evaluation uses the compiler's internal pretty-printing, and so will +be independent of the formatting in the original code. + +Note that the net effect of a macro may be negative. E.g. the `cfg!` and +`#[test]` macros often strip out code. + +If a macro is identified as causing a large increase in code size, it is worth +using `cargo expand` to inspect the post-expansion code, which includes the +code produced by all macros. It may be possible to optimize the macro to +produce smaller code, or it may be possible to avoid using it altogether. diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index a3762e4117d18..b6ce85510600e 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -169,33 +169,36 @@ impl Cfg { msg } - /// Renders the configuration for long display, as a long HTML description. - pub(crate) fn render_long_html(&self) -> String { + fn render_long_inner(&self, format: Format) -> String { let on = if self.omit_preposition() { - "" + " " } else if self.should_use_with_in_description() { - "with " + " with " } else { - "on " + " on " }; - let mut msg = format!("Available {on}{}", Display(self, Format::LongHtml)); + let mut msg = if matches!(format, Format::LongHtml) { + format!("Available{on}{}", Display(self, format)) + } else { + format!("Available{on}{}", Display(self, format)) + }; if self.should_append_only_to_description() { msg.push_str(" only"); } + msg + } + + /// Renders the configuration for long display, as a long HTML description. + pub(crate) fn render_long_html(&self) -> String { + let mut msg = self.render_long_inner(Format::LongHtml); msg.push('.'); msg } /// Renders the configuration for long display, as a long plain text description. pub(crate) fn render_long_plain(&self) -> String { - let on = if self.should_use_with_in_description() { "with" } else { "on" }; - - let mut msg = format!("Available {on} {}", Display(self, Format::LongPlain)); - if self.should_append_only_to_description() { - msg.push_str(" only"); - } - msg + self.render_long_inner(Format::LongPlain) } fn should_capitalize_first_letter(&self) -> bool { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index bde1a2e5e6642..58e05bd1e8574 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -2638,7 +2638,7 @@ mod size_asserts { static_assert_size!(GenericParamDef, 40); static_assert_size!(Generics, 16); static_assert_size!(Item, 8); - static_assert_size!(ItemInner, 136); + static_assert_size!(ItemInner, 144); static_assert_size!(ItemKind, 48); static_assert_size!(PathSegment, 32); static_assert_size!(Type, 32); diff --git a/src/tools/clippy/clippy_utils/src/sym.rs b/src/tools/clippy/clippy_utils/src/sym.rs index f417530be3672..11b085b70580c 100644 --- a/src/tools/clippy/clippy_utils/src/sym.rs +++ b/src/tools/clippy/clippy_utils/src/sym.rs @@ -76,7 +76,6 @@ generate! { Visitor, Weak, abs, - align_of, ambiguous_glob_reexports, append, arg, diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index 9957e351ff105..9e5ba96e2deac 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -272,8 +272,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let a = this.read_scalar(a)?.to_f32()?; let b = this.read_scalar(b)?.to_f32()?; let c = this.read_scalar(c)?.to_f32()?; - // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11 - let res = a.to_host().mul_add(b.to_host(), c.to_host()).to_soft(); + let res = a.mul_add(b, c).value; let res = this.adjust_nan(res, &[a, b, c]); this.write_scalar(res, dest)?; } @@ -282,8 +281,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let a = this.read_scalar(a)?.to_f64()?; let b = this.read_scalar(b)?.to_f64()?; let c = this.read_scalar(c)?.to_f64()?; - // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11 - let res = a.to_host().mul_add(b.to_host(), c.to_host()).to_soft(); + let res = a.mul_add(b, c).value; let res = this.adjust_nan(res, &[a, b, c]); this.write_scalar(res, dest)?; } @@ -295,8 +293,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let c = this.read_scalar(c)?.to_f32()?; let fuse: bool = this.machine.rng.get_mut().random(); let res = if fuse { - // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11 - a.to_host().mul_add(b.to_host(), c.to_host()).to_soft() + a.mul_add(b, c).value } else { ((a * b).value + c).value }; @@ -310,8 +307,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let c = this.read_scalar(c)?.to_f64()?; let fuse: bool = this.machine.rng.get_mut().random(); let res = if fuse { - // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11 - a.to_host().mul_add(b.to_host(), c.to_host()).to_soft() + a.mul_add(b, c).value } else { ((a * b).value + c).value }; diff --git a/src/tools/miri/src/intrinsics/simd.rs b/src/tools/miri/src/intrinsics/simd.rs index b17fd4fb7f932..7e2153ef44099 100644 --- a/src/tools/miri/src/intrinsics/simd.rs +++ b/src/tools/miri/src/intrinsics/simd.rs @@ -320,7 +320,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let b = b.to_f32()?; let c = c.to_f32()?; let res = if fuse { - a.to_host().mul_add(b.to_host(), c.to_host()).to_soft() + a.mul_add(b, c).value } else { ((a * b).value + c).value }; @@ -332,7 +332,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let b = b.to_f64()?; let c = c.to_f64()?; let res = if fuse { - a.to_host().mul_add(b.to_host(), c.to_host()).to_soft() + a.mul_add(b, c).value } else { ((a * b).value + c).value }; diff --git a/tests/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.panic-abort.diff index 8ebd07b9c9c1e..e61a3e8d73834 100644 --- a/tests/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.panic-abort.diff @@ -5,7 +5,7 @@ let mut _0: usize; bb0: { -- _0 = std::intrinsics::min_align_of::() -> [return: bb1, unwind unreachable]; +- _0 = std::intrinsics::align_of::() -> [return: bb1, unwind unreachable]; + _0 = AlignOf(T); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.panic-unwind.diff index 8ebd07b9c9c1e..e61a3e8d73834 100644 --- a/tests/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.panic-unwind.diff @@ -5,7 +5,7 @@ let mut _0: usize; bb0: { -- _0 = std::intrinsics::min_align_of::() -> [return: bb1, unwind unreachable]; +- _0 = std::intrinsics::align_of::() -> [return: bb1, unwind unreachable]; + _0 = AlignOf(T); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.rs b/tests/mir-opt/lower_intrinsics.rs index 1e4f20241947e..7729e502ad6b9 100644 --- a/tests/mir-opt/lower_intrinsics.rs +++ b/tests/mir-opt/lower_intrinsics.rs @@ -51,7 +51,7 @@ pub fn size_of() -> usize { pub fn align_of() -> usize { // CHECK-LABEL: fn align_of( // CHECK: {{_.*}} = AlignOf(T); - core::intrinsics::min_align_of::() + core::intrinsics::align_of::() } // EMIT_MIR lower_intrinsics.forget.LowerIntrinsics.diff diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir index 30eafe8594b3f..2eee8a97db0d4 100644 --- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir @@ -39,7 +39,7 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { } scope 15 (inlined std::mem::size_of::) { } - scope 16 (inlined align_of::) { + scope 16 (inlined std::mem::align_of::) { } scope 17 (inlined slice_from_raw_parts::) { debug data => _3; diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir index 30eafe8594b3f..2eee8a97db0d4 100644 --- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir @@ -39,7 +39,7 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { } scope 15 (inlined std::mem::size_of::) { } - scope 16 (inlined align_of::) { + scope 16 (inlined std::mem::align_of::) { } scope 17 (inlined slice_from_raw_parts::) { debug data => _3; diff --git a/tests/pretty/postfix-match/precedence.pp b/tests/pretty/postfix-match/precedence.pp index 967aa7bc39ef3..2052b445a2b30 100644 --- a/tests/pretty/postfix-match/precedence.pp +++ b/tests/pretty/postfix-match/precedence.pp @@ -26,7 +26,7 @@ _ => {} }; (4 as usize).match { _ => {} }; - (return).match { _ => {} }; + return.match { _ => {} }; (a = 42).match { _ => {} }; (|| {}).match { _ => {} }; (42..101).match { _ => {} }; diff --git a/tests/rustdoc/cfg-bool.rs b/tests/rustdoc/cfg-bool.rs index 34fdfbe930e12..0aaa132e0b540 100644 --- a/tests/rustdoc/cfg-bool.rs +++ b/tests/rustdoc/cfg-bool.rs @@ -3,11 +3,15 @@ // regression test for https://github.com/rust-lang/rust/issues/138112 -//@ has 'foo/fn.foo.html' '//div[@class="stab portability"]' 'Available nowhere' +//@ has 'foo/index.html' +//@ has - '//*[@class="stab portability"]/@title' 'Available nowhere' + +//@ count 'foo/fn.foo.html' '//*[@class="stab portability"]' 1 +//@ has 'foo/fn.foo.html' '//*[@class="stab portability"]' 'Available nowhere' #[doc(cfg(false))] pub fn foo() {} -// a cfg(true) will simply be ommited, as it is the same as no cfg. -//@ !has 'foo/fn.bar.html' '//div[@class="stab portability"]' '' +// a cfg(true) will simply be omitted, as it is the same as no cfg. +//@ count 'foo/fn.bar.html' '//*[@class="stab portability"]' 0 #[doc(cfg(true))] pub fn bar() {} diff --git a/tests/ui-fulldeps/pprust-parenthesis-insertion.rs b/tests/ui-fulldeps/pprust-parenthesis-insertion.rs index c566ac459e0d2..36916e9785629 100644 --- a/tests/ui-fulldeps/pprust-parenthesis-insertion.rs +++ b/tests/ui-fulldeps/pprust-parenthesis-insertion.rs @@ -63,8 +63,8 @@ static EXPRS: &[&str] = &[ "(2 += 2) += 2", // Return has lower precedence than a binary operator. "(return 2) + 2", - "2 + (return 2)", // FIXME: no parenthesis needed. - "(return) + 2", // FIXME: no parenthesis needed. + "2 + return 2", + "return + 2", // These mean different things. "return - 2", "(return) - 2", diff --git a/tests/ui/consts/auxiliary/unstable_intrinsic.rs b/tests/ui/consts/auxiliary/unstable_intrinsic.rs index 45631df78591e..c1c7571e0c90c 100644 --- a/tests/ui/consts/auxiliary/unstable_intrinsic.rs +++ b/tests/ui/consts/auxiliary/unstable_intrinsic.rs @@ -8,4 +8,4 @@ pub const unsafe fn size_of_val(x: *const T) -> usize; #[unstable(feature = "unstable", issue = "42")] #[rustc_const_unstable(feature = "unstable", issue = "42")] #[rustc_intrinsic] -pub const unsafe fn min_align_of_val(x: *const T) -> usize; +pub const unsafe fn align_of_val(x: *const T) -> usize; diff --git a/tests/ui/consts/const-adt-align-mismatch.rs b/tests/ui/consts/const-adt-align-mismatch.rs index 8faddbff30da8..6ff74ad3a9ce9 100644 --- a/tests/ui/consts/const-adt-align-mismatch.rs +++ b/tests/ui/consts/const-adt-align-mismatch.rs @@ -18,5 +18,5 @@ static FOO: Foo = Foo::C; fn main() { assert_eq!(FOO, Foo::C); assert_eq!(mem::size_of::(), 12); - assert_eq!(mem::min_align_of::(), 4); + assert_eq!(mem::align_of::(), 4); } diff --git a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs index 14cdf6bb7c66e..423ff37baef89 100644 --- a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs +++ b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs @@ -1,13 +1,13 @@ #![feature(extern_types)] #![feature(core_intrinsics)] -use std::intrinsics::{min_align_of_val, size_of_val}; +use std::intrinsics::{align_of_val, size_of_val}; extern "C" { type Opaque; } const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) }; //~ ERROR layout -const _ALIGN: usize = unsafe { min_align_of_val(&4 as *const i32 as *const Opaque) }; //~ ERROR layout +const _ALIGN: usize = unsafe { align_of_val(&4 as *const i32 as *const Opaque) }; //~ ERROR layout fn main() {} diff --git a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr index 64b7a4129e07a..c78626bdefc5c 100644 --- a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr +++ b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr @@ -7,8 +7,8 @@ LL | const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque error[E0080]: `extern type` does not have known layout --> $DIR/const-size_of_val-align_of_val-extern-type.rs:11:32 | -LL | const _ALIGN: usize = unsafe { min_align_of_val(&4 as *const i32 as *const Opaque) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `_ALIGN` failed here +LL | const _ALIGN: usize = unsafe { align_of_val(&4 as *const i32 as *const Opaque) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `_ALIGN` failed here error: aborting due to 2 previous errors diff --git a/tests/ui/consts/const-unstable-intrinsic.rs b/tests/ui/consts/const-unstable-intrinsic.rs index 890a30c73c8aa..d130eb6c707f8 100644 --- a/tests/ui/consts/const-unstable-intrinsic.rs +++ b/tests/ui/consts/const-unstable-intrinsic.rs @@ -17,13 +17,13 @@ const fn const_main() { unstable_intrinsic::size_of_val(&x); //~^ERROR: unstable library feature `unstable` //~|ERROR: not yet stable as a const intrinsic - unstable_intrinsic::min_align_of_val(&x); + unstable_intrinsic::align_of_val(&x); //~^ERROR: unstable library feature `unstable` //~|ERROR: not yet stable as a const intrinsic size_of_val(&x); //~^ERROR: cannot use `#[feature(local)]` - min_align_of_val(&x); + align_of_val(&x); //~^ERROR: cannot use `#[feature(local)]` } } @@ -35,7 +35,7 @@ pub const unsafe fn size_of_val(x: *const T) -> usize; #[unstable(feature = "local", issue = "42")] #[rustc_const_unstable(feature = "local", issue = "42")] #[rustc_intrinsic] -pub const unsafe fn min_align_of_val(x: *const T) -> usize; +pub const unsafe fn align_of_val(x: *const T) -> usize; #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] diff --git a/tests/ui/consts/const-unstable-intrinsic.stderr b/tests/ui/consts/const-unstable-intrinsic.stderr index 7e7ba966cee17..973c7bae58691 100644 --- a/tests/ui/consts/const-unstable-intrinsic.stderr +++ b/tests/ui/consts/const-unstable-intrinsic.stderr @@ -11,8 +11,8 @@ LL | unstable_intrinsic::size_of_val(&x); error[E0658]: use of unstable library feature `unstable` --> $DIR/const-unstable-intrinsic.rs:20:9 | -LL | unstable_intrinsic::min_align_of_val(&x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | unstable_intrinsic::align_of_val(&x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #42 for more information = help: add `#![feature(unstable)]` to the crate attributes to enable @@ -29,11 +29,11 @@ help: add `#![feature(unstable)]` to the crate attributes to enable LL + #![feature(unstable)] | -error: `min_align_of_val` is not yet stable as a const intrinsic +error: `align_of_val` is not yet stable as a const intrinsic --> $DIR/const-unstable-intrinsic.rs:20:9 | -LL | unstable_intrinsic::min_align_of_val(&x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | unstable_intrinsic::align_of_val(&x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: add `#![feature(unstable)]` to the crate attributes to enable | @@ -55,8 +55,8 @@ LL | const fn const_main() { error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]` --> $DIR/const-unstable-intrinsic.rs:26:9 | -LL | min_align_of_val(&x); - | ^^^^^^^^^^^^^^^^^^^^ +LL | align_of_val(&x); + | ^^^^^^^^^^^^^^^^ | help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` | diff --git a/tests/ui/intrinsics/intrinsic-alignment.rs b/tests/ui/intrinsics/intrinsic-alignment.rs index 30a523f364c7c..904da71c306b0 100644 --- a/tests/ui/intrinsics/intrinsic-alignment.rs +++ b/tests/ui/intrinsics/intrinsic-alignment.rs @@ -23,12 +23,12 @@ use std::intrinsics as rusti; mod m { #[cfg(target_arch = "x86")] pub fn main() { - assert_eq!(crate::rusti::min_align_of::(), 4); + assert_eq!(crate::rusti::align_of::(), 4); } #[cfg(not(target_arch = "x86"))] pub fn main() { - assert_eq!(crate::rusti::min_align_of::(), 8); + assert_eq!(crate::rusti::align_of::(), 8); } } @@ -36,21 +36,21 @@ mod m { mod m { #[cfg(target_arch = "x86_64")] pub fn main() { - assert_eq!(crate::rusti::min_align_of::(), 8); + assert_eq!(crate::rusti::align_of::(), 8); } } #[cfg(target_os = "windows")] mod m { pub fn main() { - assert_eq!(crate::rusti::min_align_of::(), 8); + assert_eq!(crate::rusti::align_of::(), 8); } } #[cfg(target_family = "wasm")] mod m { pub fn main() { - assert_eq!(crate::rusti::min_align_of::(), 8); + assert_eq!(crate::rusti::align_of::(), 8); } } diff --git a/tests/ui/invalid/invalid-rustc_legacy_const_generics-issue-123077.stderr b/tests/ui/invalid/invalid-rustc_legacy_const_generics-issue-123077.stderr index d92836aa063b1..8d120ae98d90d 100644 --- a/tests/ui/invalid/invalid-rustc_legacy_const_generics-issue-123077.stderr +++ b/tests/ui/invalid/invalid-rustc_legacy_const_generics-issue-123077.stderr @@ -19,7 +19,7 @@ LL | std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, 5 + || ()); help: try using a const generic argument instead | LL - std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, 5 + || ()); -LL + std::arch::x86_64::_mm_blend_ps::<{ 5 + (|| ()) }>(loop {}, loop {}); +LL + std::arch::x86_64::_mm_blend_ps::<{ 5 + || () }>(loop {}, loop {}); | error: invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items @@ -81,7 +81,7 @@ LL | std::arch::x86_64::_mm_inserti_si64(loop {}, loop {}, || (), 1 + || ()) help: try using a const generic argument instead | LL - std::arch::x86_64::_mm_inserti_si64(loop {}, loop {}, || (), 1 + || ()); -LL + std::arch::x86_64::_mm_inserti_si64::<{ || () }, { 1 + (|| ()) }>(loop {}, loop {}); +LL + std::arch::x86_64::_mm_inserti_si64::<{ || () }, { 1 + || () }>(loop {}, loop {}); | error: aborting due to 7 previous errors diff --git a/tests/ui/layout/invalid-unsized-in-always-sized-tail.stderr b/tests/ui/layout/invalid-unsized-in-always-sized-tail.stderr index 1a43fd4ad1814..5f6a6099ba23e 100644 --- a/tests/ui/layout/invalid-unsized-in-always-sized-tail.stderr +++ b/tests/ui/layout/invalid-unsized-in-always-sized-tail.stderr @@ -24,7 +24,7 @@ error[E0080]: the type `MySlice<[bool]>` has an unknown layout LL | static CHECK: () = assert!(align_of::() == 1); | ^^^^^^^^^^^^^^^^ evaluation of `CHECK` failed inside this call | -note: inside `align_of::` +note: inside `std::mem::align_of::` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL error: aborting due to 2 previous errors diff --git a/tests/ui/simd/size-align.rs b/tests/ui/simd/size-align.rs index ff23ea5980ba2..53acb686fb846 100644 --- a/tests/ui/simd/size-align.rs +++ b/tests/ui/simd/size-align.rs @@ -7,12 +7,12 @@ use std::mem; -/// `T` should satisfy `size_of T (mod min_align_of T) === 0` to be stored at `Vec` properly +/// `T` should satisfy `size_of T (mod align_of T) === 0` to be stored at `Vec` properly /// Please consult the issue #20460 fn check() { - assert_eq!(mem::size_of::() % mem::min_align_of::(), 0); - assert_eq!(mem::size_of::() % mem::min_align_of::(), 0); - assert_eq!(mem::size_of::() % mem::min_align_of::(), 0); + assert_eq!(mem::size_of::() % mem::align_of::(), 0); + assert_eq!(mem::size_of::() % mem::align_of::(), 0); + assert_eq!(mem::size_of::() % mem::align_of::(), 0); } #[repr(simd)] diff --git a/tests/ui/stability-attribute/renamed_feature.rs b/tests/ui/stability-attribute/renamed_feature.rs new file mode 100644 index 0000000000000..249c2abecff0e --- /dev/null +++ b/tests/ui/stability-attribute/renamed_feature.rs @@ -0,0 +1,3 @@ +#![feature(try_trait)] //~ ERROR feature `try_trait` has been renamed to `try_trait_v2` [E0635] + +fn main() {} diff --git a/tests/ui/stability-attribute/renamed_feature.stderr b/tests/ui/stability-attribute/renamed_feature.stderr new file mode 100644 index 0000000000000..293a2feffb226 --- /dev/null +++ b/tests/ui/stability-attribute/renamed_feature.stderr @@ -0,0 +1,9 @@ +error[E0635]: feature `try_trait` has been renamed to `try_trait_v2` + --> $DIR/renamed_feature.rs:1:12 + | +LL | #![feature(try_trait)] + | ^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0635`. diff --git a/tests/ui/stats/auxiliary/include.rs b/tests/ui/stats/auxiliary/include.rs new file mode 100644 index 0000000000000..7fb7c78113765 --- /dev/null +++ b/tests/ui/stats/auxiliary/include.rs @@ -0,0 +1,3 @@ +fn zzz(x: u32) -> u32 { + x +} diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr index f2598bd7eaf85..88f91bef30b1a 100644 --- a/tests/ui/stats/input-stats.stderr +++ b/tests/ui/stats/input-stats.stderr @@ -82,10 +82,10 @@ hir-stats - Expr 32 (NN.N%) 1 hir-stats - Let 32 (NN.N%) 1 hir-stats - Semi 32 (NN.N%) 1 hir-stats FnDecl 120 (NN.N%) 3 40 -hir-stats Attribute 128 (NN.N%) 4 32 hir-stats FieldDef 128 (NN.N%) 2 64 hir-stats GenericArgs 144 (NN.N%) 3 48 hir-stats Variant 144 (NN.N%) 2 72 +hir-stats Attribute 160 (NN.N%) 4 40 hir-stats GenericBound 256 (NN.N%) 4 64 hir-stats - Trait 256 (NN.N%) 4 hir-stats Block 288 (NN.N%) 6 48 @@ -117,5 +117,5 @@ hir-stats - Use 352 (NN.N%) 4 hir-stats Path 1_040 (NN.N%) 26 40 hir-stats PathSegment 1_776 (NN.N%) 37 48 hir-stats ---------------------------------------------------------------- -hir-stats Total 8_644 172 +hir-stats Total 8_676 172 hir-stats diff --git a/tests/ui/stats/macro-stats.rs b/tests/ui/stats/macro-stats.rs new file mode 100644 index 0000000000000..ee265d682fd6c --- /dev/null +++ b/tests/ui/stats/macro-stats.rs @@ -0,0 +1,130 @@ +//@ check-pass +//@ compile-flags: -Zmacro-stats + +#[test] +fn test_foo() { + let what = "this"; + let how = "completely"; + let when = "immediately"; + println!("{what} disappears {how} and {when}"); +} + +#[rustfmt::skip] // non-macro attr, ignored by `-Zmacro-stats` +fn rustfmt_skip() { + // Nothing to see here. +} + +#[derive(Default, Clone, Copy, Hash)] +enum E1 { + #[default] // non-macro attr, ignored by `-Zmacro-stats` + A, + B, +} + +#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +struct E2 { + a: u32, + b: String, + c: Vec, +} + +#[derive(Clone)] struct S0; +#[derive(Clone)] struct S1(u32); +#[derive(Clone)] struct S2(u32, u32); +#[derive(Clone)] struct S3(u32, u32, u32); +#[derive(Clone)] struct S4(u32, u32, u32, u32); +#[derive(Clone)] struct S5(u32, u32, u32, u32, u32); + +macro_rules! u32 { + () => { u32 } +} + +macro_rules! none { + () => { None } +} +fn opt(x: Option) { + match x { + Some(_) => {} + none!() => {} // AstFragmentKind::Pat + } +} + +macro_rules! this_is_a_really_really_long_macro_name { + ($t:ty) => { + fn f(_: $t) {} + } +} +this_is_a_really_really_long_macro_name!(u32!()); // AstFragmentKind::{Items,Ty} + +macro_rules! trait_tys { + () => { + type A; + type B; + } +} +trait Tr { + trait_tys!(); // AstFragmentKind::TraitItems +} + +macro_rules! impl_const { () => { const X: u32 = 0; } } +struct U; +impl U { + impl_const!(); // AstFragmentKind::ImplItems +} + +macro_rules! trait_impl_tys { + () => { + type A = u32; + type B = bool; + } +} +struct Tr1; +impl Tr for Tr1 { + trait_impl_tys!(); // AstFragment::TraitImplItems +} + +macro_rules! foreign_item { + () => { fn fc(a: u32) -> u32; } +} +extern "C" { + foreign_item!(); // AstFragment::ForeignItems +} + +// Include macros are ignored by `-Zmacro-stats`. +mod includes { + mod z1 { + include!("auxiliary/include.rs"); + } + mod z2 { + std::include!("auxiliary/include.rs"); + } + + const B1: &[u8] = include_bytes!("auxiliary/include.rs"); + const B2: &[u8] = std::include_bytes!("auxiliary/include.rs"); + + const S1: &str = include_str!("auxiliary/include.rs"); + const S2: &str = std::include_str!("auxiliary/include.rs"); +} + +fn main() { + macro_rules! n99 { + () => { 99 } + } + let x = n99!() + n99!(); // AstFragmentKind::Expr + + macro_rules! p { + () => { + // blah + let x = 1; + let y = x; + let _ = y; + } + } + p!(); // AstFragmentKind::Stmts + + macro_rules! q { + () => {}; + ($($x:ident),*) => { $( let $x: u32 = 12345; )* }; + } + q!(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z); +} diff --git a/tests/ui/stats/macro-stats.stderr b/tests/ui/stats/macro-stats.stderr new file mode 100644 index 0000000000000..f87e34622b92c --- /dev/null +++ b/tests/ui/stats/macro-stats.stderr @@ -0,0 +1,26 @@ +macro-stats =================================================================================== +macro-stats MACRO EXPANSION STATS: macro_stats +macro-stats Macro Name Uses Lines Avg Lines Bytes Avg Bytes +macro-stats ----------------------------------------------------------------------------------- +macro-stats #[derive(Clone)] 8 56 7.0 1_660 207.5 +macro-stats #[derive(PartialOrd)] 1 16 16.0 654 654.0 +macro-stats #[derive(Hash)] 2 15 7.5 547 273.5 +macro-stats #[derive(Ord)] 1 14 14.0 489 489.0 +macro-stats q! 1 24 24.0 435 435.0 +macro-stats #[derive(Default)] 2 14 7.0 367 183.5 +macro-stats #[derive(Eq)] 1 10 10.0 312 312.0 +macro-stats #[derive(Debug)] 1 7 7.0 261 261.0 +macro-stats #[derive(PartialEq)] 1 8 8.0 247 247.0 +macro-stats #[derive(Copy)] 1 1 1.0 46 46.0 +macro-stats p! 1 2 2.0 28 28.0 +macro-stats trait_impl_tys! 1 1 1.0 11 11.0 +macro-stats foreign_item! 1 0 0.0 6 6.0 +macro-stats impl_const! 1 0 0.0 4 4.0 +macro-stats trait_tys! 1 1 1.0 3 3.0 +macro-stats u32! 1 0 0.0 -3 -3.0 +macro-stats none! 1 0 0.0 -3 -3.0 +macro-stats n99! 2 0 0.0 -8 -4.0 +macro-stats this_is_a_really_really_long_macro_name! +macro-stats 1 0 0.0 -30 -30.0 +macro-stats #[test] 1 -6 -6.0 -158 -158.0 +macro-stats =================================================================================== diff --git a/tests/ui/structs-enums/enum-alignment.rs b/tests/ui/structs-enums/enum-alignment.rs index bb779b1e0cdd2..95f14e521b573 100644 --- a/tests/ui/structs-enums/enum-alignment.rs +++ b/tests/ui/structs-enums/enum-alignment.rs @@ -11,7 +11,7 @@ fn addr_of(ptr: &T) -> usize { fn is_aligned(ptr: &T) -> bool { unsafe { let addr: usize = mem::transmute(ptr); - (addr % mem::min_align_of::()) == 0 + (addr % mem::align_of::()) == 0 } } diff --git a/tests/ui/structs-enums/rec-align-u32.rs b/tests/ui/structs-enums/rec-align-u32.rs index 448791897398d..b18cd11198e8d 100644 --- a/tests/ui/structs-enums/rec-align-u32.rs +++ b/tests/ui/structs-enums/rec-align-u32.rs @@ -34,12 +34,12 @@ pub fn main() { // Send it through the shape code let y = format!("{:?}", x); - println!("align inner = {:?}", intrinsics::min_align_of::()); + println!("align inner = {:?}", intrinsics::align_of::()); println!("size outer = {:?}", mem::size_of::()); println!("y = {:?}", y); // per clang/gcc the alignment of `inner` is 4 on x86. - assert_eq!(intrinsics::min_align_of::(), m::align()); + assert_eq!(intrinsics::align_of::(), m::align()); // per clang/gcc the size of `outer` should be 12 // because `inner`s alignment was 4. diff --git a/tests/ui/structs-enums/rec-align-u64.rs b/tests/ui/structs-enums/rec-align-u64.rs index 0f7bb6b350575..df219892d7374 100644 --- a/tests/ui/structs-enums/rec-align-u64.rs +++ b/tests/ui/structs-enums/rec-align-u64.rs @@ -84,12 +84,12 @@ pub fn main() { let y = format!("{:?}", x); - println!("align inner = {:?}", intrinsics::min_align_of::()); + println!("align inner = {:?}", intrinsics::align_of::()); println!("size outer = {:?}", mem::size_of::()); println!("y = {:?}", y); // per clang/gcc the alignment of `Inner` is 4 on x86. - assert_eq!(intrinsics::min_align_of::(), m::m::align()); + assert_eq!(intrinsics::align_of::(), m::m::align()); // per clang/gcc the size of `Outer` should be 12 // because `Inner`s alignment was 4. diff --git a/tests/ui/structs-enums/tag-align-dyn-u64.rs b/tests/ui/structs-enums/tag-align-dyn-u64.rs index 5e7d918b4fbcd..5a4f0878c5335 100644 --- a/tests/ui/structs-enums/tag-align-dyn-u64.rs +++ b/tests/ui/structs-enums/tag-align-dyn-u64.rs @@ -19,7 +19,7 @@ fn mk_rec() -> Rec { fn is_u64_aligned(u: &Tag) -> bool { let p: usize = unsafe { mem::transmute(u) }; - let u64_align = std::mem::min_align_of::(); + let u64_align = std::mem::align_of::(); return (p & (u64_align - 1)) == 0; } diff --git a/tests/ui/structs-enums/tag-align-dyn-variants.rs b/tests/ui/structs-enums/tag-align-dyn-variants.rs index c0574f3354e65..019f1a82895b5 100644 --- a/tests/ui/structs-enums/tag-align-dyn-variants.rs +++ b/tests/ui/structs-enums/tag-align-dyn-variants.rs @@ -34,7 +34,7 @@ fn variant_data_is_aligned(amnt: usize, u: &Tag) -> bool { } pub fn main() { - let u64_align = std::mem::min_align_of::(); + let u64_align = std::mem::align_of::(); let x = mk_rec(22u64, 23u64); assert!(is_aligned(u64_align, &x.tA)); assert!(variant_data_is_aligned(u64_align, &x.tA)); diff --git a/tests/ui/structs-enums/tag-align-u64.rs b/tests/ui/structs-enums/tag-align-u64.rs index 8ab9f242822c7..e274cc0e15751 100644 --- a/tests/ui/structs-enums/tag-align-u64.rs +++ b/tests/ui/structs-enums/tag-align-u64.rs @@ -19,7 +19,7 @@ fn mk_rec() -> Rec { fn is_u64_aligned(u: &Tag) -> bool { let p: usize = unsafe { mem::transmute(u) }; - let u64_align = std::mem::min_align_of::(); + let u64_align = std::mem::align_of::(); return (p & (u64_align - 1)) == 0; } diff --git a/tests/ui/unpretty/exhaustive.expanded.stdout b/tests/ui/unpretty/exhaustive.expanded.stdout index 9712ba58e627f..cd1a5d0af08af 100644 --- a/tests/ui/unpretty/exhaustive.expanded.stdout +++ b/tests/ui/unpretty/exhaustive.expanded.stdout @@ -190,7 +190,7 @@ mod expressions { (static async || value); (static async move || value); || -> u8 { value }; - 1 + (|| {}); + 1 + || {}; } /// ExprKind::Block