@@ -376,6 +376,19 @@ struct DiagnosticMetadata<'ast> {
376
376
current_let_binding : Option < ( Span , Option < Span > , Option < Span > ) > ,
377
377
}
378
378
379
+ /// Keeps track of whether errors should be reported.
380
+ ///
381
+ /// Used by rustdoc to ignore errors in function bodies.
382
+ /// This is just a fancy boolean so it can have doc-comments.
383
+ #[ derive( Copy , Clone , Debug ) ]
384
+ pub enum IgnoreState {
385
+ /// We are at global scope or in a trait implementation, so all errors should be reported.
386
+ Report ,
387
+ /// We are in a function body, so errors shouldn't be reported.
388
+ Ignore ,
389
+ // Note that we don't need to worry about macros, which must always be resolved (or we wouldn't have gotten to the late pass).
390
+ }
391
+
379
392
struct LateResolutionVisitor < ' a , ' b , ' ast > {
380
393
r : & ' b mut Resolver < ' a > ,
381
394
@@ -395,10 +408,12 @@ struct LateResolutionVisitor<'a, 'b, 'ast> {
395
408
/// Fields used to add information to diagnostic errors.
396
409
diagnostic_metadata : DiagnosticMetadata < ' ast > ,
397
410
398
- /// Whether to report resolution errors for item bodies.
411
+ /// State used to know whether to ignore resolution errors for item bodies.
399
412
///
400
413
/// In particular, rustdoc uses this to avoid giving errors for `cfg()` items.
401
- ignore_bodies : bool ,
414
+ /// In most cases this will be `None`, in which case errors will always be reported.
415
+ /// If it is `Some(_)`, then it will be updated when entering a nested function or trait body.
416
+ ignore_bodies : Option < IgnoreState > ,
402
417
}
403
418
404
419
/// Walks the whole crate in DFS order, visiting each item, resolving names as it goes.
@@ -502,13 +517,18 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
502
517
503
518
visit:: walk_fn_ret_ty ( this, & declaration. output ) ;
504
519
520
+ let previous_ignore = this. ignore_bodies . take ( ) ;
521
+ // Ignore errors in function bodies if originally passed `ignore_state: true`
522
+ // Be sure not to set this until the function signature has been resolved.
523
+ this. ignore_bodies = previous_ignore. and ( Some ( IgnoreState :: Ignore ) ) ;
505
524
// Resolve the function body, potentially inside the body of an async closure
506
525
match fn_kind {
507
526
FnKind :: Fn ( .., body) => walk_list ! ( this, visit_block, body) ,
508
527
FnKind :: Closure ( _, body) => this. visit_expr ( body) ,
509
528
} ;
510
529
511
530
debug ! ( "(resolving function) leaving function" ) ;
531
+ this. ignore_bodies = previous_ignore;
512
532
} )
513
533
} ) ;
514
534
self . diagnostic_metadata . current_function = previous_value;
@@ -634,7 +654,7 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
634
654
impl < ' a , ' b , ' ast > LateResolutionVisitor < ' a , ' b , ' ast > {
635
655
fn new (
636
656
resolver : & ' b mut Resolver < ' a > ,
637
- ignore_bodies : bool ,
657
+ ignore_bodies : IgnoreState ,
638
658
) -> LateResolutionVisitor < ' a , ' b , ' ast > {
639
659
// During late resolution we only track the module component of the parent scope,
640
660
// although it may be useful to track other components as well for diagnostics.
@@ -652,7 +672,11 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
652
672
label_ribs : Vec :: new ( ) ,
653
673
current_trait_ref : None ,
654
674
diagnostic_metadata : DiagnosticMetadata :: default ( ) ,
655
- ignore_bodies,
675
+ ignore_bodies : match ignore_bodies {
676
+ // errors at module scope should always be reported
677
+ IgnoreState :: Ignore => Some ( IgnoreState :: Report ) ,
678
+ IgnoreState :: Report => None ,
679
+ } ,
656
680
}
657
681
}
658
682
@@ -842,7 +866,11 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
842
866
} ;
843
867
let report_error = |this : & Self , ns| {
844
868
let what = if ns == TypeNS { "type parameters" } else { "local variables" } ;
845
- this. r . session . span_err ( ident. span , & format ! ( "imports cannot refer to {}" , what) ) ;
869
+ if this. should_report_errs ( ) {
870
+ this. r
871
+ . session
872
+ . span_err ( ident. span , & format ! ( "imports cannot refer to {}" , what) ) ;
873
+ }
846
874
} ;
847
875
848
876
for & ns in nss {
@@ -1166,6 +1194,9 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1166
1194
impl_items : & ' ast [ P < AssocItem > ] ,
1167
1195
) {
1168
1196
debug ! ( "resolve_implementation" ) ;
1197
+ let old_ignore = self . ignore_bodies . take ( ) ;
1198
+ // Never ignore errors in trait implementations.
1199
+ self . ignore_bodies = old_ignore. and ( Some ( IgnoreState :: Report ) ) ;
1169
1200
// If applicable, create a rib for the type parameters.
1170
1201
self . with_generic_param_rib ( generics, ItemRibKind ( HasGenericParams :: Yes ) , |this| {
1171
1202
// Dummy self type for better errors if `Self` is used in the trait path.
@@ -1261,6 +1292,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1261
1292
} ) ;
1262
1293
} ) ;
1263
1294
} ) ;
1295
+ self . ignore_bodies = old_ignore;
1264
1296
}
1265
1297
1266
1298
fn check_trait_item < F > ( & mut self , ident : Ident , ns : Namespace , span : Span , err : F )
@@ -1298,6 +1330,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1298
1330
}
1299
1331
1300
1332
fn resolve_local ( & mut self , local : & ' ast Local ) {
1333
+ debug ! ( "resolving local ({:?})" , local) ;
1301
1334
// Resolve the type.
1302
1335
walk_list ! ( self , visit_ty, & local. ty) ;
1303
1336
@@ -1686,18 +1719,27 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1686
1719
source : PathSource < ' ast > ,
1687
1720
crate_lint : CrateLint ,
1688
1721
) -> PartialRes {
1722
+ log:: debug!( "smart_resolve_path_fragment(id={:?},qself={:?},path={:?}" , id, qself, path) ;
1689
1723
let ns = source. namespace ( ) ;
1690
1724
let is_expected = & |res| source. is_expected ( res) ;
1691
1725
1692
1726
let report_errors = |this : & mut Self , res : Option < Res > | {
1693
- let ( err, candidates) = this. smart_resolve_report_errors ( path, span, source, res) ;
1694
-
1695
- let def_id = this. parent_scope . module . normal_ancestor_id ;
1696
- let instead = res. is_some ( ) ;
1697
- let suggestion =
1698
- if res. is_none ( ) { this. report_missing_type_error ( path) } else { None } ;
1699
-
1700
- this. r . use_injections . push ( UseError { err, candidates, def_id, instead, suggestion } ) ;
1727
+ if this. should_report_errs ( ) {
1728
+ let ( err, candidates) = this. smart_resolve_report_errors ( path, span, source, res) ;
1729
+
1730
+ let def_id = this. parent_scope . module . normal_ancestor_id ;
1731
+ let instead = res. is_some ( ) ;
1732
+ let suggestion =
1733
+ if res. is_none ( ) { this. report_missing_type_error ( path) } else { None } ;
1734
+
1735
+ this. r . use_injections . push ( UseError {
1736
+ err,
1737
+ candidates,
1738
+ def_id,
1739
+ instead,
1740
+ suggestion,
1741
+ } ) ;
1742
+ }
1701
1743
1702
1744
PartialRes :: new ( Res :: Err )
1703
1745
} ;
@@ -1755,13 +1797,17 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1755
1797
1756
1798
let def_id = this. parent_scope . module . normal_ancestor_id ;
1757
1799
1758
- this. r . use_injections . push ( UseError {
1759
- err,
1760
- candidates,
1761
- def_id,
1762
- instead : false ,
1763
- suggestion : None ,
1764
- } ) ;
1800
+ if this. should_report_errs ( ) {
1801
+ this. r . use_injections . push ( UseError {
1802
+ err,
1803
+ candidates,
1804
+ def_id,
1805
+ instead : false ,
1806
+ suggestion : None ,
1807
+ } ) ;
1808
+ } else {
1809
+ err. cancel ( ) ;
1810
+ }
1765
1811
1766
1812
// We don't return `Some(parent_err)` here, because the error will
1767
1813
// be already printed as part of the `use` injections
@@ -1856,11 +1902,20 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1856
1902
///
1857
1903
/// This doesn't emit errors for function bodies if `ignore_bodies` is set.
1858
1904
fn report_error ( & self , span : Span , resolution_error : ResolutionError < ' _ > ) {
1859
- if ! self . ignore_bodies || self . diagnostic_metadata . current_function . is_none ( ) {
1905
+ if self . should_report_errs ( ) {
1860
1906
self . r . report_error ( span, resolution_error) ;
1861
1907
}
1862
1908
}
1863
1909
1910
+ #[ inline]
1911
+ fn should_report_errs ( & self ) -> bool {
1912
+ debug ! ( "should_report_errs(state={:?})" , self . ignore_bodies) ;
1913
+ match self . ignore_bodies {
1914
+ None | Some ( IgnoreState :: Report ) => true ,
1915
+ Some ( IgnoreState :: Ignore ) => false ,
1916
+ }
1917
+ }
1918
+
1864
1919
// Resolve in alternative namespaces if resolution in the primary namespace fails.
1865
1920
fn resolve_qpath_anywhere (
1866
1921
& mut self ,
@@ -2357,7 +2412,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
2357
2412
}
2358
2413
2359
2414
impl < ' a > Resolver < ' a > {
2360
- pub ( crate ) fn late_resolve_crate ( & mut self , krate : & Crate , ignore_bodies : bool ) {
2415
+ pub ( crate ) fn late_resolve_crate ( & mut self , krate : & Crate , ignore_bodies : IgnoreState ) {
2361
2416
let mut late_resolution_visitor = LateResolutionVisitor :: new ( self , ignore_bodies) ;
2362
2417
visit:: walk_crate ( & mut late_resolution_visitor, krate) ;
2363
2418
for ( id, span) in late_resolution_visitor. diagnostic_metadata . unused_labels . iter ( ) {
0 commit comments