Skip to content

Commit 46f390f

Browse files
authored
Rollup merge of rust-lang#128919 - Nadrieril:lint-query-leaks, r=cjgillot
Add an internal lint that warns when accessing untracked data Some methods access data that is not tracked by the query system and should be used with caution. As suggested in rust-lang#128815 (comment), in this PR I propose a lint (modeled on the `potential_query_instability` lint) that warns when using some specially-annotatted functions. I can't tell myself if this lint would be that useful, compared to renaming `Steal::is_stolen` to `is_stolen_untracked`. This would depend on whether there are other functions we'd want to lint like this. So far it seems they're called `*_untracked`, which may be clear enough. r? ``@oli-obk``
2 parents eb33b43 + 0402394 commit 46f390f

File tree

11 files changed

+82
-35
lines changed

11 files changed

+82
-35
lines changed

Diff for: compiler/rustc_data_structures/src/steal.rs

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ impl<T> Steal<T> {
5757
///
5858
/// This should not be used within rustc as it leaks information not tracked
5959
/// by the query system, breaking incremental compilation.
60+
#[cfg_attr(not(bootstrap), rustc_lint_untracked_query_information)]
6061
pub fn is_stolen(&self) -> bool {
6162
self.value.borrow().is_none()
6263
}

Diff for: compiler/rustc_feature/src/builtin_attrs.rs

+6
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
793793
rustc_lint_query_instability, Normal, template!(Word),
794794
WarnFollowing, EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
795795
),
796+
// Used by the `rustc::untracked_query_information` lint to warn methods which
797+
// might not be stable during incremental compilation.
798+
rustc_attr!(
799+
rustc_lint_untracked_query_information, Normal, template!(Word),
800+
WarnFollowing, EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
801+
),
796802
// Used by the `rustc::diagnostic_outside_of_impl` lints to assist in changes to diagnostic
797803
// APIs. Any function with this attribute will be checked by that lint.
798804
rustc_attr!(

Diff for: compiler/rustc_lint/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,9 @@ lint_ptr_null_checks_ref = references are not nullable, so checking them for nul
699699
lint_query_instability = using `{$query}` can result in unstable query results
700700
.note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale
701701
702+
lint_query_untracked = `{$method}` accesses information that is not tracked by the query system
703+
.note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale
704+
702705
lint_range_endpoint_out_of_range = range endpoint is out of range for `{$ty}`
703706
704707
lint_range_use_inclusive_range = use an inclusive range instead

Diff for: compiler/rustc_lint/src/internal.rs

+21-3
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ use tracing::debug;
1717

1818
use crate::lints::{
1919
BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword,
20-
NonGlobImportTypeIrInherent, QueryInstability, SpanUseEqCtxtDiag, TyQualified, TykindDiag,
21-
TykindKind, TypeIrInherentUsage, UntranslatableDiag,
20+
NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag, TyQualified,
21+
TykindDiag, TykindKind, TypeIrInherentUsage, UntranslatableDiag,
2222
};
2323
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
2424

@@ -88,7 +88,18 @@ declare_tool_lint! {
8888
report_in_external_macro: true
8989
}
9090

91-
declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY]);
91+
declare_tool_lint! {
92+
/// The `untracked_query_information` lint detects use of methods which leak information not
93+
/// tracked by the query system, such as whether a `Steal<T>` value has already been stolen. In
94+
/// order not to break incremental compilation, such methods must be used very carefully or not
95+
/// at all.
96+
pub rustc::UNTRACKED_QUERY_INFORMATION,
97+
Allow,
98+
"require explicit opt-in when accessing information not tracked by the query system",
99+
report_in_external_macro: true
100+
}
101+
102+
declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY, UNTRACKED_QUERY_INFORMATION]);
92103

93104
impl LateLintPass<'_> for QueryStability {
94105
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
@@ -102,6 +113,13 @@ impl LateLintPass<'_> for QueryStability {
102113
QueryInstability { query: cx.tcx.item_name(def_id) },
103114
);
104115
}
116+
if cx.tcx.has_attr(def_id, sym::rustc_lint_untracked_query_information) {
117+
cx.emit_span_lint(
118+
UNTRACKED_QUERY_INFORMATION,
119+
span,
120+
QueryUntracked { method: cx.tcx.item_name(def_id) },
121+
);
122+
}
105123
}
106124
}
107125
}

