@@ -376,6 +376,19 @@ struct DiagnosticMetadata<'ast> {
376376 current_let_binding : Option < ( Span , Option < Span > , Option < Span > ) > ,
377377}
378378
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+
379392struct LateResolutionVisitor < ' a , ' b , ' ast > {
380393 r : & ' b mut Resolver < ' a > ,
381394
@@ -395,10 +408,12 @@ struct LateResolutionVisitor<'a, 'b, 'ast> {
395408 /// Fields used to add information to diagnostic errors.
396409 diagnostic_metadata : DiagnosticMetadata < ' ast > ,
397410
398- /// Whether to report resolution errors for item bodies.
411+ /// State used to know whether to ignore resolution errors for item bodies.
399412 ///
400413 /// 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 > ,
402417}
403418
404419/// 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> {
502517
503518 visit:: walk_fn_ret_ty ( this, & declaration. output ) ;
504519
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 ) ) ;
505524 // Resolve the function body, potentially inside the body of an async closure
506525 match fn_kind {
507526 FnKind :: Fn ( .., body) => walk_list ! ( this, visit_block, body) ,
508527 FnKind :: Closure ( _, body) => this. visit_expr ( body) ,
509528 } ;
510529
511530 debug ! ( "(resolving function) leaving function" ) ;
531+ this. ignore_bodies = previous_ignore;
512532 } )
513533 } ) ;
514534 self . diagnostic_metadata . current_function = previous_value;
@@ -634,7 +654,7 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
634654impl < ' a , ' b , ' ast > LateResolutionVisitor < ' a , ' b , ' ast > {
635655 fn new (
636656 resolver : & ' b mut Resolver < ' a > ,
637- ignore_bodies : bool ,
657+ ignore_bodies : IgnoreState ,
638658 ) -> LateResolutionVisitor < ' a , ' b , ' ast > {
639659 // During late resolution we only track the module component of the parent scope,
640660 // 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> {
652672 label_ribs : Vec :: new ( ) ,
653673 current_trait_ref : None ,
654674 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+ } ,
656680 }
657681 }
658682
@@ -842,7 +866,11 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
842866 } ;
843867 let report_error = |this : & Self , ns| {
844868 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+ }
846874 } ;
847875
848876 for & ns in nss {
@@ -1166,6 +1194,9 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
11661194 impl_items : & ' ast [ P < AssocItem > ] ,
11671195 ) {
11681196 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 ) ) ;
11691200 // If applicable, create a rib for the type parameters.
11701201 self . with_generic_param_rib ( generics, ItemRibKind ( HasGenericParams :: Yes ) , |this| {
11711202 // 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> {
12611292 } ) ;
12621293 } ) ;
12631294 } ) ;
1295+ self . ignore_bodies = old_ignore;
12641296 }
12651297
12661298 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> {
12981330 }
12991331
13001332 fn resolve_local ( & mut self , local : & ' ast Local ) {
1333+ debug ! ( "resolving local ({:?})" , local) ;
13011334 // Resolve the type.
13021335 walk_list ! ( self , visit_ty, & local. ty) ;
13031336
@@ -1686,18 +1719,27 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
16861719 source : PathSource < ' ast > ,
16871720 crate_lint : CrateLint ,
16881721 ) -> PartialRes {
1722+ log:: debug!( "smart_resolve_path_fragment(id={:?},qself={:?},path={:?}" , id, qself, path) ;
16891723 let ns = source. namespace ( ) ;
16901724 let is_expected = & |res| source. is_expected ( res) ;
16911725
16921726 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+ }
17011743
17021744 PartialRes :: new ( Res :: Err )
17031745 } ;
@@ -1755,13 +1797,17 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
17551797
17561798 let def_id = this. parent_scope . module . normal_ancestor_id ;
17571799
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+ }
17651811
17661812 // We don't return `Some(parent_err)` here, because the error will
17671813 // be already printed as part of the `use` injections
@@ -1856,11 +1902,20 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
18561902 ///
18571903 /// This doesn't emit errors for function bodies if `ignore_bodies` is set.
18581904 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 ( ) {
18601906 self . r . report_error ( span, resolution_error) ;
18611907 }
18621908 }
18631909
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+
18641919 // Resolve in alternative namespaces if resolution in the primary namespace fails.
18651920 fn resolve_qpath_anywhere (
18661921 & mut self ,
@@ -2357,7 +2412,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
23572412}
23582413
23592414impl < ' 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 ) {
23612416 let mut late_resolution_visitor = LateResolutionVisitor :: new ( self , ignore_bodies) ;
23622417 visit:: walk_crate ( & mut late_resolution_visitor, krate) ;
23632418 for ( id, span) in late_resolution_visitor. diagnostic_metadata . unused_labels . iter ( ) {
0 commit comments