diff --git a/Cargo.lock b/Cargo.lock index dd7aa3d68324..57ed13f32c3b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6221,9 +6221,9 @@ dependencies = [ [[package]] name = "wasi-preview1-component-adapter-provider" -version = "40.0.0" +version = "43.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb5e2b9858989c3a257de4ca169977f4f79897b64e4f482f188f4fcf8ac557d1" +checksum = "93759d6fd0db242718bdcc6e4626eff8b0f3124ee7e58e47177a59f561baf164" [[package]] name = "wasm-bindgen" @@ -6272,9 +6272,9 @@ dependencies = [ [[package]] name = "wasm-component-ld" -version = "0.5.21" +version = "0.5.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59dcd765f510df84d1677a502c49057761486597a95950b4c92153e5707af091" +checksum = "216ca7b603f362831b31db4e2cdea1fa3609edd7177792fa64f62a80e10aa917" dependencies = [ "anyhow", "clap", @@ -6283,7 +6283,7 @@ dependencies = [ "libc", "tempfile", "wasi-preview1-component-adapter-provider", - "wasmparser 0.245.1", + "wasmparser 0.246.2", "wat", "windows-sys 0.61.2", "winsplit", @@ -6310,24 +6310,24 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.245.1" +version = "0.246.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9dca005e69bf015e45577e415b9af8c67e8ee3c0e38b5b0add5aa92581ed5c" +checksum = "61fb705ce81adde29d2a8e99d87995e39a6e927358c91398f374474746070ef7" dependencies = [ "leb128fmt", - "wasmparser 0.245.1", + "wasmparser 0.246.2", ] [[package]] name = "wasm-metadata" -version = "0.245.1" +version = "0.246.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da55e60097e8b37b475a0fa35c3420dd71d9eb7bd66109978ab55faf56a57efb" +checksum = "e3e4c2aa916c425dcca61a6887d3e135acdee2c6d0ed51fd61c08d41ddaf62b1" dependencies = [ "anyhow", "indexmap", - "wasm-encoder 0.245.1", - "wasmparser 0.245.1", + "wasm-encoder 0.246.2", + "wasmparser 0.246.2", ] [[package]] @@ -6352,9 +6352,9 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.245.1" +version = "0.246.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f08c9adee0428b7bddf3890fc27e015ac4b761cc608c822667102b8bfd6995e" +checksum = "71cde4757396defafd25417cfb36aa3161027d06d865b0c24baaae229aac005d" dependencies = [ "bitflags", "hashbrown 0.16.1", @@ -6365,22 +6365,22 @@ dependencies = [ [[package]] name = "wast" -version = "245.0.1" +version = "246.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cf1149285569120b8ce39db8b465e8a2b55c34cbb586bd977e43e2bc7300bf" +checksum = "fe3fe8e3bf88ad96d031b4181ddbd64634b17cb0d06dfc3de589ef43591a9a62" dependencies = [ "bumpalo", "leb128fmt", "memchr", "unicode-width 0.2.2", - "wasm-encoder 0.245.1", + "wasm-encoder 0.246.2", ] [[package]] name = "wat" -version = "1.245.1" +version = "1.246.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd48d1679b6858988cb96b154dda0ec5bbb09275b71db46057be37332d5477be" +checksum = "4bd7fda1199b94fff395c2d19a153f05dbe7807630316fa9673367666fd2ad8c" dependencies = [ "wast", ] @@ -6811,9 +6811,9 @@ dependencies = [ [[package]] name = "wit-component" -version = "0.245.1" +version = "0.246.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4894f10d2d5cbc17c77e91f86a1e48e191a788da4425293b55c98b44ba3fcac9" +checksum = "1936c26cb24b93dc36bf78fb5dc35c55cd37f66ecdc2d2663a717d9fb3ee951e" dependencies = [ "anyhow", "bitflags", @@ -6822,17 +6822,17 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "wasm-encoder 0.245.1", + "wasm-encoder 0.246.2", "wasm-metadata", - "wasmparser 0.245.1", + "wasmparser 0.246.2", "wit-parser", ] [[package]] name = "wit-parser" -version = "0.245.1" +version = "0.246.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330698718e82983499419494dd1e3d7811a457a9bf9f69734e8c5f07a2547929" +checksum = "fd979042b5ff288607ccf3b314145435453f20fc67173195f91062d2289b204d" dependencies = [ "anyhow", "hashbrown 0.16.1", @@ -6844,7 +6844,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", - "wasmparser 0.245.1", + "wasmparser 0.246.2", ] [[package]] diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 022f9e3c83f1..ee4a52fb3863 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -37,7 +37,6 @@ //! also be emitted during HIR ty lowering. use std::iter; -use std::marker::PhantomData; use ast::visit::Visitor; use hir::def::{DefKind, PartialRes, Res}; @@ -128,14 +127,12 @@ pub(crate) fn lower_delegation( { self.get_sig_id(delegation_info.resolution_node, span) } else { - return self.generate_delegation_error( - self.dcx().span_delayed_bug( - span, - format!("LoweringContext: the delegation {:?} is unresolved", item_id), - ), + self.dcx().span_delayed_bug( span, - delegation, + format!("LoweringContext: the delegation {:?} is unresolved", item_id), ); + + return self.generate_delegation_error(span, delegation); }; match sig_id { @@ -172,7 +169,7 @@ pub(crate) fn lower_delegation( DelegationResults { body_id, sig, ident, generics } } - Err(err) => self.generate_delegation_error(err, span, delegation), + Err(_) => self.generate_delegation_error(span, delegation), } } @@ -420,7 +417,6 @@ fn lower_delegation_body( resolver: this.resolver, path_id: delegation.id, self_param_id: pat_node_id, - phantom: PhantomData, }; self_resolver.visit_block(block); // Target expr needs to lower `self` path. @@ -604,7 +600,6 @@ fn process_segment( fn generate_delegation_error( &mut self, - err: ErrorGuaranteed, span: Span, delegation: &Delegation, ) -> DelegationResults<'hir> { @@ -622,36 +617,35 @@ fn generate_delegation_error( let ident = self.lower_ident(delegation.ident); let body_id = self.lower_body(|this| { - let body_expr = match delegation.body.as_ref() { - Some(box block) => { - // Generates a block when we failed to resolve delegation, where a target expression is its only statement, - // thus there will be no ICEs on further stages of analysis (see #144594) + let path = this.lower_qpath( + delegation.id, + &delegation.qself, + &delegation.path, + ParamMode::Optional, + AllowReturnTypeNotation::No, + ImplTraitContext::Disallowed(ImplTraitPosition::Path), + None, + ); - // As we generate a void function we want to convert target expression to statement to avoid additional - // errors, such as mismatched return type - let stmts = this.arena.alloc_from_iter([hir::Stmt { - hir_id: this.next_id(), - kind: rustc_hir::StmtKind::Semi( - this.arena.alloc(this.lower_target_expr(block)), - ), - span, - }]); - - let block = this.arena.alloc(hir::Block { - stmts, - expr: None, - hir_id: this.next_id(), - rules: hir::BlockCheckMode::DefaultBlock, - span, - targeted_by_break: false, - }); - - hir::ExprKind::Block(block, None) - } - None => hir::ExprKind::Err(err), + let callee_path = this.arena.alloc(this.mk_expr(hir::ExprKind::Path(path), span)); + let args = if let Some(box block) = delegation.body.as_ref() { + this.arena.alloc_slice(&[this.lower_target_expr(block)]) + } else { + &mut [] }; - (&[], this.mk_expr(body_expr, span)) + let call = this.arena.alloc(this.mk_expr(hir::ExprKind::Call(callee_path, args), span)); + + let block = this.arena.alloc(hir::Block { + stmts: &[], + expr: Some(call), + hir_id: this.next_id(), + rules: hir::BlockCheckMode::DefaultBlock, + span, + targeted_by_break: false, + }); + + (&[], this.mk_expr(hir::ExprKind::Block(block, None), span)) }); let generics = hir::Generics::empty(); @@ -673,14 +667,13 @@ fn mk_expr(&mut self, kind: hir::ExprKind<'hir>, span: Span) -> hir::Expr<'hir> } } -struct SelfResolver<'a, 'tcx, R> { +struct SelfResolver<'a, R> { resolver: &'a mut R, path_id: NodeId, self_param_id: NodeId, - phantom: PhantomData<&'tcx ()>, } -impl<'tcx, R: ResolverAstLoweringExt<'tcx>> SelfResolver<'_, 'tcx, R> { +impl<'tcx, R: ResolverAstLoweringExt<'tcx>> SelfResolver<'_, R> { fn try_replace_id(&mut self, id: NodeId) { if let Some(res) = self.resolver.get_partial_res(id) && let Some(Res::Local(sig_id)) = res.full_res() @@ -692,7 +685,7 @@ fn try_replace_id(&mut self, id: NodeId) { } } -impl<'ast, 'a, 'tcx, R: ResolverAstLoweringExt<'tcx>> Visitor<'ast> for SelfResolver<'a, 'tcx, R> { +impl<'ast, 'tcx, R: ResolverAstLoweringExt<'tcx>> Visitor<'ast> for SelfResolver<'_, R> { fn visit_id(&mut self, id: NodeId) { self.try_replace_id(id); } diff --git a/compiler/rustc_attr_parsing/src/validate_attr.rs b/compiler/rustc_attr_parsing/src/validate_attr.rs index e2521c9abf5f..f047c19a150b 100644 --- a/compiler/rustc_attr_parsing/src/validate_attr.rs +++ b/compiler/rustc_attr_parsing/src/validate_attr.rs @@ -1,15 +1,14 @@ //! Meta-syntax validation logic of attributes for post-expansion. use std::convert::identity; -use std::slice; use rustc_ast::token::Delimiter; use rustc_ast::tokenstream::DelimSpan; use rustc_ast::{ self as ast, AttrArgs, Attribute, DelimArgs, MetaItem, MetaItemInner, MetaItemKind, Safety, }; -use rustc_errors::{Applicability, FatalError, PResult}; -use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute}; +use rustc_errors::{Applicability, PResult}; +use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP}; use rustc_hir::AttrPath; use rustc_hir::lints::AttributeLintKind; use rustc_parse::parse_in; @@ -19,43 +18,23 @@ use rustc_session::parse::ParseSess; use rustc_span::{Span, Symbol, sym}; -use crate::{AttributeParser, Late, session_diagnostics as errors}; +use crate::session_diagnostics as errors; pub fn check_attr(psess: &ParseSess, attr: &Attribute) { - if attr.is_doc_comment() || attr.has_name(sym::cfg_trace) || attr.has_name(sym::cfg_attr_trace) + // Built-in attributes are parsed in their respective attribute parsers, so can be ignored here + if attr.is_doc_comment() + || attr.name().is_some_and(|name| BUILTIN_ATTRIBUTE_MAP.contains_key(&name)) { return; } - let builtin_attr_info = attr.name().and_then(|name| BUILTIN_ATTRIBUTE_MAP.get(&name)); - - // Check input tokens for built-in and key-value attributes. - match builtin_attr_info { - // `rustc_dummy` doesn't have any restrictions specific to built-in attributes. - Some(BuiltinAttribute { name, template, .. }) => { - if AttributeParser::::is_parsed_attribute(slice::from_ref(&name)) { - return; - } - match parse_meta(psess, attr) { - // Don't check safety again, we just did that - Ok(meta) => { - check_builtin_meta_item(psess, &meta, attr.style, *name, *template, false) - } - Err(err) => { - err.emit(); - } - } - } - _ => { - let attr_item = attr.get_normal_item(); - if let AttrArgs::Eq { .. } = attr_item.args.unparsed_ref().unwrap() { - // All key-value attributes are restricted to meta-item syntax. - match parse_meta(psess, attr) { - Ok(_) => {} - Err(err) => { - err.emit(); - } - } + let attr_item = attr.get_normal_item(); + if let AttrArgs::Eq { .. } = attr_item.args.unparsed_ref().unwrap() { + // All key-value attributes are restricted to meta-item syntax. + match parse_meta(psess, attr) { + Ok(_) => {} + Err(err) => { + err.emit(); } } } @@ -170,7 +149,7 @@ pub fn check_builtin_meta_item( } } -fn emit_malformed_attribute( +pub fn emit_malformed_attribute( psess: &ParseSess, style: ast::AttrStyle, span: Span, @@ -232,15 +211,3 @@ fn emit_malformed_attribute( err.emit(); } } - -pub fn emit_fatal_malformed_builtin_attribute( - psess: &ParseSess, - attr: &Attribute, - name: Symbol, -) -> ! { - let template = BUILTIN_ATTRIBUTE_MAP.get(&name).expect("builtin attr defined").template; - emit_malformed_attribute(psess, attr.style, attr.span, name, template); - // This is fatal, otherwise it will likely cause a cascade of other errors - // (and an error here is expected to be very rare). - FatalError.raise() -} diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index 6c5732f497f8..cee333e0a59f 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -603,21 +603,3 @@ pub(crate) struct TrailingMacro { pub is_trailing: bool, pub name: Ident, } - -#[derive(Diagnostic)] -#[diag("unused attribute `{$attr_name}`")] -pub(crate) struct UnusedBuiltinAttribute { - #[note( - "the built-in attribute `{$attr_name}` will be ignored, since it's applied to the macro invocation `{$macro_name}`" - )] - pub invoc_span: Span, - pub attr_name: Symbol, - pub macro_name: String, - #[suggestion( - "remove the attribute", - code = "", - applicability = "machine-applicable", - style = "tool-only" - )] - pub attr_span: Span, -} diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index e3a15f193e58..4ed87fc83b23 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -15,8 +15,8 @@ use rustc_ast_pretty::pprust; use rustc_attr_parsing::parser::AllowExprMetavar; use rustc_attr_parsing::{ - AttributeParser, CFG_TEMPLATE, Early, EvalConfigResult, ShouldEmit, eval_config_entry, - parse_cfg, validate_attr, + AttributeParser, CFG_TEMPLATE, EvalConfigResult, ShouldEmit, eval_config_entry, parse_cfg, + validate_attr, }; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -30,7 +30,7 @@ RecoverColon, RecoverComma, Recovery, token_descr, }; use rustc_session::Session; -use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS}; +use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS; use rustc_session::parse::feature_err; use rustc_span::hygiene::SyntaxContext; use rustc_span::{ErrorGuaranteed, FileName, Ident, LocalExpnId, Span, Symbol, sym}; @@ -2274,21 +2274,6 @@ fn check_attributes(&self, attrs: &[ast::Attribute], call: &ast::MacCall) { self.cx.current_expansion.lint_node_id, crate::errors::MacroCallUnusedDocComment { span: attr.span }, ); - } else if rustc_attr_parsing::is_builtin_attr(attr) - && !AttributeParser::::is_parsed_attribute(&attr.path()) - { - let attr_name = attr.name().unwrap(); - self.cx.sess.psess.buffer_lint( - UNUSED_ATTRIBUTES, - attr.span, - self.cx.current_expansion.lint_node_id, - crate::errors::UnusedBuiltinAttribute { - attr_name, - macro_name: pprust::path_to_string(&call.path), - invoc_span: call.path.span, - attr_span: attr.span, - }, - ); } } } diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index 79ab3cab22ce..803803ec3f6c 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -2,12 +2,14 @@ use std::path::{self, Path, PathBuf}; use rustc_ast::{AttrVec, Attribute, Inline, Item, ModSpans}; -use rustc_attr_parsing::validate_attr; +use rustc_attr_parsing::validate_attr::emit_malformed_attribute; use rustc_errors::{Diag, ErrorGuaranteed}; +use rustc_feature::template; use rustc_parse::lexer::StripTokens; use rustc_parse::{exp, new_parser_from_file, unwrap_or_emit_fatal}; use rustc_session::Session; use rustc_session::parse::ParseSess; +use rustc_span::fatal_error::FatalError; use rustc_span::{Ident, Span, sym}; use thin_vec::ThinVec; @@ -184,6 +186,7 @@ pub(crate) fn mod_file_path_from_attr( attrs: &[Attribute], dir_path: &Path, ) -> Option { + // FIXME(154781) use a parsed attribute here // Extract path string from first `#[path = "path_string"]` attribute. let first_path = attrs.iter().find(|at| at.has_name(sym::path))?; let Some(path_sym) = first_path.value_str() else { @@ -195,7 +198,17 @@ pub(crate) fn mod_file_path_from_attr( // Usually bad forms are checked during semantic analysis via // `TyCtxt::check_mod_attrs`), but by the time that runs the macro // is expanded, and it doesn't give an error. - validate_attr::emit_fatal_malformed_builtin_attribute(&sess.psess, first_path, sym::path); + emit_malformed_attribute( + &sess.psess, + first_path.style, + first_path.span, + sym::path, + template!( + NameValueStr: "file", + "https://doc.rust-lang.org/reference/items/modules.html#the-path-attribute" + ), + ); + FatalError.raise() }; let path_str = path_sym.as_str(); diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index acbcba90fbcc..b8b9226cc602 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -2,12 +2,9 @@ use std::sync::LazyLock; -use AttributeDuplicates::*; use AttributeGate::*; -use AttributeType::*; use rustc_data_structures::fx::FxHashMap; use rustc_hir::AttrStyle; -use rustc_hir::attrs::EncodeCrossCrate; use rustc_span::edition::Edition; use rustc_span::{Symbol, sym}; @@ -73,21 +70,10 @@ pub fn find_gated_cfg(pred: impl Fn(Symbol) -> bool) -> Option<&'static GatedCfg // move that documentation into the relevant place in the other docs, and // remove the chapter on the flag. -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum AttributeType { - /// Normal, builtin attribute that is consumed - /// by the compiler before the unused_attribute check - Normal, - - /// Builtin attribute that is only allowed at the crate level - CrateLevel, -} - #[derive(Copy, Clone, PartialEq, Debug)] pub enum AttributeSafety { /// Normal attribute that does not need `#[unsafe(...)]` Normal, - /// Unsafe attribute that requires safety obligations to be discharged. /// /// An error is emitted when `#[unsafe(...)]` is omitted, except when the attribute's edition @@ -181,57 +167,6 @@ pub fn suggestions( } } -/// How to handle multiple duplicate attributes on the same item. -#[derive(Clone, Copy, Default)] -pub enum AttributeDuplicates { - /// Duplicates of this attribute are allowed. - /// - /// This should only be used with attributes where duplicates have semantic - /// meaning, or some kind of "additive" behavior. For example, `#[warn(..)]` - /// can be specified multiple times, and it combines all the entries. Or use - /// this if there is validation done elsewhere. - #[default] - DuplicatesOk, - /// Duplicates after the first attribute will be an unused_attribute warning. - /// - /// This is usually used for "word" attributes, where they are used as a - /// boolean marker, like `#[used]`. It is not necessarily wrong that there - /// are duplicates, but the others should probably be removed. - WarnFollowing, - /// Same as `WarnFollowing`, but only issues warnings for word-style attributes. - /// - /// This is only for special cases, for example multiple `#[macro_use]` can - /// be warned, but multiple `#[macro_use(...)]` should not because the list - /// form has different meaning from the word form. - WarnFollowingWordOnly, - /// Duplicates after the first attribute will be an error. - /// - /// This should be used where duplicates would be ignored, but carry extra - /// meaning that could cause confusion. For example, `#[stable(since="1.0")] - /// #[stable(since="2.0")]`, which version should be used for `stable`? - ErrorFollowing, - /// Duplicates preceding the last instance of the attribute will be an error. - /// - /// This is the same as `ErrorFollowing`, except the last attribute is the - /// one that is "used". This is typically used in cases like codegen - /// attributes which usually only honor the last attribute. - ErrorPreceding, - /// Duplicates after the first attribute will be an unused_attribute warning - /// with a note that this will be an error in the future. - /// - /// This should be used for attributes that should be `ErrorFollowing`, but - /// because older versions of rustc silently accepted (and ignored) the - /// attributes, this is used to transition. - FutureWarnFollowing, - /// Duplicates preceding the last instance of the attribute will be a - /// warning, with a note that this will be an error in the future. - /// - /// This is the same as `FutureWarnFollowing`, except the last attribute is - /// the one that is "used". Ideally these can eventually migrate to - /// `ErrorPreceding`. - FutureWarnPreceding, -} - /// A convenience macro for constructing attribute templates. /// E.g., `template!(Word, List: "description")` means that the attribute /// supports forms `#[attr]` and `#[attr(description)]`. @@ -268,50 +203,31 @@ macro_rules! template { } macro_rules! ungated { - (unsafe($edition:ident) $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr $(,)?) => { + (unsafe($edition:ident) $attr:ident $(,)?) => { BuiltinAttribute { name: sym::$attr, - encode_cross_crate: $encode_cross_crate, - type_: $typ, safety: AttributeSafety::Unsafe { unsafe_since: Some(Edition::$edition) }, - template: $tpl, gate: Ungated, - duplicates: $duplicates, } }; - (unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr $(,)?) => { + (unsafe $attr:ident $(,)?) => { BuiltinAttribute { name: sym::$attr, - encode_cross_crate: $encode_cross_crate, - type_: $typ, safety: AttributeSafety::Unsafe { unsafe_since: None }, - template: $tpl, gate: Ungated, - duplicates: $duplicates, } }; - ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr $(,)?) => { - BuiltinAttribute { - name: sym::$attr, - encode_cross_crate: $encode_cross_crate, - type_: $typ, - safety: AttributeSafety::Normal, - template: $tpl, - gate: Ungated, - duplicates: $duplicates, - } + ($attr:ident $(,)?) => { + BuiltinAttribute { name: sym::$attr, safety: AttributeSafety::Normal, gate: Ungated } }; } macro_rules! gated { - (unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $gate:ident, $message:expr $(,)?) => { + (unsafe $attr:ident, $gate:ident, $message:expr $(,)?) => { BuiltinAttribute { name: sym::$attr, - encode_cross_crate: $encode_cross_crate, - type_: $typ, safety: AttributeSafety::Unsafe { unsafe_since: None }, - template: $tpl, - duplicates: $duplicates, + gate: Gated { feature: sym::$gate, message: $message, @@ -320,14 +236,11 @@ macro_rules! gated { }, } }; - (unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $message:expr $(,)?) => { + (unsafe $attr:ident, $message:expr $(,)?) => { BuiltinAttribute { name: sym::$attr, - encode_cross_crate: $encode_cross_crate, - type_: $typ, safety: AttributeSafety::Unsafe { unsafe_since: None }, - template: $tpl, - duplicates: $duplicates, + gate: Gated { feature: sym::$attr, message: $message, @@ -336,14 +249,11 @@ macro_rules! gated { }, } }; - ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $gate:ident, $message:expr $(,)?) => { + ($attr:ident, $gate:ident, $message:expr $(,)?) => { BuiltinAttribute { name: sym::$attr, - encode_cross_crate: $encode_cross_crate, - type_: $typ, safety: AttributeSafety::Normal, - template: $tpl, - duplicates: $duplicates, + gate: Gated { feature: sym::$gate, message: $message, @@ -352,14 +262,11 @@ macro_rules! gated { }, } }; - ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $message:expr $(,)?) => { + ($attr:ident, $message:expr $(,)?) => { BuiltinAttribute { name: sym::$attr, - encode_cross_crate: $encode_cross_crate, - type_: $typ, safety: AttributeSafety::Normal, - template: $tpl, - duplicates: $duplicates, + gate: Gated { feature: sym::$attr, message: $message, @@ -371,13 +278,8 @@ macro_rules! gated { } macro_rules! rustc_attr { - (TEST, $attr:ident, $typ:expr, $tpl:expr, $duplicate:expr, $encode_cross_crate:expr $(,)?) => { - rustc_attr!( - $attr, - $typ, - $tpl, - $duplicate, - $encode_cross_crate, + (TEST, $attr:ident $(,)?) => { + rustc_attr!( $attr, concat!( "the `#[", stringify!($attr), @@ -385,14 +287,10 @@ macro_rules! rustc_attr { ), ) }; - ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $($notes:expr),* $(,)?) => { + ($attr:ident $(, $notes:expr)* $(,)?) => { BuiltinAttribute { name: sym::$attr, - encode_cross_crate: $encode_cross_crate, - type_: $typ, safety: AttributeSafety::Normal, - template: $tpl, - duplicates: $duplicates, gate: Gated { feature: sym::rustc_attrs, message: "use of an internal attribute", @@ -416,15 +314,7 @@ macro_rules! experimental { pub struct BuiltinAttribute { pub name: Symbol, - /// Whether this attribute is encode cross crate. - /// - /// If so, it is encoded in the crate metadata. - /// Otherwise, it can only be used in the local crate. - pub encode_cross_crate: EncodeCrossCrate, - pub type_: AttributeType, pub safety: AttributeSafety, - pub template: AttributeTemplate, - pub duplicates: AttributeDuplicates, pub gate: AttributeGate, } @@ -436,379 +326,100 @@ pub struct BuiltinAttribute { // ========================================================================== // Conditional compilation: - ungated!( - cfg, Normal, - template!( - List: &["predicate"], - "https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute" - ), - DuplicatesOk, EncodeCrossCrate::No - ), - ungated!( - cfg_attr, Normal, - template!( - List: &["predicate, attr1, attr2, ..."], - "https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute" - ), - DuplicatesOk, EncodeCrossCrate::No - ), + ungated!(cfg), + ungated!(cfg_attr), // Testing: - ungated!( - ignore, Normal, - template!( - Word, - NameValueStr: "reason", - "https://doc.rust-lang.org/reference/attributes/testing.html#the-ignore-attribute" - ), - WarnFollowing, EncodeCrossCrate::No, - ), - ungated!( - should_panic, Normal, - template!( - Word, - List: &[r#"expected = "reason""#], - NameValueStr: "reason", - "https://doc.rust-lang.org/reference/attributes/testing.html#the-should_panic-attribute" - ), - FutureWarnFollowing, EncodeCrossCrate::No, - ), + ungated!(ignore), + ungated!(should_panic), // Macros: - ungated!( - automatically_derived, Normal, - template!( - Word, - "https://doc.rust-lang.org/reference/attributes/derive.html#the-automatically_derived-attribute" - ), - WarnFollowing, EncodeCrossCrate::Yes - ), - ungated!( - macro_use, Normal, - template!( - Word, - List: &["name1, name2, ..."], - "https://doc.rust-lang.org/reference/macros-by-example.html#the-macro_use-attribute" - ), - WarnFollowingWordOnly, EncodeCrossCrate::No, - ), - ungated!(macro_escape, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No), // Deprecated synonym for `macro_use`. - ungated!( - macro_export, Normal, - template!( - Word, - List: &["local_inner_macros"], - "https://doc.rust-lang.org/reference/macros-by-example.html#path-based-scope" - ), - WarnFollowing, EncodeCrossCrate::Yes - ), - ungated!( - proc_macro, Normal, - template!( - Word, - "https://doc.rust-lang.org/reference/procedural-macros.html#function-like-procedural-macros"), - ErrorFollowing, EncodeCrossCrate::No - ), - ungated!( - proc_macro_derive, Normal, - template!( - List: &["TraitName", "TraitName, attributes(name1, name2, ...)"], - "https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros" - ), - ErrorFollowing, EncodeCrossCrate::No, - ), - ungated!( - proc_macro_attribute, Normal, - template!(Word, "https://doc.rust-lang.org/reference/procedural-macros.html#attribute-macros"), - ErrorFollowing, EncodeCrossCrate::No - ), + ungated!(automatically_derived), + ungated!(macro_use), + ungated!(macro_escape), // Deprecated synonym for `macro_use`. + ungated!(macro_export), + ungated!(proc_macro), + ungated!(proc_macro_derive), + ungated!(proc_macro_attribute), // Lints: - ungated!( - warn, Normal, - template!( - List: &["lint1", "lint1, lint2, ...", r#"lint1, lint2, lint3, reason = "...""#], - "https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes" - ), - DuplicatesOk, EncodeCrossCrate::No, - ), - ungated!( - allow, Normal, - template!( - List: &["lint1", "lint1, lint2, ...", r#"lint1, lint2, lint3, reason = "...""#], - "https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes" - ), - DuplicatesOk, EncodeCrossCrate::No, - ), - ungated!( - expect, Normal, - template!( - List: &["lint1", "lint1, lint2, ...", r#"lint1, lint2, lint3, reason = "...""#], - "https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes" - ), - DuplicatesOk, EncodeCrossCrate::No, - ), - ungated!( - forbid, Normal, - template!( - List: &["lint1", "lint1, lint2, ...", r#"lint1, lint2, lint3, reason = "...""#], - "https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes" - ), - DuplicatesOk, EncodeCrossCrate::No - ), - ungated!( - deny, Normal, - template!( - List: &["lint1", "lint1, lint2, ...", r#"lint1, lint2, lint3, reason = "...""#], - "https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes" - ), - DuplicatesOk, EncodeCrossCrate::No - ), - ungated!( - must_use, Normal, - template!( - Word, - NameValueStr: "reason", - "https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute" - ), - FutureWarnFollowing, EncodeCrossCrate::Yes - ), - gated!( - must_not_suspend, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing, - EncodeCrossCrate::Yes, experimental!(must_not_suspend) - ), - ungated!( - deprecated, Normal, - template!( - Word, - List: &[r#"/*opt*/ since = "version", /*opt*/ note = "reason""#], - NameValueStr: "reason", - "https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-deprecated-attribute" - ), - ErrorFollowing, EncodeCrossCrate::Yes - ), + ungated!(warn), + ungated!(allow), + ungated!(expect), + ungated!(forbid), + ungated!(deny), + ungated!(must_use), + gated!(must_not_suspend, experimental!(must_not_suspend)), + ungated!(deprecated), // Crate properties: - ungated!( - crate_name, CrateLevel, - template!( - NameValueStr: "name", - "https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute" - ), - FutureWarnFollowing, EncodeCrossCrate::No, - ), - ungated!( - crate_type, CrateLevel, - template!( - NameValueStr: ["bin", "lib", "dylib", "cdylib", "rlib", "staticlib", "sdylib", "proc-macro"], - "https://doc.rust-lang.org/reference/linkage.html" - ), - DuplicatesOk, EncodeCrossCrate::No, - ), + ungated!(crate_name), + ungated!(crate_type), // ABI, linking, symbols, and FFI - ungated!( - link, Normal, - template!(List: &[ - r#"name = "...""#, - r#"name = "...", kind = "dylib|static|...""#, - r#"name = "...", wasm_import_module = "...""#, - r#"name = "...", import_name_type = "decorated|noprefix|undecorated""#, - r#"name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated""#, - ], "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute"), - DuplicatesOk, EncodeCrossCrate::No, - ), - ungated!( - link_name, Normal, - template!(NameValueStr: "name", "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_name-attribute"), - FutureWarnPreceding, EncodeCrossCrate::Yes - ), - ungated!( - no_link, Normal, - template!(Word, "https://doc.rust-lang.org/reference/items/extern-crates.html#the-no_link-attribute"), - WarnFollowing, EncodeCrossCrate::No - ), - ungated!( - repr, Normal, - template!( - List: &["C", "Rust", "transparent", "align(...)", "packed(...)", ""], - "https://doc.rust-lang.org/reference/type-layout.html#representations" - ), - DuplicatesOk, EncodeCrossCrate::No - ), + ungated!(link), + ungated!(link_name), + ungated!(no_link), + ungated!(repr), // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity - gated!(rustc_align, Normal, template!(List: &["alignment"]), DuplicatesOk, EncodeCrossCrate::No, fn_align, experimental!(rustc_align)), - gated!(rustc_align_static, Normal, template!(List: &["alignment"]), DuplicatesOk, EncodeCrossCrate::No, static_align, experimental!(rustc_align_static)), - ungated!( - unsafe(Edition2024) export_name, Normal, - template!(NameValueStr: "name", "https://doc.rust-lang.org/reference/abi.html#the-export_name-attribute"), - FutureWarnPreceding, EncodeCrossCrate::No - ), - ungated!( - unsafe(Edition2024) link_section, Normal, - template!(NameValueStr: "name", "https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute"), - FutureWarnPreceding, EncodeCrossCrate::No - ), - ungated!( - unsafe(Edition2024) no_mangle, Normal, - template!(Word, "https://doc.rust-lang.org/reference/abi.html#the-no_mangle-attribute"), - WarnFollowing, EncodeCrossCrate::No - ), - ungated!( - used, Normal, - template!(Word, List: &["compiler", "linker"], "https://doc.rust-lang.org/reference/abi.html#the-used-attribute"), - WarnFollowing, EncodeCrossCrate::No - ), - ungated!( - link_ordinal, Normal, - template!(List: &["ordinal"], "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute"), - ErrorPreceding, EncodeCrossCrate::Yes - ), - ungated!( - unsafe naked, Normal, - template!(Word, "https://doc.rust-lang.org/reference/attributes/codegen.html#the-naked-attribute"), - WarnFollowing, EncodeCrossCrate::No - ), + gated!(rustc_align,fn_align, experimental!(rustc_align)), + gated!(rustc_align_static,static_align, experimental!(rustc_align_static)), + ungated!(unsafe(Edition2024) export_name), + ungated!(unsafe(Edition2024) link_section), + ungated!(unsafe(Edition2024) no_mangle), + ungated!(used), + ungated!(link_ordinal), + ungated!(unsafe naked), // See `TyAndLayout::pass_indirectly_in_non_rustic_abis` for details. - rustc_attr!( - rustc_pass_indirectly_in_non_rustic_abis, Normal, template!(Word), ErrorFollowing, - EncodeCrossCrate::No, - "types marked with `#[rustc_pass_indirectly_in_non_rustic_abis]` are always passed indirectly by non-Rustic ABIs" - ), + rustc_attr!(rustc_pass_indirectly_in_non_rustic_abis, "types marked with `#[rustc_pass_indirectly_in_non_rustic_abis]` are always passed indirectly by non-Rustic ABIs"), // Limits: - ungated!( - recursion_limit, CrateLevel, - template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute"), - FutureWarnFollowing, EncodeCrossCrate::No - ), - ungated!( - type_length_limit, CrateLevel, - template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-type_length_limit-attribute"), - FutureWarnFollowing, EncodeCrossCrate::No - ), + ungated!(recursion_limit), + ungated!(type_length_limit), gated!( - move_size_limit, CrateLevel, template!(NameValueStr: "N"), ErrorFollowing, - EncodeCrossCrate::No, large_assignments, experimental!(move_size_limit) + move_size_limit, large_assignments, experimental!(move_size_limit) ), // Entry point: - ungated!( - no_main, CrateLevel, - template!(Word, "https://doc.rust-lang.org/reference/crates-and-source-files.html#the-no_main-attribute"), - WarnFollowing, EncodeCrossCrate::No - ), + ungated!(no_main), // Modules, prelude, and resolution: - ungated!( - path, Normal, - template!(NameValueStr: "file", "https://doc.rust-lang.org/reference/items/modules.html#the-path-attribute"), - FutureWarnFollowing, EncodeCrossCrate::No - ), - ungated!( - no_std, CrateLevel, - template!(Word, "https://doc.rust-lang.org/reference/names/preludes.html#the-no_std-attribute"), - WarnFollowing, EncodeCrossCrate::No - ), - ungated!( - no_implicit_prelude, Normal, - template!(Word, "https://doc.rust-lang.org/reference/names/preludes.html#the-no_implicit_prelude-attribute"), - WarnFollowing, EncodeCrossCrate::No - ), - ungated!( - non_exhaustive, Normal, - template!(Word, "https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute"), - WarnFollowing, EncodeCrossCrate::Yes - ), + ungated!(path), + ungated!(no_std), + ungated!(no_implicit_prelude), + ungated!(non_exhaustive), // Runtime - ungated!( - windows_subsystem, CrateLevel, - template!(NameValueStr: ["windows", "console"], "https://doc.rust-lang.org/reference/runtime.html#the-windows_subsystem-attribute"), - FutureWarnFollowing, EncodeCrossCrate::No - ), - ungated!( // RFC 2070 - panic_handler, Normal, - template!(Word, "https://doc.rust-lang.org/reference/panic.html#the-panic_handler-attribute"), - WarnFollowing, EncodeCrossCrate::Yes + ungated!(windows_subsystem), + ungated!(// RFC 2070 + panic_handler ), // Code generation: - ungated!( - inline, Normal, - template!( - Word, - List: &["always", "never"], - "https://doc.rust-lang.org/reference/attributes/codegen.html#the-inline-attribute" - ), - FutureWarnFollowing, EncodeCrossCrate::No - ), - ungated!( - cold, Normal, - template!(Word, "https://doc.rust-lang.org/reference/attributes/codegen.html#the-cold-attribute"), - WarnFollowing, EncodeCrossCrate::No - ), - ungated!( - no_builtins, CrateLevel, - template!(Word, "https://doc.rust-lang.org/reference/attributes/codegen.html#the-no_builtins-attribute"), - WarnFollowing, EncodeCrossCrate::Yes - ), - ungated!( - target_feature, Normal, - template!(List: &[r#"enable = "name""#], "https://doc.rust-lang.org/reference/attributes/codegen.html#the-target_feature-attribute"), - DuplicatesOk, EncodeCrossCrate::No, - ), - ungated!( - track_caller, Normal, - template!(Word, "https://doc.rust-lang.org/reference/attributes/codegen.html#the-track_caller-attribute"), - WarnFollowing, EncodeCrossCrate::Yes - ), - ungated!( - instruction_set, Normal, - template!(List: &["set"], "https://doc.rust-lang.org/reference/attributes/codegen.html#the-instruction_set-attribute"), - ErrorPreceding, EncodeCrossCrate::No + ungated!(inline), + ungated!(cold), + ungated!(no_builtins), + ungated!(target_feature), + ungated!(track_caller), + ungated!(instruction_set), + gated!( + unsafe force_target_feature, + effective_target_features, experimental!(force_target_feature) ), gated!( - unsafe force_target_feature, Normal, template!(List: &[r#"enable = "name""#]), - DuplicatesOk, EncodeCrossCrate::No, effective_target_features, experimental!(force_target_feature) + sanitize, + sanitize, experimental!(sanitize) ), gated!( - sanitize, Normal, template!(List: &[r#"address = "on|off""#, r#"kernel_address = "on|off""#, r#"cfi = "on|off""#, r#"hwaddress = "on|off""#, r#"kernel_hwaddress = "on|off""#, r#"kcfi = "on|off""#, r#"memory = "on|off""#, r#"memtag = "on|off""#, r#"shadow_call_stack = "on|off""#, r#"thread = "on|off""#]), ErrorPreceding, - EncodeCrossCrate::No, sanitize, experimental!(sanitize), - ), - gated!( - coverage, Normal, template!(OneOf: &[sym::off, sym::on]), - ErrorPreceding, EncodeCrossCrate::No, + coverage, coverage_attribute, experimental!(coverage) ), - ungated!( - doc, Normal, - template!( - List: &["hidden", "inline"], - NameValueStr: "string", - "https://doc.rust-lang.org/rustdoc/write-documentation/the-doc-attribute.html" - ), - DuplicatesOk, EncodeCrossCrate::Yes - ), + ungated!(doc), // Debugging - ungated!( - debugger_visualizer, Normal, - template!( - List: &[r#"natvis_file = "...", gdb_script_file = "...""#], - "https://doc.rust-lang.org/reference/attributes/debugger.html#the-debugger_visualizer-attribute" - ), - DuplicatesOk, EncodeCrossCrate::No - ), - ungated!( - collapse_debuginfo, Normal, - template!( - List: &["no", "external", "yes"], - "https://doc.rust-lang.org/reference/attributes/debugger.html#the-collapse_debuginfo-attribute" - ), - ErrorFollowing, EncodeCrossCrate::Yes - ), + ungated!(debugger_visualizer), + ungated!(collapse_debuginfo), // ========================================================================== // Unstable attributes: @@ -816,71 +427,61 @@ pub struct BuiltinAttribute { // Linking: gated!( - export_stable, Normal, template!(Word), WarnFollowing, - EncodeCrossCrate::No, experimental!(export_stable) + export_stable, experimental!(export_stable) ), // Testing: gated!( - test_runner, CrateLevel, template!(List: &["path"]), ErrorFollowing, - EncodeCrossCrate::Yes, custom_test_frameworks, - "custom test frameworks are an unstable feature", + test_runner, custom_test_frameworks, + "custom test frameworks are an unstable feature" ), gated!( - reexport_test_harness_main, CrateLevel, template!(NameValueStr: "name"), ErrorFollowing, - EncodeCrossCrate::No, custom_test_frameworks, - "custom test frameworks are an unstable feature", + reexport_test_harness_main, custom_test_frameworks, + "custom test frameworks are an unstable feature" ), // RFC #1268 gated!( - marker, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, - marker_trait_attr, experimental!(marker) + marker,marker_trait_attr, experimental!(marker) ), gated!( - thread_local, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, - "`#[thread_local]` is an experimental feature, and does not currently handle destructors", + thread_local,"`#[thread_local]` is an experimental feature, and does not currently handle destructors" ), gated!( - no_core, CrateLevel, template!(Word), WarnFollowing, - EncodeCrossCrate::No, experimental!(no_core) + no_core, experimental!(no_core) ), // RFC 2412 gated!( - optimize, Normal, template!(List: &["none", "size", "speed"]), ErrorPreceding, - EncodeCrossCrate::No, optimize_attribute, experimental!(optimize) + optimize, + optimize_attribute, experimental!(optimize) ), gated!( - unsafe ffi_pure, Normal, template!(Word), WarnFollowing, - EncodeCrossCrate::No, experimental!(ffi_pure) + unsafe ffi_pure, experimental!(ffi_pure) ), gated!( - unsafe ffi_const, Normal, template!(Word), WarnFollowing, - EncodeCrossCrate::No, experimental!(ffi_const) + unsafe ffi_const, experimental!(ffi_const) ), gated!( - register_tool, CrateLevel, template!(List: &["tool1, tool2, ..."]), DuplicatesOk, - EncodeCrossCrate::No, experimental!(register_tool), + register_tool, experimental!(register_tool) ), // `#[cfi_encoding = ""]` gated!( - cfi_encoding, Normal, template!(NameValueStr: "encoding"), ErrorPreceding, - EncodeCrossCrate::Yes, experimental!(cfi_encoding) + cfi_encoding, + experimental!(cfi_encoding) ), // `#[coroutine]` attribute to be applied to closures to make them coroutines instead gated!( - coroutine, Normal, template!(Word), ErrorFollowing, - EncodeCrossCrate::No, coroutines, experimental!(coroutine) + coroutine,coroutines, experimental!(coroutine) ), // RFC 3543 // `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]` gated!( - patchable_function_entry, Normal, template!(List: &["prefix_nops = m, entry_nops = n"]), ErrorPreceding, - EncodeCrossCrate::Yes, experimental!(patchable_function_entry) + patchable_function_entry, + experimental!(patchable_function_entry) ), // The `#[loop_match]` and `#[const_continue]` attributes are part of the @@ -888,12 +489,10 @@ pub struct BuiltinAttribute { // // - https://github.com/rust-lang/rust/issues/132306 gated!( - const_continue, Normal, template!(Word), ErrorFollowing, - EncodeCrossCrate::No, loop_match, experimental!(const_continue) + const_continue,loop_match, experimental!(const_continue) ), gated!( - loop_match, Normal, template!(Word), ErrorFollowing, - EncodeCrossCrate::No, loop_match, experimental!(loop_match) + loop_match,loop_match, experimental!(loop_match) ), // The `#[pin_v2]` attribute is part of the `pin_ergonomics` experiment @@ -901,74 +500,40 @@ pub struct BuiltinAttribute { // // - https://github.com/rust-lang/rust/issues/130494 gated!( - pin_v2, Normal, template!(Word), ErrorFollowing, - EncodeCrossCrate::Yes, pin_ergonomics, experimental!(pin_v2), + pin_v2,pin_ergonomics, experimental!(pin_v2), ), // ========================================================================== // Internal attributes: Stability, deprecation, and unsafe: // ========================================================================== - ungated!( - feature, CrateLevel, - template!(List: &["name1, name2, ..."]), DuplicatesOk, EncodeCrossCrate::No, - ), + ungated!(feature), // DuplicatesOk since it has its own validation - ungated!( - stable, Normal, - template!(List: &[r#"feature = "name", since = "version""#]), DuplicatesOk, EncodeCrossCrate::No, - ), - ungated!( - unstable, Normal, - template!(List: &[r#"feature = "name", reason = "...", issue = "N""#]), DuplicatesOk, - EncodeCrossCrate::Yes - ), - ungated!( - unstable_feature_bound, Normal, template!(Word, List: &["feat1, feat2, ..."]), - DuplicatesOk, EncodeCrossCrate::No, - ), - ungated!( - rustc_const_unstable, Normal, template!(List: &[r#"feature = "name""#]), - DuplicatesOk, EncodeCrossCrate::Yes - ), - ungated!( - rustc_const_stable, Normal, - template!(List: &[r#"feature = "name""#]), DuplicatesOk, EncodeCrossCrate::No, - ), - ungated!( - rustc_default_body_unstable, Normal, - template!(List: &[r#"feature = "name", reason = "...", issue = "N""#]), - DuplicatesOk, EncodeCrossCrate::No - ), + ungated!(stable), + ungated!(unstable), + ungated!(unstable_feature_bound), + ungated!(rustc_const_unstable), + ungated!(rustc_const_stable), + ungated!(rustc_default_body_unstable), gated!( - allow_internal_unstable, Normal, template!(Word, List: &["feat1, feat2, ..."]), - DuplicatesOk, EncodeCrossCrate::Yes, + allow_internal_unstable, "allow_internal_unstable side-steps feature gating and stability checks", ), gated!( - allow_internal_unsafe, Normal, template!(Word), WarnFollowing, - EncodeCrossCrate::No, "allow_internal_unsafe side-steps the unsafe_code lint", + allow_internal_unsafe, "allow_internal_unsafe side-steps the unsafe_code lint", ), gated!( - rustc_eii_foreign_item, Normal, template!(Word), - ErrorFollowing, EncodeCrossCrate::Yes, eii_internals, + rustc_eii_foreign_item, + eii_internals, "used internally to mark types with a `transparent` representation when it is guaranteed by the documentation", ), - rustc_attr!( - rustc_allowed_through_unstable_modules, Normal, template!(NameValueStr: "deprecation message"), - WarnFollowing, EncodeCrossCrate::No, + rustc_attr!(rustc_allowed_through_unstable_modules, "rustc_allowed_through_unstable_modules special cases accidental stabilizations of stable items \ through unstable paths" ), - rustc_attr!( - rustc_deprecated_safe_2024, Normal, template!(List: &[r#"audit_that = "...""#]), - ErrorFollowing, EncodeCrossCrate::Yes, - "`#[rustc_deprecated_safe_2024]` is used to declare functions unsafe across the edition 2024 boundary", + rustc_attr!(rustc_deprecated_safe_2024,"`#[rustc_deprecated_safe_2024]` is used to declare functions unsafe across the edition 2024 boundary", ), - rustc_attr!( - rustc_pub_transparent, Normal, template!(Word), - ErrorFollowing, EncodeCrossCrate::Yes, - "used internally to mark types with a `transparent` representation when it is guaranteed by the documentation", + rustc_attr!(rustc_pub_transparent,"used internally to mark types with a `transparent` representation when it is guaranteed by the documentation", ), @@ -976,25 +541,13 @@ pub struct BuiltinAttribute { // Internal attributes: Type system related: // ========================================================================== - gated!(fundamental, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes, experimental!(fundamental)), + gated!(fundamental, experimental!(fundamental)), gated!( - may_dangle, Normal, template!(Word), WarnFollowing, - EncodeCrossCrate::No, dropck_eyepatch, - "`may_dangle` has unstable semantics and may be removed in the future", + may_dangle, dropck_eyepatch, + "`may_dangle` has unstable semantics and may be removed in the future" ), - rustc_attr!( - rustc_never_type_options, - Normal, - template!(List: &[ - "", - r#"fallback = "unit""#, - r#"fallback = "niko""#, - r#"fallback = "never""#, - r#"fallback = "no""#, - ]), - ErrorFollowing, - EncodeCrossCrate::No, + rustc_attr!(rustc_never_type_options, "`rustc_never_type_options` is used to experiment with never type fallback and work on \ never type stabilization" ), @@ -1003,57 +556,33 @@ pub struct BuiltinAttribute { // Internal attributes: Runtime related: // ========================================================================== - rustc_attr!( - rustc_allocator, Normal, template!(Word), WarnFollowing, - EncodeCrossCrate::No, - ), - rustc_attr!( - rustc_nounwind, Normal, template!(Word), WarnFollowing, - EncodeCrossCrate::No, - ), - rustc_attr!( - rustc_reallocator, Normal, template!(Word), WarnFollowing, - EncodeCrossCrate::No, - ), - rustc_attr!( - rustc_deallocator, Normal, template!(Word), WarnFollowing, - EncodeCrossCrate::No, - ), - rustc_attr!( - rustc_allocator_zeroed, Normal, template!(Word), WarnFollowing, - EncodeCrossCrate::No, - ), - rustc_attr!( - rustc_allocator_zeroed_variant, Normal, template!(NameValueStr: "function"), ErrorPreceding, - EncodeCrossCrate::Yes, + rustc_attr!(rustc_allocator), + rustc_attr!(rustc_nounwind), + rustc_attr!(rustc_reallocator), + rustc_attr!(rustc_deallocator), + rustc_attr!(rustc_allocator_zeroed), + rustc_attr!(rustc_allocator_zeroed_variant), + gated!( + default_lib_allocator, allocator_internals, experimental!(default_lib_allocator), ), gated!( - default_lib_allocator, Normal, template!(Word), WarnFollowing, - EncodeCrossCrate::No, allocator_internals, experimental!(default_lib_allocator), + needs_allocator, allocator_internals, experimental!(needs_allocator), ), gated!( - needs_allocator, Normal, template!(Word), WarnFollowing, - EncodeCrossCrate::No, allocator_internals, experimental!(needs_allocator), + panic_runtime, experimental!(panic_runtime) ), gated!( - panic_runtime, CrateLevel, template!(Word), WarnFollowing, - EncodeCrossCrate::No, experimental!(panic_runtime) + needs_panic_runtime, experimental!(needs_panic_runtime) ), gated!( - needs_panic_runtime, CrateLevel, template!(Word), WarnFollowing, - EncodeCrossCrate::No, experimental!(needs_panic_runtime) - ), - gated!( - compiler_builtins, CrateLevel, template!(Word), WarnFollowing, - EncodeCrossCrate::No, + compiler_builtins, "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \ - which contains compiler-rt intrinsics and will never be stable", + which contains compiler-rt intrinsics and will never be stable" ), gated!( - profiler_runtime, CrateLevel, template!(Word), WarnFollowing, - EncodeCrossCrate::No, + profiler_runtime, "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \ - which contains the profiler runtime and will never be stable", + which contains the profiler runtime and will never be stable" ), // ========================================================================== @@ -1061,277 +590,123 @@ pub struct BuiltinAttribute { // ========================================================================== gated!( - linkage, Normal, template!(NameValueStr: [ - "available_externally", - "common", - "extern_weak", - "external", - "internal", - "linkonce", - "linkonce_odr", - "weak", - "weak_odr", - ], "https://doc.rust-lang.org/reference/linkage.html"), - ErrorPreceding, EncodeCrossCrate::No, - "the `linkage` attribute is experimental and not portable across platforms", - ), - rustc_attr!( - rustc_std_internal_symbol, Normal, template!(Word), WarnFollowing, - EncodeCrossCrate::No, - ), - rustc_attr!( - rustc_objc_class, Normal, template!(NameValueStr: "ClassName"), ErrorPreceding, - EncodeCrossCrate::No, - ), - rustc_attr!( - rustc_objc_selector, Normal, template!(NameValueStr: "methodName"), ErrorPreceding, - EncodeCrossCrate::No, + linkage, + "the `linkage` attribute is experimental and not portable across platforms" ), + rustc_attr!(rustc_std_internal_symbol), + rustc_attr!(rustc_objc_class), + rustc_attr!(rustc_objc_selector), // ========================================================================== // Internal attributes, Macro related: // ========================================================================== - rustc_attr!( - rustc_builtin_macro, Normal, - template!(Word, List: &["name", "name, /*opt*/ attributes(name1, name2, ...)"]), ErrorFollowing, - EncodeCrossCrate::Yes, - ), - rustc_attr!( - rustc_proc_macro_decls, Normal, template!(Word), WarnFollowing, - EncodeCrossCrate::No, - ), - rustc_attr!( - rustc_macro_transparency, Normal, - template!(NameValueStr: ["transparent", "semiopaque", "opaque"]), ErrorFollowing, - EncodeCrossCrate::Yes, "used internally for testing macro hygiene", - ), - rustc_attr!( - rustc_autodiff, Normal, - template!(Word, List: &[r#""...""#]), DuplicatesOk, - EncodeCrossCrate::Yes, - ), - rustc_attr!( - rustc_offload_kernel, Normal, - template!(Word), DuplicatesOk, - EncodeCrossCrate::Yes, + rustc_attr!(rustc_builtin_macro), + rustc_attr!(rustc_proc_macro_decls), + rustc_attr!(rustc_macro_transparency, + "used internally for testing macro hygiene" ), + rustc_attr!(rustc_autodiff), + rustc_attr!(rustc_offload_kernel), // Traces that are left when `cfg` and `cfg_attr` attributes are expanded. // The attributes are not gated, to avoid stability errors, but they cannot be used in stable // or unstable code directly because `sym::cfg_(attr_)trace` are not valid identifiers, they // can only be generated by the compiler. - ungated!( - cfg_trace, Normal, template!(Word /* irrelevant */), DuplicatesOk, - EncodeCrossCrate::Yes + ungated!(cfg_trace ), - ungated!( - cfg_attr_trace, Normal, template!(Word /* irrelevant */), DuplicatesOk, - EncodeCrossCrate::No + ungated!(cfg_attr_trace ), // ========================================================================== // Internal attributes, Diagnostics related: // ========================================================================== - rustc_attr!( - rustc_on_unimplemented, Normal, - template!( - List: &[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#], - NameValueStr: "message" - ), - ErrorFollowing, EncodeCrossCrate::Yes, - "see `#[diagnostic::on_unimplemented]` for the stable equivalent of this attribute" - ), - rustc_attr!( - rustc_confusables, Normal, - template!(List: &[r#""name1", "name2", ..."#]), - ErrorFollowing, EncodeCrossCrate::Yes, + rustc_attr!(rustc_on_unimplemented,"see `#[diagnostic::on_unimplemented]` for the stable equivalent of this attribute" ), + rustc_attr!(rustc_confusables), // Enumerates "identity-like" conversion methods to suggest on type mismatch. - rustc_attr!( - rustc_conversion_suggestion, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::Yes, - ), + rustc_attr!(rustc_conversion_suggestion), // Prevents field reads in the marked trait or method to be considered // during dead code analysis. - rustc_attr!( - rustc_trivial_field_reads, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::Yes, - ), + rustc_attr!(rustc_trivial_field_reads), // Used by the `rustc::potential_query_instability` lint to warn methods which // might not be stable during incremental compilation. - rustc_attr!( - rustc_lint_query_instability, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::Yes, - ), + rustc_attr!(rustc_lint_query_instability), // Used by the `rustc::untracked_query_information` lint to warn methods which // might not be stable during incremental compilation. - rustc_attr!( - rustc_lint_untracked_query_information, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::Yes, - ), + rustc_attr!(rustc_lint_untracked_query_information), // Used by the `rustc::bad_opt_access` lint to identify `DebuggingOptions` and `CodegenOptions` // types (as well as any others in future). - rustc_attr!( - rustc_lint_opt_ty, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::Yes, - ), + rustc_attr!(rustc_lint_opt_ty), // Used by the `rustc::bad_opt_access` lint on fields // types (as well as any others in future). - rustc_attr!( - rustc_lint_opt_deny_field_access, Normal, template!(List: &["message"]), - WarnFollowing, EncodeCrossCrate::Yes, - ), + rustc_attr!(rustc_lint_opt_deny_field_access), // ========================================================================== // Internal attributes, Const related: // ========================================================================== - rustc_attr!( - rustc_promotable, Normal, template!(Word), WarnFollowing, - EncodeCrossCrate::No, ), - rustc_attr!( - rustc_legacy_const_generics, Normal, template!(List: &["N"]), ErrorFollowing, - EncodeCrossCrate::Yes, - ), + rustc_attr!(rustc_promotable), + rustc_attr!(rustc_legacy_const_generics), // Do not const-check this function's body. It will always get replaced during CTFE via `hook_special_const_fn`. - rustc_attr!( - rustc_do_not_const_check, Normal, template!(Word), WarnFollowing, - EncodeCrossCrate::Yes, "`#[rustc_do_not_const_check]` skips const-check for this function's body", - ), - rustc_attr!( - rustc_const_stable_indirect, Normal, - template!(Word), - WarnFollowing, - EncodeCrossCrate::No, - "this is an internal implementation detail", - ), - rustc_attr!( - rustc_intrinsic_const_stable_indirect, Normal, - template!(Word), WarnFollowing, EncodeCrossCrate::No, "this is an internal implementation detail", - ), - rustc_attr!( - rustc_allow_const_fn_unstable, Normal, - template!(Word, List: &["feat1, feat2, ..."]), DuplicatesOk, EncodeCrossCrate::No, - "rustc_allow_const_fn_unstable side-steps feature gating and stability checks" + rustc_attr!(rustc_do_not_const_check, "`#[rustc_do_not_const_check]` skips const-check for this function's body"), + rustc_attr!(rustc_const_stable_indirect, + "this is an internal implementation detail"), + rustc_attr!(rustc_intrinsic_const_stable_indirect, + "this is an internal implementation detail"), + rustc_attr!(rustc_allow_const_fn_unstable, + "rustc_allow_const_fn_unstable side-steps feature gating and stability checks" ), // ========================================================================== // Internal attributes, Layout related: // ========================================================================== - rustc_attr!( - rustc_layout_scalar_valid_range_start, Normal, template!(List: &["value"]), ErrorFollowing, - EncodeCrossCrate::Yes, - "the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \ - niche optimizations in the standard library", - ), - rustc_attr!( - rustc_layout_scalar_valid_range_end, Normal, template!(List: &["value"]), ErrorFollowing, - EncodeCrossCrate::Yes, - "the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \ - niche optimizations in the standard library", - ), - rustc_attr!( - rustc_simd_monomorphize_lane_limit, Normal, template!(NameValueStr: "N"), ErrorFollowing, - EncodeCrossCrate::Yes, - "the `#[rustc_simd_monomorphize_lane_limit]` attribute is just used by std::simd \ - for better error messages", - ), - rustc_attr!( - rustc_nonnull_optimization_guaranteed, Normal, template!(Word), WarnFollowing, - EncodeCrossCrate::Yes, + rustc_attr!(rustc_layout_scalar_valid_range_start, "the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \ + niche optimizations in the standard library"), + rustc_attr!(rustc_layout_scalar_valid_range_end, "the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \ + niche optimizations in the standard library"), + rustc_attr!(rustc_simd_monomorphize_lane_limit, "the `#[rustc_simd_monomorphize_lane_limit]` attribute is just used by std::simd \ + for better error messages"), + rustc_attr!(rustc_nonnull_optimization_guaranteed, "the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to document \ guaranteed niche optimizations in the standard library", "the compiler does not even check whether the type indeed is being non-null-optimized; \ - it is your responsibility to ensure that the attribute is only used on types that are optimized", - ), + it is your responsibility to ensure that the attribute is only used on types that are optimized"), // ========================================================================== // Internal attributes, Misc: // ========================================================================== gated!( - lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, EncodeCrossCrate::No, lang_items, - "lang items are subject to change", + lang,lang_items, + "lang items are subject to change" ), - rustc_attr!( - rustc_as_ptr, Normal, template!(Word), ErrorFollowing, - EncodeCrossCrate::Yes, - "`#[rustc_as_ptr]` is used to mark functions returning pointers to their inner allocations" - ), - rustc_attr!( - rustc_should_not_be_called_on_const_items, Normal, template!(Word), ErrorFollowing, - EncodeCrossCrate::Yes, - "`#[rustc_should_not_be_called_on_const_items]` is used to mark methods that don't make sense to be called on interior mutable consts" - ), - rustc_attr!( - rustc_pass_by_value, Normal, template!(Word), ErrorFollowing, - EncodeCrossCrate::Yes, - "`#[rustc_pass_by_value]` is used to mark types that must be passed by value instead of reference" - ), - rustc_attr!( - rustc_never_returns_null_ptr, Normal, template!(Word), ErrorFollowing, - EncodeCrossCrate::Yes, - "`#[rustc_never_returns_null_ptr]` is used to mark functions returning non-null pointers" - ), - rustc_attr!( - rustc_no_implicit_autorefs, AttributeType::Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, - "`#[rustc_no_implicit_autorefs]` is used to mark functions for which an autoref to the dereference of a raw pointer should not be used as an argument" - ), - rustc_attr!( - rustc_coherence_is_core, AttributeType::CrateLevel, template!(Word), ErrorFollowing, EncodeCrossCrate::No, - "`#![rustc_coherence_is_core]` allows inherent methods on builtin types, only intended to be used in `core`" - ), - rustc_attr!( - rustc_coinductive, AttributeType::Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, - "`#[rustc_coinductive]` changes a trait to be coinductive, allowing cycles in the trait solver" - ), - rustc_attr!( - rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::No, - "`#[rustc_allow_incoherent_impl]` has to be added to all impl items of an incoherent inherent impl" - ), - rustc_attr!( - rustc_preserve_ub_checks, AttributeType::CrateLevel, template!(Word), ErrorFollowing, EncodeCrossCrate::No, - "`#![rustc_preserve_ub_checks]` prevents the designated crate from evaluating whether UB checks are enabled when optimizing MIR", - ), - rustc_attr!( - rustc_deny_explicit_impl, - AttributeType::Normal, - template!(Word), - ErrorFollowing, - EncodeCrossCrate::No, + rustc_attr!(rustc_as_ptr, "`#[rustc_as_ptr]` is used to mark functions returning pointers to their inner allocations"), + rustc_attr!(rustc_should_not_be_called_on_const_items, "`#[rustc_should_not_be_called_on_const_items]` is used to mark methods that don't make sense to be called on interior mutable consts"), + rustc_attr!(rustc_pass_by_value, "`#[rustc_pass_by_value]` is used to mark types that must be passed by value instead of reference"), + rustc_attr!(rustc_never_returns_null_ptr, "`#[rustc_never_returns_null_ptr]` is used to mark functions returning non-null pointers"), + rustc_attr!(rustc_no_implicit_autorefs, "`#[rustc_no_implicit_autorefs]` is used to mark functions for which an autoref to the dereference of a raw pointer should not be used as an argument"), + rustc_attr!(rustc_coherence_is_core, "`#![rustc_coherence_is_core]` allows inherent methods on builtin types, only intended to be used in `core`"), + rustc_attr!(rustc_coinductive, "`#[rustc_coinductive]` changes a trait to be coinductive, allowing cycles in the trait solver"), + rustc_attr!(rustc_allow_incoherent_impl, "`#[rustc_allow_incoherent_impl]` has to be added to all impl items of an incoherent inherent impl"), + rustc_attr!(rustc_preserve_ub_checks, "`#![rustc_preserve_ub_checks]` prevents the designated crate from evaluating whether UB checks are enabled when optimizing MIR"), + rustc_attr!(rustc_deny_explicit_impl, "`#[rustc_deny_explicit_impl]` enforces that a trait can have no user-provided impls" ), - rustc_attr!( - rustc_dyn_incompatible_trait, - AttributeType::Normal, - template!(Word), - ErrorFollowing, - EncodeCrossCrate::No, + rustc_attr!(rustc_dyn_incompatible_trait, "`#[rustc_dyn_incompatible_trait]` marks a trait as dyn-incompatible, \ even if it otherwise satisfies the requirements to be dyn-compatible." ), - rustc_attr!( - rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word), - ErrorFollowing, EncodeCrossCrate::Yes, - "`#[rustc_has_incoherent_inherent_impls]` allows the addition of incoherent inherent impls for \ + rustc_attr!(rustc_has_incoherent_inherent_impls, "`#[rustc_has_incoherent_inherent_impls]` allows the addition of incoherent inherent impls for \ the given type by annotating all impl items with `#[rustc_allow_incoherent_impl]`" ), - rustc_attr!( - rustc_non_const_trait_method, AttributeType::Normal, template!(Word), - ErrorFollowing, EncodeCrossCrate::No, - "`#[rustc_non_const_trait_method]` should only used by the standard library to mark trait methods \ + rustc_attr!(rustc_non_const_trait_method, "`#[rustc_non_const_trait_method]` should only used by the standard library to mark trait methods \ as non-const to allow large traits an easier transition to const" ), BuiltinAttribute { name: sym::rustc_diagnostic_item, - // FIXME: This can be `true` once we always use `tcx.is_diagnostic_item`. - encode_cross_crate: EncodeCrossCrate::Yes, - type_: Normal, safety: AttributeSafety::Normal, - template: template!(NameValueStr: "name"), - duplicates: ErrorFollowing, gate: Gated { feature: sym::rustc_attrs, message: "use of an internal attribute", @@ -1342,236 +717,87 @@ pub struct BuiltinAttribute { }, gated!( // Used in resolve: - prelude_import, Normal, template!(Word), WarnFollowing, - EncodeCrossCrate::No, "`#[prelude_import]` is for use by rustc only", + prelude_import, "`#[prelude_import]` is for use by rustc only", ), gated!( - rustc_paren_sugar, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, - unboxed_closures, "unboxed_closures are still evolving", + rustc_paren_sugar,unboxed_closures, "unboxed_closures are still evolving", ), - rustc_attr!( - rustc_inherit_overflow_checks, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, - "the `#[rustc_inherit_overflow_checks]` attribute is just used to control \ + rustc_attr!(rustc_inherit_overflow_checks,"the `#[rustc_inherit_overflow_checks]` attribute is just used to control \ overflow checking behavior of several functions in the standard library that are inlined \ - across crates", + across crates" ), - rustc_attr!( - rustc_reservation_impl, Normal, - template!(NameValueStr: "reservation message"), ErrorFollowing, EncodeCrossCrate::Yes, - "the `#[rustc_reservation_impl]` attribute is internally used \ + rustc_attr!(rustc_reservation_impl,"the `#[rustc_reservation_impl]` attribute is internally used \ for reserving `impl From for T` as part of the effort to stabilize `!`" ), - rustc_attr!( - rustc_test_marker, Normal, template!(NameValueStr: "name"), WarnFollowing, - EncodeCrossCrate::No, "the `#[rustc_test_marker]` attribute is used internally to track tests", - ), - rustc_attr!( - rustc_unsafe_specialization_marker, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::No, + rustc_attr!(rustc_test_marker, "the `#[rustc_test_marker]` attribute is used internally to track tests"), + rustc_attr!(rustc_unsafe_specialization_marker, "the `#[rustc_unsafe_specialization_marker]` attribute is used to check specializations" ), - rustc_attr!( - rustc_specialization_trait, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::No, + rustc_attr!(rustc_specialization_trait, "the `#[rustc_specialization_trait]` attribute is used to check specializations" ), - rustc_attr!( - rustc_main, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, - "the `#[rustc_main]` attribute is used internally to specify test entry point function", - ), - rustc_attr!( - rustc_skip_during_method_dispatch, Normal, template!(List: &["array, boxed_slice"]), ErrorFollowing, - EncodeCrossCrate::No, - "the `#[rustc_skip_during_method_dispatch]` attribute is used to exclude a trait \ + rustc_attr!(rustc_main,"the `#[rustc_main]` attribute is used internally to specify test entry point function"), + rustc_attr!(rustc_skip_during_method_dispatch, "the `#[rustc_skip_during_method_dispatch]` attribute is used to exclude a trait \ from method dispatch when the receiver is of the following type, for compatibility in \ editions < 2021 (array) or editions < 2024 (boxed_slice)" ), - rustc_attr!( - rustc_must_implement_one_of, Normal, template!(List: &["function1, function2, ..."]), - ErrorFollowing, EncodeCrossCrate::No, - "the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete \ + rustc_attr!(rustc_must_implement_one_of,"the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete \ definition of a trait. Its syntax and semantics are highly experimental and will be \ subject to change before stabilization", ), - rustc_attr!( - rustc_doc_primitive, Normal, template!(NameValueStr: "primitive name"), ErrorFollowing, - EncodeCrossCrate::Yes, "the `#[rustc_doc_primitive]` attribute is used by the standard library \ + rustc_attr!(rustc_doc_primitive,"the `#[rustc_doc_primitive]` attribute is used by the standard library \ to provide a way to generate documentation for primitive types", ), gated!( - rustc_intrinsic, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, intrinsics, - "the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items", - ), - rustc_attr!( - rustc_no_mir_inline, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes, - "`#[rustc_no_mir_inline]` prevents the MIR inliner from inlining a function while not affecting codegen" - ), - rustc_attr!( - rustc_force_inline, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing, EncodeCrossCrate::Yes, - "`#[rustc_force_inline]` forces a free function to be inlined" - ), - rustc_attr!( - rustc_scalable_vector, Normal, template!(List: &["count"]), WarnFollowing, EncodeCrossCrate::Yes, - "`#[rustc_scalable_vector]` defines a scalable vector type" + rustc_intrinsic,intrinsics, + "the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items"), + rustc_attr!(rustc_no_mir_inline,"`#[rustc_no_mir_inline]` prevents the MIR inliner from inlining a function while not affecting codegen" ), + rustc_attr!(rustc_force_inline,"`#[rustc_force_inline]` forces a free function to be inlined"), + rustc_attr!(rustc_scalable_vector,"`#[rustc_scalable_vector]` defines a scalable vector type"), // ========================================================================== // Internal attributes, Testing: // ========================================================================== - rustc_attr!(TEST, rustc_effective_visibility, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes), - rustc_attr!( - TEST, rustc_dump_inferred_outlives, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::No - ), - rustc_attr!( - TEST, rustc_capture_analysis, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::No - ), - rustc_attr!( - TEST, rustc_insignificant_dtor, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::Yes - ), - rustc_attr!( - TEST, rustc_no_implicit_bounds, CrateLevel, template!(Word), - WarnFollowing, EncodeCrossCrate::No - ), - rustc_attr!( - TEST, rustc_strict_coherence, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::Yes - ), - rustc_attr!( - TEST, rustc_dump_variances, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::No - ), - rustc_attr!( - TEST, rustc_dump_variances_of_opaques, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::No - ), - rustc_attr!( - TEST, rustc_hidden_type_of_opaques, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::No - ), - rustc_attr!( - TEST, rustc_layout, Normal, template!(List: &["field1, field2, ..."]), - WarnFollowing, EncodeCrossCrate::Yes - ), - rustc_attr!( - TEST, rustc_abi, Normal, template!(List: &["field1, field2, ..."]), - WarnFollowing, EncodeCrossCrate::No - ), - rustc_attr!( - TEST, rustc_regions, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::No - ), - rustc_attr!( - TEST, rustc_delayed_bug_from_inside_query, Normal, - template!(Word), - WarnFollowing, EncodeCrossCrate::No - ), - rustc_attr!( - TEST, rustc_dump_user_args, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::No - ), - rustc_attr!( - TEST, rustc_evaluate_where_clauses, Normal, template!(Word), WarnFollowing, - EncodeCrossCrate::Yes - ), - rustc_attr!( - TEST, rustc_if_this_changed, Normal, template!(Word, List: &["DepNode"]), DuplicatesOk, - EncodeCrossCrate::No - ), - rustc_attr!( - TEST, rustc_then_this_would_need, Normal, template!(List: &["DepNode"]), DuplicatesOk, - EncodeCrossCrate::No - ), - rustc_attr!( - TEST, rustc_clean, Normal, - template!(List: &[r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#]), - DuplicatesOk, EncodeCrossCrate::No - ), - rustc_attr!( - TEST, rustc_partition_reused, Normal, - template!(List: &[r#"cfg = "...", module = "...""#]), DuplicatesOk, EncodeCrossCrate::No - ), - rustc_attr!( - TEST, rustc_partition_codegened, Normal, - template!(List: &[r#"cfg = "...", module = "...""#]), DuplicatesOk, EncodeCrossCrate::No - ), - rustc_attr!( - TEST, rustc_expected_cgu_reuse, Normal, - template!(List: &[r#"cfg = "...", module = "...", kind = "...""#]), DuplicatesOk, - EncodeCrossCrate::No - ), - rustc_attr!( - TEST, rustc_symbol_name, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::No - ), - rustc_attr!( - TEST, rustc_def_path, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::No - ), - rustc_attr!( - TEST, rustc_mir, Normal, template!(List: &["arg1, arg2, ..."]), - DuplicatesOk, EncodeCrossCrate::Yes - ), - gated!( - custom_mir, Normal, template!(List: &[r#"dialect = "...", phase = "...""#]), - ErrorFollowing, EncodeCrossCrate::No, - "the `#[custom_mir]` attribute is just used for the Rust test suite", - ), - rustc_attr!( - TEST, rustc_dump_item_bounds, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::No - ), - rustc_attr!( - TEST, rustc_dump_predicates, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::No - ), - rustc_attr!( - TEST, rustc_dump_def_parents, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::No - ), - rustc_attr!( - TEST, rustc_dump_object_lifetime_defaults, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::No - ), - rustc_attr!( - TEST, rustc_dump_vtable, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::No - ), - rustc_attr!( - TEST, rustc_dummy, Normal, template!(Word /* doesn't matter*/), - DuplicatesOk, EncodeCrossCrate::No - ), - rustc_attr!( - TEST, pattern_complexity_limit, CrateLevel, template!(NameValueStr: "N"), - ErrorFollowing, EncodeCrossCrate::No, - ), + rustc_attr!(TEST, rustc_effective_visibility), + rustc_attr!(TEST, rustc_dump_inferred_outlives), + rustc_attr!(TEST, rustc_capture_analysis), + rustc_attr!(TEST, rustc_insignificant_dtor), + rustc_attr!(TEST, rustc_no_implicit_bounds), + rustc_attr!(TEST, rustc_strict_coherence), + rustc_attr!(TEST, rustc_dump_variances), + rustc_attr!(TEST, rustc_dump_variances_of_opaques), + rustc_attr!(TEST, rustc_hidden_type_of_opaques), + rustc_attr!(TEST, rustc_layout), + rustc_attr!(TEST, rustc_abi), + rustc_attr!(TEST, rustc_regions), + rustc_attr!(TEST, rustc_delayed_bug_from_inside_query), + rustc_attr!(TEST, rustc_dump_user_args), + rustc_attr!(TEST, rustc_evaluate_where_clauses), + rustc_attr!(TEST, rustc_if_this_changed), + rustc_attr!(TEST, rustc_then_this_would_need), + rustc_attr!(TEST, rustc_clean), + rustc_attr!(TEST, rustc_partition_reused), + rustc_attr!(TEST, rustc_partition_codegened), + rustc_attr!(TEST, rustc_expected_cgu_reuse), + rustc_attr!(TEST, rustc_symbol_name), + rustc_attr!(TEST, rustc_def_path), + rustc_attr!(TEST, rustc_mir), + gated!(custom_mir,"the `#[custom_mir]` attribute is just used for the Rust test suite"), + rustc_attr!(TEST, rustc_dump_item_bounds), + rustc_attr!(TEST, rustc_dump_predicates), + rustc_attr!(TEST, rustc_dump_def_parents), + rustc_attr!(TEST, rustc_dump_object_lifetime_defaults), + rustc_attr!(TEST, rustc_dump_vtable), + rustc_attr!(TEST, rustc_dummy), + rustc_attr!(TEST, pattern_complexity_limit), ]; pub fn is_builtin_attr_name(name: Symbol) -> bool { BUILTIN_ATTRIBUTE_MAP.get(&name).is_some() } -/// Whether this builtin attribute is encoded cross crate. -/// This means it can be used cross crate. -pub fn encode_cross_crate(name: Symbol) -> bool { - if let Some(attr) = BUILTIN_ATTRIBUTE_MAP.get(&name) { - attr.encode_cross_crate == EncodeCrossCrate::Yes - } else { - true - } -} - -pub fn is_valid_for_get_attr(name: Symbol) -> bool { - BUILTIN_ATTRIBUTE_MAP.get(&name).is_some_and(|attr| match attr.duplicates { - WarnFollowing | ErrorFollowing | ErrorPreceding | FutureWarnFollowing - | FutureWarnPreceding => true, - DuplicatesOk | WarnFollowingWordOnly => false, - }) -} - pub static BUILTIN_ATTRIBUTE_MAP: LazyLock> = LazyLock::new(|| { let mut map = FxHashMap::default(); diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index 9d046bdef1cf..40a637bfa0b8 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -129,10 +129,9 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option Vec { #[allow(rustc::potential_query_instability)] - sess.psess + let mut names = sess + .psess .check_config .well_known_names .iter() @@ -454,5 +454,7 @@ fn possible_well_known_names_for_cfg_value(sess: &Session, value: Symbol) -> Vec .unwrap_or_default() }) .copied() - .collect() + .collect::>(); + names.sort_by(|a, b| a.as_str().cmp(b.as_str())); + names } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index a05366d7147b..6b2d849a636c 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -224,7 +224,7 @@ fn process_module(&mut self, module: &ForeignModule) { let dll_imports = match attr.kind { NativeLibKind::RawDylib { .. } => foreign_items .iter() - .map(|&child_item| { + .filter_map(|&child_item| { self.build_dll_import( abi, attr.import_name_type.map(|(import_name_type, _)| import_name_type), @@ -388,7 +388,7 @@ fn build_dll_import( abi: ExternAbi, import_name_type: Option, item: DefId, - ) -> DllImport { + ) -> Option { let span = self.tcx.def_span(item); // This `extern` block should have been checked for general ABI support before, but let's @@ -465,6 +465,8 @@ fn build_dll_import( } else { DllImportSymbolType::Static } + } else if def_kind == DefKind::ForeignTy { + return None; } else { bug!("Unexpected type for raw-dylib: {}", def_kind.descr(item)); }; @@ -482,6 +484,6 @@ fn build_dll_import( } }; - DllImport { name, import_name_type, calling_convention, span, symbol_type, size } + Some(DllImport { name, import_name_type, calling_convention, span, symbol_type, size }) } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 8bf919dab8e7..3f8c11a87e85 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -864,10 +864,6 @@ fn analyze_attr(attr: &hir::Attribute, state: &mut AnalyzeAttrState<'_>) -> bool && p.encode_cross_crate() == EncodeCrossCrate::No { // Attributes not marked encode-cross-crate don't need to be encoded for downstream crates. - } else if let Some(name) = attr.name() - && !rustc_feature::encode_cross_crate(name) - { - // Attributes not marked encode-cross-crate don't need to be encoded for downstream crates. } else if let hir::Attribute::Parsed(AttributeKind::DocComment { .. }) = attr { // We keep all doc comments reachable to rustdoc because they might be "imported" into // downstream crates if they use `#[doc(inline)]` to copy an item's documentation into diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 6b207be245ba..b0c6a8a508cc 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -464,30 +464,6 @@ pub fn default_span(&self, tcx: TyCtxt<'tcx>, span: Span) -> Span { )* } } - - pub fn def_kind(&self, tcx: TyCtxt<'tcx>) -> Option { - // This is used to reduce code generation as it - // can be reused for queries with the same key type. - fn inner<'tcx>(key: &impl $crate::query::QueryKey, tcx: TyCtxt<'tcx>) - -> Option - { - key - .key_as_def_id() - .and_then(|def_id| def_id.as_local()) - .map(|def_id| tcx.def_kind(def_id)) - } - - if let TaggedQueryKey::def_kind(..) = self { - // Try to avoid infinite recursion. - return None - } - - match self { - $( - TaggedQueryKey::$name(key) => inner(key, tcx), - )* - } - } } /// Holds a `QueryVTable` for each query. diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index dbf7d643a42c..36a474688f07 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1725,13 +1725,8 @@ pub fn get_attrs_by_path( #[deprecated = "Though there are valid usecases for this method, especially when your attribute is not a parsed attribute, usually you want to call rustc_hir::find_attr! instead."] pub fn get_attr(self, did: impl Into, attr: Symbol) -> Option<&'tcx hir::Attribute> { - if cfg!(debug_assertions) && !rustc_feature::is_valid_for_get_attr(attr) { - let did: DefId = did.into(); - bug!("get_attr: unexpected called with DefId `{:?}`, attr `{:?}`", did, attr); - } else { - #[allow(deprecated)] - self.get_attrs(did, attr).next() - } + #[allow(deprecated)] + self.get_attrs(did, attr).next() } /// Determines whether an item is annotated with an attribute. diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 12b583d8fee1..3e3810b7f125 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -6,17 +6,15 @@ //! item. use std::cell::Cell; -use std::collections::hash_map::Entry; use std::slice; use rustc_abi::ExternAbi; use rustc_ast::ast; use rustc_attr_parsing::{AttributeParser, Late}; -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::unord::UnordMap; use rustc_errors::{DiagCtxtHandle, IntoDiagArg, MultiSpan, msg}; -use rustc_feature::{AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute}; +use rustc_feature::BUILTIN_ATTRIBUTE_MAP; use rustc_hir::attrs::diagnostic::Directive; use rustc_hir::attrs::{ AttributeKind, CrateType, DocAttribute, DocInline, EiiDecl, EiiImpl, EiiImplResolution, @@ -137,7 +135,6 @@ fn check_attributes( target: Target, item: Option>, ) { - let mut seen = FxHashMap::default(); let attrs = self.tcx.hir_attrs(hir_id); for attr in attrs { match attr { @@ -404,64 +401,6 @@ fn check_attributes( } } - if hir_id != CRATE_HIR_ID { - match attr { - Attribute::Parsed(_) => { /* Already validated. */ } - Attribute::Unparsed(attr) => { - // FIXME(jdonszelmann): remove once all crate-level attrs are parsed and caught by - // the above - if let Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) = - attr.path - .segments - .first() - .and_then(|name| BUILTIN_ATTRIBUTE_MAP.get(&name)) - { - match attr.style { - ast::AttrStyle::Outer => { - let attr_span = attr.span; - let bang_position = self - .tcx - .sess - .source_map() - .span_until_char(attr_span, '[') - .shrink_to_hi(); - - self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr.span, - errors::OuterCrateLevelAttr { - suggestion: errors::OuterCrateLevelAttrSuggestion { - bang_position, - }, - }, - ) - } - ast::AttrStyle::Inner => self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr.span, - errors::InnerCrateLevelAttr, - ), - } - } - } - } - } - - if let Attribute::Unparsed(unparsed_attr) = attr - && let Some(BuiltinAttribute { duplicates, .. }) = - attr.name().and_then(|name| BUILTIN_ATTRIBUTE_MAP.get(&name)) - { - check_duplicates( - self.tcx, - unparsed_attr.span, - attr, - hir_id, - *duplicates, - &mut seen, - ); - } self.check_unused_attribute(hir_id, attr) } @@ -1994,67 +1933,6 @@ pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { check_mod_attrs, ..*providers }; } -// FIXME(jdonszelmann): remove, check during parsing -fn check_duplicates( - tcx: TyCtxt<'_>, - attr_span: Span, - attr: &Attribute, - hir_id: HirId, - duplicates: AttributeDuplicates, - seen: &mut FxHashMap, -) { - use AttributeDuplicates::*; - if matches!(duplicates, WarnFollowingWordOnly) && !attr.is_word() { - return; - } - let attr_name = attr.name().unwrap(); - match duplicates { - DuplicatesOk => {} - WarnFollowing | FutureWarnFollowing | WarnFollowingWordOnly | FutureWarnPreceding => { - match seen.entry(attr_name) { - Entry::Occupied(mut entry) => { - let (this, other) = if matches!(duplicates, FutureWarnPreceding) { - let to_remove = entry.insert(attr_span); - (to_remove, attr_span) - } else { - (attr_span, *entry.get()) - }; - tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - this, - errors::UnusedDuplicate { - this, - other, - warning: matches!( - duplicates, - FutureWarnFollowing | FutureWarnPreceding - ), - }, - ); - } - Entry::Vacant(entry) => { - entry.insert(attr_span); - } - } - } - ErrorFollowing | ErrorPreceding => match seen.entry(attr_name) { - Entry::Occupied(mut entry) => { - let (this, other) = if matches!(duplicates, ErrorPreceding) { - let to_remove = entry.insert(attr_span); - (to_remove, attr_span) - } else { - (attr_span, *entry.get()) - }; - tcx.dcx().emit_err(errors::UnusedMultiple { this, other, name: attr_name }); - } - Entry::Vacant(entry) => { - entry.insert(attr_span); - } - }, - } -} - fn doc_fake_variadic_is_allowed_self_ty(self_ty: &hir::Ty<'_>) -> bool { matches!(&self_ty.kind, hir::TyKind::Tup([_])) || if let hir::TyKind::FnPtr(fn_ptr_ty) = &self_ty.kind { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 628d0b0c961a..46b96ff1da35 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -326,30 +326,6 @@ pub(crate) struct InvalidMayDangle { pub attr_span: Span, } -#[derive(Diagnostic)] -#[diag("unused attribute")] -pub(crate) struct UnusedDuplicate { - #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] - pub this: Span, - #[note("attribute also specified here")] - pub other: Span, - #[warning( - "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" - )] - pub warning: bool, -} - -#[derive(Diagnostic)] -#[diag("multiple `{$name}` attributes")] -pub(crate) struct UnusedMultiple { - #[primary_span] - #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] - pub this: Span, - #[note("attribute also specified here")] - pub other: Span, - pub name: Symbol, -} - #[derive(Diagnostic)] #[diag("this `#[deprecated]` annotation has no effect")] pub(crate) struct DeprecatedAnnotationHasNoEffect { diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index f72899a66cae..41ec05621721 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -214,18 +214,26 @@ fn propagate_node(&mut self, node: &Node<'tcx>, search_item: LocalDefId) { self.visit_const_item_rhs(init); } hir::ItemKind::Const(_, _, _, init) => { - // Only things actually ending up in the final constant value are reachable - // for codegen. Everything else is only needed during const-eval, so even if - // const-eval happens in a downstream crate, all they need is - // `mir_for_ctfe`. + if self.tcx.generics_of(item.owner_id).own_requires_monomorphization() { + // In this case, we don't want to evaluate the const initializer. + // In lieu of that, we have to consider everything mentioned in it + // as reachable, since it *may* end up in the final value. + self.visit_const_item_rhs(init); + return; + } + match self.tcx.const_eval_poly_to_alloc(item.owner_id.def_id.into()) { Ok(alloc) => { + // Only things actually ending up in the final constant value are + // reachable for codegen. Everything else is only needed during + // const-eval, so even if const-eval happens in a downstream crate, + // all they need is `mir_for_ctfe`. let alloc = self.tcx.global_alloc(alloc.alloc_id).unwrap_memory(); self.propagate_from_alloc(alloc); } - // We can't figure out which value the constant will evaluate to. In - // lieu of that, we have to consider everything mentioned in the const - // initializer reachable, since it *may* end up in the final value. + // Trivially unsatisfiable bounds on the item prevented us from + // normalizing the initializer. Similar to the other case, we have to + // everything mentioned in it as reachable. Err(ErrorHandled::TooGeneric(_)) => self.visit_const_item_rhs(init), // If there was an error evaluating the const, nothing can be reachable // via it, and anyway compilation will fail. diff --git a/compiler/rustc_query_impl/src/job.rs b/compiler/rustc_query_impl/src/job.rs index a27a6f4ea322..f8098da59371 100644 --- a/compiler/rustc_query_impl/src/job.rs +++ b/compiler/rustc_query_impl/src/job.rs @@ -229,6 +229,80 @@ fn connected_to_root<'tcx>( false } +/// Processes a found query cycle into a `Cycle` +fn process_cycle<'tcx>(job_map: &QueryJobMap<'tcx>, stack: Vec<(Span, QueryJobId)>) -> Cycle<'tcx> { + // The stack is a vector of pairs of spans and queries; reverse it so that + // the earlier entries require later entries + let (mut spans, queries): (Vec<_>, Vec<_>) = stack.into_iter().rev().unzip(); + + // Shift the spans so that queries are matched with the span for their waitee + spans.rotate_right(1); + + // Zip them back together + let mut stack: Vec<_> = iter::zip(spans, queries).collect(); + + struct EntryPoint { + query_in_cycle: QueryJobId, + query_waiting_on_cycle: Option<(Span, QueryJobId)>, + } + + // Find the queries in the cycle which are + // connected to queries outside the cycle + let entry_points = stack + .iter() + .filter_map(|&(_, query_in_cycle)| { + let mut entrypoint = false; + let mut query_waiting_on_cycle = None; + + // Find a direct waiter who leads to the root + for abstracted_waiter in abstracted_waiters_of(job_map, query_in_cycle) { + let Some(parent) = abstracted_waiter.parent else { + // The query in the cycle is directly connected to root. + entrypoint = true; + continue; + }; + + // Mark all the other queries in the cycle as already visited, + // so paths to the root through the cycle itself won't count. + let mut visited = FxHashSet::from_iter(stack.iter().map(|q| q.1)); + + if connected_to_root(job_map, parent, &mut visited) { + query_waiting_on_cycle = Some((abstracted_waiter.span, parent)); + entrypoint = true; + break; + } + } + + entrypoint.then_some(EntryPoint { query_in_cycle, query_waiting_on_cycle }) + }) + .collect::>(); + + // Pick an entry point, preferring ones with waiters + let entry_point = entry_points + .iter() + .find(|entry_point| entry_point.query_waiting_on_cycle.is_some()) + .unwrap_or(&entry_points[0]); + + // Shift the stack so that our entry point is first + let entry_point_pos = stack.iter().position(|(_, query)| *query == entry_point.query_in_cycle); + if let Some(pos) = entry_point_pos { + stack.rotate_left(pos); + } + + let usage = entry_point + .query_waiting_on_cycle + .map(|(span, job)| QueryStackFrame { span, tagged_key: job_map.tagged_key_of(job) }); + + // Create the cycle error + Cycle { + usage, + frames: stack + .iter() + .map(|&(span, job)| QueryStackFrame { span, tagged_key: job_map.tagged_key_of(job) }) + .collect(), + } +} + /// Looks for a query cycle using the last query in `jobs`. /// If a cycle is found, all queries in the cycle is removed from `jobs` and /// the function return true. @@ -245,16 +319,6 @@ fn remove_cycle<'tcx>( if let ControlFlow::Break(resumable) = find_cycle(job_map, jobs.pop().unwrap(), DUMMY_SP, &mut stack, &mut visited) { - // The stack is a vector of pairs of spans and queries; reverse it so that - // the earlier entries require later entries - let (mut spans, queries): (Vec<_>, Vec<_>) = stack.into_iter().rev().unzip(); - - // Shift the spans so that queries are matched with the span for their waitee - spans.rotate_right(1); - - // Zip them back together - let mut stack: Vec<_> = iter::zip(spans, queries).collect(); - // Remove the queries in our cycle from the list of jobs to look at for r in &stack { if let Some(pos) = jobs.iter().position(|j| j == &r.1) { @@ -262,70 +326,8 @@ fn remove_cycle<'tcx>( } } - struct EntryPoint { - query_in_cycle: QueryJobId, - query_waiting_on_cycle: Option<(Span, QueryJobId)>, - } - - // Find the queries in the cycle which are - // connected to queries outside the cycle - let entry_points = stack - .iter() - .filter_map(|&(_, query_in_cycle)| { - let mut entrypoint = false; - let mut query_waiting_on_cycle = None; - - // Find a direct waiter who leads to the root - for abstracted_waiter in abstracted_waiters_of(job_map, query_in_cycle) { - let Some(parent) = abstracted_waiter.parent else { - // The query in the cycle is directly connected to root. - entrypoint = true; - continue; - }; - - // Mark all the other queries in the cycle as already visited, - // so paths to the root through the cycle itself won't count. - let mut visited = FxHashSet::from_iter(stack.iter().map(|q| q.1)); - - if connected_to_root(job_map, parent, &mut visited) { - query_waiting_on_cycle = Some((abstracted_waiter.span, parent)); - entrypoint = true; - break; - } - } - - entrypoint.then_some(EntryPoint { query_in_cycle, query_waiting_on_cycle }) - }) - .collect::>(); - - // Pick an entry point, preferring ones with waiters - let entry_point = entry_points - .iter() - .find(|entry_point| entry_point.query_waiting_on_cycle.is_some()) - .unwrap_or(&entry_points[0]); - - // Shift the stack so that our entry point is first - let entry_point_pos = - stack.iter().position(|(_, query)| *query == entry_point.query_in_cycle); - if let Some(pos) = entry_point_pos { - stack.rotate_left(pos); - } - - let usage = entry_point - .query_waiting_on_cycle - .map(|(span, job)| QueryStackFrame { span, tagged_key: job_map.tagged_key_of(job) }); - // Create the cycle error - let error = Cycle { - usage, - frames: stack - .iter() - .map(|&(span, job)| QueryStackFrame { - span, - tagged_key: job_map.tagged_key_of(job), - }) - .collect(), - }; + let error = process_cycle(job_map, stack); // We unwrap `resumable` here since there must always be one // edge which is resumable / waited using a query latch @@ -481,13 +483,23 @@ pub(crate) fn create_cycle_error<'tcx>( usage: usage.tagged_key.description(tcx), }); - let alias = if frames - .iter() - .all(|frame| frame.tagged_key.def_kind(tcx) == Some(DefKind::TyAlias)) - { + let is_all_def_kind = |def_kind| { + // Trivial type alias and trait alias cycles consists of `type_of` and + // `explicit_implied_predicates_of` queries, so we just check just these here. + frames.iter().all(|frame| match frame.tagged_key { + TaggedQueryKey::type_of(def_id) + | TaggedQueryKey::explicit_implied_predicates_of(def_id) + if tcx.def_kind(def_id) == def_kind => + { + true + } + _ => false, + }) + }; + + let alias = if is_all_def_kind(DefKind::TyAlias) { Some(crate::error::Alias::Ty) - } else if frames.iter().all(|frame| frame.tagged_key.def_kind(tcx) == Some(DefKind::TraitAlias)) - { + } else if is_all_def_kind(DefKind::TraitAlias) { Some(crate::error::Alias::Trait) } else { None diff --git a/library/compiler-builtins/compiler-builtins/src/math/mod.rs b/library/compiler-builtins/compiler-builtins/src/math/mod.rs index 61dfad213cbe..3dfa3863bb77 100644 --- a/library/compiler-builtins/compiler-builtins/src/math/mod.rs +++ b/library/compiler-builtins/compiler-builtins/src/math/mod.rs @@ -144,8 +144,12 @@ pub mod partial_availability { libm_intrinsics! { fn acos(x: f64) -> f64; fn acosf(n: f32) -> f32; + fn acosh(x: f64) -> f64; + fn acoshf(x: f32) -> f32; fn asin(x: f64) -> f64; fn asinf(n: f32) -> f32; + fn asinh(x: f64) -> f64; + fn asinhf(x: f32) -> f32; fn atan(x: f64) -> f64; fn atan2(x: f64, y: f64) -> f64; fn atan2f(a: f32, b: f32) -> f32; diff --git a/library/core/src/autodiff.md b/library/core/src/autodiff.md new file mode 100644 index 000000000000..847ed8b3ef32 --- /dev/null +++ b/library/core/src/autodiff.md @@ -0,0 +1,157 @@ +This module provides support for automatic differentiation. For precise information on +differences between the `autodiff_forward` and `autodiff_reverse` macros and how to +use them, see their respective documentation. + +## General usage + +Autodiff macros can be applied to almost all function definitions, see below for examples. +They can be applied to functions accepting structs, arrays, slices, vectors, tuples, and more. + +It is possible to apply multiple autodiff macros to the same function. As an example, this can +be helpful to compute the partial derivatives with respect to `x` and `y` independently: +```rust,ignore (optional component) +#[autodiff_forward(dsquare1, Dual, Const, Dual)] +#[autodiff_forward(dsquare2, Const, Dual, Dual)] +#[autodiff_forward(dsquare3, Active, Active, Active)] +fn square(x: f64, y: f64) -> f64 { + x * x + 2.0 * y +} +``` + +We also support autodiff on functions with generic parameters: +```rust,ignore (optional component) +#[autodiff_forward(generic_derivative, Duplicated, Active)] +fn generic_f + Copy>(x: &T) -> T { + x * x +} +``` + +or applying autodiff to nested functions: +```rust,ignore (optional component) +fn outer(x: f64) -> f64 { + #[autodiff_forward(inner_derivative, Dual, Const)] + fn inner(y: f64) -> f64 { + y * y + } + inner_derivative(x, 1.0) +} + +fn main() { + assert_eq!(outer(3.14), 6.28); +} +``` +The generated function will be available in the same scope as the function differentiated, and +have the same private/pub usability. + +## Traits and impls +Autodiff macros can be used in multiple ways in combination with traits: +```rust,ignore (optional component) +struct Foo { + a: f64, +} + +trait MyTrait { + #[autodiff_reverse(df, Const, Active, Active)] + fn f(&self, x: f64) -> f64; +} + +impl MyTrait for Foo { + fn f(&self, x: f64) -> f64 { + x.sin() + } +} + +fn main() { + let foo = Foo { a: 3.0f64 }; + assert_eq!(foo.f(2.0), 2.0_f64.sin()); + assert_eq!(foo.df(2.0, 1.0).1, 2.0_f64.cos()); +} +``` +In this case `df` will be the default implementation provided by the library who provided the +trait. A user implementing `MyTrait` could then decide to use the default implementation of +`df`, or overwrite it with a custom implementation as a form of "custom derivatives". + +On the other hand, a function generated by either autodiff macro can also be used to implement a +trait: +```rust,ignore (optional component) +struct Foo { + a: f64, +} + +trait MyTrait { + fn f(&self, x: f64) -> f64; + fn df(&self, x: f64, seed: f64) -> (f64, f64); +} + +impl MyTrait for Foo { + #[autodiff_reverse(df, Const, Active, Active)] + fn f(&self, x: f64) -> f64 { + self.a * 0.25 * (x * x - 1.0 - 2.0 * x.ln()) + } +} +``` + +Simple `impl` blocks without traits are also supported. Differentiating with respect to the +implemented struct will then require the use of a "shadow struct" to hold the derivatives of the +struct fields: + +```rust,ignore (optional component) +struct OptProblem { + a: f64, + b: f64, +} + +impl OptProblem { + #[autodiff_reverse(d_objective, Duplicated, Duplicated, Duplicated)] + fn objective(&self, x: &[f64], out: &mut f64) { + *out = self.a + x[0].sqrt() * self.b + } +} +fn main() { + let p = OptProblem { a: 1., b: 2. }; + let mut p_shadow = OptProblem { a: 0., b: 0. }; + let mut dx = [0.0]; + let mut out = 0.0; + let mut dout = 1.0; + + p.d_objective(&mut p_shadow, &x, &mut dx, &mut out, &mut dout); +} +``` + +## Higher-order derivatives +Finally, it is possible to generate higher-order derivatives (e.g. Hessian) by applying an +autodiff macro to a function that is already generated by an autodiff macro, via a thin wrapper. +The following example uses Forward mode over Reverse mode + +```rust,ignore (optional component) +#[autodiff_reverse(df, Duplicated, Duplicated)] +fn f(x: &[f64;2], y: &mut f64) { + *y = x[0] * x[0] + x[1] * x[0] +} + +#[autodiff_forward(h, Dual, Dual, Dual, Dual)] +fn wrapper(x: &[f64;2], dx: &mut [f64;2], y: &mut f64, dy: &mut f64) { + df(x, dx, y, dy); +} + +fn main() { + let mut y = 0.0; + let x = [2.0, 2.0]; + + let mut dy = 0.0; + let mut dx = [1.0, 0.0]; + + let mut bx = [0.0, 0.0]; + let mut by = 1.0; + let mut dbx = [0.0, 0.0]; + let mut dby = 0.0; + h(&x, &mut dx, &mut bx, &mut dbx, &mut y, &mut dy, &mut by, &mut dby); + assert_eq!(&dbx, [2.0, 1.0]); +} +``` + +## Current limitations: + +- Differentiating a function which accepts a `dyn Trait` is currently not supported. +- Builds without `lto="fat"` are not yet supported. +- Builds in debug mode are currently more likely to fail compilation. diff --git a/library/core/src/intrinsics/simd/scalable.rs b/library/core/src/intrinsics/simd/scalable.rs index f33831a30c07..b2b0fec487c0 100644 --- a/library/core/src/intrinsics/simd/scalable.rs +++ b/library/core/src/intrinsics/simd/scalable.rs @@ -19,7 +19,6 @@ /// * Not be `NaN` /// * Not be infinite /// * Be representable in the return type, after truncating off its fractional part -#[cfg(target_arch = "aarch64")] #[rustc_intrinsic] #[rustc_nounwind] pub unsafe fn sve_cast(x: T) -> U; @@ -31,7 +30,6 @@ /// type `SVec`. /// /// Corresponds to Clang's `__builtin_sve_svcreate2*` builtins. -#[cfg(target_arch = "aarch64")] #[rustc_nounwind] #[rustc_intrinsic] pub unsafe fn sve_tuple_create2(x0: SVec, x1: SVec) -> SVecTup; @@ -43,7 +41,6 @@ /// type `SVec`. /// /// Corresponds to Clang's `__builtin_sve_svcreate3*` builtins. -#[cfg(target_arch = "aarch64")] #[rustc_intrinsic] #[rustc_nounwind] pub unsafe fn sve_tuple_create3(x0: SVec, x1: SVec, x2: SVec) -> SVecTup; @@ -55,7 +52,6 @@ /// type `SVec`. /// /// Corresponds to Clang's `__builtin_sve_svcreate4*` builtins. -#[cfg(target_arch = "aarch64")] #[rustc_intrinsic] #[rustc_nounwind] pub unsafe fn sve_tuple_create4(x0: SVec, x1: SVec, x2: SVec, x3: SVec) -> SVecTup; @@ -71,7 +67,6 @@ /// # Safety /// /// `IDX` must be in-bounds of the tuple. -#[cfg(target_arch = "aarch64")] #[rustc_intrinsic] #[rustc_nounwind] pub unsafe fn sve_tuple_get(tuple: SVecTup) -> SVec; @@ -87,7 +82,6 @@ /// # Safety /// /// `IDX` must be in-bounds of the tuple. -#[cfg(target_arch = "aarch64")] #[rustc_intrinsic] #[rustc_nounwind] pub unsafe fn sve_tuple_set(tuple: SVecTup, x: SVec) -> SVecTup; diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index c57f41ffbf06..3b025fdcda90 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -513,7 +513,8 @@ macro_rules! step_nonzero_impls { $( #[allow(unreachable_patterns)] #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] - impl Step for NonZero<$narrower> { + #[rustc_const_unstable(feature = "step_trait", issue = "42168")] + impl const Step for NonZero<$narrower> { step_nonzero_identical_methods!($narrower); #[inline] @@ -538,7 +539,8 @@ fn backward_checked(start: Self, n: usize) -> Option { $( #[allow(unreachable_patterns)] #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] - impl Step for NonZero<$wider> { + #[rustc_const_unstable(feature = "step_trait", issue = "42168")] + impl const Step for NonZero<$wider> { step_nonzero_identical_methods!($wider); #[inline] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 312295154dc5..299aa9f113bf 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -227,7 +227,7 @@ pub trait Sealed {} // We don't export this through #[macro_export] for now, to avoid breakage. #[unstable(feature = "autodiff", issue = "124509")] -/// Unstable module containing the unstable `autodiff` macro. +#[doc = include_str!("../../core/src/autodiff.md")] pub mod autodiff { #[unstable(feature = "autodiff", issue = "124509")] pub use crate::macros::builtin::{autodiff_forward, autodiff_reverse}; diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 3415e1d435ce..c270b947d4fd 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -184,7 +184,8 @@ impl $Trait for NonZero where T: ZeroablePrimitive + $Trait {} impl_nonzero_auto_trait!(UnwindSafe); #[stable(feature = "nonzero", since = "1.28.0")] -impl Clone for NonZero +#[rustc_const_unstable(feature = "const_clone", issue = "142757")] +impl const Clone for NonZero where T: ZeroablePrimitive, { @@ -202,7 +203,8 @@ impl Copy for NonZero where T: ZeroablePrimitive {} #[doc(hidden)] #[unstable(feature = "trivial_clone", issue = "none")] -unsafe impl TrivialClone for NonZero where T: ZeroablePrimitive {} +#[rustc_const_unstable(feature = "const_clone", issue = "142757")] +unsafe impl const TrivialClone for NonZero where T: ZeroablePrimitive {} #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index ea3ba8cf3a94..b65e40ef4675 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -474,9 +474,9 @@ //! //! In an intrusive doubly-linked list, the collection itself does not own the memory in which //! each of its elements is stored. Instead, each client is free to allocate space for elements it -//! adds to the list in whichever manner it likes, including on the stack! Elements can live on a -//! stack frame that lives shorter than the collection does provided the elements that live in a -//! given stack frame are removed from the list before going out of scope. +//! adds to the list in whichever manner it likes, including on the stack! Elements can be stored +//! in a stack frame shorter-lived than the collection, provided they are removed from the list +//! before that frame goes out of scope. //! //! To make such an intrusive data structure work, every element stores pointers to its predecessor //! and successor within its own data, rather than having the list structure itself managing those diff --git a/library/coretests/tests/cmp.rs b/library/coretests/tests/cmp.rs index 0a14470060c3..888a3cfd57a8 100644 --- a/library/coretests/tests/cmp.rs +++ b/library/coretests/tests/cmp.rs @@ -48,6 +48,37 @@ fn test_ord_min_max_by() { assert_eq!(cmp::max_by(2, -1, f), 2); } +// Regression test for #136307 / #139357: ensure compare() receives (v1, v2), not (v2, v1). +#[test] +fn min_by_compare_argument_order() { + let mut order = vec![]; + let _ = cmp::min_by(1i32, 2, |a, b| { + order.push((*a, *b)); + a.cmp(b) + }); + assert_eq!(order, [(1, 2)]); +} + +#[test] +fn max_by_compare_argument_order() { + let mut order = vec![]; + let _ = cmp::max_by(1i32, 2, |a, b| { + order.push((*a, *b)); + a.cmp(b) + }); + assert_eq!(order, [(1, 2)]); +} + +#[test] +fn minmax_by_compare_argument_order() { + let mut order = vec![]; + let _ = cmp::minmax_by(1i32, 2, |a, b| { + order.push((*a, *b)); + a.cmp(b) + }); + assert_eq!(order, [(1, 2)]); +} + #[test] fn test_ord_min_max_by_key() { let f = |x: &i32| x.abs(); diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 7fc779d3d082..129d2c013cd2 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -14,6 +14,7 @@ #![feature(char_internals)] #![feature(char_max_len)] #![feature(clone_to_uninit)] +#![feature(cmp_minmax)] #![feature(const_array)] #![feature(const_bool)] #![feature(const_cell_traits)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 7cc526b42672..e6467dd0546a 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -637,7 +637,7 @@ pub mod simd { } #[unstable(feature = "autodiff", issue = "124509")] -/// This module provides support for automatic differentiation. +#[doc = include_str!("../../core/src/autodiff.md")] pub mod autodiff { /// This macro handles automatic differentiation. pub use core::autodiff::{autodiff_forward, autodiff_reverse}; diff --git a/library/std/src/sys/pal/motor/mod.rs b/library/std/src/sys/pal/motor/mod.rs index 705413cbe0a7..ac10d81ecfb8 100644 --- a/library/std/src/sys/pal/motor/mod.rs +++ b/library/std/src/sys/pal/motor/mod.rs @@ -42,5 +42,5 @@ pub fn unsupported_err() -> io::Error { } pub fn abort_internal() -> ! { - core::intrinsics::abort(); + moto_rt::process::exit(-1) } diff --git a/license-metadata.json b/license-metadata.json index 4fb59210854e..e8e13fa8d859 100644 --- a/license-metadata.json +++ b/license-metadata.json @@ -114,10 +114,10 @@ { "directories": [], "files": [ + "Fira-LICENSE.txt", "FiraMono-Medium.woff2", "FiraMono-Regular.woff2", "FiraSans-Italic.woff2", - "FiraSans-LICENSE.txt", "FiraSans-Medium.woff2", "FiraSans-MediumItalic.woff2", "FiraSans-Regular.woff2" diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 2c3b5251e12f..36e6432ee82a 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -78,6 +78,7 @@ ":!src/rustdoc-json-types", ":!tests", ":!triagebot.toml", + ":!src/bootstrap/defaults", ]; /// Global configuration for the entire build and/or bootstrap. @@ -2237,11 +2238,7 @@ pub fn download_ci_rustc_commit<'a>( }); match freshness { PathFreshness::LastModifiedUpstream { upstream } => upstream, - PathFreshness::HasLocalModifications { upstream } => { - if if_unchanged { - return None; - } - + PathFreshness::HasLocalModifications { upstream, modifications } => { if dwn_ctx.is_running_on_ci() { eprintln!("CI rustc commit matches with HEAD and we are in CI."); eprintln!( @@ -2250,6 +2247,24 @@ pub fn download_ci_rustc_commit<'a>( return None; } + eprintln!( + "NOTE: detected {} modifications that could affect a build of rustc", + modifications.len() + ); + for file in modifications.iter().take(10) { + eprintln!("- {}", file.display()); + } + if modifications.len() > 10 { + eprintln!("- ... and {} more", modifications.len() - 10); + } + + if if_unchanged { + eprintln!("skipping rustc download due to `download-rustc = 'if-unchanged'`"); + return None; + } else { + eprintln!("downloading unconditionally due to `download-rustc = true`"); + } + upstream } PathFreshness::MissingUpstream => { diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index 277ede8d7745..c281aa94f64e 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -32,6 +32,13 @@ fn get_toml(file: &Path) -> Result { toml::from_str(&contents).and_then(|table: toml::Value| TomlConfig::deserialize(table)) } +fn modified(upstream: impl Into, changes: &[&str]) -> PathFreshness { + PathFreshness::HasLocalModifications { + upstream: upstream.into(), + modifications: changes.iter().copied().map(PathBuf::from).collect(), + } +} + #[test] fn download_ci_llvm() { let config = TestCtx::new().config("check").create_config(); @@ -692,7 +699,7 @@ fn test_pr_ci_changed_in_pr() { let sha = ctx.create_upstream_merge(&["a"]); ctx.create_nonupstream_merge(&["b"]); let src = ctx.check_modifications(&["b"], CiEnv::GitHubActions); - assert_eq!(src, PathFreshness::HasLocalModifications { upstream: sha }); + assert_eq!(src, modified(sha, &["b"])); }); } @@ -712,7 +719,7 @@ fn test_auto_ci_changed_in_pr() { let sha = ctx.create_upstream_merge(&["a"]); ctx.create_upstream_merge(&["b", "c"]); let src = ctx.check_modifications(&["c", "d"], CiEnv::GitHubActions); - assert_eq!(src, PathFreshness::HasLocalModifications { upstream: sha }); + assert_eq!(src, modified(sha, &["c"])); }); } @@ -723,10 +730,7 @@ fn test_local_uncommitted_modifications() { ctx.create_branch("feature"); ctx.modify("a"); - assert_eq!( - ctx.check_modifications(&["a", "d"], CiEnv::None), - PathFreshness::HasLocalModifications { upstream: sha } - ); + assert_eq!(ctx.check_modifications(&["a", "d"], CiEnv::None), modified(sha, &["a"]),); }); } @@ -741,10 +745,7 @@ fn test_local_committed_modifications() { ctx.modify("a"); ctx.commit(); - assert_eq!( - ctx.check_modifications(&["a", "d"], CiEnv::None), - PathFreshness::HasLocalModifications { upstream: sha } - ); + assert_eq!(ctx.check_modifications(&["a", "d"], CiEnv::None), modified(sha, &["a"]),); }); } @@ -757,10 +758,7 @@ fn test_local_committed_modifications_subdirectory() { ctx.modify("a/b/d"); ctx.commit(); - assert_eq!( - ctx.check_modifications(&["a/b"], CiEnv::None), - PathFreshness::HasLocalModifications { upstream: sha } - ); + assert_eq!(ctx.check_modifications(&["a/b"], CiEnv::None), modified(sha, &["a/b/d"]),); }); } @@ -836,11 +834,11 @@ fn test_local_changes_negative_path() { ); assert_eq!( ctx.check_modifications(&[":!c"], CiEnv::None), - PathFreshness::HasLocalModifications { upstream: upstream.clone() } + modified(&upstream, &["b", "d"]), ); assert_eq!( ctx.check_modifications(&[":!d", ":!x"], CiEnv::None), - PathFreshness::HasLocalModifications { upstream } + modified(&upstream, &["b"]), ); }); } diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 389956f14599..b8e00c596f28 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -266,7 +266,7 @@ pub(crate) fn maybe_download_ci_llvm(&self) { }); let llvm_sha = match llvm_freshness { PathFreshness::LastModifiedUpstream { upstream } => upstream, - PathFreshness::HasLocalModifications { upstream } => upstream, + PathFreshness::HasLocalModifications { upstream, modifications: _ } => upstream, PathFreshness::MissingUpstream => { eprintln!("error: could not find commit hash for downloading LLVM"); eprintln!("HELP: maybe your repository history is too shallow?"); diff --git a/src/build_helper/src/git.rs b/src/build_helper/src/git.rs index 330fb465de42..87a52eee49b8 100644 --- a/src/build_helper/src/git.rs +++ b/src/build_helper/src/git.rs @@ -1,4 +1,4 @@ -use std::path::Path; +use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use crate::ci::CiEnv; @@ -38,7 +38,7 @@ pub enum PathFreshness { /// "Local" essentially means "not-upstream" here. /// `upstream` is the latest upstream merge commit that made modifications to the /// set of paths. - HasLocalModifications { upstream: String }, + HasLocalModifications { upstream: String, modifications: Vec }, /// No upstream commit was found. /// This should not happen in most reasonable circumstances, but one never knows. MissingUpstream, @@ -134,21 +134,34 @@ pub fn check_path_modifications( // However, that should be equivalent to checking if something has changed // from the latest upstream commit *that modified `target_paths`*, and // with this approach we do not need to invoke git an additional time. - if has_changed_since(git_dir, &upstream_sha, target_paths) { - Ok(PathFreshness::HasLocalModifications { upstream: upstream_sha }) + let modifications = changes_since(git_dir, &upstream_sha, target_paths)?; + if !modifications.is_empty() { + Ok(PathFreshness::HasLocalModifications { upstream: upstream_sha, modifications }) } else { Ok(PathFreshness::LastModifiedUpstream { upstream: upstream_sha }) } } /// Returns true if any of the passed `paths` have changed since the `base` commit. -pub fn has_changed_since(git_dir: &Path, base: &str, paths: &[&str]) -> bool { - run_git_diff_index(Some(git_dir), |cmd| { - cmd.args(["--quiet", base, "--"]).args(paths); +pub fn changes_since(git_dir: &Path, base: &str, paths: &[&str]) -> Result, String> { + use std::io::BufRead; - // Exit code 0 => no changes - // Exit code 1 => some changes were detected - !cmd.status().expect("cannot run git diff-index").success() + run_git_diff_index(Some(git_dir), |cmd| { + cmd.args([base, "--name-only", "--"]).args(paths); + + let output = cmd.stderr(Stdio::inherit()).output().expect("cannot run git diff-index"); + if !output.status.success() { + return Err(format!("failed to run: {cmd:?}: {:?}", output.status)); + } + + output + .stdout + .lines() + .map(|res| match res { + Ok(line) => Ok(PathBuf::from(line)), + Err(e) => Err(format!("invalid UTF-8 in diff-index: {e:?}")), + }) + .collect() }) } diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 7c0f1d3f2930..97ddde799a75 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -94,6 +94,7 @@ jobs: dist-x86_64-linux: &job-dist-x86_64-linux name: dist-x86_64-linux env: + IMAGE: dist-x86_64-linux CODEGEN_BACKENDS: llvm,cranelift DOCKER_SCRIPT: dist.sh <<: *job-linux-36c-codebuild @@ -150,6 +151,7 @@ pr: # it in each job definition. try: - <<: *job-dist-x86_64-linux + name: dist-x86_64-linux-quick # Jobs that only run when explicitly invoked in one of the following ways: # - comment `@bors try jobs=` diff --git a/src/doc/rustc-dev-guide/src/tests/ci.md b/src/doc/rustc-dev-guide/src/tests/ci.md index 5581b7eb9d8d..b656d9495e0b 100644 --- a/src/doc/rustc-dev-guide/src/tests/ci.md +++ b/src/doc/rustc-dev-guide/src/tests/ci.md @@ -150,7 +150,10 @@ Such a try build will not execute any tests, and it will allow compilation warni It is useful when you want to get an optimized toolchain as fast as possible, for a Crater run or performance benchmarks, even if it might not be working fully correctly. -If you want to do a full build for the default try job, + +The CI job executed in fast try builds has a special suffix (`-quick`), +to distinguish it from a full build of the default try job. +If you want to do the full build instead, specify its job name in a job pattern (explained below). If you want to run custom CI jobs in a try build and make sure that they pass all tests and do diff --git a/src/librustdoc/build.rs b/src/librustdoc/build.rs index 5b497183ae60..94bb0e30fcdb 100644 --- a/src/librustdoc/build.rs +++ b/src/librustdoc/build.rs @@ -27,7 +27,7 @@ fn main() { "static/fonts/FiraSans-MediumItalic.woff2", "static/fonts/FiraMono-Regular.woff2", "static/fonts/FiraMono-Medium.woff2", - "static/fonts/FiraSans-LICENSE.txt", + "static/fonts/Fira-LICENSE.txt", "static/fonts/SourceSerif4-Regular.ttf.woff2", "static/fonts/SourceSerif4-Semibold.ttf.woff2", "static/fonts/SourceSerif4-Bold.ttf.woff2", diff --git a/src/librustdoc/html/static/COPYRIGHT.txt b/src/librustdoc/html/static/COPYRIGHT.txt index 752dab0a3478..0c295b4b0168 100644 --- a/src/librustdoc/html/static/COPYRIGHT.txt +++ b/src/librustdoc/html/static/COPYRIGHT.txt @@ -4,15 +4,16 @@ These documentation pages include resources by third parties. This copyright file applies only to those resources. The following third party resources are included, and carry their own copyright notices and license terms: -* Fira Sans (FiraSans-Regular.woff2, FiraSans-Medium.woff2): +* Fira (FiraSans-Regular.woff2, FiraSans-Medium.woff2, + FiraMono-Regular.woff2, FiraMono-Medium.woff2): Copyright (c) 2014, Mozilla Foundation https://mozilla.org/ - with Reserved Font Name Fira Sans. + with Reserved Font Name < Fira >. Copyright (c) 2014, Telefonica S.A. Licensed under the SIL Open Font License, Version 1.1. - See FiraSans-LICENSE.txt. + See Fira-LICENSE.txt. * rustdoc.css, main.js, and playpen.js: diff --git a/src/librustdoc/html/static/fonts/FiraSans-LICENSE.txt b/src/librustdoc/html/static/fonts/Fira-LICENSE.txt similarity index 100% rename from src/librustdoc/html/static/fonts/FiraSans-LICENSE.txt rename to src/librustdoc/html/static/fonts/Fira-LICENSE.txt diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index e8343b2e21c8..e9968bedebe0 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -4749,11 +4749,16 @@ class DocSearch { })(), "query": parsedQuery, }; - } else if (parsedQuery.error !== null) { + } else if (parsedQuery.error !== null || parsedQuery.foundElems === 0) { + // Symbol-only queries like `==` do not parse into type elements, + // but can still match exact item names or doc aliases. + const others = parsedQuery.userQuery.length === 0 ? + (async function*() {})() : + innerRunNameQuery(currentCrate); return { "in_args": (async function*() {})(), "returned": (async function*() {})(), - "others": innerRunNameQuery(currentCrate), + "others": others, "query": parsedQuery, }; } else { @@ -4764,14 +4769,12 @@ class DocSearch { return { "in_args": (async function*() {})(), "returned": (async function*() {})(), - "others": parsedQuery.foundElems === 0 ? - (async function*() {})() : - innerRunTypeQuery( - parsedQuery.elems, - parsedQuery.returned, - typeInfo, - currentCrate, - ), + "others": innerRunTypeQuery( + parsedQuery.elems, + parsedQuery.returned, + typeInfo, + currentCrate, + ), "query": parsedQuery, }; } diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index e670c2f39e72..84d0162d990b 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -97,7 +97,7 @@ pub(crate) fn for_each(f: impl Fn(&StaticFile) -> Result<(), E>) -> Result<() fira_sans_medium_italic => "static/fonts/FiraSans-MediumItalic.woff2", fira_mono_regular => "static/fonts/FiraMono-Regular.woff2", fira_mono_medium => "static/fonts/FiraMono-Medium.woff2", - fira_sans_license => "static/fonts/FiraSans-LICENSE.txt", + fira_license => "static/fonts/Fira-LICENSE.txt", source_serif_4_regular => "static/fonts/SourceSerif4-Regular.ttf.woff2", source_serif_4_semibold => "static/fonts/SourceSerif4-Semibold.ttf.woff2", source_serif_4_bold => "static/fonts/SourceSerif4-Bold.ttf.woff2", diff --git a/src/tools/wasm-component-ld/Cargo.toml b/src/tools/wasm-component-ld/Cargo.toml index 3f20b9e3fa12..99e84b4562f6 100644 --- a/src/tools/wasm-component-ld/Cargo.toml +++ b/src/tools/wasm-component-ld/Cargo.toml @@ -10,4 +10,4 @@ name = "wasm-component-ld" path = "src/main.rs" [dependencies] -wasm-component-ld = "0.5.21" +wasm-component-ld = "0.5.22" diff --git a/tests/codegen-llvm/dont_codegen_private_const_fn_only_used_in_const_eval.rs b/tests/codegen-llvm/dont_codegen_private_const_fn_only_used_in_const_eval.rs deleted file mode 100644 index df50b4af8098..000000000000 --- a/tests/codegen-llvm/dont_codegen_private_const_fn_only_used_in_const_eval.rs +++ /dev/null @@ -1,27 +0,0 @@ -//! This test checks that we do not monomorphize functions that are only -//! used to evaluate static items, but never used in runtime code. - -//@compile-flags: --crate-type=lib -Copt-level=0 - -#![feature(generic_const_items)] - -const fn foo() {} - -pub static FOO: () = foo(); - -// CHECK-NOT: define{{.*}}foo{{.*}} - -const fn bar() {} - -pub const BAR: () = bar(); - -// CHECK-NOT: define{{.*}}bar{{.*}} - -const fn baz() {} - -#[rustfmt::skip] -pub const BAZ: () = if C { - baz() -}; - -// CHECK: define{{.*}}baz{{.*}} diff --git a/tests/codegen-llvm/private-const-fn-only-used-in-const-eval.rs b/tests/codegen-llvm/private-const-fn-only-used-in-const-eval.rs new file mode 100644 index 000000000000..6dd20cb17c43 --- /dev/null +++ b/tests/codegen-llvm/private-const-fn-only-used-in-const-eval.rs @@ -0,0 +1,38 @@ +// Check that we — where possible — don't codegen functions that are only used to evaluate +// static / const items, but never used in runtime code. + +//@ compile-flags: --crate-type=lib -Copt-level=0 + +#![feature(generic_const_items)] // only used in the last few test cases + +pub static STATIC: () = func0(); +const fn func0() {} +// CHECK-NOT: define{{.*}}func0{{.*}} + +pub const CONSTANT: () = func1(); +const fn func1() {} +// CHECK-NOT: define{{.*}}func1{{.*}} + +// We generally don't want to evaluate the initializer of free const items if they have +// non-region params (and even if we did, const eval would fail anyway with "too polymorphic" +// if the initializer actually referenced such a param). +// +// As a result of not being able to look at the final value, during reachability analysis we +// can't tell for sure if for example certain functions end up in the final value or if they're +// only used during const eval. We fall back to a conservative HIR-based approach. + +// `func2` isn't needed at runtime but the compiler can't tell for the reason mentioned above. +pub const POLY_CONST_0: () = func2(); +const fn func2() {} +// CHECK: define{{.*}}func2{{.*}} + +// `func3` isn't needed at runtime but the compiler can't tell for the reason mentioned above. +pub const POLY_CONST_1: () = if C { func3() }; +const fn func3() {} +// CHECK: define{{.*}}func3{{.*}} + +// `func4` *is* needed at runtime (here, the HIR-based approach gets it right). +pub const POLY_CONST_2: Option = + if C { Some(func4) } else { None }; +const fn func4() {} +// CHECK: define{{.*}}func4{{.*}} diff --git a/tests/run-make/raw-dylib-elf-extern-types/bin.rs b/tests/run-make/raw-dylib-elf-extern-types/bin.rs new file mode 100644 index 000000000000..a62445af4f9c --- /dev/null +++ b/tests/run-make/raw-dylib-elf-extern-types/bin.rs @@ -0,0 +1,21 @@ +#![feature(extern_types)] +#![feature(raw_dylib_elf)] + +use std::ffi::c_char; + +#[link(name = "extern", kind = "raw-dylib")] +unsafe extern "C" { + type FOO; + fn create_foo() -> *const FOO; + fn get_foo(foo: *const FOO) -> c_char; + fn set_foo(foo: *const FOO, value: c_char); +} + +pub fn main() { + let value = unsafe { + let foo = create_foo(); + set_foo(foo, 42); + get_foo(foo) + }; + println!("{}", value); +} diff --git a/tests/run-make/raw-dylib-elf-extern-types/extern.c b/tests/run-make/raw-dylib-elf-extern-types/extern.c new file mode 100644 index 000000000000..0201cd3348ff --- /dev/null +++ b/tests/run-make/raw-dylib-elf-extern-types/extern.c @@ -0,0 +1,16 @@ +typedef struct FOO { + char val; +} FOO; + +FOO* create_foo() { + static FOO foo; + return &foo; +} + +void set_foo(FOO* foo, char val) { + foo->val = val; +} + +char get_foo(FOO* foo) { + return foo->val; +} diff --git a/tests/run-make/raw-dylib-elf-extern-types/output.txt b/tests/run-make/raw-dylib-elf-extern-types/output.txt new file mode 100644 index 000000000000..d81cc0710eb6 --- /dev/null +++ b/tests/run-make/raw-dylib-elf-extern-types/output.txt @@ -0,0 +1 @@ +42 diff --git a/tests/run-make/raw-dylib-elf-extern-types/rmake.rs b/tests/run-make/raw-dylib-elf-extern-types/rmake.rs new file mode 100644 index 000000000000..410982548ca1 --- /dev/null +++ b/tests/run-make/raw-dylib-elf-extern-types/rmake.rs @@ -0,0 +1,18 @@ +//@ only-elf +//@ ignore-cross-compile: Runs a binary. +//@ needs-dynamic-linking +// FIXME(raw_dylib_elf): Debug the failures on other targets. +//@ only-gnu +//@ only-x86_64 + +//@ ignore-rustc-debug-assertions + +use run_make_support::{build_native_dynamic_lib, diff, run, rustc}; + +fn main() { + rustc().crate_type("bin").crate_name("raw_dylib_test").input("bin.rs").run(); + build_native_dynamic_lib("extern"); + + let out_raw = run("raw_dylib_test").stdout_utf8(); + diff().expected_file("output.txt").actual_text("actual", out_raw).normalize(r#"\r"#, "").run(); +} diff --git a/tests/rustdoc-js-std/doc-alias-symbols-150921.js b/tests/rustdoc-js-std/doc-alias-symbols-150921.js new file mode 100644 index 000000000000..5183a7c19fe4 --- /dev/null +++ b/tests/rustdoc-js-std/doc-alias-symbols-150921.js @@ -0,0 +1,24 @@ +// exact-check +// Regression test for . + +const EXPECTED = [ + { + 'query': '==', + 'others': [ + { + 'path': 'std::cmp', + 'name': 'Eq', + 'alias': '==', + 'href': '../std/cmp/trait.Eq.html', + 'is_alias': true, + }, + { + 'path': 'std::cmp', + 'name': 'PartialEq', + 'alias': '==', + 'href': '../std/cmp/trait.PartialEq.html', + 'is_alias': true, + }, + ], + }, +]; diff --git a/tests/rustdoc-js/doc-alias-symbols-150921.js b/tests/rustdoc-js/doc-alias-symbols-150921.js new file mode 100644 index 000000000000..e51d70a28bfe --- /dev/null +++ b/tests/rustdoc-js/doc-alias-symbols-150921.js @@ -0,0 +1,29 @@ +// exact-check +// Regression test for . + +const EXPECTED = [ + { + 'query': '==', + 'others': [ + { + 'path': 'doc_alias_symbols_150921', + 'name': 'OperatorEqEqAlias', + 'alias': '==', + 'href': '../doc_alias_symbols_150921/struct.OperatorEqEqAlias.html', + 'is_alias': true, + }, + ], + }, + { + 'query': '!=', + 'others': [ + { + 'path': 'doc_alias_symbols_150921', + 'name': 'OperatorNotEqAlias', + 'alias': '!=', + 'href': '../doc_alias_symbols_150921/struct.OperatorNotEqAlias.html', + 'is_alias': true, + }, + ], + }, +]; diff --git a/tests/rustdoc-js/doc-alias-symbols-150921.rs b/tests/rustdoc-js/doc-alias-symbols-150921.rs new file mode 100644 index 000000000000..f67b1b3c04e6 --- /dev/null +++ b/tests/rustdoc-js/doc-alias-symbols-150921.rs @@ -0,0 +1,7 @@ +// Regression test for . + +#[doc(alias = "==")] +pub struct OperatorEqEqAlias; + +#[doc(alias = "!=")] +pub struct OperatorNotEqAlias; diff --git a/tests/ui/cfg/suggest-alternative-name-on-target.rs b/tests/ui/cfg/suggest-alternative-name-on-target.rs index e3810dbbc9c3..297321a0e2fe 100644 --- a/tests/ui/cfg/suggest-alternative-name-on-target.rs +++ b/tests/ui/cfg/suggest-alternative-name-on-target.rs @@ -32,8 +32,8 @@ #[cfg(target_abi = "windows")] //~^ ERROR unexpected `cfg` condition value: //~| NOTE see for more information about checking conditional configuration -help: `windows` is an expected value for `target_os` - | -LL - #[cfg(target_abi = "windows")] -LL + #[cfg(target_os = "windows")] - | help: `windows` is an expected value for `target_family` | LL - #[cfg(target_abi = "windows")] LL + #[cfg(target_family = "windows")] | +help: `windows` is an expected value for `target_os` + | +LL - #[cfg(target_abi = "windows")] +LL + #[cfg(target_os = "windows")] + | error: aborting due to 5 previous errors diff --git a/tests/ui/delegation/duplicate-definition-inside-trait-impl.rs b/tests/ui/delegation/duplicate-definition-inside-trait-impl.rs index 9c7afcef3ec1..3c796b91d6fa 100644 --- a/tests/ui/delegation/duplicate-definition-inside-trait-impl.rs +++ b/tests/ui/delegation/duplicate-definition-inside-trait-impl.rs @@ -18,6 +18,8 @@ impl Trait for S { reuse to_reuse::foo { self } reuse Trait::foo; //~^ ERROR duplicate definitions with name `foo` + //~| ERROR: this function takes 1 argument but 0 arguments were supplied + //~| ERROR: mismatched types } fn main() {} diff --git a/tests/ui/delegation/duplicate-definition-inside-trait-impl.stderr b/tests/ui/delegation/duplicate-definition-inside-trait-impl.stderr index a0f157800cb5..83d69d2df600 100644 --- a/tests/ui/delegation/duplicate-definition-inside-trait-impl.stderr +++ b/tests/ui/delegation/duplicate-definition-inside-trait-impl.stderr @@ -9,6 +9,32 @@ LL | reuse to_reuse::foo { self } LL | reuse Trait::foo; | ^^^^^^^^^^^^^^^^^ duplicate definition -error: aborting due to 1 previous error +error[E0061]: this function takes 1 argument but 0 arguments were supplied + --> $DIR/duplicate-definition-inside-trait-impl.rs:19:18 + | +LL | reuse Trait::foo; + | ^^^ argument #1 of type `&_` is missing + | +note: method defined here + --> $DIR/duplicate-definition-inside-trait-impl.rs:5:8 + | +LL | fn foo(&self) -> u32 { 0 } + | ^^^ ----- +help: provide the argument + | +LL | reuse Trait::foo(/* value */); + | +++++++++++++ -For more information about this error, try `rustc --explain E0201`. +error[E0308]: mismatched types + --> $DIR/duplicate-definition-inside-trait-impl.rs:19:18 + | +LL | reuse Trait::foo; + | ^^^- help: consider using a semicolon here: `;` + | | + | expected `()`, found `u32` + | expected `()` because of default return type + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0061, E0201, E0308. +For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/delegation/glob-glob-conflict.rs b/tests/ui/delegation/glob-glob-conflict.rs index 2843bf8c4934..cb07a78b84fe 100644 --- a/tests/ui/delegation/glob-glob-conflict.rs +++ b/tests/ui/delegation/glob-glob-conflict.rs @@ -3,9 +3,13 @@ trait Trait1 { fn method(&self) -> u8; + //~^ ERROR: this function takes 1 argument but 0 arguments were supplied + //~| ERROR: mismatched types } trait Trait2 { fn method(&self) -> u8; + //~^ ERROR: this function takes 1 argument but 0 arguments were supplied + //~| ERROR: mismatched types } trait Trait { fn method(&self) -> u8; diff --git a/tests/ui/delegation/glob-glob-conflict.stderr b/tests/ui/delegation/glob-glob-conflict.stderr index 8c7e5a4b023c..4259d71117b7 100644 --- a/tests/ui/delegation/glob-glob-conflict.stderr +++ b/tests/ui/delegation/glob-glob-conflict.stderr @@ -1,5 +1,5 @@ error[E0201]: duplicate definitions with name `method`: - --> $DIR/glob-glob-conflict.rs:26:5 + --> $DIR/glob-glob-conflict.rs:30:5 | LL | fn method(&self) -> u8; | ----------------------- item in trait @@ -10,7 +10,7 @@ LL | reuse Trait2::*; | ^^^^^^^^^^^^^^^^ duplicate definition error[E0201]: duplicate definitions with name `method`: - --> $DIR/glob-glob-conflict.rs:30:5 + --> $DIR/glob-glob-conflict.rs:34:5 | LL | fn method(&self) -> u8; | ----------------------- item in trait @@ -20,6 +20,57 @@ LL | reuse Trait1::*; LL | reuse Trait1::*; | ^^^^^^^^^^^^^^^^ duplicate definition -error: aborting due to 2 previous errors +error[E0061]: this function takes 1 argument but 0 arguments were supplied + --> $DIR/glob-glob-conflict.rs:10:8 + | +LL | fn method(&self) -> u8; + | ^^^^^^ argument #1 of type `&_` is missing + | +note: method defined here + --> $DIR/glob-glob-conflict.rs:10:8 + | +LL | fn method(&self) -> u8; + | ^^^^^^ ---- +help: provide the argument + | +LL | fn method(/* value */)(&self) -> u8; + | +++++++++++++ -For more information about this error, try `rustc --explain E0201`. +error[E0308]: mismatched types + --> $DIR/glob-glob-conflict.rs:10:8 + | +LL | fn method(&self) -> u8; + | ^^^^^^- help: consider using a semicolon here: `;` + | | + | expected `()`, found `u8` + | expected `()` because of default return type + +error[E0061]: this function takes 1 argument but 0 arguments were supplied + --> $DIR/glob-glob-conflict.rs:5:8 + | +LL | fn method(&self) -> u8; + | ^^^^^^ argument #1 of type `&_` is missing + | +note: method defined here + --> $DIR/glob-glob-conflict.rs:5:8 + | +LL | fn method(&self) -> u8; + | ^^^^^^ ---- +help: provide the argument + | +LL | fn method(/* value */)(&self) -> u8; + | +++++++++++++ + +error[E0308]: mismatched types + --> $DIR/glob-glob-conflict.rs:5:8 + | +LL | fn method(&self) -> u8; + | ^^^^^^- help: consider using a semicolon here: `;` + | | + | expected `()`, found `u8` + | expected `()` because of default return type + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0061, E0201, E0308. +For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/delegation/ice-issue-124347.rs b/tests/ui/delegation/ice-issue-124347.rs index 6bf3a08ba5b4..271634711834 100644 --- a/tests/ui/delegation/ice-issue-124347.rs +++ b/tests/ui/delegation/ice-issue-124347.rs @@ -4,9 +4,11 @@ trait Trait { reuse Trait::foo { &self.0 } //~^ ERROR failed to resolve delegation callee + //~| ERROR: this function takes 0 arguments but 1 argument was supplied } reuse foo; //~^ ERROR failed to resolve delegation callee +//~| WARN: function cannot return without recursing fn main() {} diff --git a/tests/ui/delegation/ice-issue-124347.stderr b/tests/ui/delegation/ice-issue-124347.stderr index 40be6be4abfa..90ad839e662c 100644 --- a/tests/ui/delegation/ice-issue-124347.stderr +++ b/tests/ui/delegation/ice-issue-124347.stderr @@ -5,10 +5,40 @@ LL | reuse Trait::foo { &self.0 } | ^^^ error: failed to resolve delegation callee - --> $DIR/ice-issue-124347.rs:9:7 + --> $DIR/ice-issue-124347.rs:10:7 | LL | reuse foo; | ^^^ -error: aborting due to 2 previous errors +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/ice-issue-124347.rs:5:18 + | +LL | reuse Trait::foo { &self.0 } + | ^^^ ------- unexpected argument + | +note: associated function defined here + --> $DIR/ice-issue-124347.rs:5:18 + | +LL | reuse Trait::foo { &self.0 } + | ^^^ +help: remove the extra argument + | +LL - reuse Trait::foo { &self.0 } +LL + reuse Trait::fo&self.0 } + | +warning: function cannot return without recursing + --> $DIR/ice-issue-124347.rs:10:7 + | +LL | reuse foo; + | ^^^ + | | + | cannot return without recursing + | recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/delegation/recursive-delegation-errors.rs b/tests/ui/delegation/recursive-delegation-errors.rs index 194182e20ed0..da295b09caea 100644 --- a/tests/ui/delegation/recursive-delegation-errors.rs +++ b/tests/ui/delegation/recursive-delegation-errors.rs @@ -5,6 +5,7 @@ mod first_mod { reuse foo; //~^ ERROR failed to resolve delegation callee + //~| WARN: function cannot return without recursing } mod second_mod { @@ -33,8 +34,10 @@ mod fourth_mod { trait Trait { reuse Trait::foo as bar; //~^ ERROR encountered a cycle during delegation signature resolution + //~| ERROR: type annotations needed reuse Trait::bar as foo; //~^ ERROR encountered a cycle during delegation signature resolution + //~| ERROR: type annotations needed } } @@ -48,6 +51,9 @@ trait GlobReuse { //~^ ERROR encountered a cycle during delegation signature resolution //~| ERROR encountered a cycle during delegation signature resolution //~| ERROR encountered a cycle during delegation signature resolution + //~| ERROR: type annotations needed + //~| ERROR: type annotations needed + //~| ERROR: type annotations needed } } diff --git a/tests/ui/delegation/recursive-delegation-errors.stderr b/tests/ui/delegation/recursive-delegation-errors.stderr index 9c4e316745ae..bf446bd872f7 100644 --- a/tests/ui/delegation/recursive-delegation-errors.stderr +++ b/tests/ui/delegation/recursive-delegation-errors.stderr @@ -5,94 +5,147 @@ LL | reuse foo; | ^^^ error: encountered a cycle during delegation signature resolution - --> $DIR/recursive-delegation-errors.rs:11:11 + --> $DIR/recursive-delegation-errors.rs:12:11 | LL | reuse foo as bar; | ^^^ error: encountered a cycle during delegation signature resolution - --> $DIR/recursive-delegation-errors.rs:13:11 + --> $DIR/recursive-delegation-errors.rs:14:11 | LL | reuse bar as foo; | ^^^ error: encountered a cycle during delegation signature resolution - --> $DIR/recursive-delegation-errors.rs:18:11 + --> $DIR/recursive-delegation-errors.rs:19:11 | LL | reuse foo as foo1; | ^^^ error: encountered a cycle during delegation signature resolution - --> $DIR/recursive-delegation-errors.rs:20:11 + --> $DIR/recursive-delegation-errors.rs:21:11 | LL | reuse foo1 as foo2; | ^^^^ error: encountered a cycle during delegation signature resolution - --> $DIR/recursive-delegation-errors.rs:22:11 + --> $DIR/recursive-delegation-errors.rs:23:11 | LL | reuse foo2 as foo3; | ^^^^ error: encountered a cycle during delegation signature resolution - --> $DIR/recursive-delegation-errors.rs:24:11 + --> $DIR/recursive-delegation-errors.rs:25:11 | LL | reuse foo3 as foo4; | ^^^^ error: encountered a cycle during delegation signature resolution - --> $DIR/recursive-delegation-errors.rs:26:11 + --> $DIR/recursive-delegation-errors.rs:27:11 | LL | reuse foo4 as foo5; | ^^^^ error: encountered a cycle during delegation signature resolution - --> $DIR/recursive-delegation-errors.rs:28:11 + --> $DIR/recursive-delegation-errors.rs:29:11 | LL | reuse foo5 as foo; | ^^^^ error: encountered a cycle during delegation signature resolution - --> $DIR/recursive-delegation-errors.rs:34:22 + --> $DIR/recursive-delegation-errors.rs:35:22 | LL | reuse Trait::foo as bar; | ^^^ error: encountered a cycle during delegation signature resolution - --> $DIR/recursive-delegation-errors.rs:36:22 + --> $DIR/recursive-delegation-errors.rs:38:22 | LL | reuse Trait::bar as foo; | ^^^ error: encountered a cycle during delegation signature resolution - --> $DIR/recursive-delegation-errors.rs:42:30 + --> $DIR/recursive-delegation-errors.rs:45:30 | LL | reuse super::fifth_mod::{bar as foo, foo as bar}; | ^^^ error: encountered a cycle during delegation signature resolution - --> $DIR/recursive-delegation-errors.rs:42:42 + --> $DIR/recursive-delegation-errors.rs:45:42 | LL | reuse super::fifth_mod::{bar as foo, foo as bar}; | ^^^ error: encountered a cycle during delegation signature resolution - --> $DIR/recursive-delegation-errors.rs:47:27 + --> $DIR/recursive-delegation-errors.rs:50:27 | LL | reuse GlobReuse::{foo as bar, bar as goo, goo as foo}; | ^^^ error: encountered a cycle during delegation signature resolution - --> $DIR/recursive-delegation-errors.rs:47:39 + --> $DIR/recursive-delegation-errors.rs:50:39 | LL | reuse GlobReuse::{foo as bar, bar as goo, goo as foo}; | ^^^ error: encountered a cycle during delegation signature resolution - --> $DIR/recursive-delegation-errors.rs:47:51 + --> $DIR/recursive-delegation-errors.rs:50:51 | LL | reuse GlobReuse::{foo as bar, bar as goo, goo as foo}; | ^^^ -error: aborting due to 16 previous errors +error[E0283]: type annotations needed + --> $DIR/recursive-delegation-errors.rs:35:22 + | +LL | reuse Trait::foo as bar; + | ^^^ cannot infer type + | + = note: the type must implement `fourth_mod::Trait` +error[E0283]: type annotations needed + --> $DIR/recursive-delegation-errors.rs:38:22 + | +LL | reuse Trait::bar as foo; + | ^^^ cannot infer type + | + = note: the type must implement `fourth_mod::Trait` + +error[E0283]: type annotations needed + --> $DIR/recursive-delegation-errors.rs:50:27 + | +LL | reuse GlobReuse::{foo as bar, bar as goo, goo as foo}; + | ^^^ cannot infer type + | + = note: the type must implement `GlobReuse` + +error[E0283]: type annotations needed + --> $DIR/recursive-delegation-errors.rs:50:39 + | +LL | reuse GlobReuse::{foo as bar, bar as goo, goo as foo}; + | ^^^ cannot infer type + | + = note: the type must implement `GlobReuse` + +error[E0283]: type annotations needed + --> $DIR/recursive-delegation-errors.rs:50:51 + | +LL | reuse GlobReuse::{foo as bar, bar as goo, goo as foo}; + | ^^^ cannot infer type + | + = note: the type must implement `GlobReuse` + +warning: function cannot return without recursing + --> $DIR/recursive-delegation-errors.rs:6:11 + | +LL | reuse foo; + | ^^^ + | | + | cannot return without recursing + | recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error: aborting due to 21 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/delegation/unlowered-path-ice-154820.rs b/tests/ui/delegation/unlowered-path-ice-154820.rs new file mode 100644 index 000000000000..a527b17cf6c4 --- /dev/null +++ b/tests/ui/delegation/unlowered-path-ice-154820.rs @@ -0,0 +1,12 @@ +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +reuse foo:: < { //~ ERROR: failed to resolve delegation callee + //~^ ERROR: function takes 0 generic arguments but 1 generic argument was supplied + fn foo() {} + reuse foo; + //~^ ERROR: the name `foo` is defined multiple times + } + >; + +fn main() {} diff --git a/tests/ui/delegation/unlowered-path-ice-154820.stderr b/tests/ui/delegation/unlowered-path-ice-154820.stderr new file mode 100644 index 000000000000..fbcb3ca9c71c --- /dev/null +++ b/tests/ui/delegation/unlowered-path-ice-154820.stderr @@ -0,0 +1,40 @@ +error[E0428]: the name `foo` is defined multiple times + --> $DIR/unlowered-path-ice-154820.rs:7:5 + | +LL | fn foo() {} + | -------- previous definition of the value `foo` here +LL | reuse foo; + | ^^^^^^^^^^ `foo` redefined here + | + = note: `foo` must be defined only once in the value namespace of this block + +error: failed to resolve delegation callee + --> $DIR/unlowered-path-ice-154820.rs:4:7 + | +LL | reuse foo:: < { + | ^^^ + +error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/unlowered-path-ice-154820.rs:4:7 + | +LL | reuse foo:: < { + | _______^^^- + | | | + | | expected 0 generic arguments +LL | | +LL | | fn foo() {} +LL | | reuse foo; +... | +LL | | >; + | |___- help: remove the unnecessary generics + | +note: function defined here, with 0 generic parameters + --> $DIR/unlowered-path-ice-154820.rs:4:7 + | +LL | reuse foo:: < { + | ^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0107, E0428. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-const-items/def-site-eval.fail.stderr b/tests/ui/generic-const-items/def-site-eval.fail.stderr index e39fbdf7802d..1fae0790c9fd 100644 --- a/tests/ui/generic-const-items/def-site-eval.fail.stderr +++ b/tests/ui/generic-const-items/def-site-eval.fail.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation panicked: explicit panic - --> $DIR/def-site-eval.rs:13:20 + --> $DIR/def-site-eval.rs:32:20 | LL | const _<'_a>: () = panic!(); | ^^^^^^^^ evaluation of `_` failed here diff --git a/tests/ui/generic-const-items/def-site-eval.rs b/tests/ui/generic-const-items/def-site-eval.rs index fa3ef5907b26..44440450b600 100644 --- a/tests/ui/generic-const-items/def-site-eval.rs +++ b/tests/ui/generic-const-items/def-site-eval.rs @@ -1,15 +1,32 @@ -//! Test that we only evaluate free const items (their def site to be clear) -//! whose generics don't require monomorphization. -#![feature(generic_const_items)] -#![expect(incomplete_features)] - +// Test that we don't evaluate the initializer of free const items if they have +// non-region generic parameters (i.e., ones that "require monomorphization"). +// +// To peek behind the curtains for a bit, at the time of writing there are three places where we +// usually evaluate the initializer: "analysis", mono item collection & reachability analysis. +// We must ensure that all of them take the generics into account. +// //@ revisions: fail pass //@[pass] check-pass +#![feature(generic_const_items)] +#![expect(incomplete_features)] +#![crate_type = "lib"] // (*) + +// All of these constants are intentionally unused since we want to test the +// behavior at the def site, not at use sites. + const _<_T>: () = panic!(); const _: () = panic!(); +// Check *public* const items specifically to exercise reachability analysis which normally +// evaluates const initializers to look for function pointers in the final const value. +// +// (*): While reachability analysis also runs for purely binary crates (to find e.g., extern items) +// setting the crate type to library (1) makes the case below 'more realistic' since +// hypothetical downstream crates that require runtime MIR could actually exist. +// (2) It ensures that we exercise the relevant part of the compiler under test. +pub const K<_T>: () = panic!(); +pub const Q: () = loop {}; + #[cfg(fail)] const _<'_a>: () = panic!(); //[fail]~ ERROR evaluation panicked: explicit panic - -fn main() {} diff --git a/tests/ui/generic-const-items/trivially-unsatisfied-bounds-0.rs b/tests/ui/generic-const-items/trivially-unsatisfied-bounds-0.rs deleted file mode 100644 index 102c7b1e5f93..000000000000 --- a/tests/ui/generic-const-items/trivially-unsatisfied-bounds-0.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![feature(generic_const_items, trivial_bounds)] -#![allow(incomplete_features)] - -// Ensure that we check if trivial bounds on const items hold or not. - -const UNUSABLE: () = () //~ ERROR entering unreachable code -where - String: Copy; - -fn main() { - let _ = UNUSABLE; //~ ERROR the trait bound `String: Copy` is not satisfied -} diff --git a/tests/ui/generic-const-items/trivially-unsatisfied-bounds-1.rs b/tests/ui/generic-const-items/trivially-unsatisfied-bounds-1.rs deleted file mode 100644 index ebe97a65bbf3..000000000000 --- a/tests/ui/generic-const-items/trivially-unsatisfied-bounds-1.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![feature(generic_const_items, trivial_bounds)] -#![allow(incomplete_features, dead_code, trivial_bounds)] - -// FIXME(generic_const_items): This looks like a bug to me. I expected that we wouldn't emit any -// errors. I thought we'd skip the evaluation of consts whose bounds don't hold. - -const UNUSED: () = () -where - String: Copy; -//~^^^ ERROR unreachable code - -fn main() {} diff --git a/tests/ui/generic-const-items/trivially-unsatisfied-bounds-1.stderr b/tests/ui/generic-const-items/trivially-unsatisfied-bounds-1.stderr deleted file mode 100644 index a5f6dd980bdc..000000000000 --- a/tests/ui/generic-const-items/trivially-unsatisfied-bounds-1.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0080]: entering unreachable code - --> $DIR/trivially-unsatisfied-bounds-1.rs:7:1 - | -LL | / const UNUSED: () = () -LL | | where -LL | | String: Copy; - | |_________________^ evaluation of `UNUSED` failed here - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/generic-const-items/trivially-unsatisfied-bounds-0.stderr b/tests/ui/generic-const-items/trivially-unsatisfied-bounds.mentioned.stderr similarity index 60% rename from tests/ui/generic-const-items/trivially-unsatisfied-bounds-0.stderr rename to tests/ui/generic-const-items/trivially-unsatisfied-bounds.mentioned.stderr index e5c3bbb0c7db..d0d65a030841 100644 --- a/tests/ui/generic-const-items/trivially-unsatisfied-bounds-0.stderr +++ b/tests/ui/generic-const-items/trivially-unsatisfied-bounds.mentioned.stderr @@ -1,25 +1,25 @@ error[E0080]: entering unreachable code - --> $DIR/trivially-unsatisfied-bounds-0.rs:6:1 + --> $DIR/trivially-unsatisfied-bounds.rs:17:1 | LL | / const UNUSABLE: () = () LL | | where -LL | | String: Copy; - | |_________________^ evaluation of `UNUSABLE` failed here +LL | | for<'_delay> String: Copy; + | |______________________________^ evaluation of `UNUSABLE` failed here error[E0277]: the trait bound `String: Copy` is not satisfied - --> $DIR/trivially-unsatisfied-bounds-0.rs:11:13 + --> $DIR/trivially-unsatisfied-bounds.rs:24:13 | LL | let _ = UNUSABLE; | ^^^^^^^^ the trait `Copy` is not implemented for `String` | note: required by a bound in `UNUSABLE` - --> $DIR/trivially-unsatisfied-bounds-0.rs:8:13 + --> $DIR/trivially-unsatisfied-bounds.rs:19:26 | LL | const UNUSABLE: () = () | -------- required by a bound in this constant LL | where -LL | String: Copy; - | ^^^^ required by this bound in `UNUSABLE` +LL | for<'_delay> String: Copy; + | ^^^^ required by this bound in `UNUSABLE` error: aborting due to 2 previous errors diff --git a/tests/ui/generic-const-items/trivially-unsatisfied-bounds.rs b/tests/ui/generic-const-items/trivially-unsatisfied-bounds.rs new file mode 100644 index 000000000000..9a0c6d0feeca --- /dev/null +++ b/tests/ui/generic-const-items/trivially-unsatisfied-bounds.rs @@ -0,0 +1,33 @@ +// Exercise trivially unsatisfied bounds on free const items. +// Their interaction with the evaluation of the initializer is interesting. +// +//@ revisions: mentioned unmentioned + +#![feature(generic_const_items)] + +// FIXME(generic_const_items): Try to get rid of error "entering unreachable error", it's +// unnecessary and actually caused by MIR pass `ImpossiblePredicates` replacing the body with the +// terminator `Unreachable` due to the unsatisfied bound which is subsequently reached. +// +// NOTE(#142293): However, don't think about suppressing the evaluation of the initializer if the +// bounds are "impossible". That'd be a SemVer hazard since it could cause downstream to fail to +// compile if upstream added a new trait impl which is undesirable[^1]. +// [^1]: Strictly speaking that's already possible due to the one-impl rule. + +const UNUSABLE: () = () //~ ERROR entering unreachable code +where + for<'_delay> String: Copy; + +fn scope() { + // Ensure that we successfully reject references of consts with trivially unsatisfied bounds. + #[cfg(mentioned)] + let _ = UNUSABLE; //[mentioned]~ ERROR the trait bound `String: Copy` is not satisfied +} + +const _BAD: () = <() as Unimplemented>::CT +where + for<'_delay> (): Unimplemented; + +trait Unimplemented { const CT: (); } + +fn main() {} diff --git a/tests/ui/generic-const-items/trivially-unsatisfied-bounds.unmentioned.stderr b/tests/ui/generic-const-items/trivially-unsatisfied-bounds.unmentioned.stderr new file mode 100644 index 000000000000..14bf489b15fb --- /dev/null +++ b/tests/ui/generic-const-items/trivially-unsatisfied-bounds.unmentioned.stderr @@ -0,0 +1,11 @@ +error[E0080]: entering unreachable code + --> $DIR/trivially-unsatisfied-bounds.rs:17:1 + | +LL | / const UNUSABLE: () = () +LL | | where +LL | | for<'_delay> String: Copy; + | |______________________________^ evaluation of `UNUSABLE` failed here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/impl-trait/associated-impl-trait-type-into-emplacable.rs b/tests/ui/impl-trait/associated-impl-trait-type-into-emplacable.rs new file mode 100644 index 000000000000..2c63b2743a0c --- /dev/null +++ b/tests/ui/impl-trait/associated-impl-trait-type-into-emplacable.rs @@ -0,0 +1,52 @@ +//! add regression test for . + +//@ check-pass + +#![feature(impl_trait_in_assoc_type)] + +use std::marker::PhantomData; + +struct Emp { + phantom: PhantomData<(*const T, F)>, +} + +impl Emp { + fn from_fn(_: F) -> Emp { + loop {} + } + + fn unsize(self) -> Emp { + Emp::from_fn(|| ()) + } +} + +trait IntoEmplacable { + type Closure; + + fn into_emplacable(self) -> Emp; +} + +impl IntoEmplacable for Emp { + type Closure = impl Sized; + + fn into_emplacable(self) -> Emp { + self.unsize() + } +} + +impl Into as IntoEmplacable>::Closure>> for Emp { + fn into(self) -> Emp as IntoEmplacable>::Closure> { + self.into_emplacable() + } +} + +fn box_new_with(_: Emp) {} + +pub struct Arr; +pub struct Slice; + +pub fn foo() { + let e: Emp = Emp { phantom: PhantomData }; + box_new_with(e.into()); +} +fn main() {} diff --git a/tests/ui/issues/issue-32377.rs b/tests/ui/intrinsics/transmute-phantomdata-generic-unequal-size.rs similarity index 83% rename from tests/ui/issues/issue-32377.rs rename to tests/ui/intrinsics/transmute-phantomdata-generic-unequal-size.rs index 6737f9820efd..203894a7217a 100644 --- a/tests/ui/issues/issue-32377.rs +++ b/tests/ui/intrinsics/transmute-phantomdata-generic-unequal-size.rs @@ -1,3 +1,4 @@ +//! regression test for //@ normalize-stderr: "\d+ bits" -> "N bits" use std::mem; diff --git a/tests/ui/issues/issue-32377.stderr b/tests/ui/intrinsics/transmute-phantomdata-generic-unequal-size.stderr similarity index 85% rename from tests/ui/issues/issue-32377.stderr rename to tests/ui/intrinsics/transmute-phantomdata-generic-unequal-size.stderr index 01a81cea1eca..76fda2f2c417 100644 --- a/tests/ui/issues/issue-32377.stderr +++ b/tests/ui/intrinsics/transmute-phantomdata-generic-unequal-size.stderr @@ -1,5 +1,5 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/issue-32377.rs:15:14 + --> $DIR/transmute-phantomdata-generic-unequal-size.rs:16:14 | LL | unsafe { mem::transmute(x) } | ^^^^^^^^^^^^^^ diff --git a/tests/ui/issues/issue-25746-bool-transmute.rs b/tests/ui/transmute/transmute-bool-u8.rs similarity index 73% rename from tests/ui/issues/issue-25746-bool-transmute.rs rename to tests/ui/transmute/transmute-bool-u8.rs index 046dcf83f62d..502683b6d136 100644 --- a/tests/ui/issues/issue-25746-bool-transmute.rs +++ b/tests/ui/transmute/transmute-bool-u8.rs @@ -1,4 +1,5 @@ -//@ run-pass +//! regression test for +//@ build-pass #![allow(unnecessary_transmutes)] use std::mem::transmute;