Auto merge of #151051 - JonathanBrouwer:rollup-SuaGLmP, r=JonathanBrouwer

Rollup of 14 pull requests

Successful merges:

 - rust-lang/rust#150151 (Destabilise `target-spec-json`)
 - rust-lang/rust#150826 (Add `f16` inline ASM support for s390x)
 - rust-lang/rust#150883 (Improve span for "unresolved intra doc link" on `deprecated` attribute)
 - rust-lang/rust#150934 (Move some checks from `check_doc_attrs` directly into `rustc_attr_parsing`)
 - rust-lang/rust#150943 (Port `#[must_not_suspend]` to attribute parser)
 - rust-lang/rust#150990 (std: sys: net: uefi: Make TcpStream Send)
 - rust-lang/rust#150995 (core: ptr: split_at_mut: fix typo in safety doc)
 - rust-lang/rust#150998 (Relax test expectation for @__llvm_profile_runtime_user)
 - rust-lang/rust#151002 (Remove a workaround for a bug (take 2))
 - rust-lang/rust#151005 (Fix typo in `MaybeUninit` docs)
 - rust-lang/rust#151011 (Update books)
 - rust-lang/rust#151029 (rustc-dev-guide subtree update)
 - rust-lang/rust#151032 (fix: added missing backtick in triagebot.toml)
 - rust-lang/rust#151035 (Don't suggest replacing closure parameter with type name)

r? @ghost
This commit is contained in:
bors 2026-01-13 10:47:20 +00:00
commit db1484bdee
69 changed files with 656 additions and 539 deletions

View file

