@@ -109,6 +109,17 @@ mod record_exports;
109
109
mod build_reduced_graph;
110
110
mod resolve_imports;
111
111
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
+
112
123
pub enum ResolutionError < ' a > {
113
124
/// error E0401: can't use type parameters from outer function
114
125
TypeParametersFromOuterFunction ,
@@ -397,7 +408,7 @@ enum PatternBindingMode {
397
408
}
398
409
399
410
#[ derive( Copy , Clone , PartialEq , Eq , Hash , Debug ) ]
400
- enum Namespace {
411
+ pub enum Namespace {
401
412
TypeNS ,
402
413
ValueNS
403
414
}
@@ -445,18 +456,22 @@ enum NameDefinition {
445
456
446
457
impl < ' a , ' v , ' tcx > Visitor < ' v > for Resolver < ' a , ' tcx > {
447
458
fn visit_item ( & mut self , item : & Item ) {
459
+ execute_callback ! ( ast_map:: Node :: NodeItem ( item) , self ) ;
448
460
self . resolve_item ( item) ;
449
461
}
450
462
fn visit_arm ( & mut self , arm : & Arm ) {
451
463
self . resolve_arm ( arm) ;
452
464
}
453
465
fn visit_block ( & mut self , block : & Block ) {
466
+ execute_callback ! ( ast_map:: Node :: NodeBlock ( block) , self ) ;
454
467
self . resolve_block ( block) ;
455
468
}
456
469
fn visit_expr ( & mut self , expr : & Expr ) {
470
+ execute_callback ! ( ast_map:: Node :: NodeExpr ( expr) , self ) ;
457
471
self . resolve_expr ( expr) ;
458
472
}
459
473
fn visit_local ( & mut self , local : & Local ) {
474
+ execute_callback ! ( ast_map:: Node :: NodeLocal ( & * local. pat) , self ) ;
460
475
self . resolve_local ( local) ;
461
476
}
462
477
fn visit_ty ( & mut self , ty : & Ty ) {
@@ -475,6 +490,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
475
490
visit:: walk_poly_trait_ref ( self , tref, m) ;
476
491
}
477
492
fn visit_variant ( & mut self , variant : & ast:: Variant , generics : & Generics ) {
493
+ execute_callback ! ( ast_map:: Node :: NodeVariant ( variant) , self ) ;
478
494
if let Some ( ref dis_expr) = variant. node . disr_expr {
479
495
// resolve the discriminator expr as a constant
480
496
self . with_constant_rib ( |this| {
@@ -498,6 +514,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
498
514
}
499
515
}
500
516
fn visit_foreign_item ( & mut self , foreign_item : & ast:: ForeignItem ) {
517
+ execute_callback ! ( ast_map:: Node :: NodeForeignItem ( foreign_item) , self ) ;
501
518
let type_parameters = match foreign_item. node {
502
519
ForeignItemFn ( _, ref generics) => {
503
520
HasTypeParameters ( generics, FnSpace , ItemRibKind )
@@ -1147,6 +1164,13 @@ pub struct Resolver<'a, 'tcx:'a> {
1147
1164
1148
1165
used_imports : HashSet < ( NodeId , Namespace ) > ,
1149
1166
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
+
1150
1174
}
1151
1175
1152
1176
#[ derive( PartialEq ) ]
@@ -1208,6 +1232,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
1208
1232
emit_errors : true ,
1209
1233
make_glob_map : make_glob_map == MakeGlobMap :: Yes ,
1210
1234
glob_map : HashMap :: new ( ) ,
1235
+
1236
+ callback : None ,
1237
+ resolved : false ,
1238
+
1211
1239
}
1212
1240
}
1213
1241
@@ -2234,7 +2262,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
2234
2262
f ( self ) ;
2235
2263
2236
2264
match type_parameters {
2237
- HasTypeParameters ( ..) => { self . type_ribs . pop ( ) ; }
2265
+ HasTypeParameters ( ..) => { if ! self . resolved { self . type_ribs . pop ( ) ; } }
2238
2266
NoTypeParameters => { }
2239
2267
}
2240
2268
}
@@ -2244,7 +2272,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
2244
2272
{
2245
2273
self . label_ribs . push ( Rib :: new ( NormalRibKind ) ) ;
2246
2274
f ( self ) ;
2247
- self . label_ribs . pop ( ) ;
2275
+ if !self . resolved {
2276
+ self . label_ribs . pop ( ) ;
2277
+ }
2248
2278
}
2249
2279
2250
2280
fn with_constant_rib < F > ( & mut self , f : F ) where
@@ -2253,8 +2283,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
2253
2283
self . value_ribs . push ( Rib :: new ( ConstantItemRibKind ) ) ;
2254
2284
self . type_ribs . push ( Rib :: new ( ConstantItemRibKind ) ) ;
2255
2285
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
+ }
2258
2290
}
2259
2291
2260
2292
fn resolve_function ( & mut self ,
@@ -2285,8 +2317,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
2285
2317
2286
2318
debug ! ( "(resolving function) leaving function" ) ;
2287
2319
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
+ }
2290
2324
}
2291
2325
2292
2326
fn resolve_trait_reference ( & mut self ,
@@ -2389,7 +2423,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
2389
2423
self_type_rib. bindings . insert ( name, DlDef ( self_def) ) ;
2390
2424
self . type_ribs . push ( self_type_rib) ;
2391
2425
f ( self ) ;
2392
- self . type_ribs . pop ( ) ;
2426
+ if !self . resolved {
2427
+ self . type_ribs . pop ( ) ;
2428
+ }
2393
2429
}
2394
2430
2395
2431
fn resolve_implementation ( & mut self ,
@@ -2558,7 +2594,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
2558
2594
visit:: walk_expr_opt ( self , & arm. guard ) ;
2559
2595
self . visit_expr ( & * arm. body ) ;
2560
2596
2561
- self . value_ribs . pop ( ) ;
2597
+ if !self . resolved {
2598
+ self . value_ribs . pop ( ) ;
2599
+ }
2562
2600
}
2563
2601
2564
2602
fn resolve_block ( & mut self , block : & Block ) {
@@ -2600,9 +2638,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
2600
2638
visit:: walk_block ( self , block) ;
2601
2639
2602
2640
// 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
+ }
2606
2645
debug ! ( "(resolving block) leaving block" ) ;
2607
2646
}
2608
2647
@@ -3044,12 +3083,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
3044
3083
/// doesn't skip straight to the containing module.
3045
3084
/// Skips `path_depth` trailing segments, which is also reflected in the
3046
3085
/// 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 > {
3053
3092
let span = path. span ;
3054
3093
let segments = & path. segments [ ..path. segments . len ( ) -path_depth] ;
3055
3094
@@ -3988,16 +4027,7 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
3988
4027
make_glob_map : MakeGlobMap )
3989
4028
-> CrateMap {
3990
4029
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 ) ;
4001
4031
4002
4032
resolver. resolve_crate ( krate) ;
4003
4033
session. abort_if_errors ( ) ;
@@ -4018,4 +4048,34 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
4018
4048
}
4019
4049
}
4020
4050
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
+
4021
4081
__build_diagnostic_array ! { librustc_resolve, DIAGNOSTICS }
0 commit comments