@@ -5,10 +5,7 @@ use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}
5
5
use rustc_ast as ast;
6
6
use rustc_errors:: Applicability ;
7
7
use rustc_hir:: def:: Res ;
8
- use rustc_hir:: {
9
- GenericArg , HirId , Item , ItemKind , MutTy , Mutability , Node , Path , PathSegment , QPath , Ty ,
10
- TyKind ,
11
- } ;
8
+ use rustc_hir:: * ;
12
9
use rustc_middle:: ty;
13
10
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
14
11
use rustc_span:: hygiene:: { ExpnKind , MacroKind } ;
@@ -51,6 +48,60 @@ impl LateLintPass<'_> for DefaultHashTypes {
51
48
}
52
49
}
53
50
51
+ declare_tool_lint ! {
52
+ pub rustc:: POTENTIAL_QUERY_INSTABILITY ,
53
+ Allow ,
54
+ "require explicit opt-in when using potentially unstable methods or functions" ,
55
+ report_in_external_macro: true
56
+ }
57
+
58
+ declare_lint_pass ! ( QueryStability => [ POTENTIAL_QUERY_INSTABILITY ] ) ;
59
+
60
+ impl LateLintPass < ' _ > for QueryStability {
61
+ fn check_expr ( & mut self , cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) {
62
+ // FIXME(rustdoc): This lint uses typecheck results, causing rustdoc to
63
+ // error if there are resolution failures.
64
+ //
65
+ // As internal lints are currently always run if there are `unstable_options`,
66
+ // they are added to the lint store of rustdoc. Internal lints are also
67
+ // not used via the `lint_mod` query. Crate lints run outside of a query
68
+ // so rustdoc currently doesn't disable them.
69
+ //
70
+ // Instead of relying on this, either change crate lints to a query disabled by
71
+ // rustdoc, only run internal lints if the user is explicitly opting in
72
+ // or figure out a different way to avoid running lints for rustdoc.
73
+ if cx. tcx . sess . opts . actually_rustdoc {
74
+ return ;
75
+ }
76
+
77
+ let ( def_id, span) = match expr. kind {
78
+ ExprKind :: Path ( ref path) if let Some ( def_id) = cx. qpath_res ( path, expr. hir_id ) . opt_def_id ( ) => {
79
+ ( def_id, expr. span )
80
+ }
81
+ ExprKind :: MethodCall ( _, span, _, _) if let Some ( def_id) = cx. typeck_results ( ) . type_dependent_def_id ( expr. hir_id ) => {
82
+ ( def_id, span)
83
+ } ,
84
+ _ => return ,
85
+ } ;
86
+
87
+ let substs = cx. typeck_results ( ) . node_substs ( expr. hir_id ) ;
88
+ if let Ok ( Some ( instance) ) = ty:: Instance :: resolve ( cx. tcx , cx. param_env , def_id, substs) {
89
+ let def_id = instance. def_id ( ) ;
90
+ if cx. tcx . has_attr ( def_id, sym:: rustc_lint_query_instability) {
91
+ cx. struct_span_lint ( POTENTIAL_QUERY_INSTABILITY , span, |lint| {
92
+ let msg = format ! (
93
+ "using `{}` can result in unstable query results" ,
94
+ cx. tcx. item_name( def_id)
95
+ ) ;
96
+ lint. build ( & msg)
97
+ . note ( "if you believe this case to be fine, allow this lint and add a comment explaining your rationale" )
98
+ . emit ( ) ;
99
+ } )
100
+ }
101
+ }
102
+ }
103
+ }
104
+
54
105
declare_tool_lint ! {
55
106
pub rustc:: USAGE_OF_TY_TYKIND ,
56
107
Allow ,
0 commit comments