Skip to content

parser: Fix resolution of #[path] dependencies from certain modules. #629

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 30, 2020
Merged
Show file tree
Hide file tree
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
37 changes: 25 additions & 12 deletions src/bindgen/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ impl<'a> Parser<'a> {
self.cache_expanded_crate.get(&pkg.name).unwrap().clone()
};

self.process_mod(pkg, None, &mod_items, 0)
self.process_mod(pkg, None, None, &mod_items, 0)
}

fn parse_mod(
Expand Down Expand Up @@ -240,30 +240,37 @@ impl<'a> Parser<'a> {
};

// Compute module directory according to Rust 2018 rules
let mod_dir_2018;
let submod_dir_2018;

let mod_dir = if depth == 0 || mod_path.ends_with("mod.rs") {
mod_path.parent().unwrap()
let mod_dir = mod_path.parent().unwrap();

let submod_dir = if depth == 0 || mod_path.ends_with("mod.rs") {
mod_dir
} else {
mod_dir_2018 = mod_path
submod_dir_2018 = mod_path
.parent()
.unwrap()
.join(mod_path.file_stem().unwrap());
&mod_dir_2018
&submod_dir_2018
};

self.process_mod(pkg, Some(&mod_dir), &mod_items, depth)
self.process_mod(pkg, Some(mod_dir), Some(submod_dir), &mod_items, depth)
}

/// `mod_dir` is the path to the current directory of the module. It may be
/// `None` for pre-expanded modules.
///
/// `submod_dir` is the path to search submodules in by default, which might
/// be different for rust 2018 for example.
fn process_mod(
&mut self,
pkg: &PackageRef,
mod_dir: Option<&FilePath>,
submod_dir: Option<&FilePath>,
items: &[syn::Item],
depth: usize,
) -> Result<(), Error> {
debug_assert_eq!(mod_dir.is_some(), submod_dir.is_some());
// We process the items first then the nested modules.
let nested_modules = self.out.load_syn_crate_mod(
&self.config,
Expand All @@ -275,18 +282,24 @@ impl<'a> Parser<'a> {

for item in nested_modules {
let next_mod_name = item.ident.to_string();

let cfg = Cfg::load(&item.attrs);
if let Some(ref cfg) = cfg {
self.cfg_stack.push(cfg.clone());
}

if let Some((_, ref inline_items)) = item.content {
let next_mod_dir = mod_dir.map(|dir| dir.join(&next_mod_name));
self.process_mod(pkg, next_mod_dir.as_deref(), inline_items, depth)?;
let next_submod_dir = submod_dir.map(|dir| dir.join(&next_mod_name));
self.process_mod(
pkg,
mod_dir,
next_submod_dir.as_deref(),
inline_items,
depth,
)?;
} else if let Some(mod_dir) = mod_dir {
let next_mod_path1 = mod_dir.join(next_mod_name.clone() + ".rs");
let next_mod_path2 = mod_dir.join(next_mod_name.clone()).join("mod.rs");
let submod_dir = submod_dir.unwrap();
let next_mod_path1 = submod_dir.join(next_mod_name.clone() + ".rs");
let next_mod_path2 = submod_dir.join(next_mod_name.clone()).join("mod.rs");

if next_mod_path1.exists() {
self.parse_mod(pkg, next_mod_path1.as_path(), depth + 1)?;
Expand Down
6 changes: 6 additions & 0 deletions tests/expectations/mod_2018.both.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,10 @@ typedef struct ExportMe {
uint64_t val;
} ExportMe;

typedef struct ExportMe2 {
uint64_t val;
} ExportMe2;

void export_me(struct ExportMe *val);

void export_me_2(struct ExportMe2*);
6 changes: 6 additions & 0 deletions tests/expectations/mod_2018.both.compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,18 @@ typedef struct ExportMe {
uint64_t val;
} ExportMe;

typedef struct ExportMe2 {
uint64_t val;
} ExportMe2;

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

void export_me(struct ExportMe *val);

void export_me_2(struct ExportMe2*);

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
6 changes: 6 additions & 0 deletions tests/expectations/mod_2018.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,10 @@ typedef struct {
uint64_t val;
} ExportMe;

typedef struct {
uint64_t val;
} ExportMe2;

void export_me(ExportMe *val);

void export_me_2(ExportMe2*);
6 changes: 6 additions & 0 deletions tests/expectations/mod_2018.compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,18 @@ typedef struct {
uint64_t val;
} ExportMe;

typedef struct {
uint64_t val;
} ExportMe2;

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

void export_me(ExportMe *val);

void export_me_2(ExportMe2*);

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
6 changes: 6 additions & 0 deletions tests/expectations/mod_2018.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@ struct ExportMe {
uint64_t val;
};

struct ExportMe2 {
uint64_t val;
};

extern "C" {

void export_me(ExportMe *val);

void export_me_2(ExportMe2*);

} // extern "C"
5 changes: 5 additions & 0 deletions tests/expectations/mod_2018.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,9 @@ cdef extern from *:
ctypedef struct ExportMe:
uint64_t val;

ctypedef struct ExportMe2:
uint64_t val;

void export_me(ExportMe *val);

void export_me_2(ExportMe2*);
6 changes: 6 additions & 0 deletions tests/expectations/mod_2018.tag.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,10 @@ struct ExportMe {
uint64_t val;
};

struct ExportMe2 {
uint64_t val;
};

void export_me(struct ExportMe *val);

void export_me_2(struct ExportMe2*);
6 changes: 6 additions & 0 deletions tests/expectations/mod_2018.tag.compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,18 @@ struct ExportMe {
uint64_t val;
};

struct ExportMe2 {
uint64_t val;
};

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

void export_me(struct ExportMe *val);

void export_me_2(struct ExportMe2*);

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
5 changes: 5 additions & 0 deletions tests/expectations/mod_2018.tag.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,9 @@ cdef extern from *:
cdef struct ExportMe:
uint64_t val;

cdef struct ExportMe2:
uint64_t val;

void export_me(ExportMe *val);

void export_me_2(ExportMe2*);
3 changes: 3 additions & 0 deletions tests/rust/mod_2018/src/nested.rs
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
pub mod other;

#[path = "other2.rs"]
pub mod other2;
7 changes: 7 additions & 0 deletions tests/rust/mod_2018/src/other2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#[repr(C)]
pub struct ExportMe2 {
val: u64
}

#[no_mangle]
pub unsafe extern "C" fn export_me_2(_: *mut ExportMe2) { }