Skip to content

Commit e262a7b

Browse files
randomPoisonthedataking
authored andcommitted
Rename the module at its normal location
1 parent eb7f18b commit e262a7b

3 files changed

Lines changed: 82 additions & 35 deletions

File tree

c2rust-transpile/src/build_files/mod.rs

Lines changed: 70 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ pub fn emit_build_files<'lcmd>(
107107
})
108108
}
109109

110-
#[derive(Serialize)]
110+
#[derive(Clone, Debug, Serialize)]
111111
struct Module {
112112
path: Option<String>,
113113
name: String,
@@ -116,19 +116,23 @@ struct Module {
116116
}
117117

118118
#[derive(Debug, Default)]
119-
struct ModuleTree(BTreeMap<String, ModuleTree>);
119+
struct ModuleTree {
120+
children: BTreeMap<String, ModuleTree>,
121+
path_modules: Vec<Module>,
122+
}
120123

121124
impl ModuleTree {
122125
/// Convert the tree representation into a linear vector
123126
/// and push it into `res`
124127
fn linearize(&self, res: &mut Vec<Module>) {
125-
for (name, child) in self.0.iter() {
128+
res.extend(self.path_modules.iter().cloned());
129+
for (name, child) in self.children.iter() {
126130
child.linearize_internal(name, res);
127131
}
128132
}
129133

130134
fn linearize_internal(&self, name: &str, res: &mut Vec<Module>) {
131-
if self.0.is_empty() {
135+
if self.path_modules.is_empty() && self.children.is_empty() {
132136
res.push(Module {
133137
name: name.to_string(),
134138
path: None,
@@ -151,6 +155,55 @@ impl ModuleTree {
151155
});
152156
}
153157
}
158+
159+
fn insert_nested(&mut self, path: Vec<String>) {
160+
let mut cur = self;
161+
for name in path {
162+
cur = cur.children.entry(name).or_default();
163+
}
164+
}
165+
166+
fn insert_path_module(
167+
&mut self,
168+
parent_path: &[String],
169+
file_name: String,
170+
module_name: String,
171+
) {
172+
let mut cur = self;
173+
for name in parent_path {
174+
cur = cur.children.entry(name.clone()).or_default();
175+
}
176+
let name = cur.unique_child_name(&module_name);
177+
cur.path_modules.push(Module {
178+
path: Some(file_name),
179+
name,
180+
open: false,
181+
close: false,
182+
});
183+
}
184+
185+
fn unique_child_name(&self, module_name: &str) -> String {
186+
if !self.child_name_exists(module_name) {
187+
return module_name.to_owned();
188+
}
189+
190+
for i in 1.. {
191+
let candidate = format!("{module_name}{i}");
192+
if !self.child_name_exists(&candidate) {
193+
return candidate;
194+
}
195+
}
196+
197+
unreachable!("We tried all the numbers and couln't find one that didn't collide")
198+
}
199+
200+
fn child_name_exists(&self, module_name: &str) -> bool {
201+
self.children.contains_key(module_name)
202+
|| self
203+
.path_modules
204+
.iter()
205+
.any(|module| module.name == module_name)
206+
}
154207
}
155208

156209
#[derive(Debug, PartialEq, Eq)]
@@ -182,7 +235,7 @@ fn convert_module_list(
182235
});
183236

184237
let mut res = vec![];
185-
let mut module_tree = ModuleTree(BTreeMap::new());
238+
let mut module_tree = ModuleTree::default();
186239
// A C file can have the same stem as a sibling directory, such as
187240
// `hash.c` and `hash/sha1.c`. The current nested module emitter cannot
188241
// represent both at `mod hash`, so emit the file module with an explicit
@@ -207,28 +260,21 @@ fn convert_module_list(
207260
.then_some(*module)
208261
})
209262
.collect::<BTreeSet<_>>();
210-
let mut used_flat_names = BTreeSet::new();
211263

264+
let mut collision_relpaths = vec![];
212265
for m in &modules {
213266
match m.strip_prefix(build_dir) {
214267
Ok(relpath) if !tcfg.is_binary(m) && !collision_modules.contains(m) => {
215268
// The module is inside the build directory, use nested modules
216-
let mut cur = &mut module_tree;
217-
for name in module_path(relpath) {
218-
cur = cur.0.entry(name).or_default();
219-
}
269+
module_tree.insert_nested(module_path(relpath));
270+
}
271+
Ok(relpath) if !tcfg.is_binary(m) => {
272+
collision_relpaths.push(relpath.to_path_buf());
220273
}
221274
_ => {
222275
let relpath = diff_paths(m, build_dir).unwrap();
223276
let path = Some(relpath.to_str().unwrap().to_string());
224-
let name = if collision_modules.contains(m) {
225-
unique_collision_module_name(
226-
m.strip_prefix(build_dir).unwrap(),
227-
&mut used_flat_names,
228-
)
229-
} else {
230-
get_module_name(m, true, false, false).unwrap()
231-
};
277+
let name = get_module_name(m, true, false, false).unwrap();
232278
res.push(Module {
233279
path,
234280
name,
@@ -238,6 +284,12 @@ fn convert_module_list(
238284
}
239285
}
240286
}
287+
for relpath in collision_relpaths {
288+
let mut path = module_path(&relpath);
289+
let module_name = format!("{}_", path.pop().unwrap());
290+
let file_name = relpath.file_name().unwrap().to_str().unwrap().to_string();
291+
module_tree.insert_path_module(&path, file_name, module_name);
292+
}
241293
module_tree.linearize(&mut res);
242294
res
243295
}
@@ -251,21 +303,6 @@ fn module_path(path: &Path) -> Vec<String> {
251303
.collect()
252304
}
253305

254-
fn unique_collision_module_name(path: &Path, used_names: &mut BTreeSet<String>) -> String {
255-
let base = format!("c2rust_{}", module_path(path).into_iter().join("_"));
256-
if used_names.insert(base.clone()) {
257-
return base;
258-
}
259-
260-
for i in 1.. {
261-
let candidate = format!("{base}_{i}");
262-
if used_names.insert(candidate.clone()) {
263-
return candidate;
264-
}
265-
}
266-
unreachable!()
267-
}
268-
269306
fn emit_thin_binaries(
270307
tcfg: &TranspilerConfig,
271308
build_dir: &Path,

c2rust-transpile/tests/module_paths.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,16 +73,23 @@ fn sibling_file_and_directory_modules_do_not_collide() {
7373
c2rust_transpile::create_temp_compile_commands(&[
7474
src.join("main.c"),
7575
src.join("hash.c"),
76+
src.join("hash_.c"),
7677
src.join("hash/sha1.c"),
7778
]);
7879

7980
c2rust_transpile::transpile(config(output_dir.clone()), &compile_commands_path, &["-w"]);
8081

8182
let lib_rs = fs::read_to_string(output_dir.join("lib.rs")).unwrap();
8283
assert!(
83-
lib_rs.contains("#[path = \"src/hash.rs\"]\npub mod c2rust_src_hash;"),
84+
lib_rs.contains("pub mod hash_;"),
85+
"generated module tree should include the non-colliding hash_.rs \
86+
module normally:\n{lib_rs}"
87+
);
88+
assert!(
89+
lib_rs.contains("#[path = \"hash.rs\"]\n pub mod hash_1;"),
8490
"generated module tree should include the sibling hash.rs module via an \
85-
explicit path module instead of shadowing it with the hash/ directory:\n{lib_rs}"
91+
explicit path module inside its parent instead of shadowing it with \
92+
the hash/ directory:\n{lib_rs}"
8693
);
8794
assert!(
8895
lib_rs.contains("pub mod sha1;"),
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
int hash_utility(void) {
2+
return 7;
3+
}

0 commit comments

Comments
 (0)