@@ -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 {
@@ -251,7 +274,7 @@ fn validate_lint_attr<T: Lint, S: Stage>(
251274 return None ;
252275 }
253276
254- if !skip_unused_check && lint_instances. is_empty ( ) {
277+ if !early && ! skip_unused_check && lint_instances. is_empty ( ) {
255278 let span = cx. attr_span ;
256279 cx. adcx ( ) . warn_empty_attribute ( span) ;
257280 }
@@ -274,6 +297,7 @@ fn check_lint<'a, S: Stage>(
274297 tool_name : Option < Symbol > ,
275298 tool_span : Option < Span > ,
276299 span : Span ,
300+ early : bool ,
277301) -> Option < & ' a [ LintId ] > {
278302 let Some ( tools) = cx. tools else {
279303 unreachable ! ( "tools required while parsing attributes" ) ;
@@ -289,15 +313,17 @@ fn check_lint<'a, S: Stage>(
289313 None => original_name,
290314 Some ( new_lint_name) => {
291315 let new_lint_name = Symbol :: intern ( & new_lint_name) ;
292- cx. emit_lint (
293- RENAMED_AND_REMOVED_LINTS ,
294- AttributeLintKind :: DeprecatedLintName {
295- name : * full_name,
296- suggestion : span,
297- replace : new_lint_name,
298- } ,
299- span,
300- ) ;
316+ if !early {
317+ cx. emit_lint (
318+ RENAMED_AND_REMOVED_LINTS ,
319+ AttributeLintKind :: DeprecatedLintName {
320+ name : * full_name,
321+ suggestion : span,
322+ replace : new_lint_name,
323+ } ,
324+ span,
325+ ) ;
326+ }
301327 new_lint_name
302328 }
303329 } ;
@@ -313,21 +339,26 @@ fn check_lint<'a, S: Stage>(
313339 }
314340
315341 CheckLintNameResult :: NoTool => {
316- cx. emit_err ( UnknownToolInScopedLint {
317- span : tool_span,
318- tool_name : tool_name. unwrap ( ) ,
319- full_lint_name : * full_name,
320- is_nightly_build : cx. sess . is_nightly_build ( ) ,
321- } ) ;
342+ if !early {
343+ cx. emit_err ( UnknownToolInScopedLint {
344+ span : tool_span,
345+ tool_name : tool_name. unwrap ( ) ,
346+ full_lint_name : * full_name,
347+ is_nightly_build : cx. sess . is_nightly_build ( ) ,
348+ } ) ;
349+ }
350+
322351 None
323352 }
324353
325354 CheckLintNameResult :: Renamed ( replace) => {
326- cx. emit_lint (
327- RENAMED_AND_REMOVED_LINTS ,
328- AttributeLintKind :: RenamedLint { name : * full_name, replace, suggestion : span } ,
329- span,
330- ) ;
355+ if !early {
356+ cx. emit_lint (
357+ RENAMED_AND_REMOVED_LINTS ,
358+ AttributeLintKind :: RenamedLint { name : * full_name, replace, suggestion : span } ,
359+ span,
360+ ) ;
361+ }
331362
332363 // Since it was renamed, and we have emitted the warning
333364 // we replace the "full_name", to ensure we don't get notes with:
@@ -348,33 +379,39 @@ fn check_lint<'a, S: Stage>(
348379 }
349380
350381 CheckLintNameResult :: RenamedToolLint ( new_name) => {
351- cx. emit_lint (
352- RENAMED_AND_REMOVED_LINTS ,
353- AttributeLintKind :: RenamedLint {
354- name : * full_name,
355- replace : new_name,
356- suggestion : span,
357- } ,
358- span,
359- ) ;
382+ if !early {
383+ cx. emit_lint (
384+ RENAMED_AND_REMOVED_LINTS ,
385+ AttributeLintKind :: RenamedLint {
386+ name : * full_name,
387+ replace : new_name,
388+ suggestion : span,
389+ } ,
390+ span,
391+ ) ;
392+ }
360393 None
361394 }
362395
363396 CheckLintNameResult :: Removed ( reason) => {
364- cx. emit_lint (
365- RENAMED_AND_REMOVED_LINTS ,
366- AttributeLintKind :: RemovedLint { name : * full_name, reason } ,
367- span,
368- ) ;
397+ if !early {
398+ cx. emit_lint (
399+ RENAMED_AND_REMOVED_LINTS ,
400+ AttributeLintKind :: RemovedLint { name : * full_name, reason } ,
401+ span,
402+ ) ;
403+ }
369404 None
370405 }
371406
372407 CheckLintNameResult :: NoLint ( suggestion) => {
373- cx. emit_lint (
374- UNKNOWN_LINTS ,
375- AttributeLintKind :: UnknownLint { name : * full_name, suggestion, span } ,
376- span,
377- ) ;
408+ if !early {
409+ cx. emit_lint (
410+ UNKNOWN_LINTS ,
411+ AttributeLintKind :: UnknownLint { name : * full_name, suggestion, span } ,
412+ span,
413+ ) ;
414+ }
378415 None
379416 }
380417 }
0 commit comments