Diff for: compiler/rustc_lint/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,7 @@ fn register_internals(store: &mut LintStore) {
609609
vec![
610610
LintId::of(DEFAULT_HASH_TYPES),
611611
LintId::of(POTENTIAL_QUERY_INSTABILITY),
612+
LintId::of(UNTRACKED_QUERY_INFORMATION),
612613
LintId::of(USAGE_OF_TY_TYKIND),
613614
LintId::of(PASS_BY_VALUE),
614615
LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),

Diff for: compiler/rustc_lint/src/lints.rs

+7
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,13 @@ pub(crate) struct QueryInstability {
894894
pub query: Symbol,
895895
}
896896

897+
#[derive(LintDiagnostic)]
898+
#[diag(lint_query_untracked)]
899+
#[note]
900+
pub(crate) struct QueryUntracked {
901+
pub method: Symbol,
902+
}
903+
897904
#[derive(LintDiagnostic)]
898905
#[diag(lint_span_use_eq_ctxt)]
899906
pub(crate) struct SpanUseEqCtxtDiag;

Diff for: compiler/rustc_passes/src/check_attr.rs

+8-32
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
125125
[sym::inline, ..] => self.check_inline(hir_id, attr, span, target),
126126
[sym::coverage, ..] => self.check_coverage(attr, span, target),
127127
[sym::optimize, ..] => self.check_optimize(hir_id, attr, target),
128-
[sym::no_sanitize, ..] => self.check_no_sanitize(hir_id, attr, span, target),
128+
[sym::no_sanitize, ..] => {
129+
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
130+
}
129131
[sym::non_exhaustive, ..] => self.check_non_exhaustive(hir_id, attr, span, target),
130132
[sym::marker, ..] => self.check_marker(hir_id, attr, span, target),
131133
[sym::target_feature, ..] => {
@@ -166,10 +168,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
166168
self.check_rustc_legacy_const_generics(hir_id, attr, span, target, item)
167169
}
168170
[sym::rustc_lint_query_instability, ..] => {
169-
self.check_rustc_lint_query_instability(hir_id, attr, span, target)
171+
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
172+
}
173+
[sym::rustc_lint_untracked_query_information, ..] => {
174+
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
170175
}
171176
[sym::rustc_lint_diagnostics, ..] => {
172-
self.check_rustc_lint_diagnostics(hir_id, attr, span, target)
177+
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
173178
}
174179
[sym::rustc_lint_opt_ty, ..] => self.check_rustc_lint_opt_ty(attr, span, target),
175180
[sym::rustc_lint_opt_deny_field_access, ..] => {
@@ -452,11 +457,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
452457
}
453458
}
454459

455-
/// Checks that `#[no_sanitize(..)]` is applied to a function or method.
456-
fn check_no_sanitize(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
457-
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
458-
}
459-
460460
fn check_generic_attr(
461461
&self,
462462
hir_id: HirId,
@@ -1635,30 +1635,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
16351635
}
16361636
}
16371637

1638-
/// Checks that the `#[rustc_lint_query_instability]` attribute is only applied to a function
1639-
/// or method.
1640-
fn check_rustc_lint_query_instability(
1641-
&self,
1642-
hir_id: HirId,
1643-
attr: &Attribute,
1644-
span: Span,
1645-
target: Target,
1646-
) {
1647-
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
1648-
}
1649-
1650-
/// Checks that the `#[rustc_lint_diagnostics]` attribute is only applied to a function or
1651-
/// method.
1652-
fn check_rustc_lint_diagnostics(
1653-
&self,
1654-
hir_id: HirId,
1655-
attr: &Attribute,
1656-
span: Span,
1657-
target: Target,
1658-
) {
1659-
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
1660-
}
1661-
16621638
/// Checks that the `#[rustc_lint_opt_ty]` attribute is only applied to a struct.
16631639
fn check_rustc_lint_opt_ty(&self, attr: &Attribute, span: Span, target: Target) {
16641640
match target {

Diff for: compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1654,6 +1654,7 @@ symbols! {
16541654
rustc_lint_opt_deny_field_access,
16551655
rustc_lint_opt_ty,
16561656
rustc_lint_query_instability,
1657+
rustc_lint_untracked_query_information,
16571658
rustc_macro_transparency,
16581659
rustc_main,
16591660
rustc_mir,

Diff for: src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs

+3
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,9 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[
464464
// Used by the `rustc::potential_query_instability` lint to warn methods which
465465
// might not be stable during incremental compilation.
466466
rustc_attr!(rustc_lint_query_instability, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
467+
// Used by the `rustc::untracked_query_information` lint to warn methods which
468+
// might break incremental compilation.
469+
rustc_attr!(rustc_lint_untracked_query_information, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
467470
// Used by the `rustc::untranslatable_diagnostic` and `rustc::diagnostic_outside_of_impl` lints
468471
// to assist in changes to diagnostic APIs.
469472
rustc_attr!(rustc_lint_diagnostics, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//@ compile-flags: -Z unstable-options
2+
// #[cfg(bootstrap)]: We can stop ignoring next beta bump; afterward this ALWAYS should run.
3+
//@ ignore-stage1 (requires matching sysroot built with in-tree compiler)
4+
#![feature(rustc_private)]
5+
#![deny(rustc::untracked_query_information)]
6+
7+
extern crate rustc_data_structures;
8+
9+
use rustc_data_structures::steal::Steal;
10+
11+
fn use_steal(x: Steal<()>) {
12+
let _ = x.is_stolen();
13+
//~^ ERROR `is_stolen` accesses information that is not tracked by the query system
14+
}
15+
16+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: `is_stolen` accesses information that is not tracked by the query system
2+
--> $DIR/query_completeness.rs:12:15
3+
|
4+
LL | let _ = x.is_stolen();
5+
| ^^^^^^^^^
6+
|
7+
= note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
8+
note: the lint level is defined here
9+
--> $DIR/query_completeness.rs:5:9
10+
|
11+
LL | #![deny(rustc::untracked_query_information)]
12+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
13+
14+
error: aborting due to 1 previous error
15+

0 commit comments

Comments
 (0)