diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 0a2a34d932f61..b9411a3269a57 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -235,14 +235,14 @@ impl AttributeExt for Attribute { } } - fn deprecation_note(&self) -> Option { + fn deprecation_note(&self) -> Option { match &self.kind { AttrKind::Normal(normal) if normal.item.path == sym::deprecated => { let meta = &normal.item; // #[deprecated = "..."] if let Some(s) = meta.value_str() { - return Some(s); + return Some(Ident { name: s, span: meta.span() }); } // #[deprecated(note = "...")] @@ -252,7 +252,7 @@ impl AttributeExt for Attribute { && mi.path == sym::note && let Some(s) = mi.value_str() { - return Some(s); + return Some(Ident { name: s, span: mi.span }); } } } @@ -905,7 +905,7 @@ pub trait AttributeExt: Debug { /// Returns the deprecation note if this is deprecation attribute. /// * `#[deprecated = "note"]` returns `Some("note")`. /// * `#[deprecated(note = "note", ...)]` returns `Some("note")`. - fn deprecation_note(&self) -> Option; + fn deprecation_note(&self) -> Option; fn is_proc_macro_attr(&self) -> bool { [sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive] diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index 36213e68a52be..4b4358ab0a9ca 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -23,6 +23,9 @@ attr_parsing_doc_alias_malformed = attr_parsing_doc_alias_start_end = {$attr_str} cannot start or end with ' ' +attr_parsing_doc_attr_not_crate_level = + `#![doc({$attr_name} = "...")]` isn't allowed as a crate-level attribute + attr_parsing_doc_attribute_not_attribute = nonexistent builtin attribute `{$attribute}` used in `#[doc(attribute = "...")]` .help = only existing builtin attributes are allowed in core/std diff --git a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs index 2d79e3a103d6e..e01377d247bb6 100644 --- a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs +++ b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs @@ -13,14 +13,14 @@ fn get( name: Symbol, param_span: Span, arg: &ArgParser, - item: &Option, -) -> Option { + item: Option, +) -> Option { if item.is_some() { cx.duplicate_key(param_span, name); return None; } if let Some(v) = arg.name_value() { - if let Some(value_str) = v.value_as_str() { + if let Some(value_str) = v.value_as_ident() { Some(value_str) } else { cx.expected_string_literal(v.value_span, Some(&v.value_as_lit())); @@ -72,7 +72,7 @@ impl SingleAttributeParser for DeprecationParser { let features = cx.features(); let mut since = None; - let mut note = None; + let mut note: Option = None; let mut suggestion = None; let is_rustc = features.staged_api(); @@ -92,10 +92,16 @@ impl SingleAttributeParser for DeprecationParser { match ident_name { Some(name @ sym::since) => { - since = Some(get(cx, name, param.span(), param.args(), &since)?); + since = Some(get(cx, name, param.span(), param.args(), since)?.name); } Some(name @ sym::note) => { - note = Some(get(cx, name, param.span(), param.args(), ¬e)?); + note = Some(get( + cx, + name, + param.span(), + param.args(), + note.map(|ident| ident.name), + )?); } Some(name @ sym::suggestion) => { if !features.deprecated_suggestion() { @@ -107,7 +113,7 @@ impl SingleAttributeParser for DeprecationParser { } suggestion = - Some(get(cx, name, param.span(), param.args(), &suggestion)?); + Some(get(cx, name, param.span(), param.args(), suggestion)?.name); } _ => { cx.expected_specific_argument( @@ -124,7 +130,7 @@ impl SingleAttributeParser for DeprecationParser { } } ArgParser::NameValue(v) => { - let Some(value) = v.value_as_str() else { + let Some(value) = v.value_as_ident() else { cx.expected_string_literal(v.value_span, Some(v.value_as_lit())); return None; }; diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index 16dbb04b48ebd..6cc4ac35eadb1 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -1,5 +1,6 @@ use rustc_ast::ast::{AttrStyle, LitKind, MetaItemLit}; use rustc_feature::template; +use rustc_hir::Target; use rustc_hir::attrs::{ AttributeKind, CfgEntry, CfgHideShow, CfgInfo, DocAttribute, DocInline, HideOrShow, }; @@ -12,8 +13,8 @@ use super::{AcceptMapping, AttributeParser}; use crate::context::{AcceptContext, FinalizeContext, Stage}; use crate::parser::{ArgParser, MetaItemOrLitParser, MetaItemParser, OwnedPathParser}; use crate::session_diagnostics::{ - DocAliasBadChar, DocAliasEmpty, DocAliasMalformed, DocAliasStartEnd, DocAttributeNotAttribute, - DocKeywordNotKeyword, + DocAliasBadChar, DocAliasEmpty, DocAliasMalformed, DocAliasStartEnd, DocAttrNotCrateLevel, + DocAttributeNotAttribute, DocKeywordNotKeyword, }; fn check_keyword(cx: &mut AcceptContext<'_, '_, S>, keyword: Symbol, span: Span) -> bool { @@ -43,16 +44,39 @@ fn check_attribute( false } -fn parse_keyword_and_attribute( +/// Checks that an attribute is *not* used at the crate level. Returns `true` if valid. +fn check_attr_not_crate_level( + cx: &mut AcceptContext<'_, '_, S>, + span: Span, + attr_name: Symbol, +) -> bool { + if cx.shared.target.is_some_and(|target| target == Target::Crate) { + cx.emit_err(DocAttrNotCrateLevel { span, attr_name }); + return false; + } + true +} + +/// Checks that an attribute is used at the crate level. Returns `true` if valid. +fn check_attr_crate_level(cx: &mut AcceptContext<'_, '_, S>, span: Span) -> bool { + if cx.shared.target.is_some_and(|target| target != Target::Crate) { + cx.emit_lint( + rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, + AttributeLintKind::AttrCrateLevelOnly, + span, + ); + return false; + } + true +} + +fn parse_keyword_and_attribute( cx: &mut AcceptContext<'_, '_, S>, path: &OwnedPathParser, args: &ArgParser, attr_value: &mut Option<(Symbol, Span)>, - callback: F, -) where - S: Stage, - F: FnOnce(&mut AcceptContext<'_, '_, S>, Symbol, Span) -> bool, -{ + attr_name: Symbol, +) { let Some(nv) = args.name_value() else { cx.expected_name_value(args.span().unwrap_or(path.span()), path.word_sym()); return; @@ -63,16 +87,26 @@ fn parse_keyword_and_attribute( return; }; - if !callback(cx, value, nv.value_span) { + let ret = if attr_name == sym::keyword { + check_keyword(cx, value, nv.value_span) + } else { + check_attribute(cx, value, nv.value_span) + }; + if !ret { return; } + let span = path.span(); if attr_value.is_some() { - cx.duplicate_key(path.span(), path.word_sym().unwrap()); + cx.duplicate_key(span, path.word_sym().unwrap()); return; } - *attr_value = Some((value, path.span())); + if !check_attr_not_crate_level(cx, span, attr_name) { + return; + } + + *attr_value = Some((value, span)); } #[derive(Default, Debug)] @@ -102,6 +136,10 @@ impl DocParser { return; } + if !check_attr_crate_level(cx, path.span()) { + return; + } + self.attribute.no_crate_inject = Some(path.span()) } Some(sym::attr) => { @@ -155,6 +193,9 @@ impl DocParser { cx.emit_err(DocAliasStartEnd { span, attr_str }); return; } + if !check_attr_not_crate_level(cx, span, sym::alias) { + return; + } if let Some(first_definition) = self.attribute.aliases.get(&alias).copied() { cx.emit_lint( @@ -366,7 +407,33 @@ impl DocParser { self.attribute.$ident = Some(path.span()); }}; } - macro_rules! string_arg { + macro_rules! no_args_and_not_crate_level { + ($ident: ident) => {{ + if let Err(span) = args.no_args() { + cx.expected_no_args(span); + return; + } + let span = path.span(); + if !check_attr_not_crate_level(cx, span, sym::$ident) { + return; + } + self.attribute.$ident = Some(span); + }}; + } + macro_rules! no_args_and_crate_level { + ($ident: ident) => {{ + if let Err(span) = args.no_args() { + cx.expected_no_args(span); + return; + } + let span = path.span(); + if !check_attr_crate_level(cx, span) { + return; + } + self.attribute.$ident = Some(span); + }}; + } + macro_rules! string_arg_and_crate_level { ($ident: ident) => {{ let Some(nv) = args.name_value() else { cx.expected_name_value(args.span().unwrap_or(path.span()), path.word_sym()); @@ -378,6 +445,10 @@ impl DocParser { return; }; + if !check_attr_crate_level(cx, path.span()) { + return; + } + // FIXME: It's errorring when the attribute is passed multiple times on the command // line. // The right fix for this would be to only check this rule if the attribute is @@ -394,12 +465,14 @@ impl DocParser { match path.word_sym() { Some(sym::alias) => self.parse_alias(cx, path, args), Some(sym::hidden) => no_args!(hidden), - Some(sym::html_favicon_url) => string_arg!(html_favicon_url), - Some(sym::html_logo_url) => string_arg!(html_logo_url), - Some(sym::html_no_source) => no_args!(html_no_source), - Some(sym::html_playground_url) => string_arg!(html_playground_url), - Some(sym::html_root_url) => string_arg!(html_root_url), - Some(sym::issue_tracker_base_url) => string_arg!(issue_tracker_base_url), + Some(sym::html_favicon_url) => string_arg_and_crate_level!(html_favicon_url), + Some(sym::html_logo_url) => string_arg_and_crate_level!(html_logo_url), + Some(sym::html_no_source) => no_args_and_crate_level!(html_no_source), + Some(sym::html_playground_url) => string_arg_and_crate_level!(html_playground_url), + Some(sym::html_root_url) => string_arg_and_crate_level!(html_root_url), + Some(sym::issue_tracker_base_url) => { + string_arg_and_crate_level!(issue_tracker_base_url) + } Some(sym::inline) => self.parse_inline(cx, path, args, DocInline::Inline), Some(sym::no_inline) => self.parse_inline(cx, path, args, DocInline::NoInline), Some(sym::masked) => no_args!(masked), @@ -410,18 +483,18 @@ impl DocParser { path, args, &mut self.attribute.keyword, - check_keyword, + sym::keyword, ), Some(sym::attribute) => parse_keyword_and_attribute( cx, path, args, &mut self.attribute.attribute, - check_attribute, + sym::attribute, ), - Some(sym::fake_variadic) => no_args!(fake_variadic), - Some(sym::search_unbox) => no_args!(search_unbox), - Some(sym::rust_logo) => no_args!(rust_logo), + Some(sym::fake_variadic) => no_args_and_not_crate_level!(fake_variadic), + Some(sym::search_unbox) => no_args_and_not_crate_level!(search_unbox), + Some(sym::rust_logo) => no_args_and_crate_level!(rust_logo), Some(sym::auto_cfg) => self.parse_auto_cfg(cx, path, args), Some(sym::test) => { let Some(list) = args.list() else { diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index fafac7ea909da..e02d71a261581 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -47,6 +47,7 @@ pub(crate) mod link_attrs; pub(crate) mod lint_helpers; pub(crate) mod loop_match; pub(crate) mod macro_attrs; +pub(crate) mod must_not_suspend; pub(crate) mod must_use; pub(crate) mod no_implicit_prelude; pub(crate) mod no_link; diff --git a/compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs b/compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs new file mode 100644 index 0000000000000..8456ce7977587 --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs @@ -0,0 +1,35 @@ +use super::prelude::*; + +pub(crate) struct MustNotSuspendParser; + +impl SingleAttributeParser for MustNotSuspendParser { + const PATH: &[rustc_span::Symbol] = &[sym::must_not_suspend]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Struct), + Allow(Target::Enum), + Allow(Target::Union), + Allow(Target::Trait), + ]); + const TEMPLATE: AttributeTemplate = template!(Word, List: &["count"]); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + let reason = match args { + ArgParser::NameValue(reason) => match reason.value_as_str() { + Some(val) => Some(val), + None => { + cx.expected_nv_or_no_args(reason.value_span); + return None; + } + }, + ArgParser::NoArgs => None, + ArgParser::List(list) => { + cx.expected_nv_or_no_args(list.span); + return None; + } + }; + + Some(AttributeKind::MustNotSupend { reason }) + } +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 00921cf54cd87..6b1b1d484283f 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -51,6 +51,7 @@ use crate::attributes::macro_attrs::{ AllowInternalUnsafeParser, CollapseDebugInfoParser, MacroEscapeParser, MacroExportParser, MacroUseParser, }; +use crate::attributes::must_not_suspend::MustNotSuspendParser; use crate::attributes::must_use::MustUseParser; use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser; use crate::attributes::no_link::NoLinkParser; @@ -89,7 +90,6 @@ use crate::session_diagnostics::{ AttributeParseError, AttributeParseErrorReason, ParsedDescription, }; use crate::target_checking::AllowedTargets; - type GroupType = LazyLock>; pub(super) struct GroupTypeInner { @@ -208,6 +208,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, @@ -655,6 +656,7 @@ pub struct SharedContext<'p, 'sess, S: Stage> { pub(crate) target_span: Span, /// The id ([`NodeId`] if `S` is `Early`, [`HirId`] if `S` is `Late`) of the syntactical component this attribute was applied to pub(crate) target_id: S::Id, + pub(crate) target: Option, pub(crate) emit_lint: &'p mut dyn FnMut(AttributeLint), } diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index 7602e3c4598a3..b7137c60e63af 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -218,6 +218,7 @@ impl<'sess> AttributeParser<'sess, Early> { cx: &mut parser, target_span, target_id: target_node_id, + target: None, emit_lint: &mut emit_lint, }, attr_span, @@ -378,6 +379,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { cx: self, target_span, target_id, + target: Some(target), emit_lint: &mut emit_lint, }, attr_span, @@ -429,6 +431,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { cx: self, target_span, target_id, + target: Some(target), emit_lint: &mut emit_lint, }, all_attrs: &attr_paths, diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index d79579fdf0b78..68265649d1823 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -322,6 +322,13 @@ impl NameValueParser { self.value_as_lit().kind.str() } + /// If the value is a string literal, it will return its value associated with its span (an + /// `Ident` in short). + pub fn value_as_ident(&self) -> Option { + let meta_item = self.value_as_lit(); + meta_item.kind.str().map(|name| Ident { name, span: meta_item.span }) + } + pub fn args_span(&self) -> Span { self.eq_span.to(self.value_span) } diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 20d00a82cadb2..85e7891b1e64b 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -47,6 +47,14 @@ pub(crate) struct DocAliasStartEnd<'a> { pub attr_str: &'a str, } +#[derive(Diagnostic)] +#[diag(attr_parsing_doc_attr_not_crate_level)] +pub(crate) struct DocAttrNotCrateLevel { + #[primary_span] + pub span: Span, + pub attr_name: Symbol, +} + #[derive(Diagnostic)] #[diag(attr_parsing_doc_keyword_not_keyword)] #[help] diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 7820198f2dcf2..2a8efd25a375f 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -1124,9 +1124,10 @@ fn get_backend_from_raw_matches( let backend_name = debug_flags .iter() .find_map(|x| x.strip_prefix("codegen-backend=").or(x.strip_prefix("codegen_backend="))); + let unstable_options = debug_flags.iter().find(|x| *x == "unstable-options").is_some(); let target = parse_target_triple(early_dcx, matches); let sysroot = Sysroot::new(matches.opt_str("sysroot").map(PathBuf::from)); - let target = config::build_target_config(early_dcx, &target, sysroot.path()); + let target = config::build_target_config(early_dcx, &target, sysroot.path(), unstable_options); get_codegen_backend(early_dcx, &sysroot, backend_name, &target) } diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 15a668bd91994..8d18d335b355b 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -136,7 +136,7 @@ pub enum IntType { pub struct Deprecation { pub since: DeprecatedSince, /// The note to issue a reason. - pub note: Option, + pub note: Option, /// A text snippet used to completely replace any use of the deprecated item in an expression. /// /// This is currently unstable. @@ -824,6 +824,9 @@ pub enum AttributeKind { /// Represents `#[move_size_limit]` MoveSizeLimit { attr_span: Span, limit_span: Span, limit: Limit }, + /// Represents `#[must_not_suspend]` + MustNotSupend { reason: Option }, + /// Represents `#[must_use]`. MustUse { span: Span, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 233aee54adbb6..33655f4f00635 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -71,6 +71,7 @@ impl AttributeKind { Marker(..) => No, MayDangle(..) => No, MoveSizeLimit { .. } => No, + MustNotSupend { .. } => Yes, MustUse { .. } => Yes, Naked(..) => No, NoCore(..) => No, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index dac4c7e3965a7..05ecb35bc5a4f 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1410,7 +1410,7 @@ impl AttributeExt for Attribute { } #[inline] - fn deprecation_note(&self) -> Option { + fn deprecation_note(&self) -> Option { match &self { Attribute::Parsed(AttributeKind::Deprecation { deprecation, .. }) => deprecation.note, _ => None, diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index b2c4a91581979..1e46db1188b7e 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -435,6 +435,7 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se &early_dcx, &config.opts.target_triple, config.opts.sysroot.path(), + config.opts.unstable_opts.unstable_options, ); let file_loader = config.file_loader.unwrap_or_else(|| Box::new(RealFileLoader)); let path_mapping = config.opts.file_path_mapping(); diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index a78b0e8e1ed81..0f60e86e0ca3c 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -46,6 +46,7 @@ where &early_dcx, &sessopts.target_triple, sessopts.sysroot.path(), + sessopts.unstable_opts.unstable_options, ); let hash_kind = sessopts.unstable_opts.src_hash_algorithm(&target); let checksum_hash_kind = sessopts.unstable_opts.checksum_hash_algorithm(); diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index b49b090272d45..9b0b1abc91df6 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -40,6 +40,11 @@ lint_atomic_ordering_load = atomic loads cannot have `Release` or `AcqRel` order lint_atomic_ordering_store = atomic stores cannot have `Acquire` or `AcqRel` ordering .help = consider using ordering modes `Release`, `SeqCst` or `Relaxed` +lint_attr_crate_level = + this attribute can only be applied at the crate level + .suggestion = to apply to the crate, use an inner attribute + .note = read for more information + lint_bad_attribute_argument = bad attribute argument lint_bad_opt_access = {$msg} diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index f622de7f84d93..5745f0d4eddec 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -417,5 +417,7 @@ pub fn decorate_attribute_lint( } &AttributeLintKind::DocTestLiteral => lints::DocTestLiteral.decorate_lint(diag), + + &AttributeLintKind::AttrCrateLevelOnly => lints::AttrCrateLevelOnly.decorate_lint(diag), } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 841b11c996872..33e9375ec71bd 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3312,3 +3312,8 @@ pub(crate) struct DocTestUnknown { #[derive(LintDiagnostic)] #[diag(lint_doc_test_literal)] pub(crate) struct DocTestLiteral; + +#[derive(LintDiagnostic)] +#[diag(lint_attr_crate_level)] +#[note] +pub(crate) struct AttrCrateLevelOnly; diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 7b41cfbb43ef0..c8713b23633f7 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -820,6 +820,7 @@ pub enum AttributeLintKind { name: Symbol, }, DocTestLiteral, + AttrCrateLevelOnly, } pub type RegisteredTools = FxIndexSet; diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 6c30ce0ddb3d3..004d73da8cbda 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -242,7 +242,6 @@ use crate::rmeta::{METADATA_HEADER, MetadataBlob, rustc_version}; pub(crate) struct CrateLocator<'a> { // Immutable per-session configuration. only_needs_metadata: bool, - sysroot: &'a Path, metadata_loader: &'a dyn MetadataLoader, cfg_version: &'static str, @@ -318,7 +317,6 @@ impl<'a> CrateLocator<'a> { CrateLocator { only_needs_metadata, - sysroot: sess.opts.sysroot.path(), metadata_loader, cfg_version: sess.cfg_version, crate_name, @@ -670,33 +668,6 @@ impl<'a> CrateLocator<'a> { continue; } - // Ok so at this point we've determined that `(lib, kind)` above is - // a candidate crate to load, and that `slot` is either none (this - // is the first crate of its kind) or if some the previous path has - // the exact same hash (e.g., it's the exact same crate). - // - // In principle these two candidate crates are exactly the same so - // we can choose either of them to link. As a stupidly gross hack, - // however, we favor crate in the sysroot. - // - // You can find more info in rust-lang/rust#39518 and various linked - // issues, but the general gist is that during testing libstd the - // compilers has two candidates to choose from: one in the sysroot - // and one in the deps folder. These two crates are the exact same - // crate but if the compiler chooses the one in the deps folder - // it'll cause spurious errors on Windows. - // - // As a result, we favor the sysroot crate here. Note that the - // candidates are all canonicalized, so we canonicalize the sysroot - // as well. - if let Some(prev) = &ret { - let sysroot = self.sysroot; - let sysroot = try_canonicalize(sysroot).unwrap_or_else(|_| sysroot.to_path_buf()); - if prev.starts_with(&sysroot) { - continue; - } - } - // We error eagerly here. If we're locating a rlib, then in theory the full metadata // could still be in a (later resolved) dylib. In practice, if the rlib and dylib // were produced in a way where one has full metadata and the other hasn't, it would diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 18520089e3ea3..63bbd1a0b8549 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -185,7 +185,7 @@ pub fn early_report_macro_deprecation( let diag = BuiltinLintDiag::DeprecatedMacro { suggestion: depr.suggestion, suggestion_span: span, - note: depr.note, + note: depr.note.map(|ident| ident.name), path, since_kind: deprecated_since_kind(is_in_effect, depr.since), }; @@ -228,7 +228,7 @@ fn late_report_deprecation( }), kind: def_kind.to_owned(), path: def_path, - note: depr.note, + note: depr.note.map(|ident| ident.name), since_kind: deprecated_since_kind(is_in_effect, depr.since), }; tcx.emit_node_span_lint(lint, hir_id, method_span, diag); diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 7fad380ba5a19..705551c58f320 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -64,9 +64,9 @@ use itertools::izip; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::pluralize; -use rustc_hir as hir; +use rustc_hir::attrs::AttributeKind; use rustc_hir::lang_items::LangItem; -use rustc_hir::{CoroutineDesugaring, CoroutineKind}; +use rustc_hir::{self as hir, CoroutineDesugaring, CoroutineKind, find_attr}; use rustc_index::bit_set::{BitMatrix, DenseBitSet, GrowableBitSet}; use rustc_index::{Idx, IndexVec, indexvec}; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; @@ -85,7 +85,6 @@ use rustc_mir_dataflow::{ }; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::source_map::dummy_spanned; -use rustc_span::symbol::sym; use rustc_span::{DUMMY_SP, Span}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::TyCtxtInferExt as _; @@ -1989,11 +1988,11 @@ fn check_must_not_suspend_def( hir_id: hir::HirId, data: SuspendCheckData<'_>, ) -> bool { - if let Some(attr) = tcx.get_attr(def_id, sym::must_not_suspend) { - let reason = attr.value_str().map(|s| errors::MustNotSuspendReason { - span: data.source_span, - reason: s.as_str().to_string(), - }); + if let Some(reason_str) = + find_attr!(tcx.get_all_attrs(def_id), AttributeKind::MustNotSupend {reason} => reason) + { + let reason = + reason_str.map(|s| errors::MustNotSuspendReason { span: data.source_span, reason: s }); tcx.emit_node_span_lint( rustc_session::lint::builtin::MUST_NOT_SUSPEND, hir_id, diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 21a6c4d653bc5..d4c58f7fe05d9 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -323,7 +323,7 @@ impl<'a> LintDiagnostic<'a, ()> for MustNotSupend<'_, '_> { pub(crate) struct MustNotSuspendReason { #[primary_span] pub span: Span, - pub reason: String, + pub reason: Symbol, } #[derive(Diagnostic)] diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 39ad541ee85a9..11e4b8b20222d 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -29,11 +29,6 @@ passes_attr_application_struct_union = attribute should be applied to a struct or union .label = not a struct or union -passes_attr_crate_level = - this attribute can only be applied at the crate level - .suggestion = to apply to the crate, use an inner attribute - .note = read for more information - passes_autodiff_attr = `#[autodiff]` should be applied to a function .label = not a function @@ -108,9 +103,6 @@ passes_doc_alias_bad_location = passes_doc_alias_not_an_alias = `#[doc(alias = "{$attr_str}"]` is the same as the item's name -passes_doc_attr_not_crate_level = - `#![doc({$attr_name} = "...")]` isn't allowed as a crate-level attribute - passes_doc_fake_variadic_not_valid = `#[doc(fake_variadic)]` must be used on the first of a set of tuple or fn pointer trait impls with varying arity @@ -376,10 +368,6 @@ passes_must_implement_not_function_note = all `#[rustc_must_implement_one_of]` a passes_must_implement_not_function_span_note = required by this annotation -passes_must_not_suspend = - `must_not_suspend` attribute should be applied to a struct, enum, union, or trait - .label = is not a struct, enum, union, or trait - passes_no_main_function = `main` function not found in crate `{$crate_name}` .here_is_main = here is a function named `main` diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 1d48785169d74..8f80822a81ab1 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -308,6 +308,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::ThreadLocal | AttributeKind::CfiEncoding { .. } | AttributeKind::RustcHasIncoherentInherentImpls + | AttributeKind::MustNotSupend { .. } ) => { /* do nothing */ } Attribute::Unparsed(attr_item) => { style = Some(attr_item.style); @@ -325,7 +326,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | [sym::rustc_dirty, ..] | [sym::rustc_if_this_changed, ..] | [sym::rustc_then_this_would_need, ..] => self.check_rustc_dirty_clean(attr), - [sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target), [sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => { self.check_autodiff(hir_id, attr, span, target) } @@ -1062,29 +1062,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Checks that an attribute is *not* used at the crate level. Returns `true` if valid. - fn check_attr_not_crate_level(&self, span: Span, hir_id: HirId, attr_name: &str) -> bool { - if CRATE_HIR_ID == hir_id { - self.dcx().emit_err(errors::DocAttrNotCrateLevel { span, attr_name }); - return false; - } - true - } - - /// Checks that an attribute is used at the crate level. Returns `true` if valid. - fn check_attr_crate_level(&self, span: Span, hir_id: HirId) -> bool { - if hir_id != CRATE_HIR_ID { - self.tcx.emit_node_span_lint( - INVALID_DOC_ATTRIBUTES, - hir_id, - span, - errors::AttrCrateLevelOnly {}, - ); - return false; - } - true - } - /// Runs various checks on `#[doc]` attributes. /// /// `specified_inline` should be initialized to `None` and kept for the scope @@ -1100,9 +1077,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { inline, // FIXME: currently unchecked cfg: _, - // already check in attr_parsing + // already checked in attr_parsing auto_cfg: _, - // already check in attr_parsing + // already checked in attr_parsing auto_cfg_change: _, fake_variadic, keyword, @@ -1110,70 +1087,48 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // FIXME: currently unchecked notable_trait: _, search_unbox, - html_favicon_url, - html_logo_url, - html_playground_url, - html_root_url, - html_no_source, - issue_tracker_base_url, + // already checked in attr_parsing + html_favicon_url: _, + // already checked in attr_parsing + html_logo_url: _, + // already checked in attr_parsing + html_playground_url: _, + // already checked in attr_parsing + html_root_url: _, + // already checked in attr_parsing + html_no_source: _, + // already checked in attr_parsing + issue_tracker_base_url: _, rust_logo, // allowed anywhere test_attrs: _, - no_crate_inject, + // already checked in attr_parsing + no_crate_inject: _, attribute, } = attr; for (alias, span) in aliases { - if self.check_attr_not_crate_level(*span, hir_id, "alias") { - self.check_doc_alias_value(*span, hir_id, target, *alias); - } + self.check_doc_alias_value(*span, hir_id, target, *alias); } - if let Some((_, span)) = keyword - && self.check_attr_not_crate_level(*span, hir_id, "keyword") - { + if let Some((_, span)) = keyword { self.check_doc_keyword_and_attribute(*span, hir_id, "keyword"); } - if let Some((_, span)) = attribute - && self.check_attr_not_crate_level(*span, hir_id, "attribute") - { + if let Some((_, span)) = attribute { self.check_doc_keyword_and_attribute(*span, hir_id, "attribute"); } - if let Some(span) = fake_variadic - && self.check_attr_not_crate_level(*span, hir_id, "fake_variadic") - { + if let Some(span) = fake_variadic { self.check_doc_fake_variadic(*span, hir_id); } - if let Some(span) = search_unbox - && self.check_attr_not_crate_level(*span, hir_id, "search_unbox") - { + if let Some(span) = search_unbox { self.check_doc_search_unbox(*span, hir_id); } - for i in [ - html_favicon_url, - html_logo_url, - html_playground_url, - issue_tracker_base_url, - html_root_url, - ] { - if let Some((_, span)) = i { - self.check_attr_crate_level(*span, hir_id); - } - } - - for i in [html_no_source, no_crate_inject] { - if let Some(span) = i { - self.check_attr_crate_level(*span, hir_id); - } - } - self.check_doc_inline(hir_id, target, inline); if let Some(span) = rust_logo - && self.check_attr_crate_level(*span, hir_id) && !self.tcx.features().rustdoc_internals() { feature_err( @@ -1197,16 +1152,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Checks if `#[must_not_suspend]` is applied to a struct, enum, union, or trait. - fn check_must_not_suspend(&self, attr: &Attribute, span: Span, target: Target) { - match target { - Target::Struct | Target::Enum | Target::Union | Target::Trait => {} - _ => { - self.dcx().emit_err(errors::MustNotSuspend { attr_span: attr.span(), span }); - } - } - } - /// Checks if `#[may_dangle]` is applied to a lifetime or type generic parameter in `Drop` impl. fn check_may_dangle(&self, hir_id: HirId, attr_span: Span) { if let hir::Node::GenericParam(param) = self.tcx.hir_node(hir_id) diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index ace738c559a42..1f3f0d7f8884f 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -179,14 +179,6 @@ pub(crate) struct DocMaskedNotExternCrateSelf { pub item_span: Span, } -#[derive(Diagnostic)] -#[diag(passes_doc_attr_not_crate_level)] -pub(crate) struct DocAttrNotCrateLevel<'a> { - #[primary_span] - pub span: Span, - pub attr_name: &'a str, -} - #[derive(Diagnostic)] #[diag(passes_both_ffi_const_and_pure, code = E0757)] pub(crate) struct BothFfiConstAndPure { @@ -194,15 +186,6 @@ pub(crate) struct BothFfiConstAndPure { pub attr_span: Span, } -#[derive(Diagnostic)] -#[diag(passes_must_not_suspend)] -pub(crate) struct MustNotSuspend { - #[primary_span] - pub attr_span: Span, - #[label] - pub span: Span, -} - #[derive(LintDiagnostic)] #[diag(passes_link)] #[warning] @@ -1095,11 +1078,6 @@ pub(crate) struct UnnecessaryPartialStableFeature { #[note] pub(crate) struct IneffectiveUnstableImpl; -#[derive(LintDiagnostic)] -#[diag(passes_attr_crate_level)] -#[note] -pub(crate) struct AttrCrateLevelOnly {} - /// "sanitize attribute not allowed here" #[derive(Diagnostic)] #[diag(passes_sanitize_attribute_not_allowed)] diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index f0dc5b9ac48c5..f8b9ae040568a 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1589,8 +1589,9 @@ pub fn build_target_config( early_dcx: &EarlyDiagCtxt, target: &TargetTuple, sysroot: &Path, + unstable_options: bool, ) -> Target { - match Target::search(target, sysroot) { + match Target::search(target, sysroot, unstable_options) { Ok((target, warnings)) => { for warning in warnings.warning_messages() { early_dcx.early_warn(warning) diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 1a0ec600af47d..1d5b36fc61b8b 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1002,8 +1002,11 @@ pub fn build_session( } let host_triple = TargetTuple::from_tuple(config::host_tuple()); - let (host, target_warnings) = Target::search(&host_triple, sopts.sysroot.path()) - .unwrap_or_else(|e| dcx.handle().fatal(format!("Error loading host specification: {e}"))); + let (host, target_warnings) = + Target::search(&host_triple, sopts.sysroot.path(), sopts.unstable_opts.unstable_options) + .unwrap_or_else(|e| { + dcx.handle().fatal(format!("Error loading host specification: {e}")) + }); for warning in target_warnings.warning_messages() { dcx.handle().warn(warning) } diff --git a/compiler/rustc_target/src/asm/s390x.rs b/compiler/rustc_target/src/asm/s390x.rs index 410590b722b14..37176c0d73eaf 100644 --- a/compiler/rustc_target/src/asm/s390x.rs +++ b/compiler/rustc_target/src/asm/s390x.rs @@ -42,13 +42,13 @@ impl S390xInlineAsmRegClass { ) -> &'static [(InlineAsmType, Option)] { match self { Self::reg | Self::reg_addr => types! { _: I8, I16, I32, I64; }, - Self::freg => types! { _: F32, F64; }, + Self::freg => types! { _: F16, F32, F64; }, Self::vreg => { if allow_experimental_reg { // non-clobber-only vector register support is unstable. types! { - vector: I32, F32, I64, F64, I128, F128, - VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2); + vector: I32, F16, F32, I64, F64, I128, F128, + VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2); } } else { &[] diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 89c9fdc935cc5..ab52a7d63301a 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -3298,10 +3298,19 @@ impl Target { pub fn search( target_tuple: &TargetTuple, sysroot: &Path, + unstable_options: bool, ) -> Result<(Target, TargetWarnings), String> { use std::{env, fs}; - fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> { + fn load_file( + path: &Path, + unstable_options: bool, + ) -> Result<(Target, TargetWarnings), String> { + if !unstable_options { + return Err( + "custom targets are unstable and require `-Zunstable-options`".to_string() + ); + } let contents = fs::read_to_string(path).map_err(|e| e.to_string())?; Target::from_json(&contents) } @@ -3325,7 +3334,7 @@ impl Target { for dir in env::split_paths(&target_path) { let p = dir.join(&path); if p.is_file() { - return load_file(&p); + return load_file(&p, unstable_options); } } @@ -3338,7 +3347,7 @@ impl Target { Path::new("target.json"), ]); if p.is_file() { - return load_file(&p); + return load_file(&p, unstable_options); } Err(format!("could not find specification for target {target_tuple:?}")) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 511e9e85b5f60..81b921b3744f4 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -5323,12 +5323,9 @@ fn hint_missing_borrow<'tcx>( ty = mut_ty.ty; left -= 1; } - let sugg = if left == 0 { - (span, String::new()) - } else { - (arg.span, expected_arg.to_string()) - }; - remove_borrow.push(sugg); + if left == 0 { + remove_borrow.push((span, String::new())); + } } } } diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index e0001153a6e7f..320eb97f83a43 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -256,7 +256,7 @@ use crate::{fmt, intrinsics, ptr, slice}; /// /// # Validity /// -/// `MaybeUninit` has no validity requirements –- any sequence of [bytes] of +/// `MaybeUninit` has no validity requirements – any sequence of [bytes] of /// the appropriate length, initialized or uninitialized, are a valid /// representation. /// diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 8976154c61db9..11e0a83bd7ec0 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1742,7 +1742,7 @@ impl *mut [T] { /// that is at least `mid * size_of::()` bytes long. Not upholding these /// requirements is *[undefined behavior]* even if the resulting pointers are not used. /// - /// Since `len` being in-bounds it is not a safety invariant of `*mut [T]` the + /// Since `len` being in-bounds is not a safety invariant of `*mut [T]` the /// safety requirements of this method are the same as for [`split_at_mut_unchecked`]. /// The explicit bounds check is only as useful as `len` is correct. /// diff --git a/library/std/src/sys/net/connection/uefi/tcp.rs b/library/std/src/sys/net/connection/uefi/tcp.rs index 3e79aa0491872..1e58db0d70468 100644 --- a/library/std/src/sys/net/connection/uefi/tcp.rs +++ b/library/std/src/sys/net/connection/uefi/tcp.rs @@ -9,6 +9,9 @@ pub(crate) enum Tcp { V4(tcp4::Tcp4), } +// SAFETY: UEFI has no threads. +unsafe impl Send for Tcp {} + impl Tcp { pub(crate) fn connect(addr: &SocketAddr, timeout: Option) -> io::Result { match addr { diff --git a/src/doc/nomicon b/src/doc/nomicon index 5b3a9d084cbc6..050c002a360fa 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 5b3a9d084cbc64e54da87e3eec7c7faae0e48ba9 +Subproject commit 050c002a360fa45b701ea34feed7a860dc8a41bf diff --git a/src/doc/reference b/src/doc/reference index 6363385ac4ebe..28b5a54419985 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 6363385ac4ebe1763f1e6fb2063c0b1db681a072 +Subproject commit 28b5a54419985f03db5294de5eede71b6665b594 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 2e02f22a10e7e..8de6ff811315a 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 2e02f22a10e7eeb758e6aba484f13d0f1988a3e5 +Subproject commit 8de6ff811315ac3a96ebe01d74057382e42ffdee diff --git a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs index d41a57d6f7474..6f4ce4415f04a 100644 --- a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs +++ b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs @@ -27,7 +27,7 @@ static REGEX_SPLIT: LazyLock = LazyLock::new(|| Regex::new(r"([^\.\d\-\*]\.|[^r]\?|!)\s").unwrap()); // list elements, numbered (1.) or not (- and *) static REGEX_LIST_ENTRY: LazyLock = - LazyLock::new(|| Regex::new(r"^\s*(\d\.|\-|\*)\s+").unwrap()); + LazyLock::new(|| Regex::new(r"^\s*(\d\.|\-|\*|\d\))\s+").unwrap()); fn main() -> Result<()> { let cli = Cli::parse(); @@ -80,6 +80,7 @@ fn ignore(line: &str, in_code_block: bool) -> bool { in_code_block || line.to_lowercase().contains("e.g.") || line.to_lowercase().contains("n.b.") + || line.contains(" etc.") || line.contains("i.e.") || line.contains("et. al") || line.contains('|') @@ -189,9 +190,11 @@ must! be. split? ignore | tables ignore e.g. and ignore i.e. and +ignore etc. and ignore E.g. too - list. entry * list. entry + 1) list. entry ``` some code. block ``` @@ -212,11 +215,14 @@ split? ignore | tables ignore e.g. and ignore i.e. and +ignore etc. and ignore E.g. too - list. entry * list. entry + 1) list. + entry ``` some code. block ``` diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index 7b444a9ef5f11..b53a66c667517 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -85c8ff69cb3efd950395cc444a54bbbdad668865 +44a5b55557c26353f388400d7da95527256fe260 diff --git a/src/doc/rustc-dev-guide/src/ambig-unambig-ty-and-consts.md b/src/doc/rustc-dev-guide/src/ambig-unambig-ty-and-consts.md index 64a15b7f9aa82..33b685861df37 100644 --- a/src/doc/rustc-dev-guide/src/ambig-unambig-ty-and-consts.md +++ b/src/doc/rustc-dev-guide/src/ambig-unambig-ty-and-consts.md @@ -6,7 +6,7 @@ parse. ```rust fn func(arg: T) { - // ^ Unambig type position + // ^ Unambig type position let a: _ = arg; // ^ Unambig type position @@ -108,4 +108,4 @@ This has a number of benefits: [`ast::AnonConst`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/struct.AnonConst.html [`hir::GenericArg::Infer`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/enum.GenericArg.html#variant.Infer [`ast::ExprKind::Underscore`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/enum.ExprKind.html#variant.Underscore -[`ast::Ty::Path(N)`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/enum.TyKind.html#variant.Path \ No newline at end of file +[`ast::Ty::Path(N)`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/enum.TyKind.html#variant.Path diff --git a/src/doc/rustc-dev-guide/src/building/new-target.md b/src/doc/rustc-dev-guide/src/building/new-target.md index 436aec8ee265b..d0ed787f520ad 100644 --- a/src/doc/rustc-dev-guide/src/building/new-target.md +++ b/src/doc/rustc-dev-guide/src/building/new-target.md @@ -1,7 +1,7 @@ # Adding a new target -These are a set of steps to add support for a new target. There are -numerous end states and paths to get there, so not all sections may be +These are a set of steps to add support for a new target. +There are numerous end states and paths to get there, so not all sections may be relevant to your desired goal. See also the associated documentation in the [target tier policy]. @@ -11,8 +11,8 @@ See also the associated documentation in the [target tier policy]. ## Specifying a new LLVM For very new targets, you may need to use a different fork of LLVM -than what is currently shipped with Rust. In that case, navigate to -the `src/llvm-project` git submodule (you might need to run `./x +than what is currently shipped with Rust. +In that case, navigate to the `src/llvm-project` git submodule (you might need to run `./x check` at least once so the submodule is updated), check out the appropriate commit for your fork, then commit that new submodule reference in the main Rust repository. @@ -31,11 +31,9 @@ git commit -m 'Use my custom LLVM' ### Using pre-built LLVM If you have a local LLVM checkout that is already built, you may be -able to configure Rust to treat your build as the system LLVM to avoid -redundant builds. +able to configure Rust to treat your build as the system LLVM to avoid redundant builds. -You can tell Rust to use a pre-built version of LLVM using the `target` section -of `bootstrap.toml`: +You can tell Rust to use a pre-built version of LLVM using the `target` section of `bootstrap.toml`: ```toml [target.x86_64-unknown-linux-gnu] @@ -48,8 +46,8 @@ before, though they may be different from your system: - `/usr/bin/llvm-config-8` - `/usr/lib/llvm-8/bin/llvm-config` -Note that you need to have the LLVM `FileCheck` tool installed, which is used -for codegen tests. This tool is normally built with LLVM, but if you use your +Note that you need to have the LLVM `FileCheck` tool installed, which is used for codegen tests. +This tool is normally built with LLVM, but if you use your own preinstalled LLVM, you will need to provide `FileCheck` in some other way. On Debian-based systems, you can install the `llvm-N-tools` package (where `N` is the LLVM version number, e.g. `llvm-8-tools`). Alternately, you can specify @@ -58,8 +56,8 @@ or you can disable codegen test with the `codegen-tests` item in `bootstrap.toml ## Creating a target specification -You should start with a target JSON file. You can see the specification -for an existing target using `--print target-spec-json`: +You should start with a target JSON file. +You can see the specification for an existing target using `--print target-spec-json`: ``` rustc -Z unstable-options --target=wasm32-unknown-unknown --print target-spec-json @@ -70,42 +68,22 @@ Save that JSON to a file and modify it as appropriate for your target. ### Adding a target specification Once you have filled out a JSON specification and been able to compile -somewhat successfully, you can copy the specification into the -compiler itself. +somewhat successfully, you can copy the specification into the compiler itself. You will need to add a line to the big table inside of the -`supported_targets` macro in the `rustc_target::spec` module. You -will then add a corresponding file for your new target containing a +`supported_targets` macro in the `rustc_target::spec` module. +You will then add a corresponding file for your new target containing a `target` function. Look for existing targets to use as examples. -After adding your target to the `rustc_target` crate you may want to add -`core`, `std`, ... with support for your new target. In that case you will -probably need access to some `target_*` cfg. Unfortunately when building with -stage0 (a precompiled compiler), you'll get an error that the target cfg is -unexpected because stage0 doesn't know about the new target specification and -we pass `--check-cfg` in order to tell it to check. - -To fix the errors you will need to manually add the unexpected value to the -different `Cargo.toml` in `library/{std,alloc,core}/Cargo.toml`. Here is an -example for adding `NEW_TARGET_ARCH` as `target_arch`: - -*`library/std/Cargo.toml`*: -```diff - [lints.rust.unexpected_cfgs] - level = "warn" - check-cfg = [ - 'cfg(bootstrap)', -- 'cfg(target_arch, values("xtensa"))', -+ # #[cfg(bootstrap)] NEW_TARGET_ARCH -+ 'cfg(target_arch, values("xtensa", "NEW_TARGET_ARCH"))', -``` - -To use this target in bootstrap, we need to explicitly add the target triple to the `STAGE0_MISSING_TARGETS` -list in `src/bootstrap/src/core/sanity.rs`. This is necessary because the default compiler bootstrap uses does -not recognize the new target we just added. Therefore, it should be added to `STAGE0_MISSING_TARGETS` so that the -bootstrap is aware that this target is not yet supported by the stage0 compiler. +To use this target in bootstrap, we need to explicitly add the target triple to +the `STAGE0_MISSING_TARGETS` list in `src/bootstrap/src/core/sanity.rs`. +This is necessary because the default bootstrap compiler (typically a beta compiler) +does not recognize the new target we just added. +Therefore, it should be added to +`STAGE0_MISSING_TARGETS` so that the bootstrap is aware that this target is not +yet supported by the stage0 compiler. ```diff const STAGE0_MISSING_TARGETS: &[&str] = &[ @@ -116,9 +94,9 @@ const STAGE0_MISSING_TARGETS: &[&str] = &[ ## Patching crates You may need to make changes to crates that the compiler depends on, -such as [`libc`][] or [`cc`][]. If so, you can use Cargo's -[`[patch]`][patch] ability. For example, if you want to use an -unreleased version of `libc`, you can add it to the top-level +such as [`libc`][] or [`cc`][]. +If so, you can use Cargo's [`[patch]`][patch] ability. +For example, if you want to use an unreleased version of `libc`, you can add it to the top-level `Cargo.toml` file: ```diff @@ -138,9 +116,9 @@ index 1e83f05e0ca..4d0172071c1 100644 After this, run `cargo update -p libc` to update the lockfiles. Beware that if you patch to a local `path` dependency, this will enable -warnings for that dependency. Some dependencies are not warning-free, and due -to the `deny-warnings` setting in `bootstrap.toml`, the build may suddenly start -to fail. +warnings for that dependency. +Some dependencies are not warning-free, and due +to the `deny-warnings` setting in `bootstrap.toml`, the build may suddenly start to fail. To work around warnings, you may want to: - Modify the dependency to remove the warnings - Or for local development purposes, suppress the warnings by setting deny-warnings = false in bootstrap.toml. @@ -157,8 +135,7 @@ deny-warnings = false ## Cross-compiling -Once you have a target specification in JSON and in the code, you can -cross-compile `rustc`: +Once you have a target specification in JSON and in the code, you can cross-compile `rustc`: ``` DESTDIR=/path/to/install/in \ diff --git a/src/doc/rustc-dev-guide/src/const-generics.md b/src/doc/rustc-dev-guide/src/const-generics.md index cb8c7adc07f46..4c2a0ddbabd51 100644 --- a/src/doc/rustc-dev-guide/src/const-generics.md +++ b/src/doc/rustc-dev-guide/src/const-generics.md @@ -111,14 +111,15 @@ The third point is also somewhat subtle, by not inheriting any of the where clau This also makes it much more likely that the compiler will ICE or atleast incidentally emit some kind of error if we *do* accidentally allow generic parameters in an anon const, as the anon const will have none of the necessary information in its environment to properly handle the generic parameters. +#### Array repeat expressions +The one exception to all of the above is repeat counts of array expressions. As a *backwards compatibility hack* we allow the repeat count const argument to use generic parameters. + ```rust fn foo() { - let a = [1_u8; size_of::<*mut T>()]; + let a = [1_u8; size_of::()]; } ``` -The one exception to all of the above is repeat counts of array expressions. As a *backwards compatibility hack* we allow the repeat count const argument to use generic parameters. - However, to avoid most of the problems involved in allowing generic parameters in anon const const arguments we require that the constant be evaluated before monomorphization (e.g. during type checking). In some sense we only allow generic parameters here when they are semantically unused. In the previous example the anon const can be evaluated for any type parameter `T` because raw pointers to sized types always have the same size (e.g. `8` on 64bit platforms). diff --git a/src/doc/rustc-dev-guide/src/external-repos.md b/src/doc/rustc-dev-guide/src/external-repos.md index c43c1f680acf0..2e32fcfe78c1d 100644 --- a/src/doc/rustc-dev-guide/src/external-repos.md +++ b/src/doc/rustc-dev-guide/src/external-repos.md @@ -29,9 +29,9 @@ The following external projects are managed using some form of a `subtree`: In contrast to `submodule` dependencies (see below for those), the `subtree` dependencies are just regular files and directories which can -be updated in tree. However, if possible, enhancements, bug fixes, etc. specific -to these tools should be filed against the tools directly in their respective -upstream repositories. The exception is that when rustc changes are required to +be updated in-tree. However, if possible, enhancements, bug fixes, etc. specific +to these tools should be filed against the tools directly in their respective upstream repositories. +The exception is that when rustc changes are required to implement a new tool feature or test, that should happen in one collective rustc PR. `subtree` dependencies are currently managed by two distinct approaches: @@ -51,7 +51,9 @@ implement a new tool feature or test, that should happen in one collective rustc ### Josh subtrees -The [josh] tool is an alternative to git subtrees, which manages git history in a different way and scales better to larger repositories. Specific tooling is required to work with josh. We provide a helper [`rustc-josh-sync`][josh-sync] tool to help with the synchronization, described [below](#synchronizing-a-josh-subtree). +The [josh] tool is an alternative to git subtrees, which manages git history in a different way and scales better to larger repositories. +Specific tooling is required to work with josh. +We provide a helper [`rustc-josh-sync`][josh-sync] tool to help with the synchronization, described [below](#synchronizing-a-josh-subtree). ### Synchronizing a Josh subtree @@ -69,12 +71,12 @@ changes from the subtree to rust-lang/rust) are performed from the subtree repos switch to its repository checkout directory in your terminal). #### Performing pull -1) Checkout a new branch that will be used to create a PR into the subtree -2) Run the pull command +1. Checkout a new branch that will be used to create a PR into the subtree +2. Run the pull command ``` rustc-josh-sync pull ``` -3) Push the branch to your fork and create a PR into the subtree repository +3. Push the branch to your fork and create a PR into the subtree repository - If you have `gh` CLI installed, `rustc-josh-sync` can create the PR for you. #### Performing push @@ -82,11 +84,11 @@ switch to its repository checkout directory in your terminal). > NOTE: > Before you proceed, look at some guidance related to Git [on josh-sync README]. -1) Run the push command to create a branch named `` in a `rustc` fork under the `` account +1. Run the push command to create a branch named `` in a `rustc` fork under the `` account ``` rustc-josh-sync push ``` -2) Create a PR from `` into `rust-lang/rust` +2. Create a PR from `` into `rust-lang/rust` ### Creating a new Josh subtree dependency @@ -97,7 +99,8 @@ If you want to migrate a repository dependency from `git subtree` or `git submod Periodically the changes made to subtree based dependencies need to be synchronized between this repository and the upstream tool repositories. -Subtree synchronizations are typically handled by the respective tool maintainers. Other users +Subtree synchronizations are typically handled by the respective tool maintainers. +Other users are welcome to submit synchronization PRs, however, in order to do so you will need to modify your local git installation and follow a very precise set of instructions. These instructions are documented, along with several useful tips and tricks, in the @@ -108,8 +111,8 @@ use the correct corresponding subtree directory and remote repository. The synchronization process goes in two directions: `subtree push` and `subtree pull`. A `subtree push` takes all the changes that happened to the copy in this repo and creates commits -on the remote repo that match the local changes. Every local -commit that touched the subtree causes a commit on the remote repo, but +on the remote repo that match the local changes. +Every local commit that touched the subtree causes a commit on the remote repo, but is modified to move the files from the specified directory to the tool repo root. A `subtree pull` takes all changes since the last `subtree pull` @@ -119,14 +122,17 @@ the tool changes into the specified directory in the Rust repository. It is recommended that you always do a push first and get that merged to the default branch of the tool. Then, when you do a pull, the merge works without conflicts. While it's definitely possible to resolve conflicts during a pull, you may have to redo the conflict -resolution if your PR doesn't get merged fast enough and there are new conflicts. Do not try to -rebase the result of a `git subtree pull`, rebasing merge commits is a bad idea in general. +resolution if your PR doesn't get merged fast enough and there are new conflicts. +Do not try to +rebase the result of a `git subtree pull`; rebasing merge commits is a bad idea in general. You always need to specify the `-P` prefix to the subtree directory and the corresponding remote -repository. If you specify the wrong directory or repository +repository. +If you specify the wrong directory or repository you'll get very fun merges that try to push the wrong directory to the wrong remote repository. Luckily you can just abort this without any consequences by throwing away either the pulled commits -in rustc or the pushed branch on the remote and try again. It is usually fairly obvious +in rustc or the pushed branch on the remote and try again. +It is usually fairly obvious that this is happening because you suddenly get thousands of commits that want to be synchronized. [clippy-sync-docs]: https://doc.rust-lang.org/nightly/clippy/development/infrastructure/sync.html @@ -140,8 +146,8 @@ repository's root directory!) git subtree add -P src/tools/clippy https://github.com/rust-lang/rust-clippy.git master ``` -This will create a new commit, which you may not rebase under any circumstances! Delete the commit -and redo the operation if you need to rebase. +This will create a new commit, which you may not rebase under any circumstances! +Delete the commit and redo the operation if you need to rebase. Now you're done, the `src/tools/clippy` directory behaves as if Clippy were part of the rustc monorepo, so no one but you (or others that synchronize @@ -149,24 +155,25 @@ subtrees) actually needs to use `git subtree`. ## External Dependencies (submodules) -Building Rust will also use external git repositories tracked using [git -submodules]. The complete list may be found in the [`.gitmodules`] file. Some -of these projects are required (like `stdarch` for the standard library) and +Building Rust will also use external git repositories tracked using [git submodules]. +The complete list may be found in the [`.gitmodules`] file. +Some of these projects are required (like `stdarch` for the standard library) and some of them are optional (like `src/doc/book`). Usage of submodules is discussed more in the [Using Git chapter](git.md#git-submodules). Some of the submodules are allowed to be in a "broken" state where they either don't build or their tests don't pass, e.g. the documentation books -like [The Rust Reference]. Maintainers of these projects will be notified -when the project is in a broken state, and they should fix them as soon -as possible. The current status is tracked on the [toolstate website]. +like [The Rust Reference]. +Maintainers of these projects will be notified +when the project is in a broken state, and they should fix them as soon as possible. +The current status is tracked on the [toolstate website]. More information may be found on the Forge [Toolstate chapter]. In practice, it is very rare for documentation to have broken toolstate. Breakage is not allowed in the beta and stable channels, and must be addressed -before the PR is merged. They are also not allowed to be broken on `main` in -the week leading up to the beta cut. +before the PR is merged. +They are also not allowed to be broken on `main` in the week leading up to the beta cut. [git submodules]: https://git-scm.com/book/en/v2/Git-Tools-Submodules [`.gitmodules`]: https://github.com/rust-lang/rust/blob/HEAD/.gitmodules diff --git a/src/doc/rustc-dev-guide/src/profiling/with_rustc_perf.md b/src/doc/rustc-dev-guide/src/profiling/with_rustc_perf.md index c47fed24e6e31..2158b655b3e27 100644 --- a/src/doc/rustc-dev-guide/src/profiling/with_rustc_perf.md +++ b/src/doc/rustc-dev-guide/src/profiling/with_rustc_perf.md @@ -1,9 +1,11 @@ # Profiling with rustc-perf The [Rust benchmark suite][rustc-perf] provides a comprehensive way of profiling and benchmarking -the Rust compiler. You can find instructions on how to use the suite in its [manual][rustc-perf-readme]. +the Rust compiler. +You can find instructions on how to use the suite in its [manual][rustc-perf-readme]. -However, using the suite manually can be a bit cumbersome. To make this easier for `rustc` contributors, +However, using the suite manually can be a bit cumbersome. +To make this easier for `rustc` contributors, the compiler build system (`bootstrap`) also provides built-in integration with the benchmarking suite, which will download and build the suite for you, build a local compiler toolchain and let you profile it using a simplified command-line interface. @@ -14,8 +16,9 @@ You can use normal bootstrap flags for this command, such as `--stage 1` or `--s `x perf` currently supports the following commands: - `benchmark `: Benchmark the compiler and store the results under the passed `id`. - `compare `: Compare the benchmark results of two compilers with the two passed `id`s. -- `eprintln`: Just run the compiler and capture its `stderr` output. Note that the compiler normally does not print - anything to `stderr`, you might want to add some `eprintln!` calls to get any output. +- `eprintln`: Just run the compiler and capture its `stderr` output. + Note that the compiler normally does not print + anything to `stderr`, so you might want to add some `eprintln!` calls to get any output. - `samply`: Profile the compiler using the [samply][samply] sampling profiler. - `cachegrind`: Use [Cachegrind][cachegrind] to generate a detailed simulated trace of the compiler's execution. @@ -28,6 +31,28 @@ You can use the following options for the `x perf` command, which mirror the cor - `--profiles`: Select profiles (`Check`, `Debug`, `Opt`, `Doc`) which should be profiled/benchmarked. - `--scenarios`: Select scenarios (`Full`, `IncrFull`, `IncrPatched`, `IncrUnchanged`) which should be profiled/benchmarked. +## Example profiling diff for external crates +It can be of interest to generate a local diff for two commits of the compiler for external crates. +To start, in the `rustc-perf` repo, build the collector, which runs the Rust compiler benchmarks as follows. +``` +cargo build --release -p collector +``` +The collector can then be run using cargo, specifying the collector binary. +It expects the following arguments: +- ``: Profiler selection for how performance should be measured. + For this example, we will use Cachegrind. +- ``: The Rust compiler revision to benchmark, specified as a commit SHA from `rust-lang/rust`. +Optional arguments allow running profiles and scenarios as described above. +More information regarding the mandatory and +optional arguments can be found in the [rustc-perf-readme-profilers]. + +Then, for the case of generating a profile diff for the crate `serve_derive-1.0.136`, for two commits `` and `` from the `rust-lang/rust` repository, +run the following in the `rustc-perf` repo: +``` +cargo run --release --bin collector profile_local cachegrind + --rustc2 + --exact-match serde_derive-1.0.136 --profiles Check --scenarios IncrUnchanged +``` + + [samply]: https://github.com/mstange/samply [cachegrind]: https://www.cs.cmu.edu/afs/cs.cmu.edu/project/cmt-40/Nice/RuleRefinement/bin/valgrind-3.2.0/docs/html/cg-manual.html [rustc-perf]: https://github.com/rust-lang/rustc-perf diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-html-test-suite.md b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-html-test-suite.md index b74405d310eb5..a88e60c183b0d 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-html-test-suite.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-html-test-suite.md @@ -34,8 +34,8 @@ pub type Alias = Option; Here, we check that documentation generated for crate `file` contains a page for the public type alias `Alias` where the code block that is found at the top contains the -expected rendering of the item. The `//*[@class="rust item-decl"]//code` is an XPath -expression. +expected rendering of the item. +The `//*[@class="rust item-decl"]//code` is an XPath expression. Conventionally, you place these directives directly above the thing they are meant to test. Technically speaking however, they don't need to be as HtmlDocCk only looks for the directives. @@ -120,8 +120,8 @@ pre-recorded subtree or text (the "snapshot") in file `FILE_STEM.NAME.html` wher is the file stem of the test file. Pass the `--bless` option to `compiletest` to accept the current subtree/text as expected. -This will overwrite the aforementioned file (or create it if it doesn't exist). It will -automatically normalize the channel-dependent URL `https://doc.rust-lang.org/CHANNEL` to +This will overwrite the aforementioned file (or create it if it doesn't exist). +It will automatically normalize the channel-dependent URL `https://doc.rust-lang.org/CHANNEL` to the special string `{{channel}}`. ### `has-dir` @@ -152,7 +152,8 @@ It's *strongly recommended* to read that chapter if you don't know anything abou Here are some details that are relevant to this test suite specifically: * While you can use both `//@ compile-flags` and `//@ doc-flags` to pass flags to `rustdoc`, - prefer to user the latter to show intent. The former is meant for `rustc`. + prefer to user the latter to show intent. + The former is meant for `rustc`. * Add `//@ build-aux-docs` to the test file that has auxiliary crates to not only compile the auxiliaries with `rustc` but to also document them with `rustdoc`. @@ -169,7 +170,8 @@ thus continue to test the correct thing or they won't in which case they would f forcing the author of the change to look at them. Compare that to *negative* checks (e.g., `//@ !has PATH XPATH PATTERN`) which won't fail if their -XPath expression "no longer" matches. The author who changed "the shape" thus won't get notified and +XPath expression "no longer" matches. +The author who changed "the shape" thus won't get notified and as a result someone else can unintentionally reintroduce `PATTERN` into the generated docs without the original negative check failing. diff --git a/src/doc/rustc-dev-guide/src/tests/best-practices.md b/src/doc/rustc-dev-guide/src/tests/best-practices.md index ff4ea11bbc7a9..b6daffa6683c0 100644 --- a/src/doc/rustc-dev-guide/src/tests/best-practices.md +++ b/src/doc/rustc-dev-guide/src/tests/best-practices.md @@ -7,8 +7,8 @@ a bunch of git archeology. It's good practice to review the test that you authored by pretending that you are a different contributor who is looking at the test that failed several years -later without much context (this also helps yourself even a few days or months -later!). Then ask yourself: how can I make my life and their lives easier? +later without much context (this also helps yourself even a few days or months later!). +Then ask yourself: how can I make my life and their lives easier? To help put this into perspective, let's start with an aside on how to write a test that makes the life of another contributor as hard as possible. @@ -35,15 +35,14 @@ test that makes the life of another contributor as hard as possible. Make it easy for the reader to immediately understand what the test is exercising, instead of having to type in the issue number and dig through github -search for what the test is trying to exercise. This has an additional benefit -of making the test possible to be filtered via `--test-args` as a collection of -related tests. +search for what the test is trying to exercise. +This has an additional benefit +of making the test possible to be filtered via `--test-args` as a collection of related tests. - Name the test after what it's trying to exercise or prevent regressions of. - Keep it concise. - Avoid using issue numbers alone as test names. -- Avoid starting the test name with `issue-xxxxx` prefix as it degrades - auto-completion. +- Avoid starting the test name with `issue-xxxxx` prefix as it degrades auto-completion. > **Avoid using only issue numbers as test names** > @@ -78,22 +77,22 @@ related tests. ## Test organization -- For most test suites, try to find a semantically meaningful subdirectory to - home the test. +- For most test suites, try to find a semantically meaningful subdirectory to home the test. - E.g. for an implementation of RFC 2093 specifically, we can group a - collection of tests under `tests/ui/rfc-2093-infer-outlives/`. For the - directory name, include what the RFC is about. + collection of tests under `tests/ui/rfc-2093-infer-outlives/`. + For the directory name, include what the RFC is about. - For the [`run-make`]/`run-make-support` test suites, each `rmake.rs` must be contained within an immediate subdirectory under `tests/run-make/` or - `tests/run-make-cargo/` respectively. Further nesting is not presently - supported. Avoid using _only_ an issue number for the test name as well. + `tests/run-make-cargo/` respectively. + Further nesting is not presently supported. + Avoid using _only_ an issue number for the test name as well. ## Test descriptions To help other contributors understand what the test is about if their changes lead to the test failing, we should make sure a test has sufficient docs about -its intent/purpose, links to relevant context (incl. issue numbers or other -discussions) and possibly relevant resources (e.g. can be helpful to link to +its intent/purpose, links to relevant context (including issue numbers or other discussions) +and possibly relevant resources (e.g. it can be helpful to link to Win32 APIs for specific behavior). **Synopsis of a test with good comments** @@ -136,8 +135,8 @@ fn main() { } ``` -For how much context/explanation is needed, it is up to the author and -reviewer's discretion. A good rule of thumb is non-trivial things exercised in +For how much context/explanation is needed, it is up to the author and reviewer's discretion. +A good rule of thumb is non-trivial things exercised in the test deserves some explanation to help other contributors to understand. This may include remarks on: @@ -146,7 +145,7 @@ This may include remarks on: separate because...). - Platform-specific behaviors. - Behavior of external dependencies and APIs: syscalls, linkers, tools, - environments and the likes. + environments and the like. ## Test content @@ -159,17 +158,17 @@ This may include remarks on: ## Flaky tests -All tests need to strive to be reproducible and reliable. Flaky tests are the -worst kind of tests, arguably even worse than not having the test in the first +All tests need to strive to be reproducible and reliable. +Flaky tests are the worst kind of tests, arguably even worse than not having the test in the first place. - Flaky tests can fail in completely unrelated PRs which can confuse other - contributors and waste their time trying to figure out if test failure is - related. + contributors and waste their time trying to figure out if test failure is related. - Flaky tests provide no useful information from its test results other than - it's flaky and not reliable: if a test passed but it's flakey, did I just get - lucky? if a test is flakey but it failed, was it just spurious? -- Flaky tests degrade confidence in the whole test suite. If a test suite can + it's flaky and not reliable: if a test passed but it's flakey, did I just get lucky? + If a test is flakey but it failed, was it just spurious? +- Flaky tests degrade confidence in the whole test suite. + If a test suite can randomly spuriously fail due to flaky tests, did the whole test suite pass or did I just get lucky/unlucky? - Flaky tests can randomly fail in full CI, wasting previous full CI resources. @@ -189,8 +188,8 @@ See [compiletest directives] for a listing of directives. See [LLVM FileCheck guide][FileCheck] for details. - Avoid matching on specific register numbers or basic block numbers unless - they're special or critical for the test. Consider using patterns to match - them where suitable. + they're special or critical for the test. + Consider using patterns to match them where suitable. > **TODO** > diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index 52e1f09dca0f0..ae341599f15ad 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -7,8 +7,8 @@ FIXME(jieyouxu) completely revise this chapter. Directives are special comments that tell compiletest how to build and interpret a test. They may also appear in `rmake.rs` [run-make tests](compiletest.md#run-make-tests). -They are normally put after the short comment that explains the point of this -test. Compiletest test suites use `//@` to signal that a comment is a directive. +They are normally put after the short comment that explains the point of this test. +Compiletest test suites use `//@` to signal that a comment is a directive. For example, this test uses the `//@ compile-flags` command to specify a custom flag to give to rustc when the test is compiled: @@ -27,15 +27,16 @@ Directives can be standalone (like `//@ run-pass`) or take a value (like `//@ compile-flags: -C overflow-checks=off`). Directives are written one directive per line: you cannot write multiple -directives on the same line. For example, if you write `//@ only-x86 -only-windows` then `only-windows` is interpreted as a comment, not a separate -directive. +directives on the same line. +For example, if you write `//@ only-x86 only-windows`, +then `only-windows` is interpreted as a comment, not a separate directive. ## Listing of compiletest directives -The following is a list of compiletest directives. Directives are linked to -sections that describe the command in more detail if available. This list may -not be exhaustive. Directives can generally be found by browsing the +The following is a list of compiletest directives. +Directives are linked to sections that describe the command in more detail if available. +This list may not be exhaustive. +Directives can generally be found by browsing the `TestProps` structure found in [`directives.rs`] from the compiletest source. [`directives.rs`]: https://github.com/rust-lang/rust/tree/HEAD/src/tools/compiletest/src/directives.rs @@ -65,8 +66,7 @@ See [Building auxiliary crates](compiletest.html#building-auxiliary-crates) ### Controlling outcome expectations -See [Controlling pass/fail -expectations](ui.md#controlling-passfail-expectations). +See [Controlling pass/fail expectations](ui.md#controlling-passfail-expectations). | Directive | Explanation | Supported test suites | Possible values | |-----------------------------|---------------------------------------------|-------------------------------------------|-----------------| @@ -87,8 +87,7 @@ expectations](ui.md#controlling-passfail-expectations). ### Controlling output snapshots and normalizations See [Normalization](ui.md#normalization), [Output -comparison](ui.md#output-comparison) and [Rustfix tests](ui.md#rustfix-tests) -for more details. +comparison](ui.md#output-comparison) and [Rustfix tests](ui.md#rustfix-tests) for more details. | Directive | Explanation | Supported test suites | Possible values | |-----------------------------------|--------------------------------------------------------------------------------------------------------------------------|----------------------------------------------|-----------------------------------------------------------------------------------------| @@ -115,8 +114,8 @@ for more details. [^check_stdout]: presently this has a weird quirk where the test binary's stdout and stderr gets concatenated and then - `error-pattern`s are matched on this combined output, which is ??? slightly - questionable to say the least. + `error-pattern`s are matched on this combined output, which is ??? + slightly questionable to say the least. ### Controlling when tests are run @@ -124,14 +123,13 @@ These directives are used to ignore the test in some situations, which means the test won't be compiled or run. * `ignore-X` where `X` is a target detail or other criteria on which to ignore the test (see below) -* `only-X` is like `ignore-X`, but will *only* run the test on that target or - stage +* `only-X` is like `ignore-X`, but will *only* run the test on that target or stage * `ignore-auxiliary` is intended for files that *participate* in one or more other main test files but that `compiletest` should not try to build the file itself. Please backlink to which main test is actually using the auxiliary file. -* `ignore-test` always ignores the test. This can be used to temporarily disable - a test if it is currently not working, but you want to keep it in tree to - re-enable it later. +* `ignore-test` always ignores the test. + This can be used to temporarily disable + a test if it is currently not working, but you want to keep it in-tree to re-enable it later. Some examples of `X` in `ignore-X` or `only-X`: @@ -158,16 +156,15 @@ Some examples of `X` in `ignore-X` or `only-X`: - This needs to be enabled with `COMPILETEST_ENABLE_DIST_TESTS=1` - The `rustc_abi` of the target: e.g. `rustc_abi-x86_64-sse2` -The following directives will check rustc build settings and target -settings: +The following directives will check rustc build settings and target settings: - `needs-asm-support` — ignores if the **host** architecture doesn't have - stable support for `asm!`. For tests that cross-compile to explicit targets + stable support for `asm!`. + For tests that cross-compile to explicit targets via `--target`, use `needs-llvm-components` instead to ensure the appropriate backend is available. - `needs-profiler-runtime` — ignores the test if the profiler runtime was not - enabled for the target - (`build.profiler = true` in rustc's `bootstrap.toml`) + enabled for the target (`build.profiler = true` in rustc's `bootstrap.toml`) - `needs-sanitizer-support` — ignores if the sanitizer support was not enabled for the target (`sanitizers = true` in rustc's `bootstrap.toml`) - `needs-sanitizer-{address,hwaddress,leak,memory,thread}` — ignores if the @@ -175,43 +172,38 @@ settings: hardware-assisted AddressSanitizer, LeakSanitizer, MemorySanitizer or ThreadSanitizer respectively) - `needs-run-enabled` — ignores if it is a test that gets executed, and running - has been disabled. Running tests can be disabled with the `x test --run=never` - flag, or running on fuchsia. + has been disabled. + Running tests can be disabled with the `x test --run=never` flag, or running on fuchsia. - `needs-unwind` — ignores if the target does not support unwinding - `needs-rust-lld` — ignores if the rust lld support is not enabled (`rust.lld = true` in `bootstrap.toml`) - `needs-threads` — ignores if the target does not have threading support - `needs-subprocess` — ignores if the target does not have subprocess support -- `needs-symlink` — ignores if the target does not support symlinks. This can be - the case on Windows if the developer did not enable privileged symlink +- `needs-symlink` — ignores if the target does not support symlinks. + This can be the case on Windows if the developer did not enable privileged symlink permissions. -- `ignore-std-debug-assertions` — ignores if std was built with debug - assertions. -- `needs-std-debug-assertions` — ignores if std was not built with debug - assertions. -- `ignore-std-remap-debuginfo` — ignores if std was built with remapping of - it's sources. -- `needs-std-remap-debugino` — ignores if std was not built with remapping of - it's sources. -- `ignore-rustc-debug-assertions` — ignores if rustc was built with debug - assertions. -- `needs-rustc-debug-assertions` — ignores if rustc was not built with debug - assertions. +- `ignore-std-debug-assertions` — ignores if std was built with debug assertions. +- `needs-std-debug-assertions` — ignores if std was not built with debug assertions. +- `ignore-std-remap-debuginfo` — ignores if std was built with remapping of it's sources. +- `needs-std-remap-debugino` — ignores if std was not built with remapping of it's sources. +- `ignore-rustc-debug-assertions` — ignores if rustc was built with debug assertions. +- `needs-rustc-debug-assertions` — ignores if rustc was not built with debug assertions. - `needs-target-has-atomic` — ignores if target does not have support for all specified atomic widths, e.g. the test with `//@ needs-target-has-atomic: 8, - 16, ptr` will only run if it supports the comma-separated list of atomic - widths. + 16, ptr` will only run if it supports the comma-separated list of atomic widths. - `needs-dynamic-linking` — ignores if target does not support dynamic linking (which is orthogonal to it being unable to create `dylib` and `cdylib` crate types) - `needs-crate-type` — ignores if target platform does not support one or more - of the comma-delimited list of specified crate types. For example, + of the comma-delimited list of specified crate types. + For example, `//@ needs-crate-type: cdylib, proc-macro` will cause the test to be ignored on `wasm32-unknown-unknown` target because the target does not support the `proc-macro` crate type. - `needs-target-std` — ignores if target platform does not have std support. -- `ignore-backends` — ignores the listed backends, separated by whitespace characters. Please note +- `ignore-backends` — ignores the listed backends, separated by whitespace characters. + Please note that this directive can be overriden with the `--bypass-ignore-backends=[BACKEND]` command line - flag. + flag. - `needs-backends` — only runs the test if current codegen backend is listed. - `needs-offload` — ignores if our LLVM backend was not built with offload support. - `needs-enzyme` — ignores if our Enzyme submodule was not built. @@ -220,29 +212,23 @@ The following directives will check LLVM support: - `exact-llvm-major-version: 19` — ignores if the llvm major version does not match the specified llvm major version. -- `min-llvm-version: 13.0` — ignored if the LLVM version is less than the given - value +- `min-llvm-version: 13.0` — ignored if the LLVM version is less than the given value - `min-system-llvm-version: 12.0` — ignored if using a system LLVM and its version is less than the given value - `max-llvm-major-version: 19` — ignored if the LLVM major version is higher than the given major version - `ignore-llvm-version: 9.0` — ignores a specific LLVM version -- `ignore-llvm-version: 7.0 - 9.9.9` — ignores LLVM versions in a range - (inclusive) -- `needs-llvm-components: powerpc` — ignores if the specific LLVM component was - not built. Note: The test will fail on CI (when - `COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS` is set) if the component does not - exist. +- `ignore-llvm-version: 7.0 - 9.9.9` — ignores LLVM versions in a range (inclusive) +- `needs-llvm-components: powerpc` — ignores if the specific LLVM component was not built. + Note: The test will fail on CI (when + `COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS` is set) if the component does not exist. - `needs-forced-clang-based-tests` — test is ignored unless the environment - variable `RUSTBUILD_FORCE_CLANG_BASED_TESTS` is set, which enables building - clang alongside LLVM + variable `RUSTBUILD_FORCE_CLANG_BASED_TESTS` is set, which enables building clang alongside LLVM - This is only set in two CI jobs ([`x86_64-gnu-debug`] and - [`aarch64-gnu-debug`]), which only runs a - subset of `run-make` tests. Other tests with this directive will not - run at all, which is usually not what you want. + [`aarch64-gnu-debug`]), which only runs a subset of `run-make` tests. + Other tests with this directive will not run at all, which is usually not what you want. -See also [Debuginfo tests](compiletest.md#debuginfo-tests) for directives for -ignoring debuggers. +See also [Debuginfo tests](compiletest.md#debuginfo-tests) for directives for ignoring debuggers. [remote testing]: running.md#running-tests-on-a-remote-machine [compare modes]: ui.md#compare-modes @@ -290,9 +276,9 @@ You can also force `./x test` to use a specific edition by passing the `-- --edi However, tests with the `//@ edition` directive will clamp the value passed to the argument. For example, if we run `./x test -- --edition=2015`: -- A test with the `//@ edition: 2018` will run with the 2018 edition. -- A test with the `//@ edition: 2015..2021` will be run with the 2015 edition. -- A test with the `//@ edition: 2018..` will run with the 2018 edition. +- A test with the `//@ edition: 2018` will run with the 2018 edition. +- A test with the `//@ edition: 2015..2021` will be run with the 2015 edition. +- A test with the `//@ edition: 2018..` will run with the 2018 edition. ### Rustdoc @@ -311,7 +297,8 @@ Asked in The test suites [`rustdoc-html`][rustdoc-html-tests], [`rustdoc-js`/`rustdoc-js-std`][rustdoc-js-tests] and [`rustdoc-json`][rustdoc-json-tests] each feature an additional set of directives whose basic syntax resembles the one of compiletest directives but which are ultimately read and checked by -separate tools. For more information, please read their respective chapters as linked above. +separate tools. +For more information, please read their respective chapters as linked above. [rustdoc-html-tests]: ../rustdoc-internals/rustdoc-html-test-suite.md [rustdoc-js-tests]: ../rustdoc-internals/search.html#testing-the-search-engine @@ -327,8 +314,7 @@ See [Pretty-printer](compiletest.md#pretty-printer-tests). - [`revisions`](compiletest.md#revisions) — compile multiple times -[`forbid-output`](compiletest.md#incremental-tests) — incremental cfail rejects output pattern -- [`should-ice`](compiletest.md#incremental-tests) — incremental cfail should - ICE +- [`should-ice`](compiletest.md#incremental-tests) — incremental cfail should ICE - [`reference`] — an annotation linking to a rule in the reference - `disable-gdb-pretty-printers` — disable gdb pretty printers for debuginfo tests @@ -348,40 +334,37 @@ test suites that use those tools: ### Tidy specific directives -The following directives control how the [tidy script](../conventions.md#formatting) -verifies tests. +The following directives control how the [tidy script](../conventions.md#formatting) verifies tests. - `ignore-tidy-target-specific-tests` disables checking that the appropriate LLVM component is required (via a `needs-llvm-components` directive) when a - test is compiled for a specific target (via the `--target` flag in a - `compile-flag` directive). + test is compiled for a specific target (via the `--target` flag in a `compile-flag` directive). - [`unused-revision-names`](compiletest.md#ignoring-unused-revision-names) - suppress tidy checks for mentioning unknown revision names. ## Substitutions Directive values support substituting a few variables which will be replaced -with their corresponding value. For example, if you need to pass a compiler flag +with their corresponding value. +For example, if you need to pass a compiler flag with a path to a specific file, something like the following could work: ```rust,ignore //@ compile-flags: --remap-path-prefix={{src-base}}=/the/src ``` -Where the sentinel `{{src-base}}` will be replaced with the appropriate path -described below: +Where the sentinel `{{src-base}}` will be replaced with the appropriate path described below: -- `{{cwd}}`: The directory where compiletest is run from. This may not be the - root of the checkout, so you should avoid using it where possible. +- `{{cwd}}`: The directory where compiletest is run from. + This may not be the root of the checkout, so you should avoid using it where possible. - Examples: `/path/to/rust`, `/path/to/build/root` -- `{{src-base}}`: The directory where the test is defined. This is equivalent to - `$DIR` for [output normalization]. +- `{{src-base}}`: The directory where the test is defined. + This is equivalent to `$DIR` for [output normalization]. - Example: `/path/to/rust/tests/ui/error-codes` -- `{{build-base}}`: The base directory where the test's output goes. This is - equivalent to `$TEST_BUILD_DIR` for [output normalization]. +- `{{build-base}}`: The base directory where the test's output goes. + This is equivalent to `$TEST_BUILD_DIR` for [output normalization]. - Example: `/path/to/rust/build/x86_64-unknown-linux-gnu/test/ui` -- `{{rust-src-base}}`: The sysroot directory where libstd/libcore/... are - located +- `{{rust-src-base}}`: The sysroot directory where libstd/libcore/... are located - `{{sysroot-base}}`: Path of the sysroot directory used to build the test. - Mainly intended for `ui-fulldeps` tests that run the compiler via API. - `{{target-linker}}`: Linker that would be passed to `-Clinker` for this test, @@ -400,7 +383,8 @@ for an example of a test that uses this substitution. ## Adding a directive One would add a new directive if there is a need to define some test property or -behavior on an individual, test-by-test basis. A directive property serves as +behavior on an individual, test-by-test basis. +A directive property serves as the directive's backing store (holds the command's current value) at runtime. To add a new directive property: @@ -420,19 +404,21 @@ declaration block is found in [`src/tools/compiletest/src/common.rs`]). `TestProps`'s `load_from()` method will try passing the current line of text to each parser, which, in turn typically checks to see if the line begins with a particular commented (`//@`) directive such as `//@ must-compile-successfully` -or `//@ failure-status`. Whitespace after the comment marker is optional. +or `//@ failure-status`. +Whitespace after the comment marker is optional. Parsers will override a given directive property's default value merely by being specified in the test file as a directive or by having a parameter value specified in the test file, depending on the directive. Parsers defined in `impl Config` are typically named `parse_` -(note kebab-case `` transformed to snake-case -``). `impl Config` also defines several 'low-level' parsers +(note kebab-case `` transformed to snake-case ``). +`impl Config` also defines several 'low-level' parsers which make it simple to parse common patterns like simple presence or not (`parse_name_directive()`), `directive:parameter(s)` (`parse_name_value_directive()`), optional parsing only if a particular `cfg` -attribute is defined (`has_cfg_prefix()`) and many more. The low-level parsers +attribute is defined (`has_cfg_prefix()`) and many more. +The low-level parsers are found near the end of the `impl Config` block; be sure to look through them and their associated parsers immediately above to see how they are used to avoid writing additional parsing code unnecessarily. @@ -483,15 +469,16 @@ As a concrete example, here is the implementation for the ### Implementing the behavior change When a test invokes a particular directive, it is expected that some behavior -will change as a result. What behavior, obviously, will depend on the purpose of -the directive. In the case of `failure-status`, the behavior that changes is +will change as a result. +What behavior, obviously, will depend on the purpose of the directive. +In the case of `failure-status`, the behavior that changes is that `compiletest` expects the failure code defined by the directive invoked in the test, rather than the default value. Although specific to `failure-status` (as every directive will have a different implementation in order to invoke behavior change) perhaps it is helpful to see -the behavior change implementation of one case, simply as an example. To -implement `failure-status`, the `check_correct_failure_status()` function found +the behavior change implementation of one case, simply as an example. +To implement `failure-status`, the `check_correct_failure_status()` function found in the `TestCx` implementation block, located in [`src/tools/compiletest/src/runtest.rs`], was modified as per below: @@ -532,10 +519,10 @@ in the `TestCx` implementation block, located in } ``` -Note the use of `self.props.failure_status` to access the directive property. In -tests which do not specify the failure status directive, -`self.props.failure_status` will evaluate to the default value of 101 at the -time of this writing. But for a test which specifies a directive of, for +Note the use of `self.props.failure_status` to access the directive property. +In tests which do not specify the failure status directive, +`self.props.failure_status` will evaluate to the default value of 101 at the time of this writing. +But for a test which specifies a directive of, for example, `//@ failure-status: 1`, `self.props.failure_status` will evaluate to 1, as `parse_failure_status()` will have overridden the `TestProps` default value, for that test specifically. diff --git a/src/doc/rustc-dev-guide/src/tests/perf.md b/src/doc/rustc-dev-guide/src/tests/perf.md index 18762556137e1..a0aa3c0331745 100644 --- a/src/doc/rustc-dev-guide/src/tests/perf.md +++ b/src/doc/rustc-dev-guide/src/tests/perf.md @@ -6,12 +6,13 @@ A lot of work is put into improving the performance of the compiler and preventing performance regressions. The [rustc-perf](https://github.com/rust-lang/rustc-perf) project provides -several services for testing and tracking performance. It provides hosted -infrastructure for running benchmarks as a service. At this time, only -`x86_64-unknown-linux-gnu` builds are tracked. +several services for testing and tracking performance. +It provides hosted infrastructure for running benchmarks as a service. +At this time, only `x86_64-unknown-linux-gnu` builds are tracked. A "perf run" is used to compare the performance of the compiler in different -configurations for a large collection of popular crates. Different +configurations for a large collection of popular crates. +Different configurations include "fresh builds", builds with incremental compilation, etc. The result of a perf run is a comparison between two versions of the compiler @@ -28,8 +29,8 @@ Any changes are noted in a comment on the PR. ### Manual perf runs -Additionally, performance tests can be ran before a PR is merged on an as-needed -basis. You should request a perf run if your PR may affect performance, +Additionally, performance tests can be ran before a PR is merged on an as-needed basis. +You should request a perf run if your PR may affect performance, especially if it can affect performance adversely. To evaluate the performance impact of a PR, write this comment on the PR: @@ -46,10 +47,10 @@ To evaluate the performance impact of a PR, write this comment on the PR: [perf run]: https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp/topic/perf.20run This will first tell bors to do a "try" build which do a full release build for -`x86_64-unknown-linux-gnu`. After the build finishes, it will place it in the -queue to run the performance suite against it. After the performance tests -finish, the bot will post a comment on the PR with a summary and a link to a -full report. +`x86_64-unknown-linux-gnu`. +After the build finishes, it will place it in the queue to run the performance suite against it. +After the performance tests +finish, the bot will post a comment on the PR with a summary and a link to a full report. If you want to do a perf run for an already built artifact (e.g. for a previous try build that wasn't benchmarked yet), you can run this instead: @@ -59,8 +60,7 @@ try build that wasn't benchmarked yet), you can run this instead: You cannot benchmark the same artifact twice though. More information about the available perf bot commands can be found -[here](https://perf.rust-lang.org/help.html). +[here](https://perf.rust-lang.org/help.html). -More details about the benchmarking process itself are available in the [perf -collector +More details about the benchmarking process itself are available in the [perf collector documentation](https://github.com/rust-lang/rustc-perf/blob/master/collector/README.md). diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index c3bafd3db13ac..c2e63f475bec4 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -26,7 +26,7 @@ use rustc_resolve::rustdoc::{ use rustc_session::Session; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{Symbol, kw, sym}; -use rustc_span::{DUMMY_SP, FileName, Loc, RemapPathScopeComponents}; +use rustc_span::{DUMMY_SP, FileName, Ident, Loc, RemapPathScopeComponents}; use tracing::{debug, trace}; use {rustc_ast as ast, rustc_hir as hir}; @@ -418,7 +418,7 @@ impl Item { { Some(Deprecation { since: DeprecatedSince::Unspecified, - note: Some(note), + note: Some(Ident { name: note, span: DUMMY_SP }), suggestion: None, }) } else { @@ -455,7 +455,7 @@ impl Item { .attrs .other_attrs .iter() - .filter_map(|attr| attr.deprecation_note().map(|_| attr.span())); + .filter_map(|attr| attr.deprecation_note().map(|note| note.span)); span_of_fragments(&self.attrs.doc_strings) .into_iter() diff --git a/tests/assembly-llvm/asm/s390x-types.rs b/tests/assembly-llvm/asm/s390x-types.rs index 24db91bf77728..10e2966ace0a3 100644 --- a/tests/assembly-llvm/asm/s390x-types.rs +++ b/tests/assembly-llvm/asm/s390x-types.rs @@ -6,8 +6,9 @@ //@[s390x_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-feature=+vector //@[s390x_vector] needs-llvm-components: systemz //@ compile-flags: -Zmerge-functions=disabled +//@ min-llvm-version: 21 -#![feature(no_core, repr_simd, f128)] +#![feature(no_core, repr_simd, f16, f128)] #![cfg_attr(s390x_vector, feature(asm_experimental_reg))] #![crate_type = "rlib"] #![no_core] @@ -27,6 +28,8 @@ pub struct i32x4([i32; 4]); #[repr(simd)] pub struct i64x2([i64; 2]); #[repr(simd)] +pub struct f16x8([f16; 8]); +#[repr(simd)] pub struct f32x4([f32; 4]); #[repr(simd)] pub struct f64x2([f64; 2]); @@ -35,6 +38,7 @@ impl Copy for i8x16 {} impl Copy for i16x8 {} impl Copy for i32x4 {} impl Copy for i64x2 {} +impl Copy for f16x8 {} impl Copy for f32x4 {} impl Copy for f64x2 {} @@ -127,6 +131,12 @@ check!(reg_i32_addr, i32, reg_addr, "lgr"); // CHECK: #NO_APP check!(reg_i64_addr, i64, reg_addr, "lgr"); +// CHECK-LABEL: reg_f16: +// CHECK: #APP +// CHECK: ler %f{{[0-9]+}}, %f{{[0-9]+}} +// CHECK: #NO_APP +check!(reg_f16, f16, freg, "ler"); + // CHECK-LABEL: reg_f32: // CHECK: #APP // CHECK: ler %f{{[0-9]+}}, %f{{[0-9]+}} @@ -173,6 +183,13 @@ check!(vreg_i32x4, i32x4, vreg, "vlr"); #[cfg(s390x_vector)] check!(vreg_i64x2, i64x2, vreg, "vlr"); +// s390x_vector-LABEL: vreg_f16x8: +// s390x_vector: #APP +// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}} +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check!(vreg_f16x8, f16x8, vreg, "vlr"); + // s390x_vector-LABEL: vreg_f32x4: // s390x_vector: #APP // s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}} @@ -208,6 +225,13 @@ check!(vreg_i64, i64, vreg, "vlr"); #[cfg(s390x_vector)] check!(vreg_i128, i128, vreg, "vlr"); +// s390x_vector-LABEL: vreg_f16: +// s390x_vector: #APP +// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}} +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check!(vreg_f16, f16, vreg, "vlr"); + // s390x_vector-LABEL: vreg_f32: // s390x_vector: #APP // s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}} @@ -253,6 +277,12 @@ check_reg!(r0_i32, i32, "r0", "lr"); // CHECK: #NO_APP check_reg!(r0_i64, i64, "r0", "lr"); +// CHECK-LABEL: f0_f16: +// CHECK: #APP +// CHECK: ler %f0, %f0 +// CHECK: #NO_APP +check_reg!(f0_f16, f16, "f0", "ler"); + // CHECK-LABEL: f0_f32: // CHECK: #APP // CHECK: ler %f0, %f0 @@ -293,6 +323,13 @@ check_reg!(v0_i32x4, i32x4, "v0", "vlr"); #[cfg(s390x_vector)] check_reg!(v0_i64x2, i64x2, "v0", "vlr"); +// s390x_vector-LABEL: v0_f16x8: +// s390x_vector: #APP +// s390x_vector: vlr %v0, %v0 +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check_reg!(v0_f16x8, f16x8, "v0", "vlr"); + // s390x_vector-LABEL: v0_f32x4: // s390x_vector: #APP // s390x_vector: vlr %v0, %v0 @@ -328,6 +365,13 @@ check_reg!(v0_i64, i64, "v0", "vlr"); #[cfg(s390x_vector)] check_reg!(v0_i128, i128, "v0", "vlr"); +// s390x_vector-LABEL: v0_f16: +// s390x_vector: #APP +// s390x_vector: vlr %v0, %v0 +// s390x_vector: #NO_APP +#[cfg(s390x_vector)] +check_reg!(v0_f16, f16, "v0", "vlr"); + // s390x_vector-LABEL: v0_f32: // s390x_vector: #APP // s390x_vector: vlr %v0, %v0 diff --git a/tests/codegen-llvm/instrument-coverage/testprog.rs b/tests/codegen-llvm/instrument-coverage/testprog.rs index 9e918499d577f..ef61ede6de8ee 100644 --- a/tests/codegen-llvm/instrument-coverage/testprog.rs +++ b/tests/codegen-llvm/instrument-coverage/testprog.rs @@ -109,7 +109,7 @@ fn main() { // CHECK: declare void @llvm.instrprof.increment(ptr, i64, i32, i32) #[[LLVM_INSTRPROF_INCREMENT_ATTR:[0-9]+]] -// WIN: define linkonce_odr hidden i32 @__llvm_profile_runtime_user() #[[LLVM_PROFILE_RUNTIME_USER_ATTR:[0-9]+]] comdat { +// WIN: define linkonce_odr hidden i32 @__llvm_profile_runtime_user() #[[LLVM_PROFILE_RUNTIME_USER_ATTR:[0-9]+]] comdat {{.*}}{ // WIN-NEXT: %1 = load i32, ptr @__llvm_profile_runtime // WIN-NEXT: ret i32 %1 // WIN-NEXT: } diff --git a/tests/run-make/target-specs/rmake.rs b/tests/run-make/target-specs/rmake.rs index 7c30a5b21b339..69292af5fd69c 100644 --- a/tests/run-make/target-specs/rmake.rs +++ b/tests/run-make/target-specs/rmake.rs @@ -15,11 +15,20 @@ fn main() { .run_fail() .assert_stderr_contains("error loading target specification"); rustc() + .arg("-Zunstable-options") .input("foo.rs") .target("my-incomplete-platform.json") .run_fail() .assert_stderr_contains("missing field `llvm-target`"); + let test_platform = rustc() + .input("foo.rs") + .target("my-x86_64-unknown-linux-gnu-platform") + .crate_type("lib") + .emit("asm") + .run_fail() + .assert_stderr_contains("custom targets are unstable and require `-Zunstable-options`"); rustc() + .arg("-Zunstable-options") .env("RUST_TARGET_PATH", ".") .input("foo.rs") .target("my-awesome-platform") @@ -27,6 +36,7 @@ fn main() { .emit("asm") .run(); rustc() + .arg("-Zunstable-options") .env("RUST_TARGET_PATH", ".") .input("foo.rs") .target("my-x86_64-unknown-linux-gnu-platform") @@ -52,27 +62,31 @@ fn main() { .actual_text("test-platform-2", test_platform_2) .run(); rustc() + .arg("-Zunstable-options") .input("foo.rs") .target("endianness-mismatch") .run_fail() .assert_stderr_contains(r#""data-layout" claims architecture is little-endian"#); rustc() + .arg("-Zunstable-options") .input("foo.rs") .target("mismatching-data-layout") .crate_type("lib") .run_fail() .assert_stderr_contains("data-layout for target"); rustc() + .arg("-Zunstable-options") .input("foo.rs") .target("require-explicit-cpu") .crate_type("lib") .run_fail() .assert_stderr_contains("target requires explicitly specifying a cpu"); rustc() + .arg("-Zunstable-options") .input("foo.rs") .target("require-explicit-cpu") .crate_type("lib") .arg("-Ctarget-cpu=generic") .run(); - rustc().target("require-explicit-cpu").arg("--print=target-cpus").run(); + rustc().arg("-Zunstable-options").target("require-explicit-cpu").print("target-cpus").run(); } diff --git a/tests/rustdoc-ui/intra-doc/deprecated.stderr b/tests/rustdoc-ui/intra-doc/deprecated.stderr index 9bd64544eef82..85290c334626d 100644 --- a/tests/rustdoc-ui/intra-doc/deprecated.stderr +++ b/tests/rustdoc-ui/intra-doc/deprecated.stderr @@ -1,8 +1,8 @@ error: unresolved link to `TypeAlias::hoge` - --> $DIR/deprecated.rs:3:1 + --> $DIR/deprecated.rs:3:16 | LL | #[deprecated = "[broken cross-reference](TypeAlias::hoge)"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the link appears in this line: @@ -16,10 +16,10 @@ LL | #![deny(rustdoc::broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unresolved link to `TypeAlias::hoge` - --> $DIR/deprecated.rs:6:1 + --> $DIR/deprecated.rs:6:38 | LL | #[deprecated(since = "0.0.0", note = "[broken cross-reference](TypeAlias::hoge)")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the link appears in this line: @@ -28,10 +28,10 @@ LL | #[deprecated(since = "0.0.0", note = "[broken cross-reference](TypeAlias::h = note: no item named `TypeAlias` in scope error: unresolved link to `TypeAlias::hoge` - --> $DIR/deprecated.rs:9:1 + --> $DIR/deprecated.rs:9:21 | LL | #[deprecated(note = "[broken cross-reference](TypeAlias::hoge)", since = "0.0.0")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the link appears in this line: diff --git a/tests/rustdoc-ui/lints/invalid-crate-level-lint.rs b/tests/rustdoc-ui/lints/invalid-crate-level-lint.rs new file mode 100644 index 0000000000000..275e20e80a173 --- /dev/null +++ b/tests/rustdoc-ui/lints/invalid-crate-level-lint.rs @@ -0,0 +1,13 @@ +#![crate_type = "lib"] + +#[doc(test(no_crate_inject))] +//~^ ERROR can only be applied at the crate level + +pub mod bar { + #![doc(test(no_crate_inject))] + //~^ ERROR can only be applied at the crate level + + #[doc(test(no_crate_inject))] + //~^ ERROR can only be applied at the crate level + fn foo() {} +} diff --git a/tests/rustdoc-ui/lints/invalid-crate-level-lint.stderr b/tests/rustdoc-ui/lints/invalid-crate-level-lint.stderr new file mode 100644 index 0000000000000..fdb95e7de41c6 --- /dev/null +++ b/tests/rustdoc-ui/lints/invalid-crate-level-lint.stderr @@ -0,0 +1,27 @@ +error: this attribute can only be applied at the crate level + --> $DIR/invalid-crate-level-lint.rs:3:12 + | +LL | #[doc(test(no_crate_inject))] + | ^^^^^^^^^^^^^^^ + | + = note: read for more information + = note: `#[deny(invalid_doc_attributes)]` on by default + +error: this attribute can only be applied at the crate level + --> $DIR/invalid-crate-level-lint.rs:7:17 + | +LL | #![doc(test(no_crate_inject))] + | ^^^^^^^^^^^^^^^ + | + = note: read for more information + +error: this attribute can only be applied at the crate level + --> $DIR/invalid-crate-level-lint.rs:10:16 + | +LL | #[doc(test(no_crate_inject))] + | ^^^^^^^^^^^^^^^ + | + = note: read for more information + +error: aborting due to 3 previous errors + diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr.rs b/tests/rustdoc-ui/lints/invalid-doc-attr.rs index a8c42b8fd79c0..169d092d7e175 100644 --- a/tests/rustdoc-ui/lints/invalid-doc-attr.rs +++ b/tests/rustdoc-ui/lints/invalid-doc-attr.rs @@ -4,18 +4,11 @@ #![doc(masked)] //~^ ERROR this attribute can only be applied to an `extern crate` item -#[doc(test(no_crate_inject))] -//~^ ERROR can only be applied at the crate level #[doc(inline)] //~^ ERROR can only be applied to a `use` item pub fn foo() {} pub mod bar { - #![doc(test(no_crate_inject))] - //~^ ERROR can only be applied at the crate level - - #[doc(test(no_crate_inject))] - //~^ ERROR can only be applied at the crate level #[doc(inline)] //~^ ERROR can only be applied to a `use` item pub fn baz() {} diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr.stderr b/tests/rustdoc-ui/lints/invalid-doc-attr.stderr index 82e1b62b57a62..e431b8df22638 100644 --- a/tests/rustdoc-ui/lints/invalid-doc-attr.stderr +++ b/tests/rustdoc-ui/lints/invalid-doc-attr.stderr @@ -1,14 +1,5 @@ -error: this attribute can only be applied at the crate level - --> $DIR/invalid-doc-attr.rs:7:12 - | -LL | #[doc(test(no_crate_inject))] - | ^^^^^^^^^^^^^^^ - | - = note: read for more information - = note: `#[deny(invalid_doc_attributes)]` on by default - error: this attribute can only be applied to a `use` item - --> $DIR/invalid-doc-attr.rs:9:7 + --> $DIR/invalid-doc-attr.rs:7:7 | LL | #[doc(inline)] | ^^^^^^ only applicable on `use` items @@ -17,17 +8,10 @@ LL | pub fn foo() {} | ------------ not a `use` item | = note: read for more information - -error: this attribute can only be applied at the crate level - --> $DIR/invalid-doc-attr.rs:14:17 - | -LL | #![doc(test(no_crate_inject))] - | ^^^^^^^^^^^^^^^ - | - = note: read for more information + = note: `#[deny(invalid_doc_attributes)]` on by default error: conflicting doc inlining attributes - --> $DIR/invalid-doc-attr.rs:24:7 + --> $DIR/invalid-doc-attr.rs:17:7 | LL | #[doc(inline)] | ^^^^^^ this attribute... @@ -37,7 +21,7 @@ LL | #[doc(no_inline)] = help: remove one of the conflicting attributes error: this attribute can only be applied to an `extern crate` item - --> $DIR/invalid-doc-attr.rs:30:7 + --> $DIR/invalid-doc-attr.rs:23:7 | LL | #[doc(masked)] | ^^^^^^ only applicable on `extern crate` items @@ -48,7 +32,7 @@ LL | pub struct Masked; = note: read for more information error: this attribute cannot be applied to an `extern crate self` item - --> $DIR/invalid-doc-attr.rs:34:7 + --> $DIR/invalid-doc-attr.rs:27:7 | LL | #[doc(masked)] | ^^^^^^ not applicable on `extern crate self` items @@ -70,16 +54,8 @@ LL | | pub extern crate self as reexport; | = note: read for more information -error: this attribute can only be applied at the crate level - --> $DIR/invalid-doc-attr.rs:17:16 - | -LL | #[doc(test(no_crate_inject))] - | ^^^^^^^^^^^^^^^ - | - = note: read for more information - error: this attribute can only be applied to a `use` item - --> $DIR/invalid-doc-attr.rs:19:11 + --> $DIR/invalid-doc-attr.rs:12:11 | LL | #[doc(inline)] | ^^^^^^ only applicable on `use` items @@ -89,5 +65,5 @@ LL | pub fn baz() {} | = note: read for more information -error: aborting due to 9 previous errors +error: aborting due to 6 previous errors diff --git a/tests/ui/asm/s390x/bad-reg.s390x_vector.stderr b/tests/ui/asm/s390x/bad-reg.s390x_vector.stderr index 897f872ae72af..8e2da4dcc2a4d 100644 --- a/tests/ui/asm/s390x/bad-reg.s390x_vector.stderr +++ b/tests/ui/asm/s390x/bad-reg.s390x_vector.stderr @@ -282,7 +282,7 @@ error: type `u8` cannot be used with this register class LL | asm!("", in("v0") b); | ^ | - = note: register class `vreg` supports these types: i32, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2 + = note: register class `vreg` supports these types: i32, f16, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2 error: type `u8` cannot be used with this register class --> $DIR/bad-reg.rs:95:28 @@ -290,7 +290,7 @@ error: type `u8` cannot be used with this register class LL | asm!("", out("v0") b); | ^ | - = note: register class `vreg` supports these types: i32, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2 + = note: register class `vreg` supports these types: i32, f16, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2 error: type `u8` cannot be used with this register class --> $DIR/bad-reg.rs:108:35 @@ -298,7 +298,7 @@ error: type `u8` cannot be used with this register class LL | asm!("/* {} */", in(vreg) b); | ^ | - = note: register class `vreg` supports these types: i32, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2 + = note: register class `vreg` supports these types: i32, f16, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2 error: type `i32` cannot be used with this register class --> $DIR/bad-reg.rs:120:27 diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index fd6f34fb45e29..fc644668735ed 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -32,21 +32,6 @@ error: malformed `patchable_function_entry` attribute input LL | #[patchable_function_entry] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]` -error: malformed `must_not_suspend` attribute input - --> $DIR/malformed-attrs.rs:138:1 - | -LL | #[must_not_suspend()] - | ^^^^^^^^^^^^^^^^^^^^^ - | -help: the following are the possible correct uses - | -LL - #[must_not_suspend()] -LL + #[must_not_suspend = "reason"] - | -LL - #[must_not_suspend()] -LL + #[must_not_suspend] - | - error: malformed `allow` attribute input --> $DIR/malformed-attrs.rs:184:1 | @@ -527,6 +512,22 @@ LL | #[rustc_layout_scalar_valid_range_end] | expected this to be a list | help: must be of the form: `#[rustc_layout_scalar_valid_range_end(end)]` +error[E0539]: malformed `must_not_suspend` attribute input + --> $DIR/malformed-attrs.rs:138:1 + | +LL | #[must_not_suspend()] + | ^^^^^^^^^^^^^^^^^^--^ + | | + | didn't expect a list here + | +help: try changing it to one of the following valid forms of the attribute + | +LL | #[must_not_suspend(count)] + | +++++ +LL - #[must_not_suspend()] +LL + #[must_not_suspend] + | + error[E0539]: malformed `cfi_encoding` attribute input --> $DIR/malformed-attrs.rs:140:1 | diff --git a/tests/ui/closures/multiple-fn-bounds.stderr b/tests/ui/closures/multiple-fn-bounds.stderr index 9b824fa0eefbd..c99cbac01faf8 100644 --- a/tests/ui/closures/multiple-fn-bounds.stderr +++ b/tests/ui/closures/multiple-fn-bounds.stderr @@ -19,11 +19,6 @@ note: required by a bound in `foo` | LL | fn foo bool + Fn(char) -> bool>(f: F) { | ^^^^^^^^^^^^^^^^ required by this bound in `foo` -help: consider adjusting the signature so it does not borrow its argument - | -LL - foo(move |x| v); -LL + foo(move |char| v); - | error: aborting due to 1 previous error diff --git a/tests/ui/lint/must_not_suspend/other_items.rs b/tests/ui/lint/must_not_suspend/other_items.rs index 7a42a2bba03b0..1c46cce7ed3ab 100644 --- a/tests/ui/lint/must_not_suspend/other_items.rs +++ b/tests/ui/lint/must_not_suspend/other_items.rs @@ -2,7 +2,7 @@ #![feature(must_not_suspend)] #![deny(must_not_suspend)] -#[must_not_suspend] //~ ERROR attribute should be +#[must_not_suspend] //~ ERROR attribute cannot be used on modules mod inner {} fn main() {} diff --git a/tests/ui/lint/must_not_suspend/other_items.stderr b/tests/ui/lint/must_not_suspend/other_items.stderr index dff5210b7e47f..999a9d2fb3dc8 100644 --- a/tests/ui/lint/must_not_suspend/other_items.stderr +++ b/tests/ui/lint/must_not_suspend/other_items.stderr @@ -1,10 +1,10 @@ -error: `must_not_suspend` attribute should be applied to a struct, enum, union, or trait +error: `#[must_not_suspend]` attribute cannot be used on modules --> $DIR/other_items.rs:5:1 | LL | #[must_not_suspend] | ^^^^^^^^^^^^^^^^^^^ -LL | mod inner {} - | ------------ is not a struct, enum, union, or trait + | + = help: `#[must_not_suspend]` can be applied to data types, traits, and unions error: aborting due to 1 previous error diff --git a/tests/ui/lint/must_not_suspend/return.rs b/tests/ui/lint/must_not_suspend/return.rs index a04f6a4cfb430..de78ee0f92998 100644 --- a/tests/ui/lint/must_not_suspend/return.rs +++ b/tests/ui/lint/must_not_suspend/return.rs @@ -2,7 +2,7 @@ #![feature(must_not_suspend)] #![deny(must_not_suspend)] -#[must_not_suspend] //~ ERROR attribute should be +#[must_not_suspend] //~ ERROR attribute cannot be used on functions fn foo() -> i32 { 0 } diff --git a/tests/ui/lint/must_not_suspend/return.stderr b/tests/ui/lint/must_not_suspend/return.stderr index 440f816568622..1a81b1a39f0c8 100644 --- a/tests/ui/lint/must_not_suspend/return.stderr +++ b/tests/ui/lint/must_not_suspend/return.stderr @@ -1,12 +1,10 @@ -error: `must_not_suspend` attribute should be applied to a struct, enum, union, or trait +error: `#[must_not_suspend]` attribute cannot be used on functions --> $DIR/return.rs:5:1 | -LL | #[must_not_suspend] - | ^^^^^^^^^^^^^^^^^^^ -LL | / fn foo() -> i32 { -LL | | 0 -LL | | } - | |_- is not a struct, enum, union, or trait +LL | #[must_not_suspend] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[must_not_suspend]` can be applied to data types, traits, and unions error: aborting due to 1 previous error diff --git a/tests/ui/rustdoc/doc-alias-crate-level.stderr b/tests/ui/rustdoc/doc-alias-crate-level.stderr index a40e31714f145..1d10446a4e7c1 100644 --- a/tests/ui/rustdoc/doc-alias-crate-level.stderr +++ b/tests/ui/rustdoc/doc-alias-crate-level.stderr @@ -1,14 +1,14 @@ -error: '\'' character isn't allowed in `#[doc(alias = "...")]` - --> $DIR/doc-alias-crate-level.rs:7:15 - | -LL | #[doc(alias = "shouldn't work!")] - | ^^^^^^^^^^^^^^^^^ - error: `#![doc(alias = "...")]` isn't allowed as a crate-level attribute --> $DIR/doc-alias-crate-level.rs:5:16 | LL | #![doc(alias = "not working!")] | ^^^^^^^^^^^^^^ +error: '\'' character isn't allowed in `#[doc(alias = "...")]` + --> $DIR/doc-alias-crate-level.rs:7:15 + | +LL | #[doc(alias = "shouldn't work!")] + | ^^^^^^^^^^^^^^^^^ + error: aborting due to 2 previous errors diff --git a/tests/ui/rustdoc/doc_keyword.stderr b/tests/ui/rustdoc/doc_keyword.stderr index 56da4b00724a5..c8038cbf01969 100644 --- a/tests/ui/rustdoc/doc_keyword.stderr +++ b/tests/ui/rustdoc/doc_keyword.stderr @@ -1,3 +1,9 @@ +error: `#![doc(keyword = "...")]` isn't allowed as a crate-level attribute + --> $DIR/doc_keyword.rs:4:8 + | +LL | #![doc(keyword = "match")] + | ^^^^^^^ + error: nonexistent keyword `tadam` used in `#[doc(keyword = "...")]` --> $DIR/doc_keyword.rs:22:17 | @@ -24,11 +30,5 @@ error: `#[doc(keyword = "...")]` should be used on modules LL | #[doc(keyword = "match")] | ^^^^^^^ -error: `#![doc(keyword = "...")]` isn't allowed as a crate-level attribute - --> $DIR/doc_keyword.rs:4:8 - | -LL | #![doc(keyword = "match")] - | ^^^^^^^ - error: aborting due to 5 previous errors diff --git a/tests/ui/unpretty/deprecated-attr.stdout b/tests/ui/unpretty/deprecated-attr.stdout index 26cc74c11604d..976598b0bfa32 100644 --- a/tests/ui/unpretty/deprecated-attr.stdout +++ b/tests/ui/unpretty/deprecated-attr.stdout @@ -10,19 +10,19 @@ use ::std::prelude::rust_2015::*; struct PlainDeprecated; #[attr = Deprecation {deprecation: Deprecation {since: Unspecified, -note: "here's why this is deprecated"}}] +note: here's why this is deprecated#0}}] struct DirectNote; #[attr = Deprecation {deprecation: Deprecation {since: Unspecified, -note: "here's why this is deprecated"}}] +note: here's why this is deprecated#0}}] struct ExplicitNote; #[attr = Deprecation {deprecation: Deprecation {since: NonStandard("1.2.3"), -note: "here's why this is deprecated"}}] +note: here's why this is deprecated#0}}] struct SinceAndNote; #[attr = Deprecation {deprecation: Deprecation {since: NonStandard("1.2.3"), -note: "here's why this is deprecated"}}] +note: here's why this is deprecated#0}}] struct FlippedOrder; fn f() { diff --git a/triagebot.toml b/triagebot.toml index 89118fdb5948f..f00b4b9daffc8 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1006,7 +1006,7 @@ cc = ["@fmease"] [mentions."library/core/src/mem/type_info.rs"] message = """ The reflection data structures are tied exactly to the implementation -in the compiler. Make sure to also adjust `rustc_const_eval/src/const_eval/type_info.rs +in the compiler. Make sure to also adjust `rustc_const_eval/src/const_eval/type_info.rs` """ cc = ["@oli-obk"]