@@ -74,38 +74,66 @@ const UNIX_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = {
74
74
} ;
75
75
76
76
/// Gets an instance for a path.
77
- fn try_resolve_did < ' tcx > ( tcx : TyCtxt < ' tcx > , path : & [ & str ] , namespace : Namespace ) -> Option < DefId > {
78
- tcx. crates ( ( ) ) . iter ( ) . find ( |& & krate| tcx. crate_name ( krate) . as_str ( ) == path[ 0 ] ) . and_then (
79
- |krate| {
80
- let krate = DefId { krate : * krate, index : CRATE_DEF_INDEX } ;
81
- let mut items = tcx. module_children ( krate) ;
82
-
83
- for & segment in & path[ 1 ..path. len ( ) - 1 ] {
84
- let next_mod = items. iter ( ) . find ( |item| {
85
- item. ident . name . as_str ( ) == segment
86
- && tcx. def_kind ( item. res . def_id ( ) ) == DefKind :: Mod
87
- } ) ?;
88
-
89
- items = tcx. module_children ( next_mod. res . def_id ( ) ) ;
90
- }
91
-
92
- let item_name = * path. last ( ) . unwrap ( ) ;
93
-
94
- let item = items. iter ( ) . find ( |item| {
95
- item. ident . name . as_str ( ) == item_name
96
- && tcx. def_kind ( item. res . def_id ( ) ) . ns ( ) == Some ( namespace)
97
- } ) ?;
77
+ ///
78
+ /// A `None` namespace indicates we are looking for a module.
79
+ fn try_resolve_did < ' tcx > (
80
+ tcx : TyCtxt < ' tcx > ,
81
+ path : & [ & str ] ,
82
+ namespace : Option < Namespace > ,
83
+ ) -> Option < DefId > {
84
+ /// Yield all children of the given item, that have the given name.
85
+ fn find_children < ' tcx : ' a , ' a > (
86
+ tcx : TyCtxt < ' tcx > ,
87
+ item : DefId ,
88
+ name : & ' a str ,
89
+ ) -> impl Iterator < Item = DefId > + ' a {
90
+ tcx. module_children ( item)
91
+ . iter ( )
92
+ . filter ( move |item| item. ident . name . as_str ( ) == name)
93
+ . map ( move |item| item. res . def_id ( ) )
94
+ }
98
95
99
- Some ( item. res . def_id ( ) )
100
- } ,
101
- )
96
+ // Take apart the path: leading crate, a sequence of modules, and potentially a final item.
97
+ let ( & crate_name, path) = path. split_first ( ) . expect ( "paths must have at least one segment" ) ;
98
+ let ( modules, item) = if let Some ( namespace) = namespace {
99
+ let ( & item_name, modules) =
100
+ path. split_last ( ) . expect ( "non-module paths must have at least 2 segments" ) ;
101
+ ( modules, Some ( ( item_name, namespace) ) )
102
+ } else {
103
+ ( path, None )
104
+ } ;
105
+
106
+ // First find the crate.
107
+ let krate =
108
+ tcx. crates ( ( ) ) . iter ( ) . find ( |& & krate| tcx. crate_name ( krate) . as_str ( ) == crate_name) ?;
109
+ let mut cur_item = DefId { krate : * krate, index : CRATE_DEF_INDEX } ;
110
+ // Then go over the modules.
111
+ for & segment in modules {
112
+ cur_item = find_children ( tcx, cur_item, segment)
113
+ . find ( |item| tcx. def_kind ( item) == DefKind :: Mod ) ?;
114
+ }
115
+ // Finally, look up the desired item in this module, if any.
116
+ match item {
117
+ Some ( ( item_name, namespace) ) =>
118
+ Some (
119
+ find_children ( tcx, cur_item, item_name)
120
+ . find ( |item| tcx. def_kind ( item) . ns ( ) == Some ( namespace) ) ?,
121
+ ) ,
122
+ None => Some ( cur_item) ,
123
+ }
102
124
}
103
125
104
126
pub trait EvalContextExt < ' mir , ' tcx : ' mir > : crate :: MiriInterpCxExt < ' mir , ' tcx > {
127
+ /// Checks if the given crate/module exists.
128
+ fn have_module ( & self , path : & [ & str ] ) -> bool {
129
+ try_resolve_did ( * self . eval_context_ref ( ) . tcx , path, None ) . is_some ( )
130
+ }
131
+
105
132
/// Gets an instance for a path; fails gracefully if the path does not exist.
106
133
fn try_resolve_path ( & self , path : & [ & str ] , namespace : Namespace ) -> Option < ty:: Instance < ' tcx > > {
107
- let did = try_resolve_did ( self . eval_context_ref ( ) . tcx . tcx , path, namespace) ?;
108
- Some ( ty:: Instance :: mono ( self . eval_context_ref ( ) . tcx . tcx , did) )
134
+ let tcx = self . eval_context_ref ( ) . tcx . tcx ;
135
+ let did = try_resolve_did ( tcx, path, Some ( namespace) ) ?;
136
+ Some ( ty:: Instance :: mono ( tcx, did) )
109
137
}
110
138
111
139
/// Gets an instance for a path.
0 commit comments