Rust: rework derived type paths

This commit is contained in:
Paolo Tranquilli
2024-12-06 09:27:08 +01:00
parent 98d355fb1d
commit 9563d99ebc
11 changed files with 137 additions and 76 deletions

View File

@@ -1 +1 @@
mod.rs f28f770a937d79fa8a02058ecdb5a8898b43da3d4d785c7abd90af32e5d8ef23 f28f770a937d79fa8a02058ecdb5a8898b43da3d4d785c7abd90af32e5d8ef23
mod.rs f80e3ee6008c0742d684de1fd89195710970b455dd2b5aedde5c895409e97ee4 f80e3ee6008c0742d684de1fd89195710970b455dd2b5aedde5c895409e97ee4

View File

@@ -11345,7 +11345,7 @@ impl From<trap::Label<ConcreteTypeCanonicalPath>> for trap::Label<TypeCanonicalP
#[derive(Debug)]
pub struct DerivedTypeCanonicalPath {
pub id: trap::TrapId<DerivedTypeCanonicalPath>,
pub modifier: String,
pub modifiers: Vec<String>,
pub base: Vec<trap::Label<TypeCanonicalPath>>,
}
@@ -11355,7 +11355,10 @@ impl trap::TrapEntry for DerivedTypeCanonicalPath {
}
fn emit(self, id: trap::Label<Self>, out: &mut trap::Writer) {
out.add_tuple("derived_type_canonical_paths", vec![id.into(), self.modifier.into()]);
out.add_tuple("derived_type_canonical_paths", vec![id.into()]);
for (i, v) in self.modifiers.into_iter().enumerate() {
out.add_tuple("derived_type_canonical_path_modifiers", vec![id.into(), i.into(), v.into()]);
}
for (i, v) in self.base.into_iter().enumerate() {
out.add_tuple("derived_type_canonical_path_bases", vec![id.into(), i.into(), v.into()]);
}

View File

@@ -327,6 +327,31 @@ impl<'a> Translator<'a> {
);
}
}
fn emit_derived_type_canonical_path<T: AsRef<str>>(
&mut self,
modifiers: &[T],
bases: Vec<Label<generated::TypeCanonicalPath>>,
) -> Label<generated::TypeCanonicalPath> {
let modifiers = modifiers
.iter()
.map(|s| s.as_ref().to_owned())
.collect::<Vec<String>>();
let id = itertools::interleave(
modifiers.iter().cloned(),
bases.iter().map(|t| t.as_key_part()),
)
.join("")
.into();
self.trap
.emit(generated::DerivedTypeCanonicalPath {
id,
modifiers,
base: bases,
})
.into()
}
fn canonical_path_from_type(
&mut self,
ty: Type,
@@ -368,41 +393,17 @@ impl<'a> Translator<'a> {
.into(),
)
} else if let Some((it, size)) = ty.as_array(sema.db) {
let modifier = format!("[{{0}}; {size}]");
let base = vec![self.canonical_path_from_type(it)?];
Some(
self.trap
.emit(generated::DerivedTypeCanonicalPath {
id: trap_key!(modifier, base),
modifier,
base,
})
.into(),
)
let modifiers = ["[".to_owned(), format!("; {size}]")];
let bases = vec![self.canonical_path_from_type(it)?];
Some(self.emit_derived_type_canonical_path(&modifiers, bases))
} else if let Some(it) = ty.as_slice() {
let modifier = "[{0}]".to_owned();
let base = vec![self.canonical_path_from_type(it)?];
Some(
self.trap
.emit(generated::DerivedTypeCanonicalPath {
id: trap_key!(modifier, base),
modifier,
base,
})
.into(),
)
let modifiers = ["[", "]"];
let bases = vec![self.canonical_path_from_type(it)?];
Some(self.emit_derived_type_canonical_path(&modifiers, bases))
} else if ty.is_unit() {
let modifier = "()".to_owned();
let base = vec![];
Some(
self.trap
.emit(generated::DerivedTypeCanonicalPath {
id: trap_key!(modifier, base),
modifier,
base,
})
.into(),
)
let modifiers = ["()"];
let bases = vec![];
Some(self.emit_derived_type_canonical_path(&modifiers, bases))
} else if let Some(it) = ty.as_builtin() {
let name = it.name().as_str().to_owned();
Some(
@@ -414,20 +415,13 @@ impl<'a> Translator<'a> {
.into(),
)
} else if let Some((it, mutability)) = ty.as_reference() {
let modifier = format!("&{}{{0}}", mutability.as_keyword_for_ref());
let base = vec![self.canonical_path_from_type(it)?];
Some(
self.trap
.emit(generated::DerivedTypeCanonicalPath {
id: trap_key!(modifier, base),
modifier,
base,
})
.into(),
)
let modifiers = [format!("&{}", mutability.as_keyword_for_ref())];
let bases = vec![self.canonical_path_from_type(it)?];
Some(self.emit_derived_type_canonical_path(&modifiers, bases))
} else if ty.as_type_param(sema.db).is_some() {
// from the canonical path perspective, we just want a special name
// e.g. `crate::<_ as SomeTrait>::func`
// TODO: This will not work for assigning trap keys to types themselves!
Some(
self.trap
.emit(generated::PlaceholderTypeCanonicalPath { id: trap_key!("_") })
@@ -438,20 +432,15 @@ impl<'a> Translator<'a> {
if tuple_args.is_empty() {
None
} else {
let modifier = format!("({{{}}})", (0..tuple_args.len()).join("}, {"));
let base = tuple_args
let modifiers = std::iter::once("(")
.chain(std::iter::repeat(", ").take(tuple_args.len() - 1))
.chain(std::iter::once(")"))
.collect::<Vec<_>>();
let bases = tuple_args
.into_iter()
.map(|arg| self.canonical_path_from_type(arg))
.collect::<Option<Vec<_>>>()?;
Some(
self.trap
.emit(generated::DerivedTypeCanonicalPath {
id: trap_key!(modifier, base),
modifier,
base,
})
.into(),
)
Some(self.emit_derived_type_canonical_path(&modifiers, bases))
}
}
}
@@ -712,11 +701,7 @@ impl<'a> Translator<'a> {
return None;
};
let path = self.canonical_path_from_module_def(def)?;
generated::Resolvable::emit_resolved_canonical_path(
label.into(),
path,
&mut self.trap.writer,
);
generated::Resolvable::emit_resolved_canonical_path(label, path, &mut self.trap.writer);
Some(())
})();
}