@ -235,14 +235,14 @@ impl AttributeExt for Attribute {
}
}
fn deprecation_note(&self) -> Option<Symbol> {
fn deprecation_note(&self) -> Option<Ident> {
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<Symbol>;
fn deprecation_note(&self) -> Option<Ident>;
fn is_proc_macro_attr(&self) -> bool {
[sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive]

View file

@ -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

View file

@ -13,14 +13,14 @@ fn get<S: Stage>(
name: Symbol,
param_span: Span,
arg: &ArgParser,
item: &Option<Symbol>,
) -> Option<Symbol> {
item: Option<Symbol>,
) -> Option<Ident> {
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<S: Stage> SingleAttributeParser<S> for DeprecationParser {
let features = cx.features();
let mut since = None;
let mut note = None;
let mut note: Option<Ident> = None;
let mut suggestion = None;
let is_rustc = features.staged_api();
@ -92,10 +92,16 @@ impl<S: Stage> SingleAttributeParser<S> 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(), &note)?);
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<S: Stage> SingleAttributeParser<S> 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<S: Stage> SingleAttributeParser<S> 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;
};

View file

@ -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<S: Stage>(cx: &mut AcceptContext<'_, '_, S>, keyword: Symbol, span: Span) -> bool {
@ -43,16 +44,39 @@ fn check_attribute<S: Stage>(
false
}
fn parse_keyword_and_attribute<S, F>(
/// Checks that an attribute is *not* used at the crate level. Returns `true` if valid.
fn check_attr_not_crate_level<S: Stage>(
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<S: Stage>(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<S: Stage>(
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<S, F>(
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 {

View file

@ -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;

View file

@ -0,0 +1,35 @@
use super::prelude::*;
pub(crate) struct MustNotSuspendParser;
impl<S: Stage> SingleAttributeParser<S> for MustNotSuspendParser {
const PATH: &[rustc_span::Symbol] = &[sym::must_not_suspend];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = 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<AttributeKind> {
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 })
}
}

View file

@ -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<S> = LazyLock<GroupTypeInner<S>>;
pub(super) struct GroupTypeInner<S: Stage> {
@ -208,6 +208,7 @@ attribute_parsers!(
Single<LinkageParser>,
Single<MacroExportParser>,
Single<MoveSizeLimitParser>,
Single<MustNotSuspendParser>,
Single<MustUseParser>,
Single<ObjcClassParser>,
Single<ObjcSelectorParser>,
@ -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<rustc_hir::Target>,
pub(crate) emit_lint: &'p mut dyn FnMut(AttributeLint<S::Id>),
}

View file

@ -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,

View file

@ -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<Ident> {
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)
}

View file

@ -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]

View file

@ -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)
}

View file

@ -136,7 +136,7 @@ pub enum IntType {
pub struct Deprecation {
pub since: DeprecatedSince,
/// The note to issue a reason.
pub note: Option<Symbol>,
pub note: Option<Ident>,
/// 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<Symbol> },
/// Represents `#[must_use]`.
MustUse {
span: Span,

View file

@ -71,6 +71,7 @@ impl AttributeKind {
Marker(..) => No,
MayDangle(..) => No,
MoveSizeLimit { .. } => No,
MustNotSupend { .. } => Yes,
MustUse { .. } => Yes,
Naked(..) => No,
NoCore(..) => No,

View file

@ -1410,7 +1410,7 @@ impl AttributeExt for Attribute {
}
#[inline]
fn deprecation_note(&self) -> Option<Symbol> {
fn deprecation_note(&self) -> Option<Ident> {
match &self {
Attribute::Parsed(AttributeKind::Deprecation { deprecation, .. }) => deprecation.note,
_ => None,

View file

@ -435,6 +435,7 @@ pub fn run_compiler<R: Send>(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();

View file

@ -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();

View file

@ -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 <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
lint_bad_attribute_argument = bad attribute argument
lint_bad_opt_access = {$msg}

View file

@ -417,5 +417,7 @@ pub fn decorate_attribute_lint(
}
&AttributeLintKind::DocTestLiteral => lints::DocTestLiteral.decorate_lint(diag),
&AttributeLintKind::AttrCrateLevelOnly => lints::AttrCrateLevelOnly.decorate_lint(diag),
}
}

View file

@ -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;

View file

@ -820,6 +820,7 @@ pub enum AttributeLintKind {
name: Symbol,
},
DocTestLiteral,
AttrCrateLevelOnly,
}
pub type RegisteredTools = FxIndexSet<Ident>;

View file

@ -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

View file

@ -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);

View file

@ -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,

View file

@ -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)]

View file

@ -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 <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> 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`

View file

@ -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)

View file

@ -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)]

View file

@ -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)

View file

@ -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)
}

View file

@ -42,13 +42,13 @@ impl S390xInlineAsmRegClass {
) -> &'static [(InlineAsmType, Option<Symbol>)] {
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 {
&[]

View file

@ -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:?}"))

View file

@ -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()));
}
}
}
}

View file

@ -256,7 +256,7 @@ use crate::{fmt, intrinsics, ptr, slice};
///
/// # Validity
///
/// `MaybeUninit<T>` has no validity requirements - any sequence of [bytes] of
/// `MaybeUninit<T>` has no validity requirements any sequence of [bytes] of
/// the appropriate length, initialized or uninitialized, are a valid
/// representation.
///

View file

@ -1742,7 +1742,7 @@ impl<T> *mut [T] {
/// that is at least `mid * size_of::<T>()` 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.
///

View file

@ -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<Duration>) -> io::Result<Self> {
match addr {

@ -1 +1 @@
Subproject commit 5b3a9d084cbc64e54da87e3eec7c7faae0e48ba9
Subproject commit 050c002a360fa45b701ea34feed7a860dc8a41bf

@ -1 +1 @@
Subproject commit 6363385ac4ebe1763f1e6fb2063c0b1db681a072
Subproject commit 28b5a54419985f03db5294de5eede71b6665b594

@ -1 +1 @@
Subproject commit 2e02f22a10e7eeb758e6aba484f13d0f1988a3e5
Subproject commit 8de6ff811315ac3a96ebe01d74057382e42ffdee

View file

@ -27,7 +27,7 @@ static REGEX_SPLIT: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"([^\.\d\-\*]\.|[^r]\?|!)\s").unwrap());
// list elements, numbered (1.) or not (- and *)
static REGEX_LIST_ENTRY: LazyLock<Regex> =
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
```

View file

@ -1 +1 @@
85c8ff69cb3efd950395cc444a54bbbdad668865
44a5b55557c26353f388400d7da95527256fe260

View file

@ -6,7 +6,7 @@ parse.
```rust
fn func<T, const N: usize>(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
[`ast::Ty::Path(N)`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/enum.TyKind.html#variant.Path

View file

@ -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 \

View file

@ -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<T: Sized>() {
let a = [1_u8; size_of::<*mut T>()];
let a = [1_u8; size_of::<T>()];
}
```
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).

View file

@ -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 `<branch-name>` in a `rustc` fork under the `<gh-username>` account
1. Run the push command to create a branch named `<branch-name>` in a `rustc` fork under the `<gh-username>` account
```
rustc-josh-sync push <branch-name> <gh-username>
```
2) Create a PR from `<branch-name>` into `rust-lang/rust`
2. Create a PR from `<branch-name>` 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

View file

@ -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 <id>`: Benchmark the compiler and store the results under the passed `id`.
- `compare <baseline> <modified>`: 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:
- `<PROFILE>`: Profiler selection for how performance should be measured.
For this example, we will use Cachegrind.
- `<RUSTC>`: 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 `<SHA1>` and `<SHA2>` from the `rust-lang/rust` repository,
run the following in the `rustc-perf` repo:
```
cargo run --release --bin collector profile_local cachegrind +<SHA1> --rustc2 +<SHA2> --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

View file

@ -34,8 +34,8 @@ pub type Alias = Option<i32>;
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.

View file

@ -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**
>

View file

@ -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 <!-- date-check: Oct 2024 --> 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_<directive-name>`
(note kebab-case `<directive-command>` transformed to snake-case
`<directive_command>`). `impl Config` also defines several 'low-level' parsers
(note kebab-case `<directive-command>` transformed to snake-case `<directive_command>`).
`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.

View file

@ -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).

View file

@ -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()

View file

@ -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

View file

@ -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: }

View file

@ -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();
}

View file

@ -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:

View file

@ -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() {}
}

View file

@ -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 <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> 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 <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> 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 <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
error: aborting due to 3 previous errors

View file

@ -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() {}

View file

@ -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 <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> 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 <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> 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 <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> 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 <https://doc.rust-lang.org/unstable-book/language-features/doc-masked.html> 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 <https://doc.rust-lang.org/unstable-book/language-features/doc-masked.html> 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 <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> 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 <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
error: aborting due to 9 previous errors
error: aborting due to 6 previous errors

View file

@ -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

View file

@ -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
|

View file

@ -19,11 +19,6 @@ note: required by a bound in `foo`
|
LL | fn foo<F: Fn(&char) -> 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

View file

@ -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() {}

View file

@ -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

View file

@ -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
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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() {

View file

@ -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"]