Skip to content

Commit 0810a03

Browse files
committed
Add an internal lint that warns when accessing untracked data
1 parent 19469cb commit 0810a03

File tree

11 files changed

+80
-35
lines changed

11 files changed

+80
-35
lines changed

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
}

compiler/rustc_feature/src/builtin_attrs.rs

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

compiler/rustc_lint/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,9 @@ lint_ptr_null_checks_ref = references are not nullable, so checking them for nul
690690
lint_query_instability = using `{$query}` can result in unstable query results
691691
.note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale
692692
693+
lint_query_untracked = `{$method}` accesses information that is not tracked by the query system
694+
.note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale
695+
693696
lint_range_endpoint_out_of_range = range endpoint is out of range for `{$ty}`
694697
695698
lint_range_use_inclusive_range = use an inclusive range instead

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, UntranslatableDiag,
20+
NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag, TyQualified,
21+
TykindDiag, TykindKind, 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
}

compiler/rustc_lint/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,7 @@ fn register_internals(store: &mut LintStore) {
604604
vec![
605605
LintId::of(DEFAULT_HASH_TYPES),
606606
LintId::of(POTENTIAL_QUERY_INSTABILITY),
607+
LintId::of(UNTRACKED_QUERY_INFORMATION),
607608
LintId::of(USAGE_OF_TY_TYKIND),
608609
LintId::of(PASS_BY_VALUE),
609610
LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),

compiler/rustc_lint/src/lints.rs

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

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

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, ..] => {
@@ -451,11 +456,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
451456
}
452457
}
453458

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

1606-
/// Checks that the `#[rustc_lint_query_instability]` attribute is only applied to a function
1607-
/// or method.
1608-
fn check_rustc_lint_query_instability(
1609-
&self,
1610-
hir_id: HirId,
1611-
attr: &Attribute,
1612-
span: Span,
1613-
target: Target,
1614-
) {
1615-
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
1616-
}
1617-
1618-
/// Checks that the `#[rustc_lint_diagnostics]` attribute is only applied to a function or
1619-
/// method.
1620-
fn check_rustc_lint_diagnostics(
1621-
&self,
1622-
hir_id: HirId,
1623-
attr: &Attribute,
1624-
span: Span,
1625-
target: Target,
1626-
) {
1627-
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
1628-
}
1629-
16301606
/// Checks that the `#[rustc_lint_opt_ty]` attribute is only applied to a struct.
16311607
fn check_rustc_lint_opt_ty(&self, attr: &Attribute, span: Span, target: Target) {
16321608
match target {

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1644,6 +1644,7 @@ symbols! {
16441644
rustc_lint_opt_deny_field_access,
16451645
rustc_lint_opt_ty,
16461646
rustc_lint_query_instability,
1647+
rustc_lint_untracked_query_information,
16471648
rustc_macro_transparency,
16481649
rustc_main,
16491650
rustc_mir,

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),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//@ compile-flags: -Z unstable-options
2+
#![feature(rustc_private)]
3+
#![deny(rustc::untracked_query_information)]
4+
5+
extern crate rustc_data_structures;
6+
7+
use rustc_data_structures::steal::Steal;
8+
9+
fn use_steal(x: Steal<()>) {
10+
let _ = x.is_stolen();
11+
//~^ ERROR `is_stolen` accesses information that is not tracked by the query system
12+
}
13+
14+
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:10: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:3: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)