From 9563d99ebcea5f99b8538992e18b90cf4e2c4645 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Fri, 6 Dec 2024 09:27:08 +0100 Subject: [PATCH] Rust: rework derived type paths --- rust/extractor/src/generated/.generated.list | 2 +- rust/extractor/src/generated/mod.rs | 7 +- rust/extractor/src/translate/base.rs | 105 ++++++++---------- rust/ql/.generated.list | 4 +- .../internal/DerivedTypeCanonicalPathImpl.qll | 12 +- .../rust/elements/internal/generated/Raw.qll | 4 +- .../DerivedTypeCanonicalPath.qll | 16 ++- rust/ql/lib/rust.dbscheme | 8 +- .../canonical_path/canonical_paths.expected | 25 +++++ .../extractor-tests/canonical_path/regular.rs | 28 +++++ rust/schema/prelude.py | 2 +- 11 files changed, 137 insertions(+), 76 deletions(-) diff --git a/rust/extractor/src/generated/.generated.list b/rust/extractor/src/generated/.generated.list index 6bd3437cfab..18f343101db 100644 --- a/rust/extractor/src/generated/.generated.list +++ b/rust/extractor/src/generated/.generated.list @@ -1 +1 @@ -mod.rs f28f770a937d79fa8a02058ecdb5a8898b43da3d4d785c7abd90af32e5d8ef23 f28f770a937d79fa8a02058ecdb5a8898b43da3d4d785c7abd90af32e5d8ef23 +mod.rs f80e3ee6008c0742d684de1fd89195710970b455dd2b5aedde5c895409e97ee4 f80e3ee6008c0742d684de1fd89195710970b455dd2b5aedde5c895409e97ee4 diff --git a/rust/extractor/src/generated/mod.rs b/rust/extractor/src/generated/mod.rs index 510ea80a5f0..48e2c1f35ff 100644 --- a/rust/extractor/src/generated/mod.rs +++ b/rust/extractor/src/generated/mod.rs @@ -11345,7 +11345,7 @@ impl From> for trap::Label, - pub modifier: String, + pub modifiers: Vec, pub base: Vec>, } @@ -11355,7 +11355,10 @@ impl trap::TrapEntry for DerivedTypeCanonicalPath { } fn emit(self, id: trap::Label, 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()]); } diff --git a/rust/extractor/src/translate/base.rs b/rust/extractor/src/translate/base.rs index 975777c08a8..a4716935f1a 100644 --- a/rust/extractor/src/translate/base.rs +++ b/rust/extractor/src/translate/base.rs @@ -327,6 +327,31 @@ impl<'a> Translator<'a> { ); } } + + fn emit_derived_type_canonical_path>( + &mut self, + modifiers: &[T], + bases: Vec>, + ) -> Label { + let modifiers = modifiers + .iter() + .map(|s| s.as_ref().to_owned()) + .collect::>(); + 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::>(); + let bases = tuple_args .into_iter() .map(|arg| self.canonical_path_from_type(arg)) .collect::>>()?; - 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(()) })(); } diff --git a/rust/ql/.generated.list b/rust/ql/.generated.list index 1f8a0fa0e6c..3b2bc50429c 100644 --- a/rust/ql/.generated.list +++ b/rust/ql/.generated.list @@ -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 diff --git a/rust/ql/lib/codeql/rust/elements/canonical_paths/internal/DerivedTypeCanonicalPathImpl.qll b/rust/ql/lib/codeql/rust/elements/canonical_paths/internal/DerivedTypeCanonicalPathImpl.qll index d4023aa82b8..b68c963fc28 100644 --- a/rust/ql/lib/codeql/rust/elements/canonical_paths/internal/DerivedTypeCanonicalPathImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/canonical_paths/internal/DerivedTypeCanonicalPathImpl.qll @@ -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() + ) } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/Raw.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/Raw.qll index 49f785cc932..62c4c260c36 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/Raw.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/Raw.qll @@ -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). diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/canonical_paths/DerivedTypeCanonicalPath.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/canonical_paths/DerivedTypeCanonicalPath.qll index 6cf5284b7ed..c325b887d86 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/canonical_paths/DerivedTypeCanonicalPath.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/canonical_paths/DerivedTypeCanonicalPath.qll @@ -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). */ diff --git a/rust/ql/lib/rust.dbscheme b/rust/ql/lib/rust.dbscheme index 8823a4e17e4..ceebbb7a9b8 100644 --- a/rust/ql/lib/rust.dbscheme +++ b/rust/ql/lib/rust.dbscheme @@ -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 ); diff --git a/rust/ql/test/extractor-tests/canonical_path/canonical_paths.expected b/rust/ql/test/extractor-tests/canonical_path/canonical_paths.expected index 50eb649c58a..f8f893bfd9b 100644 --- a/rust/ql/test/extractor-tests/canonical_path/canonical_paths.expected +++ b/rust/ql/test/extractor-tests/canonical_path/canonical_paths.expected @@ -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 | diff --git a/rust/ql/test/extractor-tests/canonical_path/regular.rs b/rust/ql/test/extractor-tests/canonical_path/regular.rs index 9df656ffa20..bbd0ba05d68 100644 --- a/rust/ql/test/extractor-tests/canonical_path/regular.rs +++ b/rust/ql/test/extractor-tests/canonical_path/regular.rs @@ -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(); +} diff --git a/rust/schema/prelude.py b/rust/schema/prelude.py index 640002fc7ab..a1ae6edbafe 100644 --- a/rust/schema/prelude.py +++ b/rust/schema/prelude.py @@ -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):