Auto merge of #154958 - JonathanBrouwer:rollup-PEahluH, r=JonathanBrouwer

Rollup of 22 pull requests

Successful merges:

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