1 //! Parsing and validation of builtin attributes
3 use rustc_ast
::{self as ast, Attribute, Lit, LitKind, MetaItem, MetaItemKind, NestedMetaItem}
;
4 use rustc_ast_pretty
::pprust
;
5 use rustc_errors
::{struct_span_err, Applicability}
;
6 use rustc_feature
::{find_gated_cfg, is_builtin_attr_name, Features, GatedCfg}
;
7 use rustc_macros
::HashStable_Generic
;
8 use rustc_session
::parse
::{feature_err, ParseSess}
;
9 use rustc_session
::Session
;
10 use rustc_span
::hygiene
::Transparency
;
11 use rustc_span
::{symbol::sym, symbol::Symbol, Span}
;
12 use std
::num
::NonZeroU32
;
14 pub fn is_builtin_attr(attr
: &Attribute
) -> bool
{
15 attr
.is_doc_comment() || attr
.ident().filter(|ident
| is_builtin_attr_name(ident
.name
)).is_some()
20 UnknownMetaItem(String
, &'
static [&'
static str]),
24 MultipleStabilityLevels
,
25 UnsupportedLiteral(&'
static str, /* is_bytestr */ bool
),
28 fn handle_errors(sess
: &ParseSess
, span
: Span
, error
: AttrError
) {
29 let diag
= &sess
.span_diagnostic
;
31 AttrError
::MultipleItem(item
) => {
32 struct_span_err
!(diag
, span
, E0538
, "multiple '{}' items", item
).emit();
34 AttrError
::UnknownMetaItem(item
, expected
) => {
35 let expected
= expected
.iter().map(|name
| format
!("`{}`", name
)).collect
::<Vec
<_
>>();
36 struct_span_err
!(diag
, span
, E0541
, "unknown meta item '{}'", item
)
37 .span_label(span
, format
!("expected one of {}", expected
.join(", ")))
40 AttrError
::MissingSince
=> {
41 struct_span_err
!(diag
, span
, E0542
, "missing 'since'").emit();
43 AttrError
::NonIdentFeature
=> {
44 struct_span_err
!(diag
, span
, E0546
, "'feature' is not an identifier").emit();
46 AttrError
::MissingFeature
=> {
47 struct_span_err
!(diag
, span
, E0546
, "missing 'feature'").emit();
49 AttrError
::MultipleStabilityLevels
=> {
50 struct_span_err
!(diag
, span
, E0544
, "multiple stability levels").emit();
52 AttrError
::UnsupportedLiteral(msg
, is_bytestr
) => {
53 let mut err
= struct_span_err
!(diag
, span
, E0565
, "{}", msg
);
55 if let Ok(lint_str
) = sess
.source_map().span_to_snippet(span
) {
58 "consider removing the prefix",
59 lint_str
[1..].to_string(),
60 Applicability
::MaybeIncorrect
,
69 #[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug)]
77 #[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
78 pub enum InstructionSetAttr
{
83 #[derive(Clone, Encodable, Decodable, Debug)]
84 pub enum OptimizeAttr
{
90 #[derive(Copy, Clone, PartialEq)]
96 /// Determine what `#[unwind]` attribute is present in `attrs`, if any.
97 pub fn find_unwind_attr(sess
: &Session
, attrs
: &[Attribute
]) -> Option
<UnwindAttr
> {
98 attrs
.iter().fold(None
, |ia
, attr
| {
99 if sess
.check_name(attr
, sym
::unwind
) {
100 if let Some(meta
) = attr
.meta() {
101 if let MetaItemKind
::List(items
) = meta
.kind
{
102 if items
.len() == 1 {
103 if items
[0].has_name(sym
::allowed
) {
104 return Some(UnwindAttr
::Allowed
);
105 } else if items
[0].has_name(sym
::aborts
) {
106 return Some(UnwindAttr
::Aborts
);
114 "malformed `unwind` attribute input"
116 .span_label(attr
.span
, "invalid argument")
119 "the allowed arguments are `allowed` and `aborts`",
120 (vec
!["allowed", "aborts"])
122 .map(|s
| format
!("#[unwind({})]", s
)),
123 Applicability
::MachineApplicable
,
134 /// Represents the following attributes:
138 #[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
139 #[derive(HashStable_Generic)]
140 pub struct Stability
{
141 pub level
: StabilityLevel
,
145 /// Represents the `#[rustc_const_unstable]` and `#[rustc_const_stable]` attributes.
146 #[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
147 #[derive(HashStable_Generic)]
148 pub struct ConstStability
{
149 pub level
: StabilityLevel
,
151 /// whether the function has a `#[rustc_promotable]` attribute
152 pub promotable
: bool
,
155 /// The available stability levels.
156 #[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
157 #[derive(HashStable_Generic)]
158 pub enum StabilityLevel
{
159 // Reason for the current stability level and the relevant rust-lang issue
160 Unstable { reason: Option<Symbol>, issue: Option<NonZeroU32>, is_soft: bool }
,
161 Stable { since: Symbol }
,
164 impl StabilityLevel
{
165 pub fn is_unstable(&self) -> bool
{
166 matches
!(self, StabilityLevel
::Unstable { .. }
)
168 pub fn is_stable(&self) -> bool
{
169 matches
!(self, StabilityLevel
::Stable { .. }
)
173 /// Collects stability info from all stability attributes in `attrs`.
174 /// Returns `None` if no stability attributes are found.
175 pub fn find_stability(
179 ) -> (Option
<(Stability
, Span
)>, Option
<(ConstStability
, Span
)>) {
180 find_stability_generic(sess
, attrs
.iter(), item_sp
)
183 fn find_stability_generic
<'a
, I
>(
187 ) -> (Option
<(Stability
, Span
)>, Option
<(ConstStability
, Span
)>)
189 I
: Iterator
<Item
= &'a Attribute
>,
191 use StabilityLevel
::*;
193 let mut stab
: Option
<(Stability
, Span
)> = None
;
194 let mut const_stab
: Option
<(ConstStability
, Span
)> = None
;
195 let mut promotable
= false;
197 let diagnostic
= &sess
.parse_sess
.span_diagnostic
;
199 'outer
: for attr
in attrs_iter
{
201 sym
::rustc_const_unstable
,
202 sym
::rustc_const_stable
,
205 sym
::rustc_promotable
,
208 .any(|&s
| attr
.has_name(s
))
210 continue; // not a stability level
213 sess
.mark_attr_used(attr
);
215 let meta
= attr
.meta();
217 if attr
.has_name(sym
::rustc_promotable
) {
220 // attributes with data
221 else if let Some(MetaItem { kind: MetaItemKind::List(ref metas), .. }
) = meta
{
222 let meta
= meta
.as_ref().unwrap();
223 let get
= |meta
: &MetaItem
, item
: &mut Option
<Symbol
>| {
228 AttrError
::MultipleItem(pprust
::path_to_string(&meta
.path
)),
232 if let Some(v
) = meta
.value_str() {
236 struct_span_err
!(diagnostic
, meta
.span
, E0539
, "incorrect meta item").emit();
241 let meta_name
= meta
.name_or_empty();
243 sym
::rustc_const_unstable
| sym
::unstable
=> {
244 if meta_name
== sym
::unstable
&& stab
.is_some() {
248 AttrError
::MultipleStabilityLevels
,
251 } else if meta_name
== sym
::rustc_const_unstable
&& const_stab
.is_some() {
255 AttrError
::MultipleStabilityLevels
,
260 let mut feature
= None
;
261 let mut reason
= None
;
262 let mut issue
= None
;
263 let mut issue_num
= None
;
264 let mut is_soft
= false;
266 if let Some(mi
) = meta
.meta_item() {
267 match mi
.name_or_empty() {
269 if !get(mi
, &mut feature
) {
274 if !get(mi
, &mut reason
) {
279 if !get(mi
, &mut issue
) {
283 // These unwraps are safe because `get` ensures the meta item
284 // is a name/value pair string literal.
285 issue_num
= match &*issue
.unwrap().as_str() {
288 let emit_diag
= |msg
: &str| {
293 "`issue` must be a non-zero numeric string \
297 mi
.name_value_literal_span().unwrap(),
302 match issue
.parse() {
305 "`issue` must not be \"0\", \
306 use \"none\" instead",
310 Ok(num
) => NonZeroU32
::new(num
),
312 emit_diag(&err
.to_string());
321 let msg
= "`soft` should not have any arguments";
322 sess
.parse_sess
.span_diagnostic
.span_err(mi
.span
, msg
);
330 AttrError
::UnknownMetaItem(
331 pprust
::path_to_string(&mi
.path
),
332 &["feature", "reason", "issue", "soft"],
342 AttrError
::UnsupportedLiteral("unsupported literal", false),
348 match (feature
, reason
, issue
) {
349 (Some(feature
), reason
, Some(_
)) => {
350 if !rustc_lexer
::is_ident(&feature
.as_str()) {
354 AttrError
::NonIdentFeature
,
358 let level
= Unstable { reason, issue: issue_num, is_soft }
;
359 if sym
::unstable
== meta_name
{
360 stab
= Some((Stability { level, feature }
, attr
.span
));
363 ConstStability { level, feature, promotable: false }
,
369 handle_errors(&sess
.parse_sess
, attr
.span
, AttrError
::MissingFeature
);
373 struct_span_err
!(diagnostic
, attr
.span
, E0547
, "missing 'issue'")
379 sym
::rustc_const_stable
| sym
::stable
=> {
380 if meta_name
== sym
::stable
&& stab
.is_some() {
384 AttrError
::MultipleStabilityLevels
,
387 } else if meta_name
== sym
::rustc_const_stable
&& const_stab
.is_some() {
391 AttrError
::MultipleStabilityLevels
,
396 let mut feature
= None
;
397 let mut since
= None
;
400 NestedMetaItem
::MetaItem(mi
) => match mi
.name_or_empty() {
402 if !get(mi
, &mut feature
) {
407 if !get(mi
, &mut since
) {
415 AttrError
::UnknownMetaItem(
416 pprust
::path_to_string(&mi
.path
),
423 NestedMetaItem
::Literal(lit
) => {
427 AttrError
::UnsupportedLiteral("unsupported literal", false),
434 match (feature
, since
) {
435 (Some(feature
), Some(since
)) => {
436 let level
= Stable { since }
;
437 if sym
::stable
== meta_name
{
438 stab
= Some((Stability { level, feature }
, attr
.span
));
441 ConstStability { level, feature, promotable: false }
,
447 handle_errors(&sess
.parse_sess
, attr
.span
, AttrError
::MissingFeature
);
451 handle_errors(&sess
.parse_sess
, attr
.span
, AttrError
::MissingSince
);
461 // Merge the const-unstable info into the stability info
463 if let Some((ref mut stab
, _
)) = const_stab
{
464 stab
.promotable
= promotable
;
470 "`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` \
471 or a `rustc_const_stable` attribute"
480 pub fn find_crate_name(sess
: &Session
, attrs
: &[Attribute
]) -> Option
<Symbol
> {
481 sess
.first_attr_value_str_by_name(attrs
, sym
::crate_name
)
484 /// Tests if a cfg-pattern matches the cfg set
485 pub fn cfg_matches(cfg
: &ast
::MetaItem
, sess
: &ParseSess
, features
: Option
<&Features
>) -> bool
{
486 eval_condition(cfg
, sess
, features
, &mut |cfg
| {
487 try_gate_cfg(cfg
, sess
, features
);
488 let error
= |span
, msg
| {
489 sess
.span_diagnostic
.span_err(span
, msg
);
492 if cfg
.path
.segments
.len() != 1 {
493 return error(cfg
.path
.span
, "`cfg` predicate key must be an identifier");
496 MetaItemKind
::List(..) => {
497 error(cfg
.span
, "unexpected parentheses after `cfg` predicate key")
499 MetaItemKind
::NameValue(lit
) if !lit
.kind
.is_str() => {
503 AttrError
::UnsupportedLiteral(
504 "literal in `cfg` predicate value must be a string",
505 lit
.kind
.is_bytestr(),
510 MetaItemKind
::NameValue(..) | MetaItemKind
::Word
=> {
511 let ident
= cfg
.ident().expect("multi-segment cfg predicate");
512 sess
.config
.contains(&(ident
.name
, cfg
.value_str()))
518 fn try_gate_cfg(cfg
: &ast
::MetaItem
, sess
: &ParseSess
, features
: Option
<&Features
>) {
519 let gate
= find_gated_cfg(|sym
| cfg
.has_name(sym
));
520 if let (Some(feats
), Some(gated_cfg
)) = (features
, gate
) {
521 gate_cfg(&gated_cfg
, cfg
.span
, sess
, feats
);
525 fn gate_cfg(gated_cfg
: &GatedCfg
, cfg_span
: Span
, sess
: &ParseSess
, features
: &Features
) {
526 let (cfg
, feature
, has_feature
) = gated_cfg
;
527 if !has_feature(features
) && !cfg_span
.allows_unstable(*feature
) {
528 let explain
= format
!("`cfg({})` is experimental and subject to change", cfg
);
529 feature_err(sess
, *feature
, cfg_span
, &explain
).emit();
533 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
540 fn parse_version(s
: &str, allow_appendix
: bool
) -> Option
<Version
> {
541 let mut components
= s
.split('
-'
);
542 let d
= components
.next()?
;
543 if !allow_appendix
&& components
.next().is_some() {
546 let mut digits
= d
.splitn(3, '
.'
);
547 let major
= digits
.next()?
.parse().ok()?
;
548 let minor
= digits
.next()?
.parse().ok()?
;
549 let patch
= digits
.next().unwrap_or("0").parse().ok()?
;
550 Some(Version { major, minor, patch }
)
553 /// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to
554 /// evaluate individual items.
555 pub fn eval_condition(
558 features
: Option
<&Features
>,
559 eval
: &mut impl FnMut(&ast
::MetaItem
) -> bool
,
562 ast
::MetaItemKind
::List(ref mis
) if cfg
.name_or_empty() == sym
::version
=> {
563 try_gate_cfg(cfg
, sess
, features
);
564 let (min_version
, span
) = match &mis
[..] {
565 [NestedMetaItem
::Literal(Lit { kind: LitKind::Str(sym, ..), span, .. }
)] => {
568 [NestedMetaItem
::Literal(Lit { span, .. }
)
569 | NestedMetaItem
::MetaItem(MetaItem { span, .. }
)] => {
571 .struct_span_err(*span
, "expected a version literal")
577 .struct_span_err(cfg
.span
, "expected single version literal")
582 let min_version
= match parse_version(&min_version
.as_str(), false) {
588 "unknown version literal format, assuming it refers to a future version",
594 let rustc_version
= parse_version(env
!("CFG_RELEASE"), true).unwrap();
596 // See https://github.com/rust-lang/rust/issues/64796#issuecomment-640851454 for details
597 if sess
.assume_incomplete_release
{
598 rustc_version
> min_version
600 rustc_version
>= min_version
603 ast
::MetaItemKind
::List(ref mis
) => {
604 for mi
in mis
.iter() {
605 if !mi
.is_meta_item() {
609 AttrError
::UnsupportedLiteral("unsupported literal", false),
615 // The unwraps below may look dangerous, but we've already asserted
616 // that they won't fail with the loop above.
617 match cfg
.name_or_empty() {
620 .any(|mi
| eval_condition(mi
.meta_item().unwrap(), sess
, features
, eval
)),
623 .all(|mi
| eval_condition(mi
.meta_item().unwrap(), sess
, features
, eval
)),
627 sess
.span_diagnostic
,
630 "expected 1 cfg-pattern"
636 !eval_condition(mis
[0].meta_item().unwrap(), sess
, features
, eval
)
640 sess
.span_diagnostic
,
643 "invalid predicate `{}`",
644 pprust
::path_to_string(&cfg
.path
)
651 ast
::MetaItemKind
::Word
| ast
::MetaItemKind
::NameValue(..) => eval(cfg
),
655 #[derive(Debug, Encodable, Decodable, Clone, HashStable_Generic)]
656 pub struct Deprecation
{
657 pub since
: Option
<Symbol
>,
658 /// The note to issue a reason.
659 pub note
: Option
<Symbol
>,
660 /// A text snippet used to completely replace any use of the deprecated item in an expression.
662 /// This is currently unstable.
663 pub suggestion
: Option
<Symbol
>,
665 /// Whether to treat the since attribute as being a Rust version identifier
666 /// (rather than an opaque string).
667 pub is_since_rustc_version
: bool
,
670 /// Finds the deprecation attribute. `None` if none exists.
671 pub fn find_deprecation(sess
: &Session
, attrs
: &[Attribute
]) -> Option
<(Deprecation
, Span
)> {
672 find_deprecation_generic(sess
, attrs
.iter())
675 fn find_deprecation_generic
<'a
, I
>(sess
: &Session
, attrs_iter
: I
) -> Option
<(Deprecation
, Span
)>
677 I
: Iterator
<Item
= &'a Attribute
>,
679 let mut depr
: Option
<(Deprecation
, Span
)> = None
;
680 let diagnostic
= &sess
.parse_sess
.span_diagnostic
;
682 'outer
: for attr
in attrs_iter
{
683 if !(sess
.check_name(attr
, sym
::deprecated
) || sess
.check_name(attr
, sym
::rustc_deprecated
))
688 if let Some((_
, span
)) = &depr
{
689 struct_span_err
!(diagnostic
, attr
.span
, E0550
, "multiple deprecated attributes")
690 .span_label(attr
.span
, "repeated deprecation attribute")
691 .span_label(*span
, "first deprecation attribute")
696 let meta
= match attr
.meta() {
700 let mut since
= None
;
702 let mut suggestion
= None
;
704 MetaItemKind
::Word
=> {}
705 MetaItemKind
::NameValue(..) => note
= meta
.value_str(),
706 MetaItemKind
::List(list
) => {
707 let get
= |meta
: &MetaItem
, item
: &mut Option
<Symbol
>| {
712 AttrError
::MultipleItem(pprust
::path_to_string(&meta
.path
)),
716 if let Some(v
) = meta
.value_str() {
720 if let Some(lit
) = meta
.name_value_literal() {
724 AttrError
::UnsupportedLiteral(
725 "literal in `deprecated` \
726 value must be a string",
727 lit
.kind
.is_bytestr(),
731 struct_span_err
!(diagnostic
, meta
.span
, E0551
, "incorrect meta item")
741 NestedMetaItem
::MetaItem(mi
) => match mi
.name_or_empty() {
743 if !get(mi
, &mut since
) {
747 sym
::note
if sess
.check_name(attr
, sym
::deprecated
) => {
748 if !get(mi
, &mut note
) {
752 sym
::reason
if sess
.check_name(attr
, sym
::rustc_deprecated
) => {
753 if !get(mi
, &mut note
) {
757 sym
::suggestion
if sess
.check_name(attr
, sym
::rustc_deprecated
) => {
758 if !get(mi
, &mut suggestion
) {
766 AttrError
::UnknownMetaItem(
767 pprust
::path_to_string(&mi
.path
),
768 if sess
.check_name(attr
, sym
::deprecated
) {
771 &["since", "reason", "suggestion"]
778 NestedMetaItem
::Literal(lit
) => {
782 AttrError
::UnsupportedLiteral(
783 "item in `deprecated` must be a key/value pair",
794 if suggestion
.is_some() && sess
.check_name(attr
, sym
::deprecated
) {
795 unreachable
!("only allowed on rustc_deprecated")
798 if sess
.check_name(attr
, sym
::rustc_deprecated
) {
800 handle_errors(&sess
.parse_sess
, attr
.span
, AttrError
::MissingSince
);
805 struct_span_err
!(diagnostic
, attr
.span
, E0543
, "missing 'reason'").emit();
810 sess
.mark_attr_used(&attr
);
812 let is_since_rustc_version
= sess
.check_name(attr
, sym
::rustc_deprecated
);
813 depr
= Some((Deprecation { since, note, suggestion, is_since_rustc_version }
, attr
.span
));
819 #[derive(PartialEq, Debug, Encodable, Decodable, Copy, Clone)]
830 #[derive(Eq, PartialEq, Debug, Copy, Clone)]
831 #[derive(Encodable, Decodable, HashStable_Generic)]
833 SignedInt(ast
::IntTy
),
834 UnsignedInt(ast
::UintTy
),
839 pub fn is_signed(self) -> bool
{
843 SignedInt(..) => true,
844 UnsignedInt(..) => false,
849 /// Parse #[repr(...)] forms.
851 /// Valid repr contents: any of the primitive integral type names (see
852 /// `int_type_of_word`, below) to specify enum discriminant type; `C`, to use
853 /// the same discriminant size that the corresponding C enum would or C
854 /// structure layout, `packed` to remove padding, and `transparent` to elegate representation
855 /// concerns to the only non-ZST field.
856 pub fn find_repr_attrs(sess
: &Session
, attr
: &Attribute
) -> Vec
<ReprAttr
> {
859 let mut acc
= Vec
::new();
860 let diagnostic
= &sess
.parse_sess
.span_diagnostic
;
861 if attr
.has_name(sym
::repr
) {
862 if let Some(items
) = attr
.meta_item_list() {
863 sess
.mark_attr_used(attr
);
865 if !item
.is_meta_item() {
869 AttrError
::UnsupportedLiteral(
870 "meta item in `repr` must be an identifier",
877 let mut recognised
= false;
879 let hint
= match item
.name_or_empty() {
880 sym
::C
=> Some(ReprC
),
881 sym
::packed
=> Some(ReprPacked(1)),
882 sym
::simd
=> Some(ReprSimd
),
883 sym
::transparent
=> Some(ReprTransparent
),
884 sym
::no_niche
=> Some(ReprNoNiche
),
885 name
=> int_type_of_word(name
).map(ReprInt
),
888 if let Some(h
) = hint
{
892 } else if let Some((name
, value
)) = item
.name_value_literal() {
893 let parse_alignment
= |node
: &ast
::LitKind
| -> Result
<u32, &'
static str> {
894 if let ast
::LitKind
::Int(literal
, ast
::LitIntType
::Unsuffixed
) = node
{
895 if literal
.is_power_of_two() {
896 // rustc_middle::ty::layout::Align restricts align to <= 2^29
897 if *literal
<= 1 << 29 {
900 Err("larger than 2^29")
903 Err("not a power of two")
906 Err("not an unsuffixed integer")
910 let mut literal_error
= None
;
911 if name
== sym
::align
{
913 match parse_alignment(&value
.kind
) {
914 Ok(literal
) => acc
.push(ReprAlign(literal
)),
915 Err(message
) => literal_error
= Some(message
),
917 } else if name
== sym
::packed
{
919 match parse_alignment(&value
.kind
) {
920 Ok(literal
) => acc
.push(ReprPacked(literal
)),
921 Err(message
) => literal_error
= Some(message
),
924 if let Some(literal_error
) = literal_error
{
929 "invalid `repr(align)` attribute: {}",
934 } else if let Some(meta_item
) = item
.meta_item() {
935 if meta_item
.has_name(sym
::align
) {
936 if let MetaItemKind
::NameValue(ref value
) = meta_item
.kind
{
938 let mut err
= struct_span_err
!(
942 "incorrect `repr(align)` attribute format"
945 ast
::LitKind
::Int(int
, ast
::LitIntType
::Unsuffixed
) => {
948 "use parentheses instead",
949 format
!("align({})", int
),
950 Applicability
::MachineApplicable
,
953 ast
::LitKind
::Str(s
, _
) => {
956 "use parentheses instead",
957 format
!("align({})", s
),
958 Applicability
::MachineApplicable
,
968 // Not a word we recognize
973 "unrecognized representation hint"
983 fn int_type_of_word(s
: Symbol
) -> Option
<IntType
> {
987 sym
::i8 => Some(SignedInt(ast
::IntTy
::I8
)),
988 sym
::u8 => Some(UnsignedInt(ast
::UintTy
::U8
)),
989 sym
::i16 => Some(SignedInt(ast
::IntTy
::I16
)),
990 sym
::u16 => Some(UnsignedInt(ast
::UintTy
::U16
)),
991 sym
::i32 => Some(SignedInt(ast
::IntTy
::I32
)),
992 sym
::u32 => Some(UnsignedInt(ast
::UintTy
::U32
)),
993 sym
::i64 => Some(SignedInt(ast
::IntTy
::I64
)),
994 sym
::u64 => Some(UnsignedInt(ast
::UintTy
::U64
)),
995 sym
::i128
=> Some(SignedInt(ast
::IntTy
::I128
)),
996 sym
::u128
=> Some(UnsignedInt(ast
::UintTy
::U128
)),
997 sym
::isize => Some(SignedInt(ast
::IntTy
::Isize
)),
998 sym
::usize => Some(UnsignedInt(ast
::UintTy
::Usize
)),
1003 pub enum TransparencyError
{
1004 UnknownTransparency(Symbol
, Span
),
1005 MultipleTransparencyAttrs(Span
, Span
),
1008 pub fn find_transparency(
1010 attrs
: &[Attribute
],
1012 ) -> (Transparency
, Option
<TransparencyError
>) {
1013 let mut transparency
= None
;
1014 let mut error
= None
;
1016 if sess
.check_name(attr
, sym
::rustc_macro_transparency
) {
1017 if let Some((_
, old_span
)) = transparency
{
1018 error
= Some(TransparencyError
::MultipleTransparencyAttrs(old_span
, attr
.span
));
1020 } else if let Some(value
) = attr
.value_str() {
1021 transparency
= Some((
1023 sym
::transparent
=> Transparency
::Transparent
,
1024 sym
::semitransparent
=> Transparency
::SemiTransparent
,
1025 sym
::opaque
=> Transparency
::Opaque
,
1027 error
= Some(TransparencyError
::UnknownTransparency(value
, attr
.span
));
1036 let fallback
= if macro_rules { Transparency::SemiTransparent }
else { Transparency::Opaque }
;
1037 (transparency
.map_or(fallback
, |t
| t
.0), error
)
1040 pub fn allow_internal_unstable
<'a
>(
1042 attrs
: &'a
[Attribute
],
1043 ) -> impl Iterator
<Item
= Symbol
> + 'a
{
1044 allow_unstable(sess
, attrs
, sym
::allow_internal_unstable
)
1047 pub fn rustc_allow_const_fn_unstable
<'a
>(
1049 attrs
: &'a
[Attribute
],
1050 ) -> impl Iterator
<Item
= Symbol
> + 'a
{
1051 allow_unstable(sess
, attrs
, sym
::rustc_allow_const_fn_unstable
)
1054 fn allow_unstable
<'a
>(
1056 attrs
: &'a
[Attribute
],
1058 ) -> impl Iterator
<Item
= Symbol
> + 'a
{
1059 let attrs
= sess
.filter_by_name(attrs
, symbol
);
1061 .filter_map(move |attr
| {
1062 attr
.meta_item_list().or_else(|| {
1063 sess
.diagnostic().span_err(
1065 &format
!("`{}` expects a list of feature names", symbol
.to_ident_string()),
1072 list
.into_iter().filter_map(move |it
| {
1073 let name
= it
.ident().map(|ident
| ident
.name
);
1075 sess
.diagnostic().span_err(
1077 &format
!("`{}` expects feature names", symbol
.to_ident_string()),