Skip to content

Commit 9563d99

Browse files
author
Paolo Tranquilli
committed
Rust: rework derived type paths
1 parent 98d355f commit 9563d99

File tree

11 files changed

+137
-76
lines changed

11 files changed

+137
-76
lines changed

rust/extractor/src/generated/.generated.list

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/extractor/src/generated/mod.rs

Lines changed: 5 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/extractor/src/translate/base.rs

Lines changed: 45 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,31 @@ impl<'a> Translator<'a> {
327327
);
328328
}
329329
}
330+
331+
fn emit_derived_type_canonical_path<T: AsRef<str>>(
332+
&mut self,
333+
modifiers: &[T],
334+
bases: Vec<Label<generated::TypeCanonicalPath>>,
335+
) -> Label<generated::TypeCanonicalPath> {
336+
let modifiers = modifiers
337+
.iter()
338+
.map(|s| s.as_ref().to_owned())
339+
.collect::<Vec<String>>();
340+
let id = itertools::interleave(
341+
modifiers.iter().cloned(),
342+
bases.iter().map(|t| t.as_key_part()),
343+
)
344+
.join("")
345+
.into();
346+
self.trap
347+
.emit(generated::DerivedTypeCanonicalPath {
348+
id,
349+
modifiers,
350+
base: bases,
351+
})
352+
.into()
353+
}
354+
330355
fn canonical_path_from_type(
331356
&mut self,
332357
ty: Type,
@@ -368,41 +393,17 @@ impl<'a> Translator<'a> {
368393
.into(),
369394
)
370395
} else if let Some((it, size)) = ty.as_array(sema.db) {
371-
let modifier = format!("[{{0}}; {size}]");
372-
let base = vec![self.canonical_path_from_type(it)?];
373-
Some(
374-
self.trap
375-
.emit(generated::DerivedTypeCanonicalPath {
376-
id: trap_key!(modifier, base),
377-
modifier,
378-
base,
379-
})
380-
.into(),
381-
)
396+
let modifiers = ["[".to_owned(), format!("; {size}]")];
397+
let bases = vec![self.canonical_path_from_type(it)?];
398+
Some(self.emit_derived_type_canonical_path(&modifiers, bases))
382399
} else if let Some(it) = ty.as_slice() {
383-
let modifier = "[{0}]".to_owned();
384-
let base = vec![self.canonical_path_from_type(it)?];
385-
Some(
386-
self.trap
387-
.emit(generated::DerivedTypeCanonicalPath {
388-
id: trap_key!(modifier, base),
389-
modifier,
390-
base,
391-
})
392-
.into(),
393-
)
400+
let modifiers = ["[", "]"];
401+
let bases = vec![self.canonical_path_from_type(it)?];
402+
Some(self.emit_derived_type_canonical_path(&modifiers, bases))
394403
} else if ty.is_unit() {
395-
let modifier = "()".to_owned();
396-
let base = vec![];
397-
Some(
398-
self.trap
399-
.emit(generated::DerivedTypeCanonicalPath {
400-
id: trap_key!(modifier, base),
401-
modifier,
402-
base,
403-
})
404-
.into(),
405-
)
404+
let modifiers = ["()"];
405+
let bases = vec![];
406+
Some(self.emit_derived_type_canonical_path(&modifiers, bases))
406407
} else if let Some(it) = ty.as_builtin() {
407408
let name = it.name().as_str().to_owned();
408409
Some(
@@ -414,20 +415,13 @@ impl<'a> Translator<'a> {
414415
.into(),
415416
)
416417
} else if let Some((it, mutability)) = ty.as_reference() {
417-
let modifier = format!("&{}{{0}}", mutability.as_keyword_for_ref());
418-
let base = vec![self.canonical_path_from_type(it)?];
419-
Some(
420-
self.trap
421-
.emit(generated::DerivedTypeCanonicalPath {
422-
id: trap_key!(modifier, base),
423-
modifier,
424-
base,
425-
})
426-
.into(),
427-
)
418+
let modifiers = [format!("&{}", mutability.as_keyword_for_ref())];
419+
let bases = vec![self.canonical_path_from_type(it)?];
420+
Some(self.emit_derived_type_canonical_path(&modifiers, bases))
428421
} else if ty.as_type_param(sema.db).is_some() {
429422
// from the canonical path perspective, we just want a special name
430423
// e.g. `crate::<_ as SomeTrait>::func`
424+
// TODO: This will not work for assigning trap keys to types themselves!
431425
Some(
432426
self.trap
433427
.emit(generated::PlaceholderTypeCanonicalPath { id: trap_key!("_") })
@@ -438,20 +432,15 @@ impl<'a> Translator<'a> {
438432
if tuple_args.is_empty() {
439433
None
440434
} else {
441-
let modifier = format!("({{{}}})", (0..tuple_args.len()).join("}, {"));
442-
let base = tuple_args
435+
let modifiers = std::iter::once("(")
436+
.chain(std::iter::repeat(", ").take(tuple_args.len() - 1))
437+
.chain(std::iter::once(")"))
438+
.collect::<Vec<_>>();
439+
let bases = tuple_args
443440
.into_iter()
444441
.map(|arg| self.canonical_path_from_type(arg))
445442
.collect::<Option<Vec<_>>>()?;
446-
Some(
447-
self.trap
448-
.emit(generated::DerivedTypeCanonicalPath {
449-
id: trap_key!(modifier, base),
450-
modifier,
451-
base,
452-
})
453-
.into(),
454-
)
443+
Some(self.emit_derived_type_canonical_path(&modifiers, bases))
455444
}
456445
}
457446
}
@@ -712,11 +701,7 @@ impl<'a> Translator<'a> {
712701
return None;
713702
};
714703
let path = self.canonical_path_from_module_def(def)?;
715-
generated::Resolvable::emit_resolved_canonical_path(
716-
label.into(),
717-
path,
718-
&mut self.trap.writer,
719-
);
704+
generated::Resolvable::emit_resolved_canonical_path(label, path, &mut self.trap.writer);
720705
Some(())
721706
})();
722707
}