View File

@@ -571,7 +571,7 @@ lib/codeql/rust/elements/internal/generated/PtrTypeRepr.qll 51d1e9e683fc79dddbff
lib/codeql/rust/elements/internal/generated/PureSynthConstructors.qll e5b8e69519012bbaae29dcb82d53f7f7ecce368c0358ec27ef6180b228a0057f e5b8e69519012bbaae29dcb82d53f7f7ecce368c0358ec27ef6180b228a0057f
lib/codeql/rust/elements/internal/generated/RangeExpr.qll 23cca03bf43535f33b22a38894f70d669787be4e4f5b8fe5c8f7b964d30e9027 18624cef6c6b679eeace2a98737e472432e0ead354cca02192b4d45330f047c9
lib/codeql/rust/elements/internal/generated/RangePat.qll 80826a6a6868a803aa2372e31c52a03e1811a3f1f2abdb469f91ca0bfdd9ecb6 34ee1e208c1690cba505dff2c588837c0cd91e185e2a87d1fe673191962276a9
lib/codeql/rust/elements/internal/generated/Raw.qll 4da93ab1fd3d45277dfb32aa66913dd2ccc6d3f7d52b5861038b74cf84a4e7b4 9a824c0093fdfd2d215736c18d3934f688ea6fdf5eb435513637eaff4119673b
lib/codeql/rust/elements/internal/generated/Raw.qll 16bcc7b31037cd9050b40bbcaf20e7fd56abeb14cab01fd094bad378ad41fde1 adeb639ad18e0dcdead0b85d6bc3d82ac6366f88476a525498136348de70a952
lib/codeql/rust/elements/internal/generated/RecordExpr.qll 2131b2cb336caa76170082e69776011bf02576bbfdd34ba68ca84af24209250a 39a2e3ec32352b594c43cc1295e0e8b3f9808173322d3d73cb7d48ef969d5565
lib/codeql/rust/elements/internal/generated/RecordExprField.qll 7e9f8663d3b74ebbc9603b10c9912f082febba6bd73d344b100bbd3edf837802 fbe6b578e7fd5d5a6f21bbb8c388957ab7210a6a249ec71510a50fb35b319ea1
lib/codeql/rust/elements/internal/generated/RecordExprFieldList.qll 179a97211fe7aa6265085d4d54115cdbc0e1cd7c9b2135591e8f36d6432f13d3 dd44bbbc1e83a1ed3a587afb729d7debf7aeb7b63245de181726af13090e50c0
@@ -638,7 +638,7 @@ lib/codeql/rust/elements/internal/generated/canonical_paths/CanonicalPathElement
lib/codeql/rust/elements/internal/generated/canonical_paths/ConcreteTypeCanonicalPath.qll 4401616f47a95cccec68199bb49c18442a78dde023832f8fd5e16c73219baede 12f65fd81dc20ff5f4b74dac2232818fe75cb2e7f9abfdcae2177acc620b2c0f
lib/codeql/rust/elements/internal/generated/canonical_paths/ConstGenericTypeArg.qll 69aae3c8c9d0ba87d543e6cec3d8783950b31888a6da15e5be37da81c7690238 780a9afc1e43ec885afc2ea22259c4f417244a7efcfb8dd3dc6209462e5faffc
lib/codeql/rust/elements/internal/generated/canonical_paths/CrateRoot.qll fe71542b7f5943dc612bf8e52bc817473276460a9138babb7b33176c97d734a7 9cdc982cd8bf7802a82ec08c628ee262c527e25967b15632dc0e47f8e78daa28
lib/codeql/rust/elements/internal/generated/canonical_paths/DerivedTypeCanonicalPath.qll 7370bc3c7d171f1cda9e6b268e3fd91de60ea0245798b65c78bd71cade5727bc fcba582a58f729e087b0a858e71cd581ce4371340b925b07b08daf3a5d11e9b4
lib/codeql/rust/elements/internal/generated/canonical_paths/DerivedTypeCanonicalPath.qll 8e57c57332da344c2b5d9fcdbd079da0f8e322d500b953c5ddeac12dd783fb6f 57224ed02e4e1ada6b01dfa58953bdd7f13cab06d55b90957e64d9d1accead0a
lib/codeql/rust/elements/internal/generated/canonical_paths/ImplItemCanonicalPath.qll ec8e443974dfa7320f996fd676eac81b39b577d3daef58289cba90b9fb0a87e4 100b0d7a10bfdaaa5812bca8efcda90bd4ba53251fccb03d263c563e1ab0041f
lib/codeql/rust/elements/internal/generated/canonical_paths/LangCrateRoot.qll 4573e6afb64c334e7337c996d944763cea78e05174e00f1f5fc7598a7b66e364 84892d3a47b66ae2fd0f542141ed747b2cd700731891a7f86fd1a193c745b3db
lib/codeql/rust/elements/internal/generated/canonical_paths/ModuleItemCanonicalPath.qll 0b31c6cff057a402051b44ea06a1224c107d8255848c028dbb48c5d8d5e92544 0e157a31e92d6cb9ac4a4cc828b204144def6511ff9fa9002f95b43064cb81e2

