Merge branch 'main' into rust-saa-additions

This commit is contained in:
Simon Friis Vindum
2024-10-28 11:42:32 +01:00
318 changed files with 16386 additions and 15278 deletions

View File

@@ -1,2 +1,2 @@
mod.rs 4bcb9def847469aae9d8649461546b7c21ec97cf6e63d3cf394e339915ce65d7 4bcb9def847469aae9d8649461546b7c21ec97cf6e63d3cf394e339915ce65d7
top.rs f7bff00786adef1f7f80825d9f613a958c92d35896ea8c3c3b077b9992dca590 f7bff00786adef1f7f80825d9f613a958c92d35896ea8c3c3b077b9992dca590
top.rs a77ab900964451c668839aad6827ea539b8932e7c93b54a7987ece0e1bd846ba a77ab900964451c668839aad6827ea539b8932e7c93b54a7987ece0e1bd846ba

View File

@@ -6232,62 +6232,44 @@ impl From<trap::Label<ParenType>> for trap::Label<TypeRef> {
}
#[derive(Debug)]
pub struct PathExpr {
pub id: trap::TrapId<PathExpr>,
pub attrs: Vec<trap::Label<Attr>>,
pub path: Option<trap::Label<Path>>,
pub struct PathExprBase {
_unused: ()
}
impl trap::TrapEntry for PathExpr {
fn extract_id(&mut self) -> trap::TrapId<Self> {
std::mem::replace(&mut self.id, trap::TrapId::Star)
}
fn emit(self, id: trap::Label<Self>, out: &mut trap::Writer) {
out.add_tuple("path_exprs", vec![id.into()]);
for (i, v) in self.attrs.into_iter().enumerate() {
out.add_tuple("path_expr_attrs", vec![id.into(), i.into(), v.into()]);
}
if let Some(v) = self.path {
out.add_tuple("path_expr_paths", vec![id.into(), v.into()]);
}
}
impl trap::TrapClass for PathExprBase {
fn class_name() -> &'static str { "PathExprBase" }
}
impl trap::TrapClass for PathExpr {
fn class_name() -> &'static str { "PathExpr" }
}
impl From<trap::Label<PathExpr>> for trap::Label<AstNode> {
fn from(value: trap::Label<PathExpr>) -> Self {
// SAFETY: this is safe because in the dbscheme PathExpr is a subclass of AstNode
impl From<trap::Label<PathExprBase>> for trap::Label<AstNode> {
fn from(value: trap::Label<PathExprBase>) -> Self {
// SAFETY: this is safe because in the dbscheme PathExprBase is a subclass of AstNode
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<PathExpr>> for trap::Label<Element> {
fn from(value: trap::Label<PathExpr>) -> Self {
// SAFETY: this is safe because in the dbscheme PathExpr is a subclass of Element
impl From<trap::Label<PathExprBase>> for trap::Label<Element> {
fn from(value: trap::Label<PathExprBase>) -> Self {
// SAFETY: this is safe because in the dbscheme PathExprBase is a subclass of Element
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<PathExpr>> for trap::Label<Expr> {
fn from(value: trap::Label<PathExpr>) -> Self {
// SAFETY: this is safe because in the dbscheme PathExpr is a subclass of Expr
impl From<trap::Label<PathExprBase>> for trap::Label<Expr> {
fn from(value: trap::Label<PathExprBase>) -> Self {
// SAFETY: this is safe because in the dbscheme PathExprBase is a subclass of Expr
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<PathExpr>> for trap::Label<Locatable> {
fn from(value: trap::Label<PathExpr>) -> Self {
// SAFETY: this is safe because in the dbscheme PathExpr is a subclass of Locatable
impl From<trap::Label<PathExprBase>> for trap::Label<Locatable> {
fn from(value: trap::Label<PathExprBase>) -> Self {
// SAFETY: this is safe because in the dbscheme PathExprBase is a subclass of Locatable
unsafe {
Self::from_untyped(value.as_untyped())
}
@@ -9225,6 +9207,78 @@ impl From<trap::Label<Module>> for trap::Label<Stmt> {
}
}
#[derive(Debug)]
pub struct PathExpr {
pub id: trap::TrapId<PathExpr>,
pub attrs: Vec<trap::Label<Attr>>,
pub path: Option<trap::Label<Path>>,
}
impl trap::TrapEntry for PathExpr {
fn extract_id(&mut self) -> trap::TrapId<Self> {
std::mem::replace(&mut self.id, trap::TrapId::Star)
}
fn emit(self, id: trap::Label<Self>, out: &mut trap::Writer) {
out.add_tuple("path_exprs", vec![id.into()]);
for (i, v) in self.attrs.into_iter().enumerate() {
out.add_tuple("path_expr_attrs", vec![id.into(), i.into(), v.into()]);
}
if let Some(v) = self.path {
out.add_tuple("path_expr_paths", vec![id.into(), v.into()]);
}
}
}
impl trap::TrapClass for PathExpr {
fn class_name() -> &'static str { "PathExpr" }
}
impl From<trap::Label<PathExpr>> for trap::Label<AstNode> {
fn from(value: trap::Label<PathExpr>) -> Self {
// SAFETY: this is safe because in the dbscheme PathExpr is a subclass of AstNode
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<PathExpr>> for trap::Label<Element> {
fn from(value: trap::Label<PathExpr>) -> Self {
// SAFETY: this is safe because in the dbscheme PathExpr is a subclass of Element
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<PathExpr>> for trap::Label<Expr> {
fn from(value: trap::Label<PathExpr>) -> Self {
// SAFETY: this is safe because in the dbscheme PathExpr is a subclass of Expr
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<PathExpr>> for trap::Label<Locatable> {
fn from(value: trap::Label<PathExpr>) -> Self {
// SAFETY: this is safe because in the dbscheme PathExpr is a subclass of Locatable
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<PathExpr>> for trap::Label<PathExprBase> {
fn from(value: trap::Label<PathExpr>) -> Self {
// SAFETY: this is safe because in the dbscheme PathExpr is a subclass of PathExprBase
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
#[derive(Debug)]
pub struct Static {
pub id: trap::TrapId<Static>,

View File

@@ -1,5 +1,5 @@
use itertools::Itertools;
use log::info;
use log::{debug, info};
use ra_ap_base_db::SourceDatabase;
use ra_ap_base_db::SourceDatabaseFileInputExt;
use ra_ap_hir::Semantics;
@@ -119,10 +119,21 @@ pub fn find_project_manifests(
.map(|path| AbsPathBuf::assert_utf8(current.join(path)))
.collect();
let ret = ra_ap_project_model::ProjectManifest::discover_all(&abs_files);
info!(
"found manifests: {}",
ret.iter().map(|m| format!("{m}")).join(", ")
);
let iter = || ret.iter().map(|m| format!(" {m}"));
const LOG_LIMIT: usize = 10;
if ret.len() <= LOG_LIMIT {
info!("found manifests:\n{}", iter().join("\n"));
} else {
info!(
"found manifests:\n{}\nand {} more",
iter().take(LOG_LIMIT).join("\n"),
ret.len() - LOG_LIMIT
);
debug!(
"rest of the manifests found:\n{}",
iter().dropping(LOG_LIMIT).join("\n")
);
}
Ok(ret)
}
fn from_utf8_lossy(v: &[u8]) -> (Cow<'_, str>, Option<SyntaxError>) {

View File

@@ -142,7 +142,7 @@ impl<'a> Translator<'a> {
self.trap.emit_location(self.label, label, start, end)
} else {
self.emit_diagnostic(
DiagnosticSeverity::Info,
DiagnosticSeverity::Debug,
"locations".to_owned(),
"missing location for AstNode".to_owned(),
"missing location for AstNode".to_owned(),
@@ -169,9 +169,9 @@ impl<'a> Translator<'a> {
pub fn emit_diagnostic(
&mut self,
severity: DiagnosticSeverity,
error_tag: String,
error_message: String,
full_error_message: String,
tag: String,
message: String,
full_message: String,
location: (LineCol, LineCol),
) {
let (start, end) = location;
@@ -187,16 +187,13 @@ impl<'a> Translator<'a> {
self.path,
start.line + 1,
start.col + 1,
&error_message
);
let location = self.trap.emit_location_label(self.label, start, end);
self.trap.emit_diagnostic(
severity,
error_tag,
error_message,
full_error_message,
location,
&message
);
if severity > DiagnosticSeverity::Debug {
let location = self.trap.emit_location_label(self.label, start, end);
self.trap
.emit_diagnostic(severity, tag, message, full_message, location);
}
}
pub fn emit_parse_error(&mut self, owner: &impl ast::AstNode, err: &SyntaxError) {
let owner_range: TextRange = owner.syntax().text_range();

View File

@@ -128,7 +128,7 @@ pub struct TrapFile {
compression: Compression,
}
#[derive(Copy, Clone)]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum DiagnosticSeverity {
Debug = 10,
Info = 20,

View File

@@ -40,8 +40,11 @@ lib/codeql/rust/elements/FieldList.qll bd243adc4696c60f636055a1c2da28039fe202847
lib/codeql/rust/elements/FnPtrType.qll c4a90dc660cf620972dc23b95494f5caf9f050eabd4bdb52fdc061f8797ba9a1 f8defc91582fa503607664668f9e2e6c2cd8b320c7c449610f21e52e332a129f
lib/codeql/rust/elements/ForExpr.qll 312804d53dd9236a2f2a15c9d6ec348b46e139a54eb5893e7e12487725df7444 fa5e20099b1179033bc209bad3548e3d1d4019c7fe0e455cec8ca1a9d48692ab
lib/codeql/rust/elements/ForType.qll 0036bed8749358c356d78c4a0eef40d73e2796284293cde5604ae70ddd6d0470 4edcaf8f7c67d42ebe3ebb1be6a7643758717d4fe88f5f648b6a1c5ff4ee4de7
lib/codeql/rust/elements/Format.qll 506172d176f4b965f428585c032464f4abe07a0e47c574f8e011d8641ec45370 653e81bf233b8729649064de64f4a7a8533f8864ac6d2ea913f347088c924c60
lib/codeql/rust/elements/FormatArgsArg.qll 5bc9b4cd1bac7131165836e93838c45452a08ea6011741cbddace3cbf9c69440 f825140e98dc9800d5c045402186793c7b21511448e2f6bf6402d1e06305219c
lib/codeql/rust/elements/FormatArgsExpr.qll f2ffad5a1105b29a8437c8ed6cf918cfcf4d65ac164bbf1be0585c3b673ca749 3ba20dc312a0a994bb43b37b2db72cbd4e06061b97918fa0e84ce355070ffbeb
lib/codeql/rust/elements/FormatArgument.qll bdd93e1da78637f19beee6f953d3a45512100e925d90cb5ad08a097f412009b8 2a0ae7eb885615e380f925c0d130a1b795bf3c395486550a1f1c9c82848f8d77
lib/codeql/rust/elements/FormatTemplateVariableAccess.qll ff3218a1dda30c232d0ecd9d1c60bbb9f3973456ef0bee1d1a12ad14b1e082b5 e4316291c939800d8b34d477d92be9404a30d52b7eee37302aef3d3205cf4ae0
lib/codeql/rust/elements/Function.qll 2c76c2c7036891996b1f0ebde16c414edf37ebb44ff9c3483088dc6218733e07 d84d017d98aa240bf3bee6502a030aa8cfb7ed95425ffa9853e73b41485e1f4a
lib/codeql/rust/elements/GenericArg.qll 5f11ce0e3c5f08de84db61f56ba1b984652455ba6b95a8b8a5b5a235913d4072 756b6a73d66fde45bdcc65ce2362a5b1391af2927e6d54b6550b3ecd5fd11e75
lib/codeql/rust/elements/GenericArgList.qll dcf274db517b0e8f19e4545d77f86cdd4066ff2805e68c808d0bb5750b49f569 1055a82929e850264e501b367ef4d314a3e6bb8943ec95f4284d157fb4d0092f
@@ -94,7 +97,8 @@ lib/codeql/rust/elements/ParenPat.qll 40d033de6c85ad042223e0da80479adebab3549439
lib/codeql/rust/elements/ParenType.qll e1f5695b143c97b98ccdb460a5cf872461cfc13b83a4f005f26c288dc0afae10 1164f8efae7f255925411bddb33939fab0bf1c07955a16fef173b3f4675d09ae
lib/codeql/rust/elements/Pat.qll 56211c5cb4709e7c12a2bfd2da5e413a451672d99e23a8386c08ad0b999fd45c b1b1893a13a75c4f0390f7e2a14ee98a46f067cfdc991a8d43adc82497d20aff
lib/codeql/rust/elements/Path.qll 0655adfe84b08c286022a0307511a781bc1bfc943c12bc50600ebffb9d00e4b0 48e55afee9d019b7c62bfb02110c626c570ecbf683258cf23786807966f0b6fc
lib/codeql/rust/elements/PathExpr.qll 99aa8af9deb9e276eb262b1fbd1a19f1c816cafac605aedb173ecb245c3c3cbd 306c837388ba60a5a89d2a546453527c62006696e15c043ed04d1ba27345815b
lib/codeql/rust/elements/PathExpr.qll 906df1d80c662b79f1b0b0428c39754b7f8dbcb2234919dd45dd8206a099dd36 1d6015afab6378c926c5838c9a5772cfcfeedf474e2eeca3e46085300ff8d4e1
lib/codeql/rust/elements/PathExprBase.qll bb41092ec690ae926e3233c215dcaf1fd8e161b8a6955151949f492e02dba13a b2257072f8062d31c29c63ee1311b07e0d2eb37075f582cfc76bb542ef773198
lib/codeql/rust/elements/PathPat.qll 6897e69bcb24b56d39ede796cf5767988dcd5741e02333fa8495dd7c814f771a 2a011fb92f17e4b4ff713e6d29f591054dfede22a9aaa006e67fca2c23ab76bf
lib/codeql/rust/elements/PathSegment.qll 536a8fe172db367e5f1dc678a014e2350eadfc379242d2b5451725e826ab1448 1a3a237f56c1d9ccdce6832ec6417fed25cd3e29ba836363cc6085e2125de4c5
lib/codeql/rust/elements/PathType.qll a7bd3b05dc2c0e96c91c5485db508a1f5bb8fe3a01486be6815ae9dabb163add b11e996b6c0cc21a3d8d1ddc23c37e4d54a78e84a9278b3ceca1e94cb7321532
@@ -232,7 +236,6 @@ lib/codeql/rust/elements/internal/ForTypeImpl.qll b515639844778d0fbe51e6161a2ec1
lib/codeql/rust/elements/internal/FormatArgsArgConstructor.qll 8bd9b4e035ef8adeb3ac510dd68043934c0140facb933be1f240096d01cdfa11 74e9d3bbd8882ae59a7e88935d468e0a90a6529a4e2af6a3d83e93944470f0ee
lib/codeql/rust/elements/internal/FormatArgsArgImpl.qll 601f7715e9a65bcfa7cea1979fa30d694b5bea29650d799d7dd3080b8eea58e9 ecb0800cdb8c0f93277982dad295ac6a5332e42eff4fb5c8ff19f903b9857003
lib/codeql/rust/elements/internal/FormatArgsExprConstructor.qll ce29ff5a839b885b1ab7a02d6a381ae474ab1be3e6ee7dcfd7595bdf28e4b558 63bf957426871905a51ea319662a59e38104c197a1024360aca364dc145b11e8
lib/codeql/rust/elements/internal/FormatArgsExprImpl.qll bdb992ebc6be59311b486f40325b39f52a69921cfc66a731085cb184da00050f 6336e7770f9cb700f1b3914fd940c3423ab4e971b34ed8fcc79da80c1f1cdba3
lib/codeql/rust/elements/internal/FunctionConstructor.qll b50aea579938d03745dfbd8b5fa8498f7f83b967369f63d6875510e09ab7f5d2 19cca32aeaecaf9debc27329e8c39ecec69464bb1d89d7b09908a1d73a8d92a2
lib/codeql/rust/elements/internal/GenericArgImpl.qll 6b1b804c357425c223f926e560a688e81506f5a35b95485cecf704e88cc009ee cc1ccf6a23dadc397e82664f3911d4b385d4c8ca80b1ee16d5275d9c936148dd
lib/codeql/rust/elements/internal/GenericArgListConstructor.qll 46859bb3eb09d77987a18642d65ba2e13471a4dc9c0a83a192fddc82e37c335c 2c7d54c876269a88d3461b05745e73b06532b1616cae9b614ac94b28735d8fc4
@@ -325,6 +328,7 @@ lib/codeql/rust/elements/internal/ParenTypeConstructor.qll d62e656a4a3c8ffd4eb87
lib/codeql/rust/elements/internal/ParenTypeImpl.qll 6f7b4fade4ac0af69bf9766ee7d73da3da1742ba8a7c12d2a067b71c7f96d849 f065ea466111a5abca33d97b9878ef2fcc221f286fc65bec87f3a9c2fd5d57fc
lib/codeql/rust/elements/internal/PatImpl.qll 37c9b1da7aa625117644e2cd74ec0b174f69a38cf66926add01786a05d5ad2ad 143685a0b4873fa0b73b204285dca956e59b32d527bfac6cc336326d244994b7
lib/codeql/rust/elements/internal/PathConstructor.qll 5c6354c28faf9f28f3efee8e19bdb82773adcf4b0c1a38788b06af25bcb6bc4a 3e2aeef7b6b9cda7f7f45a6c8119c98803aa644cf6a492cf0fce318eba40fe8f
lib/codeql/rust/elements/internal/PathExprBaseImpl.qll e8b09447ee41b4123f7d94c6b366b2602d8022c9644f1088c670c7794307ab2e 96b9b328771aaf19ba18d0591e85fcc915c0f930b2479b433de3bfdd2ea25249
lib/codeql/rust/elements/internal/PathExprConstructor.qll cf6e0a338a8ed2d1042bdee4c2c49be5827e8c572d8c56e828db265d39e59ae3 36a3d1b7c5cc2cf527616be787b32071b9e2a6613a4f6b3f82e2a3b0e02a516f
lib/codeql/rust/elements/internal/PathExprImpl.qll 01ad25aa940bf949056db86220362f0f5a1b03a772af6a2f6aff8854170c5e49 a0f5ff6b04e2f9f22bda78bb2a7352d890899ba16cb7f6a267af902a3650c5ed
lib/codeql/rust/elements/internal/PathImpl.qll 67ccef5792c0d17d800b910cbda3651aaa5c0ba8daa64e1fea23a1518b562193 6a54b958f7206c43565889a273a64b95aa4b915044a986ffffe7cfb4b8f9c3a9
@@ -493,8 +497,11 @@ lib/codeql/rust/elements/internal/generated/FieldList.qll 43c13c6e3c9ba75a7a4cb8
lib/codeql/rust/elements/internal/generated/FnPtrType.qll 748d766dbefd19a7d644734c57885eeede66897029bbfe1b87919517f43bfde2 5a7d80acc00e56594ed85026a8ea4923104d2e98c2e42db8c5bcd32ddd164e48
lib/codeql/rust/elements/internal/generated/ForExpr.qll 541b62b48911d4999f9ed64ab6c8b9910073ac4add0225761f319677328cf120 976c3a91c9eedfb1e2d9ea76ac501348643b3d23c723d7a777042258d416d091
lib/codeql/rust/elements/internal/generated/ForType.qll 3d43d044a1189281f09c55caafb6c8020a836f49e2866077086101925a573cf2 646b59bfd1b428aaf7211f574c49f79cb4c6a79ca151aa0663b2b31480298721
lib/codeql/rust/elements/internal/generated/Format.qll 37ad20cf2bf363b4027a8913d095292c8a4eb8ccdf2a9965f2fb7d41930f9bfe 329b89cdd75ce951269273dd18897e32ff5cfcc94f451001c64143386c1e48dd
lib/codeql/rust/elements/internal/generated/FormatArgsArg.qll e07a1ae310f590003f1b88fada7dcf4847c99adb9d4c838d1c88e66e1da85c5f 0ef7342451fe2cb06e765fb4b33bb8c4a9b927f5edbc8feb5c6ba3655697f447
lib/codeql/rust/elements/internal/generated/FormatArgsExpr.qll 40d6daa7d2bafb33798a21d79774dc802cfbd7a31618ac3bd0149399ea2bf893 d1172e2151791228559004792e125fc4625f6a26ffad25f29efb0ad263bf8795
lib/codeql/rust/elements/internal/generated/FormatArgument.qll 00646f38217a66978b8b2648cca39dddbed22ece693b26cb682f019fbfedda95 e364e085f967847a7ed21b76156a9203d64032f0f0eea357b4779885a41bf9a7
lib/codeql/rust/elements/internal/generated/FormatTemplateVariableAccess.qll a6175214fad445df9234b3ee9bf5147da75baf82473fb8d384b455e3add0dac1 a928db0ff126b2e54a18f5c488232abd1bd6c5eda24591d3c3bb80c6ee71c770
lib/codeql/rust/elements/internal/generated/Function.qll f285ee0c771f897eba6db34a7e98f3cfb7db91b0df252ff4b37fc9d779de0bfb 07401e832565ff376acda219514c2e2bbe4ae5058c76a73b40ca6ca66f1626c7
lib/codeql/rust/elements/internal/generated/GenericArg.qll 464da0ba1c5ddcd1be68617167f177773d99b5ac4775ec8ea24d503e789a9099 6faa1033d59baf7c210ac4837a55781cfc054b7acbad8027faf4630dbfa6e101
lib/codeql/rust/elements/internal/generated/GenericArgList.qll b8cd936bba6f28344e28c98acf38acb8ef43af6ecf8367d79ed487e5b9da17cb 8b14331261e49d004807285b02fca190aafd62bfb9378b05c7d9c1e95525fe7b
@@ -545,19 +552,20 @@ lib/codeql/rust/elements/internal/generated/ParamList.qll c808c9d84dd7800573832b
lib/codeql/rust/elements/internal/generated/ParenExpr.qll bc0731505bfe88516205ec360582a4222d2681d11342c93e15258590ddee82f2 d4bd6e0c80cf1d63746c88d4bcb3a01d4c75732e5da09e3ebd9437ced227fb60
lib/codeql/rust/elements/internal/generated/ParenPat.qll ce24b8f8ecbf0f204af200317405724063887257460c80cf250c39b2fdf37185 e7c87d37e1a0ca7ea03840017e1aa9ddb7f927f1f3b6396c0305b46aeee33db6
lib/codeql/rust/elements/internal/generated/ParenType.qll 9cc954d73f8330dcac7b475f97748b63af5c8766dee9d2f2872c0a7e4c903537 c07534c8a9c683c4a9b11d490095647e420de0a0bfc23273eaf6f31b00244273
lib/codeql/rust/elements/internal/generated/ParentChild.qll 823b35d9802fab617be5c76327d65a3e52abd4be72bbc36d93e673cea7a9baaf 9d58eb407d0a929aefc0f4d532ef39dded81f6a370b6735ef581709c82ff9bc6
lib/codeql/rust/elements/internal/generated/ParentChild.qll 611eff5fe700323eba2dbee6f9495952059e77c3ec12038c9d45d2cdaa57efd5 f317538e9919e39dfbf3825a96231f8023568f2d4c61d814c4cebaaf8335f94c
lib/codeql/rust/elements/internal/generated/Pat.qll 3605ac062be2f294ee73336e9669027b8b655f4ad55660e1eab35266275154ee 7f9400db2884d336dd1d21df2a8093759c2a110be9bf6482ce8e80ae0fd74ed4
lib/codeql/rust/elements/internal/generated/Path.qll 299abce24762a5ab023f3cf1ab9718b83047e171aed42a8092e7a155914b1657 db1a23d18640c548f08c9f94823838b5e019ac85877c7b15df2d1493d1846572
lib/codeql/rust/elements/internal/generated/PathExpr.qll 17cdb0a7393258a207450f08e37178fc9d35d167f064ba6015be94246f3dc933 a75fdd280aff6d87e083a92030e041c2eb52b57cf7151d4a6989fcd31d6a64bf
lib/codeql/rust/elements/internal/generated/PathExpr.qll 2096e3c1db22ee488a761690adabfc9cfdea501c99f7c5d96c0019cb113fc506 54245ce0449c4e263173213df01e079d5168a758503a5dbd61b25ad35a311140
lib/codeql/rust/elements/internal/generated/PathExprBase.qll d8218e201b8557fa6d9ca2c30b764e5ad9a04a2e4fb695cc7219bbd7636a6ac2 4ef178426d7095a156f4f8c459b4d16f63abc64336cb50a6cf883a5f7ee09113
lib/codeql/rust/elements/internal/generated/PathPat.qll 98c9938d6a359fd717829b196eb09701d2c798e18c1f43fa7b2a9145afdf6c19 caba2e629cae08682baac90a76ae9a48cda2d7d6f9c23d506fa0ff3f292978a4
lib/codeql/rust/elements/internal/generated/PathSegment.qll 4621597fd86246f788b8f9ca73f6b0f27929fc04261ce3ccf85da1183071431d aadda8bce386a3b7a9c53b98465eedcc4f724e37b8a904c1775af5b7ffb041ee
lib/codeql/rust/elements/internal/generated/PathType.qll 45de78e5374d6eb0446e2112ec72d3692c2811df9fa2ad03d0127e426940abe3 622cf70408413a565a0dac58f451035ac1339c8d0ee5b24f630680201cb0aa48
lib/codeql/rust/elements/internal/generated/PrefixExpr.qll c9ede5f2deb7b41bc8240969e8554f645057018fe96e7e9ad9c2924c8b14722b 5ae2e3c3dc8fa73e7026ef6534185afa6b0b5051804435d8b741dd3640c864e1
lib/codeql/rust/elements/internal/generated/PtrType.qll 40099c5a4041314b66932dfd777c9e2bef90a0711fb8d7c2c2cec764c003ac4a cf8297d93557356a572223d3e8acca701837c4b1f54e8d4351ba195fb7ed27f8
lib/codeql/rust/elements/internal/generated/PureSynthConstructors.qll dc03515d678ba052c2ff2dd9f0883e0bce54cac740ba9a15e5173f292c1b6971 dc03515d678ba052c2ff2dd9f0883e0bce54cac740ba9a15e5173f292c1b6971
lib/codeql/rust/elements/internal/generated/PureSynthConstructors.qll ea294a3ba33fd1bc632046c4fedbcb84dcb961a8e4599969d65893b19d90e590 ea294a3ba33fd1bc632046c4fedbcb84dcb961a8e4599969d65893b19d90e590
lib/codeql/rust/elements/internal/generated/RangeExpr.qll 23cca03bf43535f33b22a38894f70d669787be4e4f5b8fe5c8f7b964d30e9027 18624cef6c6b679eeace2a98737e472432e0ead354cca02192b4d45330f047c9
lib/codeql/rust/elements/internal/generated/RangePat.qll efd93730de217cf50dcba5875595263a5eadf9f7e4e1272401342a094d158614 229b251b3d118932e31e78ac4dfb75f48b766f240f20d436062785606d44467b
lib/codeql/rust/elements/internal/generated/Raw.qll 429057964308876b8186a0ca901634273d91b783e4bb85aa5e47860010f4da0b feb8231d0b724fedb1d9d2a65d4a8759ae58baec902b44e3bebdb81a7fbc1fd1
lib/codeql/rust/elements/internal/generated/Raw.qll 6ce0e8a0d2922b2484d48108ffafb1daf6312103e3b8b190774a7a6f12c73ab3 e90268b1865f7e9a671f8bcff3812bf9c0b75baf573a031395747269dfe054c8
lib/codeql/rust/elements/internal/generated/RecordExpr.qll eb6cb662e463f9260efae1a6ce874fa781172063b916ef1963f861e9942d308d 1a21cbccc8f3799ff13281e822818ebfb21d81591720a427cac3625512cb9d40
lib/codeql/rust/elements/internal/generated/RecordExprField.qll 7e9f8663d3b74ebbc9603b10c9912f082febba6bd73d344b100bbd3edf837802 fbe6b578e7fd5d5a6f21bbb8c388957ab7210a6a249ec71510a50fb35b319ea1
lib/codeql/rust/elements/internal/generated/RecordExprFieldList.qll 179a97211fe7aa6265085d4d54115cdbc0e1cd7c9b2135591e8f36d6432f13d3 dd44bbbc1e83a1ed3a587afb729d7debf7aeb7b63245de181726af13090e50c0
@@ -582,8 +590,8 @@ lib/codeql/rust/elements/internal/generated/Static.qll 5fbd6879858cf356d4bdaa6da
lib/codeql/rust/elements/internal/generated/Stmt.qll 8473ff532dd5cc9d7decaddcd174b94d610f6ca0aec8e473cc051dad9f3db917 6ef7d2b5237c2dbdcacbf7d8b39109d4dc100229f2b28b5c9e3e4fbf673ba72b
lib/codeql/rust/elements/internal/generated/StmtList.qll a667193e32341e17400867c6e359878c4e645ef9f5f4d97676afc0283a33a026 a320ed678ee359302e2fc1b70a9476705cd616fcfa44a499d32f0c7715627f73
lib/codeql/rust/elements/internal/generated/Struct.qll 4d57f0db12dc7ad3e31e750a24172ef1505406b4dab16386af0674bd18bf8f4b 1a73c83df926b996f629316f74c61ea775be04532ab61b56af904223354f033e
lib/codeql/rust/elements/internal/generated/Synth.qll dd9d72a46cf446af025cd7b0085f3780ee7bf7d09a458d3ae6f495e999d342c8 cda06e3155f1a3eecc5ee8ec8097d5362234b44f815aff9bc3940860435262b3
lib/codeql/rust/elements/internal/generated/SynthConstructors.qll 5d30b6d4f36791637f250734ee38820102c64f196454e20f79e30097da1a8e20 5d30b6d4f36791637f250734ee38820102c64f196454e20f79e30097da1a8e20
lib/codeql/rust/elements/internal/generated/Synth.qll 68126fecadf402b76a30b6e916b1d1c15db1b06c48a401267bf59ac06aaa5ec3 545f3fa49591cf9a11b9bf6d9c860726db31dffe43be8c96ac3f2cac8d47c010
lib/codeql/rust/elements/internal/generated/SynthConstructors.qll e929c49ea60810a2bbc19ad38110b8bbaf21db54dae90393b21a3459a54abf6f e929c49ea60810a2bbc19ad38110b8bbaf21db54dae90393b21a3459a54abf6f
lib/codeql/rust/elements/internal/generated/Token.qll 77a91a25ca5669703cf3a4353b591cef4d72caa6b0b9db07bb9e005d69c848d1 2fdffc4882ed3a6ca9ac6d1fb5f1ac5a471ca703e2ffdc642885fa558d6e373b
lib/codeql/rust/elements/internal/generated/TokenTree.qll 8577c2b097c1be2f0f7daa5acfcf146f78674a424d99563e08a84dd3e6d91b46 d2f30764e84dbfc0a6a5d3d8a5f935cd432413688cb32da9c94e420fbc10665c
lib/codeql/rust/elements/internal/generated/Trait.qll a570fa93d0b78a35766b00d5ca256c102f824564248b9d8b678a981d6eea3e2e d9c7475e5102e21cfdee3b1791f89a4f9cdba5a4200349ff706532b704c02664
@@ -617,7 +625,7 @@ lib/codeql/rust/elements/internal/generated/WhileExpr.qll fec8a9211b82a80601bf73
lib/codeql/rust/elements/internal/generated/WildcardPat.qll d74b70b57a0a66bfae017a329352a5b27a6b9e73dd5521d627f680e810c6c59e 4b913b548ba27ff3c82fcd32cf996ff329cb57d176d3bebd0fcef394486ea499
lib/codeql/rust/elements/internal/generated/YeetExpr.qll cac328200872a35337b4bcb15c851afb4743f82c080f9738d295571eb01d7392 94af734eea08129b587fed849b643e7572800e8330c0b57d727d41abda47930b
lib/codeql/rust/elements/internal/generated/YieldExpr.qll 37e5f0c1e373a22bbc53d8b7f2c0e1f476e5be5080b8437c5e964f4e83fad79a 4a9a68643401637bf48e5c2b2f74a6bf0ddcb4ff76f6bffb61d436b685621e85
lib/codeql/rust/elements.qll ef8063c90411cb957c776756837a4c7ad43aa4eeb52595786e8b2b96dc10ebff ef8063c90411cb957c776756837a4c7ad43aa4eeb52595786e8b2b96dc10ebff
lib/codeql/rust/elements.qll 6dc44d60d8180da23e7df8815adafa506936c7704723df0592bd1c6c60280abe 6dc44d60d8180da23e7df8815adafa506936c7704723df0592bd1c6c60280abe
test/extractor-tests/generated/Abi/Abi.ql 7f6e7dc4af86eca3ebdc79b10373988cd0871bd78b51997d3cffd969105e5fdd 2f936b6ca005c6157c755121584410c03e4a3949c23bee302fbe05ee10ce118f
test/extractor-tests/generated/Abi/Abi_getAbiString.ql a496762fcec5a0887b87023bbf93e9b650f02e20113e25c44d6e4281ae8f5335 14109c7ce11ba25e3cd6e7f1b3fcb4cb00622f2a4eac91bfe43145c5f366bc52
test/extractor-tests/generated/ArgList/ArgList.ql e412927756e72165d0e7c5c9bd3fca89d08197bbf760db8fb7683c64bb2229bc 043dba8506946fbb87753e22c387987d7eded6ddb963aa067f9e60ef9024d684

10
rust/ql/.gitattributes generated vendored
View File

@@ -42,8 +42,11 @@
/lib/codeql/rust/elements/FnPtrType.qll linguist-generated
/lib/codeql/rust/elements/ForExpr.qll linguist-generated
/lib/codeql/rust/elements/ForType.qll linguist-generated
/lib/codeql/rust/elements/Format.qll linguist-generated
/lib/codeql/rust/elements/FormatArgsArg.qll linguist-generated
/lib/codeql/rust/elements/FormatArgsExpr.qll linguist-generated
/lib/codeql/rust/elements/FormatArgument.qll linguist-generated
/lib/codeql/rust/elements/FormatTemplateVariableAccess.qll linguist-generated
/lib/codeql/rust/elements/Function.qll linguist-generated
/lib/codeql/rust/elements/GenericArg.qll linguist-generated
/lib/codeql/rust/elements/GenericArgList.qll linguist-generated
@@ -97,6 +100,7 @@
/lib/codeql/rust/elements/Pat.qll linguist-generated
/lib/codeql/rust/elements/Path.qll linguist-generated
/lib/codeql/rust/elements/PathExpr.qll linguist-generated
/lib/codeql/rust/elements/PathExprBase.qll linguist-generated
/lib/codeql/rust/elements/PathPat.qll linguist-generated
/lib/codeql/rust/elements/PathSegment.qll linguist-generated
/lib/codeql/rust/elements/PathType.qll linguist-generated
@@ -234,7 +238,6 @@
/lib/codeql/rust/elements/internal/FormatArgsArgConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/FormatArgsArgImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/FormatArgsExprConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/FormatArgsExprImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/FunctionConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/GenericArgImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/GenericArgListConstructor.qll linguist-generated
@@ -327,6 +330,7 @@
/lib/codeql/rust/elements/internal/ParenTypeImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/PatImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/PathConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/PathExprBaseImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/PathExprConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/PathExprImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/PathImpl.qll linguist-generated
@@ -495,8 +499,11 @@
/lib/codeql/rust/elements/internal/generated/FnPtrType.qll linguist-generated
/lib/codeql/rust/elements/internal/generated/ForExpr.qll linguist-generated
/lib/codeql/rust/elements/internal/generated/ForType.qll linguist-generated
/lib/codeql/rust/elements/internal/generated/Format.qll linguist-generated
/lib/codeql/rust/elements/internal/generated/FormatArgsArg.qll linguist-generated
/lib/codeql/rust/elements/internal/generated/FormatArgsExpr.qll linguist-generated
/lib/codeql/rust/elements/internal/generated/FormatArgument.qll linguist-generated
/lib/codeql/rust/elements/internal/generated/FormatTemplateVariableAccess.qll linguist-generated
/lib/codeql/rust/elements/internal/generated/Function.qll linguist-generated
/lib/codeql/rust/elements/internal/generated/GenericArg.qll linguist-generated
/lib/codeql/rust/elements/internal/generated/GenericArgList.qll linguist-generated
@@ -551,6 +558,7 @@
/lib/codeql/rust/elements/internal/generated/Pat.qll linguist-generated
/lib/codeql/rust/elements/internal/generated/Path.qll linguist-generated
/lib/codeql/rust/elements/internal/generated/PathExpr.qll linguist-generated
/lib/codeql/rust/elements/internal/generated/PathExprBase.qll linguist-generated
/lib/codeql/rust/elements/internal/generated/PathPat.qll linguist-generated
/lib/codeql/rust/elements/internal/generated/PathSegment.qll linguist-generated
/lib/codeql/rust/elements/internal/generated/PathType.qll linguist-generated

View File

@@ -0,0 +1,5 @@
fn foo() {
wat
is
this?
}

View File

@@ -0,0 +1,5 @@
import rust
from Function f
where exists(f.getLocation().getFile().getRelativePath())
select f

View File

@@ -0,0 +1 @@
qltest_cargo_check: true

View File

@@ -0,0 +1 @@
| test.rs:1:1:1:11 | foo |

View File

@@ -0,0 +1,5 @@
import rust
from Function f
where exists(f.getLocation().getFile().getRelativePath())
select f

View File

@@ -0,0 +1 @@
fn foo() {}

View File

@@ -0,0 +1,2 @@
| main.rs:1:1:1:12 | main |
| test.rs:1:1:1:11 | foo |

View File

@@ -0,0 +1,5 @@
import rust
from Function f
where exists(f.getLocation().getFile().getRelativePath())
select f

View File

@@ -0,0 +1 @@
fn main() {}

View File

@@ -0,0 +1 @@
fn foo() {}

View File

@@ -0,0 +1,5 @@
dependencies:
codeql/rust-queries: '*'
codeql/rust-all: '*'
extractor: rust
warnOnImplicitThis: true

View File

@@ -0,0 +1,17 @@
import runs_on
# these tests are meant to exercise QL test running on multiple platforms
# therefore they don't rely on integration test built-in QL test running
# (which skips `qltest.{sh,cmd}`)
def test_lib(codeql, rust, cwd):
codeql.test.run("lib", threads=1)
def test_main(codeql, rust):
codeql.test.run("main", threads=1)
def test_failing_cargo_check(codeql, rust):
out = codeql.test.run("failing_cargo_check", threads=1, show_extractor_output=True,
_assert_failure=True, _capture="stderr")
# TODO: QL test output redirection is currently broken on windows, leaving it up for follow-up work
if not runs_on.windows:
assert "requested cargo check failed" in out

View File

@@ -1,68 +1,8 @@
/** Provides classes for working with locations. */
import files.FileSystem
private import codeql.rust.elements.internal.LocationImpl
/**
* A location as given by a file, a start line, a start column,
* an end line, and an end column.
*
* For more information about locations see [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
class Location extends @location_default {
/** Gets the file for this location. */
File getFile() { locations_default(this, result, _, _, _, _) }
final class Location = LocationImpl::Location;
/** Gets the 1-based line number (inclusive) where this location starts. */
int getStartLine() { locations_default(this, _, result, _, _, _) }
/** Gets the 1-based column number (inclusive) where this location starts. */
int getStartColumn() { locations_default(this, _, _, result, _, _) }
/** Gets the 1-based line number (inclusive) where this location ends. */
int getEndLine() { locations_default(this, _, _, _, result, _) }
/** Gets the 1-based column number (inclusive) where this location ends. */
int getEndColumn() { locations_default(this, _, _, _, _, result) }
/** Gets the number of lines covered by this location. */
int getNumLines() { result = this.getEndLine() - this.getStartLine() + 1 }
/** Gets a textual representation of this element. */
bindingset[this]
pragma[inline_late]
string toString() {
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
this.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
result = filepath + "@" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn
)
}
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Providing locations in CodeQL queries](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
exists(File f |
locations_default(this, f, startline, startcolumn, endline, endcolumn) and
filepath = f.getAbsolutePath()
)
}
/** Holds if this location starts strictly before the specified location. */
pragma[inline]
predicate strictlyBefore(Location other) {
this.getStartLine() < other.getStartLine()
or
this.getStartLine() = other.getStartLine() and this.getStartColumn() < other.getStartColumn()
}
}
/** An entity representing an empty location. */
class EmptyLocation extends Location {
EmptyLocation() { empty_location(this) }
}
final class EmptyLocation = LocationImpl::EmptyLocation;

View File

@@ -20,7 +20,9 @@ query predicate multipleToStrings(Element e, string s) {
*/
query predicate multipleLocations(Locatable e) { strictcount(e.getLocation()) > 1 }
private predicate multiplePrimaryQlClasses(Element e) { strictcount(e.getAPrimaryQlClass()) > 1 }
private predicate multiplePrimaryQlClasses(Element e) {
strictcount(string cls | cls = e.getAPrimaryQlClass() and cls != "VariableAccess") > 1
}
/**
* Holds if `e` has more than one `getPrimaryQlClasses()` result.

View File

@@ -1,6 +1,7 @@
/** Provides classes relating to extraction diagnostics. */
private import codeql.Locations
private import codeql.rust.elements.internal.LocationImpl
/** A diagnostic emitted during extraction, such as a parse error */
class Diagnostic extends @diagnostic {
@@ -10,7 +11,12 @@ class Diagnostic extends @diagnostic {
string fullMessage;
Location location;
Diagnostic() { diagnostics(this, severity, tag, message, fullMessage, location) }
Diagnostic() {
exists(@location_default loc |
diagnostics(this, severity, tag, message, fullMessage, loc) and
location = LocationImpl::TLocationDefault(loc)
)
}
/**
* Gets the numerical severity level associated with this diagnostic.

View File

@@ -5,6 +5,7 @@ private import Scope as Scope
private import codeql.rust.controlflow.ControlFlowGraph as Cfg
private module CfgInput implements InputSig<Location> {
private import codeql.rust.internal.CachedStages
private import rust as Rust
private import Completion as C
@@ -21,7 +22,10 @@ private module CfgInput implements InputSig<Location> {
/** An AST node with an associated control-flow graph. */
class CfgScope = Scope::CfgScope;
CfgScope getCfgScope(AstNode n) { result = n.getEnclosingCallable() }
CfgScope getCfgScope(AstNode n) {
result = n.getEnclosingCallable() and
Stages::CfgStage::ref()
}
class SuccessorType = Cfg::SuccessorType;
@@ -89,6 +93,31 @@ class ParamTree extends StandardPostOrderTree, Param {
override AstNode getChildNode(int i) { i = 0 and result = this.getPat() }
}
class FormatArgsExprTree extends StandardPostOrderTree, FormatArgsExpr {
override AstNode getChildNode(int i) {
i = -1 and result = this.getTemplate()
or
result = this.getArg(i).getExpr()
or
result =
any(FormatTemplateVariableAccess v, Format f, int index, int kind |
f = this.getFormat(index) and
(
v.getArgument() = f.getArgumentRef() and kind = 0
or
v.getArgument() = f.getWidthArgument() and kind = 1
or
v.getArgument() = f.getPrecisionArgument() and kind = 2
) and
i = this.getNumberOfArgs() + index * 3 + kind
|
v
)
}
}
class FormatTemplateVariableAccessTree extends LeafTree, FormatTemplateVariableAccess { }
class ItemTree extends LeafTree, Item {
ItemTree() {
not this instanceof MacroCall and

View File

@@ -4,8 +4,10 @@ private import Scope
cached
private module Cached {
private import codeql.rust.internal.CachedStages
cached
newtype TSplitKind = TConditionalCompletionSplitKind()
newtype TSplitKind = TConditionalCompletionSplitKind() { Stages::CfgStage::ref() }
cached
newtype TSplit = TConditionalCompletionSplit(ConditionalCompletion c)

View File

@@ -1,10 +1,11 @@
private import rust
private import codeql.util.Boolean
private import Completion
private import codeql.rust.internal.CachedStages
cached
newtype TSuccessorType =
TSuccessorSuccessor() or
TNormalSuccessor() { Stages::CfgStage::ref() } or
TBooleanSuccessor(Boolean b) or
TMatchSuccessor(Boolean b) or
TBreakSuccessor() or
@@ -18,7 +19,7 @@ abstract class SuccessorTypeImpl extends TSuccessorType {
}
/** A normal control flow successor. */
class NormalSuccessorImpl extends SuccessorTypeImpl, TSuccessorSuccessor {
class NormalSuccessorImpl extends SuccessorTypeImpl, TNormalSuccessor {
override string toString() { result = "successor" }
}

View File

@@ -45,8 +45,11 @@ import codeql.rust.elements.FieldList
import codeql.rust.elements.FnPtrType
import codeql.rust.elements.ForExpr
import codeql.rust.elements.ForType
import codeql.rust.elements.Format
import codeql.rust.elements.FormatArgsArg
import codeql.rust.elements.FormatArgsExpr
import codeql.rust.elements.FormatArgument
import codeql.rust.elements.FormatTemplateVariableAccess
import codeql.rust.elements.Function
import codeql.rust.elements.GenericArg
import codeql.rust.elements.GenericArgList
@@ -100,6 +103,7 @@ import codeql.rust.elements.ParenType
import codeql.rust.elements.Pat
import codeql.rust.elements.Path
import codeql.rust.elements.PathExpr
import codeql.rust.elements.PathExprBase
import codeql.rust.elements.PathPat
import codeql.rust.elements.PathSegment
import codeql.rust.elements.PathType

View File

@@ -0,0 +1,16 @@
// generated by codegen, do not edit
/**
* This module provides the public class `Format`.
*/
private import internal.FormatImpl
import codeql.rust.elements.FormatArgsExpr
import codeql.rust.elements.Locatable
/**
* A format element in a formatting template. For example the `{}` in:
* ```rust
* println!("Hello {}", "world");
* ```
*/
final class Format = Impl::Format;

View File

@@ -0,0 +1,20 @@
// generated by codegen, do not edit
/**
* This module provides the public class `FormatArgument`.
*/
private import internal.FormatArgumentImpl
import codeql.rust.elements.Format
import codeql.rust.elements.Locatable
/**
* An argument in a format element in a formatting template. For example the `width`, `precision`, and `value` in:
* ```rust
* println!("Value {value:#width$.precision$}");
* ```
* or the `0`, `1` and `2` in:
* ```rust
* println!("Value {0:#1$.2$}", value, width, precision);
* ```
*/
final class FormatArgument = Impl::FormatArgument;

View File

@@ -0,0 +1,9 @@
// generated by codegen, do not edit
/**
* This module provides the public class `FormatTemplateVariableAccess`.
*/
private import internal.FormatTemplateVariableAccessImpl
import codeql.rust.elements.PathExprBase
final class FormatTemplateVariableAccess = Impl::FormatTemplateVariableAccess;

View File

@@ -0,0 +1,7 @@
/**
* This module provides the public class `NamedFormatArgument`.
*/
private import internal.FormatArgumentImpl
final class NamedFormatArgument = Impl::NamedFormatArgument;

View File

@@ -5,8 +5,8 @@
private import internal.PathExprImpl
import codeql.rust.elements.Attr
import codeql.rust.elements.Expr
import codeql.rust.elements.Path
import codeql.rust.elements.PathExprBase
/**
* A path expression. For example:

View File

@@ -0,0 +1,12 @@
// generated by codegen, do not edit
/**
* This module provides the public class `PathExprBase`.
*/
private import internal.PathExprBaseImpl
import codeql.rust.elements.Expr
/**
* A path expression or a variable access in a formatting template. See `PathExpr` and `FormatTemplateVariableAccess` for further details.
*/
final class PathExprBase = Impl::PathExprBase;

View File

@@ -0,0 +1,7 @@
/**
* This module provides the public class `PositionalFormatArgument`.
*/
private import internal.FormatArgumentImpl
final class PositionalFormatArgument = Impl::PositionalFormatArgument;

View File

@@ -1,4 +1,3 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module provides a hand-modifiable wrapper around the generated class `FormatArgsExpr`.
*
@@ -6,17 +5,27 @@
*/
private import codeql.rust.elements.internal.generated.FormatArgsExpr
private import codeql.rust.elements.Format
/**
* INTERNAL: This module contains the customizable definition of `FormatArgsExpr` and should not
* be referenced directly.
*/
module Impl {
// the following QLdoc is generated: if you need to edit it, do it in the schema file
/**
* A FormatArgsExpr. For example:
* ```rust
* todo!()
* ```
*/
class FormatArgsExpr extends Generated::FormatArgsExpr { }
class FormatArgsExpr extends Generated::FormatArgsExpr {
/**
* Gets the `index`th format of this `FormatArgsExpr`'s formatting template (0-based).
*/
Format getFormat(int index) {
result =
rank[index + 1](Format f, int i | f.getParent() = this and f.getIndex() = i | f order by i)
}
}
}

View File

@@ -0,0 +1,33 @@
/**
* This module defines the hook used internally to tweak the characteristic predicate of
* `FormatArgument` synthesized instances.
* INTERNAL: Do not use.
*/
private import codeql.rust.elements.internal.generated.Raw
private import codeql.rust.elements.internal.generated.Synth
private import codeql.rust.elements.internal.FormatConstructor
/**
* The characteristic predicate of `FormatArgument` synthesized instances.
* INTERNAL: Do not use.
*/
predicate constructFormatArgument(
Raw::FormatArgsExpr parent, int index, int kind, string value, boolean positional, int offset
) {
exists(string text, int formatOffset, int group |
group = [3, 4] and offset = formatOffset + 1 and kind = 0
or
group = [15, 16] and
offset = formatOffset + min(text.indexOf(value + "$")) and
kind = 1
or
group = [23, 24] and
offset = formatOffset + max(text.indexOf(value + "$")) and
kind = 2
|
text = formatElement(parent, index, formatOffset) and
value = text.regexpCapture(formatRegex(), group) and
if group % 2 = 1 then positional = true else positional = false
)
}

View File

@@ -0,0 +1,87 @@
/**
* This module provides a hand-modifiable wrapper around the generated class `FormatArgument`.
*
* INTERNAL: Do not use.
*/
private import codeql.rust.elements.internal.generated.FormatArgument
private import codeql.rust.elements.internal.generated.Raw
private import codeql.rust.elements.internal.generated.Synth
private import codeql.rust.elements.internal.FormatArgumentConstructor
private import codeql.rust.elements.internal.LocatableImpl::Impl as LocatableImpl
private import codeql.files.FileSystem
/**
* INTERNAL: This module contains the customizable definition of `FormatArgument` and should not
* be referenced directly.
*/
module Impl {
// the following QLdoc is generated: if you need to edit it, do it in the schema file
/**
* An argument in a format element in a formatting template. For example the `width`, `precision`, and `value` in:
* ```rust
* println!("Value {value:#width$.precision$}");
* ```
* or the `0`, `1` and `2` in:
* ```rust
* println!("Value {0:#1$.2$}", value, width, precision);
* ```
*/
class FormatArgument extends Generated::FormatArgument {
Raw::FormatArgsExpr parent;
int index;
int kind;
string name;
int offset;
FormatArgument() { this = Synth::TFormatArgument(parent, index, kind, name, _, offset) }
override string toString() { result = name }
override Format getParent() { result = Synth::TFormat(parent, index, _, _) }
}
private class FormatSynthLocationImpl extends FormatArgument, LocatableImpl::SynthLocatable {
override predicate hasSynthLocationInfo(
File file, int startline, int startcolumn, int endline, int endcolumn
) {
// TODO: handle locations in multi-line comments
// TODO: handle the case where the template is from a nested macro call
Synth::convertFormatArgsExprFromRaw(parent)
.(FormatArgsExpr)
.getTemplate()
.getLocation()
.hasLocationInfo(file.getAbsolutePath(), startline, startcolumn - offset, _, _) and
endline = startline and
endcolumn = startcolumn + name.length() - 1
}
}
/**
* A positional `FormatArgument`. For example `0` in
* ```rust
* let name = "Alice";
* println!("{0} in wonderland", name);
* ```
*/
class PositionalFormatArgument extends FormatArgument {
PositionalFormatArgument() { this = Synth::TFormatArgument(_, _, _, _, true, _) }
/** Gets the index of this positional argument */
int getIndex() { result = name.toInt() }
}
/**
* A named `FormatArgument`. For example `name` in
* ```rust
* let name = "Alice";
* println!("{name} in wonderland");
* ```
*/
class NamedFormatArgument extends FormatArgument {
NamedFormatArgument() { this = Synth::TFormatArgument(_, _, _, _, false, _) }
/** Gets the name of this named argument */
string getName() { result = name }
}
}

View File

@@ -0,0 +1,84 @@
/**
* This module defines the hook used internally to tweak the characteristic predicate of
* `Format` synthesized instances.
* INTERNAL: Do not use.
*/
private import codeql.rust.elements.internal.generated.Raw
/**
* The characteristic predicate of `Format` synthesized instances.
* INTERNAL: Do not use.
*
* Match an element of a format string, either text (`Hello`) or a format placeholder (`{}`).
*/
predicate constructFormat(Raw::FormatArgsExpr parent, int index, string text, int offset) {
text = formatElement(parent, index, offset) and
text.charAt(0) = "{" and
text.charAt(1) != "{"
}
/**
* Match an element of a format string, either text (`Hello`) or a format placeholder (`{}`).
*/
string formatElement(Raw::FormatArgsExpr parent, int occurrenceIndex, int occurrenceOffset) {
result =
parent
.getTemplate()
.(Raw::LiteralExpr)
.getTextValue()
// TODO: should also handle surrounding quotes and escaped characters
.regexpFind(textRegex() + "|" + formatRegex(), occurrenceIndex, occurrenceOffset)
}
/**
* A regular expression for matching format elements in a formatting template. The syntax of
* formatting templates is defined at https://doc.rust-lang.org/stable/std/fmt/#syntax . The
* regular expression is generated from the following python code:
*
*
* ```python
* identifier = "([A-Za-z_][A-Za-z0-9_]*)"
* integer = "([0-9]+)"
*
* # argument := integer | identifier
* argument = "({integer}|{identifier})".format(integer=integer, identifier=identifier)
*
* # parameter := argument '$'
* parameter = "(({argument})\\$)".format(argument=argument)
*
* # count := parameter | integer
* count = "({parameter}|{integer})".format(integer=integer, parameter=parameter)
*
* # fill := character
* fill = "(.)"
*
* # align := '<' | '^' | '>'
* align = "([<^>])"
*
* # sign := '+' | '-'
* sign = "([+-])"
*
* # width := count
* width = count
*
* # precision := count | '*'
* precision = "({count}|(\\*))".format(count=count)
*
* # type := '' | '?' | 'x?' | 'X?' | identifier
* type = "(|\\?|x\\?|X\\?|{identifier})".format(identifier=identifier)
*
* # format_spec := [[fill]align][sign]['#']['0'][width]['.' precision]type
* format_spec = "({fill}?{align})?{sign}?(#)?(0)?{width}?(\\.{precision})?{type}".format(fill=fill, align=align, sign=sign, width=width, precision=precision, type=type)
*
* # format := '{' [ argument ] [ ':' format_spec ] [ ws ] * '}'
* format = "(\\{{{argument}?(:{format_spec})?\s*}\\})".format(argument=argument, format_spec=format_spec)
*
* ```
*/
string formatRegex() {
result =
"(\\{(([0-9]+)|([A-Za-z_][A-Za-z0-9_]*))?(:((.)?([<^>]))?([+-])?(#)?(0)?(((([0-9]+)|([A-Za-z_][A-Za-z0-9_]*))\\$)|([0-9]+))?(\\.((((([0-9]+)|([A-Za-z_][A-Za-z0-9_]*))\\$)|([0-9]+))|(\\*)))?(|\\?|x\\?|X\\?|([A-Za-z_][A-Za-z0-9_]*)))?\\s*\\})"
}
private string textRegex() { result = "([^{}]|\\{\\{|\\}\\})+" }

View File

@@ -0,0 +1,90 @@
/**
* This module provides a hand-modifiable wrapper around the generated class `Format`.
*
* INTERNAL: Do not use.
*/
private import codeql.rust.elements.internal.generated.Format
private import codeql.rust.elements.internal.generated.Raw
private import codeql.rust.elements.internal.generated.Synth
private import codeql.rust.elements.internal.FormatConstructor
private import codeql.rust.elements.internal.LocatableImpl::Impl as LocatableImpl
private import codeql.files.FileSystem
import codeql.rust.elements.FormatArgument
/**
* INTERNAL: This module contains the customizable definition of `Format` and should not
* be referenced directly.
*/
module Impl {
// the following QLdoc is generated: if you need to edit it, do it in the schema file
/**
* A format element in a formatting template. For example the `{}` in:
* ```rust
* println!("Hello {}", "world");
* ```
*/
class Format extends Generated::Format {
private Raw::FormatArgsExpr parent;
string text;
private int index;
int offset;
Format() { this = Synth::TFormat(parent, index, text, offset) }
override string toString() { result = text }
override FormatArgsExpr getParent() { result = Synth::convertFormatArgsExprFromRaw(parent) }
override int getIndex() { result = index }
/**
* Gets the name or position reference of this format, if any. For example `name` and `0` in:
* ```rust
* let name = "Alice";
* println!("{name} in wonderland");
* println!("{0} in wonderland", name);
* ```
*/
FormatArgument getArgumentRef() {
result.getParent() = this and result = Synth::TFormatArgument(_, _, 0, _, _, _)
}
/**
* Gets the name or position reference of the width parameter in this format, if any. For example `width` and `1` in:
* ```rust
* let width = 6;
* println!("{:width$}", PI);
* println!("{:1$}", PI, width);
* ```
*/
FormatArgument getWidthArgument() {
result.getParent() = this and result = Synth::TFormatArgument(_, _, 1, _, _, _)
}
/**
* Gets the name or position reference of the width parameter in this format, if any. For example `prec` and `1` in:
* ```rust
* let prec = 6;
* println!("{:.prec$}", PI);
* println!("{:.1$}", PI, prec);
* ```
*/
FormatArgument getPrecisionArgument() {
result.getParent() = this and result = Synth::TFormatArgument(_, _, 2, _, _, _)
}
}
private class FormatSynthLocationImpl extends Format, LocatableImpl::SynthLocatable {
override predicate hasSynthLocationInfo(
File file, int startline, int startcolumn, int endline, int endcolumn
) {
this.getParent()
.getTemplate()
.getLocation()
.hasLocationInfo(file.getAbsolutePath(), startline, startcolumn - offset, _, _) and
endline = startline and
endcolumn = startcolumn + text.length() - 1
}
}
}

View File

@@ -0,0 +1,39 @@
/**
* This module defines the hook used internally to tweak the characteristic predicate of
* `FormatTemplateVariableAccess` synthesized instances.
* INTERNAL: Do not use.
*/
private import codeql.rust.elements.internal.generated.Raw
private import codeql.rust.elements.internal.generated.Synth
private import codeql.rust.elements.Format
private import codeql.rust.elements.NamedFormatArgument
/**
* The characteristic predicate of `FormatTemplateVariableAccess` synthesized instances.
* INTERNAL: Do not use.
*/
predicate constructFormatTemplateVariableAccess(Raw::FormatArgsExpr parent, int index, int kind) {
unboundNamedFormatArgument(parent, index, kind, _)
}
/**
* A named format argument for which no binding is found in the parent `FormatArgsExpr::getArg(_)`.
* INTERNAL: Do not use.
*/
predicate unboundNamedFormatArgument(
Raw::FormatArgsExpr parent, int index, int kind, NamedFormatArgument arg
) {
exists(Format format, string name |
not parent.getArg(_).getName().getText() = name and
name = arg.getName() and
Synth::convertFormatArgsExprToRaw(format.getParent()) = parent and
format.getIndex() = index
|
arg = format.getArgumentRef() and kind = 0
or
arg = format.getWidthArgument() and kind = 1
or
arg = format.getPrecisionArgument() and kind = 2
)
}

View File

@@ -0,0 +1,40 @@
/**
* This module provides a hand-modifiable wrapper around the generated class `FormatTemplateVariableAccess`.
*
* INTERNAL: Do not use.
*/
private import codeql.rust.elements.internal.generated.FormatTemplateVariableAccess
private import codeql.rust.elements.internal.FormatTemplateVariableAccessConstructor
private import codeql.rust.elements.internal.generated.Raw
private import codeql.rust.elements.internal.generated.Synth
private import codeql.rust.elements.Format
private import codeql.rust.elements.NamedFormatArgument
private import codeql.Locations
/**
* INTERNAL: This module contains the customizable definition of `FormatTemplateVariableAccess` and should not
* be referenced directly.
*/
module Impl {
class FormatTemplateVariableAccess extends Generated::FormatTemplateVariableAccess {
private NamedFormatArgument argument;
FormatTemplateVariableAccess() {
exists(Raw::FormatArgsExpr parent, int index, int kind |
this = Synth::TFormatTemplateVariableAccess(parent, index, kind) and
unboundNamedFormatArgument(parent, index, kind, argument)
)
}
override Location getLocation() { result = argument.getLocation() }
override string toString() { result = this.getName() }
/** Gets the name of the variable */
string getName() { result = argument.getName() }
/** Gets the underlying `NamedFormatArgument` . */
NamedFormatArgument getArgument() { result = argument }
}
}

View File

@@ -5,6 +5,7 @@
*/
import codeql.Locations
private import codeql.rust.elements.internal.LocationImpl
private import codeql.rust.elements.internal.generated.Locatable
private import codeql.rust.elements.internal.generated.Synth
private import codeql.rust.elements.internal.generated.Raw
@@ -14,17 +15,32 @@ private import codeql.rust.elements.internal.generated.Raw
* be referenced directly.
*/
module Impl {
abstract class SynthLocatable extends Locatable {
abstract predicate hasSynthLocationInfo(
File file, int startline, int startcolumn, int endline, int endcolumn
);
final override Location getLocation() {
not locatable_locations(Synth::convertLocatableToRaw(this), _) and
exists(File file, int beginLine, int beginColumn, int endLine, int endColumn |
this.hasSynthLocationInfo(file, beginLine, beginColumn, endLine, endColumn)
|
result = LocationImpl::TLocationSynth(file, beginLine, beginColumn, endLine, endColumn)
or
exists(@location_default location |
result = LocationImpl::TLocationDefault(location) and
locations_default(location, file, beginLine, beginColumn, endLine, endColumn)
)
)
}
}
class Locatable extends Generated::Locatable {
pragma[nomagic]
final Location getLocation() {
exists(Raw::Locatable raw |
raw = Synth::convertLocatableToRaw(this) and
(
locatable_locations(raw, result)
or
not exists(Location loc | locatable_locations(raw, loc)) and
result instanceof EmptyLocation
)
Location getLocation() {
exists(@location_default location |
result = LocationImpl::TLocationDefault(location) and
locatable_locations(Synth::convertLocatableToRaw(this), location)
)
}

View File

@@ -0,0 +1,100 @@
private import codeql.files.FileSystem
private import codeql.rust.elements.internal.LocatableImpl::Impl as LocatableImpl
private import codeql.rust.elements.Locatable
private import codeql.rust.elements.Format
private import codeql.rust.elements.FormatArgument
module LocationImpl {
newtype TLocation =
TLocationDefault(@location_default location) or
TLocationSynth(File file, int beginLine, int beginColumn, int endLine, int endColumn) {
not locations_default(_, file, beginLine, beginColumn, endLine, endColumn) and
any(LocatableImpl::SynthLocatable l)
.hasSynthLocationInfo(file, beginLine, beginColumn, endLine, endColumn)
}
/**
* A location as given by a file, a start line, a start column,
* an end line, and an end column.
*
* For more information about locations see [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
abstract class Location extends TLocation {
/** Gets the file for this location. */
File getFile() { this.hasLocationInfo(result.getAbsolutePath(), _, _, _, _) }
/** Gets the 1-based line number (inclusive) where this location starts. */
int getStartLine() { this.hasLocationInfo(_, result, _, _, _) }
/** Gets the 1-based column number (inclusive) where this location starts. */
int getStartColumn() { this.hasLocationInfo(_, _, result, _, _) }
/** Gets the 1-based line number (inclusive) where this location ends. */
int getEndLine() { this.hasLocationInfo(_, _, _, result, _) }
/** Gets the 1-based column number (inclusive) where this location ends. */
int getEndColumn() { this.hasLocationInfo(_, _, _, _, result) }
/** Gets the number of lines covered by this location. */
int getNumLines() { result = this.getEndLine() - this.getStartLine() + 1 }
/** Gets a textual representation of this element. */
bindingset[this]
pragma[inline_late]
string toString() {
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
this.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
result = filepath + "@" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn
)
}
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Providing locations in CodeQL queries](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
abstract predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
);
/** Holds if this location starts strictly before the specified location. */
pragma[inline]
predicate strictlyBefore(Location other) {
this.getStartLine() < other.getStartLine()
or
this.getStartLine() = other.getStartLine() and this.getStartColumn() < other.getStartColumn()
}
}
private class LocationDefault extends Location, TLocationDefault {
@location_default self;
LocationDefault() { this = TLocationDefault(self) }
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
exists(File f |
locations_default(self, f, startline, startcolumn, endline, endcolumn) and
filepath = f.getAbsolutePath()
)
}
}
/** An entity representing an empty location. */
class EmptyLocation extends LocationDefault {
EmptyLocation() { empty_location(self) }
}
private class LocationSynth extends Location, TLocationSynth {
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this =
TLocationSynth(any(File f | f.getAbsolutePath() = filepath), startline, startcolumn,
endline, endcolumn)
}
}
}

View File

@@ -0,0 +1,19 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module provides a hand-modifiable wrapper around the generated class `PathExprBase`.
*
* INTERNAL: Do not use.
*/
private import codeql.rust.elements.internal.generated.PathExprBase
/**
* INTERNAL: This module contains the customizable definition of `PathExprBase` and should not
* be referenced directly.
*/
module Impl {
/**
* A path expression or a variable access in a formatting template. See `PathExpr` and `FormatTemplateVariableAccess` for further details.
*/
class PathExprBase extends Generated::PathExprBase { }
}

View File

@@ -1,6 +1,7 @@
private import rust
private import codeql.rust.elements.internal.generated.ParentChild
private import codeql.rust.elements.internal.PathExprImpl::Impl as PathExprImpl
private import codeql.rust.elements.internal.PathExprBaseImpl::Impl as PathExprBaseImpl
private import codeql.rust.elements.internal.FormatTemplateVariableAccessImpl::Impl as FormatTemplateVariableAccessImpl
private import codeql.util.DenseRank
module Impl {
@@ -83,7 +84,10 @@ module Impl {
// an enum constant (e.g. `None`). This excludes static and constant variables (UPPERCASE),
// which we don't appear to recognize yet anyway. This also assumes programmers follow the
// naming guidelines, which they generally do, but they're not enforced.
not name.charAt(0).isUppercase()
not name.charAt(0).isUppercase() and
// exclude parameters from functions without a body as these are trait method declarations
// without implementations
not exists(Function f | not f.hasBody() and f.getParamList().getAParam().getPat() = p)
}
/** A variable. */
@@ -138,12 +142,12 @@ module Impl {
}
/** A path expression that may access a local variable. */
private class VariableAccessCand extends PathExpr {
private class VariableAccessCand extends PathExprBase {
string name_;
VariableAccessCand() {
exists(Path p, PathSegment ps |
p = this.getPath() and
p = this.(PathExpr).getPath() and
not p.hasQualifier() and
ps = p.getPart() and
not ps.hasGenericArgList() and
@@ -152,8 +156,12 @@ module Impl {
not ps.hasReturnTypeSyntax() and
name_ = ps.getNameRef().getText()
)
or
this.(FormatTemplateVariableAccess).getName() = name_
}
string toString() { result = name_ }
string getName() { result = name_ }
}
@@ -164,7 +172,10 @@ module Impl {
n instanceof LetStmt or
n instanceof VariableScope
) and
exists(AstNode n0 | result = getImmediateParent(n0) |
exists(AstNode n0 |
result = getImmediateParent(n0) or
result = n0.(FormatTemplateVariableAccess).getArgument().getParent().getParent()
|
n0 = n
or
n0 = getAnAncestorInVariableScope(n) and
@@ -422,7 +433,7 @@ module Impl {
}
/** A variable access. */
class VariableAccess extends PathExprImpl::PathExpr instanceof VariableAccessCand {
class VariableAccess extends PathExprBaseImpl::PathExprBase instanceof VariableAccessCand {
private string name;
private Variable v;

View File

@@ -0,0 +1,38 @@
// generated by codegen, do not edit
/**
* This module provides the generated definition of `Format`.
* INTERNAL: Do not import directly.
*/
private import codeql.rust.elements.internal.generated.Synth
private import codeql.rust.elements.internal.generated.Raw
import codeql.rust.elements.FormatArgsExpr
import codeql.rust.elements.internal.LocatableImpl::Impl as LocatableImpl
/**
* INTERNAL: This module contains the fully generated definition of `Format` and should not
* be referenced directly.
*/
module Generated {
/**
* A format element in a formatting template. For example the `{}` in:
* ```rust
* println!("Hello {}", "world");
* ```
* INTERNAL: Do not reference the `Generated::Format` class directly.
* Use the subclass `Format`, where the following predicates are available.
*/
class Format extends Synth::TFormat, LocatableImpl::Locatable {
override string getAPrimaryQlClass() { result = "Format" }
/**
* Gets the parent of this format.
*/
FormatArgsExpr getParent() { none() }
/**
* Gets the index of this format.
*/
int getIndex() { none() }
}
}

View File

@@ -0,0 +1,37 @@
// generated by codegen, do not edit
/**
* This module provides the generated definition of `FormatArgument`.
* INTERNAL: Do not import directly.
*/
private import codeql.rust.elements.internal.generated.Synth
private import codeql.rust.elements.internal.generated.Raw
import codeql.rust.elements.Format
import codeql.rust.elements.internal.LocatableImpl::Impl as LocatableImpl
/**
* INTERNAL: This module contains the fully generated definition of `FormatArgument` and should not
* be referenced directly.
*/
module Generated {
/**
* An argument in a format element in a formatting template. For example the `width`, `precision`, and `value` in:
* ```rust
* println!("Value {value:#width$.precision$}");
* ```
* or the `0`, `1` and `2` in:
* ```rust
* println!("Value {0:#1$.2$}", value, width, precision);
* ```
* INTERNAL: Do not reference the `Generated::FormatArgument` class directly.
* Use the subclass `FormatArgument`, where the following predicates are available.
*/
class FormatArgument extends Synth::TFormatArgument, LocatableImpl::Locatable {
override string getAPrimaryQlClass() { result = "FormatArgument" }
/**
* Gets the parent of this format argument.
*/
Format getParent() { none() }
}
}

View File

@@ -0,0 +1,25 @@
// generated by codegen, do not edit
/**
* This module provides the generated definition of `FormatTemplateVariableAccess`.
* INTERNAL: Do not import directly.
*/
private import codeql.rust.elements.internal.generated.Synth
private import codeql.rust.elements.internal.generated.Raw
import codeql.rust.elements.internal.PathExprBaseImpl::Impl as PathExprBaseImpl
/**
* INTERNAL: This module contains the fully generated definition of `FormatTemplateVariableAccess` and should not
* be referenced directly.
*/
module Generated {
/**
* INTERNAL: Do not reference the `Generated::FormatTemplateVariableAccess` class directly.
* Use the subclass `FormatTemplateVariableAccess`, where the following predicates are available.
*/
class FormatTemplateVariableAccess extends Synth::TFormatTemplateVariableAccess,
PathExprBaseImpl::PathExprBase
{
override string getAPrimaryQlClass() { result = "FormatTemplateVariableAccess" }
}
}

View File

@@ -51,6 +51,34 @@ private module Impl {
)
}
private Element getImmediateChildOfFormat(Format e, int index, string partialPredicateCall) {
exists(int b, int bLocatable, int n |
b = 0 and
bLocatable = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLocatable(e, i, _)) | i) and
n = bLocatable and
(
none()
or
result = getImmediateChildOfLocatable(e, index - b, partialPredicateCall)
)
)
}
private Element getImmediateChildOfFormatArgument(
FormatArgument e, int index, string partialPredicateCall
) {
exists(int b, int bLocatable, int n |
b = 0 and
bLocatable = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLocatable(e, i, _)) | i) and
n = bLocatable and
(
none()
or
result = getImmediateChildOfLocatable(e, index - b, partialPredicateCall)
)
)
}
private Element getImmediateChildOfMissing(Missing e, int index, string partialPredicateCall) {
exists(int b, int bUnextracted, int n |
b = 0 and
@@ -2214,22 +2242,17 @@ private module Impl {
)
}
private Element getImmediateChildOfPathExpr(PathExpr e, int index, string partialPredicateCall) {
exists(int b, int bExpr, int n, int nAttr, int nPath |
private Element getImmediateChildOfPathExprBase(
PathExprBase e, int index, string partialPredicateCall
) {
exists(int b, int bExpr, int n |
b = 0 and
bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and
n = bExpr and
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
nPath = nAttr + 1 and
(
none()
or
result = getImmediateChildOfExpr(e, index - b, partialPredicateCall)
or
result = e.getAttr(index - n) and
partialPredicateCall = "Attr(" + (index - n).toString() + ")"
or
index = nAttr and result = e.getPath() and partialPredicateCall = "Path()"
)
)
}
@@ -2940,6 +2963,22 @@ private module Impl {
)
}
private Element getImmediateChildOfFormatTemplateVariableAccess(
FormatTemplateVariableAccess e, int index, string partialPredicateCall
) {
exists(int b, int bPathExprBase, int n |
b = 0 and
bPathExprBase =
b + 1 + max(int i | i = -1 or exists(getImmediateChildOfPathExprBase(e, i, _)) | i) and
n = bPathExprBase and
(
none()
or
result = getImmediateChildOfPathExprBase(e, index - b, partialPredicateCall)
)
)
}
private Element getImmediateChildOfFunction(Function e, int index, string partialPredicateCall) {
exists(
int b, int bAssocItem, int bExternItem, int bItem, int bCallable, int n, int nAbi, int nBody,
@@ -3176,6 +3215,27 @@ private module Impl {
)
}
private Element getImmediateChildOfPathExpr(PathExpr e, int index, string partialPredicateCall) {
exists(int b, int bPathExprBase, int n, int nAttr, int nPath |
b = 0 and
bPathExprBase =
b + 1 + max(int i | i = -1 or exists(getImmediateChildOfPathExprBase(e, i, _)) | i) and
n = bPathExprBase and
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
nPath = nAttr + 1 and
(
none()
or
result = getImmediateChildOfPathExprBase(e, index - b, partialPredicateCall)
or
result = e.getAttr(index - n) and
partialPredicateCall = "Attr(" + (index - n).toString() + ")"
or
index = nAttr and result = e.getPath() and partialPredicateCall = "Path()"
)
)
}
private Element getImmediateChildOfStatic(Static e, int index, string partialPredicateCall) {
exists(
int b, int bExternItem, int bItem, int n, int nAttr, int nBody, int nName, int nTy,
@@ -3459,6 +3519,10 @@ private module Impl {
// * none() simplifies generation, as we can append `or ...` without a special case for the first item
none()
or
result = getImmediateChildOfFormat(e, index, partialAccessor)
or
result = getImmediateChildOfFormatArgument(e, index, partialAccessor)
or
result = getImmediateChildOfMissing(e, index, partialAccessor)
or
result = getImmediateChildOfUnimplemented(e, index, partialAccessor)
@@ -3649,8 +3713,6 @@ private module Impl {
or
result = getImmediateChildOfParenType(e, index, partialAccessor)
or
result = getImmediateChildOfPathExpr(e, index, partialAccessor)
or
result = getImmediateChildOfPathPat(e, index, partialAccessor)
or
result = getImmediateChildOfPathType(e, index, partialAccessor)
@@ -3719,6 +3781,8 @@ private module Impl {
or
result = getImmediateChildOfExternCrate(e, index, partialAccessor)
or
result = getImmediateChildOfFormatTemplateVariableAccess(e, index, partialAccessor)
or
result = getImmediateChildOfFunction(e, index, partialAccessor)
or
result = getImmediateChildOfImpl(e, index, partialAccessor)
@@ -3733,6 +3797,8 @@ private module Impl {
or
result = getImmediateChildOfModule(e, index, partialAccessor)
or
result = getImmediateChildOfPathExpr(e, index, partialAccessor)
or
result = getImmediateChildOfStatic(e, index, partialAccessor)
or
result = getImmediateChildOfStruct(e, index, partialAccessor)

View File

@@ -7,8 +7,8 @@
private import codeql.rust.elements.internal.generated.Synth
private import codeql.rust.elements.internal.generated.Raw
import codeql.rust.elements.Attr
import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl
import codeql.rust.elements.Path
import codeql.rust.elements.internal.PathExprBaseImpl::Impl as PathExprBaseImpl
/**
* INTERNAL: This module contains the fully generated definition of `PathExpr` and should not
@@ -26,7 +26,7 @@ module Generated {
* INTERNAL: Do not reference the `Generated::PathExpr` class directly.
* Use the subclass `PathExpr`, where the following predicates are available.
*/
class PathExpr extends Synth::TPathExpr, ExprImpl::Expr {
class PathExpr extends Synth::TPathExpr, PathExprBaseImpl::PathExprBase {
override string getAPrimaryQlClass() { result = "PathExpr" }
/**

View File

@@ -0,0 +1,22 @@
// generated by codegen, do not edit
/**
* This module provides the generated definition of `PathExprBase`.
* INTERNAL: Do not import directly.
*/
private import codeql.rust.elements.internal.generated.Synth
private import codeql.rust.elements.internal.generated.Raw
import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl
/**
* INTERNAL: This module contains the fully generated definition of `PathExprBase` and should not
* be referenced directly.
*/
module Generated {
/**
* A path expression or a variable access in a formatting template. See `PathExpr` and `FormatTemplateVariableAccess` for further details.
* INTERNAL: Do not reference the `Generated::PathExprBase` class directly.
* Use the subclass `PathExprBase`, where the following predicates are available.
*/
class PathExprBase extends Synth::TPathExprBase, ExprImpl::Expr { }
}

View File

@@ -3,3 +3,6 @@
* This module exports all modules providing `Element` subclasses.
*/
import codeql.rust.elements.internal.FormatConstructor
import codeql.rust.elements.internal.FormatArgumentConstructor
import codeql.rust.elements.internal.FormatTemplateVariableAccessConstructor

View File

@@ -2460,27 +2460,9 @@ module Raw {
/**
* INTERNAL: Do not use.
* A path expression. For example:
* ```rust
* let x = variable;
* let x = foo::bar;
* let y = <T>::foo;
* let z = <TypeRef as Trait>::foo;
* ```
* A path expression or a variable access in a formatting template. See `PathExpr` and `FormatTemplateVariableAccess` for further details.
*/
class PathExpr extends @path_expr, Expr {
override string toString() { result = "PathExpr" }
/**
* Gets the `index`th attr of this path expression (0-based).
*/
Attr getAttr(int index) { path_expr_attrs(this, index, result) }
/**
* Gets the path of this path expression, if it exists.
*/
Path getPath() { path_expr_paths(this, result) }
}
class PathExprBase extends @path_expr_base, Expr { }
/**
* INTERNAL: Do not use.
@@ -3608,6 +3590,30 @@ module Raw {
Visibility getVisibility() { module_visibilities(this, result) }
}
/**
* INTERNAL: Do not use.
* A path expression. For example:
* ```rust
* let x = variable;
* let x = foo::bar;
* let y = <T>::foo;
* let z = <TypeRef as Trait>::foo;
* ```
*/
class PathExpr extends @path_expr, PathExprBase {
override string toString() { result = "PathExpr" }
/**
* Gets the `index`th attr of this path expression (0-based).
*/
Attr getAttr(int index) { path_expr_attrs(this, index, result) }
/**
* Gets the path of this path expression, if it exists.
*/
Path getPath() { path_expr_paths(this, result) }
}
/**
* INTERNAL: Do not use.
* A Static. For example:

View File

@@ -150,6 +150,12 @@ module Synth {
* INTERNAL: Do not use.
*/
TForType(Raw::ForType id) { constructForType(id) } or
/**
* INTERNAL: Do not use.
*/
TFormat(Raw::FormatArgsExpr parent, int index, string text, int offset) {
constructFormat(parent, index, text, offset)
} or
/**
* INTERNAL: Do not use.
*/
@@ -158,6 +164,20 @@ module Synth {
* INTERNAL: Do not use.
*/
TFormatArgsExpr(Raw::FormatArgsExpr id) { constructFormatArgsExpr(id) } or
/**
* INTERNAL: Do not use.
*/
TFormatArgument(
Raw::FormatArgsExpr parent, int index, int kind, string name, boolean positional, int offset
) {
constructFormatArgument(parent, index, kind, name, positional, offset)
} or
/**
* INTERNAL: Do not use.
*/
TFormatTemplateVariableAccess(Raw::FormatArgsExpr parent, int index, int kind) {
constructFormatTemplateVariableAccess(parent, index, kind)
} or
/**
* INTERNAL: Do not use.
*/
@@ -628,7 +648,7 @@ module Synth {
TArrayExpr or TAsmExpr or TAwaitExpr or TBecomeExpr or TBinaryExpr or TBlockExpr or
TBreakExpr or TCallExprBase or TCastExpr or TClosureExpr or TContinueExpr or TFieldExpr or
TForExpr or TFormatArgsExpr or TIfExpr or TIndexExpr or TLetExpr or TLiteralExpr or
TLoopExpr or TMacroExpr or TMatchExpr or TOffsetOfExpr or TParenExpr or TPathExpr or
TLoopExpr or TMacroExpr or TMatchExpr or TOffsetOfExpr or TParenExpr or TPathExprBase or
TPrefixExpr or TRangeExpr or TRecordExpr or TRefExpr or TReturnExpr or TTryExpr or
TTupleExpr or TUnderscoreExpr or TWhileExpr or TYeetExpr or TYieldExpr;
@@ -663,7 +683,7 @@ module Synth {
/**
* INTERNAL: Do not use.
*/
class TLocatable = TAstNode;
class TLocatable = TAstNode or TFormat or TFormatArgument;
/**
* INTERNAL: Do not use.
@@ -673,6 +693,11 @@ module Synth {
TPathPat or TRangePat or TRecordPat or TRefPat or TRestPat or TSlicePat or TTuplePat or
TTupleStructPat or TWildcardPat;
/**
* INTERNAL: Do not use.
*/
class TPathExprBase = TFormatTemplateVariableAccess or TPathExpr;
/**
* INTERNAL: Do not use.
*/
@@ -900,6 +925,12 @@ module Synth {
*/
TForType convertForTypeFromRaw(Raw::Element e) { result = TForType(e) }
/**
* INTERNAL: Do not use.
* Converts a raw element to a synthesized `TFormat`, if possible.
*/
TFormat convertFormatFromRaw(Raw::Element e) { none() }
/**
* INTERNAL: Do not use.
* Converts a raw element to a synthesized `TFormatArgsArg`, if possible.
@@ -912,6 +943,20 @@ module Synth {
*/
TFormatArgsExpr convertFormatArgsExprFromRaw(Raw::Element e) { result = TFormatArgsExpr(e) }
/**
* INTERNAL: Do not use.
* Converts a raw element to a synthesized `TFormatArgument`, if possible.
*/
TFormatArgument convertFormatArgumentFromRaw(Raw::Element e) { none() }
/**
* INTERNAL: Do not use.
* Converts a raw element to a synthesized `TFormatTemplateVariableAccess`, if possible.
*/
TFormatTemplateVariableAccess convertFormatTemplateVariableAccessFromRaw(Raw::Element e) {
none()
}
/**
* INTERNAL: Do not use.
* Converts a raw element to a synthesized `TFunction`, if possible.
@@ -1781,7 +1826,7 @@ module Synth {
or
result = convertParenExprFromRaw(e)
or
result = convertPathExprFromRaw(e)
result = convertPathExprBaseFromRaw(e)
or
result = convertPrefixExprFromRaw(e)
or
@@ -1900,7 +1945,13 @@ module Synth {
* INTERNAL: Do not use.
* Converts a raw DB element to a synthesized `TLocatable`, if possible.
*/
TLocatable convertLocatableFromRaw(Raw::Element e) { result = convertAstNodeFromRaw(e) }
TLocatable convertLocatableFromRaw(Raw::Element e) {
result = convertAstNodeFromRaw(e)
or
result = convertFormatFromRaw(e)
or
result = convertFormatArgumentFromRaw(e)
}
/**
* INTERNAL: Do not use.
@@ -1940,6 +1991,16 @@ module Synth {
result = convertWildcardPatFromRaw(e)
}
/**
* INTERNAL: Do not use.
* Converts a raw DB element to a synthesized `TPathExprBase`, if possible.
*/
TPathExprBase convertPathExprBaseFromRaw(Raw::Element e) {
result = convertFormatTemplateVariableAccessFromRaw(e)
or
result = convertPathExprFromRaw(e)
}
/**
* INTERNAL: Do not use.
* Converts a raw DB element to a synthesized `TStmt`, if possible.
@@ -2206,6 +2267,12 @@ module Synth {
*/
Raw::Element convertForTypeToRaw(TForType e) { e = TForType(result) }
/**
* INTERNAL: Do not use.
* Converts a synthesized `TFormat` to a raw DB element, if possible.
*/
Raw::Element convertFormatToRaw(TFormat e) { none() }
/**
* INTERNAL: Do not use.
* Converts a synthesized `TFormatArgsArg` to a raw DB element, if possible.
@@ -2218,6 +2285,18 @@ module Synth {
*/
Raw::Element convertFormatArgsExprToRaw(TFormatArgsExpr e) { e = TFormatArgsExpr(result) }
/**
* INTERNAL: Do not use.
* Converts a synthesized `TFormatArgument` to a raw DB element, if possible.
*/
Raw::Element convertFormatArgumentToRaw(TFormatArgument e) { none() }
/**
* INTERNAL: Do not use.
* Converts a synthesized `TFormatTemplateVariableAccess` to a raw DB element, if possible.
*/
Raw::Element convertFormatTemplateVariableAccessToRaw(TFormatTemplateVariableAccess e) { none() }
/**
* INTERNAL: Do not use.
* Converts a synthesized `TFunction` to a raw DB element, if possible.
@@ -3087,7 +3166,7 @@ module Synth {
or
result = convertParenExprToRaw(e)
or
result = convertPathExprToRaw(e)
result = convertPathExprBaseToRaw(e)
or
result = convertPrefixExprToRaw(e)
or
@@ -3206,7 +3285,13 @@ module Synth {
* INTERNAL: Do not use.
* Converts a synthesized `TLocatable` to a raw DB element, if possible.
*/
Raw::Element convertLocatableToRaw(TLocatable e) { result = convertAstNodeToRaw(e) }
Raw::Element convertLocatableToRaw(TLocatable e) {
result = convertAstNodeToRaw(e)
or
result = convertFormatToRaw(e)
or
result = convertFormatArgumentToRaw(e)
}
/**
* INTERNAL: Do not use.
@@ -3246,6 +3331,16 @@ module Synth {
result = convertWildcardPatToRaw(e)
}
/**
* INTERNAL: Do not use.
* Converts a synthesized `TPathExprBase` to a raw DB element, if possible.
*/
Raw::Element convertPathExprBaseToRaw(TPathExprBase e) {
result = convertFormatTemplateVariableAccessToRaw(e)
or
result = convertPathExprToRaw(e)
}
/**
* INTERNAL: Do not use.
* Converts a synthesized `TStmt` to a raw DB element, if possible.

View File

@@ -37,8 +37,11 @@ import codeql.rust.elements.internal.FieldExprConstructor
import codeql.rust.elements.internal.FnPtrTypeConstructor
import codeql.rust.elements.internal.ForExprConstructor
import codeql.rust.elements.internal.ForTypeConstructor
import codeql.rust.elements.internal.FormatConstructor
import codeql.rust.elements.internal.FormatArgsArgConstructor
import codeql.rust.elements.internal.FormatArgsExprConstructor
import codeql.rust.elements.internal.FormatArgumentConstructor
import codeql.rust.elements.internal.FormatTemplateVariableAccessConstructor
import codeql.rust.elements.internal.FunctionConstructor
import codeql.rust.elements.internal.GenericArgListConstructor
import codeql.rust.elements.internal.GenericParamListConstructor

View File

@@ -0,0 +1,65 @@
/**
* The purpose of this file is to control which cached predicates belong to the same stage.
*
* Combining stages can improve performance as we are more likely to reuse shared, non-cached predicates.
*
* To make a predicate `p` belong to a stage `A`:
* - make `p` depend on `A::ref()`, and
* - make `A::backref()` depend on `p`.
*
* Since `A` is a cached module, `ref` and `backref` must be in the same stage, and the dependency
* chain above thus forces `p` to be in that stage as well.
*
* With these two predicates in a `cached module` we ensure that all the cached predicates will be in a single stage at runtime.
*
* Grouping stages can cause unnecessary computation, as a concrete query might not depend on
* all the cached predicates in a stage.
* Care should therefore be taken not to combine two stages, if it is likely that a query only depend
* on some but not all the cached predicates in the combined stage.
*/
import rust
/**
* Contains a `cached module` for each stage.
* Each `cached module` ensures that predicates that are supposed to be in the same stage, are in the same stage.
*
* Each `cached module` contain two predicates:
* The first, `ref`, always holds, and is referenced from `cached` predicates.
* The second, `backref`, contains references to the same `cached` predicates.
* The `backref` predicate starts with `1 = 1 or` to ensure that the predicate will be optimized down to a constant by the optimizer.
*/
module Stages {
/**
* The control flow graph (CFG) stage.
*/
cached
module CfgStage {
private import codeql.rust.controlflow.internal.Splitting
private import codeql.rust.controlflow.internal.SuccessorType
private import codeql.rust.controlflow.internal.ControlFlowGraphImpl
/**
* Always holds.
* Ensures that a predicate is evaluated as part of the BasicBlocks stage.
*/
cached
predicate ref() { 1 = 1 }
/**
* DO NOT USE!
*
* Contains references to each predicate that use the above `ref` predicate.
*/
cached
predicate backref() {
1 = 1
or
exists(TConditionalCompletionSplitKind())
or
exists(TNormalSuccessor())
or
exists(AstCfgNode n)
}
}
}

View File

@@ -310,7 +310,7 @@ closure_binder_generic_param_lists(
| @match_expr
| @offset_of_expr
| @paren_expr
| @path_expr
| @path_expr_base
| @prefix_expr
| @range_expr
| @record_expr
@@ -2113,22 +2113,9 @@ paren_type_ties(
int ty: @type_ref ref
);
path_exprs(
unique int id: @path_expr
);
#keyset[id, index]
path_expr_attrs(
int id: @path_expr ref,
int index: int ref,
int attr: @attr ref
);
#keyset[id]
path_expr_paths(
int id: @path_expr ref,
int path: @path ref
);
@path_expr_base =
@path_expr
;
path_pats(
unique int id: @path_pat
@@ -3036,6 +3023,23 @@ module_visibilities(
int visibility: @visibility ref
);
path_exprs(
unique int id: @path_expr
);
#keyset[id, index]
path_expr_attrs(
int id: @path_expr ref,
int index: int ref,
int attr: @attr ref
);
#keyset[id]
path_expr_paths(
int id: @path_expr ref,
int path: @path ref
);
statics(
unique int id: @static
);

View File

@@ -6,3 +6,5 @@ import codeql.files.FileSystem
import codeql.rust.elements.AssignmentOperation
import codeql.rust.elements.LogicalOperation
import codeql.rust.elements.Variable
import codeql.rust.elements.NamedFormatArgument
import codeql.rust.elements.PositionalFormatArgument

View File

@@ -0,0 +1,132 @@
getFormat
| main.rs:5:14:5:61 | FormatArgsExpr | main.rs:5:21:5:46 | {value:#width$.precision$} | 0 |
| main.rs:6:14:6:56 | FormatArgsExpr | main.rs:6:21:6:30 | {0:#1$.2$} | 0 |
| main.rs:7:14:7:40 | FormatArgsExpr | main.rs:7:21:7:22 | {} | 0 |
| main.rs:7:14:7:40 | FormatArgsExpr | main.rs:7:24:7:25 | {} | 1 |
| main.rs:11:14:11:34 | FormatArgsExpr | main.rs:11:22:11:23 | {} | 0 |
| main.rs:12:14:12:34 | FormatArgsExpr | main.rs:12:29:12:30 | {} | 0 |
| main.rs:13:14:13:27 | FormatArgsExpr | main.rs:13:15:13:18 | {:?} | 0 |
| main.rs:14:14:14:33 | FormatArgsExpr | main.rs:14:15:14:21 | {value} | 0 |
| main.rs:16:14:16:30 | FormatArgsExpr | main.rs:16:21:16:28 | {people} | 0 |
| main.rs:17:14:17:26 | FormatArgsExpr | main.rs:17:15:17:16 | {} | 0 |
| main.rs:17:14:17:26 | FormatArgsExpr | main.rs:17:18:17:19 | {} | 1 |
| main.rs:18:14:18:24 | FormatArgsExpr | main.rs:18:15:18:19 | {:04} | 0 |
| main.rs:19:14:19:32 | FormatArgsExpr | main.rs:19:15:19:19 | {:#?} | 0 |
| main.rs:21:14:21:34 | FormatArgsExpr | main.rs:21:15:21:17 | {1} | 0 |
| main.rs:21:14:21:34 | FormatArgsExpr | main.rs:21:19:21:20 | {} | 1 |
| main.rs:21:14:21:34 | FormatArgsExpr | main.rs:21:22:21:24 | {0} | 2 |
| main.rs:21:14:21:34 | FormatArgsExpr | main.rs:21:26:21:27 | {} | 3 |
| main.rs:22:14:22:31 | FormatArgsExpr | main.rs:22:21:22:24 | {:5} | 0 |
| main.rs:23:14:23:35 | FormatArgsExpr | main.rs:23:21:23:25 | {:1$} | 0 |
| main.rs:24:14:24:36 | FormatArgsExpr | main.rs:24:21:24:26 | {1:0$} | 0 |
| main.rs:25:14:25:47 | FormatArgsExpr | main.rs:25:21:25:29 | {:width$} | 0 |
| main.rs:27:14:27:36 | FormatArgsExpr | main.rs:27:21:27:29 | {:width$} | 0 |
| main.rs:28:24:28:42 | FormatArgsExpr | main.rs:28:31:28:35 | {:<5} | 0 |
| main.rs:29:24:29:43 | FormatArgsExpr | main.rs:29:31:29:36 | {:-<5} | 0 |
| main.rs:30:24:30:42 | FormatArgsExpr | main.rs:30:31:30:35 | {:^5} | 0 |
| main.rs:31:24:31:42 | FormatArgsExpr | main.rs:31:31:31:35 | {:>5} | 0 |
| main.rs:32:14:32:57 | FormatArgsExpr | main.rs:32:21:32:26 | {:^15} | 0 |
| main.rs:32:39:32:56 | FormatArgsExpr | main.rs:32:40:32:43 | {:?} | 0 |
| main.rs:33:24:33:39 | FormatArgsExpr | main.rs:33:31:33:34 | {:+} | 0 |
| main.rs:34:24:34:35 | FormatArgsExpr | main.rs:34:25:34:29 | {:#x} | 0 |
| main.rs:35:24:35:40 | FormatArgsExpr | main.rs:35:31:35:35 | {:05} | 0 |
| main.rs:36:24:36:41 | FormatArgsExpr | main.rs:36:31:36:35 | {:05} | 0 |
| main.rs:37:24:37:38 | FormatArgsExpr | main.rs:37:25:37:32 | {:#010x} | 0 |
| main.rs:39:14:39:45 | FormatArgsExpr | main.rs:39:21:39:23 | {0} | 0 |
| main.rs:39:14:39:45 | FormatArgsExpr | main.rs:39:28:39:33 | {1:.5} | 1 |
| main.rs:41:14:41:49 | FormatArgsExpr | main.rs:41:21:41:23 | {1} | 0 |
| main.rs:41:14:41:49 | FormatArgsExpr | main.rs:41:28:41:34 | {2:.0$} | 1 |
| main.rs:43:14:43:49 | FormatArgsExpr | main.rs:43:21:43:23 | {0} | 0 |
| main.rs:43:14:43:49 | FormatArgsExpr | main.rs:43:28:43:34 | {2:.1$} | 1 |
| main.rs:45:14:45:46 | FormatArgsExpr | main.rs:45:21:45:22 | {} | 0 |
| main.rs:45:14:45:46 | FormatArgsExpr | main.rs:45:27:45:31 | {:.*} | 1 |
| main.rs:47:14:47:48 | FormatArgsExpr | main.rs:47:21:47:23 | {1} | 0 |
| main.rs:47:14:47:48 | FormatArgsExpr | main.rs:47:28:47:33 | {2:.*} | 1 |
| main.rs:48:14:48:47 | FormatArgsExpr | main.rs:48:21:48:22 | {} | 0 |
| main.rs:48:14:48:47 | FormatArgsExpr | main.rs:48:27:48:32 | {2:.*} | 1 |
| main.rs:49:14:49:72 | FormatArgsExpr | main.rs:49:21:49:22 | {} | 0 |
| main.rs:49:14:49:72 | FormatArgsExpr | main.rs:49:27:49:41 | {number:.prec$} | 1 |
| main.rs:52:9:55:22 | FormatArgsExpr | main.rs:52:10:52:11 | {} | 0 |
| main.rs:52:9:55:22 | FormatArgsExpr | main.rs:52:15:52:23 | {name:.*} | 1 |
| main.rs:58:9:61:24 | FormatArgsExpr | main.rs:58:10:58:11 | {} | 0 |
| main.rs:58:9:61:24 | FormatArgsExpr | main.rs:58:15:58:23 | {name:.*} | 1 |
| main.rs:64:9:67:24 | FormatArgsExpr | main.rs:64:10:64:11 | {} | 0 |
| main.rs:64:9:67:24 | FormatArgsExpr | main.rs:64:15:64:25 | {name:>8.*} | 1 |
| main.rs:70:12:70:31 | FormatArgsExpr | main.rs:70:13:70:20 | {0:.1$e} | 0 |
| main.rs:71:12:71:31 | FormatArgsExpr | main.rs:71:13:71:20 | {0:.1$e} | 0 |
| main.rs:73:14:73:35 | FormatArgsExpr | main.rs:73:28:73:29 | {} | 0 |
getArgumentRef
| main.rs:5:21:5:46 | {value:#width$.precision$} | main.rs:5:22:5:26 | value |
| main.rs:6:21:6:30 | {0:#1$.2$} | main.rs:6:22:6:22 | 0 |
| main.rs:14:15:14:21 | {value} | main.rs:14:16:14:20 | value |
| main.rs:16:21:16:28 | {people} | main.rs:16:22:16:27 | people |
| main.rs:21:15:21:17 | {1} | main.rs:21:16:21:16 | 1 |
| main.rs:21:22:21:24 | {0} | main.rs:21:23:21:23 | 0 |
| main.rs:24:21:24:26 | {1:0$} | main.rs:24:22:24:22 | 1 |
| main.rs:39:21:39:23 | {0} | main.rs:39:22:39:22 | 0 |
| main.rs:39:28:39:33 | {1:.5} | main.rs:39:29:39:29 | 1 |
| main.rs:41:21:41:23 | {1} | main.rs:41:22:41:22 | 1 |
| main.rs:41:28:41:34 | {2:.0$} | main.rs:41:29:41:29 | 2 |
| main.rs:43:21:43:23 | {0} | main.rs:43:22:43:22 | 0 |
| main.rs:43:28:43:34 | {2:.1$} | main.rs:43:29:43:29 | 2 |
| main.rs:47:21:47:23 | {1} | main.rs:47:22:47:22 | 1 |
| main.rs:47:28:47:33 | {2:.*} | main.rs:47:29:47:29 | 2 |
| main.rs:48:27:48:32 | {2:.*} | main.rs:48:28:48:28 | 2 |
| main.rs:49:27:49:41 | {number:.prec$} | main.rs:49:28:49:33 | number |
| main.rs:52:15:52:23 | {name:.*} | main.rs:52:16:52:19 | name |
| main.rs:58:15:58:23 | {name:.*} | main.rs:58:16:58:19 | name |
| main.rs:64:15:64:25 | {name:>8.*} | main.rs:64:16:64:19 | name |
| main.rs:70:13:70:20 | {0:.1$e} | main.rs:70:14:70:14 | 0 |
| main.rs:71:13:71:20 | {0:.1$e} | main.rs:71:14:71:14 | 0 |
getWidthArgument
| main.rs:5:21:5:46 | {value:#width$.precision$} | main.rs:5:29:5:33 | width |
| main.rs:6:21:6:30 | {0:#1$.2$} | main.rs:6:25:6:25 | 1 |
| main.rs:23:21:23:25 | {:1$} | main.rs:23:23:23:23 | 1 |
| main.rs:24:21:24:26 | {1:0$} | main.rs:24:24:24:24 | 0 |
| main.rs:25:21:25:29 | {:width$} | main.rs:25:23:25:27 | width |
| main.rs:27:21:27:29 | {:width$} | main.rs:27:23:27:27 | width |
getPrecisionArgument
| main.rs:5:21:5:46 | {value:#width$.precision$} | main.rs:5:36:5:44 | precision |
| main.rs:6:21:6:30 | {0:#1$.2$} | main.rs:6:28:6:28 | 2 |
| main.rs:41:28:41:34 | {2:.0$} | main.rs:41:32:41:32 | 0 |
| main.rs:43:28:43:34 | {2:.1$} | main.rs:43:32:43:32 | 1 |
| main.rs:49:27:49:41 | {number:.prec$} | main.rs:49:36:49:39 | prec |
| main.rs:70:13:70:20 | {0:.1$e} | main.rs:70:17:70:17 | 1 |
| main.rs:71:13:71:20 | {0:.1$e} | main.rs:71:17:71:17 | 1 |
getIndex
| main.rs:6:22:6:22 | 0 | 0 |
| main.rs:6:25:6:25 | 1 | 1 |
| main.rs:6:28:6:28 | 2 | 2 |
| main.rs:21:16:21:16 | 1 | 1 |
| main.rs:21:23:21:23 | 0 | 0 |
| main.rs:23:23:23:23 | 1 | 1 |
| main.rs:24:22:24:22 | 1 | 1 |
| main.rs:24:24:24:24 | 0 | 0 |
| main.rs:39:22:39:22 | 0 | 0 |
| main.rs:39:29:39:29 | 1 | 1 |
| main.rs:41:22:41:22 | 1 | 1 |
| main.rs:41:29:41:29 | 2 | 2 |
| main.rs:41:32:41:32 | 0 | 0 |
| main.rs:43:22:43:22 | 0 | 0 |
| main.rs:43:29:43:29 | 2 | 2 |
| main.rs:43:32:43:32 | 1 | 1 |
| main.rs:47:22:47:22 | 1 | 1 |
| main.rs:47:29:47:29 | 2 | 2 |
| main.rs:48:28:48:28 | 2 | 2 |
| main.rs:70:14:70:14 | 0 | 0 |
| main.rs:70:17:70:17 | 1 | 1 |
| main.rs:71:14:71:14 | 0 | 0 |
| main.rs:71:17:71:17 | 1 | 1 |
getName
| main.rs:5:22:5:26 | value | value |
| main.rs:5:29:5:33 | width | width |
| main.rs:5:36:5:44 | precision | precision |
| main.rs:14:16:14:20 | value | value |
| main.rs:16:22:16:27 | people | people |
| main.rs:25:23:25:27 | width | width |
| main.rs:27:23:27:27 | width | width |
| main.rs:49:28:49:33 | number | number |
| main.rs:49:36:49:39 | prec | prec |
| main.rs:52:16:52:19 | name | name |
| main.rs:58:16:58:19 | name | name |
| main.rs:64:16:64:19 | name | name |

View File

@@ -0,0 +1,19 @@
import rust
query predicate getFormat(FormatArgsExpr arg, Format format, int index) {
format = arg.getFormat(index)
}
query predicate getArgumentRef(Format format, FormatArgument arg) { arg = format.getArgumentRef() }
query predicate getWidthArgument(Format format, FormatArgument arg) {
arg = format.getWidthArgument()
}
query predicate getPrecisionArgument(Format format, FormatArgument arg) {
arg = format.getPrecisionArgument()
}
query predicate getIndex(PositionalFormatArgument arg, int index) { arg.getIndex() = index }
query predicate getName(NamedFormatArgument arg, string name) { arg.getName() = name }

View File

@@ -0,0 +1,77 @@
fn main() {
let width = 4;
let precision = 2;
let value = 10;
println!("Value {value:#width$.precision$}", value = 10.5);
println!("Value {0:#1$.2$}", value, width, precision);
println!("Value {} {}", value, width);
// Examples from https://doc.rust-lang.org/std/fmt
println!("Hello");
println!("Hello, {}!", "world");
println!("The number is {}", 1);
println!("{:?}", (3, 4));
println!("{value}", value = 4);
let people = "Rustaceans";
println!("Hello {people}!");
println!("{} {}", 1, 2);
println!("{:04}", 42);
println!("{:#?}", (100, 200));
println!("{1} {} {0} {}", 1, 2);
println!("Hello {:5}!", "x");
println!("Hello {:1$}!", "x", 5);
println!("Hello {1:0$}!", 5, "x");
println!("Hello {:width$}!", "x", width = 5);
let width = 5;
println!("Hello {:width$}!", "x");
assert_eq!(format!("Hello {:<5}!", "x"), "Hello x !");
assert_eq!(format!("Hello {:-<5}!", "x"), "Hello x----!");
assert_eq!(format!("Hello {:^5}!", "x"), "Hello x !");
assert_eq!(format!("Hello {:>5}!", "x"), "Hello x!");
println!("Hello {:^15}!", format!("{:?}", Some("hi")));
assert_eq!(format!("Hello {:+}!", 5), "Hello +5!");
assert_eq!(format!("{:#x}!", 27), "0x1b!");
assert_eq!(format!("Hello {:05}!", 5), "Hello 00005!");
assert_eq!(format!("Hello {:05}!", -5), "Hello -0005!");
assert_eq!(format!("{:#010x}!", 27), "0x0000001b!");
println!("Hello {0} is {1:.5}", "x", 0.01);
println!("Hello {1} is {2:.0$}", 5, "x", 0.01);
println!("Hello {0} is {2:.1$}", "x", 5, 0.01);
println!("Hello {} is {:.*}", "x", 5, 0.01);
println!("Hello {1} is {2:.*}", 5, "x", 0.01);
println!("Hello {} is {2:.*}", "x", 5, 0.01);
println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01);
println!(
"{}, `{name:.*}` has 3 fractional digits",
"Hello",
3,
name = 1234.56
);
println!(
"{}, `{name:.*}` has 3 characters",
"Hello",
3,
name = "1234.56"
);
println!(
"{}, `{name:>8.*}` has 3 right-aligned characters",
"Hello",
3,
name = "1234.56"
);
print!("{0:.1$e}", 12345, 3);
print!("{0:.1$e}", 12355, 3);
println!("The value is {}", 1.5);
assert_eq!(format!("Hello {{}}"), "Hello {}");
assert_eq!(format!("{{ Hello"), "{ Hello");
}

View File

@@ -19,15 +19,10 @@
| main.rs:370:9:370:9 | x | Variable is assigned a value that is never used. |
| main.rs:378:17:378:17 | x | Variable is assigned a value that is never used. |
| main.rs:432:9:432:10 | i6 | Variable is assigned a value that is never used. |
| more.rs:8:9:8:13 | times | Variable is assigned a value that is never used. |
| more.rs:9:9:9:14 | unused | Variable is assigned a value that is never used. |
| more.rs:21:9:21:14 | unused | Variable is assigned a value that is never used. |
| more.rs:38:23:38:25 | val | Variable is assigned a value that is never used. |
| more.rs:42:19:42:21 | val | Variable is assigned a value that is never used. |
| more.rs:58:9:58:11 | val | Variable is assigned a value that is never used. |
| more.rs:80:9:80:14 | a_ptr4 | Variable is assigned a value that is never used. |
| more.rs:95:9:95:13 | d_ptr | Variable is assigned a value that is never used. |
| more.rs:101:9:101:17 | f_ptr | Variable is assigned a value that is never used. |
| more.rs:24:9:24:11 | val | Variable is assigned a value that is never used. |
| more.rs:46:9:46:14 | a_ptr4 | Variable is assigned a value that is never used. |
| more.rs:61:9:61:13 | d_ptr | Variable is assigned a value that is never used. |
| more.rs:67:9:67:17 | f_ptr | Variable is assigned a value that is never used. |
| unreachable.rs:166:6:166:6 | x | Variable is assigned a value that is never used. |
| unreachable.rs:190:14:190:14 | a | Variable is assigned a value that is never used. |
| unreachable.rs:199:9:199:9 | a | Variable is assigned a value that is never used. |

View File

@@ -2,8 +2,6 @@
| main.rs:90:13:90:13 | d | Variable is not used. |
| main.rs:141:5:141:5 | y | Variable is not used. |
| main.rs:168:9:168:9 | x | Variable is not used. |
| main.rs:196:9:196:9 | x | Variable is not used. |
| main.rs:201:9:201:9 | x | Variable is not used. |
| main.rs:250:17:250:17 | a | Variable is not used. |
| main.rs:258:20:258:22 | val | Variable is not used. |
| main.rs:272:14:272:16 | val | Variable is not used. |
@@ -20,3 +18,4 @@
| main.rs:379:21:379:21 | y | Variable is not used. |
| main.rs:427:27:427:29 | val | Variable is not used. |
| main.rs:430:22:430:24 | acc | Variable is not used. |
| main.rs:455:9:455:14 | unused | Variable is not used. |

View File

@@ -193,12 +193,12 @@ fn loops() {
}
}
for x // SPURIOUS: unused variable
for x
in 1..10 {
println!("x is {x}");
}
for x // SPURIOUS: unused variable
for x
in 1..10 {
_ = format!("x is {x}"); // SPURIOUS: unused value `res`
}
@@ -434,6 +434,38 @@ fn folds_and_closures() {
_ = a6.fold(0, | acc, val | acc + val + i6);
}
// --- traits ---
trait Incrementable {
fn increment(
&mut self,
times: i32,
unused: &mut i32
);
}
struct MyValue {
value: i32,
}
impl Incrementable for MyValue {
fn increment(
&mut self,
times: i32,
unused: i32 // BAD: unused variable
) {
self.value += times;
}
}
fn traits() {
let mut i = MyValue { value: 0 };
let a = 1;
let b = 2;
i.increment(a, b);
}
// --- main ---
fn main() {

View File

@@ -1,45 +1,11 @@
// --- traits ---
trait Incrementable {
fn increment(
&mut self,
times: i32, // SPURIOUS: unused value
unused: i32 // SPURIOUS: unused value
);
}
struct MyValue {
value: i32,
}
impl Incrementable for MyValue {
fn increment(
&mut self,
times: i32,
unused: i32 // BAD: unused variable [NOT DETECTED] SPURIOUS: unused value
) {
self.value += times;
}
}
fn traits() {
let mut i = MyValue { value: 0 };
let a = 1;
let b = 2;
i.increment(a, b);
}
// --- generics ---
trait MySettable<T> {
fn set(&mut self, val: T); // SPURIOUS: unused value
fn set(&mut self, val: T);
}
trait MyGettable<T> {
fn get(&self, val: T) -> &T; // SPURIOUS: unused value
fn get(&self, val: T) -> &T;
}
struct MyContainer<T> {

View File

@@ -101,7 +101,13 @@ class _:
"""
@annotate(PathExpr)
class PathExprBase(Expr):
"""
A path expression or a variable access in a formatting template. See `PathExpr` and `FormatTemplateVariableAccess` for further details.
"""
@annotate(PathExpr, replace_bases={Expr: PathExprBase})
class _:
"""
A path expression. For example:
@@ -191,6 +197,7 @@ class _:
```
"""
class CallExprBase(Expr):
"""
A function or method call expression. See `CallExpr` and `MethodCallExpr` for further details.
@@ -213,6 +220,7 @@ class _:
arg_list: drop
attrs: drop
@annotate(MethodCallExpr, replace_bases={Expr: CallExprBase})
class _:
"""
@@ -1741,6 +1749,7 @@ class _:
```
"""
@annotate(Function, add_bases=[Callable])
class _:
param_list: drop
@@ -1751,3 +1760,38 @@ class _:
class _:
param_list: drop
attrs: drop
@qltest.skip
@synth.on_arguments(parent="FormatArgsExpr", index=int, kind=int)
class FormatTemplateVariableAccess(PathExprBase):
pass
@qltest.skip
@synth.on_arguments(parent=FormatArgsExpr, index=int, text=string, offset=int)
class Format(Locatable):
"""
A format element in a formatting template. For example the `{}` in:
```rust
println!("Hello {}", "world");
```
"""
parent: FormatArgsExpr
index: int
@qltest.skip
@synth.on_arguments(parent=FormatArgsExpr, index=int, kind=int, name=string, positional=boolean, offset=int)
class FormatArgument(Locatable):
"""
An argument in a format element in a formatting template. For example the `width`, `precision`, and `value` in:
```rust
println!("Value {value:#width$.precision$}");
```
or the `0`, `1` and `2` in:
```rust
println!("Value {0:#1$.2$}", value, width, precision);
```
"""
parent: Format

View File

@@ -3,7 +3,7 @@
set "RUST_BACKTRACE=full"
set "QLTEST_LOG=%CODEQL_EXTRACTOR_RUST_LOG_DIR%/qltest.log"
type NUL && "%CODEQL_EXTRACTOR_RUST_ROOT%/tools/%CODEQL_PLATFORM%/extractor" --qltest >"%QLTEST_LOG%"
type NUL && "%CODEQL_EXTRACTOR_RUST_ROOT%/tools/%CODEQL_PLATFORM%/extractor" --qltest >"%QLTEST_LOG%" 2>&1
if %ERRORLEVEL% neq 0 (
type "%QLTEST_LOG%"

View File

@@ -4,7 +4,7 @@ set -eu
export RUST_BACKTRACE=full
QLTEST_LOG="$CODEQL_EXTRACTOR_RUST_LOG_DIR"/qltest.log
if ! "$CODEQL_EXTRACTOR_RUST_ROOT/tools/$CODEQL_PLATFORM/extractor" --qltest &>> "$QLTEST_LOG"; then
if ! "$CODEQL_EXTRACTOR_RUST_ROOT/tools/$CODEQL_PLATFORM/extractor" --qltest >> "$QLTEST_LOG" 2>&1; then
cat "$QLTEST_LOG"
exit 1
fi