diff --git a/.mailmap b/.mailmap index 948f1ab14fdea..92c884be41232 100644 --- a/.mailmap +++ b/.mailmap @@ -579,6 +579,9 @@ Ralph Giles Ralph Giles Ramkumar Ramachandra Raphaël Huchet rChaser53 +Redddy +Redddy +Redddy <78539407+reddevilmidzy@users.noreply.github.com> Rémy Rakic Rémy Rakic Rémy Rakic diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 2fc057ae38823..bd46a40c02da1 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -27,7 +27,6 @@ use rustc_abi::FieldIdx; use rustc_data_structures::frozen::Frozen; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::graph::dominators::Dominators; -use rustc_errors::LintDiagnostic; use rustc_hir as hir; use rustc_hir::CRATE_HIR_ID; use rustc_hir::def_id::LocalDefId; @@ -715,7 +714,7 @@ impl<'tcx> Deref for BorrowckInferCtxt<'tcx> { } } -struct MirBorrowckCtxt<'a, 'infcx, 'tcx> { +pub(crate) struct MirBorrowckCtxt<'a, 'infcx, 'tcx> { root_cx: &'a mut BorrowCheckRootCtxt<'tcx>, infcx: &'infcx BorrowckInferCtxt<'tcx>, body: &'a Body<'tcx>, @@ -1428,13 +1427,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { borrow, Some((WriteKind::StorageDeadOrDrop, place)), ); - this.infcx.tcx.node_span_lint( + this.infcx.tcx.emit_node_span_lint( TAIL_EXPR_DROP_ORDER, CRATE_HIR_ID, borrowed, - |diag| { - session_diagnostics::TailExprDropOrder { borrowed }.decorate_lint(diag); - explain.add_explanation_to_diagnostic(&this, diag, "", None, None); + session_diagnostics::TailExprDropOrder { + borrowed, + callback: |diag| { + explain.add_explanation_to_diagnostic(&this, diag, "", None, None); + }, }, ); // We may stop at the first case diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index eaa41ce1caacf..fea5c2b990372 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -1,6 +1,6 @@ -use rustc_errors::MultiSpan; use rustc_errors::codes::*; -use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; +use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, MultiSpan}; +use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::{GenericArg, Ty}; use rustc_span::Span; @@ -595,9 +595,20 @@ pub(crate) struct SimdIntrinsicArgConst { pub intrinsic: String, } -#[derive(LintDiagnostic)] -#[diag("relative drop order changing in Rust 2024")] -pub(crate) struct TailExprDropOrder { - #[label("this temporary value will be dropped at the end of the block")] +pub(crate) struct TailExprDropOrder)> { pub borrowed: Span, + pub callback: F, +} + +impl<'a, F: FnOnce(&mut Diag<'_, ()>)> Diagnostic<'a, ()> for TailExprDropOrder { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + let Self { borrowed, callback } = self; + let mut diag = Diag::new(dcx, level, "relative drop order changing in Rust 2024") + .with_span_label( + borrowed, + "this temporary value will be dropped at the end of the block", + ); + callback(&mut diag); + diag + } } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 3f511fd65a416..e7b821a400ea4 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -22,7 +22,7 @@ use rustc_ast::visit::{FnCtxt, FnKind}; use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust::expr_to_string; use rustc_attr_parsing::AttributeParser; -use rustc_errors::{Applicability, LintDiagnostic, msg}; +use rustc_errors::{Applicability, Diagnostic, msg}; use rustc_feature::GateIssue; use rustc_hir::attrs::{AttributeKind, DocAttribute}; use rustc_hir::def::{DefKind, Res}; @@ -235,7 +235,7 @@ impl UnsafeCode { &self, cx: &EarlyContext<'_>, span: Span, - decorate: impl for<'a> LintDiagnostic<'a, ()>, + decorate: impl for<'a> Diagnostic<'a, ()>, ) { // This comes from a macro that has `#[allow_internal_unsafe]`. if span.allows_unsafe() { diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 561bdd1a2db67..971170aaba304 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -11,7 +11,7 @@ use rustc_ast::util::parser::ExprPrecedence; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync; use rustc_data_structures::unord::UnordMap; -use rustc_errors::{Diag, LintBuffer, LintDiagnostic, MultiSpan}; +use rustc_errors::{Diag, Diagnostic, LintBuffer, LintDiagnostic, MultiSpan}; use rustc_feature::Features; use rustc_hir::def::Res; use rustc_hir::def_id::{CrateNum, DefId}; @@ -522,17 +522,28 @@ pub trait LintContext { decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), ); + // FIXME: These methods should not take an Into -- instead, callers should need to + // set the span in their `decorate` function (preferably using set_span). + /// Emit a lint at the appropriate level, with an optional associated span. + /// + /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature + #[track_caller] + fn opt_span_diag_lint>( + &self, + lint: &'static Lint, + span: Option, + decorate: impl for<'a> Diagnostic<'a, ()>, + ); + /// Emit a lint at `span` from a lint struct (some type that implements `LintDiagnostic`, /// typically generated by `#[derive(LintDiagnostic)]`). fn emit_span_lint>( &self, lint: &'static Lint, span: S, - decorator: impl for<'a> LintDiagnostic<'a, ()>, + decorator: impl for<'a> Diagnostic<'a, ()>, ) { - self.opt_span_lint(lint, Some(span), |lint| { - decorator.decorate_lint(lint); - }); + self.opt_span_diag_lint(lint, Some(span), decorator); } /// Emit a lint at `span` from a lazily-constructed lint struct (some type that implements @@ -570,6 +581,12 @@ pub trait LintContext { }); } + /// Emit a lint from a lint struct (some type that implements `LintDiagnostic`, typically + /// generated by `#[derive(LintDiagnostic)]`). + fn emit_diag_lint(&self, lint: &'static Lint, decorator: impl for<'a> Diagnostic<'a, ()>) { + self.opt_span_diag_lint(lint, None as Option, decorator); + } + /// Emit a lint at the appropriate level, with no associated span. /// /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature @@ -644,6 +661,20 @@ impl<'tcx> LintContext for LateContext<'tcx> { } } + fn opt_span_diag_lint>( + &self, + lint: &'static Lint, + span: Option, + decorate: impl for<'a> Diagnostic<'a, ()>, + ) { + let hir_id = self.last_node_with_lint_attrs; + + match span { + Some(s) => self.tcx.emit_node_span_lint(lint, hir_id, s, decorate), + None => self.tcx.emit_node_lint(lint, hir_id, decorate), + } + } + fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource { self.tcx.lint_level_at_node(lint, self.last_node_with_lint_attrs) } @@ -664,6 +695,15 @@ impl LintContext for EarlyContext<'_> { self.builder.opt_span_lint(lint, span.map(|s| s.into()), decorate) } + fn opt_span_diag_lint>( + &self, + lint: &'static Lint, + span: Option, + decorator: impl for<'a> Diagnostic<'a, ()>, + ) { + self.builder.opt_span_diag_lint(lint, span.map(|s| s.into()), decorator) + } + fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource { self.builder.lint_level(lint) } diff --git a/compiler/rustc_lint/src/dangling.rs b/compiler/rustc_lint/src/dangling.rs index 448c0ded637c6..d162ae4b77647 100644 --- a/compiler/rustc_lint/src/dangling.rs +++ b/compiler/rustc_lint/src/dangling.rs @@ -269,7 +269,6 @@ fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) { && let Some(fn_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) && find_attr!(cx.tcx, fn_id, RustcAsPtr(_)) { - // FIXME: use `emit_node_lint` when `#[primary_span]` is added. cx.tcx.emit_node_span_lint( DANGLING_POINTERS_FROM_TEMPORARIES, expr.hir_id, diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 0723395d6d1cd..cb4c5077a5263 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -638,7 +638,7 @@ impl EarlyLintPass for BadUseOfFindAttr { cx.emit_span_lint( BAD_USE_OF_FIND_ATTR, segment.span(), - AttributeKindInFindAttr {}, + AttributeKindInFindAttr, ); } } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index a3376ad967e06..a134b623d7bd4 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -2,7 +2,7 @@ use rustc_ast::attr::AttributeExt; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::unord::UnordSet; -use rustc_errors::{Diag, LintDiagnostic, MultiSpan, msg}; +use rustc_errors::{Diag, Diagnostic, MultiSpan, msg}; use rustc_feature::{Features, GateIssue}; use rustc_hir::HirId; use rustc_hir::intravisit::{self, Visitor}; @@ -10,8 +10,8 @@ use rustc_index::IndexVec; use rustc_middle::bug; use rustc_middle::hir::nested_filter; use rustc_middle::lint::{ - LevelAndSource, LintExpectation, LintLevelSource, ShallowLintLevelMap, lint_level, - reveal_actual_level, + LevelAndSource, LintExpectation, LintLevelSource, ShallowLintLevelMap, diag_lint_level, + lint_level, reveal_actual_level, }; use rustc_middle::query::Providers; use rustc_middle::ty::{RegisteredTools, TyCtxt}; @@ -822,8 +822,11 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { RenamedLintSuggestion::WithSpan { suggestion: sp, replace }; let name = tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name); - let lint = RenamedLint { name: name.as_str(), replace, suggestion }; - self.emit_span_lint(RENAMED_AND_REMOVED_LINTS, sp.into(), lint); + self.emit_span_lint( + RENAMED_AND_REMOVED_LINTS, + sp.into(), + RenamedLint { name: name.as_str(), replace, suggestion }, + ); } // If this lint was renamed, apply the new lint instead of ignoring the @@ -844,8 +847,11 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { if self.lint_added_lints { let name = tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name); - let lint = RemovedLint { name: name.as_str(), reason }; - self.emit_span_lint(RENAMED_AND_REMOVED_LINTS, sp.into(), lint); + self.emit_span_lint( + RENAMED_AND_REMOVED_LINTS, + sp.into(), + RemovedLint { name: name.as_str(), reason }, + ); } continue; } @@ -861,8 +867,11 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { from_rustc, } }); - let lint = UnknownLint { name, suggestion }; - self.emit_span_lint(UNKNOWN_LINTS, sp.into(), lint); + self.emit_span_lint( + UNKNOWN_LINTS, + sp.into(), + UnknownLint { name, suggestion }, + ); } continue; } @@ -967,8 +976,6 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { /// Used to emit a lint-related diagnostic based on the current state of /// this lint context. - /// - /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature #[track_caller] pub(crate) fn opt_span_lint( &self, @@ -980,25 +987,34 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { lint_level(self.sess, lint, level, span, decorate) } + /// Used to emit a lint-related diagnostic based on the current state of + /// this lint context. + #[track_caller] + pub(crate) fn opt_span_diag_lint( + &self, + lint: &'static Lint, + span: Option, + decorator: impl for<'a> Diagnostic<'a, ()>, + ) { + let level = self.lint_level(lint); + diag_lint_level(self.sess, lint, level, span, decorator) + } + #[track_caller] pub fn emit_span_lint( &self, lint: &'static Lint, span: MultiSpan, - decorate: impl for<'a> LintDiagnostic<'a, ()>, + decorator: impl for<'a> Diagnostic<'a, ()>, ) { let level = self.lint_level(lint); - lint_level(self.sess, lint, level, Some(span), |lint| { - decorate.decorate_lint(lint); - }); + diag_lint_level(self.sess, lint, level, Some(span), decorator); } #[track_caller] - pub fn emit_lint(&self, lint: &'static Lint, decorate: impl for<'a> LintDiagnostic<'a, ()>) { + pub fn emit_lint(&self, lint: &'static Lint, decorator: impl for<'a> Diagnostic<'a, ()>) { let level = self.lint_level(lint); - lint_level(self.sess, lint, level, None, |lint| { - decorate.decorate_lint(lint); - }); + diag_lint_level(self.sess, lint, level, None, decorator); } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 1d8f2d4e3442d..0461d19d544c6 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -5,8 +5,8 @@ use std::num::NonZero; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagArgValue, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic, - ElidedLifetimeInPathSubdiag, EmissionGuarantee, Level, LintDiagnostic, MultiSpan, - Subdiagnostic, SuggestionStyle, msg, + ElidedLifetimeInPathSubdiag, EmissionGuarantee, Level, MultiSpan, Subdiagnostic, + SuggestionStyle, msg, }; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -24,7 +24,7 @@ use crate::errors::{OverruledAttributeSub, RequestedLevel}; use crate::lifetime_syntax::LifetimeSyntaxCategories; // array_into_iter.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "this method call resolves to `<&{$target} as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<{$target} as IntoIterator>::into_iter` in Rust {$edition}" )] @@ -65,7 +65,7 @@ pub(crate) enum ShadowedIntoIterDiagSub { } // autorefs.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("implicit autoref creates a reference to the dereference of a raw pointer")] #[note( "creating a reference requires the pointer target to be valid and imposes aliasing requirements" @@ -119,7 +119,7 @@ pub(crate) struct ImplicitUnsafeAutorefsSuggestion { } // builtin.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("denote infinite loops with `loop {\"{\"} ... {\"}\"}`")] pub(crate) struct BuiltinWhileTrue { #[suggestion( @@ -132,7 +132,7 @@ pub(crate) struct BuiltinWhileTrue { pub replace: String, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("the `{$ident}:` in this pattern is redundant")] pub(crate) struct BuiltinNonShorthandFieldPatterns { pub ident: Ident, @@ -145,7 +145,7 @@ pub(crate) struct BuiltinNonShorthandFieldPatterns { pub prefix: &'static str, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] pub(crate) enum BuiltinUnsafe { #[diag( "`allow_internal_unsafe` allows defining macros using unsafe without triggering the `unsafe_code` lint at their call site" @@ -210,14 +210,14 @@ pub(crate) enum BuiltinUnsafe { GlobalAsm, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("missing documentation for {$article} {$desc}")] pub(crate) struct BuiltinMissingDoc<'a> { pub article: &'a str, pub desc: &'a str, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("type could implement `Copy`; consider adding `impl Copy`")] pub(crate) struct BuiltinMissingCopyImpl; @@ -227,14 +227,18 @@ pub(crate) struct BuiltinMissingDebugImpl<'a> { } // Needed for def_path_str -impl<'a> LintDiagnostic<'a, ()> for BuiltinMissingDebugImpl<'_> { - fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::Diag<'a, ()>) { - diag.primary_message(msg!("type does not implement `{$debug}`; consider adding `#[derive(Debug)]` or a manual implementation")); - diag.arg("debug", self.tcx.def_path_str(self.def_id)); +impl<'a> Diagnostic<'a, ()> for BuiltinMissingDebugImpl<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + let Self { tcx, def_id } = self; + Diag::new( + dcx, + level, + msg!("type does not implement `{$debug}`; consider adding `#[derive(Debug)]` or a manual implementation"), + ).with_arg("debug", tcx.def_path_str(def_id)) } } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("anonymous parameters are deprecated and will be removed in the next edition")] pub(crate) struct BuiltinAnonymousParams<'a> { #[suggestion("try naming the parameter or explicitly ignoring it", code = "_: {ty_snip}")] @@ -242,7 +246,7 @@ pub(crate) struct BuiltinAnonymousParams<'a> { pub ty_snip: &'a str, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unused doc comment")] pub(crate) struct BuiltinUnusedDocComment<'a> { pub kind: &'a str, @@ -260,7 +264,7 @@ pub(crate) enum BuiltinUnusedDocCommentSub { BlockHelp, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("functions generic over types or consts must be mangled")] pub(crate) struct BuiltinNoMangleGeneric { // Use of `#[no_mangle]` suggests FFI intent; correct @@ -274,20 +278,20 @@ pub(crate) struct BuiltinNoMangleGeneric { pub suggestion: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("const items should never be `#[no_mangle]`")] pub(crate) struct BuiltinConstNoMangle { #[suggestion("try a static value", code = "pub static ", applicability = "machine-applicable")] pub suggestion: Option, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell" )] pub(crate) struct BuiltinMutablesTransmutes; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("use of an unstable feature")] pub(crate) struct BuiltinUnstableFeatures; @@ -297,19 +301,20 @@ pub(crate) struct BuiltinUngatedAsyncFnTrackCaller<'a> { pub session: &'a Session, } -impl<'a> LintDiagnostic<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> { - fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(msg!("`#[track_caller]` on async functions is a no-op")); - diag.span_label(self.label, msg!("this function will not propagate the caller location")); +impl<'a> Diagnostic<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + let mut diag = Diag::new(dcx, level, "`#[track_caller]` on async functions is a no-op") + .with_span_label(self.label, "this function will not propagate the caller location"); rustc_session::parse::add_feature_diagnostics( - diag, + &mut diag, self.session, sym::async_fn_track_caller, ); + diag } } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unreachable `pub` {$what}")] pub(crate) struct BuiltinUnreachablePub<'a> { pub what: &'a str, @@ -320,7 +325,7 @@ pub(crate) struct BuiltinUnreachablePub<'a> { pub help: bool, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("the `expr` fragment specifier will accept more expressions in the 2024 edition")] pub(crate) struct MacroExprFragment2024 { #[suggestion( @@ -340,18 +345,18 @@ pub(crate) struct BuiltinTypeAliasBounds<'hir> { pub ty: Option<&'hir hir::Ty<'hir>>, } -impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> { - fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(if self.in_where_clause { +impl<'a> Diagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + let mut diag = Diag::new(dcx, level, if self.in_where_clause { msg!("where clauses on type aliases are not enforced") } else { msg!("bounds on generic parameters in type aliases are not enforced") - }); - diag.span_label(self.label, msg!("will not be checked at usage sites of the type alias")); - diag.note(msg!( - "this is a known limitation of the type checker that may be lifted in a future edition. - see issue #112792 for more information" - )); + }) + .with_span_label(self.label, msg!("will not be checked at usage sites of the type alias")) + .with_note(msg!( + "this is a known limitation of the type checker that may be lifted in a future edition. + see issue #112792 for more information" + )); if self.enable_feat_help { diag.help(msg!("add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics")); } @@ -413,10 +418,11 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> { Applicability::HasPlaceholders, ); } + diag } } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "{$predicate_kind_name} bound {$predicate} does not depend on any type or lifetime parameters" )] @@ -425,7 +431,7 @@ pub(crate) struct BuiltinTrivialBounds<'a> { pub predicate: Clause<'a>, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("use of a double negation")] #[note( "the prefix `--` could be misinterpreted as a decrement operator which exists in other languages" @@ -445,7 +451,7 @@ pub(crate) struct BuiltinDoubleNegationsAddParens { pub end_span: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] pub(crate) enum BuiltinEllipsisInclusiveRangePatternsLint { #[diag("`...` range patterns are deprecated")] Parenthesise { @@ -469,7 +475,7 @@ pub(crate) enum BuiltinEllipsisInclusiveRangePatternsLint { }, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("`{$kw}` is a keyword in the {$next} edition")] pub(crate) struct BuiltinKeywordIdents { pub kw: Ident, @@ -483,7 +489,7 @@ pub(crate) struct BuiltinKeywordIdents { pub prefix: &'static str, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("outlives requirements can be inferred")] pub(crate) struct BuiltinExplicitOutlives { pub count: usize, @@ -505,7 +511,7 @@ pub(crate) struct BuiltinExplicitOutlivesSuggestion { pub applicability: Applicability, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "the feature `{$name}` is incomplete and may not be safe to use and/or cause compiler crashes" )] @@ -517,7 +523,7 @@ pub(crate) struct BuiltinIncompleteFeatures { pub help: Option, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("the feature `{$name}` is internal to the compiler or standard library")] #[note("using it is strongly discouraged")] pub(crate) struct BuiltinInternalFeatures { @@ -542,11 +548,11 @@ pub(crate) struct BuiltinUnpermittedTypeInit<'a> { pub tcx: TyCtxt<'a>, } -impl<'a> LintDiagnostic<'a, ()> for BuiltinUnpermittedTypeInit<'_> { - fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(self.msg); - diag.arg("ty", self.ty); - diag.span_label(self.label, msg!("this code causes undefined behavior when executed")); +impl<'a> Diagnostic<'a, ()> for BuiltinUnpermittedTypeInit<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + let mut diag = Diag::new(dcx, level, self.msg) + .with_arg("ty", self.ty) + .with_span_label(self.label, msg!("this code causes undefined behavior when executed")); if let InhabitedPredicate::True = self.ty.inhabited_predicate(self.tcx) { // Only suggest late `MaybeUninit::assume_init` initialization if the type is inhabited. diag.span_label( @@ -554,7 +560,8 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinUnpermittedTypeInit<'_> { msg!("help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done"), ); } - self.sub.add_to_diag(diag); + self.sub.add_to_diag(&mut diag); + diag } } @@ -624,7 +631,7 @@ impl Subdiagnostic for BuiltinClashingExternSub<'_> { } } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("dereferencing a null pointer")] pub(crate) struct BuiltinDerefNullptr { #[label("this code causes undefined behavior when executed")] @@ -633,7 +640,7 @@ pub(crate) struct BuiltinDerefNullptr { // FIXME: migrate fluent::lint::builtin_asm_labels -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] pub(crate) enum BuiltinSpecialModuleNameUsed { #[diag("found module declaration for lib.rs")] #[note("lib.rs is the root of this crate's library target")] @@ -645,7 +652,7 @@ pub(crate) enum BuiltinSpecialModuleNameUsed { } // deref_into_dyn_supertrait.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("this `Deref` implementation is covered by an implicit supertrait coercion")] pub(crate) struct SupertraitAsDerefTarget<'a> { pub self_ty: Ty<'a>, @@ -667,7 +674,7 @@ pub(crate) struct SupertraitAsDerefTargetLabel { } // enum_intrinsics_non_enums.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("the return value of `mem::discriminant` is unspecified when called with a non-enum type")] pub(crate) struct EnumIntrinsicsMemDiscriminate<'a> { pub ty_param: Ty<'a>, @@ -677,7 +684,7 @@ pub(crate) struct EnumIntrinsicsMemDiscriminate<'a> { pub note: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("the return value of `mem::variant_count` is unspecified when called with a non-enum type")] #[note( "the type parameter of `variant_count` should be an enum, but it was instantiated with the type `{$ty_param}`, which is not an enum" @@ -705,7 +712,7 @@ pub(crate) struct ExpectationNote { } // ptr_nulls.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] pub(crate) enum UselessPtrNullChecksDiag<'a> { #[diag( "function pointers are not nullable, so checking them for null will always return false" @@ -730,7 +737,7 @@ pub(crate) enum UselessPtrNullChecksDiag<'a> { FnRet { fn_name: Ident }, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] pub(crate) enum InvalidNullArgumentsDiag { #[diag( "calling this function with a null pointer is undefined behavior, even if the result of the function is unused" @@ -755,7 +762,7 @@ pub(crate) enum InvalidNullArgumentsDiag { } // for_loops_over_fallibles.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "for loop over {$article} `{$ref_prefix}{$ty}`. This is more readably written as an `if let` statement" )] @@ -838,7 +845,7 @@ pub(crate) enum UseLetUnderscoreIgnoreSuggestion { } // drop_forget_useless.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("calls to `std::mem::drop` with a reference instead of an owned value does nothing")] pub(crate) struct DropRefDiag<'a> { pub arg_ty: Ty<'a>, @@ -848,7 +855,7 @@ pub(crate) struct DropRefDiag<'a> { pub sugg: UseLetUnderscoreIgnoreSuggestion, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("calls to `std::mem::drop` with a value that implements `Copy` does nothing")] pub(crate) struct DropCopyDiag<'a> { pub arg_ty: Ty<'a>, @@ -858,7 +865,7 @@ pub(crate) struct DropCopyDiag<'a> { pub sugg: UseLetUnderscoreIgnoreSuggestion, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("calls to `std::mem::forget` with a reference instead of an owned value does nothing")] pub(crate) struct ForgetRefDiag<'a> { pub arg_ty: Ty<'a>, @@ -868,7 +875,7 @@ pub(crate) struct ForgetRefDiag<'a> { pub sugg: UseLetUnderscoreIgnoreSuggestion, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("calls to `std::mem::forget` with a value that implements `Copy` does nothing")] pub(crate) struct ForgetCopyDiag<'a> { pub arg_ty: Ty<'a>, @@ -878,7 +885,7 @@ pub(crate) struct ForgetCopyDiag<'a> { pub sugg: UseLetUnderscoreIgnoreSuggestion, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "calls to `std::mem::drop` with `std::mem::ManuallyDrop` instead of the inner value does nothing" )] @@ -903,7 +910,7 @@ pub(crate) struct UndroppedManuallyDropsSuggestion { } // invalid_from_utf8.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] pub(crate) enum InvalidFromUtf8Diag { #[diag("calls to `{$method}` with an invalid literal are undefined behavior")] Unchecked { @@ -922,7 +929,7 @@ pub(crate) enum InvalidFromUtf8Diag { } // interior_mutable_consts.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("mutation of an interior mutable `const` item with call to `{$method_name}`")] #[note("each usage of a `const` item creates a new temporary")] #[note("only the temporaries and never the original `const {$const_name}` will be modified")] @@ -957,7 +964,7 @@ pub(crate) enum ConstItemInteriorMutationsSuggestionStatic { } // reference_casting.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] pub(crate) enum InvalidReferenceCastingDiag<'tcx> { #[diag( "casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`" @@ -1002,7 +1009,7 @@ pub(crate) enum InvalidReferenceCastingDiag<'tcx> { } // map_unit_fn.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("`Iterator::map` call that discard the iterator's values")] #[note( "`Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated" @@ -1026,7 +1033,7 @@ pub(crate) struct MappingToUnit { } // internal.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("prefer `{$preferred}` over `{$used}`, it has better performance")] #[note("a `use rustc_data_structures::fx::{$preferred}` may be necessary")] pub(crate) struct DefaultHashTypesDiag<'a> { @@ -1034,7 +1041,7 @@ pub(crate) struct DefaultHashTypesDiag<'a> { pub used: Symbol, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("using `{$query}` can result in unstable query results")] #[note( "if you believe this case to be fine, allow this lint and add a comment explaining your rationale" @@ -1043,7 +1050,7 @@ pub(crate) struct QueryInstability { pub query: Symbol, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("`{$method}` accesses information that is not tracked by the query system")] #[note( "if you believe this case to be fine, allow this lint and add a comment explaining your rationale" @@ -1052,16 +1059,16 @@ pub(crate) struct QueryUntracked { pub method: Symbol, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("use `.eq_ctxt()` instead of `.ctxt() == .ctxt()`")] pub(crate) struct SpanUseEqCtxtDiag; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("using `Symbol::intern` on a string literal")] #[help("consider adding the symbol to `compiler/rustc_span/src/symbol.rs`")] pub(crate) struct SymbolInternStringLiteralDiag; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("usage of `ty::TyKind::`")] pub(crate) struct TykindKind { #[suggestion( @@ -1072,12 +1079,12 @@ pub(crate) struct TykindKind { pub suggestion: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("usage of `ty::TyKind`")] #[help("try using `Ty` instead")] pub(crate) struct TykindDiag; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("usage of qualified `ty::{$ty}`")] pub(crate) struct TyQualified { pub ty: String, @@ -1089,14 +1096,14 @@ pub(crate) struct TyQualified { pub suggestion: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("do not use `rustc_type_ir::inherent` unless you're inside of the trait solver")] #[note( "the method or struct you're looking for is likely defined somewhere else downstream in the compiler" )] pub(crate) struct TypeIrInherentUsage; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "do not use `rustc_type_ir::Interner` or `rustc_type_ir::InferCtxtLike` unless you're inside of the trait solver" )] @@ -1105,12 +1112,12 @@ pub(crate) struct TypeIrInherentUsage; )] pub(crate) struct TypeIrTraitUsage; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("do not use `rustc_type_ir` unless you are implementing type system internals")] #[note("use `rustc_middle::ty` instead")] pub(crate) struct TypeIrDirectUse; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("non-glob import of `rustc_type_ir::inherent`")] pub(crate) struct NonGlobImportTypeIrInherent { #[suggestion( @@ -1122,18 +1129,18 @@ pub(crate) struct NonGlobImportTypeIrInherent { pub snippet: &'static str, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("implementing `LintPass` by hand")] #[help("try using `declare_lint_pass!` or `impl_lint_pass!` instead")] pub(crate) struct LintPassByHand; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("{$msg}")] pub(crate) struct BadOptAccessDiag<'a> { pub msg: &'a str, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "dangerous use of `extern crate {$name}` which is not guaranteed to exist exactly once in the sysroot" )] @@ -1144,14 +1151,14 @@ pub(crate) struct ImplicitSysrootCrateImportDiag<'a> { pub name: &'a str, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("use of `AttributeKind` in `find_attr!(...)` invocation")] #[note("`find_attr!(...)` already imports `AttributeKind::*`")] #[help("remove `AttributeKind`")] -pub(crate) struct AttributeKindInFindAttr {} +pub(crate) struct AttributeKindInFindAttr; // let_underscore.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] pub(crate) enum NonBindingLet { #[diag("non-binding let on a synchronization lock")] SyncLock { @@ -1213,7 +1220,7 @@ impl Subdiagnostic for NonBindingLetSub { } // levels.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("{$lint_level}({$lint_source}) incompatible with previous forbid")] pub(crate) struct OverruledAttributeLint<'a> { #[label("overruled by previous forbid")] @@ -1224,7 +1231,7 @@ pub(crate) struct OverruledAttributeLint<'a> { pub sub: OverruledAttributeSub, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("lint name `{$name}` is deprecated and may not have an effect in the future")] pub(crate) struct DeprecatedLintName<'a> { pub name: String, @@ -1233,7 +1240,7 @@ pub(crate) struct DeprecatedLintName<'a> { pub replace: &'a str, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("lint name `{$name}` is deprecated and may not have an effect in the future")] #[help("change it to {$replace}")] pub(crate) struct DeprecatedLintNameFromCommandLine<'a> { @@ -1243,7 +1250,7 @@ pub(crate) struct DeprecatedLintNameFromCommandLine<'a> { pub requested_level: RequestedLevel<'a>, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("lint `{$name}` has been renamed to `{$replace}`")] pub(crate) struct RenamedLint<'a> { pub name: &'a str, @@ -1264,7 +1271,7 @@ pub(crate) enum RenamedLintSuggestion<'a> { WithoutSpan { replace: &'a str }, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("lint `{$name}` has been renamed to `{$replace}`")] pub(crate) struct RenamedLintFromCommandLine<'a> { pub name: &'a str, @@ -1275,14 +1282,14 @@ pub(crate) struct RenamedLintFromCommandLine<'a> { pub requested_level: RequestedLevel<'a>, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("lint `{$name}` has been removed: {$reason}")] pub(crate) struct RemovedLint<'a> { pub name: &'a str, pub reason: &'a str, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("lint `{$name}` has been removed: {$reason}")] pub(crate) struct RemovedLintFromCommandLine<'a> { pub name: &'a str, @@ -1291,7 +1298,7 @@ pub(crate) struct RemovedLintFromCommandLine<'a> { pub requested_level: RequestedLevel<'a>, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unknown lint: `{$name}`")] pub(crate) struct UnknownLint { pub name: String, @@ -1324,7 +1331,7 @@ pub(crate) enum UnknownLintSuggestion { WithoutSpan { replace: Symbol, from_rustc: bool }, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unknown lint: `{$name}`", code = E0602)] pub(crate) struct UnknownLintFromCommandLine<'a> { pub name: String, @@ -1334,7 +1341,7 @@ pub(crate) struct UnknownLintFromCommandLine<'a> { pub requested_level: RequestedLevel<'a>, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("{$level}({$name}) is ignored unless specified at crate level")] pub(crate) struct IgnoredUnlessCrateSpecified<'a> { pub level: &'a str, @@ -1376,18 +1383,18 @@ pub(crate) struct DanglingPointersFromLocals<'tcx> { } // multiple_supertrait_upcastable.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("`{$ident}` is dyn-compatible and has multiple supertraits")] pub(crate) struct MultipleSupertraitUpcastable { pub ident: Ident, } // non_ascii_idents.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("identifier contains non-ASCII characters")] pub(crate) struct IdentifierNonAsciiChar; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "identifier contains {$codepoints_len -> [one] { $identifier_type -> @@ -1421,7 +1428,7 @@ pub(crate) struct IdentifierUncommonCodepoints { pub identifier_type: &'static str, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("found both `{$existing_sym}` and `{$sym}` as identifiers, which look alike")] pub(crate) struct ConfusableIdentifierPair { pub existing_sym: Symbol, @@ -1432,7 +1439,7 @@ pub(crate) struct ConfusableIdentifierPair { pub main_label: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables" )] @@ -1450,9 +1457,9 @@ pub(crate) struct NonFmtPanicUnused { } // Used because of two suggestions based on one Option -impl<'a> LintDiagnostic<'a, ()> for NonFmtPanicUnused { - fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(msg!( +impl<'a> Diagnostic<'a, ()> for NonFmtPanicUnused { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + let mut diag = Diag::new(dcx, level, msg!( "panic message contains {$count -> [one] an unused *[other] unused @@ -1460,9 +1467,9 @@ impl<'a> LintDiagnostic<'a, ()> for NonFmtPanicUnused { [one] placeholder *[other] placeholders }" - )); - diag.arg("count", self.count); - diag.note(msg!("this message is not used as a format string when given without arguments, but will be in Rust 2021")); + )) + .with_arg("count", self.count) + .with_note(msg!("this message is not used as a format string when given without arguments, but will be in Rust 2021")); if let Some(span) = self.suggestion { diag.span_suggestion( span.shrink_to_hi(), @@ -1482,10 +1489,11 @@ impl<'a> LintDiagnostic<'a, ()> for NonFmtPanicUnused { Applicability::MachineApplicable, ); } + diag } } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "panic message contains {$count -> [one] a brace @@ -1504,7 +1512,7 @@ pub(crate) struct NonFmtPanicBraces { } // nonstandard_style.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("{$sort} `{$name}` should have an upper camel case name")] pub(crate) struct NonCamelCaseType<'a> { pub sort: &'a str, @@ -1532,7 +1540,7 @@ pub(crate) enum NonCamelCaseTypeSub { }, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("{$sort} `{$name}` should have a snake case name")] pub(crate) struct NonSnakeCaseDiag<'a> { pub sort: &'a str, @@ -1630,7 +1638,7 @@ pub(crate) struct NonUpperCaseGlobalSubTool { } // noop_method_call.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("call to `.{$method}()` on a reference in this situation does nothing")] #[note( "the type `{$orig_ty}` does not implement `{$trait_}`, so calling `{$method}` on `&{$orig_ty}` copies the reference, which does not do anything and can be removed" @@ -1649,7 +1657,7 @@ pub(crate) struct NoopMethodCallDiag<'a> { pub suggest_derive: Option, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type" )] @@ -1657,7 +1665,7 @@ pub(crate) struct SuspiciousDoubleRefDerefDiag<'a> { pub ty: Ty<'a>, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "using `.clone()` on a double reference, which returns `{$ty}` instead of cloning the inner type" )] @@ -1685,8 +1693,9 @@ pub(crate) enum NonLocalDefinitionsDiag { }, } -impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { - fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { +impl<'a> Diagnostic<'a, ()> for NonLocalDefinitionsDiag { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + let mut diag = Diag::new(dcx, level, ""); match self { NonLocalDefinitionsDiag::Impl { depth, @@ -1759,6 +1768,7 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { } } } + diag } } @@ -1773,7 +1783,7 @@ pub(crate) struct NonLocalDefinitionsCargoUpdateNote { } // precedence.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("`-` has lower precedence than method calls, which might be unexpected")] #[note("e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4`")] pub(crate) struct AmbiguousNegativeLiteralsDiag { @@ -1808,7 +1818,7 @@ pub(crate) struct AmbiguousNegativeLiteralsCurrentBehaviorSuggestion { } // disallowed_pass_by_ref.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("passing `{$ty}` by reference")] pub(crate) struct DisallowedPassByRefDiag { pub ty: String, @@ -1817,7 +1827,7 @@ pub(crate) struct DisallowedPassByRefDiag { } // redundant_semicolon.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "unnecessary trailing {$multiple -> [true] semicolons @@ -1853,11 +1863,11 @@ pub(crate) struct DropTraitConstraintsDiag<'a> { } // Needed for def_path_str -impl<'a> LintDiagnostic<'a, ()> for DropTraitConstraintsDiag<'_> { - fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(msg!("bounds on `{$predicate}` are most likely incorrect, consider instead using `{$needs_drop}` to detect whether a type can be trivially dropped")); - diag.arg("predicate", self.predicate); - diag.arg("needs_drop", self.tcx.def_path_str(self.def_id)); +impl<'a> Diagnostic<'a, ()> for DropTraitConstraintsDiag<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + Diag::new(dcx, level, msg!("bounds on `{$predicate}` are most likely incorrect, consider instead using `{$needs_drop}` to detect whether a type can be trivially dropped")) + .with_arg("predicate", self.predicate) + .with_arg("needs_drop", self.tcx.def_path_str(self.def_id)) } } @@ -1867,10 +1877,10 @@ pub(crate) struct DropGlue<'a> { } // Needed for def_path_str -impl<'a> LintDiagnostic<'a, ()> for DropGlue<'_> { - fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(msg!("types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped")); - diag.arg("needs_drop", self.tcx.def_path_str(self.def_id)); +impl<'a> Diagnostic<'a, ()> for DropGlue<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + Diag::new(dcx, level, msg!("types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped")) + .with_arg("needs_drop", self.tcx.def_path_str(self.def_id)) } } @@ -1925,7 +1935,7 @@ pub(crate) enum IntegerToPtrTransmutesSuggestion<'tcx> { } // types.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("range endpoint is out of range for `{$ty}`")] pub(crate) struct RangeEndpointOutOfRange<'a> { pub ty: &'a str, @@ -1958,7 +1968,7 @@ pub(crate) enum UseInclusiveRange<'a> { }, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("literal out of range for `{$ty}`")] pub(crate) struct OverflowingBinHex<'a> { pub ty: &'a str, @@ -2016,7 +2026,7 @@ pub(crate) struct OverflowingBinHexSignBitSub<'a> { pub int_ty: &'a str, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("literal out of range for `{$ty}`")] #[note("the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`")] pub(crate) struct OverflowingInt<'a> { @@ -2034,7 +2044,7 @@ pub(crate) struct OverflowingIntHelp<'a> { pub suggestion_ty: &'a str, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("only `u8` can be cast into `char`")] pub(crate) struct OnlyCastu8ToChar { #[suggestion( @@ -2046,7 +2056,7 @@ pub(crate) struct OnlyCastu8ToChar { pub literal: u128, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("literal out of range for `{$ty}`")] #[note("the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`")] pub(crate) struct OverflowingUInt<'a> { @@ -2056,7 +2066,7 @@ pub(crate) struct OverflowingUInt<'a> { pub max: u128, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("literal out of range for `{$ty}`")] #[note( "the literal `{$lit}` does not fit into the type `{$ty}` and will be converted to `{$ty}::INFINITY`" @@ -2066,31 +2076,31 @@ pub(crate) struct OverflowingLiteral<'a> { pub lit: String, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("surrogate values are not valid for `char`")] #[note("`0xD800..=0xDFFF` are reserved for Unicode surrogates and are not valid `char` values")] pub(crate) struct SurrogateCharCast { pub literal: u128, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("value exceeds maximum `char` value")] #[note("maximum valid `char` value is `0x10FFFF`")] pub(crate) struct TooLargeCharCast { pub literal: u128, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type" )] pub(crate) struct UsesPowerAlignment; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("comparison is useless due to type limits")] pub(crate) struct UnusedComparisons; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] pub(crate) enum InvalidNanComparisons { #[diag("incorrect NaN comparison, NaN cannot be directly compared to itself")] EqNe { @@ -2120,7 +2130,7 @@ pub(crate) enum InvalidNanComparisonsSuggestion { Spanless, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] pub(crate) enum AmbiguousWidePointerComparisons<'a> { #[diag( "ambiguous wide pointer comparison, the comparison includes metadata which may not be expected" @@ -2233,7 +2243,7 @@ pub(crate) struct AmbiguousWidePointerComparisonsExpectSuggestion<'a> { pub(crate) after: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] pub(crate) enum UnpredictableFunctionPointerComparisons<'a, 'tcx> { #[diag( "function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique" @@ -2309,12 +2319,16 @@ pub(crate) struct ImproperCTypes<'a> { } // Used because of the complexity of Option, DiagMessage, and Option -impl<'a> LintDiagnostic<'a, ()> for ImproperCTypes<'_> { - fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(msg!("`extern` {$desc} uses type `{$ty}`, which is not FFI-safe")); - diag.arg("ty", self.ty); - diag.arg("desc", self.desc); - diag.span_label(self.label, msg!("not FFI-safe")); +impl<'a> Diagnostic<'a, ()> for ImproperCTypes<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + let mut diag = Diag::new( + dcx, + level, + msg!("`extern` {$desc} uses type `{$ty}`, which is not FFI-safe"), + ) + .with_arg("ty", self.ty) + .with_arg("desc", self.desc) + .with_span_label(self.label, msg!("not FFI-safe")); if let Some(help) = self.help { diag.help(help); } @@ -2322,6 +2336,7 @@ impl<'a> LintDiagnostic<'a, ()> for ImproperCTypes<'_> { if let Some(note) = self.span_note { diag.span_note(note, msg!("the type is defined here")); } + diag } } @@ -2332,34 +2347,34 @@ pub(crate) struct ImproperGpuKernelArg<'a> { pub ty: Ty<'a>, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("function with the \"gpu-kernel\" ABI has a mangled name")] #[help("use `unsafe(no_mangle)` or `unsafe(export_name = \"\")`")] #[note("mangled names make it hard to find the kernel, this is usually not intended")] pub(crate) struct MissingGpuKernelExportName; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("enum variant is more than three times larger ({$largest} bytes) than the next largest")] pub(crate) struct VariantSizeDifferencesDiag { pub largest: u64, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("atomic loads cannot have `Release` or `AcqRel` ordering")] #[help("consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`")] pub(crate) struct AtomicOrderingLoad; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("atomic stores cannot have `Acquire` or `AcqRel` ordering")] #[help("consider using ordering modes `Release`, `SeqCst` or `Relaxed`")] pub(crate) struct AtomicOrderingStore; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("memory fences cannot have `Relaxed` ordering")] #[help("consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst`")] pub(crate) struct AtomicOrderingFence; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "`{$method}`'s failure ordering may not be `Release` or `AcqRel`, since a failed `{$method}` does not result in a write" )] @@ -2371,7 +2386,7 @@ pub(crate) struct InvalidAtomicOrderingDiag { } // unused.rs -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unused {$op} that must be used")] pub(crate) struct UnusedOp<'a> { pub op: &'a str, @@ -2406,7 +2421,7 @@ pub(crate) enum UnusedOpSuggestion { }, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unused result of type `{$ty}`")] pub(crate) struct UnusedResult<'a> { pub ty: Ty<'a>, @@ -2414,7 +2429,7 @@ pub(crate) struct UnusedResult<'a> { // FIXME(davidtwco): this isn't properly translatable because of the // pre/post strings -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "unused {$pre}{$count -> [one] closure @@ -2430,7 +2445,7 @@ pub(crate) struct UnusedClosure<'a> { // FIXME(davidtwco): this isn't properly translatable because of the // pre/post strings -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "unused {$pre}{$count -> [one] coroutine @@ -2481,12 +2496,13 @@ pub(crate) enum UnusedDefSuggestion { } // Needed because of def_path_str -impl<'a> LintDiagnostic<'a, ()> for UnusedDef<'_, '_> { - fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(msg!("unused {$pre}`{$def}`{$post} that must be used")); - diag.arg("pre", self.pre); - diag.arg("post", self.post); - diag.arg("def", self.cx.tcx.def_path_str(self.def_id)); +impl<'a> Diagnostic<'a, ()> for UnusedDef<'_, '_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + let mut diag = + Diag::new(dcx, level, msg!("unused {$pre}`{$def}`{$post} that must be used")) + .with_arg("pre", self.pre) + .with_arg("post", self.post) + .with_arg("def", self.cx.tcx.def_path_str(self.def_id)); // check for #[must_use = "..."] if let Some(note) = self.note { diag.note(note.to_string()); @@ -2494,10 +2510,11 @@ impl<'a> LintDiagnostic<'a, ()> for UnusedDef<'_, '_> { if let Some(sugg) = self.suggestion { diag.subdiagnostic(sugg); } + diag } } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("path statement drops value")] pub(crate) struct PathStatementDrop { #[subdiagnostic] @@ -2523,11 +2540,11 @@ pub(crate) enum PathStatementDropSub { }, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("path statement with no effect")] pub(crate) struct PathStatementNoEffect; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unnecessary {$delim} around {$item}")] pub(crate) struct UnusedDelim<'a> { pub delim: &'static str, @@ -2547,17 +2564,17 @@ pub(crate) struct UnusedDelimSuggestion { pub end_replace: &'static str, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("braces around {$node} is unnecessary")] pub(crate) struct UnusedImportBracesDiag { pub node: Symbol, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unnecessary allocation, use `&` instead")] pub(crate) struct UnusedAllocationDiag; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unnecessary allocation, use `&mut` instead")] pub(crate) struct UnusedAllocationMutDiag; @@ -2580,14 +2597,14 @@ impl<'a> Diagnostic<'a, ()> for AsyncFnInTraitDiag { } } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("binding has unit type `()`")] pub(crate) struct UnitBindingsDiag { #[label("this pattern is inferred to be the unit type `()`")] pub label: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] pub(crate) enum InvalidAsmLabel { #[diag("avoid using named labels in inline assembly")] #[help("only local labels of the form `:` should be used in inline asm")] @@ -3344,7 +3361,7 @@ pub(crate) struct AssociatedConstElidedLifetime { pub lifetimes_in_scope: MultiSpan, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("creating a {$shared_label}reference to mutable static")] pub(crate) struct RefOfMutStatic<'a> { #[label("{$shared_label}reference to mutable static")] @@ -3384,9 +3401,9 @@ pub(crate) enum MutRefSugg { }, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("`use` of a local item without leading `self::`, `super::`, or `crate::`")] -pub(crate) struct UnqualifiedLocalImportsDiag {} +pub(crate) struct UnqualifiedLocalImportsDiag; #[derive(LintDiagnostic)] #[diag("will be parsed as a guarded string in Rust 2024")] @@ -3438,8 +3455,8 @@ pub(crate) struct MismatchedLifetimeSyntaxes { pub suggestions: Vec, } -impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for MismatchedLifetimeSyntaxes { - fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) { +impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for MismatchedLifetimeSyntaxes { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { let counts = self.inputs.len() + self.outputs.len(); let message = match counts { LifetimeSyntaxCategories { hidden: 0, elided: 0, named: 0 } => { @@ -3462,7 +3479,7 @@ impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for MismatchedLifetimeSynta msg!("hiding or eliding a lifetime that's named elsewhere is confusing") } }; - diag.primary_message(message); + let mut diag = Diag::new(dcx, level, message); for s in self.inputs.hidden { diag.span_label(s, msg!("the lifetime is hidden here")); @@ -3497,6 +3514,7 @@ impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for MismatchedLifetimeSynta diag.subdiagnostic(s); } } + diag } } @@ -3933,7 +3951,7 @@ pub(crate) struct MalformedOnConstAttrLint { pub span: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("`Eq::assert_receiver_is_total_eq` should never be implemented by hand")] #[note("this method was used to add checks to the `Eq` derive macro")] pub(crate) struct EqInternalMethodImplemented; diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index b5b57eaa33894..5e43b8c65db40 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -1,6 +1,6 @@ use rustc_hir::{self as hir, AmbigArg}; use rustc_infer::infer::TyCtxtInferExt; -use rustc_macros::{LintDiagnostic, Subdiagnostic}; +use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::print::{PrintTraitPredicateExt as _, TraitPredPrintModifiersAndPath}; use rustc_middle::ty::{self, BottomUpFolder, Ty, TypeFoldable}; use rustc_session::{declare_lint, declare_lint_pass}; @@ -201,7 +201,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { } } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("opaque type `{$ty}` does not satisfy its associated type bounds")] struct OpaqueHiddenInferredBoundLint<'tcx> { ty: Ty<'tcx>, diff --git a/compiler/rustc_lint/src/unqualified_local_imports.rs b/compiler/rustc_lint/src/unqualified_local_imports.rs index d3aff05123763..888bf026b4ed9 100644 --- a/compiler/rustc_lint/src/unqualified_local_imports.rs +++ b/compiler/rustc_lint/src/unqualified_local_imports.rs @@ -77,7 +77,7 @@ impl<'tcx> LateLintPass<'tcx> for UnqualifiedLocalImports { cx.emit_span_lint( UNQUALIFIED_LOCAL_IMPORTS, first_seg.ident.span, - lints::UnqualifiedLocalImportsDiag {}, + lints::UnqualifiedLocalImportsDiag, ); } } diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 5dff30f4c0841..63b78955ba87b 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -51,14 +51,14 @@ use std::fmt; use std::hash::Hash; use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint}; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey}; +use rustc_data_structures::stable_hasher::{StableHasher, StableOrd, ToStableHashKey}; use rustc_hir::def_id::DefId; use rustc_hir::definitions::DefPathHash; use rustc_macros::{Decodable, Encodable, HashStable}; use rustc_span::Symbol; use super::{KeyFingerprintStyle, SerializedDepNodeIndex}; -use crate::ich::StableHashingContext; +use crate::dep_graph::DepNodeKey; use crate::mir::mono::MonoItem; use crate::ty::{TyCtxt, tls}; @@ -168,58 +168,6 @@ impl fmt::Debug for DepNode { } } -/// Trait for query keys as seen by dependency-node tracking. -pub trait DepNodeKey<'tcx>: fmt::Debug + Sized { - fn key_fingerprint_style() -> KeyFingerprintStyle; - - /// This method turns a query key into an opaque `Fingerprint` to be used - /// in `DepNode`. - fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint; - - fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String; - - /// This method tries to recover the query key from the given `DepNode`, - /// something which is needed when forcing `DepNode`s during red-green - /// evaluation. The query system will only call this method if - /// `fingerprint_style()` is not `FingerprintStyle::Opaque`. - /// It is always valid to return `None` here, in which case incremental - /// compilation will treat the query as having changed instead of forcing it. - fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option; -} - -// Blanket impl of `DepNodeKey`, which is specialized by other impls elsewhere. -impl<'tcx, T> DepNodeKey<'tcx> for T -where - T: for<'a> HashStable> + fmt::Debug, -{ - #[inline(always)] - default fn key_fingerprint_style() -> KeyFingerprintStyle { - KeyFingerprintStyle::Opaque - } - - #[inline(always)] - default fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { - tcx.with_stable_hashing_context(|mut hcx| { - let mut hasher = StableHasher::new(); - self.hash_stable(&mut hcx, &mut hasher); - hasher.finish() - }) - } - - #[inline(always)] - default fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - // Make sure to print dep node params with reduced queries since printing - // may themselves call queries, which may lead to (possibly untracked!) - // query cycles. - tcx.with_reduced_queries(|| format!("{self:?}")) - } - - #[inline(always)] - default fn try_recover_key(_: TyCtxt<'tcx>, _: &DepNode) -> Option { - None - } -} - /// This struct stores function pointers and other metadata for a particular DepKind. /// /// Information is retrieved by indexing the `DEP_KINDS` array using the integer value diff --git a/compiler/rustc_middle/src/dep_graph/dep_node_key.rs b/compiler/rustc_middle/src/dep_graph/dep_node_key.rs index c488a94712376..10e785ac6b870 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node_key.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node_key.rs @@ -1,11 +1,67 @@ +use std::fmt::Debug; + use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, ModDefId}; use rustc_hir::definitions::DefPathHash; use rustc_hir::{HirId, ItemLocalId, OwnerId}; -use crate::dep_graph::{DepNode, DepNodeKey, KeyFingerprintStyle}; +use crate::dep_graph::{DepNode, KeyFingerprintStyle}; +use crate::ich::StableHashingContext; use crate::ty::TyCtxt; +/// Trait for query keys as seen by dependency-node tracking. +pub trait DepNodeKey<'tcx>: Debug + Sized { + fn key_fingerprint_style() -> KeyFingerprintStyle; + + /// This method turns a query key into an opaque `Fingerprint` to be used + /// in `DepNode`. + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint; + + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String; + + /// This method tries to recover the query key from the given `DepNode`, + /// something which is needed when forcing `DepNode`s during red-green + /// evaluation. The query system will only call this method if + /// `fingerprint_style()` is not `FingerprintStyle::Opaque`. + /// It is always valid to return `None` here, in which case incremental + /// compilation will treat the query as having changed instead of forcing it. + fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option; +} + +// Blanket impl of `DepNodeKey`, which is specialized by other impls elsewhere. +impl<'tcx, T> DepNodeKey<'tcx> for T +where + T: for<'a> HashStable> + Debug, +{ + #[inline(always)] + default fn key_fingerprint_style() -> KeyFingerprintStyle { + KeyFingerprintStyle::Opaque + } + + #[inline(always)] + default fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + tcx.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + self.hash_stable(&mut hcx, &mut hasher); + hasher.finish() + }) + } + + #[inline(always)] + default fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + // Make sure to print dep node params with reduced queries since printing + // may themselves call queries, which may lead to (possibly untracked!) + // query cycles. + tcx.with_reduced_queries(|| format!("{self:?}")) + } + + #[inline(always)] + default fn try_recover_key(_: TyCtxt<'tcx>, _: &DepNode) -> Option { + None + } +} + impl<'tcx> DepNodeKey<'tcx> for () { #[inline(always)] fn key_fingerprint_style() -> KeyFingerprintStyle { diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index e0ba944d81573..1c922ffb3ef0d 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -3,8 +3,9 @@ use std::panic; use tracing::instrument; pub use self::dep_node::{ - DepKind, DepKindVTable, DepNode, DepNodeKey, WorkProductId, dep_kind_from_label, label_strs, + DepKind, DepKindVTable, DepNode, WorkProductId, dep_kind_from_label, label_strs, }; +pub use self::dep_node_key::DepNodeKey; pub use self::graph::{ DepGraph, DepGraphData, DepNodeIndex, QuerySideEffect, TaskDepsRef, WorkProduct, WorkProductMap, hash_result, diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 08ccc4a0fca41..7347fe6d9d5e0 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -299,7 +299,6 @@ fn explain_lint_level_source( /// for example: /// - [`TyCtxt::emit_node_span_lint`] /// - [`TyCtxt::node_span_lint`] -/// - [`TyCtxt::emit_node_lint`] /// - [`TyCtxt::node_lint`] /// - `LintContext::opt_span_lint` /// @@ -490,7 +489,6 @@ pub fn lint_level( /// /// - [`TyCtxt::emit_node_span_lint`] /// - [`TyCtxt::node_span_lint`] -/// - [`TyCtxt::emit_node_lint`] /// - [`TyCtxt::node_lint`] /// - `LintContext::opt_span_lint` /// diff --git a/compiler/rustc_middle/src/query/caches.rs b/compiler/rustc_middle/src/query/caches.rs index 2adcecc5aaef1..acd1b2cc341d8 100644 --- a/compiler/rustc_middle/src/query/caches.rs +++ b/compiler/rustc_middle/src/query/caches.rs @@ -1,19 +1,13 @@ -use std::fmt::Debug; -use std::hash::Hash; use std::sync::OnceLock; use rustc_data_structures::sharded::ShardedHashMap; -use rustc_data_structures::stable_hasher::HashStable; pub use rustc_data_structures::vec_cache::VecCache; use rustc_hir::def_id::LOCAL_CRATE; use rustc_index::Idx; use rustc_span::def_id::{DefId, DefIndex}; use crate::dep_graph::DepNodeIndex; -use crate::ich::StableHashingContext; - -/// Traits that all query keys must satisfy. -pub trait QueryCacheKey = Hash + Eq + Copy + Debug + for<'a> HashStable>; +use crate::query::keys::QueryKey; /// Trait for types that serve as an in-memory cache for query results, /// for a given key (argument) type and value (return) type. @@ -21,7 +15,7 @@ pub trait QueryCacheKey = Hash + Eq + Copy + Debug + for<'a> HashStable Default for DefaultCache { impl QueryCache for DefaultCache where - K: QueryCacheKey, + K: QueryKey, V: Copy, { type Key = K; @@ -180,7 +174,7 @@ where impl QueryCache for VecCache where - K: Idx + QueryCacheKey, + K: Idx + QueryKey, V: Copy, { type Key = K; diff --git a/compiler/rustc_middle/src/query/inner.rs b/compiler/rustc_middle/src/query/inner.rs index 775669231228a..bd4d5bcab4a33 100644 --- a/compiler/rustc_middle/src/query/inner.rs +++ b/compiler/rustc_middle/src/query/inner.rs @@ -35,17 +35,16 @@ where #[inline(always)] pub(crate) fn query_get_at<'tcx, C>( tcx: TyCtxt<'tcx>, - execute_query: fn(TyCtxt<'tcx>, Span, C::Key, QueryMode) -> Option, - query_cache: &C, span: Span, + query: &'tcx QueryVTable<'tcx, C>, key: C::Key, ) -> C::Value where C: QueryCache, { - match try_get_cached(tcx, query_cache, &key) { + match try_get_cached(tcx, &query.cache, &key) { Some(value) => value, - None => execute_query(tcx, span, key, QueryMode::Get).unwrap(), + None => (query.execute_query_fn)(tcx, span, key, QueryMode::Get).unwrap(), } } @@ -54,15 +53,14 @@ where #[inline] pub(crate) fn query_ensure<'tcx, C>( tcx: TyCtxt<'tcx>, - execute_query: fn(TyCtxt<'tcx>, Span, C::Key, QueryMode) -> Option, - query_cache: &C, + query: &'tcx QueryVTable<'tcx, C>, key: C::Key, ensure_mode: EnsureMode, ) where C: QueryCache, { - if try_get_cached(tcx, query_cache, &key).is_none() { - execute_query(tcx, DUMMY_SP, key, QueryMode::Ensure { ensure_mode }); + if try_get_cached(tcx, &query.cache, &key).is_none() { + (query.execute_query_fn)(tcx, DUMMY_SP, key, QueryMode::Ensure { ensure_mode }); } } @@ -71,8 +69,7 @@ pub(crate) fn query_ensure<'tcx, C>( #[inline] pub(crate) fn query_ensure_error_guaranteed<'tcx, C, T>( tcx: TyCtxt<'tcx>, - execute_query: fn(TyCtxt<'tcx>, Span, C::Key, QueryMode) -> Option, - query_cache: &C, + query: &'tcx QueryVTable<'tcx, C>, key: C::Key, // This arg is needed to match the signature of `query_ensure`, // but should always be `EnsureMode::Ok`. @@ -84,10 +81,10 @@ where { assert_matches!(ensure_mode, EnsureMode::Ok); - if let Some(res) = try_get_cached(tcx, query_cache, &key) { + if let Some(res) = try_get_cached(tcx, &query.cache, &key) { erase::restore_val(res).map(drop) } else { - execute_query(tcx, DUMMY_SP, key, QueryMode::Ensure { ensure_mode }) + (query.execute_query_fn)(tcx, DUMMY_SP, key, QueryMode::Ensure { ensure_mode }) .map(erase::restore_val) .map(|res| res.map(drop)) // Either we actually executed the query, which means we got a full `Result`, diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index 6652e6e78e761..54b72c5b6714b 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -1,13 +1,17 @@ //! Defines the set of legal keys that can be used in queries. use std::ffi::OsStr; +use std::fmt::Debug; +use std::hash::Hash; use rustc_ast::tokenstream::TokenStream; +use rustc_data_structures::stable_hasher::HashStable; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId}; use rustc_hir::hir_id::OwnerId; use rustc_span::{DUMMY_SP, Ident, LocalExpnId, Span, Symbol}; use crate::dep_graph::DepNodeIndex; +use crate::ich::StableHashingContext; use crate::infer::canonical::CanonicalQueryInput; use crate::mir::mono::CollectionMode; use crate::query::{DefIdCache, DefaultCache, SingleCache, VecCache}; @@ -20,9 +24,10 @@ use crate::{mir, traits}; #[derive(Copy, Clone, Debug)] pub struct LocalCrate; -/// The `Key` trait controls what types can legally be used as the key -/// for a query. -pub trait Key: Sized { +pub trait QueryKeyBounds = Copy + Debug + Eq + Hash + for<'a> HashStable>; + +/// Controls what types can legally be used as the key for a query. +pub trait QueryKey: Sized + QueryKeyBounds { /// The type of in-memory cache to use for queries with this key type. /// /// In practice the cache type must implement [`QueryCache`], though that @@ -47,15 +52,15 @@ pub trait Key: Sized { } } -pub trait AsLocalKey: Key { - type LocalKey; +pub trait AsLocalQueryKey: QueryKey { + type LocalQueryKey; /// Given an instance of this key, what crate is it referring to? /// This is used to find the provider. - fn as_local_key(&self) -> Option; + fn as_local_key(&self) -> Option; } -impl Key for () { +impl QueryKey for () { type Cache = SingleCache; fn default_span(&self, _: TyCtxt<'_>) -> Span { @@ -63,37 +68,37 @@ impl Key for () { } } -impl<'tcx> Key for ty::InstanceKind<'tcx> { +impl<'tcx> QueryKey for ty::InstanceKind<'tcx> { fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(self.def_id()) } } -impl<'tcx> Key for ty::Instance<'tcx> { +impl<'tcx> QueryKey for ty::Instance<'tcx> { fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(self.def_id()) } } -impl<'tcx> Key for mir::interpret::GlobalId<'tcx> { +impl<'tcx> QueryKey for mir::interpret::GlobalId<'tcx> { fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.instance.default_span(tcx) } } -impl<'tcx> Key for (Ty<'tcx>, Option>) { +impl<'tcx> QueryKey for (Ty<'tcx>, Option>) { fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP } } -impl<'tcx> Key for ty::LitToConstInput<'tcx> { +impl<'tcx> QueryKey for ty::LitToConstInput<'tcx> { fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { DUMMY_SP } } -impl Key for CrateNum { +impl QueryKey for CrateNum { type Cache = VecCache; fn default_span(&self, _: TyCtxt<'_>) -> Span { @@ -101,16 +106,16 @@ impl Key for CrateNum { } } -impl AsLocalKey for CrateNum { - type LocalKey = LocalCrate; +impl AsLocalQueryKey for CrateNum { + type LocalQueryKey = LocalCrate; #[inline(always)] - fn as_local_key(&self) -> Option { + fn as_local_key(&self) -> Option { (*self == LOCAL_CRATE).then_some(LocalCrate) } } -impl Key for OwnerId { +impl QueryKey for OwnerId { type Cache = VecCache; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { @@ -122,7 +127,7 @@ impl Key for OwnerId { } } -impl Key for LocalDefId { +impl QueryKey for LocalDefId { type Cache = VecCache; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { @@ -134,7 +139,7 @@ impl Key for LocalDefId { } } -impl Key for DefId { +impl QueryKey for DefId { type Cache = DefIdCache; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { @@ -147,16 +152,16 @@ impl Key for DefId { } } -impl AsLocalKey for DefId { - type LocalKey = LocalDefId; +impl AsLocalQueryKey for DefId { + type LocalQueryKey = LocalDefId; #[inline(always)] - fn as_local_key(&self) -> Option { + fn as_local_key(&self) -> Option { self.as_local() } } -impl Key for LocalModDefId { +impl QueryKey for LocalModDefId { fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(*self) } @@ -167,19 +172,19 @@ impl Key for LocalModDefId { } } -impl Key for SimplifiedType { +impl QueryKey for SimplifiedType { fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP } } -impl Key for (DefId, DefId) { +impl QueryKey for (DefId, DefId) { fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.1.default_span(tcx) } } -impl Key for (DefId, Ident) { +impl QueryKey for (DefId, Ident) { fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(self.0) } @@ -190,73 +195,73 @@ impl Key for (DefId, Ident) { } } -impl Key for (LocalDefId, LocalDefId, Ident) { +impl QueryKey for (LocalDefId, LocalDefId, Ident) { fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.1.default_span(tcx) } } -impl Key for (CrateNum, DefId) { +impl QueryKey for (CrateNum, DefId) { fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.1.default_span(tcx) } } -impl AsLocalKey for (CrateNum, DefId) { - type LocalKey = DefId; +impl AsLocalQueryKey for (CrateNum, DefId) { + type LocalQueryKey = DefId; #[inline(always)] - fn as_local_key(&self) -> Option { + fn as_local_key(&self) -> Option { (self.0 == LOCAL_CRATE).then(|| self.1) } } -impl Key for (CrateNum, SimplifiedType) { +impl QueryKey for (CrateNum, SimplifiedType) { fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP } } -impl AsLocalKey for (CrateNum, SimplifiedType) { - type LocalKey = SimplifiedType; +impl AsLocalQueryKey for (CrateNum, SimplifiedType) { + type LocalQueryKey = SimplifiedType; #[inline(always)] - fn as_local_key(&self) -> Option { + fn as_local_key(&self) -> Option { (self.0 == LOCAL_CRATE).then(|| self.1) } } -impl Key for (DefId, ty::SizedTraitKind) { +impl QueryKey for (DefId, ty::SizedTraitKind) { fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.0.default_span(tcx) } } -impl<'tcx> Key for GenericArgsRef<'tcx> { +impl<'tcx> QueryKey for GenericArgsRef<'tcx> { fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP } } -impl<'tcx> Key for (DefId, GenericArgsRef<'tcx>) { +impl<'tcx> QueryKey for (DefId, GenericArgsRef<'tcx>) { fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.0.default_span(tcx) } } -impl<'tcx> Key for ty::TraitRef<'tcx> { +impl<'tcx> QueryKey for ty::TraitRef<'tcx> { fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(self.def_id) } } -impl<'tcx> Key for GenericArg<'tcx> { +impl<'tcx> QueryKey for GenericArg<'tcx> { fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP } } -impl<'tcx> Key for Ty<'tcx> { +impl<'tcx> QueryKey for Ty<'tcx> { fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP } @@ -270,19 +275,19 @@ impl<'tcx> Key for Ty<'tcx> { } } -impl<'tcx> Key for (Ty<'tcx>, Ty<'tcx>) { +impl<'tcx> QueryKey for (Ty<'tcx>, Ty<'tcx>) { fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP } } -impl<'tcx> Key for ty::Clauses<'tcx> { +impl<'tcx> QueryKey for ty::Clauses<'tcx> { fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP } } -impl<'tcx, T: Key> Key for ty::PseudoCanonicalInput<'tcx, T> { +impl<'tcx, T: QueryKey> QueryKey for ty::PseudoCanonicalInput<'tcx, T> { fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.value.default_span(tcx) } @@ -292,19 +297,19 @@ impl<'tcx, T: Key> Key for ty::PseudoCanonicalInput<'tcx, T> { } } -impl Key for Symbol { +impl QueryKey for Symbol { fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { DUMMY_SP } } -impl Key for Option { +impl QueryKey for Option { fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { DUMMY_SP } } -impl<'tcx> Key for &'tcx OsStr { +impl<'tcx> QueryKey for &'tcx OsStr { fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { DUMMY_SP } @@ -312,55 +317,55 @@ impl<'tcx> Key for &'tcx OsStr { /// Canonical query goals correspond to abstract trait operations that /// are not tied to any crate in particular. -impl<'tcx, T: Clone> Key for CanonicalQueryInput<'tcx, T> { +impl<'tcx, T: QueryKeyBounds> QueryKey for CanonicalQueryInput<'tcx, T> { fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { DUMMY_SP } } -impl<'tcx, T: Clone> Key for (CanonicalQueryInput<'tcx, T>, bool) { +impl<'tcx, T: QueryKeyBounds> QueryKey for (CanonicalQueryInput<'tcx, T>, bool) { fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { DUMMY_SP } } -impl<'tcx> Key for (Ty<'tcx>, rustc_abi::VariantIdx) { +impl<'tcx> QueryKey for (Ty<'tcx>, rustc_abi::VariantIdx) { fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { DUMMY_SP } } -impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) { +impl<'tcx> QueryKey for (ty::Predicate<'tcx>, traits::WellFormedLoc) { fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { DUMMY_SP } } -impl<'tcx> Key for (ty::PolyFnSig<'tcx>, &'tcx ty::List>) { +impl<'tcx> QueryKey for (ty::PolyFnSig<'tcx>, &'tcx ty::List>) { fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP } } -impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List>) { +impl<'tcx> QueryKey for (ty::Instance<'tcx>, &'tcx ty::List>) { fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.0.default_span(tcx) } } -impl<'tcx> Key for ty::Value<'tcx> { +impl<'tcx> QueryKey for ty::Value<'tcx> { fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP } } -impl<'tcx> Key for (LocalExpnId, &'tcx TokenStream) { +impl<'tcx> QueryKey for (LocalExpnId, &'tcx TokenStream) { fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { self.0.expn_data().call_site } } -impl<'tcx> Key for (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) { +impl<'tcx> QueryKey for (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) { // Just forward to `Ty<'tcx>` fn default_span(&self, _: TyCtxt<'_>) -> Span { @@ -375,7 +380,7 @@ impl<'tcx> Key for (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx> } } -impl<'tcx> Key for (ty::Instance<'tcx>, CollectionMode) { +impl<'tcx> QueryKey for (ty::Instance<'tcx>, CollectionMode) { fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.0.default_span(tcx) } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index bb457ab03fb55..eb252f18bbb98 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1,10 +1,8 @@ use rustc_hir::def_id::LocalDefId; -pub use self::caches::{ - DefIdCache, DefaultCache, QueryCache, QueryCacheKey, SingleCache, VecCache, -}; +pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCache}; pub use self::job::{QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryWaiter}; -pub use self::keys::{AsLocalKey, Key, LocalCrate}; +pub use self::keys::{AsLocalQueryKey, LocalCrate, QueryKey}; pub use self::plumbing::{ ActiveKeyStatus, CycleError, CycleErrorHandling, EnsureMode, IntoQueryParam, QueryMode, QueryState, TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk, diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index c2d524d200dee..55d760c55cd2f 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -157,6 +157,15 @@ pub struct QueryVTable<'tcx, C: QueryCache> { /// Used when reporting query cycle errors and similar problems. pub description_fn: fn(TyCtxt<'tcx>, C::Key) -> String, + /// Function pointer that is called by the query methods on [`TyCtxt`] and + /// friends[^1], after they have checked the in-memory cache and found no + /// existing value for this key. + /// + /// Transitive responsibilities include trying to load a disk-cached value + /// if possible (incremental only), invoking the query provider if necessary, + /// and putting the obtained value into the in-memory cache. + /// + /// [^1]: [`TyCtxt`], [`TyCtxtAt`], [`TyCtxtEnsureOk`], [`TyCtxtEnsureDone`] pub execute_query_fn: fn(TyCtxt<'tcx>, Span, C::Key, QueryMode) -> Option, } @@ -383,7 +392,7 @@ macro_rules! define_callbacks { pub type LocalKey<'tcx> = if_separate_provide_extern!( [$($modifiers)*] - ( as $crate::query::AsLocalKey>::LocalKey) + ( as $crate::query::AsLocalQueryKey>::LocalQueryKey) (Key<'tcx>) ); @@ -427,8 +436,8 @@ macro_rules! define_callbacks { erase::erase_val(value) } - pub type Storage<'tcx> = - as $crate::query::Key>::Cache>>; + pub type Cache<'tcx> = + as $crate::query::QueryKey>::Cache>>; // Ensure that keys grow no larger than 88 bytes by accident. // Increase this limit if necessary, but do try to keep the size low if possible @@ -495,8 +504,7 @@ macro_rules! define_callbacks { (crate::query::inner::query_ensure) )( self.tcx, - self.tcx.query_system.query_vtables.$name.execute_query_fn, - &self.tcx.query_system.query_vtables.$name.cache, + &self.tcx.query_system.query_vtables.$name, $crate::query::IntoQueryParam::into_query_param(key), $crate::query::EnsureMode::Ok, ) @@ -511,8 +519,7 @@ macro_rules! define_callbacks { pub fn $name(self, key: query_helper_param_ty!($($K)*)) { crate::query::inner::query_ensure( self.tcx, - self.tcx.query_system.query_vtables.$name.execute_query_fn, - &self.tcx.query_system.query_vtables.$name.cache, + &self.tcx.query_system.query_vtables.$name, $crate::query::IntoQueryParam::into_query_param(key), $crate::query::EnsureMode::Done, ); @@ -540,9 +547,8 @@ macro_rules! define_callbacks { erase::restore_val::<$V>(inner::query_get_at( self.tcx, - self.tcx.query_system.query_vtables.$name.execute_query_fn, - &self.tcx.query_system.query_vtables.$name.cache, self.span, + &self.tcx.query_system.query_vtables.$name, $crate::query::IntoQueryParam::into_query_param(key), )) } @@ -575,7 +581,7 @@ macro_rules! define_callbacks { /// Holds a `QueryVTable` for each query. pub struct QueryVTables<'tcx> { $( - pub $name: ::rustc_middle::query::plumbing::QueryVTable<'tcx, $name::Storage<'tcx>>, + pub $name: ::rustc_middle::query::plumbing::QueryVTable<'tcx, $name::Cache<'tcx>>, )* } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index d21f07a23e328..7107453faa615 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -29,7 +29,7 @@ use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{ self, DynSend, DynSync, FreezeReadGuard, Lock, RwLock, WorkerLocal, }; -use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, LintDiagnostic, MultiSpan}; +use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, MultiSpan}; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::definitions::{DefPathData, Definitions, DisambiguatorState}; @@ -2554,18 +2554,17 @@ impl<'tcx> TyCtxt<'tcx> { } } - /// Emit a lint from a lint struct (some type that implements `LintDiagnostic`, typically - /// generated by `#[derive(LintDiagnostic)]`). + /// Emit a lint from a lint struct (some type that implements `Diagnostic`, typically generated + /// by `#[derive(Diagnostic)]`). #[track_caller] pub fn emit_node_lint( self, lint: &'static Lint, id: HirId, - decorator: impl for<'a> LintDiagnostic<'a, ()>, + decorator: impl for<'a> Diagnostic<'a, ()>, ) { - self.node_lint(lint, id, |lint| { - decorator.decorate_lint(lint); - }) + let level = self.lint_level_at_node(lint, id); + diag_lint_level(self.sess, lint, level, None, decorator); } /// Emit a lint at the appropriate level for a hir node. diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 34720fc2f2958..820becd7031a4 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -4,7 +4,7 @@ use rustc_errors::{ }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::mir::AssertKind; -use rustc_middle::query::Key; +use rustc_middle::query::QueryKey; use rustc_middle::ty::TyCtxt; use rustc_session::lint::{self, Lint}; use rustc_span::def_id::DefId; diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs index 655dbe52df3e6..f4c1df145af35 100644 --- a/compiler/rustc_query_impl/src/execution.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -270,6 +270,7 @@ fn wait_for_query<'tcx, C: QueryCache>( } } +/// Shared main part of both [`execute_query_incr_inner`] and [`execute_query_non_incr_inner`]. #[inline(never)] fn try_execute_query<'tcx, C: QueryCache, const INCR: bool>( query: &'tcx QueryVTable<'tcx, C>, @@ -650,8 +651,10 @@ fn check_if_ensure_can_skip_execution<'tcx, C: QueryCache>( } } +/// Called by a macro-generated impl of [`QueryVTable::execute_query_fn`], +/// in non-incremental mode. #[inline(always)] -pub(super) fn get_query_non_incr<'tcx, C: QueryCache>( +pub(super) fn execute_query_non_incr_inner<'tcx, C: QueryCache>( query: &'tcx QueryVTable<'tcx, C>, tcx: TyCtxt<'tcx>, span: Span, @@ -662,8 +665,10 @@ pub(super) fn get_query_non_incr<'tcx, C: QueryCache>( ensure_sufficient_stack(|| try_execute_query::(query, tcx, span, key, None).0) } +/// Called by a macro-generated impl of [`QueryVTable::execute_query_fn`], +/// in incremental mode. #[inline(always)] -pub(super) fn get_query_incr<'tcx, C: QueryCache>( +pub(super) fn execute_query_incr_inner<'tcx, C: QueryCache>( query: &'tcx QueryVTable<'tcx, C>, tcx: TyCtxt<'tcx>, span: Span, diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index afb41f69b5ebb..1b93ffe945b3d 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -13,7 +13,7 @@ use rustc_middle::dep_graph; use rustc_middle::queries::{self, ExternProviders, Providers}; use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; use rustc_middle::query::plumbing::{QuerySystem, QueryVTable}; -use rustc_middle::query::{AsLocalKey, QueryCache, QueryMode}; +use rustc_middle::query::{AsLocalQueryKey, QueryCache, QueryMode}; use rustc_middle::ty::TyCtxt; use rustc_span::Span; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 275fe5b63d8b0..8920f8dba38d1 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -19,7 +19,8 @@ use rustc_middle::query::on_disk_cache::{ }; use rustc_middle::query::plumbing::QueryVTable; use rustc_middle::query::{ - Key, QueryCache, QueryJobId, QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra, erase, + QueryCache, QueryJobId, QueryKey, QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra, + erase, }; use rustc_middle::ty::codec::TyEncoder; use rustc_middle::ty::print::with_reduced_queries; @@ -274,7 +275,7 @@ fn mk_query_stack_frame_extra<'tcx, Cache>( ) -> QueryStackFrameExtra where Cache: QueryCache, - Cache::Key: Key, + Cache::Key: QueryKey, { let def_id = key.key_as_def_id(); @@ -313,7 +314,7 @@ pub(crate) fn create_deferred_query_stack_frame<'tcx, C>( ) -> QueryStackFrame> where C: QueryCache, - C::Key: Key + DynSend + DynSync, + C::Key: QueryKey + DynSend + DynSync, QueryVTable<'tcx, C>: DynSync, { let kind = vtable.dep_kind; @@ -475,7 +476,12 @@ macro_rules! define_queries { use super::super::*; use ::rustc_middle::query::erase::{self, Erased}; - pub(crate) mod get_query_incr { + // It seems to be important that every query has its own monomorphic + // copy of `execute_query_incr` and `execute_query_non_incr`. + // Trying to inline these wrapper functions into their generic + // "inner" helpers tends to break `tests/run-make/short-ice`. + + pub(crate) mod execute_query_incr { use super::*; // Adding `__rust_end_short_backtrace` marker to backtraces so that we emit the frames @@ -489,7 +495,7 @@ macro_rules! define_queries { ) -> Option>> { #[cfg(debug_assertions)] let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered(); - execution::get_query_incr( + execution::execute_query_incr_inner( &tcx.query_system.query_vtables.$name, tcx, span, @@ -499,7 +505,7 @@ macro_rules! define_queries { } } - pub(crate) mod get_query_non_incr { + pub(crate) mod execute_query_non_incr { use super::*; #[inline(never)] @@ -509,7 +515,7 @@ macro_rules! define_queries { key: queries::$name::Key<'tcx>, __mode: QueryMode, ) -> Option>> { - Some(execution::get_query_non_incr( + Some(execution::execute_query_non_incr_inner( &tcx.query_system.query_vtables.$name, tcx, span, @@ -549,7 +555,7 @@ macro_rules! define_queries { } pub(crate) fn make_query_vtable<'tcx>(incremental: bool) - -> QueryVTable<'tcx, queries::$name::Storage<'tcx>> + -> QueryVTable<'tcx, queries::$name::Cache<'tcx>> { QueryVTable { name: stringify!($name), @@ -604,9 +610,9 @@ macro_rules! define_queries { format_value: |value| format!("{:?}", erase::restore_val::>(*value)), description_fn: $crate::queries::_description_fns::$name, execute_query_fn: if incremental { - query_impl::$name::get_query_incr::__rust_end_short_backtrace + query_impl::$name::execute_query_incr::__rust_end_short_backtrace } else { - query_impl::$name::get_query_non_incr::__rust_end_short_backtrace + query_impl::$name::execute_query_non_incr::__rust_end_short_backtrace }, } } @@ -615,7 +621,7 @@ macro_rules! define_queries { pub(crate) enum VTableGetter {} impl<'tcx> GetQueryVTable<'tcx> for VTableGetter { - type Cache = rustc_middle::queries::$name::Storage<'tcx>; + type Cache = rustc_middle::queries::$name::Cache<'tcx>; #[inline(always)] fn query_vtable(tcx: TyCtxt<'tcx>) -> &'tcx QueryVTable<'tcx, Self::Cache> { diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 2bb9816a31005..0f4ff1790bdf2 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -422,7 +422,7 @@ pub enum RegionOriginNote<'a> { impl Subdiagnostic for RegionOriginNote<'_> { fn add_to_diag(self, diag: &mut Diag<'_, G>) { - let mut label_or_note = |span, msg: DiagMessage| { + let label_or_note = |diag: &mut Diag<'_, G>, span, msg: DiagMessage| { let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count(); let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count(); let span_is_primary = diag.span.primary_spans().iter().all(|&sp| sp == span); @@ -436,22 +436,26 @@ impl Subdiagnostic for RegionOriginNote<'_> { }; match self { RegionOriginNote::Plain { span, msg } => { - label_or_note(span, msg); + label_or_note(diag, span, msg); } RegionOriginNote::WithName { span, msg, name, continues } => { - label_or_note(span, msg); diag.arg("name", name); diag.arg("continues", continues); + label_or_note(diag, span, msg); } RegionOriginNote::WithRequirement { span, requirement, expected_found: Some((expected, found)), } => { - label_or_note( - span, - msg!( - "...so that the {$requirement -> + // `RegionOriginNote` can appear multiple times on one diagnostic with different + // `requirement` values. Scope args per-note and eagerly translate to avoid + // cross-note arg collisions. + // See https://github.com/rust-lang/rust/issues/143872 for details. + diag.store_args(); + diag.arg("requirement", requirement); + let msg = diag.eagerly_translate(msg!( + "...so that the {$requirement -> [method_compat] method type is compatible with trait [type_compat] associated type is compatible with trait [const_compat] const is compatible with trait @@ -464,9 +468,9 @@ impl Subdiagnostic for RegionOriginNote<'_> { [method_correct_type] method receiver has the correct type *[other] types are compatible }" - ), - ); - diag.arg("requirement", requirement); + )); + diag.restore_args(); + label_or_note(diag, span, msg); diag.note_expected_found("", expected, "", found); } @@ -474,10 +478,10 @@ impl Subdiagnostic for RegionOriginNote<'_> { // FIXME: this really should be handled at some earlier stage. Our // handling of region checking when type errors are present is // *terrible*. - label_or_note( - span, - msg!( - "...so that {$requirement -> + diag.store_args(); + diag.arg("requirement", requirement); + let msg = diag.eagerly_translate(msg!( + "...so that {$requirement -> [method_compat] method type is compatible with trait [type_compat] associated type is compatible with trait [const_compat] const is compatible with trait @@ -490,9 +494,9 @@ impl Subdiagnostic for RegionOriginNote<'_> { [method_correct_type] method receiver has the correct type *[other] types are compatible }" - ), - ); - diag.arg("requirement", requirement); + )); + diag.restore_args(); + label_or_note(diag, span, msg); } }; } diff --git a/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr b/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr index 709cf76b444c2..6c3fd9eb400f2 100644 --- a/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr +++ b/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr @@ -4,8 +4,8 @@ warning: creating a mutable reference to mutable static LL | let sfoo: *mut Foo = &mut SFOO; | ^^^^^^^^^ mutable reference to mutable static | - = note: for more information, see = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives + = note: for more information, see = note: `#[warn(static_mut_refs)]` (part of `#[warn(rust_2024_compatibility)]`) on by default help: use `&raw mut` instead to create a raw pointer | diff --git a/tests/ui/consts/const_let_assign2.stderr b/tests/ui/consts/const_let_assign2.stderr index ad3587b713411..e4edb58461054 100644 --- a/tests/ui/consts/const_let_assign2.stderr +++ b/tests/ui/consts/const_let_assign2.stderr @@ -4,8 +4,8 @@ warning: creating a mutable reference to mutable static LL | let ptr = unsafe { &mut BB }; | ^^^^^^^ mutable reference to mutable static | - = note: for more information, see = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives + = note: for more information, see = note: `#[warn(static_mut_refs)]` (part of `#[warn(rust_2024_compatibility)]`) on by default help: use `&raw mut` instead to create a raw pointer | diff --git a/tests/ui/deriving/internal_eq_trait_method_impls.stderr b/tests/ui/deriving/internal_eq_trait_method_impls.stderr index 8ff8fe337a78c..118c4011e33e9 100644 --- a/tests/ui/deriving/internal_eq_trait_method_impls.stderr +++ b/tests/ui/deriving/internal_eq_trait_method_impls.stderr @@ -28,9 +28,9 @@ error: `Eq::assert_receiver_is_total_eq` should never be implemented by hand LL | fn assert_receiver_is_total_eq(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = note: this method was used to add checks to the `Eq` derive macro = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #152336 - = note: this method was used to add checks to the `Eq` derive macro note: the lint level is defined here --> $DIR/internal_eq_trait_method_impls.rs:1:21 | diff --git a/tests/ui/issues/issue-39367.stderr b/tests/ui/issues/issue-39367.stderr index 1592b8b6672c7..e94c961f431d1 100644 --- a/tests/ui/issues/issue-39367.stderr +++ b/tests/ui/issues/issue-39367.stderr @@ -9,8 +9,8 @@ LL | | (Box::new(__static_ref_initialize())); LL | | }); | |______________^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see = note: `#[warn(static_mut_refs)]` (part of `#[warn(rust_2024_compatibility)]`) on by default warning: 1 warning emitted diff --git a/tests/ui/lint/static-mut-refs.e2021.stderr b/tests/ui/lint/static-mut-refs.e2021.stderr index 86854ab2ddab2..56b4ad239afe3 100644 --- a/tests/ui/lint/static-mut-refs.e2021.stderr +++ b/tests/ui/lint/static-mut-refs.e2021.stderr @@ -4,8 +4,8 @@ warning: creating a shared reference to mutable static LL | let _y = &X; | ^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see = note: `#[warn(static_mut_refs)]` (part of `#[warn(rust_2024_compatibility)]`) on by default help: use `&raw const` instead to create a raw pointer | @@ -18,8 +18,8 @@ warning: creating a mutable reference to mutable static LL | let _y = &mut X; | ^^^^^^ mutable reference to mutable static | - = note: for more information, see = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives + = note: for more information, see help: use `&raw mut` instead to create a raw pointer | LL | let _y = &raw mut X; @@ -31,8 +31,8 @@ warning: creating a shared reference to mutable static LL | let ref _a = X; | ^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see warning: creating a shared reference to mutable static --> $DIR/static-mut-refs.rs:54:25 @@ -40,8 +40,8 @@ warning: creating a shared reference to mutable static LL | let (_b, _c) = (&X, &Y); | ^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see help: use `&raw const` instead to create a raw pointer | LL | let (_b, _c) = (&raw const X, &Y); @@ -53,8 +53,8 @@ warning: creating a shared reference to mutable static LL | let (_b, _c) = (&X, &Y); | ^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see help: use `&raw const` instead to create a raw pointer | LL | let (_b, _c) = (&X, &raw const Y); @@ -66,8 +66,8 @@ warning: creating a shared reference to mutable static LL | foo(&X); | ^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see help: use `&raw const` instead to create a raw pointer | LL | foo(&raw const X); @@ -79,8 +79,8 @@ warning: creating a shared reference to mutable static LL | let _ = Z.len(); | ^^^^^^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see warning: creating a shared reference to mutable static --> $DIR/static-mut-refs.rs:72:33 @@ -88,8 +88,8 @@ warning: creating a shared reference to mutable static LL | let _ = format!("{:?}", Z); | ^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see warning: creating a shared reference to mutable static --> $DIR/static-mut-refs.rs:76:18 @@ -97,8 +97,8 @@ warning: creating a shared reference to mutable static LL | let _v = &A.value; | ^^^^^^^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see help: use `&raw const` instead to create a raw pointer | LL | let _v = &raw const A.value; @@ -110,8 +110,8 @@ warning: creating a shared reference to mutable static LL | let _s = &A.s.value; | ^^^^^^^^^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see help: use `&raw const` instead to create a raw pointer | LL | let _s = &raw const A.s.value; @@ -123,8 +123,8 @@ warning: creating a shared reference to mutable static LL | let ref _v = A.value; | ^^^^^^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see warning: creating a mutable reference to mutable static --> $DIR/static-mut-refs.rs:14:14 @@ -135,8 +135,8 @@ LL | &mut ($x.0) LL | let _x = bar!(FOO); | --------- in this macro invocation | - = note: for more information, see = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives + = note: for more information, see = note: this warning originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) warning: 12 warnings emitted diff --git a/tests/ui/lint/static-mut-refs.e2024.stderr b/tests/ui/lint/static-mut-refs.e2024.stderr index 5c21c5b0dd9b3..0b7f48a507c94 100644 --- a/tests/ui/lint/static-mut-refs.e2024.stderr +++ b/tests/ui/lint/static-mut-refs.e2024.stderr @@ -4,8 +4,8 @@ error: creating a shared reference to mutable static LL | let _y = &X; | ^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see = note: `#[deny(static_mut_refs)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `&raw const` instead to create a raw pointer | @@ -18,8 +18,8 @@ error: creating a mutable reference to mutable static LL | let _y = &mut X; | ^^^^^^ mutable reference to mutable static | - = note: for more information, see = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives + = note: for more information, see help: use `&raw mut` instead to create a raw pointer | LL | let _y = &raw mut X; @@ -31,8 +31,8 @@ error: creating a shared reference to mutable static LL | let ref _a = X; | ^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see error: creating a shared reference to mutable static --> $DIR/static-mut-refs.rs:54:25 @@ -40,8 +40,8 @@ error: creating a shared reference to mutable static LL | let (_b, _c) = (&X, &Y); | ^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see help: use `&raw const` instead to create a raw pointer | LL | let (_b, _c) = (&raw const X, &Y); @@ -53,8 +53,8 @@ error: creating a shared reference to mutable static LL | let (_b, _c) = (&X, &Y); | ^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see help: use `&raw const` instead to create a raw pointer | LL | let (_b, _c) = (&X, &raw const Y); @@ -66,8 +66,8 @@ error: creating a shared reference to mutable static LL | foo(&X); | ^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see help: use `&raw const` instead to create a raw pointer | LL | foo(&raw const X); @@ -79,8 +79,8 @@ error: creating a shared reference to mutable static LL | let _ = Z.len(); | ^^^^^^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see error: creating a shared reference to mutable static --> $DIR/static-mut-refs.rs:72:33 @@ -88,8 +88,8 @@ error: creating a shared reference to mutable static LL | let _ = format!("{:?}", Z); | ^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see error: creating a shared reference to mutable static --> $DIR/static-mut-refs.rs:76:18 @@ -97,8 +97,8 @@ error: creating a shared reference to mutable static LL | let _v = &A.value; | ^^^^^^^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see help: use `&raw const` instead to create a raw pointer | LL | let _v = &raw const A.value; @@ -110,8 +110,8 @@ error: creating a shared reference to mutable static LL | let _s = &A.s.value; | ^^^^^^^^^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see help: use `&raw const` instead to create a raw pointer | LL | let _s = &raw const A.s.value; @@ -123,8 +123,8 @@ error: creating a shared reference to mutable static LL | let ref _v = A.value; | ^^^^^^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see error: creating a mutable reference to mutable static --> $DIR/static-mut-refs.rs:14:14 @@ -135,8 +135,8 @@ LL | &mut ($x.0) LL | let _x = bar!(FOO); | --------- in this macro invocation | - = note: for more information, see = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives + = note: for more information, see = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 12 previous errors diff --git a/tests/ui/macros/non-fmt-panic.stderr b/tests/ui/macros/non-fmt-panic.stderr index edef9d8d97c43..9cadaf3fbe388 100644 --- a/tests/ui/macros/non-fmt-panic.stderr +++ b/tests/ui/macros/non-fmt-panic.stderr @@ -4,8 +4,8 @@ warning: panic message contains a brace LL | panic!("here's a brace: {"); | ^ | - = note: for more information, see = note: this message is not used as a format string, but will be in Rust 2021 + = note: for more information, see = note: `#[warn(non_fmt_panics)]` (part of `#[warn(rust_2021_compatibility)]`) on by default help: add a "{}" format string to use the message literally | @@ -18,8 +18,8 @@ warning: panic message contains a brace LL | unreachable!("here's a brace: {"); | ^ | - = note: for more information, see = note: this message is not used as a format string, but will be in Rust 2021 + = note: for more information, see help: add a "{}" format string to use the message literally | LL | unreachable!("{}", "here's a brace: {"); @@ -31,8 +31,8 @@ warning: panic message contains a brace LL | std::panic!("another one: }"); | ^ | - = note: for more information, see = note: this message is not used as a format string, but will be in Rust 2021 + = note: for more information, see help: add a "{}" format string to use the message literally | LL | std::panic!("{}", "another one: }"); @@ -44,8 +44,8 @@ warning: panic message contains an unused formatting placeholder LL | core::panic!("Hello {}"); | ^^ | - = note: for more information, see = note: this message is not used as a format string when given without arguments, but will be in Rust 2021 + = note: for more information, see help: add the missing argument | LL | core::panic!("Hello {}", ...); @@ -61,8 +61,8 @@ warning: panic message contains unused formatting placeholders LL | assert!(false, "{:03x} {test} bla"); | ^^^^^^ ^^^^^^ | - = note: for more information, see = note: this message is not used as a format string when given without arguments, but will be in Rust 2021 + = note: for more information, see help: add the missing arguments | LL | assert!(false, "{:03x} {test} bla", ...); @@ -120,8 +120,8 @@ warning: panic message contains braces LL | debug_assert!(false, "{{}} bla"); | ^^^^ | - = note: for more information, see = note: this message is not used as a format string, but will be in Rust 2021 + = note: for more information, see help: add a "{}" format string to use the message literally | LL | debug_assert!(false, "{}", "{{}} bla"); @@ -241,8 +241,8 @@ warning: panic message contains an unused formatting placeholder LL | panic!(concat!("{", "}")); | ^^^^^^^^^^^^^^^^^ | - = note: for more information, see = note: this message is not used as a format string when given without arguments, but will be in Rust 2021 + = note: for more information, see help: add the missing argument | LL | panic!(concat!("{", "}"), ...); @@ -258,8 +258,8 @@ warning: panic message contains braces LL | panic!(concat!("{", "{")); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: for more information, see = note: this message is not used as a format string, but will be in Rust 2021 + = note: for more information, see help: add a "{}" format string to use the message literally | LL | panic!("{}", concat!("{", "{")); @@ -271,8 +271,8 @@ warning: panic message contains an unused formatting placeholder LL | fancy_panic::fancy_panic!("test {} 123"); | ^^ | - = note: for more information, see = note: this message is not used as a format string when given without arguments, but will be in Rust 2021 + = note: for more information, see warning: panic message is not a string literal --> $DIR/non-fmt-panic.rs:53:12 diff --git a/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr b/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr index 63744c15fda9c..19a3a786ac940 100644 --- a/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr +++ b/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr @@ -4,8 +4,8 @@ warning: creating a mutable reference to mutable static LL | S1 { a: unsafe { &mut X1 } } | ^^^^^^^ mutable reference to mutable static | - = note: for more information, see = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives + = note: for more information, see = note: `#[warn(static_mut_refs)]` (part of `#[warn(rust_2024_compatibility)]`) on by default help: use `&raw mut` instead to create a raw pointer | diff --git a/tests/ui/statics/issue-15261.stderr b/tests/ui/statics/issue-15261.stderr index 20ac078524508..fdc8e0c1f5ef7 100644 --- a/tests/ui/statics/issue-15261.stderr +++ b/tests/ui/statics/issue-15261.stderr @@ -4,8 +4,8 @@ warning: creating a shared reference to mutable static LL | static n: &'static usize = unsafe { &n_mut }; | ^^^^^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see = note: `#[warn(static_mut_refs)]` (part of `#[warn(rust_2024_compatibility)]`) on by default help: use `&raw const` instead to create a raw pointer | diff --git a/tests/ui/statics/static-mut-shared-parens.stderr b/tests/ui/statics/static-mut-shared-parens.stderr index c900fcde16f6a..1265bdc7cf0d3 100644 --- a/tests/ui/statics/static-mut-shared-parens.stderr +++ b/tests/ui/statics/static-mut-shared-parens.stderr @@ -4,8 +4,8 @@ warning: creating a shared reference to mutable static LL | let _ = unsafe { (&TEST) as *const usize }; | ^^^^^^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see = note: `#[warn(static_mut_refs)]` (part of `#[warn(rust_2024_compatibility)]`) on by default help: use `&raw const` instead to create a raw pointer | @@ -18,8 +18,8 @@ warning: creating a mutable reference to mutable static LL | let _ = unsafe { (&mut TEST) as *const usize }; | ^^^^^^^^^^^ mutable reference to mutable static | - = note: for more information, see = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives + = note: for more information, see help: use `&raw mut` instead to create a raw pointer | LL | let _ = unsafe { (&raw mut TEST) as *const usize }; diff --git a/tests/ui/statics/static-mut-xc.stderr b/tests/ui/statics/static-mut-xc.stderr index 73c4e91b8e034..d0b30ce6f8514 100644 --- a/tests/ui/statics/static-mut-xc.stderr +++ b/tests/ui/statics/static-mut-xc.stderr @@ -4,8 +4,8 @@ warning: creating a shared reference to mutable static LL | assert_eq!(static_mut_xc::a, 3); | ^^^^^^^^^^^^^^^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see = note: `#[warn(static_mut_refs)]` (part of `#[warn(rust_2024_compatibility)]`) on by default warning: creating a shared reference to mutable static @@ -14,8 +14,8 @@ warning: creating a shared reference to mutable static LL | assert_eq!(static_mut_xc::a, 4); | ^^^^^^^^^^^^^^^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see warning: creating a shared reference to mutable static --> $DIR/static-mut-xc.rs:25:16 @@ -23,8 +23,8 @@ warning: creating a shared reference to mutable static LL | assert_eq!(static_mut_xc::a, 5); | ^^^^^^^^^^^^^^^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see warning: creating a shared reference to mutable static --> $DIR/static-mut-xc.rs:28:16 @@ -32,8 +32,8 @@ warning: creating a shared reference to mutable static LL | assert_eq!(static_mut_xc::a, 15); | ^^^^^^^^^^^^^^^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see warning: creating a shared reference to mutable static --> $DIR/static-mut-xc.rs:31:16 @@ -41,8 +41,8 @@ warning: creating a shared reference to mutable static LL | assert_eq!(static_mut_xc::a, -3); | ^^^^^^^^^^^^^^^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see warning: creating a shared reference to mutable static --> $DIR/static-mut-xc.rs:33:18 @@ -50,8 +50,8 @@ warning: creating a shared reference to mutable static LL | static_bound(&static_mut_xc::a); | ^^^^^^^^^^^^^^^^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see help: use `&raw const` instead to create a raw pointer | LL | static_bound(&raw const static_mut_xc::a); @@ -63,8 +63,8 @@ warning: creating a mutable reference to mutable static LL | static_bound_set(&mut static_mut_xc::a); | ^^^^^^^^^^^^^^^^^^^^^ mutable reference to mutable static | - = note: for more information, see = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives + = note: for more information, see help: use `&raw mut` instead to create a raw pointer | LL | static_bound_set(&raw mut static_mut_xc::a); diff --git a/tests/ui/statics/static-recursive.stderr b/tests/ui/statics/static-recursive.stderr index 16d5e183ccbd7..1ae96dfd5a832 100644 --- a/tests/ui/statics/static-recursive.stderr +++ b/tests/ui/statics/static-recursive.stderr @@ -4,8 +4,8 @@ warning: creating a shared reference to mutable static LL | static mut S: *const u8 = unsafe { &S as *const *const u8 as *const u8 }; | ^^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see = note: `#[warn(static_mut_refs)]` (part of `#[warn(rust_2024_compatibility)]`) on by default help: use `&raw const` instead to create a raw pointer | @@ -18,8 +18,8 @@ warning: creating a shared reference to mutable static LL | assert_eq!(S, *(S as *const *const u8)); | ^ shared reference to mutable static | - = note: for more information, see = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see warning: 2 warnings emitted diff --git a/tests/ui/traits/compare-impl-item-conflicting-lifetime-requirements.rs b/tests/ui/traits/compare-impl-item-conflicting-lifetime-requirements.rs new file mode 100644 index 0000000000000..5cf5dcc34d6d4 --- /dev/null +++ b/tests/ui/traits/compare-impl-item-conflicting-lifetime-requirements.rs @@ -0,0 +1,23 @@ +//@ compile-flags: --crate-type=lib +// Regression test for https://github.com/rust-lang/rust/issues/143872 + +trait Project { + type Ty; +} + +impl Project for &'_ &'static () { + type Ty = (); +} + +trait Trait { + fn get<'s>(s: &'s str, _: ()) -> &'_ str; +} + +impl Trait for () { + fn get<'s>(s: &'s str, _: <&&'s () as Project>::Ty) -> &'static str { + //~^ ERROR cannot infer an appropriate lifetime for lifetime parameter 's in generic type due to conflicting requirements + //~| ERROR mismatched types + //~| ERROR lifetime may not live long enough + s + } +} diff --git a/tests/ui/traits/compare-impl-item-conflicting-lifetime-requirements.stderr b/tests/ui/traits/compare-impl-item-conflicting-lifetime-requirements.stderr new file mode 100644 index 0000000000000..f6ae851430cd8 --- /dev/null +++ b/tests/ui/traits/compare-impl-item-conflicting-lifetime-requirements.stderr @@ -0,0 +1,55 @@ +error[E0803]: cannot infer an appropriate lifetime for lifetime parameter 's in generic type due to conflicting requirements + --> $DIR/compare-impl-item-conflicting-lifetime-requirements.rs:17:5 + | +LL | fn get<'s>(s: &'s str, _: <&&'s () as Project>::Ty) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first, the lifetime cannot outlive the lifetime `'s` as defined here... + --> $DIR/compare-impl-item-conflicting-lifetime-requirements.rs:13:12 + | +LL | fn get<'s>(s: &'s str, _: ()) -> &'_ str; + | ^^ +note: ...so that the method type is compatible with trait + --> $DIR/compare-impl-item-conflicting-lifetime-requirements.rs:17:5 + | +LL | fn get<'s>(s: &'s str, _: <&&'s () as Project>::Ty) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected `fn(&'s _, ()) -> &'s _` + found `fn(&_, ()) -> &'static _` + = note: but, the lifetime must be valid for the static lifetime... +note: ...so that the types are compatible + --> $DIR/compare-impl-item-conflicting-lifetime-requirements.rs:17:5 + | +LL | fn get<'s>(s: &'s str, _: <&&'s () as Project>::Ty) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected `<&&() as Project>` + found `<&&'static () as Project>` + +error[E0308]: mismatched types + --> $DIR/compare-impl-item-conflicting-lifetime-requirements.rs:17:31 + | +LL | fn get<'s>(s: &'s str, _: <&&'s () as Project>::Ty) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected trait `<&&'s () as Project>` + found trait `<&&'static () as Project>` +note: the lifetime `'s` as defined here... + --> $DIR/compare-impl-item-conflicting-lifetime-requirements.rs:17:12 + | +LL | fn get<'s>(s: &'s str, _: <&&'s () as Project>::Ty) -> &'static str { + | ^^ + = note: ...does not necessarily outlive the static lifetime + +error: lifetime may not live long enough + --> $DIR/compare-impl-item-conflicting-lifetime-requirements.rs:17:5 + | +LL | fn get<'s>(s: &'s str, _: <&&'s () as Project>::Ty) -> &'static str { + | ^^^^^^^--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | lifetime `'s` defined here + | requires that `'s` must outlive `'static` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0803. +For more information about an error, try `rustc --explain E0308`.