View File

@@ -16,10 +16,14 @@ module Impl {
* A derived canonical type, like `[i32; 4]`, `&mut std::string::String` or `(i32, std::string::String)`.
*/
class DerivedTypeCanonicalPath extends Generated::DerivedTypeCanonicalPath {
override string toString() {
result =
this.getModifier() + "(" +
strictconcat(int i | | this.getBase(i).toAbbreviatedString(), ", " order by i) + ")"
override string toString() { result = strictconcat(int i | | this.toStringPart(i) order by i) }
private string toStringPart(int index) {
exists(int j |
index = 2 * j and result = this.getModifier(j)
or
index = 2 * j + 1 and result = this.getBase(j).toAbbreviatedString()
)
}
}
}

View File

@@ -4204,9 +4204,9 @@ module Raw {
override string toString() { result = "DerivedTypeCanonicalPath" }
/**
* Gets the modifier of this derived type canonical path.
* Gets the `index`th modifier of this derived type canonical path (0-based).
*/
string getModifier() { derived_type_canonical_paths(this, result) }
string getModifier(int index) { derived_type_canonical_path_modifiers(this, index, result) }
/**
* Gets the `index`th base of this derived type canonical path (0-based).

View File

@@ -25,15 +25,25 @@ module Generated {
override string getAPrimaryQlClass() { result = "DerivedTypeCanonicalPath" }
/**
* Gets the modifier of this derived type canonical path.
* Gets the `index`th modifier of this derived type canonical path (0-based).
*/
string getModifier() {
string getModifier(int index) {
result =
Synth::convertDerivedTypeCanonicalPathToRaw(this)
.(Raw::DerivedTypeCanonicalPath)
.getModifier()
.getModifier(index)
}
/**
* Gets any of the modifiers of this derived type canonical path.
*/
final string getAModifier() { result = this.getModifier(_) }
/**
* Gets the number of modifiers of this derived type canonical path.
*/
final int getNumberOfModifiers() { result = count(int i | exists(this.getModifier(i))) }
/**
* Gets the `index`th base of this derived type canonical path (0-based).
*/

View File

@@ -3477,7 +3477,13 @@ concrete_type_canonical_paths( //dir=canonical_paths
);
derived_type_canonical_paths( //dir=canonical_paths
unique int id: @derived_type_canonical_path,
unique int id: @derived_type_canonical_path
);
#keyset[id, index]
derived_type_canonical_path_modifiers( //dir=canonical_paths
int id: @derived_type_canonical_path ref,
int index: int ref,
string modifier: string ref
);

View File

@@ -58,6 +58,18 @@ canonicalPaths
| regular.rs:102:1:104:1 | impl GenericTrait::<...> for GenericEnum::<...> { ... } | None |
| regular.rs:103:5:103:39 | fn generic_method | <... as ...>::generic_method |
| regular.rs:106:1:119:1 | fn generic_usage | ...::generic_usage |
| regular.rs:121:1:123:1 | impl Trait for ... { ... } | None |
| regular.rs:122:5:122:18 | fn f | <... as ...>::f |
| regular.rs:125:1:127:1 | impl Trait for ... { ... } | None |
| regular.rs:126:5:126:18 | fn f | <... as ...>::f |
| regular.rs:129:1:131:1 | impl Trait for ... { ... } | None |
| regular.rs:130:5:130:18 | fn f | <... as ...>::f |
| regular.rs:133:1:135:1 | impl Trait for ... { ... } | None |
| regular.rs:134:5:134:18 | fn f | <... as ...>::f |
| regular.rs:137:1:139:1 | impl Trait for ... { ... } | None |
| regular.rs:138:5:138:18 | fn f | <... as ...>::f |
| regular.rs:141:1:147:1 | fn use_trait | ...::use_trait |
| regular.rs:144:5:144:17 | vec!... | None |
resolvedPaths
| anonymous.rs:27:17:27:30 | OtherStruct {...} | None |
| anonymous.rs:28:9:28:9 | s | None |
@@ -105,6 +117,14 @@ resolvedPaths
| regular.rs:117:13:117:37 | ...::U | ...::U |
| regular.rs:118:5:118:5 | x | None |
| regular.rs:118:5:118:23 | ... .generic_method(...) | <... as ...>::generic_method |
| regular.rs:142:5:142:10 | ... .f(...) | <... as ...>::f |
| regular.rs:143:5:143:15 | ... .f(...) | <... as ...>::f |
| regular.rs:144:5:144:17 | ...::into_vec | <...>::into_vec |
| regular.rs:144:5:144:17 | ...::new | None |
| regular.rs:144:5:144:28 | ... .as_slice(...) | <...>::as_slice |
| regular.rs:144:5:144:32 | ... .f(...) | <... as ...>::f |
| regular.rs:145:5:145:16 | ... .f(...) | <... as ...>::f |
| regular.rs:146:5:146:20 | ... .f(...) | <... as ...>::f |
resolve
| regular.rs:27:13:27:21 | Struct {...} | regular.rs:1:1:2:18 | struct Struct |
| regular.rs:28:5:28:9 | ... .f(...) | regular.rs:9:5:9:18 | fn f |
@@ -133,3 +153,8 @@ resolve
| regular.rs:116:5:116:27 | ... .generic_method(...) | regular.rs:99:5:99:37 | fn generic_method |
| regular.rs:117:13:117:37 | ...::U | regular.rs:79:5:79:8 | U |
| regular.rs:118:5:118:23 | ... .generic_method(...) | regular.rs:103:5:103:39 | fn generic_method |
| regular.rs:142:5:142:10 | ... .f(...) | regular.rs:122:5:122:18 | fn f |
| regular.rs:143:5:143:15 | ... .f(...) | regular.rs:126:5:126:18 | fn f |
| regular.rs:144:5:144:32 | ... .f(...) | regular.rs:130:5:130:18 | fn f |
| regular.rs:145:5:145:16 | ... .f(...) | regular.rs:134:5:134:18 | fn f |
| regular.rs:146:5:146:20 | ... .f(...) | regular.rs:138:5:138:18 | fn f |

View File

@@ -117,3 +117,31 @@ fn generic_usage() {
let x = GenericEnum::<&str, _>::U(0);
x.generic_method(1);
}
impl Trait for () {
fn f(&self) {}
}
impl Trait for (i32, &str) {
fn f(&self) {}
}
impl Trait for [i32] {
fn f(&self) {}
}
impl Trait for [&str; 2] {
fn f(&self) {}
}
impl Trait for [&str; 3] {
fn f(&self) {}
}
fn use_trait() {
().f();
(0, "").f();
vec![0, 1, 2].as_slice().f();
["", ""].f();
["", "", ""].f();
}

View File

@@ -202,7 +202,7 @@ class DerivedTypeCanonicalPath(TypeCanonicalPath):
"""
A derived canonical type, like `[i32; 4]`, `&mut std::string::String` or `(i32, std::string::String)`.
"""
modifier: string
modifiers: list[string]
base: list[TypeCanonicalPath]
class ModuleItemCanonicalPath(CanonicalPath):