rust/ql/.generated.list

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/ql/lib/codeql/rust/elements/canonical_paths/internal/DerivedTypeCanonicalPathImpl.qll

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,14 @@ module Impl {
1616
* A derived canonical type, like `[i32; 4]`, `&mut std::string::String` or `(i32, std::string::String)`.
1717
*/
1818
class DerivedTypeCanonicalPath extends Generated::DerivedTypeCanonicalPath {
19-
override string toString() {
20-
result =
21-
this.getModifier() + "(" +
22-
strictconcat(int i | | this.getBase(i).toAbbreviatedString(), ", " order by i) + ")"
19+
override string toString() { result = strictconcat(int i | | this.toStringPart(i) order by i) }
20+
21+
private string toStringPart(int index) {
22+
exists(int j |
23+
index = 2 * j and result = this.getModifier(j)
24+
or
25+
index = 2 * j + 1 and result = this.getBase(j).toAbbreviatedString()
26+
)
2327
}
2428
}
2529
}

rust/ql/lib/codeql/rust/elements/internal/generated/Raw.qll

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/ql/lib/codeql/rust/elements/internal/generated/canonical_paths/DerivedTypeCanonicalPath.qll

Lines changed: 13 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/ql/lib/rust.dbscheme

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3477,7 +3477,13 @@ concrete_type_canonical_paths( //dir=canonical_paths
34773477
);
34783478

34793479
derived_type_canonical_paths( //dir=canonical_paths
3480-
unique int id: @derived_type_canonical_path,
3480+
unique int id: @derived_type_canonical_path
3481+
);
3482+
3483+
#keyset[id, index]
3484+
derived_type_canonical_path_modifiers( //dir=canonical_paths
3485+
int id: @derived_type_canonical_path ref,
3486+
int index: int ref,
34813487
string modifier: string ref
34823488
);
34833489

rust/ql/test/extractor-tests/canonical_path/canonical_paths.expected

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,18 @@ canonicalPaths
5858
| regular.rs:102:1:104:1 | impl GenericTrait::<...> for GenericEnum::<...> { ... } | None |
5959
| regular.rs:103:5:103:39 | fn generic_method | <... as ...>::generic_method |
6060
| regular.rs:106:1:119:1 | fn generic_usage | ...::generic_usage |
61+
| regular.rs:121:1:123:1 | impl Trait for ... { ... } | None |
62+
| regular.rs:122:5:122:18 | fn f | <... as ...>::f |
63+
| regular.rs:125:1:127:1 | impl Trait for ... { ... } | None |
64+
| regular.rs:126:5:126:18 | fn f | <... as ...>::f |
65+
| regular.rs:129:1:131:1 | impl Trait for ... { ... } | None |
66+
| regular.rs:130:5:130:18 | fn f | <... as ...>::f |
67+
| regular.rs:133:1:135:1 | impl Trait for ... { ... } | None |
68+
| regular.rs:134:5:134:18 | fn f | <... as ...>::f |
69+
| regular.rs:137:1:139:1 | impl Trait for ... { ... } | None |
70+
| regular.rs:138:5:138:18 | fn f | <... as ...>::f |
71+
| regular.rs:141:1:147:1 | fn use_trait | ...::use_trait |
72+
| regular.rs:144:5:144:17 | vec!... | None |
6173
resolvedPaths
6274
| anonymous.rs:27:17:27:30 | OtherStruct {...} | None |
6375
| anonymous.rs:28:9:28:9 | s | None |
@@ -105,6 +117,14 @@ resolvedPaths
105117
| regular.rs:117:13:117:37 | ...::U | ...::U |
106118
| regular.rs:118:5:118:5 | x | None |
107119
| regular.rs:118:5:118:23 | ... .generic_method(...) | <... as ...>::generic_method |
120+
| regular.rs:142:5:142:10 | ... .f(...) | <... as ...>::f |
121+
| regular.rs:143:5:143:15 | ... .f(...) | <... as ...>::f |
122+
| regular.rs:144:5:144:17 | ...::into_vec | <...>::into_vec |
123+
| regular.rs:144:5:144:17 | ...::new | None |
124+
| regular.rs:144:5:144:28 | ... .as_slice(...) | <...>::as_slice |
125+
| regular.rs:144:5:144:32 | ... .f(...) | <... as ...>::f |
126+
| regular.rs:145:5:145:16 | ... .f(...) | <... as ...>::f |
127+
| regular.rs:146:5:146:20 | ... .f(...) | <... as ...>::f |
108128
resolve
109129
| regular.rs:27:13:27:21 | Struct {...} | regular.rs:1:1:2:18 | struct Struct |
110130
| regular.rs:28:5:28:9 | ... .f(...) | regular.rs:9:5:9:18 | fn f |
@@ -133,3 +153,8 @@ resolve
133153
| regular.rs:116:5:116:27 | ... .generic_method(...) | regular.rs:99:5:99:37 | fn generic_method |
134154
| regular.rs:117:13:117:37 | ...::U | regular.rs:79:5:79:8 | U |
135155
| regular.rs:118:5:118:23 | ... .generic_method(...) | regular.rs:103:5:103:39 | fn generic_method |
156+
| regular.rs:142:5:142:10 | ... .f(...) | regular.rs:122:5:122:18 | fn f |
157+
| regular.rs:143:5:143:15 | ... .f(...) | regular.rs:126:5:126:18 | fn f |
158+
| regular.rs:144:5:144:32 | ... .f(...) | regular.rs:130:5:130:18 | fn f |
159+
| regular.rs:145:5:145:16 | ... .f(...) | regular.rs:134:5:134:18 | fn f |
160+
| regular.rs:146:5:146:20 | ... .f(...) | regular.rs:138:5:138:18 | fn f |

rust/ql/test/extractor-tests/canonical_path/regular.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,31 @@ fn generic_usage() {
117117
let x = GenericEnum::<&str, _>::U(0);
118118
x.generic_method(1);
119119
}
120+
121+
impl Trait for () {
122+
fn f(&self) {}
123+
}
124+
125+
impl Trait for (i32, &str) {
126+
fn f(&self) {}
127+
}
128+
129+
impl Trait for [i32] {
130+
fn f(&self) {}
131+
}
132+
133+
impl Trait for [&str; 2] {
134+
fn f(&self) {}
135+
}
136+
137+
impl Trait for [&str; 3] {
138+
fn f(&self) {}
139+
}
140+
141+
fn use_trait() {
142+
().f();
143+
(0, "").f();
144+
vec![0, 1, 2].as_slice().f();
145+
["", ""].f();
146+
["", "", ""].f();
147+
}

0 commit comments

Comments
 (0)