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
12 changes: 7 additions & 5 deletions c2rust-refactor/src/transform/reorganize_definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,13 +267,15 @@ impl<'a, 'tcx> Reorganizer<'a, 'tcx> {
return false;
}

// The header belongs to this module if it is named after it,
// either exactly or with the usual `_h` suffix. Splitting the
// header name at the module name's length in bytes would panic
// when that offset falls inside a multi-byte character.
let header_ident = declaration.parent_header.ident.as_str();
let module_ident = dest_module_info.orig_ident.as_str();
if header_ident.len() >= module_ident.len() {
let (base, ext) = header_ident.split_at(module_ident.len());
base == &*module_ident && (ext.is_empty() || ext == "_h")
} else {
false
match header_ident.strip_prefix(&*module_ident) {
Some(ext) => ext.is_empty() || ext == "_h",
None => false,
}
});
let dest_module = match dest_module {
Expand Down
17 changes: 17 additions & 0 deletions c2rust-refactor/tests/snapshots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,23 @@ fn test_reorganize_multi_namespace() {
.test();
}

/// `find_destination_id` decides whether a header belongs to a candidate
/// destination by comparing their names, which must not assume either is
/// ASCII: slicing the header name at the destination name's length in *bytes*
/// panics when that offset falls inside a multi-byte character.
///
/// Module `a` is one byte long, so comparing it against `ü_h` used to split
/// the `ü` in half; the names don't match, so `thing` moves to a new module.
/// Module `é` is the matching case, pinning down that non-ASCII names are
/// still compared correctly rather than merely never matching: `é_h` is named
/// after its parent, so `other` moves into it.
#[test]
fn test_reorganize_non_ascii_ident() {
refactor("reorganize_definitions")
.named("reorganize_non_ascii_ident.rs")
.test();
}

#[test]
fn test_reorganize_self_import_destination() {
refactor("reorganize_definitions")
Expand Down
40 changes: 40 additions & 0 deletions c2rust-refactor/tests/snapshots/reorganize_non_ascii_ident.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 a {
#[c2rust::header_src = "/home/user/some/workspace/ü.h:1"]
pub mod ü_h {
#[c2rust::src_loc = "2:0"]
#[derive(Copy, Clone)]
#[repr(C)]
pub struct thing {
pub x: i32,
}
}

pub fn go() -> i32 {
let t = ü_h::thing { x: 1 };
t.x
}
}

pub mod é {
#[c2rust::header_src = "/home/user/some/workspace/é.h:3"]
pub mod é_h {
#[c2rust::src_loc = "4:0"]
#[derive(Copy, Clone)]
#[repr(C)]
pub struct other {
pub y: i32,
}
}

pub fn go() -> i32 {
let o = é_h::other { y: 2 };
o.y
}
}

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

pub mod ü_h {
#[derive(Copy, Clone)]
#[repr(C)]
pub struct thing {
pub x: i32,
}
}
pub mod a {

pub fn go() -> i32 {
let t = crate::ü_h::thing { x: 1 };
t.x
}
}

pub mod é {

// =============== BEGIN é_h ================
#[derive(Copy, Clone)]
#[repr(C)]
pub struct other {
pub y: i32,
}

pub fn go() -> i32 {
let o = crate::é::other { y: 2 };
o.y
}
}

fn main() {}
Loading