@@ -2,12 +2,12 @@ pub mod convert;
22
33use std:: cmp;
44use std:: iter;
5- use std:: mem;
65use std:: num:: NonZeroUsize ;
76use std:: time:: Duration ;
87
98use log:: trace;
109
10+ use rustc_hir:: def:: { DefKind , Namespace } ;
1111use rustc_hir:: def_id:: { DefId , CRATE_DEF_INDEX } ;
1212use rustc_middle:: mir;
1313use rustc_middle:: ty:: {
@@ -74,48 +74,79 @@ const UNIX_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = {
7474} ;
7575
7676/// Gets an instance for a path.
77- fn try_resolve_did < ' tcx > ( tcx : TyCtxt < ' tcx > , path : & [ & str ] ) -> 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- let mut path_it = path. iter ( ) . skip ( 1 ) . peekable ( ) ;
83-
84- while let Some ( segment) = path_it. next ( ) {
85- for item in mem:: take ( & mut items) . iter ( ) {
86- if item. ident . name . as_str ( ) == * segment {
87- if path_it. peek ( ) . is_none ( ) {
88- return Some ( item. res . def_id ( ) ) ;
89- }
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+ }
9095
91- items = tcx. module_children ( item. res . def_id ( ) ) ;
92- break ;
93- }
94- }
95- }
96- None
97- } ,
98- )
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+ }
99124}
100125
101126pub 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+
102132 /// Gets an instance for a path; fails gracefully if the path does not exist.
103- fn try_resolve_path ( & self , path : & [ & str ] ) -> Option < ty:: Instance < ' tcx > > {
104- let did = try_resolve_did ( self . eval_context_ref ( ) . tcx . tcx , path) ?;
105- Some ( ty:: Instance :: mono ( self . eval_context_ref ( ) . tcx . tcx , did) )
133+ fn try_resolve_path ( & self , path : & [ & str ] , namespace : Namespace ) -> Option < ty:: Instance < ' tcx > > {
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) )
106137 }
107138
108139 /// Gets an instance for a path.
109- fn resolve_path ( & self , path : & [ & str ] ) -> ty:: Instance < ' tcx > {
110- self . try_resolve_path ( path)
140+ fn resolve_path ( & self , path : & [ & str ] , namespace : Namespace ) -> ty:: Instance < ' tcx > {
141+ self . try_resolve_path ( path, namespace )
111142 . unwrap_or_else ( || panic ! ( "failed to find required Rust item: {path:?}" ) )
112143 }
113144
114145 /// Evaluates the scalar at the specified path. Returns Some(val)
115146 /// if the path could be resolved, and None otherwise
116147 fn eval_path_scalar ( & self , path : & [ & str ] ) -> InterpResult < ' tcx , Scalar < Provenance > > {
117148 let this = self . eval_context_ref ( ) ;
118- let instance = this. resolve_path ( path) ;
149+ let instance = this. resolve_path ( path, Namespace :: ValueNS ) ;
119150 let cid = GlobalId { instance, promoted : None } ;
120151 // We don't give a span -- this isn't actually used directly by the program anyway.
121152 let const_val = this. eval_global ( cid, None ) ?;
@@ -147,15 +178,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
147178 /// Helper function to get the `TyAndLayout` of a `libc` type
148179 fn libc_ty_layout ( & self , name : & str ) -> InterpResult < ' tcx , TyAndLayout < ' tcx > > {
149180 let this = self . eval_context_ref ( ) ;
150- let ty = this. resolve_path ( & [ "libc" , name] ) . ty ( * this. tcx , ty:: ParamEnv :: reveal_all ( ) ) ;
181+ let ty = this
182+ . resolve_path ( & [ "libc" , name] , Namespace :: TypeNS )
183+ . ty ( * this. tcx , ty:: ParamEnv :: reveal_all ( ) ) ;
151184 this. layout_of ( ty)
152185 }
153186
154187 /// Helper function to get the `TyAndLayout` of a `windows` type
155188 fn windows_ty_layout ( & self , name : & str ) -> InterpResult < ' tcx , TyAndLayout < ' tcx > > {
156189 let this = self . eval_context_ref ( ) ;
157190 let ty = this
158- . resolve_path ( & [ "std" , "sys" , "windows" , "c" , name] )
191+ . resolve_path ( & [ "std" , "sys" , "windows" , "c" , name] , Namespace :: TypeNS )
159192 . ty ( * this. tcx , ty:: ParamEnv :: reveal_all ( ) ) ;
160193 this. layout_of ( ty)
161194 }
0 commit comments