mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-21 17:52:12 +03:00
Auto merge of #156576 - GuillaumeGomez:rollup-3CJ0vjd, r=GuillaumeGomez
Rollup of 3 pull requests Successful merges: - rust-lang/rust#146220 (feat(rustdoc): stabilize `--emit` flag) - rust-lang/rust#153785 (Hand-written Debug implementation for `TypeTest`) - rust-lang/rust#156564 (Lint level cleanups)
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
use std::collections::VecDeque;
|
||||
use std::fmt;
|
||||
use std::rc::Rc;
|
||||
|
||||
use rustc_data_structures::frozen::Frozen;
|
||||
@@ -182,7 +183,7 @@ pub(crate) enum Cause {
|
||||
/// For more information about this translation, see
|
||||
/// `InferCtxt::process_registered_region_obligations` and
|
||||
/// `InferCtxt::type_must_outlive` in `rustc_infer::infer::InferCtxt`.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct TypeTest<'tcx> {
|
||||
/// The type `T` that must outlive the region.
|
||||
pub generic_kind: GenericKind<'tcx>,
|
||||
@@ -198,6 +199,47 @@ pub(crate) struct TypeTest<'tcx> {
|
||||
pub verify_bound: VerifyBound<'tcx>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for TypeTest<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fn fmt_bound(
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
generic_kind: GenericKind<'_>,
|
||||
lower: RegionVid,
|
||||
bound: &VerifyBound<'_>,
|
||||
) -> fmt::Result {
|
||||
let fmt_bounds =
|
||||
|f: &mut fmt::Formatter<'_>, bounds: &[VerifyBound<'_>]| -> fmt::Result {
|
||||
let mut it = bounds.iter().peekable();
|
||||
while let Some(bound) = it.next() {
|
||||
fmt_bound(f, generic_kind, lower, bound)?;
|
||||
if it.peek().is_some() {
|
||||
write!(f, ", ")?
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
};
|
||||
match bound {
|
||||
VerifyBound::IfEq(binder) => write!(f, "{:?} == {:?}", generic_kind, binder),
|
||||
VerifyBound::OutlivedBy(region) => write!(f, "{region:?}: {lower:?}"),
|
||||
VerifyBound::AnyBound(verify_bounds) => {
|
||||
write!(f, "Any[")?;
|
||||
fmt_bounds(f, verify_bounds)?;
|
||||
write!(f, "]")
|
||||
}
|
||||
VerifyBound::AllBounds(verify_bounds) => {
|
||||
write!(f, "All[")?;
|
||||
fmt_bounds(f, verify_bounds)?;
|
||||
write!(f, "]")
|
||||
}
|
||||
VerifyBound::IsEmpty => write!(f, "Empty({lower:?})"),
|
||||
}
|
||||
}
|
||||
write!(f, "TypeTest from {:?}[", self.span)?;
|
||||
fmt_bound(f, self.generic_kind, self.lower_bound, &self.verify_bound)?;
|
||||
write!(f, "] ⊢ {:?}: {:?}", self.generic_kind, self.lower_bound)
|
||||
}
|
||||
}
|
||||
|
||||
/// When we have an unmet lifetime constraint, we try to propagate it outward (e.g. to a closure
|
||||
/// environment). If we can't, it is an error.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
use super::rpath::{self, RPathConfig};
|
||||
use super::{apple, rmeta_link, versioned_llvm_target};
|
||||
use crate::base::needs_allocator_shim_for_linking;
|
||||
use crate::{CodegenLintLevels, CompiledModule, CompiledModules, CrateInfo, NativeLib, errors};
|
||||
use crate::{CodegenLintLevelSpecs, CompiledModule, CompiledModules, CrateInfo, NativeLib, errors};
|
||||
|
||||
pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) {
|
||||
if let Err(e) = fs::remove_file(path) {
|
||||
@@ -728,7 +728,12 @@ fn is_windows_gnu_clang(sess: &Session) -> bool {
|
||||
&& sess.target.options.cfg_abi == CfgAbi::Llvm
|
||||
}
|
||||
|
||||
fn report_linker_output(sess: &Session, levels: CodegenLintLevels, stdout: &[u8], stderr: &[u8]) {
|
||||
fn report_linker_output(
|
||||
sess: &Session,
|
||||
levels: CodegenLintLevelSpecs,
|
||||
stdout: &[u8],
|
||||
stderr: &[u8],
|
||||
) {
|
||||
let mut escaped_stderr = escape_string(&stderr);
|
||||
let mut escaped_stdout = escape_string(&stdout);
|
||||
let mut linker_info = String::new();
|
||||
@@ -1106,7 +1111,7 @@ fn link_natively(
|
||||
}
|
||||
|
||||
info!("reporting linker output: flavor={flavor:?}");
|
||||
report_linker_output(sess, crate_info.lint_levels, &prog.stdout, &prog.stderr);
|
||||
report_linker_output(sess, crate_info.lint_level_specs, &prog.stdout, &prog.stderr);
|
||||
}
|
||||
Err(e) => {
|
||||
let linker_not_found = e.kind() == io::ErrorKind::NotFound;
|
||||
|
||||
@@ -49,7 +49,9 @@
|
||||
use crate::mir::operand::OperandValue;
|
||||
use crate::mir::place::PlaceRef;
|
||||
use crate::traits::*;
|
||||
use crate::{CachedModuleCodegen, CodegenLintLevels, CrateInfo, ModuleCodegen, errors, meth, mir};
|
||||
use crate::{
|
||||
CachedModuleCodegen, CodegenLintLevelSpecs, CrateInfo, ModuleCodegen, errors, meth, mir,
|
||||
};
|
||||
|
||||
pub(crate) fn bin_op_to_icmp_predicate(op: BinOp, signed: bool) -> IntPredicate {
|
||||
match (op, signed) {
|
||||
@@ -953,7 +955,7 @@ pub fn new(tcx: TyCtxt<'_>, target_cpu: String) -> CrateInfo {
|
||||
dependency_formats: Arc::clone(tcx.dependency_formats(())),
|
||||
windows_subsystem,
|
||||
natvis_debugger_visualizers: Default::default(),
|
||||
lint_levels: CodegenLintLevels::from_tcx(tcx),
|
||||
lint_level_specs: CodegenLintLevelSpecs::from_tcx(tcx),
|
||||
metadata_symbol: exported_symbols::metadata_symbol_name(tcx),
|
||||
each_linked_rlib_file_for_lto: Default::default(),
|
||||
exported_symbols_for_lto: Default::default(),
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
use rustc_macros::{Decodable, Encodable};
|
||||
use rustc_metadata::EncodedMetadata;
|
||||
use rustc_middle::dep_graph::WorkProduct;
|
||||
use rustc_middle::lint::LevelAndSource;
|
||||
use rustc_middle::lint::LevelSpec;
|
||||
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
|
||||
use rustc_middle::middle::dependency_format::Dependencies;
|
||||
use rustc_middle::middle::exported_symbols::SymbolExportKind;
|
||||
@@ -223,7 +223,7 @@ pub struct CrateInfo {
|
||||
pub dependency_formats: Arc<Dependencies>,
|
||||
pub windows_subsystem: Option<WindowsSubsystemKind>,
|
||||
pub natvis_debugger_visualizers: BTreeSet<DebuggerVisualizerFile>,
|
||||
pub lint_levels: CodegenLintLevels,
|
||||
pub lint_level_specs: CodegenLintLevelSpecs,
|
||||
pub metadata_symbol: String,
|
||||
pub each_linked_rlib_file_for_lto: Vec<PathBuf>,
|
||||
pub exported_symbols_for_lto: Vec<String>,
|
||||
@@ -341,16 +341,16 @@ pub fn deserialize_rlink(
|
||||
/// solely from the `.rlink` file. `Lint`s are defined too early to be encodeable.
|
||||
/// Instead, encode exactly the information we need.
|
||||
#[derive(Copy, Clone, Debug, Encodable, Decodable)]
|
||||
pub struct CodegenLintLevels {
|
||||
linker_messages: LevelAndSource,
|
||||
linker_info: LevelAndSource,
|
||||
pub struct CodegenLintLevelSpecs {
|
||||
linker_messages: LevelSpec,
|
||||
linker_info: LevelSpec,
|
||||
}
|
||||
|
||||
impl CodegenLintLevels {
|
||||
impl CodegenLintLevelSpecs {
|
||||
pub fn from_tcx(tcx: TyCtxt<'_>) -> Self {
|
||||
Self {
|
||||
linker_messages: tcx.lint_level_at_node(LINKER_MESSAGES, CRATE_HIR_ID),
|
||||
linker_info: tcx.lint_level_at_node(LINKER_INFO, CRATE_HIR_ID),
|
||||
linker_messages: tcx.lint_level_spec_at_node(LINKER_MESSAGES, CRATE_HIR_ID),
|
||||
linker_info: tcx.lint_level_spec_at_node(LINKER_INFO, CRATE_HIR_ID),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -735,11 +735,11 @@ fn increment_const_eval_counter(ecx: &mut InterpCx<'tcx, Self>) -> InterpResult<
|
||||
let hir_id = ecx.machine.best_lint_scope(*ecx.tcx);
|
||||
let is_error = ecx
|
||||
.tcx
|
||||
.lint_level_at_node(
|
||||
.lint_level_spec_at_node(
|
||||
rustc_session::lint::builtin::LONG_RUNNING_CONST_EVAL,
|
||||
hir_id,
|
||||
)
|
||||
.level
|
||||
.level()
|
||||
.is_error();
|
||||
let span = ecx.cur_span();
|
||||
ecx.tcx.emit_node_span_lint(
|
||||
|
||||
@@ -714,7 +714,7 @@ fn print_crate_info(
|
||||
let lint_store = crate::unerased_lint_store(sess);
|
||||
let features = rustc_expand::config::features(sess, attrs, crate_name);
|
||||
let registered_tools = rustc_resolve::registered_tools_ast(sess.dcx(), attrs, sess);
|
||||
let lint_levels = rustc_lint::LintLevelsBuilder::crate_root(
|
||||
let builder = rustc_lint::LintLevelsBuilder::crate_root(
|
||||
sess,
|
||||
&features,
|
||||
true,
|
||||
@@ -729,7 +729,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).level;
|
||||
let level = builder.lint_level_spec(lint).level();
|
||||
println_info!("{}={}", lint.name_lower(), level.as_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2415,11 +2415,8 @@ fn should_do_rust_2021_incompatible_closure_captures_analysis(
|
||||
return false;
|
||||
}
|
||||
|
||||
let level = tcx
|
||||
.lint_level_at_node(lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, closure_id)
|
||||
.level;
|
||||
|
||||
!matches!(level, lint::Level::Allow)
|
||||
!tcx.lint_level_spec_at_node(lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, closure_id)
|
||||
.is_allow()
|
||||
}
|
||||
|
||||
/// Return a two string tuple (s1, s2)
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
use rustc_hir::intravisit::FnKind as HirFnKind;
|
||||
use rustc_hir::{self as hir, Body, FnDecl, ImplItemImplKind, PatKind, PredicateOrigin, find_attr};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::lint::LevelAndSource;
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{
|
||||
@@ -61,7 +60,8 @@
|
||||
BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment,
|
||||
BuiltinUnusedDocCommentSub, BuiltinWhileTrue, EqInternalMethodImplemented, InvalidAsmLabel,
|
||||
};
|
||||
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext};
|
||||
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
|
||||
|
||||
declare_lint! {
|
||||
/// The `while_true` lint detects `while true { }`.
|
||||
///
|
||||
@@ -695,9 +695,7 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
|
||||
}
|
||||
|
||||
// Avoid listing trait impls if the trait is allowed.
|
||||
let LevelAndSource { level, .. } =
|
||||
cx.tcx.lint_level_at_node(MISSING_DEBUG_IMPLEMENTATIONS, item.hir_id());
|
||||
if level == Level::Allow {
|
||||
if cx.tcx.lint_level_spec_at_node(MISSING_DEBUG_IMPLEMENTATIONS, item.hir_id()).is_allow() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
|
||||
use rustc_hir::{Pat, PatKind};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::lint::LevelAndSource;
|
||||
use rustc_middle::lint::LevelSpec;
|
||||
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};
|
||||
@@ -537,8 +537,8 @@ fn emit_span_lint<S: Into<MultiSpan>>(
|
||||
self.opt_span_lint(lint, Some(span), decorator);
|
||||
}
|
||||
|
||||
/// This returns the lint level for the given lint at the current location.
|
||||
fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource;
|
||||
/// This returns the lint level spec for the given lint at the current location.
|
||||
fn get_lint_level_spec(&self, lint: &'static Lint) -> LevelSpec;
|
||||
|
||||
/// This function can be used to manually fulfill an expectation. This can
|
||||
/// be used for lints which contain several spans, and should be suppressed,
|
||||
@@ -604,8 +604,8 @@ fn opt_span_lint<S: Into<MultiSpan>>(
|
||||
}
|
||||
}
|
||||
|
||||
fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource {
|
||||
self.tcx.lint_level_at_node(lint, self.last_node_with_lint_attrs)
|
||||
fn get_lint_level_spec(&self, lint: &'static Lint) -> LevelSpec {
|
||||
self.tcx.lint_level_spec_at_node(lint, self.last_node_with_lint_attrs)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -624,8 +624,8 @@ fn opt_span_lint<S: Into<MultiSpan>>(
|
||||
self.builder.opt_span_lint(lint, span.map(|s| s.into()), decorator)
|
||||
}
|
||||
|
||||
fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource {
|
||||
self.builder.lint_level(lint)
|
||||
fn get_lint_level_spec(&self, lint: &'static Lint) -> LevelSpec {
|
||||
self.builder.lint_level_spec(lint)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,11 +9,10 @@
|
||||
use rustc_hir::HirId;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::lint::{
|
||||
LevelAndSource, LintExpectation, LintLevelSource, ShallowLintLevelMap, emit_lint_base,
|
||||
reveal_actual_level,
|
||||
LevelSpec, LintExpectation, LintLevelSource, ShallowLintLevelMap, emit_lint_base,
|
||||
reveal_actual_level_spec,
|
||||
};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{RegisteredTools, TyCtxt};
|
||||
@@ -65,9 +64,9 @@ struct LintStackIndex {
|
||||
/// to find the specifications for a given lint.
|
||||
#[derive(Debug)]
|
||||
struct LintSet {
|
||||
// -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which
|
||||
// -A,-W,-D flags, a `Symbol` for the flag itself and `LevelSpec` for which
|
||||
// flag.
|
||||
specs: FxIndexMap<LintId, LevelAndSource>,
|
||||
specs: FxIndexMap<LintId, LevelSpec>,
|
||||
parent: LintStackIndex,
|
||||
}
|
||||
|
||||
@@ -76,32 +75,34 @@ fn new() -> Self {
|
||||
LintLevelSets { list: IndexVec::new() }
|
||||
}
|
||||
|
||||
fn get_lint_level(
|
||||
fn get_lint_level_spec(
|
||||
&self,
|
||||
lint: &'static Lint,
|
||||
idx: LintStackIndex,
|
||||
aux: Option<&FxIndexMap<LintId, LevelAndSource>>,
|
||||
aux: Option<&FxIndexMap<LintId, LevelSpec>>,
|
||||
sess: &Session,
|
||||
) -> LevelAndSource {
|
||||
reveal_actual_level(sess, LintId::of(lint), |id| self.raw_lint_id_level(id, idx, aux))
|
||||
) -> LevelSpec {
|
||||
reveal_actual_level_spec(sess, LintId::of(lint), |id| {
|
||||
self.raw_lint_level_spec(id, idx, aux)
|
||||
})
|
||||
}
|
||||
|
||||
fn raw_lint_id_level(
|
||||
fn raw_lint_level_spec(
|
||||
&self,
|
||||
id: LintId,
|
||||
mut idx: LintStackIndex,
|
||||
aux: Option<&FxIndexMap<LintId, LevelAndSource>>,
|
||||
) -> Option<LevelAndSource> {
|
||||
aux: Option<&FxIndexMap<LintId, LevelSpec>>,
|
||||
) -> Option<LevelSpec> {
|
||||
if let Some(specs) = aux
|
||||
&& let Some(level) = specs.get(&id)
|
||||
&& let Some(level_spec) = specs.get(&id)
|
||||
{
|
||||
return Some(*level);
|
||||
return Some(*level_spec);
|
||||
}
|
||||
|
||||
loop {
|
||||
let LintSet { ref specs, parent } = self.list[idx];
|
||||
if let Some(level) = specs.get(&id) {
|
||||
return Some(*level);
|
||||
if let Some(level_spec) = specs.get(&id) {
|
||||
return Some(*level_spec);
|
||||
}
|
||||
if idx == COMMAND_LINE {
|
||||
return None;
|
||||
@@ -125,11 +126,11 @@ fn lints_that_dont_need_to_run(tcx: TyCtxt<'_>, (): ()) -> UnordSet<LintId> {
|
||||
!has_future_breakage && !lint.eval_always
|
||||
})
|
||||
.filter(|lint| {
|
||||
let lint_level =
|
||||
root_map.lint_level_id_at_node(tcx, LintId::of(lint), hir::CRATE_HIR_ID);
|
||||
let level_spec =
|
||||
root_map.lint_level_spec_at_node(tcx, LintId::of(lint), hir::CRATE_HIR_ID);
|
||||
// Only include lints that are allowed at crate root or by default.
|
||||
matches!(lint_level.level, Level::Allow)
|
||||
|| (matches!(lint_level.src, LintLevelSource::Default)
|
||||
level_spec.is_allow()
|
||||
|| (matches!(level_spec.src, LintLevelSource::Default)
|
||||
&& lint.default_level(tcx.sess.edition()) == Level::Allow)
|
||||
})
|
||||
.map(|lint| LintId::of(*lint))
|
||||
@@ -140,8 +141,8 @@ fn lints_that_dont_need_to_run(tcx: TyCtxt<'_>, (): ()) -> UnordSet<LintId> {
|
||||
|
||||
// All lints that appear with a non-allow level must be run.
|
||||
for (_, specs) in map.specs.iter() {
|
||||
for (lint, level_and_source) in specs.iter() {
|
||||
if !matches!(level_and_source.level, Level::Allow) {
|
||||
for (lint, level_spec) in specs.iter() {
|
||||
if !level_spec.is_allow() {
|
||||
dont_need_to_run.remove(lint);
|
||||
}
|
||||
}
|
||||
@@ -212,23 +213,23 @@ pub struct TopDown {
|
||||
}
|
||||
|
||||
pub trait LintLevelsProvider {
|
||||
fn current_specs(&self) -> &FxIndexMap<LintId, LevelAndSource>;
|
||||
fn insert(&mut self, id: LintId, lvl: LevelAndSource);
|
||||
fn get_lint_level(&self, lint: &'static Lint, sess: &Session) -> LevelAndSource;
|
||||
fn current_specs(&self) -> &FxIndexMap<LintId, LevelSpec>;
|
||||
fn insert(&mut self, id: LintId, level_spec: LevelSpec);
|
||||
fn get_lint_level_spec(&self, lint: &'static Lint, sess: &Session) -> LevelSpec;
|
||||
fn push_expectation(&mut self, id: LintExpectationId, expectation: LintExpectation);
|
||||
}
|
||||
|
||||
impl LintLevelsProvider for TopDown {
|
||||
fn current_specs(&self) -> &FxIndexMap<LintId, LevelAndSource> {
|
||||
fn current_specs(&self) -> &FxIndexMap<LintId, LevelSpec> {
|
||||
&self.sets.list[self.cur].specs
|
||||
}
|
||||
|
||||
fn insert(&mut self, id: LintId, lvl: LevelAndSource) {
|
||||
self.sets.list[self.cur].specs.insert(id, lvl);
|
||||
fn insert(&mut self, id: LintId, level_spec: LevelSpec) {
|
||||
self.sets.list[self.cur].specs.insert(id, level_spec);
|
||||
}
|
||||
|
||||
fn get_lint_level(&self, lint: &'static Lint, sess: &Session) -> LevelAndSource {
|
||||
self.sets.get_lint_level(lint, self.cur, Some(self.current_specs()), sess)
|
||||
fn get_lint_level_spec(&self, lint: &'static Lint, sess: &Session) -> LevelSpec {
|
||||
self.sets.get_lint_level_spec(lint, self.cur, Some(self.current_specs()), sess)
|
||||
}
|
||||
|
||||
fn push_expectation(&mut self, _: LintExpectationId, _: LintExpectation) {}
|
||||
@@ -239,19 +240,19 @@ struct LintLevelQueryMap<'tcx> {
|
||||
cur: HirId,
|
||||
specs: ShallowLintLevelMap,
|
||||
/// Empty hash map to simplify code.
|
||||
empty: FxIndexMap<LintId, LevelAndSource>,
|
||||
empty: FxIndexMap<LintId, LevelSpec>,
|
||||
attrs: &'tcx hir::AttributeMap<'tcx>,
|
||||
}
|
||||
|
||||
impl LintLevelsProvider for LintLevelQueryMap<'_> {
|
||||
fn current_specs(&self) -> &FxIndexMap<LintId, LevelAndSource> {
|
||||
fn current_specs(&self) -> &FxIndexMap<LintId, LevelSpec> {
|
||||
self.specs.specs.get(&self.cur.local_id).unwrap_or(&self.empty)
|
||||
}
|
||||
fn insert(&mut self, id: LintId, lvl: LevelAndSource) {
|
||||
self.specs.specs.get_mut_or_insert_default(self.cur.local_id).insert(id, lvl);
|
||||
fn insert(&mut self, id: LintId, level_spec: LevelSpec) {
|
||||
self.specs.specs.get_mut_or_insert_default(self.cur.local_id).insert(id, level_spec);
|
||||
}
|
||||
fn get_lint_level(&self, lint: &'static Lint, _: &Session) -> LevelAndSource {
|
||||
self.specs.lint_level_id_at_node(self.tcx, LintId::of(lint), self.cur)
|
||||
fn get_lint_level_spec(&self, lint: &'static Lint, _: &Session) -> LevelSpec {
|
||||
self.specs.lint_level_spec_at_node(self.tcx, LintId::of(lint), self.cur)
|
||||
}
|
||||
fn push_expectation(&mut self, id: LintExpectationId, expectation: LintExpectation) {
|
||||
self.specs.expectations.push((id, expectation))
|
||||
@@ -455,12 +456,12 @@ pub(crate) fn features(&self) -> &Features {
|
||||
self.features
|
||||
}
|
||||
|
||||
fn current_specs(&self) -> &FxIndexMap<LintId, LevelAndSource> {
|
||||
fn current_specs(&self) -> &FxIndexMap<LintId, LevelSpec> {
|
||||
self.provider.current_specs()
|
||||
}
|
||||
|
||||
fn insert(&mut self, id: LintId, lvl: LevelAndSource) {
|
||||
self.provider.insert(id, lvl)
|
||||
fn insert(&mut self, id: LintId, level_spec: LevelSpec) {
|
||||
self.provider.insert(id, level_spec)
|
||||
}
|
||||
|
||||
fn add_command_line(&mut self) {
|
||||
@@ -519,26 +520,31 @@ fn add_command_line(&mut self) {
|
||||
};
|
||||
for &id in ids {
|
||||
// ForceWarn and Forbid cannot be overridden
|
||||
if let Some(LevelAndSource { level: Level::ForceWarn | Level::Forbid, .. }) =
|
||||
self.current_specs().get(&id)
|
||||
if let Some(level_spec) = self.current_specs().get(&id)
|
||||
&& matches!(level_spec.level(), Level::ForceWarn | Level::Forbid)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if self.check_gated_lint(id, DUMMY_SP, true) {
|
||||
let src = LintLevelSource::CommandLine(lint_flag_val, level);
|
||||
self.insert(id, LevelAndSource { level, lint_id: None, src });
|
||||
self.insert(id, LevelSpec::new(level, None, src));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempts to insert the `id` to `level_src` map entry. If unsuccessful
|
||||
/// Attempts to insert the `id` to `LevelSpec` 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, lint_id, src }: LevelAndSource) {
|
||||
let LevelAndSource { level: old_level, src: old_src, .. } =
|
||||
self.provider.get_lint_level(id.lint, self.sess);
|
||||
fn insert_spec(&mut self, id: LintId, level_spec: LevelSpec) {
|
||||
let level = level_spec.level();
|
||||
let lint_id = level_spec.lint_id();
|
||||
let src = level_spec.src;
|
||||
|
||||
let old_level_spec = self.provider.get_lint_level_spec(id.lint, self.sess);
|
||||
let old_level = old_level_spec.level();
|
||||
let old_src = old_level_spec.src;
|
||||
|
||||
// Setting to a non-forbid level is an error if the lint previously had
|
||||
// a forbid level. Note that this is not necessarily true even with a
|
||||
@@ -621,15 +627,14 @@ fn insert_spec(&mut self, id: LintId, LevelAndSource { level, lint_id, src }: Le
|
||||
match (old_level, level) {
|
||||
// If the new level is an expectation store it in `ForceWarn`
|
||||
(Level::ForceWarn, Level::Expect) => {
|
||||
self.insert(id, LevelAndSource { level: Level::ForceWarn, lint_id, src: old_src })
|
||||
self.insert(id, LevelSpec::new(Level::ForceWarn, lint_id, old_src))
|
||||
}
|
||||
// Keep `ForceWarn` level but drop the expectation
|
||||
(Level::ForceWarn, _) => self.insert(
|
||||
id,
|
||||
LevelAndSource { level: Level::ForceWarn, lint_id: None, src: old_src },
|
||||
),
|
||||
(Level::ForceWarn, _) => {
|
||||
self.insert(id, LevelSpec::new(Level::ForceWarn, None, old_src))
|
||||
}
|
||||
// Set the lint level as normal
|
||||
_ => self.insert(id, LevelAndSource { level, lint_id, src }),
|
||||
_ => self.insert(id, LevelSpec::new(level, lint_id, src)),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -644,11 +649,7 @@ fn add(
|
||||
if attr.is_automatically_derived_attr() {
|
||||
self.insert(
|
||||
LintId::of(SINGLE_USE_LIFETIMES),
|
||||
LevelAndSource {
|
||||
level: Level::Allow,
|
||||
lint_id: None,
|
||||
src: LintLevelSource::Default,
|
||||
},
|
||||
LevelSpec::new(Level::Allow, None, LintLevelSource::Default),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
@@ -657,34 +658,28 @@ fn add(
|
||||
if attr.is_doc_hidden() {
|
||||
self.insert(
|
||||
LintId::of(MISSING_DOCS),
|
||||
LevelAndSource {
|
||||
level: Level::Allow,
|
||||
lint_id: None,
|
||||
src: LintLevelSource::Default,
|
||||
},
|
||||
LevelSpec::new(Level::Allow, None, LintLevelSource::Default),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
let (level, lint_id) = match Level::from_attr(attr.name(), || attr.id()) {
|
||||
let (level, lint_id) = match Level::from_opt_symbol(attr.name()) {
|
||||
None => continue,
|
||||
// This is the only lint level with a `LintExpectationId` that can be created from
|
||||
// an attribute.
|
||||
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")
|
||||
// `Expect` is the only lint level with a `LintExpectationId` that can be created
|
||||
// from an attribute.
|
||||
Some(Level::Expect) => {
|
||||
let id = if let Some(hir_id) = source_hir_id {
|
||||
LintExpectationId::Stable {
|
||||
hir_id,
|
||||
attr_index: attr_index.try_into().unwrap(),
|
||||
lint_index: None,
|
||||
}
|
||||
} else {
|
||||
LintExpectationId::Unstable { attr_id: attr.id(), lint_index: None }
|
||||
};
|
||||
|
||||
let stable_id = LintExpectationId::Stable {
|
||||
hir_id,
|
||||
attr_index: attr_index.try_into().unwrap(),
|
||||
lint_index: None,
|
||||
};
|
||||
|
||||
(Level::Expect, Some(stable_id))
|
||||
(Level::Expect, Some(id))
|
||||
}
|
||||
Some((lvl, id)) => (lvl, id),
|
||||
Some(level) => (level, None),
|
||||
};
|
||||
|
||||
let Some(mut metas) = attr.meta_item_list() else { continue };
|
||||
@@ -876,7 +871,7 @@ fn add(
|
||||
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, lint_id, src });
|
||||
self.insert_spec(id, LevelSpec::new(level, lint_id, src));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -907,12 +902,13 @@ fn add(
|
||||
}
|
||||
|
||||
if self.lint_added_lints && !is_crate_node {
|
||||
for (id, &LevelAndSource { level, ref src, .. }) in self.current_specs().iter() {
|
||||
for (id, level_spec) in self.current_specs().iter() {
|
||||
if !id.lint.crate_level_only {
|
||||
continue;
|
||||
}
|
||||
|
||||
let LintLevelSource::Node { name: lint_attr_name, span: lint_attr_span, .. } = *src
|
||||
let LintLevelSource::Node { name: lint_attr_name, span: lint_attr_span, .. } =
|
||||
level_spec.src
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
@@ -920,7 +916,10 @@ fn add(
|
||||
self.emit_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
lint_attr_span.into(),
|
||||
IgnoredUnlessCrateSpecified { level: level.as_str(), name: lint_attr_name },
|
||||
IgnoredUnlessCrateSpecified {
|
||||
level: level_spec.level().as_str(),
|
||||
name: lint_attr_name,
|
||||
},
|
||||
);
|
||||
// don't set a separate error for every lint in the group
|
||||
break;
|
||||
@@ -975,11 +974,11 @@ fn into_diag(
|
||||
|
||||
if self.lint_added_lints {
|
||||
let lint = builtin::UNKNOWN_LINTS;
|
||||
let level = self.lint_level(builtin::UNKNOWN_LINTS);
|
||||
let level_spec = self.lint_level_spec(builtin::UNKNOWN_LINTS);
|
||||
emit_lint_base(
|
||||
self.sess,
|
||||
lint,
|
||||
level,
|
||||
level_spec,
|
||||
Some(span.into()),
|
||||
UnknownLint { sess: &self.sess, lint_id, feature, lint_from_cli },
|
||||
);
|
||||
@@ -989,8 +988,8 @@ fn into_diag(
|
||||
}
|
||||
|
||||
/// Find the lint level for a lint.
|
||||
pub fn lint_level(&self, lint: &'static Lint) -> LevelAndSource {
|
||||
self.provider.get_lint_level(lint, self.sess)
|
||||
pub fn lint_level_spec(&self, lint: &'static Lint) -> LevelSpec {
|
||||
self.provider.get_lint_level_spec(lint, self.sess)
|
||||
}
|
||||
|
||||
/// Used to emit a lint-related diagnostic based on the current state of
|
||||
@@ -1002,8 +1001,8 @@ pub(crate) fn opt_span_lint(
|
||||
span: Option<MultiSpan>,
|
||||
decorator: impl for<'a> Diagnostic<'a, ()>,
|
||||
) {
|
||||
let level = self.lint_level(lint);
|
||||
emit_lint_base(self.sess, lint, level, span, decorator)
|
||||
let level_spec = self.lint_level_spec(lint);
|
||||
emit_lint_base(self.sess, lint, level_spec, span, decorator)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
@@ -1013,14 +1012,14 @@ pub fn emit_span_lint(
|
||||
span: MultiSpan,
|
||||
decorator: impl for<'a> Diagnostic<'a, ()>,
|
||||
) {
|
||||
let level = self.lint_level(lint);
|
||||
emit_lint_base(self.sess, lint, level, Some(span), decorator);
|
||||
let level_spec = self.lint_level_spec(lint);
|
||||
emit_lint_base(self.sess, lint, level_spec, Some(span), decorator);
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn emit_lint(&self, lint: &'static Lint, decorator: impl for<'a> Diagnostic<'a, ()>) {
|
||||
let level = self.lint_level(lint);
|
||||
emit_lint_base(self.sess, lint, level, None, decorator);
|
||||
let level_spec = self.lint_level_spec(lint);
|
||||
emit_lint_base(self.sess, lint, level_spec, None, decorator);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -155,17 +155,14 @@ impl EarlyLintPass for NonAsciiIdents {
|
||||
fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use rustc_session::lint::Level;
|
||||
use rustc_span::Span;
|
||||
use unicode_security::GeneralSecurityProfile;
|
||||
|
||||
let check_non_ascii_idents = cx.builder.lint_level(NON_ASCII_IDENTS).level != Level::Allow;
|
||||
let check_uncommon_codepoints =
|
||||
cx.builder.lint_level(UNCOMMON_CODEPOINTS).level != Level::Allow;
|
||||
let check_confusable_idents =
|
||||
cx.builder.lint_level(CONFUSABLE_IDENTS).level != Level::Allow;
|
||||
let check_non_ascii_idents = !cx.builder.lint_level_spec(NON_ASCII_IDENTS).is_allow();
|
||||
let check_uncommon_codepoints = !cx.builder.lint_level_spec(UNCOMMON_CODEPOINTS).is_allow();
|
||||
let check_confusable_idents = !cx.builder.lint_level_spec(CONFUSABLE_IDENTS).is_allow();
|
||||
let check_mixed_script_confusables =
|
||||
cx.builder.lint_level(MIXED_SCRIPT_CONFUSABLES).level != Level::Allow;
|
||||
!cx.builder.lint_level_spec(MIXED_SCRIPT_CONFUSABLES).is_allow();
|
||||
|
||||
if !check_non_ascii_idents
|
||||
&& !check_uncommon_codepoints
|
||||
|
||||
@@ -118,13 +118,6 @@ pub fn is_stable(&self) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_lint_index(&self) -> Option<u16> {
|
||||
let (LintExpectationId::Unstable { lint_index, .. }
|
||||
| LintExpectationId::Stable { lint_index, .. }) = self;
|
||||
|
||||
*lint_index
|
||||
}
|
||||
|
||||
pub fn set_lint_index(&mut self, new_lint_index: Option<u16>) {
|
||||
let (LintExpectationId::Unstable { lint_index, .. }
|
||||
| LintExpectationId::Stable { lint_index, .. }) = self;
|
||||
@@ -215,34 +208,19 @@ pub fn from_str(x: &str) -> Option<Self> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts an `Attribute` to a level.
|
||||
pub fn from_attr(
|
||||
attr_name: Option<Symbol>,
|
||||
attr_id: impl Fn() -> AttrId,
|
||||
) -> Option<(Self, Option<LintExpectationId>)> {
|
||||
attr_name.and_then(|name| Self::from_symbol(name, || Some(attr_id())))
|
||||
/// Converts an `Option<Symbol>` to a level.
|
||||
pub fn from_opt_symbol(s: Option<Symbol>) -> Option<Self> {
|
||||
s.and_then(Self::from_symbol)
|
||||
}
|
||||
|
||||
/// Converts a `Symbol` to a level.
|
||||
pub fn from_symbol(
|
||||
s: Symbol,
|
||||
id: impl FnOnce() -> Option<AttrId>,
|
||||
) -> Option<(Self, Option<LintExpectationId>)> {
|
||||
pub fn from_symbol(s: Symbol) -> Option<Self> {
|
||||
match s {
|
||||
sym::allow => Some((Level::Allow, None)),
|
||||
sym::expect => {
|
||||
if let Some(attr_id) = id() {
|
||||
Some((
|
||||
Level::Expect,
|
||||
Some(LintExpectationId::Unstable { attr_id, lint_index: None }),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
sym::warn => Some((Level::Warn, None)),
|
||||
sym::deny => Some((Level::Deny, None)),
|
||||
sym::forbid => Some((Level::Forbid, None)),
|
||||
sym::allow => Some(Level::Allow),
|
||||
sym::expect => Some(Level::Expect),
|
||||
sym::warn => Some(Level::Warn),
|
||||
sym::deny => Some(Level::Deny),
|
||||
sym::forbid => Some(Level::Forbid),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,8 +328,11 @@ pub fn report_unused_deps(&self, tcx: TyCtxt<'_>) {
|
||||
return;
|
||||
}
|
||||
let level = tcx
|
||||
.lint_level_at_node(lint::builtin::UNUSED_CRATE_DEPENDENCIES, rustc_hir::CRATE_HIR_ID)
|
||||
.level;
|
||||
.lint_level_spec_at_node(
|
||||
lint::builtin::UNUSED_CRATE_DEPENDENCIES,
|
||||
rustc_hir::CRATE_HIR_ID,
|
||||
)
|
||||
.level();
|
||||
if level != lint::Level::Allow {
|
||||
let unused_externs =
|
||||
self.unused_externs.iter().map(|ident| ident.to_ident_string()).collect::<Vec<_>>();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::cmp;
|
||||
use std::cmp::min;
|
||||
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::sorted_map::SortedMap;
|
||||
@@ -53,14 +53,59 @@ pub fn span(&self) -> Span {
|
||||
}
|
||||
}
|
||||
|
||||
/// Convenience helper for moving things around together that frequently are paired
|
||||
/// Convenience helper for things that are frequently used together.
|
||||
#[derive(Copy, Clone, Debug, StableHash, Encodable, Decodable)]
|
||||
pub struct LevelAndSource {
|
||||
pub level: Level,
|
||||
pub lint_id: Option<LintExpectationId>,
|
||||
pub struct LevelSpec {
|
||||
// This field *must* be private. It must be set in tandem with `lint_id`, only in
|
||||
// `LevelSpec::new`, because only certain `level`/`lint_id` combinations are valid. See
|
||||
// `LevelSpec::new` for those combinations.
|
||||
//
|
||||
// If you are thinking right now that `level` and `lint_id` should be combined into a single
|
||||
// type that excludes the invalid combinations, that's a reasonable thought, but in practice
|
||||
// it's painful because `level` needs to be used by itself, without `lint_id`, in many places.
|
||||
// Making the fields private prevents invalid combinations while retaining the flexibility of
|
||||
// two separate fields.
|
||||
level: Level,
|
||||
|
||||
// This field *must* be private. See the comment on `level`.
|
||||
lint_id: Option<LintExpectationId>,
|
||||
|
||||
pub src: LintLevelSource,
|
||||
}
|
||||
|
||||
impl LevelSpec {
|
||||
// Panics if an invalid `level`/`lint_id` combination is given.
|
||||
pub fn new(
|
||||
level: Level,
|
||||
lint_id: Option<LintExpectationId>,
|
||||
src: LintLevelSource,
|
||||
) -> LevelSpec {
|
||||
match (level, lint_id) {
|
||||
(Level::Allow | Level::Warn | Level::Deny | Level::Forbid, None) => {}
|
||||
(Level::Expect, Some(_)) => {}
|
||||
(Level::ForceWarn, _) => {}
|
||||
_ => panic!("invalid level/lint_id combination"),
|
||||
}
|
||||
LevelSpec { level, lint_id, src }
|
||||
}
|
||||
|
||||
pub fn level(self) -> Level {
|
||||
self.level
|
||||
}
|
||||
|
||||
pub fn is_allow(self) -> bool {
|
||||
self.level == Level::Allow
|
||||
}
|
||||
|
||||
pub fn is_expect(self) -> bool {
|
||||
self.level == Level::Expect
|
||||
}
|
||||
|
||||
pub fn lint_id(self) -> Option<LintExpectationId> {
|
||||
self.lint_id
|
||||
}
|
||||
}
|
||||
|
||||
/// Return type for the `shallow_lint_levels_on` query.
|
||||
///
|
||||
/// This map represents the set of allowed lints and allowance levels given
|
||||
@@ -68,32 +113,32 @@ pub struct LevelAndSource {
|
||||
#[derive(Default, Debug, StableHash)]
|
||||
pub struct ShallowLintLevelMap {
|
||||
pub expectations: Vec<(LintExpectationId, LintExpectation)>,
|
||||
pub specs: SortedMap<ItemLocalId, FxIndexMap<LintId, LevelAndSource>>,
|
||||
pub specs: SortedMap<ItemLocalId, FxIndexMap<LintId, LevelSpec>>,
|
||||
}
|
||||
|
||||
/// Verify the effect of special annotations: `warnings` lint level and lint caps.
|
||||
///
|
||||
/// The return of this function is suitable for diagnostics.
|
||||
pub fn reveal_actual_level(
|
||||
pub fn reveal_actual_level_spec(
|
||||
sess: &Session,
|
||||
lint: LintId,
|
||||
probe_for_lint_level: impl Fn(LintId) -> Option<LevelAndSource>,
|
||||
) -> LevelAndSource {
|
||||
let level = probe_for_lint_level(lint);
|
||||
probe_for_lint_level_spec: impl Fn(LintId) -> Option<LevelSpec>,
|
||||
) -> LevelSpec {
|
||||
let level_spec = probe_for_lint_level_spec(lint);
|
||||
|
||||
// If `level` is none then we actually assume the default level for this lint.
|
||||
let mut level = level.unwrap_or_else(|| LevelAndSource {
|
||||
level: lint.lint.default_level(sess.edition()),
|
||||
lint_id: None,
|
||||
src: LintLevelSource::Default,
|
||||
let mut level_spec = level_spec.unwrap_or_else(|| {
|
||||
LevelSpec::new(lint.lint.default_level(sess.edition()), None, LintLevelSource::Default)
|
||||
});
|
||||
|
||||
// If we're about to issue a warning, check at the last minute for any
|
||||
// directives against the `warnings` lint group. If, for example, there's an
|
||||
// `allow(warnings)` in scope then we want to respect that instead.
|
||||
if level.level == Level::Warn {
|
||||
if let Some(configured_level) = probe_for_lint_level(LintId::of(builtin::WARNINGS)) {
|
||||
let respect_warnings_lint_group = match configured_level.level {
|
||||
if level_spec.level == Level::Warn {
|
||||
if let Some(configured_level_spec) =
|
||||
probe_for_lint_level_spec(LintId::of(builtin::WARNINGS))
|
||||
{
|
||||
let respect_warnings_lint_group = match configured_level_spec.level {
|
||||
// -Wwarnings is a no-op.
|
||||
Level::Warn => false,
|
||||
// Some warnings cannot be denied from the `warnings` lint group, only individually.
|
||||
@@ -105,48 +150,46 @@ pub fn reveal_actual_level(
|
||||
Level::Expect => true,
|
||||
Level::ForceWarn => {
|
||||
sess.dcx().span_delayed_bug(
|
||||
configured_level.src.span(),
|
||||
configured_level_spec.src.span(),
|
||||
"cannot --force-warn the `warnings` lint group",
|
||||
);
|
||||
false
|
||||
}
|
||||
};
|
||||
if respect_warnings_lint_group {
|
||||
level = configured_level;
|
||||
level_spec = configured_level_spec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that we never exceed the `--cap-lints` argument unless the source is a --force-warn
|
||||
level.level = if let LintLevelSource::CommandLine(_, Level::ForceWarn) = level.src {
|
||||
level.level
|
||||
} else {
|
||||
cmp::min(level.level, sess.opts.lint_cap.unwrap_or(Level::Forbid))
|
||||
if !matches!(level_spec.src, LintLevelSource::CommandLine(_, Level::ForceWarn)) {
|
||||
level_spec.level = min(level_spec.level, sess.opts.lint_cap.unwrap_or(Level::Forbid));
|
||||
};
|
||||
|
||||
// Ensure that we never exceed driver level.
|
||||
if let Some(driver_level) = sess.driver_lint_caps.get(&lint) {
|
||||
// Ensure that we never exceed driver level.
|
||||
level.level = cmp::min(level.level, *driver_level);
|
||||
level_spec.level = min(level_spec.level, *driver_level);
|
||||
}
|
||||
|
||||
level
|
||||
level_spec
|
||||
}
|
||||
|
||||
impl ShallowLintLevelMap {
|
||||
/// Perform a deep probe in the HIR tree looking for the actual level for the lint.
|
||||
/// This lint level is not usable for diagnostics, it needs to be corrected by
|
||||
/// Perform a deep probe in the HIR tree looking for the actual level spec for the lint.
|
||||
/// This lint level spec is not usable for diagnostics, it needs to be corrected by
|
||||
/// `reveal_actual_level` beforehand.
|
||||
#[instrument(level = "trace", skip(self, tcx), ret)]
|
||||
fn probe_for_lint_level(
|
||||
fn probe_for_lint_level_spec(
|
||||
&self,
|
||||
tcx: TyCtxt<'_>,
|
||||
id: LintId,
|
||||
start: HirId,
|
||||
) -> Option<LevelAndSource> {
|
||||
) -> Option<LevelSpec> {
|
||||
if let Some(map) = self.specs.get(&start.local_id)
|
||||
&& let Some(level) = map.get(&id)
|
||||
&& let Some(level_spec) = map.get(&id)
|
||||
{
|
||||
return Some(*level);
|
||||
return Some(*level_spec);
|
||||
}
|
||||
|
||||
let mut owner = start.owner;
|
||||
@@ -158,31 +201,28 @@ fn probe_for_lint_level(
|
||||
specs = &tcx.shallow_lint_levels_on(owner).specs;
|
||||
}
|
||||
if let Some(map) = specs.get(&parent.local_id)
|
||||
&& let Some(level) = map.get(&id)
|
||||
&& let Some(level_spec) = map.get(&id)
|
||||
{
|
||||
return Some(*level);
|
||||
return Some(*level_spec);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Fetch and return the user-visible lint level for the given lint at the given HirId.
|
||||
/// Fetch and return the user-visible lint level spec for the given lint at the given HirId.
|
||||
#[instrument(level = "trace", skip(self, tcx), ret)]
|
||||
pub fn lint_level_id_at_node(
|
||||
&self,
|
||||
tcx: TyCtxt<'_>,
|
||||
lint: LintId,
|
||||
cur: HirId,
|
||||
) -> LevelAndSource {
|
||||
reveal_actual_level(tcx.sess, lint, |lint| self.probe_for_lint_level(tcx, lint, cur))
|
||||
pub fn lint_level_spec_at_node(&self, tcx: TyCtxt<'_>, lint: LintId, cur: HirId) -> LevelSpec {
|
||||
reveal_actual_level_spec(tcx.sess, lint, |lint| {
|
||||
self.probe_for_lint_level_spec(tcx, lint, cur)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TyCtxt<'_> {
|
||||
/// Fetch and return the user-visible lint level for the given lint at the given HirId.
|
||||
pub fn lint_level_at_node(self, lint: &'static Lint, id: HirId) -> LevelAndSource {
|
||||
self.shallow_lint_levels_on(id.owner).lint_level_id_at_node(self, LintId::of(lint), id)
|
||||
/// Fetch and return the user-visible lint level spec for the given lint at the given HirId.
|
||||
pub fn lint_level_spec_at_node(self, lint: &'static Lint, id: HirId) -> LevelSpec {
|
||||
self.shallow_lint_levels_on(id.owner).lint_level_spec_at_node(self, LintId::of(lint), id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,7 +362,7 @@ fn explain_lint_level_source(
|
||||
pub fn emit_lint_base<'a, D: Diagnostic<'a, ()> + 'a>(
|
||||
sess: &'a Session,
|
||||
lint: &'static Lint,
|
||||
level: LevelAndSource,
|
||||
level_spec: LevelSpec,
|
||||
span: Option<MultiSpan>,
|
||||
decorate: D,
|
||||
) {
|
||||
@@ -332,13 +372,13 @@ pub fn emit_lint_base<'a, D: Diagnostic<'a, ()> + 'a>(
|
||||
fn emit_lint_base_impl<'a>(
|
||||
sess: &'a Session,
|
||||
lint: &'static Lint,
|
||||
level: LevelAndSource,
|
||||
level_spec: LevelSpec,
|
||||
span: Option<MultiSpan>,
|
||||
decorate: Box<
|
||||
dyn FnOnce(rustc_errors::DiagCtxtHandle<'a>, rustc_errors::Level) -> Diag<'a, ()> + 'a,
|
||||
>,
|
||||
) {
|
||||
let LevelAndSource { level, lint_id, src } = level;
|
||||
let LevelSpec { level, lint_id, src } = level_spec;
|
||||
|
||||
// Check for future incompatibility lints and issue a stronger warning.
|
||||
let future_incompatible = lint.future_incompatible;
|
||||
@@ -516,7 +556,7 @@ fn emit_lint_base_impl<'a>(
|
||||
emit_lint_base_impl(
|
||||
sess,
|
||||
lint,
|
||||
level,
|
||||
level_spec,
|
||||
span,
|
||||
Box::new(move |dcx, level| decorate.into_diag(dcx, level)),
|
||||
);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
use rustc_session::Session;
|
||||
use rustc_session::errors::feature_err_issue;
|
||||
use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE};
|
||||
use rustc_session::lint::{DeprecatedSinceKind, Level, Lint};
|
||||
use rustc_session::lint::{DeprecatedSinceKind, Lint};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use tracing::debug;
|
||||
|
||||
@@ -234,7 +234,7 @@ fn late_report_deprecation(
|
||||
// Calculating message for lint involves calling `self.def_path_str`,
|
||||
// which will by default invoke the expensive `visible_parent_map` query.
|
||||
// Skip all that work if the lint is allowed anyway.
|
||||
if tcx.lint_level_at_node(lint, hir_id).level == Level::Allow {
|
||||
if tcx.lint_level_spec_at_node(lint, hir_id).is_allow() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -2459,8 +2459,8 @@ pub fn emit_node_span_lint(
|
||||
span: impl Into<MultiSpan>,
|
||||
decorator: impl for<'a> Diagnostic<'a, ()>,
|
||||
) {
|
||||
let level = self.lint_level_at_node(lint, hir_id);
|
||||
emit_lint_base(self.sess, lint, level, Some(span.into()), decorator)
|
||||
let level_spec = self.lint_level_spec_at_node(lint, hir_id);
|
||||
emit_lint_base(self.sess, lint, level_spec, Some(span.into()), decorator)
|
||||
}
|
||||
|
||||
/// Find the appropriate span where `use` and outer attributes can be inserted at.
|
||||
@@ -2502,8 +2502,8 @@ pub fn emit_node_lint(
|
||||
id: HirId,
|
||||
decorator: impl for<'a> Diagnostic<'a, ()>,
|
||||
) {
|
||||
let level = self.lint_level_at_node(lint, id);
|
||||
emit_lint_base(self.sess, lint, level, None, decorator);
|
||||
let level_spec = self.lint_level_spec_at_node(lint, id);
|
||||
emit_lint_base(self.sess, lint, level_spec, None, decorator);
|
||||
}
|
||||
|
||||
pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx [TraitCandidate<'tcx>]> {
|
||||
|
||||
@@ -1302,7 +1302,7 @@ fn maybe_lint_level_root_bounded(&mut self, orig_id: HirId) -> HirId {
|
||||
.tcx
|
||||
.hir_attrs(id)
|
||||
.iter()
|
||||
.any(|attr| Level::from_attr(attr.name(), || attr.id()).is_some())
|
||||
.any(|attr| Level::from_opt_symbol(attr.name()).is_some())
|
||||
{
|
||||
// This is a rare case. It's for a node path that doesn't reach the root due to an
|
||||
// intervening lint level attribute. This result doesn't get cached.
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
use rustc_middle::thir::*;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_session::lint::Level;
|
||||
use rustc_session::lint::builtin::{DEPRECATED_SAFE_2024, UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
|
||||
use rustc_span::def_id::{DefId, LocalDefId};
|
||||
use rustc_span::{Span, Symbol};
|
||||
@@ -175,7 +174,7 @@ fn warn_unused_unsafe(
|
||||
|
||||
/// Whether the `unsafe_op_in_unsafe_fn` lint is `allow`ed at the current HIR node.
|
||||
fn unsafe_op_in_unsafe_fn_allowed(&self) -> bool {
|
||||
self.tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, self.hir_context).level == Level::Allow
|
||||
self.tcx.lint_level_spec_at_node(UNSAFE_OP_IN_UNSAFE_FN, self.hir_context).is_allow()
|
||||
}
|
||||
|
||||
/// Handle closures/coroutines/inline-consts, which is unsafecked with their parent body.
|
||||
@@ -233,10 +232,7 @@ fn visit_block(&mut self, block: &'a Block) {
|
||||
});
|
||||
}
|
||||
BlockSafety::ExplicitUnsafe(hir_id) => {
|
||||
let used = matches!(
|
||||
self.tcx.lint_level_at_node(UNUSED_UNSAFE, hir_id).level,
|
||||
Level::Allow
|
||||
);
|
||||
let used = self.tcx.lint_level_spec_at_node(UNUSED_UNSAFE, hir_id).is_allow();
|
||||
self.in_safety_context(
|
||||
SafetyContext::UnsafeBlock {
|
||||
span: block.span,
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, MatchSource};
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_lint_defs::Level;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::thir::visit::Visitor;
|
||||
use rustc_middle::thir::*;
|
||||
@@ -1026,7 +1025,7 @@ fn find_fallback_pattern_typo<'tcx>(
|
||||
pat: &Pat<'tcx>,
|
||||
lint: &mut UnreachablePattern<'_>,
|
||||
) {
|
||||
if let Level::Allow = cx.tcx.lint_level_at_node(UNREACHABLE_PATTERNS, hir_id).level {
|
||||
if cx.tcx.lint_level_spec_at_node(UNREACHABLE_PATTERNS, hir_id).is_allow() {
|
||||
// This is because we use `with_no_trimmed_paths` later, so if we never emit the lint we'd
|
||||
// ICE. At the same time, we don't really need to do all of this if we won't emit anything.
|
||||
return;
|
||||
|
||||
@@ -779,7 +779,7 @@ fn has_allow_dead_code_or_lang_attr(
|
||||
) -> Option<ComesFromAllowExpect> {
|
||||
fn has_allow_expect_dead_code(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
||||
let hir_id = tcx.local_def_id_to_hir_id(def_id);
|
||||
let lint_level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).level;
|
||||
let lint_level = tcx.lint_level_spec_at_node(lint::builtin::DEAD_CODE, hir_id).level();
|
||||
matches!(lint_level, lint::Allow | lint::Expect)
|
||||
}
|
||||
|
||||
@@ -1035,7 +1035,7 @@ fn mark_live_symbols_and_ignored_derived_traits(
|
||||
struct DeadItem {
|
||||
def_id: LocalDefId,
|
||||
name: Symbol,
|
||||
level: (lint::Level, Option<LintExpectationId>),
|
||||
level_plus: (lint::Level, Option<LintExpectationId>),
|
||||
}
|
||||
|
||||
struct DeadVisitor<'tcx> {
|
||||
@@ -1082,10 +1082,10 @@ fn should_warn_about_field(&mut self, field: &ty::FieldDef) -> ShouldWarnAboutFi
|
||||
ShouldWarnAboutField::Yes
|
||||
}
|
||||
|
||||
fn def_lint_level(&self, id: LocalDefId) -> (lint::Level, Option<LintExpectationId>) {
|
||||
fn def_lint_level_plus(&self, id: LocalDefId) -> (lint::Level, Option<LintExpectationId>) {
|
||||
let hir_id = self.tcx.local_def_id_to_hir_id(id);
|
||||
let level = self.tcx.lint_level_at_node(self.target_lint, hir_id);
|
||||
(level.level, level.lint_id)
|
||||
let level_spec = self.tcx.lint_level_spec_at_node(self.target_lint, hir_id);
|
||||
(level_spec.level(), level_spec.lint_id())
|
||||
}
|
||||
|
||||
fn dead_code_pub_in_binary_note(&self) -> Option<DeadCodePubInBinaryNote> {
|
||||
@@ -1108,8 +1108,8 @@ fn lint_at_single_level(
|
||||
let Some(&first_item) = dead_codes.first() else { return };
|
||||
let tcx = self.tcx;
|
||||
|
||||
let first_lint_level = first_item.level;
|
||||
assert!(dead_codes.iter().skip(1).all(|item| item.level == first_lint_level));
|
||||
let first_lint_level_plus = first_item.level_plus;
|
||||
assert!(dead_codes.iter().skip(1).all(|item| item.level_plus == first_lint_level_plus));
|
||||
|
||||
let names: Vec<_> = dead_codes.iter().map(|item| item.name).collect();
|
||||
let spans: Vec<_> = dead_codes
|
||||
@@ -1266,9 +1266,10 @@ fn warn_multiple(
|
||||
if dead_codes.is_empty() {
|
||||
return;
|
||||
}
|
||||
// FIXME: `dead_codes` should probably be morally equivalent to `IndexMap<(Level, LintExpectationId), (DefId, Symbol)>`
|
||||
dead_codes.sort_by_key(|v| v.level.0);
|
||||
for group in dead_codes.chunk_by(|a, b| a.level == b.level) {
|
||||
// FIXME: `dead_codes` should probably be morally equivalent to
|
||||
// `IndexMap<(Level, LintExpectationId), (DefId, Symbol)>`
|
||||
dead_codes.sort_by_key(|v| v.level_plus.0);
|
||||
for group in dead_codes.chunk_by(|a, b| a.level_plus == b.level_plus) {
|
||||
self.lint_at_single_level(&group, participle, Some(def_id), report_on);
|
||||
}
|
||||
}
|
||||
@@ -1277,7 +1278,7 @@ fn warn_dead_code(&mut self, id: LocalDefId, participle: &str) {
|
||||
let item = DeadItem {
|
||||
def_id: id,
|
||||
name: self.tcx.item_name(id.to_def_id()),
|
||||
level: self.def_lint_level(id),
|
||||
level_plus: self.def_lint_level_plus(id),
|
||||
};
|
||||
self.lint_at_single_level(&[&item], participle, None, ReportOn::NamedField);
|
||||
}
|
||||
@@ -1381,8 +1382,8 @@ fn lint_dead_codes<'tcx>(
|
||||
&& !visitor.is_live_code(local_def_id)
|
||||
{
|
||||
let name = tcx.item_name(def_id);
|
||||
let level = visitor.def_lint_level(local_def_id);
|
||||
dead_codes.push(DeadItem { def_id: local_def_id, name, level });
|
||||
let level_plus = visitor.def_lint_level_plus(local_def_id);
|
||||
dead_codes.push(DeadItem { def_id: local_def_id, name, level_plus });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1408,8 +1409,8 @@ fn lint_dead_codes<'tcx>(
|
||||
let def_id = variant.def_id.expect_local();
|
||||
if !live_symbols.contains(&def_id) {
|
||||
// Record to group diagnostics.
|
||||
let level = visitor.def_lint_level(def_id);
|
||||
dead_variants.push(DeadItem { def_id, name: variant.name, level });
|
||||
let level_plus = visitor.def_lint_level_plus(def_id);
|
||||
dead_variants.push(DeadItem { def_id, name: variant.name, level_plus });
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1424,8 +1425,8 @@ fn lint_dead_codes<'tcx>(
|
||||
.filter_map(|field| {
|
||||
let def_id = field.did.expect_local();
|
||||
if let ShouldWarnAboutField::Yes = visitor.should_warn_about_field(field) {
|
||||
let level = visitor.def_lint_level(def_id);
|
||||
Some(DeadItem { def_id, name: field.name, level })
|
||||
let level_plus = visitor.def_lint_level_plus(def_id);
|
||||
Some(DeadItem { def_id, name: field.name, level_plus })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
@@ -843,9 +843,7 @@ fn visit_path(&mut self, path: &hir::Path<'tcx>, id: hir::HirId) {
|
||||
// Calculating message for lint involves calling `self.def_path_str`,
|
||||
// which will by default invoke the expensive `visible_parent_map` query.
|
||||
// Skip all that work if the lint is allowed anyway.
|
||||
if self.tcx.lint_level_at_node(DEPRECATED, id).level
|
||||
== lint::Level::Allow
|
||||
{
|
||||
if self.tcx.lint_level_spec_at_node(DEPRECATED, id).is_allow() {
|
||||
return;
|
||||
}
|
||||
// Show a deprecation message.
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use rustc_middle::lint::LevelAndSource;
|
||||
use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
|
||||
use rustc_span::ErrorGuaranteed;
|
||||
use tracing::instrument;
|
||||
@@ -64,10 +63,11 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'p, 'tcx>(
|
||||
pat_column: &PatternColumn<'p, RustcPatCtxt<'p, 'tcx>>,
|
||||
scrut_ty: RevealedTy<'tcx>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
if !matches!(
|
||||
rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, rcx.match_lint_level).level,
|
||||
rustc_session::lint::Level::Allow
|
||||
) {
|
||||
if !rcx
|
||||
.tcx
|
||||
.lint_level_spec_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, rcx.match_lint_level)
|
||||
.is_allow()
|
||||
{
|
||||
let witnesses = collect_nonexhaustive_missing_variants(rcx, pat_column)?;
|
||||
if !witnesses.is_empty() {
|
||||
// Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
|
||||
@@ -89,12 +89,13 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'p, 'tcx>(
|
||||
// arm. This no longer makes sense so we warn users, to avoid silently breaking their
|
||||
// usage of the lint.
|
||||
for arm in arms {
|
||||
let LevelAndSource { level, src, .. } =
|
||||
rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.arm_data);
|
||||
if !matches!(level, rustc_session::lint::Level::Allow) {
|
||||
let level_spec =
|
||||
rcx.tcx.lint_level_spec_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.arm_data);
|
||||
let level = level_spec.level();
|
||||
if level != rustc_session::lint::Level::Allow {
|
||||
rcx.tcx.dcx().emit_warn(NonExhaustiveOmittedPatternLintOnArm {
|
||||
span: arm.pat.data().span,
|
||||
lint_span: src.span(),
|
||||
lint_span: level_spec.src.span(),
|
||||
suggest_lint_on_match: rcx.whole_match_span.map(|span| span.shrink_to_lo()),
|
||||
lint_level: level.as_str(),
|
||||
lint_name: "non_exhaustive_omitted_patterns",
|
||||
|
||||
@@ -440,6 +440,37 @@ When `rustdoc` receives this flag, it will print an extra "Version (version)" in
|
||||
the crate root's docs. You can use this flag to differentiate between different versions of your
|
||||
library's documentation.
|
||||
|
||||
## `--emit`: control the types of output for rustdoc to emit
|
||||
|
||||
This flag controls the types of output by rustdoc. It accepts a comma-separated
|
||||
list of values, and may be specified multiple times. The valid emit kinds are:
|
||||
|
||||
- `html-static-files` --- Generates shared static files whose contents are
|
||||
tied to a specific toolchain version. These are written with a filename
|
||||
that includes a hash of their contents, so they are safe to cache with
|
||||
the change if the toolchain version or their contents change, or with the
|
||||
`Cache-Control: immutable` directive.
|
||||
- `html-non-static-files` --- Generates files based on the crate(s) being
|
||||
documented. These file names need to be deterministic so there is no
|
||||
content-hash in their file names.
|
||||
- `dep-info` --- Generates a file with Makefile syntax that indicates all the
|
||||
source files that were loaded to document the crate. The default output
|
||||
filename is `CRATE_NAME.d`. This emit type can can optionally be followed by
|
||||
`=` to specify an explicit output path, for example,
|
||||
`--emit=dep-info=/path/to/foo.d`. The output can be sent to stdout by
|
||||
specifying `-` as the path (e.g., `--emit=dep-info=-`).
|
||||
|
||||
Using this flag looks like this:
|
||||
|
||||
```bash
|
||||
$ rustdoc src/lib.rs --emit=html-static-files,html-non-static-files,dep-info=/path/to/build/cache/foo.d
|
||||
```
|
||||
|
||||
If not specified, the default emit types would be
|
||||
`--emit=html-static-files,html-non-static-files`.
|
||||
|
||||
Output files are written to the current directory unless the `--out-dir` flag is used.
|
||||
|
||||
## `-`: load source code from the standard input
|
||||
|
||||
If you specify `-` as the INPUT on the command line, then `rustdoc` will read the
|
||||
|
||||
@@ -534,7 +534,7 @@ fn opts() -> Vec<RustcOptGroup> {
|
||||
"",
|
||||
),
|
||||
opt(
|
||||
Unstable,
|
||||
Stable,
|
||||
Multi,
|
||||
"",
|
||||
"emit",
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::builtin::MISSING_DOCS;
|
||||
use rustc_middle::lint::{LevelAndSource, LintLevelSource};
|
||||
use rustc_session::lint;
|
||||
use rustc_middle::lint::LintLevelSource;
|
||||
use rustc_span::{FileName, RemapPathScopeComponents};
|
||||
use serde::Serialize;
|
||||
use tracing::debug;
|
||||
@@ -222,8 +221,7 @@ fn visit_item(&mut self, i: &clean::Item) {
|
||||
|
||||
let has_doc_example = tests.found_tests != 0;
|
||||
let hir_id = DocContext::as_local_hir_id(self.ctx.tcx, i.item_id).unwrap();
|
||||
let LevelAndSource { level, src, .. } =
|
||||
self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id);
|
||||
let level_spec = self.ctx.tcx.lint_level_spec_at_node(MISSING_DOCS, hir_id);
|
||||
|
||||
// In case we have:
|
||||
//
|
||||
@@ -258,7 +256,8 @@ fn visit_item(&mut self, i: &clean::Item) {
|
||||
// unless the user had an explicit `allow`.
|
||||
//
|
||||
let should_have_docs = !should_be_ignored
|
||||
&& (level != lint::Level::Allow || matches!(src, LintLevelSource::Default));
|
||||
&& (!level_spec.is_allow()
|
||||
|| matches!(level_spec.src, LintLevelSource::Default));
|
||||
|
||||
if let Some(span) = i.span(self.ctx.tcx) {
|
||||
let filename = span.filename(self.ctx.sess());
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
|
||||
use rustc_hir as hir;
|
||||
use rustc_macros::Diagnostic;
|
||||
use rustc_middle::lint::{LevelAndSource, LintLevelSource};
|
||||
use rustc_session::lint;
|
||||
use rustc_middle::lint::LintLevelSource;
|
||||
use tracing::debug;
|
||||
|
||||
use super::Pass;
|
||||
@@ -110,11 +109,11 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -
|
||||
{
|
||||
return false;
|
||||
}
|
||||
let LevelAndSource { level, src, .. } = cx.tcx.lint_level_at_node(
|
||||
let level_spec = cx.tcx.lint_level_spec_at_node(
|
||||
crate::lint::MISSING_DOC_CODE_EXAMPLES,
|
||||
cx.tcx.local_def_id_to_hir_id(def_id),
|
||||
);
|
||||
level != lint::Level::Allow || matches!(src, LintLevelSource::Default)
|
||||
!level_spec.is_allow() || matches!(level_spec.src, LintLevelSource::Default)
|
||||
}
|
||||
|
||||
pub(crate) fn look_for_tests(cx: &DocContext<'_>, dox: &str, item: &Item) {
|
||||
|
||||
@@ -583,7 +583,7 @@ fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
|
||||
if matches!(name, sym::allow | sym::expect) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) {
|
||||
allow_attributes_without_reason::check(cx, name, items, attr);
|
||||
}
|
||||
if is_lint_level(name, attr.id) {
|
||||
if is_lint_level(name) {
|
||||
blanket_clippy_restriction_lints::check(cx, name, items);
|
||||
}
|
||||
if items.is_empty() || !attr.has_name(sym::deprecated) {
|
||||
|
||||
@@ -15,7 +15,7 @@ pub(super) fn check(
|
||||
) {
|
||||
if cfg_attr.has_name(sym::clippy)
|
||||
&& let Some(ident) = behind_cfg_attr.ident()
|
||||
&& Level::from_symbol(ident.name, || Some(attr.id)).is_some()
|
||||
&& Level::from_symbol(ident.name).is_some()
|
||||
&& let Some(items) = behind_cfg_attr.meta_item_list()
|
||||
{
|
||||
let nb_items = items.len();
|
||||
|
||||
@@ -15,7 +15,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) {
|
||||
return;
|
||||
}
|
||||
if let Some(lint_list) = &attr.meta_item_list()
|
||||
&& attr.name().is_some_and(|name| is_lint_level(name, attr.id))
|
||||
&& attr.name().is_some_and(|name| is_lint_level(name))
|
||||
{
|
||||
for lint in lint_list {
|
||||
match item.kind {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use clippy_utils::macros::{is_panic, macro_backtrace};
|
||||
use rustc_ast::{AttrId, MetaItemInner};
|
||||
use rustc_ast::MetaItemInner;
|
||||
use rustc_hir::{
|
||||
Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, StmtKind, TraitFn, TraitItem, TraitItemKind,
|
||||
};
|
||||
@@ -16,8 +16,8 @@ pub(super) fn is_word(nmi: &MetaItemInner, expected: Symbol) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn is_lint_level(symbol: Symbol, attr_id: AttrId) -> bool {
|
||||
Level::from_symbol(symbol, || Some(attr_id)).is_some()
|
||||
pub(super) fn is_lint_level(symbol: Symbol) -> bool {
|
||||
Level::from_symbol(symbol).is_some()
|
||||
}
|
||||
|
||||
pub(super) fn is_relevant_item(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::intravisit::{FnKind, Visitor, walk_expr};
|
||||
use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, RustcVersion, UnOp};
|
||||
use rustc_lint::{LateContext, LateLintPass, Level};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::{Span, Symbol, SyntaxContext};
|
||||
@@ -204,7 +204,7 @@ fn check_simplify_not(cx: &LateContext<'_>, msrv: Msrv, expr: &Expr<'_>) {
|
||||
&& !expr.span.from_expansion()
|
||||
&& !inner.span.from_expansion()
|
||||
&& let Some(suggestion) = simplify_not(cx, msrv, inner)
|
||||
&& cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, expr.hir_id).level != Level::Allow
|
||||
&& !cx.tcx.lint_level_spec_at_node(NONMINIMAL_BOOL, expr.hir_id).is_allow()
|
||||
{
|
||||
use clippy_utils::sugg::{Sugg, has_enclosing_paren};
|
||||
let maybe_par = if let Some(sug) = Sugg::hir_opt(cx, inner) {
|
||||
@@ -612,7 +612,7 @@ fn bool_expr(&self, e: &'tcx Expr<'_>) {
|
||||
}
|
||||
}
|
||||
let nonminimal_bool_lint = |mut suggestions: Vec<_>| {
|
||||
if self.cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, e.hir_id).level != Level::Allow {
|
||||
if !self.cx.tcx.lint_level_spec_at_node(NONMINIMAL_BOOL, e.hir_id).is_allow() {
|
||||
suggestions.sort();
|
||||
span_lint_hir_and_then(
|
||||
self.cx,
|
||||
|
||||
@@ -238,7 +238,7 @@ fn check_significant_tokens_and_expect_attrs(
|
||||
},
|
||||
|
||||
[attr]
|
||||
if matches!(Level::from_attr(attr.name(), || attr.id()), Some((Level::Expect, _)))
|
||||
if matches!(Level::from_opt_symbol(attr.name()), Some(Level::Expect))
|
||||
&& let Some(metas) = attr.meta_item_list()
|
||||
&& let Some(MetaItemInner::MetaItem(meta_item)) = metas.first()
|
||||
&& let [tool, lint_name] = meta_item.path.segments.as_slice()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use rustc_ast::ast;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext};
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use unicode_script::{Script, UnicodeScript};
|
||||
|
||||
@@ -69,7 +69,7 @@ fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
|
||||
// Implementation is heavily inspired by the implementation of [`non_ascii_idents`] lint:
|
||||
// https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_lint/src/non_ascii_idents.rs
|
||||
|
||||
let check_disallowed_script_idents = cx.builder.lint_level(DISALLOWED_SCRIPT_IDENTS).level != Level::Allow;
|
||||
let check_disallowed_script_idents = !cx.builder.lint_level_spec(DISALLOWED_SCRIPT_IDENTS).is_allow();
|
||||
if !check_disallowed_script_idents {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
use rustc_ast::ast::{Crate, Inline, Item, ItemKind, ModKind};
|
||||
use rustc_errors::MultiSpan;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext};
|
||||
use rustc_middle::lint::LevelAndSource;
|
||||
use rustc_middle::lint::LevelSpec;
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::{FileName, Span};
|
||||
use std::collections::BTreeMap;
|
||||
@@ -51,7 +51,7 @@
|
||||
struct Modules {
|
||||
local_path: PathBuf,
|
||||
spans: Vec<Span>,
|
||||
lint_levels: Vec<LevelAndSource>,
|
||||
lint_level_specs: Vec<LevelSpec>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -71,10 +71,10 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
|
||||
let modules = self.modules.entry(absolute_path).or_insert(Modules {
|
||||
local_path,
|
||||
spans: Vec::new(),
|
||||
lint_levels: Vec::new(),
|
||||
lint_level_specs: Vec::new(),
|
||||
});
|
||||
modules.spans.push(item.span_with_attributes());
|
||||
modules.lint_levels.push(cx.get_lint_level(DUPLICATE_MOD));
|
||||
modules.lint_level_specs.push(cx.get_lint_level_spec(DUPLICATE_MOD));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ fn check_crate_post(&mut self, cx: &EarlyContext<'_>, _: &Crate) {
|
||||
for Modules {
|
||||
local_path,
|
||||
spans,
|
||||
lint_levels,
|
||||
lint_level_specs,
|
||||
} in self.modules.values()
|
||||
{
|
||||
if spans.len() < 2 {
|
||||
@@ -90,16 +90,16 @@ fn check_crate_post(&mut self, cx: &EarlyContext<'_>, _: &Crate) {
|
||||
}
|
||||
|
||||
// At this point the lint would be emitted
|
||||
assert_eq!(spans.len(), lint_levels.len());
|
||||
assert_eq!(spans.len(), lint_level_specs.len());
|
||||
let spans: Vec<_> = spans
|
||||
.iter()
|
||||
.zip(lint_levels)
|
||||
.filter_map(|(span, lvl)| {
|
||||
if let Some(id) = lvl.lint_id {
|
||||
.zip(lint_level_specs)
|
||||
.filter_map(|(span, level_spec)| {
|
||||
if let Some(id) = level_spec.lint_id() {
|
||||
cx.fulfill_expectation(id);
|
||||
}
|
||||
|
||||
(!matches!(lvl.level, Level::Allow | Level::Expect)).then_some(*span)
|
||||
(!matches!(level_spec.level(), Level::Allow | Level::Expect)).then_some(*span)
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::intravisit::{Visitor, walk_block, walk_expr, walk_stmt};
|
||||
use rustc_hir::{BlockCheckMode, Expr, ExprKind, HirId, Stmt, UnsafeSource, find_attr};
|
||||
use rustc_lint::{LateContext, LateLintPass, Level, LintContext};
|
||||
use rustc_middle::lint::LevelAndSource;
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::{Span, SyntaxContext};
|
||||
use std::collections::BTreeMap;
|
||||
@@ -252,17 +251,15 @@ fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
|
||||
.flatten()
|
||||
.copied()
|
||||
.inspect(|&unsafe_block| {
|
||||
if let LevelAndSource {
|
||||
level: Level::Expect,
|
||||
lint_id: Some(id),
|
||||
..
|
||||
} = cx.tcx.lint_level_at_node(MACRO_METAVARS_IN_UNSAFE, unsafe_block)
|
||||
{
|
||||
let level_spec =
|
||||
cx.tcx.lint_level_spec_at_node(MACRO_METAVARS_IN_UNSAFE, unsafe_block);
|
||||
if level_spec.is_expect() {
|
||||
// Since we're going to deduplicate expanded unsafe blocks by its enclosing macro definition soon,
|
||||
// which would lead to unfulfilled `#[expect()]`s in all other unsafe blocks that are filtered out
|
||||
// except for the one we emit the warning at, we must manually fulfill the lint
|
||||
// for all unsafe blocks here.
|
||||
cx.fulfill_expectation(id);
|
||||
// `unwrap` is safe because `Expect` lints always have a `lint_id`.
|
||||
cx.fulfill_expectation(level_spec.lint_id().unwrap());
|
||||
}
|
||||
})
|
||||
.map(|id| {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::source::snippet;
|
||||
use rustc_ast::ast::{self, Inline, ItemKind, ModKind};
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext};
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::def_id::LOCAL_CRATE;
|
||||
use rustc_span::{FileName, Ident, SourceFile, Span, SyntaxContext, sym};
|
||||
@@ -137,9 +137,9 @@ fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
|
||||
}
|
||||
|
||||
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
|
||||
if cx.builder.lint_level(MOD_MODULE_FILES).level == Level::Allow
|
||||
&& cx.builder.lint_level(SELF_NAMED_MODULE_FILES).level == Level::Allow
|
||||
&& cx.builder.lint_level(INLINE_MODULES).level == Level::Allow
|
||||
if cx.builder.lint_level_spec(MOD_MODULE_FILES).is_allow()
|
||||
&& cx.builder.lint_level_spec(SELF_NAMED_MODULE_FILES).is_allow()
|
||||
&& cx.builder.lint_level_spec(INLINE_MODULES).is_allow()
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -192,9 +192,9 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
|
||||
}
|
||||
|
||||
fn check_item_post(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
|
||||
if cx.builder.lint_level(MOD_MODULE_FILES).level == Level::Allow
|
||||
&& cx.builder.lint_level(SELF_NAMED_MODULE_FILES).level == Level::Allow
|
||||
&& cx.builder.lint_level(INLINE_MODULES).level == Level::Allow
|
||||
if cx.builder.lint_level_spec(MOD_MODULE_FILES).is_allow()
|
||||
&& cx.builder.lint_level_spec(SELF_NAMED_MODULE_FILES).is_allow()
|
||||
&& cx.builder.lint_level_spec(INLINE_MODULES).is_allow()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ fn check_raw_string(&self, cx: &EarlyContext<'_>, str: &str, lit_span: Span, pre
|
||||
);
|
||||
},
|
||||
);
|
||||
if !matches!(cx.get_lint_level(NEEDLESS_RAW_STRINGS).level, rustc_lint::Allow) {
|
||||
if !cx.get_lint_level_spec(NEEDLESS_RAW_STRINGS).is_allow() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ fn check_final_expr<'tcx>(
|
||||
match cx.tcx.hir_attrs(expr.hir_id) {
|
||||
[] => {},
|
||||
[attr] => {
|
||||
if matches!(Level::from_attr(attr.name(), || attr.id()), Some((Level::Expect, _)))
|
||||
if matches!(Level::from_opt_symbol(attr.name()), Some(Level::Expect))
|
||||
&& let metas = attr.meta_item_list()
|
||||
&& let Some(lst) = metas
|
||||
&& let [MetaItemInner::MetaItem(meta_item), ..] = lst.as_slice()
|
||||
|
||||
@@ -104,7 +104,6 @@
|
||||
use rustc_lint::{LateContext, Level, Lint, LintContext};
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::hir::place::PlaceBase;
|
||||
use rustc_middle::lint::LevelAndSource;
|
||||
use rustc_middle::mir::{AggregateKind, Operand, RETURN_PLACE, Rvalue, StatementKind, TerminatorKind};
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, DerefAdjustKind, PointerCoercion};
|
||||
use rustc_middle::ty::layout::IntegerExt;
|
||||
@@ -1663,12 +1662,12 @@ pub fn fulfill_or_allowed(cx: &LateContext<'_>, lint: &'static Lint, ids: impl I
|
||||
let mut suppress_lint = false;
|
||||
|
||||
for id in ids {
|
||||
let LevelAndSource { level, lint_id, .. } = cx.tcx.lint_level_at_node(lint, id);
|
||||
if let Some(expectation) = lint_id {
|
||||
let level_spec = cx.tcx.lint_level_spec_at_node(lint, id);
|
||||
if let Some(expectation) = level_spec.lint_id() {
|
||||
cx.fulfill_expectation(expectation);
|
||||
}
|
||||
|
||||
match level {
|
||||
match level_spec.level() {
|
||||
Level::Allow | Level::Expect => suppress_lint = true,
|
||||
Level::Warn | Level::ForceWarn | Level::Deny | Level::Forbid => {},
|
||||
}
|
||||
@@ -1685,7 +1684,7 @@ pub fn fulfill_or_allowed(cx: &LateContext<'_>, lint: &'static Lint, ids: impl I
|
||||
/// make sure to use `span_lint_hir` functions to emit the lint. This ensures that
|
||||
/// expectations at the checked nodes will be fulfilled.
|
||||
pub fn is_lint_allowed(cx: &LateContext<'_>, lint: &'static Lint, id: HirId) -> bool {
|
||||
cx.tcx.lint_level_at_node(lint, id).level == Level::Allow
|
||||
cx.tcx.lint_level_spec_at_node(lint, id).is_allow()
|
||||
}
|
||||
|
||||
pub fn strip_pat_refs<'hir>(mut pat: &'hir Pat<'hir>) -> &'hir Pat<'hir> {
|
||||
|
||||
Reference in New Issue
Block a user