Skip to content
Open
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
5 changes: 5 additions & 0 deletions c2rust-refactor/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -944,6 +944,11 @@ impl<'a, 'tcx> RefactorCtxt<'a, 'tcx> {
smallvec![Namespace::TypeNS, Namespace::ValueNS]
}

// A macro shares no namespace with a type or a value of the same
// name, so it must not be reported as occupying `TypeNS`; doing so
// makes an unrelated type of the same name look like a collision.
ItemKind::MacroDef(..) => smallvec![Namespace::MacroNS],

_ => smallvec![Namespace::TypeNS],
}
}
Expand Down
6 changes: 6 additions & 0 deletions c2rust-refactor/src/transform/reorganize_definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,12 @@ impl<'a, 'tcx> Reorganizer<'a, 'tcx> {
// Values
ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => Namespace::ValueNS,

// Macros. Kept in sync with `item_namespaces`, which decides
// the namespaces the declarations searched below were filed
// under; classifying a macro here as a type would look for it
// among the type declarations and never find it.
ItemKind::MacroDef(..) => Namespace::MacroNS,

// Types
_ => Namespace::TypeNS,
};
Expand Down
10 changes: 10 additions & 0 deletions c2rust-refactor/tests/snapshots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,16 @@ fn test_reorganize_forward_decl_with_local_definition() {
.test();
}

/// A macro and a struct sharing a name live in different namespaces and do
/// not collide, so the struct must still move into the module holding the
/// macro rather than being banished to a new `thing_h` module.
#[test]
fn test_reorganize_macro_namespace() {
refactor("reorganize_definitions")
.named("reorganize_macro_namespace.rs")
.test();
}

#[test]
fn test_reorganize_multi_namespace() {
refactor("reorganize_definitions")
Expand Down
40 changes: 40 additions & 0 deletions c2rust-refactor/tests/snapshots/reorganize_macro_namespace.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#![feature(register_tool)]
#![register_tool(c2rust)]
#![allow(non_camel_case_types)]
#![allow(dead_code)]

pub mod thing {
#[c2rust::header_src = "/home/user/some/workspace/thing.h:1"]
pub mod thing_h {
#[c2rust::src_loc = "2:0"]
#[derive(Copy, Clone)]
#[repr(C)]
pub struct point {
pub x: i32,
}
}

// A macro sharing the `point` spelling with the struct in the header
// above. Macros live in the macro namespace, so the two names do not
// collide and the struct still moves into this module. Classifying
// `MacroDef` as a type instead would make `update_module_info_items`
// record `point` as occupying this module's *type* namespace, and
// `find_destination_id` would reject `thing` as a destination.
//
// Note there is deliberately no `use self::thing_h::point;` here: an
// import of the struct would land in `import_targets` and let the
// conflict check see that the two `point`s are the same definition,
// masking the misclassification.
macro_rules! point {
() => {
0
};
}

pub fn go() -> i32 {
let p = thing_h::point { x: point!() };
p.x
}
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
source: c2rust-refactor/tests/snapshots.rs
expression: c2rust-refactor reorganize_definitions --rewrite-mode alongside -- tests/snapshots/reorganize_macro_namespace.rs --edition 2021
---
#![feature(register_tool)]
#![register_tool(c2rust)]
#![allow(non_camel_case_types)]
#![allow(dead_code)]

pub mod thing {

// =============== BEGIN thing_h ================
#[derive(Copy, Clone)]
#[repr(C)]
pub struct point {
pub x: i32,
}

// A macro sharing the `point` spelling with the struct in the header
// above. Macros live in the macro namespace, so the two names do not
// collide and the struct still moves into this module. Classifying
// `MacroDef` as a type instead would make `update_module_info_items`
// record `point` as occupying this module's *type* namespace, and
// `find_destination_id` would reject `thing` as a destination.
//
// Note there is deliberately no `use self::thing_h::point;` here: an
// import of the struct would land in `import_targets` and let the
// conflict check see that the two `point`s are the same definition,
// masking the misclassification.
macro_rules! point {
() => {
0
};
}

pub fn go() -> i32 {
let p = crate::thing::point { x: point!() };
p.x
}
}

fn main() {}
Loading