Port #[custom_mir(..)] to the new attribute system
This commit is contained in:
@@ -43,6 +43,7 @@ pub(crate) mod no_implicit_prelude;
|
||||
pub(crate) mod non_exhaustive;
|
||||
pub(crate) mod path;
|
||||
pub(crate) mod proc_macro_attrs;
|
||||
pub(crate) mod prototype;
|
||||
pub(crate) mod repr;
|
||||
pub(crate) mod rustc_internal;
|
||||
pub(crate) mod semantics;
|
||||
|
||||
140
compiler/rustc_attr_parsing/src/attributes/prototype.rs
Normal file
140
compiler/rustc_attr_parsing/src/attributes/prototype.rs
Normal file
@@ -0,0 +1,140 @@
|
||||
//! Attributes that are only used on function prototypes.
|
||||
|
||||
use rustc_feature::{AttributeTemplate, template};
|
||||
use rustc_hir::Target;
|
||||
use rustc_hir::attrs::{AttributeKind, MirDialect, MirPhase};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
|
||||
use super::{AttributeOrder, OnDuplicate};
|
||||
use crate::attributes::SingleAttributeParser;
|
||||
use crate::context::{AcceptContext, AllowedTargets, MaybeWarn, Stage};
|
||||
use crate::parser::ArgParser;
|
||||
|
||||
pub(crate) struct CustomMirParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for CustomMirParser {
|
||||
const PATH: &[rustc_span::Symbol] = &[sym::custom_mir];
|
||||
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
|
||||
const ALLOWED_TARGETS: AllowedTargets =
|
||||
AllowedTargets::AllowList(&[MaybeWarn::Allow(Target::Fn)]);
|
||||
|
||||
const TEMPLATE: AttributeTemplate = template!(List: &[r#"dialect = "...", phase = "...""#]);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let Some(list) = args.list() else {
|
||||
cx.expected_list(cx.attr_span);
|
||||
return None;
|
||||
};
|
||||
|
||||
let mut dialect = None;
|
||||
let mut phase = None;
|
||||
let mut failed = false;
|
||||
|
||||
for item in list.mixed() {
|
||||
let Some(meta_item) = item.meta_item() else {
|
||||
cx.expected_name_value(item.span(), None);
|
||||
failed = true;
|
||||
break;
|
||||
};
|
||||
|
||||
if let Some(arg) = meta_item.word_is(sym::dialect) {
|
||||
extract_value(cx, sym::dialect, arg, meta_item.span(), &mut dialect, &mut failed);
|
||||
} else if let Some(arg) = meta_item.word_is(sym::phase) {
|
||||
extract_value(cx, sym::phase, arg, meta_item.span(), &mut phase, &mut failed);
|
||||
} else if let Some(word) = meta_item.path().word() {
|
||||
let word = word.to_string();
|
||||
cx.unknown_key(meta_item.span(), word, &["dialect", "phase"]);
|
||||
failed = true;
|
||||
} else {
|
||||
cx.expected_name_value(meta_item.span(), None);
|
||||
failed = true;
|
||||
};
|
||||
}
|
||||
|
||||
let dialect = parse_dialect(cx, dialect, &mut failed);
|
||||
let phase = parse_phase(cx, phase, &mut failed);
|
||||
|
||||
if failed {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(AttributeKind::CustomMir(dialect, phase, cx.attr_span))
|
||||
}
|
||||
}
|
||||
|
||||
fn extract_value<S: Stage>(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
key: Symbol,
|
||||
arg: &ArgParser<'_>,
|
||||
span: Span,
|
||||
out_val: &mut Option<(Symbol, Span)>,
|
||||
failed: &mut bool,
|
||||
) {
|
||||
if out_val.is_some() {
|
||||
cx.duplicate_key(span, key);
|
||||
*failed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(val) = arg.name_value() else {
|
||||
cx.expected_single_argument(arg.span().unwrap_or(span));
|
||||
*failed = true;
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(value_sym) = val.value_as_str() else {
|
||||
cx.expected_string_literal(val.value_span, Some(val.value_as_lit()));
|
||||
*failed = true;
|
||||
return;
|
||||
};
|
||||
|
||||
*out_val = Some((value_sym, val.value_span));
|
||||
}
|
||||
|
||||
fn parse_dialect<S: Stage>(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
dialect: Option<(Symbol, Span)>,
|
||||
failed: &mut bool,
|
||||
) -> Option<(MirDialect, Span)> {
|
||||
let (dialect, span) = dialect?;
|
||||
|
||||
let dialect = match dialect {
|
||||
sym::analysis => MirDialect::Analysis,
|
||||
sym::built => MirDialect::Built,
|
||||
sym::runtime => MirDialect::Runtime,
|
||||
|
||||
_ => {
|
||||
cx.expected_specific_argument(span, vec!["analysis", "built", "runtime"]);
|
||||
*failed = true;
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
Some((dialect, span))
|
||||
}
|
||||
|
||||
fn parse_phase<S: Stage>(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
phase: Option<(Symbol, Span)>,
|
||||
failed: &mut bool,
|
||||
) -> Option<(MirPhase, Span)> {
|
||||
let (phase, span) = phase?;
|
||||
|
||||
let phase = match phase {
|
||||
sym::initial => MirPhase::Initial,
|
||||
sym::post_cleanup => MirPhase::PostCleanup,
|
||||
sym::optimized => MirPhase::Optimized,
|
||||
|
||||
_ => {
|
||||
cx.expected_specific_argument(span, vec!["initial", "post-cleanup", "optimized"]);
|
||||
*failed = true;
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
Some((phase, span))
|
||||
}
|
||||
@@ -46,6 +46,7 @@ use crate::attributes::path::PathParser as PathAttributeParser;
|
||||
use crate::attributes::proc_macro_attrs::{
|
||||
ProcMacroAttributeParser, ProcMacroDeriveParser, ProcMacroParser, RustcBuiltinMacroParser,
|
||||
};
|
||||
use crate::attributes::prototype::CustomMirParser;
|
||||
use crate::attributes::repr::{AlignParser, ReprParser};
|
||||
use crate::attributes::rustc_internal::{
|
||||
RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart,
|
||||
@@ -167,6 +168,7 @@ attribute_parsers!(
|
||||
|
||||
// tidy-alphabetical-start
|
||||
Single<CoverageParser>,
|
||||
Single<CustomMirParser>,
|
||||
Single<DeprecationParser>,
|
||||
Single<DummyParser>,
|
||||
Single<ExportNameParser>,
|
||||
|
||||
@@ -9,6 +9,7 @@ use rustc_abi::TargetDataLayoutErrors;
|
||||
use rustc_ast::util::parser::ExprPrecedence;
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_hir::RustcVersion;
|
||||
use rustc_hir::attrs::{MirDialect, MirPhase};
|
||||
use rustc_macros::Subdiagnostic;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::{Ident, MacroRulesNormalizedIdent, Span, Symbol};
|
||||
@@ -312,6 +313,28 @@ impl IntoDiagArg for ExprPrecedence {
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for MirDialect {
|
||||
fn into_diag_arg(self, _path: &mut Option<PathBuf>) -> DiagArgValue {
|
||||
let arg = match self {
|
||||
MirDialect::Analysis => "analysis",
|
||||
MirDialect::Built => "built",
|
||||
MirDialect::Runtime => "runtime",
|
||||
};
|
||||
DiagArgValue::Str(Cow::Borrowed(arg))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for MirPhase {
|
||||
fn into_diag_arg(self, _path: &mut Option<PathBuf>) -> DiagArgValue {
|
||||
let arg = match self {
|
||||
MirPhase::Initial => "initial",
|
||||
MirPhase::PostCleanup => "post-cleanup",
|
||||
MirPhase::Optimized => "optimized",
|
||||
};
|
||||
DiagArgValue::Str(Cow::Borrowed(arg))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DiagSymbolList<S = Symbol>(Vec<S>);
|
||||
|
||||
|
||||
@@ -205,6 +205,22 @@ pub enum Linkage {
|
||||
WeakODR,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Decodable, Debug, Encodable, PartialEq)]
|
||||
#[derive(HashStable_Generic, PrintAttribute)]
|
||||
pub enum MirDialect {
|
||||
Analysis,
|
||||
Built,
|
||||
Runtime,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Decodable, Debug, Encodable, PartialEq)]
|
||||
#[derive(HashStable_Generic, PrintAttribute)]
|
||||
pub enum MirPhase {
|
||||
Initial,
|
||||
PostCleanup,
|
||||
Optimized,
|
||||
}
|
||||
|
||||
/// Represents parsed *built-in* inert attributes.
|
||||
///
|
||||
/// ## Overview
|
||||
@@ -324,6 +340,9 @@ pub enum AttributeKind {
|
||||
/// Represents `#[coverage(..)]`.
|
||||
Coverage(Span, CoverageAttrKind),
|
||||
|
||||
/// Represents `#[custom_mir]`.
|
||||
CustomMir(Option<(MirDialect, Span)>, Option<(MirPhase, Span)>, Span),
|
||||
|
||||
///Represents `#[rustc_deny_explicit_impl]`.
|
||||
DenyExplicitImpl(Span),
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ impl AttributeKind {
|
||||
ConstTrait(..) => No,
|
||||
Coroutine(..) => No,
|
||||
Coverage(..) => No,
|
||||
CustomMir(_, _, _) => Yes,
|
||||
DenyExplicitImpl(..) => No,
|
||||
Deprecation { .. } => Yes,
|
||||
DoNotImplementViaObject(..) => No,
|
||||
|
||||
@@ -115,48 +115,6 @@ impl MirPhase {
|
||||
MirPhase::Runtime(runtime_phase) => (3, 1 + runtime_phase as usize),
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses a `MirPhase` from a pair of strings. Panics if this isn't possible for any reason.
|
||||
pub fn parse(dialect: String, phase: Option<String>) -> Self {
|
||||
match &*dialect.to_ascii_lowercase() {
|
||||
"built" => {
|
||||
assert!(phase.is_none(), "Cannot specify a phase for `Built` MIR");
|
||||
MirPhase::Built
|
||||
}
|
||||
"analysis" => Self::Analysis(AnalysisPhase::parse(phase)),
|
||||
"runtime" => Self::Runtime(RuntimePhase::parse(phase)),
|
||||
_ => bug!("Unknown MIR dialect: '{}'", dialect),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AnalysisPhase {
|
||||
pub fn parse(phase: Option<String>) -> Self {
|
||||
let Some(phase) = phase else {
|
||||
return Self::Initial;
|
||||
};
|
||||
|
||||
match &*phase.to_ascii_lowercase() {
|
||||
"initial" => Self::Initial,
|
||||
"post_cleanup" | "post-cleanup" | "postcleanup" => Self::PostCleanup,
|
||||
_ => bug!("Unknown analysis phase: '{}'", phase),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RuntimePhase {
|
||||
pub fn parse(phase: Option<String>) -> Self {
|
||||
let Some(phase) = phase else {
|
||||
return Self::Initial;
|
||||
};
|
||||
|
||||
match &*phase.to_ascii_lowercase() {
|
||||
"initial" => Self::Initial,
|
||||
"post_cleanup" | "post-cleanup" | "postcleanup" => Self::PostCleanup,
|
||||
"optimized" => Self::Optimized,
|
||||
_ => bug!("Unknown runtime phase: '{}'", phase),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Where a specific `mir::Body` comes from.
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{Attribute, HirId};
|
||||
use rustc_hir::{HirId, attrs};
|
||||
use rustc_index::{IndexSlice, IndexVec};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::thir::*;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
@@ -39,7 +39,8 @@ pub(super) fn build_custom_mir<'tcx>(
|
||||
return_ty: Ty<'tcx>,
|
||||
return_ty_span: Span,
|
||||
span: Span,
|
||||
attr: &Attribute,
|
||||
dialect: Option<attrs::MirDialect>,
|
||||
phase: Option<attrs::MirPhase>,
|
||||
) -> Body<'tcx> {
|
||||
let mut body = Body {
|
||||
basic_blocks: BasicBlocks::new(IndexVec::new()),
|
||||
@@ -72,7 +73,7 @@ pub(super) fn build_custom_mir<'tcx>(
|
||||
inlined_parent_scope: None,
|
||||
local_data: ClearCrossCrate::Set(SourceScopeLocalData { lint_root: hir_id }),
|
||||
});
|
||||
body.injection_phase = Some(parse_attribute(attr));
|
||||
body.injection_phase = Some(parse_attribute(dialect, phase));
|
||||
|
||||
let mut pctxt = ParseCtxt {
|
||||
tcx,
|
||||
@@ -98,40 +99,38 @@ pub(super) fn build_custom_mir<'tcx>(
|
||||
body
|
||||
}
|
||||
|
||||
fn parse_attribute(attr: &Attribute) -> MirPhase {
|
||||
let meta_items = attr.meta_item_list().unwrap();
|
||||
let mut dialect: Option<String> = None;
|
||||
let mut phase: Option<String> = None;
|
||||
|
||||
// Not handling errors properly for this internal attribute; will just abort on errors.
|
||||
for nested in meta_items {
|
||||
let name = nested.name().unwrap();
|
||||
let value = nested.value_str().unwrap().as_str().to_string();
|
||||
match name.as_str() {
|
||||
"dialect" => {
|
||||
assert!(dialect.is_none());
|
||||
dialect = Some(value);
|
||||
}
|
||||
"phase" => {
|
||||
assert!(phase.is_none());
|
||||
phase = Some(value);
|
||||
}
|
||||
other => {
|
||||
span_bug!(
|
||||
nested.span(),
|
||||
"Unexpected key while parsing custom_mir attribute: '{}'",
|
||||
other
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Turns the arguments passed to `#[custom_mir(..)]` into a proper
|
||||
/// [`MirPhase`]. Panics if this isn't possible for any reason.
|
||||
fn parse_attribute(dialect: Option<attrs::MirDialect>, phase: Option<attrs::MirPhase>) -> MirPhase {
|
||||
let Some(dialect) = dialect else {
|
||||
// Caught during attribute checking.
|
||||
assert!(phase.is_none());
|
||||
return MirPhase::Built;
|
||||
};
|
||||
|
||||
MirPhase::parse(dialect, phase)
|
||||
match dialect {
|
||||
attrs::MirDialect::Built => {
|
||||
// Caught during attribute checking.
|
||||
assert!(phase.is_none(), "Cannot specify a phase for `Built` MIR");
|
||||
MirPhase::Built
|
||||
}
|
||||
attrs::MirDialect::Analysis => match phase {
|
||||
None | Some(attrs::MirPhase::Initial) => MirPhase::Analysis(AnalysisPhase::Initial),
|
||||
|
||||
Some(attrs::MirPhase::PostCleanup) => MirPhase::Analysis(AnalysisPhase::PostCleanup),
|
||||
|
||||
Some(attrs::MirPhase::Optimized) => {
|
||||
// Caught during attribute checking.
|
||||
bug!("`optimized` dialect is not compatible with the `analysis` dialect")
|
||||
}
|
||||
},
|
||||
|
||||
attrs::MirDialect::Runtime => match phase {
|
||||
None | Some(attrs::MirPhase::Initial) => MirPhase::Runtime(RuntimePhase::Initial),
|
||||
Some(attrs::MirPhase::PostCleanup) => MirPhase::Runtime(RuntimePhase::PostCleanup),
|
||||
Some(attrs::MirPhase::Optimized) => MirPhase::Runtime(RuntimePhase::Optimized),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
struct ParseCtxt<'a, 'tcx> {
|
||||
|
||||
@@ -11,9 +11,10 @@ use rustc_ast::attr;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sorted_map::SortedIndexMultiMap;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, ItemLocalId, Node};
|
||||
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, ItemLocalId, Node, find_attr};
|
||||
use rustc_index::bit_set::GrowableBitSet;
|
||||
use rustc_index::{Idx, IndexSlice, IndexVec};
|
||||
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||
@@ -479,8 +480,7 @@ fn construct_fn<'tcx>(
|
||||
ty => span_bug!(span_with_body, "unexpected type of body: {ty:?}"),
|
||||
};
|
||||
|
||||
if let Some(custom_mir_attr) =
|
||||
tcx.hir_attrs(fn_id).iter().find(|attr| attr.has_name(sym::custom_mir))
|
||||
if let Some((dialect, phase)) = find_attr!(tcx.hir_attrs(fn_id), AttributeKind::CustomMir(dialect, phase, _) => (dialect, phase))
|
||||
{
|
||||
return custom::build_custom_mir(
|
||||
tcx,
|
||||
@@ -492,7 +492,8 @@ fn construct_fn<'tcx>(
|
||||
return_ty,
|
||||
return_ty_span,
|
||||
span_with_body,
|
||||
custom_mir_attr,
|
||||
dialect.as_ref().map(|(d, _)| *d),
|
||||
phase.as_ref().map(|(p, _)| *p),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,9 @@ use std::ops::Bound;
|
||||
use rustc_ast::AsmMacro;
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_errors::DiagArgValue;
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability};
|
||||
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability, find_attr};
|
||||
use rustc_middle::middle::codegen_fn_attrs::TargetFeature;
|
||||
use rustc_middle::mir::BorrowKind;
|
||||
use rustc_middle::span_bug;
|
||||
@@ -1157,7 +1158,7 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
|
||||
// Closures and inline consts are handled by their owner, if it has a body
|
||||
assert!(!tcx.is_typeck_child(def.to_def_id()));
|
||||
// Also, don't safety check custom MIR
|
||||
if tcx.has_attr(def, sym::custom_mir) {
|
||||
if find_attr!(tcx.get_all_attrs(def), AttributeKind::CustomMir(..) => ()).is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
|
||||
use rustc_data_structures::steal::Steal;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::HirId;
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{self as hir, HirId, find_attr};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::middle::region;
|
||||
use rustc_middle::thir::*;
|
||||
@@ -111,10 +111,8 @@ impl<'tcx> ThirBuildCx<'tcx> {
|
||||
typeck_results,
|
||||
rvalue_scopes: &typeck_results.rvalue_scopes,
|
||||
body_owner: def.to_def_id(),
|
||||
apply_adjustments: tcx
|
||||
.hir_attrs(hir_id)
|
||||
.iter()
|
||||
.all(|attr| !attr.has_name(rustc_span::sym::custom_mir)),
|
||||
apply_adjustments:
|
||||
!find_attr!(tcx.hir_attrs(hir_id), AttributeKind::CustomMir(..) => ()).is_some(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -74,6 +74,16 @@ passes_const_stable_not_stable =
|
||||
attribute `#[rustc_const_stable]` can only be applied to functions that are declared `#[stable]`
|
||||
.label = attribute specified here
|
||||
|
||||
passes_custom_mir_incompatible_dialect_and_phase =
|
||||
The {$dialect} dialect is not compatible with the {$phase} phase
|
||||
.dialect_span = this dialect...
|
||||
.phase_span = ... is not compatible with this phase
|
||||
|
||||
passes_custom_mir_phase_requires_dialect =
|
||||
`dialect` key required
|
||||
.phase_span = `phase` argument requires a `dialect` argument
|
||||
|
||||
|
||||
passes_dead_codes =
|
||||
{ $multiple ->
|
||||
*[true] multiple {$descr}s are
|
||||
|
||||
@@ -18,7 +18,7 @@ use rustc_feature::{
|
||||
ACCEPTED_LANG_FEATURES, AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP,
|
||||
BuiltinAttribute,
|
||||
};
|
||||
use rustc_hir::attrs::{AttributeKind, InlineAttr, ReprAttr};
|
||||
use rustc_hir::attrs::{AttributeKind, InlineAttr, MirDialect, MirPhase, ReprAttr};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::LocalModDefId;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
@@ -197,6 +197,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||
Attribute::Parsed(AttributeKind::MustUse { span, .. }) => {
|
||||
self.check_must_use(hir_id, *span, target)
|
||||
}
|
||||
&Attribute::Parsed(AttributeKind::CustomMir(dialect, phase, attr_span)) => {
|
||||
self.check_custom_mir(dialect, phase, attr_span)
|
||||
}
|
||||
Attribute::Parsed(
|
||||
AttributeKind::BodyStability { .. }
|
||||
| AttributeKind::ConstStabilityIndirect
|
||||
@@ -248,7 +251,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||
| AttributeKind::Coroutine(..)
|
||||
| AttributeKind::Linkage(..),
|
||||
) => { /* do nothing */ }
|
||||
|
||||
Attribute::Unparsed(attr_item) => {
|
||||
style = Some(attr_item.style);
|
||||
match attr.path().as_slice() {
|
||||
@@ -331,8 +333,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||
| sym::panic_handler
|
||||
| sym::lang
|
||||
| sym::needs_allocator
|
||||
| sym::default_lib_allocator
|
||||
| sym::custom_mir,
|
||||
| sym::default_lib_allocator,
|
||||
..
|
||||
] => {}
|
||||
[name, rest@..] => {
|
||||
@@ -2113,6 +2114,48 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||
self.dcx().emit_err(errors::ConstContinueAttr { attr_span, node_span });
|
||||
};
|
||||
}
|
||||
|
||||
fn check_custom_mir(
|
||||
&self,
|
||||
dialect: Option<(MirDialect, Span)>,
|
||||
phase: Option<(MirPhase, Span)>,
|
||||
attr_span: Span,
|
||||
) {
|
||||
let Some((dialect, dialect_span)) = dialect else {
|
||||
if let Some((_, phase_span)) = phase {
|
||||
self.dcx()
|
||||
.emit_err(errors::CustomMirPhaseRequiresDialect { attr_span, phase_span });
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
||||
match dialect {
|
||||
MirDialect::Analysis => {
|
||||
if let Some((MirPhase::Optimized, phase_span)) = phase {
|
||||
self.dcx().emit_err(errors::CustomMirIncompatibleDialectAndPhase {
|
||||
dialect,
|
||||
phase: MirPhase::Optimized,
|
||||
attr_span,
|
||||
dialect_span,
|
||||
phase_span,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
MirDialect::Built => {
|
||||
if let Some((phase, phase_span)) = phase {
|
||||
self.dcx().emit_err(errors::CustomMirIncompatibleDialectAndPhase {
|
||||
dialect,
|
||||
phase,
|
||||
attr_span,
|
||||
dialect_span,
|
||||
phase_span,
|
||||
});
|
||||
}
|
||||
}
|
||||
MirDialect::Runtime => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
|
||||
|
||||
@@ -7,6 +7,7 @@ use rustc_errors::{
|
||||
MultiSpan, Subdiagnostic,
|
||||
};
|
||||
use rustc_hir::Target;
|
||||
use rustc_hir::attrs::{MirDialect, MirPhase};
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
use rustc_middle::ty::{MainDefinition, Ty};
|
||||
use rustc_span::{DUMMY_SP, Span, Symbol};
|
||||
@@ -1570,3 +1571,25 @@ pub(crate) struct ReprAlignShouldBeAlign {
|
||||
pub span: Span,
|
||||
pub item: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_custom_mir_phase_requires_dialect)]
|
||||
pub(crate) struct CustomMirPhaseRequiresDialect {
|
||||
#[primary_span]
|
||||
pub attr_span: Span,
|
||||
#[label]
|
||||
pub phase_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_custom_mir_incompatible_dialect_and_phase)]
|
||||
pub(crate) struct CustomMirIncompatibleDialectAndPhase {
|
||||
pub dialect: MirDialect,
|
||||
pub phase: MirPhase,
|
||||
#[primary_span]
|
||||
pub attr_span: Span,
|
||||
#[label]
|
||||
pub dialect_span: Span,
|
||||
#[label]
|
||||
pub phase_span: Span,
|
||||
}
|
||||
|
||||
@@ -446,6 +446,7 @@ symbols! {
|
||||
altivec,
|
||||
alu32,
|
||||
always,
|
||||
analysis,
|
||||
and,
|
||||
and_then,
|
||||
anon,
|
||||
@@ -587,6 +588,7 @@ symbols! {
|
||||
btreemap_contains_key,
|
||||
btreemap_insert,
|
||||
btreeset_iter,
|
||||
built,
|
||||
builtin_syntax,
|
||||
c,
|
||||
c_dash_variadic,
|
||||
@@ -851,6 +853,7 @@ symbols! {
|
||||
destructuring_assignment,
|
||||
diagnostic,
|
||||
diagnostic_namespace,
|
||||
dialect,
|
||||
direct,
|
||||
discriminant_kind,
|
||||
discriminant_type,
|
||||
@@ -1207,6 +1210,7 @@ symbols! {
|
||||
infer_static_outlives_requirements,
|
||||
inherent_associated_types,
|
||||
inherit,
|
||||
initial,
|
||||
inlateout,
|
||||
inline,
|
||||
inline_const,
|
||||
@@ -1542,6 +1546,7 @@ symbols! {
|
||||
opt_out_copy,
|
||||
optimize,
|
||||
optimize_attribute,
|
||||
optimized,
|
||||
optin_builtin_traits,
|
||||
option,
|
||||
option_env,
|
||||
@@ -1623,6 +1628,7 @@ symbols! {
|
||||
pattern_types,
|
||||
permissions_from_mode,
|
||||
phantom_data,
|
||||
phase,
|
||||
pic,
|
||||
pie,
|
||||
pin,
|
||||
@@ -1639,6 +1645,7 @@ symbols! {
|
||||
poll,
|
||||
poll_next,
|
||||
position,
|
||||
post_cleanup: "post-cleanup",
|
||||
post_dash_lto: "post-lto",
|
||||
postfix_match,
|
||||
powerpc_target_feature,
|
||||
@@ -1802,6 +1809,7 @@ symbols! {
|
||||
roundf128,
|
||||
rt,
|
||||
rtm_target_feature,
|
||||
runtime,
|
||||
rust,
|
||||
rust_2015,
|
||||
rust_2018,
|
||||
|
||||
Reference in New Issue
Block a user