@@ -8,6 +8,7 @@ use rustc_session::lint::builtin::{RENAMED_AND_REMOVED_LINTS, UNKNOWN_LINTS, UNU
88use rustc_session:: lint:: { CheckLintNameResult , LintId } ;
99
1010use super :: prelude:: * ;
11+ use crate :: ShouldEmit ;
1112use crate :: attributes:: AcceptFn ;
1213use crate :: session_diagnostics:: UnknownToolInScopedLint ;
1314
@@ -136,13 +137,21 @@ fn validate_lint_attr<T: Lint, S: Stage>(
136137 cx : & mut AcceptContext < ' _ , ' _ , S > ,
137138 args : & ArgParser ,
138139) -> Option < LintAttribute > {
140+ // ShouldEmit is Nothing during early parsing, so to avoid delayed bugs, we just dont emit
141+ // The reason for why we don't want to delay bugs, is that when compiling lib
142+ // they usually skip this attr parsing but since lint-attrs is parsed in pre expansion,
143+ // these delayed bugs would never be emitted as errors and therefore ICE
144+ let early = matches ! ( cx. stage. should_emit( ) , ShouldEmit :: Nothing ) ;
145+
139146 let Some ( lint_store) = cx. sess . lint_store . as_ref ( ) . map ( |store| store. to_owned ( ) ) else {
140147 unreachable ! ( "lint_store required while parsing attributes" ) ;
141148 } ;
142149 let lint_store = lint_store. as_ref ( ) ;
143150 let Some ( list) = args. list ( ) else {
144151 let span = cx. inner_span ;
145- cx. adcx ( ) . expected_list ( span, args) ;
152+ if !early {
153+ cx. adcx ( ) . expected_list ( span, args) ;
154+ }
146155 return None ;
147156 } ;
148157 let mut list = list. mixed ( ) . peekable ( ) ;
@@ -155,7 +164,9 @@ fn validate_lint_attr<T: Lint, S: Stage>(
155164 let targeting_crate = matches ! ( cx. target, Target :: Crate ) ;
156165 while let Some ( item) = list. next ( ) {
157166 let Some ( meta_item) = item. meta_item ( ) else {
158- cx. adcx ( ) . expected_identifier ( item. span ( ) ) ;
167+ if !early {
168+ cx. adcx ( ) . expected_identifier ( item. span ( ) ) ;
169+ }
159170 errored = true ;
160171 continue ;
161172 } ;
@@ -164,25 +175,33 @@ fn validate_lint_attr<T: Lint, S: Stage>(
164175 ArgParser :: NameValue ( nv_parser) if meta_item. path ( ) . word_is ( sym:: reason) => {
165176 //FIXME replace this with duplicate check?
166177 if list. peek ( ) . is_some ( ) {
167- cx. adcx ( ) . expected_nv_as_last_argument ( meta_item. span ( ) , sym:: reason) ;
178+ if !early {
179+ cx. adcx ( ) . expected_nv_as_last_argument ( meta_item. span ( ) , sym:: reason) ;
180+ }
168181 errored = true ;
169182 continue ;
170183 }
171184
172185 let val_lit = nv_parser. value_as_lit ( ) ;
173186 let LitKind :: Str ( reason_sym, _) = val_lit. kind else {
174- cx. adcx ( ) . expected_string_literal ( nv_parser. value_span , Some ( val_lit) ) ;
187+ if !early {
188+ cx. adcx ( ) . expected_string_literal ( nv_parser. value_span , Some ( val_lit) ) ;
189+ }
175190 errored = true ;
176191 continue ;
177192 } ;
178193 reason = Some ( reason_sym) ;
179194 }
180195 ArgParser :: NameValue ( _) => {
181- cx. adcx ( ) . expected_specific_argument ( meta_item. span ( ) , & [ sym:: reason] ) ;
196+ if !early {
197+ cx. adcx ( ) . expected_specific_argument ( meta_item. span ( ) , & [ sym:: reason] ) ;
198+ }
182199 errored = true ;
183200 }
184201 ArgParser :: List ( list) => {
185- cx. adcx ( ) . expected_no_args ( list. span ) ;
202+ if !early {
203+ cx. adcx ( ) . expected_no_args ( list. span ) ;
204+ }
186205 errored = true ;
187206 }
188207 ArgParser :: NoArgs => {
@@ -222,8 +241,12 @@ fn validate_lint_attr<T: Lint, S: Stage>(
222241 tool_name,
223242 tool_span,
224243 meta_item_span,
244+ early,
225245 ) {
226- if !targeting_crate && ids. iter ( ) . any ( |lint_id| lint_id. lint . crate_level_only ) {
246+ if !early
247+ && !targeting_crate
248+ && ids. iter ( ) . any ( |lint_id| lint_id. lint . crate_level_only )
249+ {
227250 cx. emit_lint (
228251 UNUSED_ATTRIBUTES ,
229252 AttributeLintKind :: IgnoredUnlessCrateSpecified {
@@ -241,7 +264,7 @@ fn validate_lint_attr<T: Lint, S: Stage>(
241264 }
242265 }
243266 }
244- if !skip_unused_check && !errored && lint_instances. is_empty ( ) {
267+ if !early && ! skip_unused_check && !errored && lint_instances. is_empty ( ) {
245268 let span = cx. attr_span ;
246269 cx. adcx ( ) . warn_empty_attribute ( span) ;
247270 }
@@ -264,6 +287,7 @@ fn check_lint<'a, S: Stage>(
264287 tool_name : Option < Symbol > ,
265288 tool_span : Option < Span > ,
266289 span : Span ,
290+ early : bool ,
267291) -> Option < & ' a [ LintId ] > {
268292 let Some ( tools) = cx. tools else {
269293 unreachable ! ( "tools required while parsing attributes" ) ;
@@ -279,15 +303,17 @@ fn check_lint<'a, S: Stage>(
279303 None => original_name,
280304 Some ( new_lint_name) => {
281305 let new_lint_name = Symbol :: intern ( & new_lint_name) ;
282- cx. emit_lint (
283- RENAMED_AND_REMOVED_LINTS ,
284- AttributeLintKind :: DeprecatedLintName {
285- name : * full_name,
286- suggestion : span,
287- replace : new_lint_name,
288- } ,
289- span,
290- ) ;
306+ if !early {
307+ cx. emit_lint (
308+ RENAMED_AND_REMOVED_LINTS ,
309+ AttributeLintKind :: DeprecatedLintName {
310+ name : * full_name,
311+ suggestion : span,
312+ replace : new_lint_name,
313+ } ,
314+ span,
315+ ) ;
316+ }
291317 new_lint_name
292318 }
293319 } ;
@@ -303,21 +329,26 @@ fn check_lint<'a, S: Stage>(
303329 }
304330
305331 CheckLintNameResult :: NoTool => {
306- cx. emit_err ( UnknownToolInScopedLint {
307- span : tool_span,
308- tool_name : tool_name. unwrap ( ) ,
309- full_lint_name : * full_name,
310- is_nightly_build : cx. sess . is_nightly_build ( ) ,
311- } ) ;
332+ if !early {
333+ cx. emit_err ( UnknownToolInScopedLint {
334+ span : tool_span,
335+ tool_name : tool_name. unwrap ( ) ,
336+ full_lint_name : * full_name,
337+ is_nightly_build : cx. sess . is_nightly_build ( ) ,
338+ } ) ;
339+ }
340+
312341 None
313342 }
314343
315344 CheckLintNameResult :: Renamed ( replace) => {
316- cx. emit_lint (
317- RENAMED_AND_REMOVED_LINTS ,
318- AttributeLintKind :: RenamedLint { name : * full_name, replace, suggestion : span } ,
319- span,
320- ) ;
345+ if !early {
346+ cx. emit_lint (
347+ RENAMED_AND_REMOVED_LINTS ,
348+ AttributeLintKind :: RenamedLint { name : * full_name, replace, suggestion : span } ,
349+ span,
350+ ) ;
351+ }
321352
322353 // Since it was renamed, and we have emitted the warning
323354 // we replace the "full_name", to ensure we don't get notes with:
@@ -338,33 +369,39 @@ fn check_lint<'a, S: Stage>(
338369 }
339370
340371 CheckLintNameResult :: RenamedToolLint ( new_name) => {
341- cx. emit_lint (
342- RENAMED_AND_REMOVED_LINTS ,
343- AttributeLintKind :: RenamedLint {
344- name : * full_name,
345- replace : new_name,
346- suggestion : span,
347- } ,
348- span,
349- ) ;
372+ if !early {
373+ cx. emit_lint (
374+ RENAMED_AND_REMOVED_LINTS ,
375+ AttributeLintKind :: RenamedLint {
376+ name : * full_name,
377+ replace : new_name,
378+ suggestion : span,
379+ } ,
380+ span,
381+ ) ;
382+ }
350383 None
351384 }
352385
353386 CheckLintNameResult :: Removed ( reason) => {
354- cx. emit_lint (
355- RENAMED_AND_REMOVED_LINTS ,
356- AttributeLintKind :: RemovedLint { name : * full_name, reason } ,
357- span,
358- ) ;
387+ if !early {
388+ cx. emit_lint (
389+ RENAMED_AND_REMOVED_LINTS ,
390+ AttributeLintKind :: RemovedLint { name : * full_name, reason } ,
391+ span,
392+ ) ;
393+ }
359394 None
360395 }
361396
362397 CheckLintNameResult :: NoLint ( suggestion) => {
363- cx. emit_lint (
364- UNKNOWN_LINTS ,
365- AttributeLintKind :: UnknownLint { name : * full_name, suggestion, span } ,
366- span,
367- ) ;
398+ if !early {
399+ cx. emit_lint (
400+ UNKNOWN_LINTS ,
401+ AttributeLintKind :: UnknownLint { name : * full_name, suggestion, span } ,
402+ span,
403+ ) ;
404+ }
368405 None
369406 }
370407 }
0 commit comments