@@ -109,6 +109,17 @@ mod record_exports;
109109mod build_reduced_graph;
110110mod resolve_imports;
111111
112+ // Perform the callback, not walking deeper if the return is true
113+ macro_rules! execute_callback {
114+ ( $node: expr, $walker: expr) => (
115+ if let Some ( ref callback) = $walker. callback {
116+ if callback( $node, & mut $walker. resolved) {
117+ return ;
118+ }
119+ }
120+ )
121+ }
122+
112123pub enum ResolutionError < ' a > {
113124 /// error E0401: can't use type parameters from outer function
114125 TypeParametersFromOuterFunction ,
@@ -397,7 +408,7 @@ enum PatternBindingMode {
397408}
398409
399410#[ derive( Copy , Clone , PartialEq , Eq , Hash , Debug ) ]
400- enum Namespace {
411+ pub enum Namespace {
401412 TypeNS ,
402413 ValueNS
403414}
@@ -445,18 +456,22 @@ enum NameDefinition {
445456
446457impl < ' a , ' v , ' tcx > Visitor < ' v > for Resolver < ' a , ' tcx > {
447458 fn visit_item ( & mut self , item : & Item ) {
459+ execute_callback ! ( ast_map:: Node :: NodeItem ( item) , self ) ;
448460 self . resolve_item ( item) ;
449461 }
450462 fn visit_arm ( & mut self , arm : & Arm ) {
451463 self . resolve_arm ( arm) ;
452464 }
453465 fn visit_block ( & mut self , block : & Block ) {
466+ execute_callback ! ( ast_map:: Node :: NodeBlock ( block) , self ) ;
454467 self . resolve_block ( block) ;
455468 }
456469 fn visit_expr ( & mut self , expr : & Expr ) {
470+ execute_callback ! ( ast_map:: Node :: NodeExpr ( expr) , self ) ;
457471 self . resolve_expr ( expr) ;
458472 }
459473 fn visit_local ( & mut self , local : & Local ) {
474+ execute_callback ! ( ast_map:: Node :: NodeLocal ( & * local. pat) , self ) ;
460475 self . resolve_local ( local) ;
461476 }
462477 fn visit_ty ( & mut self , ty : & Ty ) {
@@ -475,6 +490,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
475490 visit:: walk_poly_trait_ref ( self , tref, m) ;
476491 }
477492 fn visit_variant ( & mut self , variant : & ast:: Variant , generics : & Generics ) {
493+ execute_callback ! ( ast_map:: Node :: NodeVariant ( variant) , self ) ;
478494 if let Some ( ref dis_expr) = variant. node . disr_expr {
479495 // resolve the discriminator expr as a constant
480496 self . with_constant_rib ( |this| {
@@ -498,6 +514,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
498514 }
499515 }
500516 fn visit_foreign_item ( & mut self , foreign_item : & ast:: ForeignItem ) {
517+ execute_callback ! ( ast_map:: Node :: NodeForeignItem ( foreign_item) , self ) ;
501518 let type_parameters = match foreign_item. node {
502519 ForeignItemFn ( _, ref generics) => {
503520 HasTypeParameters ( generics, FnSpace , ItemRibKind )
@@ -1147,6 +1164,13 @@ pub struct Resolver<'a, 'tcx:'a> {
11471164
11481165 used_imports : HashSet < ( NodeId , Namespace ) > ,
11491166 used_crates : HashSet < CrateNum > ,
1167+
1168+ // Callback function for intercepting walks
1169+ callback : Option < Box < Fn ( ast_map:: Node , & mut bool ) -> bool > > ,
1170+ // The intention is that the callback modifies this flag.
1171+ // Once set, the resolver falls out of the walk, preserving the ribs.
1172+ resolved : bool ,
1173+
11501174}
11511175
11521176#[ derive( PartialEq ) ]
@@ -1208,6 +1232,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
12081232 emit_errors : true ,
12091233 make_glob_map : make_glob_map == MakeGlobMap :: Yes ,
12101234 glob_map : HashMap :: new ( ) ,
1235+
1236+ callback : None ,
1237+ resolved : false ,
1238+
12111239 }
12121240 }
12131241
@@ -2234,7 +2262,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
22342262 f ( self ) ;
22352263
22362264 match type_parameters {
2237- HasTypeParameters ( ..) => { self . type_ribs . pop ( ) ; }
2265+ HasTypeParameters ( ..) => { if ! self . resolved { self . type_ribs . pop ( ) ; } }
22382266 NoTypeParameters => { }
22392267 }
22402268 }
@@ -2244,7 +2272,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
22442272 {
22452273 self . label_ribs . push ( Rib :: new ( NormalRibKind ) ) ;
22462274 f ( self ) ;
2247- self . label_ribs . pop ( ) ;
2275+ if !self . resolved {
2276+ self . label_ribs . pop ( ) ;
2277+ }
22482278 }
22492279
22502280 fn with_constant_rib < F > ( & mut self , f : F ) where
@@ -2253,8 +2283,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
22532283 self . value_ribs . push ( Rib :: new ( ConstantItemRibKind ) ) ;
22542284 self . type_ribs . push ( Rib :: new ( ConstantItemRibKind ) ) ;
22552285 f ( self ) ;
2256- self . type_ribs . pop ( ) ;
2257- self . value_ribs . pop ( ) ;
2286+ if !self . resolved {
2287+ self . type_ribs . pop ( ) ;
2288+ self . value_ribs . pop ( ) ;
2289+ }
22582290 }
22592291
22602292 fn resolve_function ( & mut self ,
@@ -2285,8 +2317,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
22852317
22862318 debug ! ( "(resolving function) leaving function" ) ;
22872319
2288- self . label_ribs . pop ( ) ;
2289- self . value_ribs . pop ( ) ;
2320+ if !self . resolved {
2321+ self . label_ribs . pop ( ) ;
2322+ self . value_ribs . pop ( ) ;
2323+ }
22902324 }
22912325
22922326 fn resolve_trait_reference ( & mut self ,
@@ -2389,7 +2423,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
23892423 self_type_rib. bindings . insert ( name, DlDef ( self_def) ) ;
23902424 self . type_ribs . push ( self_type_rib) ;
23912425 f ( self ) ;
2392- self . type_ribs . pop ( ) ;
2426+ if !self . resolved {
2427+ self . type_ribs . pop ( ) ;
2428+ }
23932429 }
23942430
23952431 fn resolve_implementation ( & mut self ,
@@ -2558,7 +2594,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
25582594 visit:: walk_expr_opt ( self , & arm. guard ) ;
25592595 self . visit_expr ( & * arm. body ) ;
25602596
2561- self . value_ribs . pop ( ) ;
2597+ if !self . resolved {
2598+ self . value_ribs . pop ( ) ;
2599+ }
25622600 }
25632601
25642602 fn resolve_block ( & mut self , block : & Block ) {
@@ -2600,9 +2638,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
26002638 visit:: walk_block ( self , block) ;
26012639
26022640 // Move back up.
2603- self . current_module = orig_module;
2604-
2605- self . value_ribs . pop ( ) ;
2641+ if !self . resolved {
2642+ self . current_module = orig_module;
2643+ self . value_ribs . pop ( ) ;
2644+ }
26062645 debug ! ( "(resolving block) leaving block" ) ;
26072646 }
26082647
@@ -3044,12 +3083,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
30443083 /// doesn't skip straight to the containing module.
30453084 /// Skips `path_depth` trailing segments, which is also reflected in the
30463085 /// returned value. See `middle::def::PathResolution` for more info.
3047- fn resolve_path ( & mut self ,
3048- id : NodeId ,
3049- path : & Path ,
3050- path_depth : usize ,
3051- namespace : Namespace ,
3052- check_ribs : bool ) -> Option < PathResolution > {
3086+ pub fn resolve_path ( & mut self ,
3087+ id : NodeId ,
3088+ path : & Path ,
3089+ path_depth : usize ,
3090+ namespace : Namespace ,
3091+ check_ribs : bool ) -> Option < PathResolution > {
30533092 let span = path. span ;
30543093 let segments = & path. segments [ ..path. segments . len ( ) -path_depth] ;
30553094
@@ -3988,16 +4027,7 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
39884027 make_glob_map : MakeGlobMap )
39894028 -> CrateMap {
39904029 let krate = ast_map. krate ( ) ;
3991- let mut resolver = Resolver :: new ( session, ast_map, krate. span , make_glob_map) ;
3992-
3993- build_reduced_graph:: build_reduced_graph ( & mut resolver, krate) ;
3994- session. abort_if_errors ( ) ;
3995-
3996- resolve_imports:: resolve_imports ( & mut resolver) ;
3997- session. abort_if_errors ( ) ;
3998-
3999- record_exports:: record ( & mut resolver) ;
4000- session. abort_if_errors ( ) ;
4030+ let mut resolver = create_resolver ( session, ast_map, krate, make_glob_map, None ) ;
40014031
40024032 resolver. resolve_crate ( krate) ;
40034033 session. abort_if_errors ( ) ;
@@ -4018,4 +4048,34 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
40184048 }
40194049}
40204050
4051+ /// Builds a name resolution walker to be used within this module,
4052+ /// or used externally, with an optional callback function.
4053+ ///
4054+ /// The callback takes a &mut bool which allows callbacks to end a
4055+ /// walk when set to true, passing through the rest of the walk, while
4056+ /// preserving the ribs + current module. This allows resolve_path
4057+ /// calls to be made with the correct scope info. The node in the
4058+ /// callback corresponds to the current node in the walk.
4059+ pub fn create_resolver < ' a , ' tcx > ( session : & ' a Session ,
4060+ ast_map : & ' a ast_map:: Map < ' tcx > ,
4061+ krate : & ' a Crate ,
4062+ make_glob_map : MakeGlobMap ,
4063+ callback : Option < Box < Fn ( ast_map:: Node , & mut bool ) -> bool > > )
4064+ -> Resolver < ' a , ' tcx > {
4065+ let mut resolver = Resolver :: new ( session, ast_map, krate. span , make_glob_map) ;
4066+
4067+ resolver. callback = callback;
4068+
4069+ build_reduced_graph:: build_reduced_graph ( & mut resolver, krate) ;
4070+ session. abort_if_errors ( ) ;
4071+
4072+ resolve_imports:: resolve_imports ( & mut resolver) ;
4073+ session. abort_if_errors ( ) ;
4074+
4075+ record_exports:: record ( & mut resolver) ;
4076+ session. abort_if_errors ( ) ;
4077+
4078+ resolver
4079+ }
4080+
40214081__build_diagnostic_array ! { librustc_resolve, DIAGNOSTICS }
0 commit comments