Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 47 additions & 12 deletions c2rust-refactor/src/ast_manip/load_modules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use rustc_ast::*;
use rustc_parse::new_parser_from_file;
use rustc_session::parse::ParseSess;
use rustc_span::source_map::SourceMap;
use rustc_span::FileName;
use rustc_span::{sym, FileName};
use smallvec::SmallVec;
use std::path::PathBuf;

Expand All @@ -26,9 +26,20 @@ impl<'a> MutVisitor for LoadModules<'a> {
return mut_visit::noop_flat_map_item(i, self);
};

match mod_kind {
let child_path = match mod_kind {
ModKind::Loaded(_items, Inline::Yes, _spans) => {
// TODO: handle #[path="..."]
// An explicit `#[path = "..."]` on an inline module sets the directory
// used to resolve any of its out-of-line child modules.
let path_attr = attrs
.iter()
.find(|attr| attr.has_name(sym::path))
.and_then(|attr| attr.value_str());

if let Some(path) = path_attr {
self.dir_path.join(path.as_str())
} else {
self.dir_path.join(ident.as_str())
}
}

ModKind::Loaded(_items, Inline::No, _spans) => {
Expand All @@ -39,11 +50,24 @@ impl<'a> MutVisitor for LoadModules<'a> {
}

ModKind::Unloaded => {
// Look for dir_path/foo.rs, then try dir_path/foo/mod.rs
let mut mod_file_path = self.dir_path.join(ident.as_str()).with_extension("rs");
if !self.source_map.file_exists(&mod_file_path) {
mod_file_path = self.dir_path.join(ident.as_str()).join("mod.rs");
}
// An explicit `#[path = "..."]` overrides the usual file lookup;
// the transpiler emits this for modules whose name was deconflicted
// from a sibling (e.g. `hash.c` and `hash/` becoming `hash_` and `hash`).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't hash.c be hash_1?

let path_attr = attrs
.iter()
.find(|attr| attr.has_name(sym::path))
.and_then(|attr| attr.value_str());

let mod_file_path = if let Some(path) = path_attr {
self.dir_path.join(path.as_str())
Comment thread
ahomescu marked this conversation as resolved.
} else {
// Look for dir_path/foo.rs, then try dir_path/foo/mod.rs
let mut p = self.dir_path.join(ident.as_str()).with_extension("rs");
if !self.source_map.file_exists(&p) {
p = self.dir_path.join(ident.as_str()).join("mod.rs");
}
p
};
if !self.source_map.file_exists(&mod_file_path) {
panic!("unable to load module file {mod_file_path:?}");
}
Expand All @@ -52,16 +76,27 @@ impl<'a> MutVisitor for LoadModules<'a> {
new_parser_from_file(&self.parse_sess, &mod_file_path, Some(*span));
let (mut inner_attrs, items, inner_span) = parser
.parse_mod(&token::Eof)
.expect("failed to parse {mod_file_path:?}");
.expect(&format!("failed to parse {mod_file_path:?}"));

attrs.append(&mut inner_attrs);
*mod_kind = ModKind::Loaded(items, Inline::No, inner_span);

if path_attr.is_some() {
// If the module was loaded from a `#[path="..."]` attribute, use
// the parent directory of the specified file for any child modules.
Comment thread
ahomescu marked this conversation as resolved.
mod_file_path
.parent()
.expect("have module file path")
.to_owned()
} else {
self.dir_path.join(ident.as_str())
}
}
}
};

self.dir_path.push(ident.as_str());
let saved_dir_path = std::mem::replace(&mut self.dir_path, child_path);
let res = mut_visit::noop_flat_map_item(i, self);
self.dir_path.pop();
self.dir_path = saved_dir_path;

res
}
Expand Down
Loading