Skip to content

Commit 6085fcb

Browse files
authored
Assert that both C++ and Rust rules use the same generics (#101)
1 parent a6d3427 commit 6085fcb

7 files changed

Lines changed: 34 additions & 17 deletions

File tree

cpp2rust/converter/mapper.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,6 @@ matchTemplate(const std::string &template_str,
227227
size_t si = 0;
228228

229229
while (ti < template_str.size()) {
230-
// Match T{N}. TODO: currently only T0..9 are supported
231230
if (template_str[ti] == 'T' && ti + 1 < template_str.size() &&
232231
std::isdigit(template_str[ti + 1])) {
233232
size_t tj = ti + 2;
@@ -236,6 +235,8 @@ matchTemplate(const std::string &template_str,
236235
}
237236

238237
size_t type_idx = std::stoi(&template_str[ti + 1]) - 1;
238+
assert(type_idx < TranslationRule::kMaxGenerics &&
239+
"template placeholder exceeds kMaxGenerics");
239240
ti = tj;
240241

241242
std::string_view nextLit;
@@ -341,7 +342,8 @@ matchTemplate(const std::string &template_str,
341342
// result = "Vec<i32>"
342343
std::string instantiateTgt(const std::vector<std::optional<std::string>> &types,
343344
const std::string &tgt_template) {
344-
assert(types.size() <= 9);
345+
assert(types.size() <= TranslationRule::kMaxGenerics &&
346+
"template placeholder exceeds kMaxGenerics");
345347
std::string instantiated_template = tgt_template;
346348
std::string::size_type pos = 0;
347349
while ((pos = instantiated_template.find('T', pos)) != std::string::npos) {

cpp2rust/converter/translation_rule.cpp

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,28 @@ void ExprRule::dump() const {
303303
}
304304
}
305305

306+
std::array<const char *, kMaxGenerics> kGenericPlaceholders = {
307+
"T1", "T2", "T3", "T4", "T5", "T6", "T7", "T8", "T9"};
308+
309+
void ExprRule::validate(const std::string &name) const {
310+
if (src.empty()) {
311+
llvm::errs() << name << '\n';
312+
dump();
313+
assert(0 && "Expr rule loaded from IR but has no src");
314+
}
315+
316+
for (unsigned i = 0, e = generics.size(); i < e; ++i) {
317+
const char *placeholder = kGenericPlaceholders[i];
318+
if (src.find(placeholder) == std::string::npos) {
319+
llvm::errs() << name << '\n';
320+
dump();
321+
llvm::errs() << "generic " << placeholder
322+
<< " declared but missing from src: " << src << '\n';
323+
assert(0 && "Expr rule declares a generic absent from its src");
324+
}
325+
}
326+
}
327+
306328
void GenericFragment::dump() const { log() << " generic: " << n << '\n'; }
307329

308330
void TypeInfo::dump() const {
@@ -339,11 +361,7 @@ std::pair<ExprRules, TypeRules> Load(const std::filesystem::path &path,
339361
LoadIrSrc(exprs, types, dir / "ir_src.json");
340362

341363
for (auto &[name, rule] : exprs) {
342-
if (rule.src.empty()) {
343-
llvm::errs() << name << '\n';
344-
rule.dump();
345-
assert(0 && "Expr rule loaded from IR but has no src");
346-
}
364+
rule.validate(name);
347365
}
348366
for (auto &[name, rule] : types) {
349367
if (rule.src.empty()) {

cpp2rust/converter/translation_rule.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
namespace cpp2rust::TranslationRule {
1717

18+
inline constexpr unsigned kMaxGenerics = 9;
19+
1820
struct TextFragment {
1921
std::string text;
2022

@@ -70,6 +72,7 @@ struct ExprRule {
7072
bool multi_statement = false;
7173

7274
void dump() const;
75+
void validate(const std::string &name) const;
7376
};
7477

7578
struct TypeRule {

rules/algorithm/ir_unsafe.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -419,9 +419,6 @@
419419
}
420420
}
421421
],
422-
"generics": {
423-
"T1": []
424-
},
425422
"multi_statement": true,
426423
"params": {
427424
"a0": {

rules/algorithm/tgt_unsafe.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ unsafe fn f12<T1: Clone>(a0: *mut T1, a1: *mut T1, a2: T1) {
110110
}
111111
}
112112

113-
unsafe fn f13<T1>(a0: *const u8, a1: *const u8, a2: &mut ::std::fs::File) -> ::std::fs::File {
113+
unsafe fn f13(a0: *const u8, a1: *const u8, a2: &mut ::std::fs::File) -> ::std::fs::File {
114114
let __start = a0 as *const u8;
115115
let __end = a1 as *const u8;
116116
let __len = __end.offset_from(__start) as usize;

rules/string/ir_unsafe.json

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,19 +1212,16 @@
12121212
"text": " as usize]\n }"
12131213
}
12141214
],
1215-
"generics": {
1216-
"T1": []
1217-
},
12181215
"params": {
12191216
"a0": {
1220-
"type": "&mut Vec<T1>"
1217+
"type": "&mut Vec<u8>"
12211218
},
12221219
"a1": {
12231220
"type": "usize"
12241221
}
12251222
},
12261223
"return_type": {
1227-
"type": "*mut T1",
1224+
"type": "*mut u8",
12281225
"is_unsafe_pointer": true
12291226
}
12301227
},

rules/string/tgt_unsafe.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ unsafe fn f25(a0: &mut Vec<u8>) {
146146
a0.shrink_to_fit()
147147
}
148148

149-
unsafe fn f26<T1>(a0: &mut Vec<T1>, a1: usize) -> *mut T1 {
149+
unsafe fn f26(a0: &mut Vec<u8>, a1: usize) -> *mut u8 {
150150
if a1 as usize >= a0.len() - 1 {
151151
panic!("out of bounds access")
152152
} else {

0 commit comments

Comments
 (0)