Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4409,7 +4409,6 @@ dependencies = [
"rustc_middle",
"rustc_query_system",
"rustc_serialize",
"rustc_session",
"rustc_span",
"tracing",
]
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_attr_parsing/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -247,3 +247,7 @@ attr_parsing_raw_dylib_only_windows =

attr_parsing_whole_archive_needs_static =
linking modifier `whole-archive` is only compatible with `static` linking kind

attr_parsing_limit_invalid =
`limit` must be a non-negative integer
.label = {$error_str}
143 changes: 142 additions & 1 deletion compiler/rustc_attr_parsing/src/attributes/crate_level.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,40 @@
use rustc_feature::AttributeType;
use std::num::IntErrorKind;

use rustc_hir::limit::Limit;

use super::prelude::*;
use crate::session_diagnostics::LimitInvalid;

impl<S: Stage> AcceptContext<'_, '_, S> {
fn parse_limit_int(&self, nv: &NameValueParser) -> Option<Limit> {
let Some(limit) = nv.value_as_str() else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fn parse_limit_int(&self, nv: &NameValueParser) -> Option<Limit> {
fn parse_limit(&self, nv: &NameValueParser) -> Option<Limit> {

?

self.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
return None;
};

let error_str = match limit.as_str().parse() {
Ok(i) => return Some(Limit::new(i)),
Err(e) => match e.kind() {
IntErrorKind::PosOverflow => "`limit` is too large",
IntErrorKind::Empty => "`limit` must be a non-negative integer",
IntErrorKind::InvalidDigit => "not a valid integer",
IntErrorKind::NegOverflow => {
panic!(
"`limit` should never negatively overflow since we're parsing into a usize and we'd get Empty instead"
)
}
IntErrorKind::Zero => {
panic!("zero is a valid `limit` so should have returned Ok() when parsing")
}
kind => panic!("unimplemented IntErrorKind variant: {:?}", kind),
},
};

self.emit_err(LimitInvalid { span: self.attr_span, value_span: nv.value_span, error_str });

None
}
}

pub(crate) struct CrateNameParser;

Expand Down Expand Up @@ -34,3 +68,110 @@ impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
})
}
}

pub(crate) struct RecursionLimitParser;

impl<S: Stage> SingleAttributeParser<S> for RecursionLimitParser {
const PATH: &[Symbol] = &[sym::recursion_limit];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute");
const TYPE: AttributeType = AttributeType::CrateLevel;

// FIXME: recursion limit is allowed on all targets and ignored,
// even though it should only be valid on crates of course
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
let ArgParser::NameValue(nv) = args else {
cx.expected_name_value(cx.attr_span, None);
return None;
};

Some(AttributeKind::RecursionLimit {
limit: cx.parse_limit_int(nv)?,
attr_span: cx.attr_span,
limit_span: nv.value_span,
})
}
}

pub(crate) struct MoveSizeLimitParser;

impl<S: Stage> SingleAttributeParser<S> for MoveSizeLimitParser {
const PATH: &[Symbol] = &[sym::move_size_limit];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if you want to do that in this PR but #![move_size_limit] is still unstable under feature large_assignments (RUST-83518), so theoretically we could just bump this to OnDuplicate::Error.


// FIXME: recursion limit is allowed on all targets and ignored,
// even though it should only be valid on crates of course
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// FIXME: recursion limit is allowed on all targets and ignored,
// FIXME: move size limit is allowed on all targets and ignored,

const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, this could be bumped to AllowedTargets::AllowList(&[Target::Crate]) (is that how it's done?) because it's still unstable.

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
let ArgParser::NameValue(nv) = args else {
cx.expected_name_value(cx.attr_span, None);
return None;
};

Some(AttributeKind::MoveSizeLimit {
limit: cx.parse_limit_int(nv)?,
attr_span: cx.attr_span,
limit_span: nv.value_span,
})
}
}

pub(crate) struct TypeLengthLimitParser;

impl<S: Stage> SingleAttributeParser<S> for TypeLengthLimitParser {
const PATH: &[Symbol] = &[sym::type_length_limit];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
const TYPE: AttributeType = AttributeType::CrateLevel;

// FIXME: recursion limit is allowed on all targets and ignored,
// even though it should only be valid on crates of course
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
let ArgParser::NameValue(nv) = args else {
cx.expected_name_value(cx.attr_span, None);
return None;
};

Some(AttributeKind::TypeLengthLimit {
limit: cx.parse_limit_int(nv)?,
attr_span: cx.attr_span,
limit_span: nv.value_span,
})
}
}

pub(crate) struct PatternComplexityLimitParser;

impl<S: Stage> SingleAttributeParser<S> for PatternComplexityLimitParser {
const PATH: &[Symbol] = &[sym::pattern_complexity_limit];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since #![pattern_complexity_limit] is gated behind the internal feature rustc_attrs (for some reason, lol), this could be upgraded to OnDuplicate::Error.

const TYPE: AttributeType = AttributeType::CrateLevel;

// FIXME: recursion limit is allowed on all targets and ignored,
// even though it should only be valid on crates of course
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

… and this one to AllowList(&[Level::Crate]) (if that's the correct policy) for the same reason.

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
let ArgParser::NameValue(nv) = args else {
cx.expected_name_value(cx.attr_span, None);
return None;
};

Some(AttributeKind::PatternComplexityLimit {
limit: cx.parse_limit_int(nv)?,
attr_span: cx.attr_span,
limit_span: nv.value_span,
})
}
}
5 changes: 2 additions & 3 deletions compiler/rustc_attr_parsing/src/attributes/prelude.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
// templates
#[doc(hidden)]
pub(super) use rustc_feature::{AttributeTemplate, template};
// data structures
#[doc(hidden)]
pub(super) use rustc_feature::{AttributeTemplate, AttributeType, template};
#[doc(hidden)]
pub(super) use rustc_hir::attrs::AttributeKind;
#[doc(hidden)]
pub(super) use rustc_hir::lints::AttributeLintKind;
Expand Down
20 changes: 15 additions & 5 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ use crate::attributes::codegen_attrs::{
UsedParser,
};
use crate::attributes::confusables::ConfusablesParser;
use crate::attributes::crate_level::CrateNameParser;
use crate::attributes::crate_level::{
CrateNameParser, MoveSizeLimitParser, PatternComplexityLimitParser, RecursionLimitParser,
TypeLengthLimitParser,
};
use crate::attributes::deprecation::DeprecationParser;
use crate::attributes::dummy::DummyParser;
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
Expand Down Expand Up @@ -181,10 +184,13 @@ attribute_parsers!(
Single<LinkOrdinalParser>,
Single<LinkSectionParser>,
Single<LinkageParser>,
Single<MoveSizeLimitParser>,
Single<MustUseParser>,
Single<OptimizeParser>,
Single<PathAttributeParser>,
Single<PatternComplexityLimitParser>,
Single<ProcMacroDeriveParser>,
Single<RecursionLimitParser>,
Single<RustcBuiltinMacroParser>,
Single<RustcForceInlineParser>,
Single<RustcLayoutScalarValidRangeEnd>,
Expand All @@ -194,6 +200,7 @@ attribute_parsers!(
Single<ShouldPanicParser>,
Single<SkipDuringMethodDispatchParser>,
Single<TransparencyParser>,
Single<TypeLengthLimitParser>,
Single<WithoutArgs<AllowIncoherentImplParser>>,
Single<WithoutArgs<AllowInternalUnsafeParser>>,
Single<WithoutArgs<AsPtrParser>>,
Expand Down Expand Up @@ -346,7 +353,10 @@ impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
/// must be delayed until after HIR is built. This method will take care of the details of
/// that.
pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) {
if matches!(self.stage.should_emit(), ShouldEmit::Nothing) {
if !matches!(
self.stage.should_emit(),
ShouldEmit::ErrorsAndLints | ShouldEmit::EarlyFatal { also_emit_lints: true }
) {
return;
}
let id = self.target_id;
Expand Down Expand Up @@ -670,7 +680,7 @@ pub enum ShouldEmit {
///
/// Only relevant when early parsing, in late parsing equivalent to `ErrorsAndLints`.
/// Late parsing is never fatal, and instead tries to emit as many diagnostics as possible.
EarlyFatal,
EarlyFatal { also_emit_lints: bool },
/// The operation will emit errors and lints.
/// This is usually what you need.
ErrorsAndLints,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(preexisting) docs of variant Nothing mention nonexistent variant Emit.

Expand All @@ -682,8 +692,8 @@ pub enum ShouldEmit {
impl ShouldEmit {
pub(crate) fn emit_err(&self, diag: Diag<'_>) -> ErrorGuaranteed {
match self {
ShouldEmit::EarlyFatal if diag.level() == Level::DelayedBug => diag.emit(),
ShouldEmit::EarlyFatal => diag.upgrade_to_fatal().emit(),
ShouldEmit::EarlyFatal { .. } if diag.level() == Level::DelayedBug => diag.emit(),
ShouldEmit::EarlyFatal { .. } => diag.upgrade_to_fatal().emit(),
ShouldEmit::ErrorsAndLints => diag.emit(),
ShouldEmit::Nothing => diag.delay_as_bug(),
}
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_attr_parsing/src/session_diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -930,3 +930,13 @@ pub(crate) struct ImportNameTypeRaw {
#[primary_span]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(attr_parsing_limit_invalid)]
pub(crate) struct LimitInvalid<'a> {
#[primary_span]
pub span: Span,
#[label]
pub value_span: Span,
pub error_str: &'a str,
}
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use either::{Left, Right};
use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout};
use rustc_errors::DiagCtxtHandle;
use rustc_hir::def_id::DefId;
use rustc_hir::limit::Limit;
use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo};
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::layout::{
Expand All @@ -12,7 +13,6 @@ use rustc_middle::ty::layout::{
};
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypingEnv, Variance};
use rustc_middle::{mir, span_bug};
use rustc_session::Limit;
use rustc_span::Span;
use rustc_target::callconv::FnAbi;
use tracing::{debug, trace};
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ use rustc_feature::Features;
use rustc_hir as hir;
use rustc_hir::attrs::{AttributeKind, CfgEntry, Deprecation};
use rustc_hir::def::MacroKinds;
use rustc_hir::limit::Limit;
use rustc_hir::{Stability, find_attr};
use rustc_lint_defs::RegisteredTools;
use rustc_parse::MACRO_ARGUMENTS;
use rustc_parse::parser::{ForceCollect, Parser};
use rustc_session::Session;
use rustc_session::config::CollapseMacroDebuginfo;
use rustc_session::parse::ParseSess;
use rustc_session::{Limit, Session};
use rustc_span::def_id::{CrateNum, DefId, LocalDefId};
use rustc_span::edition::Edition;
use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId, MacroKind};
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_expand/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use std::borrow::Cow;

use rustc_ast::ast;
use rustc_errors::codes::*;
use rustc_hir::limit::Limit;
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_session::Limit;
use rustc_span::{Ident, MacroRulesNormalizedIdent, Span, Symbol};

#[derive(Diagnostic)]
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_expand/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,15 @@ use rustc_errors::PResult;
use rustc_feature::Features;
use rustc_hir::Target;
use rustc_hir::def::MacroKinds;
use rustc_hir::limit::Limit;
use rustc_parse::parser::{
AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, RecoverColon, RecoverComma,
token_descr,
};
use rustc_session::Session;
use rustc_session::lint::BuiltinLintDiag;
use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS};
use rustc_session::parse::feature_err;
use rustc_session::{Limit, Session};
use rustc_span::hygiene::SyntaxContext;
use rustc_span::{ErrorGuaranteed, FileName, Ident, LocalExpnId, Span, Symbol, sym};
use smallvec::SmallVec;
Expand Down Expand Up @@ -2529,6 +2530,7 @@ impl ExpansionConfig<'_> {
ExpansionConfig {
crate_name,
features,
// FIXME should this limit be configurable?
recursion_limit: Limit::new(1024),
trace_mac: false,
should_test: false,
Expand Down
13 changes: 13 additions & 0 deletions compiler/rustc_hir/src/attrs/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub use rustc_target::spec::SanitizerSet;
use thin_vec::ThinVec;

use crate::attrs::pretty_printing::PrintAttribute;
use crate::limit::Limit;
use crate::{DefaultBodyStability, PartialConstStability, RustcVersion, Stability};

#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic, PrintAttribute)]
Expand Down Expand Up @@ -565,6 +566,9 @@ pub enum AttributeKind {
/// Represents [`#[may_dangle]`](https://std-dev-guide.rust-lang.org/tricky/may-dangle.html).
MayDangle(Span),

/// Represents `#[move_size_limit]`
MoveSizeLimit { attr_span: Span, limit_span: Span, limit: Limit },

/// Represents `#[must_use]`.
MustUse {
span: Span,
Expand Down Expand Up @@ -596,6 +600,9 @@ pub enum AttributeKind {
/// Represents `#[path]`
Path(Symbol, Span),

/// Represents `#[pattern_complexity_limit]`
PatternComplexityLimit { attr_span: Span, limit_span: Span, limit: Limit },

/// Represents `#[pointee]`
Pointee(Span),

Expand All @@ -611,6 +618,9 @@ pub enum AttributeKind {
/// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
PubTransparent(Span),

/// Represents [`#[recursion_limit]`](https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute)
RecursionLimit { attr_span: Span, limit_span: Span, limit: Limit },

/// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations).
Repr { reprs: ThinVec<(ReprAttr, Span)>, first_span: Span },

Expand Down Expand Up @@ -661,6 +671,9 @@ pub enum AttributeKind {
/// Represents `#[type_const]`.
TypeConst(Span),

/// Represents `#[type_length_limit]`
TypeLengthLimit { attr_span: Span, limit_span: Span, limit: Limit },

/// Represents `#[rustc_unsafe_specialization_marker]`.
UnsafeSpecializationMarker(Span),

Expand Down
Loading
Loading