Skip to content

Commit 2ea5c96

Browse files
authored
transpile: Dedup keywords (#1636)
This change extracts keywords into `c2rust-transpile::RUST_KEYWORDS` and reduces the amount of renaming in a few places. If I have understood the code correctly, `RESERVED_NAMES` should have only been used when renaming types, but it was also being used when renaming field names and module names.
2 parents 594f7b4 + c54541b commit 2ea5c96

8 files changed

Lines changed: 163 additions & 422 deletions

File tree

c2rust-transpile/src/convert_type.rs

Lines changed: 3 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -29,118 +29,12 @@ pub struct TypeConverter {
2929
extern_crates: CrateSet,
3030
}
3131

32-
pub const RESERVED_NAMES: [&str; 100] = [
33-
// Keywords currently in use
34-
"as",
35-
"async",
36-
"await",
37-
"break",
38-
"const",
39-
"continue",
40-
"crate",
41-
"dyn",
42-
"else",
43-
"enum",
44-
"extern",
45-
"false",
46-
"fn",
47-
"for",
48-
"if",
49-
"impl",
50-
"in",
51-
"let",
52-
"loop",
53-
"match",
54-
"mod",
55-
"move",
56-
"mut",
57-
"pub",
58-
"ref",
59-
"return",
60-
"self",
61-
"Self",
62-
"static",
63-
"struct",
64-
"super",
65-
"trait",
66-
"true",
67-
"type",
68-
"unsafe",
69-
"use",
70-
"where",
71-
"while",
72-
// Keywords reserved for future use
73-
"abstract",
74-
"become",
75-
"box",
76-
"do",
77-
"final",
78-
"gen",
79-
"macro",
80-
"override",
81-
"priv",
82-
"try",
83-
"typeof",
84-
"unsized",
85-
"virtual",
86-
"yield",
87-
// Types exported in prelude
88-
"Copy",
89-
"Send",
90-
"Sized",
91-
"Sync",
92-
"Drop",
93-
"Fn",
94-
"FnMut",
95-
"FnOnce",
96-
"Box",
97-
"ToOwned",
98-
"Clone",
99-
"PartialEq",
100-
"PartialOrd",
101-
"Eq",
102-
"Ord",
103-
"AsRef",
104-
"AsMut",
105-
"Into",
106-
"From",
107-
"Default",
108-
"Iterator",
109-
"Extend",
110-
"IntoIterator",
111-
"DoubleEndedIterator",
112-
"ExactSizeIterator",
113-
"Option",
114-
"Result",
115-
"SliceConcatExt",
116-
"String",
117-
"ToString",
118-
"Vec",
119-
"bool",
120-
"char",
121-
"f32",
122-
"f64",
123-
"i8",
124-
"i16",
125-
"i32",
126-
"i64",
127-
"i128",
128-
"isize",
129-
"u8",
130-
"u16",
131-
"u32",
132-
"u64",
133-
"u128",
134-
"usize",
135-
"str",
136-
];
137-
13832
impl TypeConverter {
13933
pub fn new(tcfg: &TranspilerConfig) -> TypeConverter {
14034
TypeConverter {
14135
edition: tcfg.edition,
14236
translate_valist: tcfg.translate_valist,
143-
renamer: Renamer::new(&RESERVED_NAMES),
37+
renamer: Renamer::type_namespace(),
14438
fields: HashMap::new(),
14539
suffix_names: HashMap::new(),
14640
features: HashSet::new(),
@@ -197,7 +91,7 @@ impl TypeConverter {
19791

19892
self.fields
19993
.entry(record_id)
200-
.or_insert_with(|| Renamer::new(&RESERVED_NAMES))
94+
.or_insert_with(|| Renamer::keywords())
20195
.insert(FieldKey::Field(field_id), name)
20296
.expect("Field already declared")
20397
}
@@ -206,7 +100,7 @@ impl TypeConverter {
206100
let field = self
207101
.fields
208102
.entry(record_id)
209-
.or_insert_with(|| Renamer::new(&RESERVED_NAMES));
103+
.or_insert_with(|| Renamer::keywords());
210104
let key = FieldKey::Padding(padding_idx);
211105
if let Some(name) = field.get(&key) {
212106
name

c2rust-transpile/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use std::process::Command;
2020
use std::{env, io};
2121

2222
use crate::compile_cmds::CompileCmd;
23+
use crate::renamer::RUST_KEYWORDS;
2324
use c2rust_rust_tools::{rustfmt, RustEdition};
2425
use failure::{format_err, Error};
2526
use itertools::Itertools;
@@ -36,7 +37,6 @@ use c2rust_ast_exporter as ast_exporter;
3637

3738
use crate::build_files::{emit_build_files, get_build_dir, CrateConfig};
3839
use crate::compile_cmds::get_compile_commands;
39-
use crate::convert_type::RESERVED_NAMES;
4040
pub use crate::translator::ReplaceMode;
4141
use std::prelude::v1::Vec;
4242

@@ -248,7 +248,7 @@ fn str_to_ident_checked(s: &str, check_reserved: bool) -> String {
248248
let s = str_to_ident(s);
249249

250250
// make sure the name does not clash with keywords
251-
if check_reserved && RESERVED_NAMES.contains(&s.as_str()) {
251+
if check_reserved && RUST_KEYWORDS.contains(&s.as_str()) {
252252
format!("r#{}", s)
253253
} else {
254254
s

c2rust-transpile/src/renamer.rs

Lines changed: 142 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::collections::HashMap;
22
use std::collections::HashSet;
33
use std::hash::Hash;
4-
use std::iter::FromIterator;
54

65
struct Scope<T> {
76
name_map: HashMap<T, String>,
@@ -37,6 +36,125 @@ impl<T: Clone + Eq + Hash> Scope<T> {
3736
}
3837
}
3938

39+
// Keywords obtained from https://doc.rust-lang.org/reference/keywords.html
40+
#[rustfmt::skip] // Preserve one keyword per line.
41+
pub const RUST_KEYWORDS: &[&str] = &[
42+
// Strict keywords
43+
"as",
44+
"async", // 2018 Edition
45+
"await", // 2018 Edition
46+
"break",
47+
"const",
48+
"continue",
49+
"crate",
50+
"dyn", // 2018 Edition
51+
"else",
52+
"enum",
53+
"extern",
54+
"false",
55+
"fn",
56+
"for",
57+
"if",
58+
"impl",
59+
"in",
60+
"let",
61+
"loop",
62+
"match",
63+
"mod",
64+
"move",
65+
"mut",
66+
"pub",
67+
"ref",
68+
"return",
69+
"self",
70+
"Self",
71+
"static",
72+
"struct",
73+
"super",
74+
"trait",
75+
"true",
76+
"type",
77+
"unsafe",
78+
"use",
79+
"where",
80+
"while",
81+
// Reserved keywords
82+
"abstract",
83+
"become",
84+
"box",
85+
"do",
86+
"final",
87+
"gen", // 2024 Edition
88+
"macro",
89+
"override",
90+
"priv",
91+
"try", // 2018 Edition
92+
"typeof",
93+
"unsized",
94+
"virtual",
95+
"yield",
96+
];
97+
98+
const PRELUDE_TYPE_NAMESPACE: &[&str] = &[
99+
"Copy",
100+
"Send",
101+
"Sized",
102+
"Sync",
103+
"Drop",
104+
"Fn",
105+
"FnMut",
106+
"FnOnce",
107+
"Box",
108+
"ToOwned",
109+
"Clone",
110+
"PartialEq",
111+
"PartialOrd",
112+
"Eq",
113+
"Ord",
114+
"AsRef",
115+
"AsMut",
116+
"Into",
117+
"From",
118+
"Default",
119+
"Iterator",
120+
"Extend",
121+
"IntoIterator",
122+
"DoubleEndedIterator",
123+
"ExactSizeIterator",
124+
"Option",
125+
"Result",
126+
"SliceConcatExt",
127+
"String",
128+
"ToString",
129+
"Vec",
130+
"bool",
131+
"char",
132+
"f32",
133+
"f64",
134+
"i8",
135+
"i16",
136+
"i32",
137+
"i64",
138+
"i128",
139+
"isize",
140+
"u8",
141+
"u16",
142+
"u32",
143+
"u64",
144+
"u128",
145+
"usize",
146+
"str",
147+
];
148+
149+
#[rustfmt::skip] // Preserve one symbol per line.
150+
const PRELUDE_VALUE_NAMESPACE: &[&str] = &[
151+
"drop",
152+
"Some",
153+
"None",
154+
"Ok",
155+
"Err",
156+
];
157+
40158
pub struct Renamer<T> {
41159
scopes: Vec<Scope<T>>,
42160
next_fresh: u64,
@@ -46,14 +164,34 @@ impl<T: Clone + Eq + Hash> Renamer<T> {
46164
/// Creates a new renaming environment with a single, empty scope. The given set of
47165
/// reserved names will exclude those names from being chosen as the mangled names from
48166
/// the insert method.
49-
pub fn new(reserved_names: &[&str]) -> Self {
50-
let set: HashSet<String> = HashSet::from_iter(reserved_names.iter().map(|&x| x.to_owned()));
167+
pub fn new(reserved_names: &[&[&str]]) -> Self {
168+
let set = reserved_names
169+
.iter()
170+
.flat_map(|&names| names)
171+
.map(|&s| s.to_owned())
172+
.collect::<HashSet<_>>();
51173
Renamer {
52174
scopes: vec![Scope::new_with_reserved(set)],
53175
next_fresh: 0,
54176
}
55177
}
56178

179+
pub fn keywords() -> Self {
180+
Renamer::new(&[RUST_KEYWORDS])
181+
}
182+
183+
pub fn type_namespace() -> Self {
184+
Renamer::new(&[RUST_KEYWORDS, PRELUDE_TYPE_NAMESPACE])
185+
}
186+
187+
pub fn value_namespace() -> Self {
188+
Renamer::new(&[RUST_KEYWORDS, PRELUDE_VALUE_NAMESPACE])
189+
}
190+
191+
pub fn global_value_namespace() -> Self {
192+
Renamer::new(&[RUST_KEYWORDS, PRELUDE_VALUE_NAMESPACE, &["main"]])
193+
}
194+
57195
/// Introduces a new name binding scope
58196
pub fn add_scope(&mut self) {
59197
self.scopes.push(Scope::new())
@@ -190,7 +328,7 @@ mod tests {
190328

191329
#[test]
192330
fn simple() {
193-
let mut renamer = Renamer::new(&["reserved"]);
331+
let mut renamer = Renamer::new(&[&["reserved"]]);
194332

195333
let one1 = renamer.insert(1, "one").unwrap();
196334
let one2 = renamer.get(&1).unwrap();

c2rust-transpile/src/translator/mod.rs

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,19 +1545,8 @@ impl<'c> Translation<'c> {
15451545
type_converter: RefCell::new(type_converter),
15461546
ast_context,
15471547
tcfg,
1548-
renamer: RefCell::new(Renamer::new(&[
1549-
// Keywords currently in use
1550-
"as", "break", "const", "continue", "crate", "else", "enum", "extern", "false",
1551-
"fn", "for", "if", "impl", "in", "let", "loop", "match", "mod", "move", "mut",
1552-
"pub", "ref", "return", "Self", "self", "static", "struct", "super", "trait",
1553-
"true", "type", "unsafe", "use", "where", "while", "dyn",
1554-
// Keywords reserved for future use
1555-
"abstract", "alignof", "become", "box", "do", "final", "macro", "offsetof",
1556-
"override", "priv", "proc", "pure", "sizeof", "typeof", "unsized", "virtual",
1557-
"async", "try", "yield", // Prevent use for other reasons
1558-
"main", // prelude names
1559-
"drop", "Some", "None", "Ok", "Err",
1560-
])),
1548+
// TODO: Use Renamer::value_namespace() for most renamings.
1549+
renamer: RefCell::new(Renamer::global_value_namespace()),
15611550
zero_inits: RefCell::new(IndexMap::new()),
15621551
function_context: RefCell::new(FuncContext::new()),
15631552
potential_flexible_array_members: RefCell::new(IndexSet::new()),

0 commit comments

Comments
 (0)