expand: Leave traces when expanding cfg
attributes
This commit is contained in:
parent
65899c06f1
commit
92d802eda6
24 changed files with 88 additions and 108 deletions
|
@ -334,8 +334,7 @@ impl<'a> AstValidator<'a> {
|
||||||
.filter(|attr| {
|
.filter(|attr| {
|
||||||
let arr = [
|
let arr = [
|
||||||
sym::allow,
|
sym::allow,
|
||||||
sym::cfg,
|
sym::cfg_trace,
|
||||||
sym::cfg_attr,
|
|
||||||
sym::cfg_attr_trace,
|
sym::cfg_attr_trace,
|
||||||
sym::deny,
|
sym::deny,
|
||||||
sym::expect,
|
sym::expect,
|
||||||
|
|
|
@ -593,7 +593,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_attribute_inline(&mut self, attr: &ast::Attribute, is_inline: bool) -> bool {
|
fn print_attribute_inline(&mut self, attr: &ast::Attribute, is_inline: bool) -> bool {
|
||||||
if attr.has_name(sym::cfg_attr_trace) {
|
if attr.has_name(sym::cfg_trace) || attr.has_name(sym::cfg_attr_trace) {
|
||||||
// It's not a valid identifier, so avoid printing it
|
// It's not a valid identifier, so avoid printing it
|
||||||
// to keep the printed code reasonably parse-able.
|
// to keep the printed code reasonably parse-able.
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -156,6 +156,19 @@ pub fn pre_configure_attrs(sess: &Session, attrs: &[Attribute]) -> ast::AttrVec
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn attr_into_trace(mut attr: Attribute, trace_name: Symbol) -> Attribute {
|
||||||
|
match &mut attr.kind {
|
||||||
|
AttrKind::Normal(normal) => {
|
||||||
|
let NormalAttr { item, tokens } = &mut **normal;
|
||||||
|
item.path.segments[0].ident.name = trace_name;
|
||||||
|
// This makes the trace attributes unobservable to token-based proc macros.
|
||||||
|
*tokens = Some(LazyAttrTokenStream::new(AttrTokenStream::default()));
|
||||||
|
}
|
||||||
|
AttrKind::DocComment(..) => unreachable!(),
|
||||||
|
}
|
||||||
|
attr
|
||||||
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! configure {
|
macro_rules! configure {
|
||||||
($this:ident, $node:ident) => {
|
($this:ident, $node:ident) => {
|
||||||
|
@ -280,16 +293,7 @@ impl<'a> StripUnconfigured<'a> {
|
||||||
|
|
||||||
// A trace attribute left in AST in place of the original `cfg_attr` attribute.
|
// A trace attribute left in AST in place of the original `cfg_attr` attribute.
|
||||||
// It can later be used by lints or other diagnostics.
|
// It can later be used by lints or other diagnostics.
|
||||||
let mut trace_attr = cfg_attr.clone();
|
let trace_attr = attr_into_trace(cfg_attr.clone(), sym::cfg_attr_trace);
|
||||||
match &mut trace_attr.kind {
|
|
||||||
AttrKind::Normal(normal) => {
|
|
||||||
let NormalAttr { item, tokens } = &mut **normal;
|
|
||||||
item.path.segments[0].ident.name = sym::cfg_attr_trace;
|
|
||||||
// This makes the trace attributes unobservable to token-based proc macros.
|
|
||||||
*tokens = Some(LazyAttrTokenStream::new(AttrTokenStream::default()));
|
|
||||||
}
|
|
||||||
AttrKind::DocComment(..) => unreachable!(),
|
|
||||||
}
|
|
||||||
|
|
||||||
let Some((cfg_predicate, expanded_attrs)) =
|
let Some((cfg_predicate, expanded_attrs)) =
|
||||||
rustc_parse::parse_cfg_attr(cfg_attr, &self.sess.psess)
|
rustc_parse::parse_cfg_attr(cfg_attr, &self.sess.psess)
|
||||||
|
|
|
@ -33,7 +33,7 @@ use rustc_span::{ErrorGuaranteed, FileName, Ident, LocalExpnId, Span, sym};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use crate::base::*;
|
use crate::base::*;
|
||||||
use crate::config::StripUnconfigured;
|
use crate::config::{StripUnconfigured, attr_into_trace};
|
||||||
use crate::errors::{
|
use crate::errors::{
|
||||||
EmptyDelegationMac, GlobDelegationOutsideImpls, GlobDelegationTraitlessQpath, IncompleteParse,
|
EmptyDelegationMac, GlobDelegationOutsideImpls, GlobDelegationTraitlessQpath, IncompleteParse,
|
||||||
RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue,
|
RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue,
|
||||||
|
@ -2003,7 +2003,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
||||||
let attr_name = attr.ident().unwrap().name;
|
let attr_name = attr.ident().unwrap().name;
|
||||||
// `#[cfg]` and `#[cfg_attr]` are special - they are
|
// `#[cfg]` and `#[cfg_attr]` are special - they are
|
||||||
// eagerly evaluated.
|
// eagerly evaluated.
|
||||||
if attr_name != sym::cfg && attr_name != sym::cfg_attr_trace {
|
if attr_name != sym::cfg_trace && attr_name != sym::cfg_attr_trace {
|
||||||
self.cx.sess.psess.buffer_lint(
|
self.cx.sess.psess.buffer_lint(
|
||||||
UNUSED_ATTRIBUTES,
|
UNUSED_ATTRIBUTES,
|
||||||
attr.span,
|
attr.span,
|
||||||
|
@ -2027,11 +2027,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
||||||
) -> (bool, Option<ast::MetaItem>) {
|
) -> (bool, Option<ast::MetaItem>) {
|
||||||
let (res, meta_item) = self.cfg().cfg_true(&attr);
|
let (res, meta_item) = self.cfg().cfg_true(&attr);
|
||||||
if res {
|
if res {
|
||||||
// FIXME: `cfg(TRUE)` attributes do not currently remove themselves during expansion,
|
// A trace attribute left in AST in place of the original `cfg` attribute.
|
||||||
// and some tools like rustdoc and clippy rely on that. Find a way to remove them
|
// It can later be used by lints or other diagnostics.
|
||||||
// while keeping the tools working.
|
let trace_attr = attr_into_trace(attr, sym::cfg_trace);
|
||||||
self.cx.expanded_inert_attrs.mark(&attr);
|
node.visit_attrs(|attrs| attrs.insert(pos, trace_attr));
|
||||||
node.visit_attrs(|attrs| attrs.insert(pos, attr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(res, meta_item)
|
(res, meta_item)
|
||||||
|
|
|
@ -760,10 +760,14 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
template!(Word, List: r#""...""#), DuplicatesOk,
|
template!(Word, List: r#""...""#), DuplicatesOk,
|
||||||
EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
|
EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
|
||||||
),
|
),
|
||||||
// Trace that is left when a `cfg_attr` attribute is expanded.
|
// Traces that are left when `cfg` and `cfg_attr` attributes are expanded.
|
||||||
// The attribute is not gated, to avoid stability errors, but it cannot be used in stable or
|
// The attributes are not gated, to avoid stability errors, but they cannot be used in stable
|
||||||
// unstable code directly because `sym::cfg_attr_trace` is not a valid identifier, it can only
|
// or unstable code directly because `sym::cfg_(attr_)trace` are not valid identifiers, they
|
||||||
// be generated by the compiler.
|
// can only be generated by the compiler.
|
||||||
|
ungated!(
|
||||||
|
cfg_trace, Normal, template!(Word /* irrelevant */), DuplicatesOk,
|
||||||
|
EncodeCrossCrate::No
|
||||||
|
),
|
||||||
ungated!(
|
ungated!(
|
||||||
cfg_attr_trace, Normal, template!(Word /* irrelevant */), DuplicatesOk,
|
cfg_attr_trace, Normal, template!(Word /* irrelevant */), DuplicatesOk,
|
||||||
EncodeCrossCrate::No
|
EncodeCrossCrate::No
|
||||||
|
|
|
@ -16,7 +16,8 @@ use rustc_span::{Span, Symbol, sym};
|
||||||
use crate::{errors, parse_in};
|
use crate::{errors, parse_in};
|
||||||
|
|
||||||
pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
|
pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
|
||||||
if attr.is_doc_comment() || attr.has_name(sym::cfg_attr_trace) {
|
if attr.is_doc_comment() || attr.has_name(sym::cfg_trace) || attr.has_name(sym::cfg_attr_trace)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,11 +216,7 @@ pub fn check_builtin_meta_item(
|
||||||
template: AttributeTemplate,
|
template: AttributeTemplate,
|
||||||
deny_unsafety: bool,
|
deny_unsafety: bool,
|
||||||
) {
|
) {
|
||||||
// Some special attributes like `cfg` must be checked
|
if !is_attr_template_compatible(&template, &meta.kind) {
|
||||||
// before the generic check, so we skip them here.
|
|
||||||
let should_skip = |name| name == sym::cfg;
|
|
||||||
|
|
||||||
if !should_skip(name) && !is_attr_template_compatible(&template, &meta.kind) {
|
|
||||||
emit_malformed_attribute(psess, style, meta.span, name, template);
|
emit_malformed_attribute(psess, style, meta.span, name, template);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -272,6 +272,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
| sym::forbid
|
| sym::forbid
|
||||||
| sym::cfg
|
| sym::cfg
|
||||||
| sym::cfg_attr
|
| sym::cfg_attr
|
||||||
|
| sym::cfg_trace
|
||||||
| sym::cfg_attr_trace
|
| sym::cfg_attr_trace
|
||||||
// need to be fixed
|
// need to be fixed
|
||||||
| sym::cfi_encoding // FIXME(cfi_encoding)
|
| sym::cfi_encoding // FIXME(cfi_encoding)
|
||||||
|
@ -574,8 +575,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
// NOTE: when making changes to this list, check that `error_codes/E0736.md` remains accurate
|
// NOTE: when making changes to this list, check that `error_codes/E0736.md` remains accurate
|
||||||
const ALLOW_LIST: &[rustc_span::Symbol] = &[
|
const ALLOW_LIST: &[rustc_span::Symbol] = &[
|
||||||
// conditional compilation
|
// conditional compilation
|
||||||
sym::cfg,
|
sym::cfg_trace,
|
||||||
sym::cfg_attr,
|
|
||||||
sym::cfg_attr_trace,
|
sym::cfg_attr_trace,
|
||||||
// testing (allowed here so better errors can be generated in `rustc_builtin_macros::test`)
|
// testing (allowed here so better errors can be generated in `rustc_builtin_macros::test`)
|
||||||
sym::test,
|
sym::test,
|
||||||
|
@ -2656,7 +2656,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
|
||||||
// only `#[cfg]` and `#[cfg_attr]` are allowed, but it should be removed
|
// only `#[cfg]` and `#[cfg_attr]` are allowed, but it should be removed
|
||||||
// if we allow more attributes (e.g., tool attributes and `allow/deny/warn`)
|
// if we allow more attributes (e.g., tool attributes and `allow/deny/warn`)
|
||||||
// in where clauses. After that, only `self.check_attributes` should be enough.
|
// in where clauses. After that, only `self.check_attributes` should be enough.
|
||||||
const ATTRS_ALLOWED: &[Symbol] = &[sym::cfg, sym::cfg_attr, sym::cfg_attr_trace];
|
const ATTRS_ALLOWED: &[Symbol] = &[sym::cfg_trace, sym::cfg_attr_trace];
|
||||||
let spans = self
|
let spans = self
|
||||||
.tcx
|
.tcx
|
||||||
.hir_attrs(where_predicate.hir_id)
|
.hir_attrs(where_predicate.hir_id)
|
||||||
|
|
|
@ -8,7 +8,7 @@ mod hcx;
|
||||||
mod impls_syntax;
|
mod impls_syntax;
|
||||||
|
|
||||||
pub const IGNORED_ATTRIBUTES: &[Symbol] = &[
|
pub const IGNORED_ATTRIBUTES: &[Symbol] = &[
|
||||||
sym::cfg,
|
sym::cfg_trace, // FIXME should this really be ignored?
|
||||||
sym::rustc_if_this_changed,
|
sym::rustc_if_this_changed,
|
||||||
sym::rustc_then_this_would_need,
|
sym::rustc_then_this_would_need,
|
||||||
sym::rustc_dirty,
|
sym::rustc_dirty,
|
||||||
|
|
|
@ -623,6 +623,7 @@ symbols! {
|
||||||
cfg_target_has_atomic_equal_alignment,
|
cfg_target_has_atomic_equal_alignment,
|
||||||
cfg_target_thread_local,
|
cfg_target_thread_local,
|
||||||
cfg_target_vendor,
|
cfg_target_vendor,
|
||||||
|
cfg_trace: "<cfg>", // must not be a valid identifier
|
||||||
cfg_ub_checks,
|
cfg_ub_checks,
|
||||||
cfg_version,
|
cfg_version,
|
||||||
cfi,
|
cfi,
|
||||||
|
|
|
@ -2773,7 +2773,7 @@ fn add_without_unwanted_attributes<'hir>(
|
||||||
if ident == sym::doc {
|
if ident == sym::doc {
|
||||||
filter_doc_attr(&mut normal.args, is_inline);
|
filter_doc_attr(&mut normal.args, is_inline);
|
||||||
attrs.push((Cow::Owned(attr), import_parent));
|
attrs.push((Cow::Owned(attr), import_parent));
|
||||||
} else if is_inline || ident != sym::cfg {
|
} else if is_inline || ident != sym::cfg_trace {
|
||||||
// If it's not a `cfg()` attribute, we keep it.
|
// If it's not a `cfg()` attribute, we keep it.
|
||||||
attrs.push((Cow::Owned(attr), import_parent));
|
attrs.push((Cow::Owned(attr), import_parent));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1059,7 +1059,7 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute>
|
||||||
// `doc(cfg())` overrides `cfg()`).
|
// `doc(cfg())` overrides `cfg()`).
|
||||||
attrs
|
attrs
|
||||||
.clone()
|
.clone()
|
||||||
.filter(|attr| attr.has_name(sym::cfg))
|
.filter(|attr| attr.has_name(sym::cfg_trace))
|
||||||
.filter_map(|attr| single(attr.meta_item_list()?))
|
.filter_map(|attr| single(attr.meta_item_list()?))
|
||||||
.filter_map(|attr| Cfg::parse_without(attr.meta_item()?, hidden_cfg).ok().flatten())
|
.filter_map(|attr| Cfg::parse_without(attr.meta_item()?, hidden_cfg).ok().flatten())
|
||||||
.fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
|
.fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
|
||||||
|
|
|
@ -37,7 +37,6 @@ fn check_duplicated_attr(
|
||||||
let Some(ident) = attr.ident() else { return };
|
let Some(ident) = attr.ident() else { return };
|
||||||
let name = ident.name;
|
let name = ident.name;
|
||||||
if name == sym::doc
|
if name == sym::doc
|
||||||
|| name == sym::cfg_attr
|
|
||||||
|| name == sym::cfg_attr_trace
|
|| name == sym::cfg_attr_trace
|
||||||
|| name == sym::rustc_on_unimplemented
|
|| name == sym::rustc_on_unimplemented
|
||||||
|| name == sym::reason {
|
|| name == sym::reason {
|
||||||
|
@ -47,7 +46,7 @@ fn check_duplicated_attr(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let Some(direct_parent) = parent.last()
|
if let Some(direct_parent) = parent.last()
|
||||||
&& ["cfg", "cfg_attr"].contains(&direct_parent.as_str())
|
&& direct_parent == sym::cfg_trace.as_str()
|
||||||
&& [sym::all, sym::not, sym::any].contains(&name)
|
&& [sym::all, sym::not, sym::any].contains(&name)
|
||||||
{
|
{
|
||||||
// FIXME: We don't correctly check `cfg`s for now, so if it's more complex than just a one
|
// FIXME: We don't correctly check `cfg`s for now, so if it's more complex than just a one
|
||||||
|
|
|
@ -32,7 +32,7 @@ declare_lint_pass!(CfgNotTest => [CFG_NOT_TEST]);
|
||||||
|
|
||||||
impl EarlyLintPass for CfgNotTest {
|
impl EarlyLintPass for CfgNotTest {
|
||||||
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &rustc_ast::Attribute) {
|
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &rustc_ast::Attribute) {
|
||||||
if attr.has_name(rustc_span::sym::cfg) && contains_not_test(attr.meta_item_list().as_deref(), false) {
|
if attr.has_name(rustc_span::sym::cfg_trace) && contains_not_test(attr.meta_item_list().as_deref(), false) {
|
||||||
span_lint_and_then(
|
span_lint_and_then(
|
||||||
cx,
|
cx,
|
||||||
CFG_NOT_TEST,
|
CFG_NOT_TEST,
|
||||||
|
|
|
@ -41,7 +41,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_
|
||||||
fn is_under_cfg(cx: &LateContext<'_>, id: HirId) -> bool {
|
fn is_under_cfg(cx: &LateContext<'_>, id: HirId) -> bool {
|
||||||
cx.tcx
|
cx.tcx
|
||||||
.hir_parent_id_iter(id)
|
.hir_parent_id_iter(id)
|
||||||
.any(|id| cx.tcx.hir_attrs(id).iter().any(|attr| attr.has_name(sym::cfg)))
|
.any(|id| cx.tcx.hir_attrs(id).iter().any(|attr| attr.has_name(sym::cfg_trace)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Similar to [`clippy_utils::expr_or_init`], but does not go up the chain if the initialization
|
/// Similar to [`clippy_utils::expr_or_init`], but does not go up the chain if the initialization
|
||||||
|
|
|
@ -2629,7 +2629,7 @@ pub fn peel_ref_operators<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>
|
||||||
pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
|
pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
|
||||||
if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
|
if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
|
||||||
if let Res::Def(_, def_id) = path.res {
|
if let Res::Def(_, def_id) = path.res {
|
||||||
return cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr);
|
return cx.tcx.has_attr(def_id, sym::cfg_trace) || cx.tcx.has_attr(def_id, sym::cfg_attr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
|
@ -2699,7 +2699,7 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool {
|
||||||
/// use [`is_in_cfg_test`]
|
/// use [`is_in_cfg_test`]
|
||||||
pub fn is_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool {
|
pub fn is_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool {
|
||||||
tcx.hir_attrs(id).iter().any(|attr| {
|
tcx.hir_attrs(id).iter().any(|attr| {
|
||||||
if attr.has_name(sym::cfg)
|
if attr.has_name(sym::cfg_trace)
|
||||||
&& let Some(items) = attr.meta_item_list()
|
&& let Some(items) = attr.meta_item_list()
|
||||||
&& let [item] = &*items
|
&& let [item] = &*items
|
||||||
&& item.has_name(sym::test)
|
&& item.has_name(sym::test)
|
||||||
|
@ -2723,11 +2723,11 @@ pub fn is_in_test(tcx: TyCtxt<'_>, hir_id: HirId) -> bool {
|
||||||
|
|
||||||
/// Checks if the item of any of its parents has `#[cfg(...)]` attribute applied.
|
/// Checks if the item of any of its parents has `#[cfg(...)]` attribute applied.
|
||||||
pub fn inherits_cfg(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
pub fn inherits_cfg(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
||||||
tcx.has_attr(def_id, sym::cfg)
|
tcx.has_attr(def_id, sym::cfg_trace)
|
||||||
|| tcx
|
|| tcx
|
||||||
.hir_parent_iter(tcx.local_def_id_to_hir_id(def_id))
|
.hir_parent_iter(tcx.local_def_id_to_hir_id(def_id))
|
||||||
.flat_map(|(parent_id, _)| tcx.hir_attrs(parent_id))
|
.flat_map(|(parent_id, _)| tcx.hir_attrs(parent_id))
|
||||||
.any(|attr| attr.has_name(sym::cfg))
|
.any(|attr| attr.has_name(sym::cfg_trace))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Walks up the HIR tree from the given expression in an attempt to find where the value is
|
/// Walks up the HIR tree from the given expression in an attempt to find where the value is
|
||||||
|
|
|
@ -10,7 +10,6 @@ extern crate std;
|
||||||
//@ pp-exact:tests-are-sorted.pp
|
//@ pp-exact:tests-are-sorted.pp
|
||||||
|
|
||||||
extern crate test;
|
extern crate test;
|
||||||
#[cfg(test)]
|
|
||||||
#[rustc_test_marker = "m_test"]
|
#[rustc_test_marker = "m_test"]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub const m_test: test::TestDescAndFn =
|
pub const m_test: test::TestDescAndFn =
|
||||||
|
@ -35,7 +34,6 @@ pub const m_test: test::TestDescAndFn =
|
||||||
fn m_test() {}
|
fn m_test() {}
|
||||||
|
|
||||||
extern crate test;
|
extern crate test;
|
||||||
#[cfg(test)]
|
|
||||||
#[rustc_test_marker = "z_test"]
|
#[rustc_test_marker = "z_test"]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub const z_test: test::TestDescAndFn =
|
pub const z_test: test::TestDescAndFn =
|
||||||
|
@ -61,7 +59,6 @@ pub const z_test: test::TestDescAndFn =
|
||||||
fn z_test() {}
|
fn z_test() {}
|
||||||
|
|
||||||
extern crate test;
|
extern crate test;
|
||||||
#[cfg(test)]
|
|
||||||
#[rustc_test_marker = "a_test"]
|
#[rustc_test_marker = "a_test"]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub const a_test: test::TestDescAndFn =
|
pub const a_test: test::TestDescAndFn =
|
||||||
|
|
|
@ -29,7 +29,6 @@ macro_rules! generate_s10 {
|
||||||
($expr: expr) => {
|
($expr: expr) => {
|
||||||
#[cfg(feature = $expr)]
|
#[cfg(feature = $expr)]
|
||||||
//~^ ERROR expected unsuffixed literal, found expression `concat!("nonexistent")`
|
//~^ ERROR expected unsuffixed literal, found expression `concat!("nonexistent")`
|
||||||
//~| ERROR expected unsuffixed literal, found expression `concat!("nonexistent")`
|
|
||||||
struct S10;
|
struct S10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,19 +65,7 @@ LL | generate_s10!(concat!("nonexistent"));
|
||||||
|
|
|
|
||||||
= note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: expected unsuffixed literal, found expression `concat!("nonexistent")`
|
error: aborting due to 10 previous errors
|
||||||
--> $DIR/cfg-attr-syntax-validation.rs:30:25
|
|
||||||
|
|
|
||||||
LL | #[cfg(feature = $expr)]
|
|
||||||
| ^^^^^
|
|
||||||
...
|
|
||||||
LL | generate_s10!(concat!("nonexistent"));
|
|
||||||
| ------------------------------------- in this macro invocation
|
|
||||||
|
|
|
||||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
|
||||||
= note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error: aborting due to 11 previous errors
|
|
||||||
|
|
||||||
Some errors have detailed explanations: E0537, E0565.
|
Some errors have detailed explanations: E0537, E0565.
|
||||||
For more information about an error, try `rustc --explain E0537`.
|
For more information about an error, try `rustc --explain E0537`.
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
// This was triggering an assertion failure in `NodeRange::new`.
|
// This was triggering an assertion failure in `NodeRange::new`.
|
||||||
|
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
#![feature(cfg_eval)]
|
#![feature(cfg_eval)]
|
||||||
#![feature(stmt_expr_attributes)]
|
#![feature(stmt_expr_attributes)]
|
||||||
|
|
||||||
fn f() -> u32 {
|
fn f() -> u32 {
|
||||||
#[cfg_eval] #[cfg(not(FALSE))] 0
|
#[cfg_eval] #[cfg(not(FALSE))] 0
|
||||||
//~^ ERROR removing an expression is not supported in this position
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
error: removing an expression is not supported in this position
|
|
||||||
--> $DIR/invalid-node-range-issue-129166.rs:7:17
|
|
||||||
|
|
|
||||||
LL | #[cfg_eval] #[cfg(not(FALSE))] 0
|
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ macro_rules! mac {
|
||||||
($attr_item: meta) => {
|
($attr_item: meta) => {
|
||||||
#[cfg($attr_item)]
|
#[cfg($attr_item)]
|
||||||
//~^ ERROR expected unsuffixed literal, found `meta` metavariable
|
//~^ ERROR expected unsuffixed literal, found `meta` metavariable
|
||||||
//~| ERROR expected unsuffixed literal, found `meta` metavariable
|
|
||||||
struct S;
|
struct S;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +10,6 @@ mac!(an(arbitrary token stream));
|
||||||
|
|
||||||
#[cfg(feature = -1)]
|
#[cfg(feature = -1)]
|
||||||
//~^ ERROR expected unsuffixed literal, found `-`
|
//~^ ERROR expected unsuffixed literal, found `-`
|
||||||
//~| ERROR expected unsuffixed literal, found `-`
|
|
||||||
fn handler() {}
|
fn handler() {}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: expected unsuffixed literal, found `-`
|
error: expected unsuffixed literal, found `-`
|
||||||
--> $DIR/attr-bad-meta-4.rs:12:17
|
--> $DIR/attr-bad-meta-4.rs:11:17
|
||||||
|
|
|
|
||||||
LL | #[cfg(feature = -1)]
|
LL | #[cfg(feature = -1)]
|
||||||
| ^
|
| ^
|
||||||
|
@ -15,25 +15,5 @@ LL | mac!(an(arbitrary token stream));
|
||||||
|
|
|
|
||||||
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: expected unsuffixed literal, found `meta` metavariable
|
error: aborting due to 2 previous errors
|
||||||
--> $DIR/attr-bad-meta-4.rs:3:15
|
|
||||||
|
|
|
||||||
LL | #[cfg($attr_item)]
|
|
||||||
| ^^^^^^^^^^
|
|
||||||
...
|
|
||||||
LL | mac!(an(arbitrary token stream));
|
|
||||||
| -------------------------------- in this macro invocation
|
|
||||||
|
|
|
||||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
|
||||||
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error: expected unsuffixed literal, found `-`
|
|
||||||
--> $DIR/attr-bad-meta-4.rs:12:17
|
|
||||||
|
|
|
||||||
LL | #[cfg(feature = -1)]
|
|
||||||
| ^
|
|
||||||
|
|
|
||||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
//@ check-pass
|
//@ check-pass
|
||||||
//@ proc-macro: test-macros.rs
|
//@ proc-macro: test-macros.rs
|
||||||
|
|
||||||
|
#![feature(cfg_boolean_literals)]
|
||||||
#![feature(cfg_eval)]
|
#![feature(cfg_eval)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -10,8 +11,13 @@ extern crate test_macros;
|
||||||
|
|
||||||
#[cfg_eval]
|
#[cfg_eval]
|
||||||
#[test_macros::print_attr]
|
#[test_macros::print_attr]
|
||||||
#[cfg_attr(FALSE, test_macros::print_attr)]
|
#[cfg_attr(false, test_macros::print_attr)]
|
||||||
#[cfg_attr(all(), test_macros::print_attr)]
|
#[cfg_attr(true, test_macros::print_attr)]
|
||||||
struct S;
|
struct S;
|
||||||
|
|
||||||
|
#[cfg_eval]
|
||||||
|
#[test_macros::print_attr]
|
||||||
|
#[cfg(true)]
|
||||||
|
struct Z;
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -4,59 +4,75 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
|
||||||
Punct {
|
Punct {
|
||||||
ch: '#',
|
ch: '#',
|
||||||
spacing: Alone,
|
spacing: Alone,
|
||||||
span: #0 bytes(271..272),
|
span: #0 bytes(305..306),
|
||||||
},
|
},
|
||||||
Group {
|
Group {
|
||||||
delimiter: Bracket,
|
delimiter: Bracket,
|
||||||
stream: TokenStream [
|
stream: TokenStream [
|
||||||
Ident {
|
Ident {
|
||||||
ident: "test_macros",
|
ident: "test_macros",
|
||||||
span: #0 bytes(289..300),
|
span: #0 bytes(322..333),
|
||||||
},
|
},
|
||||||
Punct {
|
Punct {
|
||||||
ch: ':',
|
ch: ':',
|
||||||
spacing: Joint,
|
spacing: Joint,
|
||||||
span: #0 bytes(300..301),
|
span: #0 bytes(333..334),
|
||||||
},
|
},
|
||||||
Punct {
|
Punct {
|
||||||
ch: ':',
|
ch: ':',
|
||||||
spacing: Alone,
|
spacing: Alone,
|
||||||
span: #0 bytes(301..302),
|
span: #0 bytes(334..335),
|
||||||
},
|
},
|
||||||
Ident {
|
Ident {
|
||||||
ident: "print_attr",
|
ident: "print_attr",
|
||||||
span: #0 bytes(302..312),
|
span: #0 bytes(335..345),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
span: #0 bytes(272..314),
|
span: #0 bytes(306..347),
|
||||||
},
|
},
|
||||||
Ident {
|
Ident {
|
||||||
ident: "struct",
|
ident: "struct",
|
||||||
span: #0 bytes(315..321),
|
span: #0 bytes(348..354),
|
||||||
},
|
},
|
||||||
Ident {
|
Ident {
|
||||||
ident: "S",
|
ident: "S",
|
||||||
span: #0 bytes(322..323),
|
span: #0 bytes(355..356),
|
||||||
},
|
},
|
||||||
Punct {
|
Punct {
|
||||||
ch: ';',
|
ch: ';',
|
||||||
spacing: Alone,
|
spacing: Alone,
|
||||||
span: #0 bytes(323..324),
|
span: #0 bytes(356..357),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
PRINT-ATTR INPUT (DISPLAY): struct S;
|
PRINT-ATTR INPUT (DISPLAY): struct S;
|
||||||
PRINT-ATTR INPUT (DEBUG): TokenStream [
|
PRINT-ATTR INPUT (DEBUG): TokenStream [
|
||||||
Ident {
|
Ident {
|
||||||
ident: "struct",
|
ident: "struct",
|
||||||
span: #0 bytes(315..321),
|
span: #0 bytes(348..354),
|
||||||
},
|
},
|
||||||
Ident {
|
Ident {
|
||||||
ident: "S",
|
ident: "S",
|
||||||
span: #0 bytes(322..323),
|
span: #0 bytes(355..356),
|
||||||
},
|
},
|
||||||
Punct {
|
Punct {
|
||||||
ch: ';',
|
ch: ';',
|
||||||
spacing: Alone,
|
spacing: Alone,
|
||||||
span: #0 bytes(323..324),
|
span: #0 bytes(356..357),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
PRINT-ATTR INPUT (DISPLAY): struct Z;
|
||||||
|
PRINT-ATTR INPUT (DEBUG): TokenStream [
|
||||||
|
Ident {
|
||||||
|
ident: "struct",
|
||||||
|
span: #0 bytes(411..417),
|
||||||
|
},
|
||||||
|
Ident {
|
||||||
|
ident: "Z",
|
||||||
|
span: #0 bytes(418..419),
|
||||||
|
},
|
||||||
|
Punct {
|
||||||
|
ch: ';',
|
||||||
|
spacing: Alone,
|
||||||
|
span: #0 bytes(419..420),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue