Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
2d2307e
Dedup `&mut *` reborrow suggestion in loops
ShE3py Mar 13, 2025
2feb911
io: Avoid marking buffer as uninit when copying to `BufWriter`
a1phyr Mar 28, 2025
8787868
io: Avoid Avoid marking bytes as uninit in `BufReader::peek`
a1phyr Mar 28, 2025
1d6ddd6
Remove unused variables generated in merged doctests
GuillaumeGomez Apr 2, 2025
2dd4501
Put Noratrieb on vacation
Noratrieb Apr 2, 2025
f798c46
Map myself
RossSmyth Mar 4, 2025
076cccd
Remove `Op` type.
nnethercote Dec 19, 2024
ac8ccf0
Use `BinOpKind` instead of `BinOp` for function args where possible.
nnethercote Dec 19, 2024
ddcb370
Tighten up assignment operator representations.
nnethercote Dec 19, 2024
f3eaf16
Split ExpectationLintId off Level
oli-obk Mar 18, 2025
c51816e
Make LevelAndSource a struct
oli-obk Mar 19, 2025
805f389
Remove `LintExpectationId` from `Level` variants
oli-obk Mar 19, 2025
0795b3d
Upvars HirIds always have the same owner, thus just use an ItemLocalId
oli-obk Mar 17, 2025
5a4e7eb
impl !PartialOrd for UpvarMigrationInfo
oli-obk Mar 17, 2025
57c4ab7
impl !PartialOrd for HirId
oli-obk Mar 17, 2025
3df2acd
Allow boolean literals in `check-cfg`
clubby789 Mar 21, 2025
b310e8c
add Marco Ieni to mailmap
marcoieni Apr 3, 2025
e5c7451
Rollup merge of #138017 - nnethercote:tighten-assignment-op, r=spasto…
matthiaskrgr Apr 3, 2025
731ce84
Rollup merge of #138462 - ShE3py:mut-borrow-in-loop, r=oli-obk
matthiaskrgr Apr 3, 2025
48a3919
Rollup merge of #138610 - oli-obk:no-sort-hir-ids, r=compiler-errors
matthiaskrgr Apr 3, 2025
9d733ec
Rollup merge of #138767 - clubby789:check-cfg-bool, r=Urgau
matthiaskrgr Apr 3, 2025
ff8f2ef
Rollup merge of #139068 - a1phyr:less_uninit, r=joboet
matthiaskrgr Apr 3, 2025
ed6efe6
Rollup merge of #139255 - GuillaumeGomez:unused-var-merged-doctest, r…
matthiaskrgr Apr 3, 2025
ec9aa8c
Rollup merge of #139270 - RossSmyth:mailmap, r=Noratrieb
matthiaskrgr Apr 3, 2025
42aef0c
Rollup merge of #139303 - Noratrieb:Noratrieb-patch-3, r=Noratrieb
matthiaskrgr Apr 3, 2025
4cf6c21
Rollup merge of #139312 - marcoieni:marco-mailmap, r=Kobzol
matthiaskrgr Apr 3, 2025
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
Prev Previous commit
Next Next commit
Remove LintExpectationId from Level variants
  • Loading branch information
oli-obk committed Apr 3, 2025
commit 805f389da5d8870dc19f879300684bd421194d88
2 changes: 1 addition & 1 deletion compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,7 @@ fn print_crate_info(
// lint is unstable and feature gate isn't active, don't print
continue;
}
let level = lint_levels.lint_level(lint).0;
let level = lint_levels.lint_level(lint).level;
println_info!("{}={}", lint.name_lower(), level.as_str());
}
}
Expand Down
15 changes: 7 additions & 8 deletions compiler/rustc_lint/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,12 @@ use rustc_hir::def_id::{CrateNum, DefId};
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
use rustc_hir::{Pat, PatKind};
use rustc_middle::bug;
use rustc_middle::lint::LevelAndSource;
use rustc_middle::middle::privacy::EffectiveVisibilities;
use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, Printer, with_no_trimmed_paths};
use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingEnv, TypingMode};
use rustc_session::lint::{
FutureIncompatibleInfo, Level, Lint, LintBuffer, LintExpectationId, LintId,
};
use rustc_session::lint::{FutureIncompatibleInfo, Lint, LintBuffer, LintExpectationId, LintId};
use rustc_session::{LintStoreMarker, Session};
use rustc_span::edit_distance::find_best_match_for_names;
use rustc_span::{Ident, Span, Symbol, sym};
Expand Down Expand Up @@ -573,7 +572,7 @@ pub trait LintContext {
}

/// This returns the lint level for the given lint at the current location.
fn get_lint_level(&self, lint: &'static Lint) -> Level;
fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource;

/// This function can be used to manually fulfill an expectation. This can
/// be used for lints which contain several spans, and should be suppressed,
Expand Down Expand Up @@ -642,8 +641,8 @@ impl<'tcx> LintContext for LateContext<'tcx> {
}
}

fn get_lint_level(&self, lint: &'static Lint) -> Level {
self.tcx.lint_level_at_node(lint, self.last_node_with_lint_attrs).level
fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource {
self.tcx.lint_level_at_node(lint, self.last_node_with_lint_attrs)
}
}

Expand All @@ -663,8 +662,8 @@ impl LintContext for EarlyContext<'_> {
self.builder.opt_span_lint(lint, span.map(|s| s.into()), decorate)
}

fn get_lint_level(&self, lint: &'static Lint) -> Level {
self.builder.lint_level(lint).level
fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource {
self.builder.lint_level(lint)
}
}

Expand Down
90 changes: 43 additions & 47 deletions compiler/rustc_lint/src/levels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,28 +84,28 @@ impl LintLevelSets {
) -> LevelAndSource {
let lint = LintId::of(lint);
let (level, mut src) = self.raw_lint_id_level(lint, idx, aux);
let level = reveal_actual_level(level, &mut src, sess, lint, |id| {
let (level, lint_id) = reveal_actual_level(level, &mut src, sess, lint, |id| {
self.raw_lint_id_level(id, idx, aux)
});
LevelAndSource { level, src }
LevelAndSource { level, lint_id, src }
}

fn raw_lint_id_level(
&self,
id: LintId,
mut idx: LintStackIndex,
aux: Option<&FxIndexMap<LintId, LevelAndSource>>,
) -> (Option<Level>, LintLevelSource) {
) -> (Option<(Level, Option<LintExpectationId>)>, LintLevelSource) {
if let Some(specs) = aux
&& let Some(&LevelAndSource { level, src }) = specs.get(&id)
&& let Some(&LevelAndSource { level, lint_id, src }) = specs.get(&id)
{
return (Some(level), src);
return (Some((level, lint_id)), src);
}

loop {
let LintSet { ref specs, parent } = self.list[idx];
if let Some(&LevelAndSource { level, src }) = specs.get(&id) {
return (Some(level), src);
if let Some(&LevelAndSource { level, lint_id, src }) = specs.get(&id) {
return (Some((level, lint_id)), src);
}
if idx == COMMAND_LINE {
return (None, LintLevelSource::Default);
Expand Down Expand Up @@ -379,13 +379,7 @@ impl<'tcx> Visitor<'tcx> for LintLevelMaximum<'tcx> {
fn visit_attribute(&mut self, attribute: &'tcx hir::Attribute) {
if matches!(
Level::from_attr(attribute),
Some(
Level::Warn
| Level::Deny
| Level::Forbid
| Level::Expect(..)
| Level::ForceWarn(..),
)
Some((Level::Warn | Level::Deny | Level::Forbid | Level::Expect | Level::ForceWarn, _))
) {
let store = unerased_lint_store(self.tcx.sess);
// Lint attributes are always a metalist inside a
Expand Down Expand Up @@ -541,9 +535,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
for &(ref lint_name, level) in &self.sess.opts.lint_opts {
// Checks the validity of lint names derived from the command line.
let (tool_name, lint_name_only) = parse_lint_and_tool_name(lint_name);
if lint_name_only == crate::WARNINGS.name_lower()
&& matches!(level, Level::ForceWarn(_))
{
if lint_name_only == crate::WARNINGS.name_lower() && matches!(level, Level::ForceWarn) {
self.sess
.dcx()
.emit_err(UnsupportedGroup { lint_group: crate::WARNINGS.name_lower() });
Expand Down Expand Up @@ -586,7 +578,6 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
_ => {}
};

let orig_level = level;
let lint_flag_val = Symbol::intern(lint_name);

let Ok(ids) = self.store.find_lints(lint_name) else {
Expand All @@ -595,15 +586,15 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
};
for id in ids {
// ForceWarn and Forbid cannot be overridden
if let Some(LevelAndSource { level: Level::ForceWarn(_) | Level::Forbid, .. }) =
if let Some(LevelAndSource { level: Level::ForceWarn | Level::Forbid, .. }) =
self.current_specs().get(&id)
{
continue;
}

if self.check_gated_lint(id, DUMMY_SP, true) {
let src = LintLevelSource::CommandLine(lint_flag_val, orig_level);
self.insert(id, LevelAndSource { level, src });
let src = LintLevelSource::CommandLine(lint_flag_val, level);
self.insert(id, LevelAndSource { level, lint_id: None, src });
}
}
}
Expand All @@ -612,8 +603,8 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
/// Attempts to insert the `id` to `level_src` map entry. If unsuccessful
/// (e.g. if a forbid was already inserted on the same scope), then emits a
/// diagnostic with no change to `specs`.
fn insert_spec(&mut self, id: LintId, LevelAndSource { level, src }: LevelAndSource) {
let LevelAndSource { level: old_level, src: old_src } =
fn insert_spec(&mut self, id: LintId, LevelAndSource { level, lint_id, src }: LevelAndSource) {
let LevelAndSource { level: old_level, src: old_src, .. } =
self.provider.get_lint_level(id.lint, self.sess);

// Setting to a non-forbid level is an error if the lint previously had
Expand Down Expand Up @@ -686,24 +677,24 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
// The lint `unfulfilled_lint_expectations` can't be expected, as it would suppress itself.
// Handling expectations of this lint would add additional complexity with little to no
// benefit. The expect level for this lint will therefore be ignored.
if let Level::Expect(_) = level
if let Level::Expect = level
&& id == LintId::of(UNFULFILLED_LINT_EXPECTATIONS)
{
return;
}

match (old_level, level) {
// If the new level is an expectation store it in `ForceWarn`
(Level::ForceWarn(_), Level::Expect(expectation_id)) => self.insert(
(Level::ForceWarn, Level::Expect) => {
self.insert(id, LevelAndSource { level: Level::ForceWarn, lint_id, src: old_src })
}
// Keep `ForceWarn` level but drop the expectation
(Level::ForceWarn, _) => self.insert(
id,
LevelAndSource { level: Level::ForceWarn(Some(expectation_id)), src: old_src },
LevelAndSource { level: Level::ForceWarn, lint_id: None, src: old_src },
),
// Keep `ForceWarn` level but drop the expectation
(Level::ForceWarn(_), _) => {
self.insert(id, LevelAndSource { level: Level::ForceWarn(None), src: old_src })
}
// Set the lint level as normal
_ => self.insert(id, LevelAndSource { level, src }),
_ => self.insert(id, LevelAndSource { level, lint_id, src }),
};
}

Expand All @@ -718,7 +709,11 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
if attr.has_name(sym::automatically_derived) {
self.insert(
LintId::of(SINGLE_USE_LIFETIMES),
LevelAndSource { level: Level::Allow, src: LintLevelSource::Default },
LevelAndSource {
level: Level::Allow,
lint_id: None,
src: LintLevelSource::Default,
},
);
continue;
}
Expand All @@ -731,16 +726,20 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
{
self.insert(
LintId::of(MISSING_DOCS),
LevelAndSource { level: Level::Allow, src: LintLevelSource::Default },
LevelAndSource {
level: Level::Allow,
lint_id: None,
src: LintLevelSource::Default,
},
);
continue;
}

let level = match Level::from_attr(attr) {
let (level, lint_id) = match Level::from_attr(attr) {
None => continue,
// This is the only lint level with a `LintExpectationId` that can be created from
// an attribute.
Some(Level::Expect(unstable_id)) if let Some(hir_id) = source_hir_id => {
Some((Level::Expect, Some(unstable_id))) if let Some(hir_id) = source_hir_id => {
let LintExpectationId::Unstable { lint_index: None, attr_id: _ } = unstable_id
else {
bug!("stable id Level::from_attr")
Expand All @@ -752,9 +751,9 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
lint_index: None,
};

Level::Expect(stable_id)
(Level::Expect, Some(stable_id))
}
Some(lvl) => lvl,
Some((lvl, id)) => (lvl, id),
};

let Some(mut metas) = attr.meta_item_list() else { continue };
Expand Down Expand Up @@ -802,13 +801,10 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
}

for (lint_index, li) in metas.iter_mut().enumerate() {
let level = match level {
Level::Expect(mut id) => {
id.set_lint_index(Some(lint_index as u16));
Level::Expect(id)
}
level => level,
};
let mut lint_id = lint_id;
if let Some(id) = &mut lint_id {
id.set_lint_index(Some(lint_index as u16));
}

let sp = li.span();
let meta_item = match li {
Expand Down Expand Up @@ -940,7 +936,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
let src = LintLevelSource::Node { name, span: sp, reason };
for &id in ids {
if self.check_gated_lint(id, sp, false) {
self.insert_spec(id, LevelAndSource { level, src });
self.insert_spec(id, LevelAndSource { level, lint_id, src });
}
}

Expand All @@ -949,7 +945,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
// overriding the lint level but instead add an expectation that can't be
// fulfilled. The lint message will include an explanation, that the
// `unfulfilled_lint_expectations` lint can't be expected.
if let Level::Expect(expect_id) = level {
if let (Level::Expect, Some(expect_id)) = (level, lint_id) {
// The `unfulfilled_lint_expectations` lint is not part of any lint
// groups. Therefore. we only need to check the slice if it contains a
// single lint.
Expand All @@ -971,7 +967,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
}

if self.lint_added_lints && !is_crate_node {
for (id, &LevelAndSource { level, ref src }) in self.current_specs().iter() {
for (id, &LevelAndSource { level, ref src, .. }) in self.current_specs().iter() {
if !id.lint.crate_level_only {
continue;
}
Expand Down
45 changes: 22 additions & 23 deletions compiler/rustc_lint_defs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,19 +199,19 @@ pub enum Level {
///
/// See RFC 2383.
///
/// The [`LintExpectationId`] is used to later link a lint emission to the actual
/// Requires a [`LintExpectationId`] to later link a lint emission to the actual
/// expectation. It can be ignored in most cases.
Expect(LintExpectationId),
Expect,
/// The `warn` level will produce a warning if the lint was violated, however the
/// compiler will continue with its execution.
Warn,
/// This lint level is a special case of [`Warn`], that can't be overridden. This is used
/// to ensure that a lint can't be suppressed. This lint level can currently only be set
/// via the console and is therefore session specific.
///
/// The [`LintExpectationId`] is intended to fulfill expectations marked via the
/// Requires a [`LintExpectationId`] to fulfill expectations marked via the
/// `#[expect]` attribute, that will still be suppressed due to the level.
ForceWarn(Option<LintExpectationId>),
ForceWarn,
/// The `deny` level will produce an error and stop further execution after the lint
/// pass is complete.
Deny,
Expand All @@ -225,9 +225,9 @@ impl Level {
pub fn as_str(self) -> &'static str {
match self {
Level::Allow => "allow",
Level::Expect(_) => "expect",
Level::Expect => "expect",
Level::Warn => "warn",
Level::ForceWarn(_) => "force-warn",
Level::ForceWarn => "force-warn",
Level::Deny => "deny",
Level::Forbid => "forbid",
}
Expand All @@ -246,24 +246,30 @@ impl Level {
}

/// Converts an `Attribute` to a level.
pub fn from_attr(attr: &impl AttributeExt) -> Option<Self> {
pub fn from_attr(attr: &impl AttributeExt) -> Option<(Self, Option<LintExpectationId>)> {
Self::from_symbol(attr.name_or_empty(), || Some(attr.id()))
}

/// Converts a `Symbol` to a level.
pub fn from_symbol(s: Symbol, id: impl FnOnce() -> Option<AttrId>) -> Option<Self> {
pub fn from_symbol(
s: Symbol,
id: impl FnOnce() -> Option<AttrId>,
) -> Option<(Self, Option<LintExpectationId>)> {
match s {
sym::allow => Some(Level::Allow),
sym::allow => Some((Level::Allow, None)),
sym::expect => {
if let Some(attr_id) = id() {
Some(Level::Expect(LintExpectationId::Unstable { attr_id, lint_index: None }))
Some((
Level::Expect,
Some(LintExpectationId::Unstable { attr_id, lint_index: None }),
))
} else {
None
}
}
sym::warn => Some(Level::Warn),
sym::deny => Some(Level::Deny),
sym::forbid => Some(Level::Forbid),
sym::warn => Some((Level::Warn, None)),
sym::deny => Some((Level::Deny, None)),
sym::forbid => Some((Level::Forbid, None)),
_ => None,
}
}
Expand All @@ -274,26 +280,19 @@ impl Level {
Level::Deny => "-D",
Level::Forbid => "-F",
Level::Allow => "-A",
Level::ForceWarn(_) => "--force-warn",
Level::Expect(_) => {
Level::ForceWarn => "--force-warn",
Level::Expect => {
unreachable!("the expect level does not have a commandline flag")
}
}
}

pub fn is_error(self) -> bool {
match self {
Level::Allow | Level::Expect(_) | Level::Warn | Level::ForceWarn(_) => false,
Level::Allow | Level::Expect | Level::Warn | Level::ForceWarn => false,
Level::Deny | Level::Forbid => true,
}
}

pub fn get_expectation_id(&self) -> Option<LintExpectationId> {
match self {
Level::Expect(id) | Level::ForceWarn(Some(id)) => Some(*id),
_ => None,
}
}
}

/// Specification of a single lint.
Expand Down
Loading