Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 245857b

Browse files
committed
refactor try_resolve_did and also support resolving crates/modules
1 parent 0822c31 commit 245857b

File tree

1 file changed

+54
-26
lines changed

1 file changed

+54
-26
lines changed

src/tools/miri/src/helpers.rs

Lines changed: 54 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -74,38 +74,66 @@ 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], 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+
}
9895

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+
}
102124
}
103125

104126
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+
105132
/// Gets an instance for a path; fails gracefully if the path does not exist.
106133
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))
109137
}
110138

111139
/// Gets an instance for a path.

0 commit comments

Comments
 (0)