Title: Rust: modules declared in a file brought in by `include!` are not resolved (no canonical paths, unresolved calls), e.g. in `windows-sys` and `windows` · Issue #23009 · github/codeql · GitHub
Open Graph Title: Rust: modules declared in a file brought in by `include!` are not resolved (no canonical paths, unresolved calls), e.g. in `windows-sys` and `windows` · Issue #23009 · github/codeql
X Title: Rust: modules declared in a file brought in by `include!` are not resolved (no canonical paths, unresolved calls), e.g. in `windows-sys` and `windows` · Issue #23009 · github/codeql
Description: Description of the issue When a crate's lib.rs brings in part of its module tree with include!("tree/mod.rs"), and that file declares pub mod inner;, CodeQL looks for inner next to lib.rs instead of next to tree/mod.rs, where rustc finds...
Open Graph Description: Description of the issue When a crate's lib.rs brings in part of its module tree with include!("tree/mod.rs"), and that file declares pub mod inner;, CodeQL looks for inner next to lib.rs instead o...
X Description: Description of the issue When a crate's lib.rs brings in part of its module tree with include!("tree/mod.rs"), and that file declares pub mod inner;, CodeQL looks for inner next to li...
Opengraph URL: https://github.com/github/codeql/issues/23009
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Rust: modules declared in a file brought in by `include!` are not resolved (no canonical paths, unresolved calls), e.g. in `windows-sys` and `windows`","articleBody":"**Description of the issue**\n\nWhen a crate's `lib.rs` brings in part of its module tree with `include!(\"tree/mod.rs\")`, and that file declares `pub mod inner;`, CodeQL looks for `inner` next to `lib.rs` instead of next to `tree/mod.rs`, where rustc finds it. As a result, nothing in `inner` gets a canonical path, calls into it have no `getStaticTarget()`, and models-as-data rows for its functions never apply.\n\nThe public `windows-sys` and `windows` crates are built this way (`lib.rs` contains `include!(\"Windows/mod.rs\")`), so Windows API calls made through them are never resolved:\n\n- `windows-sys` 0.61.2: 0 of the 10,661 functions under `src/Windows/Win32` have a canonical path.\n- `windows` 0.62.2: 777 of 130,113 do (with `codeql/rust-all` 0.2.25); `CreateFileW` is not among them.\n- Calls to `CreateFileW`, `ReadFile`, `RegQueryValueExW`, `CreateProcessW`, `ShellExecuteW` and `recv` through `windows-sys`, and to the first four through `windows`, are unresolved.\n\nSeen with CodeQL 2.27.2 (`codeql/rust-all` 0.2.23) and 2.27.4 (`codeql/rust-all` 0.2.25), Rust 1.99.0, Windows x64. Setting `extract_dependencies_as_source=true` does not change it.\n\n**Reproduction**\n\nA two-crate workspace. `toy-include` brings in module `inner` through `include!`; module `direct`, declared normally, has the same contents and serves as a control.\n\n`Cargo.toml`\n```toml\n[workspace]\nmembers = [\"toy-include\", \"toy-user\"]\nresolver = \"2\"\n```\n\n`toy-include/Cargo.toml`\n```toml\n[package]\nname = \"toy-include\"\nversion = \"0.1.0\"\nedition = \"2021\"\n```\n\n`toy-include/src/lib.rs`\n```rust\nmacro_rules! declare {\n ($name:ident) => {\n extern \"C\" {\n pub fn $name() -> u32;\n }\n };\n}\n\ninclude!(\"tree/mod.rs\");\n\npub mod direct;\n```\n\n`toy-include/src/tree/mod.rs`\n```rust\npub mod inner;\n```\n\n`toy-include/src/tree/inner/mod.rs`\n```rust\npub fn hidden() -> u32 {\n 1\n}\n\ndeclare!(hidden_extern);\n```\n\n`toy-include/src/direct.rs`\n```rust\npub fn visible() -> u32 {\n 2\n}\n\ndeclare!(visible_extern);\n```\n\n`toy-user/Cargo.toml`\n```toml\n[package]\nname = \"toy-user\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[dependencies]\ntoy-include = { path = \"../toy-include\" }\n```\n\n`toy-user/src/main.rs`\n```rust\nfn main() {\n let a = toy_include::inner::hidden();\n let b = toy_include::direct::visible();\n let c = unsafe { toy_include::inner::hidden_extern() };\n let d = unsafe { toy_include::direct::visible_extern() };\n println!(\"{}\", a + b + c + d);\n}\n```\n\nThe workspace builds with `cargo check`. Query (`query/qlpack.yml` depends on `codeql/rust-all: \"*\"`):\n\n`query/include-paths.ql`\n```ql\nimport rust\n\n/** Each function of the `toy-include` crate, with its canonical path (none if CodeQL gives none). */\nquery predicate functions(string file, string name, string canonicalPath) {\n exists(Function f |\n f.getFile().getAbsolutePath().matches(\"%toy-include%\") and\n file = f.getFile().getAbsolutePath().regexpCapture(\".*toy-include[/\\\\\\\\]src[/\\\\\\\\](.*)\", 1) and\n name = f.getName().getText() and\n if exists(f.getCanonicalPath()) then canonicalPath = f.getCanonicalPath() else canonicalPath = \"(none)\"\n )\n}\n\n/** Each call in the program, with the function it resolves to (none if unresolved). */\nquery predicate calls(int line, string call, string target) {\n exists(Call c | c.getFile().getBaseName() = \"main.rs\" |\n line = c.getLocation().getStartLine() and\n call = c.toString() and\n if exists(c.getStaticTarget())\n then target = c.getStaticTarget().getCanonicalPath()\n else target = \"(unresolved)\"\n )\n}\n\nselect 1\n```\n\nRun:\n```\ncodeql database create db --language=rust --source-root=.\ncodeql query run query/include-paths.ql --database=db --output=out.bqrs\ncodeql bqrs decode out.bqrs --format=csv --result-set=functions\ncodeql bqrs decode out.bqrs --format=csv --result-set=calls\n```\n\n**Expected:** `hidden` and `hidden_extern` have the canonical paths `toy_include::inner::hidden` and `toy_include::inner::hidden_extern`, and the calls on lines 2 and 4 resolve to them, like the control module's.\n\n**Actual:**\n```\n\"file\",\"name\",\"canonicalPath\"\n\"direct.rs\",\"visible\",\"toy_include::direct::visible\"\n\"direct.rs\",\"visible_extern\",\"toy_include::direct::visible_extern\"\n\"tree/inner/mod.rs\",\"hidden\",\"(none)\"\n\"tree/inner/mod.rs\",\"hidden_extern\",\"(none)\"\n\n\"line\",\"call\",\"target\"\n2,\"...::hidden(...)\",\"(unresolved)\"\n3,\"...::visible(...)\",\"toy_include::direct::visible\"\n4,\"...::hidden_extern(...)\",\"(unresolved)\"\n5,\"...::visible_extern(...)\",\"toy_include::direct::visible_extern\"\n```\n\n**Likely cause**\n\n- In the extractor, `text_range_for_node` (`rust/extractor/src/translate/base.rs`) keeps a node's location only if it maps into the file being extracted. Nodes produced by an `include!` map into the included file, so the `inner` module in the expansion reports `lib.rs` as its file.\n- `modImport0` in `codeql/rust/internal/PathResolution.qll` then looks for `mod inner;` relative to `lib.rs` (`src/inner.rs`, `src/inner/mod.rs`) instead of `src/tree/`.\n- `tree/mod.rs` is also extracted on its own, and there `mod inner;` does resolve, but that copy is not part of the crate's module tree.\n\nA possible fix: have the extractor give `include!`d nodes their locations in the included file (or record which file each `include!` includes), so that `mod` files are looked up next to the file that declares them.\n\n","author":{"url":"https://github.com/bdrodes","@type":"Person","name":"bdrodes"},"datePublished":"2026-11-04T01:42:23Z","url":"https://github.com/github/codeql/issues/23009"}
| react-profiling | 0 |
| react-import-map | react,react-dom,react-dom/client,react-dom/profiling,react-is,react-reconciler,react/compiler-runtime,react/jsx-dev-runtime,react/jsx-runtime,scheduler@d5750093facf |
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:62f011be-573d-9564-ecc2-0762b0859bd8 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | ECF8:1672EC:152F95A:1BC99E5:6AF890AC |
| html-safe-nonce | 8ab2f9daf2acb40b3e730b359fc8d3c91d95e121b08fa8d691fbab7958a7c775 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFQ0Y4OjE2NzJFQzoxNTJGOTVBOjFCQzk5RTU6NkFGODkwQUMiLCJ2aXNpdG9yX2lkIjoiNjU2MjEyMzY0Njc4NzY4NjU3MiIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | a6e0523f49f48cc33fc0a4dc68f2164123eb3438def4b027d1afc63000e34bb4 |
| hovercard-subject-tag | issue:6194559589 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/github/codeql/23009/issue_layout |
| twitter:image | https://opengraph.githubassets.com/7106eed8b2167fff905ea4d5669938c433f33cb9ef6ebc42e8e4e8d42ab136f5/github/codeql/issues/23009 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/7106eed8b2167fff905ea4d5669938c433f33cb9ef6ebc42e8e4e8d42ab136f5/github/codeql/issues/23009 |
| og:image:alt | Description of the issue When a crate's lib.rs brings in part of its module tree with include!("tree/mod.rs"), and that file declares pub mod inner;, CodeQL looks for inner next to lib.rs instead o... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | bdrodes |
| hostname | github.com |
| expected-hostname | github.com |
| None | 612d3e6ffd693e7ea8d9fcf452370995872baef31d825b1fedef704cd3d24ac7 |
| turbo-cache-control | no-preview |
| go-import | github.com/github/codeql git https://github.com/github/codeql.git |
| octolytics-dimension-user_id | 9919 |
| octolytics-dimension-user_login | github |
| octolytics-dimension-repository_id | 143040428 |
| octolytics-dimension-repository_nwo | github/codeql |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 143040428 |
| octolytics-dimension-repository_network_root_nwo | github/codeql |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 072e34035c13c31543fba9f025cbbbda4210dae4 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
| react-app-name | issues |
Links:
Viewport: width=device-width