| author | bors <bors@rust-lang.org> 2025-10-14 17:45:05 UTC |
| committer | bors <bors@rust-lang.org> 2025-10-14 17:45:05 UTC |
| log | 844264adda6f41ca6d0d61c4bcac0f263fc5072f |
| tree | ef873a1c2b817dab26151c4a355a6c7f71ec135c |
| parent | e100792918c8bd9e0cb830f96fc9b171e8892fa1 |
| parent | 7d93599fb13060cd1a57d53133b5962106849a26 |
`rust-analyzer` subtree update
Subtree update of `rust-analyzer` to https://github.com/rust-lang/rust-analyzer/commit/6d4b23478d8e5114e68278c64d4691ee6cf615e4.
Created using https://github.com/rust-lang/josh-sync.
r? `@ghost`219 files changed, 11101 insertions(+), 9715 deletions(-)
src/bootstrap/src/core/build_steps/tool.rs+1-1| ... | ... | @@ -1021,7 +1021,7 @@ impl RustAnalyzer { |
| 1021 | 1021 | } |
| 1022 | 1022 | |
| 1023 | 1023 | impl RustAnalyzer { |
| 1024 | pub const ALLOW_FEATURES: &'static str = "rustc_private,proc_macro_internals,proc_macro_diagnostic,proc_macro_span,proc_macro_span_shrink,proc_macro_def_site"; | |
| 1024 | pub const ALLOW_FEATURES: &'static str = "rustc_private,proc_macro_internals,proc_macro_diagnostic,proc_macro_span,proc_macro_span_shrink,proc_macro_def_site,new_zeroed_alloc"; | |
| 1025 | 1025 | } |
| 1026 | 1026 | |
| 1027 | 1027 | impl Step for RustAnalyzer { |
src/tools/rust-analyzer/.github/workflows/ci.yaml+1-1| ... | ... | @@ -293,7 +293,7 @@ jobs: |
| 293 | 293 | timeout-minutes: 10 |
| 294 | 294 | env: |
| 295 | 295 | FORCE_COLOR: 1 |
| 296 | TYPOS_VERSION: v1.28.3 | |
| 296 | TYPOS_VERSION: v1.38.1 | |
| 297 | 297 | steps: |
| 298 | 298 | - name: download typos |
| 299 | 299 | run: curl -LsSf https://github.com/crate-ci/typos/releases/download/$TYPOS_VERSION/typos-$TYPOS_VERSION-x86_64-unknown-linux-musl.tar.gz | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin |
src/tools/rust-analyzer/.github/workflows/release.yaml+2-2| ... | ... | @@ -16,7 +16,7 @@ env: |
| 16 | 16 | RUSTFLAGS: "-D warnings -W unreachable-pub" |
| 17 | 17 | RUSTUP_MAX_RETRIES: 10 |
| 18 | 18 | FETCH_DEPTH: 0 # pull in the tags for the version string |
| 19 | MACOSX_DEPLOYMENT_TARGET: 13.0 | |
| 19 | MACOSX_DEPLOYMENT_TARGET: 14.0 | |
| 20 | 20 | ZIG_VERSION: 0.13.0 |
| 21 | 21 | ZIGBUILD_VERSION: 0.19.8 |
| 22 | 22 | |
| ... | ... | @@ -52,7 +52,7 @@ jobs: |
| 52 | 52 | target: arm-unknown-linux-gnueabihf |
| 53 | 53 | zig_target: arm-unknown-linux-gnueabihf.2.28 |
| 54 | 54 | code-target: linux-armhf |
| 55 | - os: macos-13 | |
| 55 | - os: macos-14 | |
| 56 | 56 | target: x86_64-apple-darwin |
| 57 | 57 | code-target: darwin-x64 |
| 58 | 58 | pgo: clap-rs/clap@v4.5.36 |
src/tools/rust-analyzer/.typos.toml+1| ... | ... | @@ -32,6 +32,7 @@ makro = "makro" |
| 32 | 32 | trivias = "trivias" |
| 33 | 33 | thir = "thir" |
| 34 | 34 | jod = "jod" |
| 35 | tructure = "tructure" | |
| 35 | 36 | |
| 36 | 37 | [default.extend-identifiers] |
| 37 | 38 | anc = "anc" |
src/tools/rust-analyzer/Cargo.lock+251-274| ... | ... | @@ -31,15 +31,15 @@ checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" |
| 31 | 31 | |
| 32 | 32 | [[package]] |
| 33 | 33 | name = "anyhow" |
| 34 | version = "1.0.98" | |
| 34 | version = "1.0.100" | |
| 35 | 35 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 36 | checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" | |
| 36 | checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" | |
| 37 | 37 | |
| 38 | 38 | [[package]] |
| 39 | 39 | name = "arbitrary" |
| 40 | version = "1.4.1" | |
| 40 | version = "1.4.2" | |
| 41 | 41 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 42 | checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" | |
| 42 | checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" | |
| 43 | 43 | dependencies = [ |
| 44 | 44 | "derive_arbitrary", |
| 45 | 45 | ] |
| ... | ... | @@ -61,9 +61,9 @@ dependencies = [ |
| 61 | 61 | |
| 62 | 62 | [[package]] |
| 63 | 63 | name = "autocfg" |
| 64 | version = "1.4.0" | |
| 64 | version = "1.5.0" | |
| 65 | 65 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 66 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" | |
| 66 | checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" | |
| 67 | 67 | |
| 68 | 68 | [[package]] |
| 69 | 69 | name = "backtrace" |
| ... | ... | @@ -115,9 +115,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" |
| 115 | 115 | |
| 116 | 116 | [[package]] |
| 117 | 117 | name = "bitflags" |
| 118 | version = "2.9.1" | |
| 118 | version = "2.9.4" | |
| 119 | 119 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 120 | checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" | |
| 120 | checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" | |
| 121 | 121 | |
| 122 | 122 | [[package]] |
| 123 | 123 | name = "borsh" |
| ... | ... | @@ -130,9 +130,9 @@ dependencies = [ |
| 130 | 130 | |
| 131 | 131 | [[package]] |
| 132 | 132 | name = "boxcar" |
| 133 | version = "0.2.13" | |
| 133 | version = "0.2.14" | |
| 134 | 134 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 135 | checksum = "26c4925bc979b677330a8c7fe7a8c94af2dbb4a2d37b4a20a80d884400f46baa" | |
| 135 | checksum = "36f64beae40a84da1b4b26ff2761a5b895c12adc41dc25aaee1c4f2bbfe97a6e" | |
| 136 | 136 | |
| 137 | 137 | [[package]] |
| 138 | 138 | name = "byteorder" |
| ... | ... | @@ -142,11 +142,11 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" |
| 142 | 142 | |
| 143 | 143 | [[package]] |
| 144 | 144 | name = "camino" |
| 145 | version = "1.1.10" | |
| 145 | version = "1.2.0" | |
| 146 | 146 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 147 | checksum = "0da45bc31171d8d6960122e222a67740df867c1dd53b4d51caa297084c185cab" | |
| 147 | checksum = "e1de8bc0aa9e9385ceb3bf0c152e3a9b9544f6c4a912c8ae504e80c1f0368603" | |
| 148 | 148 | dependencies = [ |
| 149 | "serde", | |
| 149 | "serde_core", | |
| 150 | 150 | ] |
| 151 | 151 | |
| 152 | 152 | [[package]] |
| ... | ... | @@ -184,7 +184,7 @@ dependencies = [ |
| 184 | 184 | "serde", |
| 185 | 185 | "serde-untagged", |
| 186 | 186 | "serde-value", |
| 187 | "thiserror 2.0.12", | |
| 187 | "thiserror 2.0.16", | |
| 188 | 188 | "toml", |
| 189 | 189 | "unicode-xid", |
| 190 | 190 | "url", |
| ... | ... | @@ -202,7 +202,7 @@ dependencies = [ |
| 202 | 202 | "semver", |
| 203 | 203 | "serde", |
| 204 | 204 | "serde_json", |
| 205 | "thiserror 2.0.12", | |
| 205 | "thiserror 2.0.16", | |
| 206 | 206 | ] |
| 207 | 207 | |
| 208 | 208 | [[package]] |
| ... | ... | @@ -217,15 +217,16 @@ dependencies = [ |
| 217 | 217 | "semver", |
| 218 | 218 | "serde", |
| 219 | 219 | "serde_json", |
| 220 | "thiserror 2.0.12", | |
| 220 | "thiserror 2.0.16", | |
| 221 | 221 | ] |
| 222 | 222 | |
| 223 | 223 | [[package]] |
| 224 | 224 | name = "cc" |
| 225 | version = "1.2.26" | |
| 225 | version = "1.2.38" | |
| 226 | 226 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 227 | checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" | |
| 227 | checksum = "80f41ae168f955c12fb8960b057d70d0ca153fb83182b57d86380443527be7e9" | |
| 228 | 228 | dependencies = [ |
| 229 | "find-msvc-tools", | |
| 229 | 230 | "shlex", |
| 230 | 231 | ] |
| 231 | 232 | |
| ... | ... | @@ -234,7 +235,6 @@ name = "cfg" |
| 234 | 235 | version = "0.0.0" |
| 235 | 236 | dependencies = [ |
| 236 | 237 | "arbitrary", |
| 237 | "derive_arbitrary", | |
| 238 | 238 | "expect-test", |
| 239 | 239 | "intern", |
| 240 | 240 | "oorandom", |
| ... | ... | @@ -247,9 +247,9 @@ dependencies = [ |
| 247 | 247 | |
| 248 | 248 | [[package]] |
| 249 | 249 | name = "cfg-if" |
| 250 | version = "1.0.1" | |
| 250 | version = "1.0.3" | |
| 251 | 251 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 252 | checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" | |
| 252 | checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" | |
| 253 | 253 | |
| 254 | 254 | [[package]] |
| 255 | 255 | name = "cfg_aliases" |
| ... | ... | @@ -275,24 +275,24 @@ version = "0.104.0" |
| 275 | 275 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 276 | 276 | checksum = "7047a516de16226cd17344d41a319d0ea1064bf9e60bd612ab341ab4a34bbfa8" |
| 277 | 277 | dependencies = [ |
| 278 | "bitflags 2.9.1", | |
| 278 | "bitflags 2.9.4", | |
| 279 | 279 | "chalk-derive", |
| 280 | 280 | ] |
| 281 | 281 | |
| 282 | 282 | [[package]] |
| 283 | 283 | name = "clap" |
| 284 | version = "4.5.42" | |
| 284 | version = "4.5.48" | |
| 285 | 285 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 286 | checksum = "ed87a9d530bb41a67537289bafcac159cb3ee28460e0a4571123d2a778a6a882" | |
| 286 | checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae" | |
| 287 | 287 | dependencies = [ |
| 288 | 288 | "clap_builder", |
| 289 | 289 | ] |
| 290 | 290 | |
| 291 | 291 | [[package]] |
| 292 | 292 | name = "clap_builder" |
| 293 | version = "4.5.42" | |
| 293 | version = "4.5.48" | |
| 294 | 294 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 295 | checksum = "64f4f3f3c77c94aff3c7e9aac9a2ca1974a5adf392a8bb751e827d6d127ab966" | |
| 295 | checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9" | |
| 296 | 296 | dependencies = [ |
| 297 | 297 | "anstyle", |
| 298 | 298 | "clap_lex", |
| ... | ... | @@ -310,7 +310,7 @@ version = "0.3.0" |
| 310 | 310 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 311 | 311 | checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" |
| 312 | 312 | dependencies = [ |
| 313 | "thiserror 2.0.12", | |
| 313 | "thiserror 2.0.16", | |
| 314 | 314 | ] |
| 315 | 315 | |
| 316 | 316 | [[package]] |
| ... | ... | @@ -321,15 +321,15 @@ checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636" |
| 321 | 321 | |
| 322 | 322 | [[package]] |
| 323 | 323 | name = "cov-mark" |
| 324 | version = "2.0.0" | |
| 324 | version = "2.1.0" | |
| 325 | 325 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 326 | checksum = "0570650661aa447e7335f1d5e4f499d8e58796e617bedc9267d971e51c8b49d4" | |
| 326 | checksum = "3f1d92727879fb4f24cec33a35e3bff74035541326cbc12ad44ba8886d1927b0" | |
| 327 | 327 | |
| 328 | 328 | [[package]] |
| 329 | 329 | name = "crc32fast" |
| 330 | version = "1.4.2" | |
| 330 | version = "1.5.0" | |
| 331 | 331 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 332 | checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" | |
| 332 | checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" | |
| 333 | 333 | dependencies = [ |
| 334 | 334 | "cfg-if", |
| 335 | 335 | ] |
| ... | ... | @@ -385,12 +385,13 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" |
| 385 | 385 | |
| 386 | 386 | [[package]] |
| 387 | 387 | name = "ctrlc" |
| 388 | version = "3.4.7" | |
| 388 | version = "3.5.0" | |
| 389 | 389 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 390 | checksum = "46f93780a459b7d656ef7f071fe699c4d3d2cb201c4b24d085b6ddc505276e73" | |
| 390 | checksum = "881c5d0a13b2f1498e2306e82cbada78390e152d4b1378fb28a84f4dcd0dc4f3" | |
| 391 | 391 | dependencies = [ |
| 392 | "dispatch", | |
| 392 | 393 | "nix", |
| 393 | "windows-sys 0.59.0", | |
| 394 | "windows-sys 0.61.0", | |
| 394 | 395 | ] |
| 395 | 396 | |
| 396 | 397 | [[package]] |
| ... | ... | @@ -409,18 +410,18 @@ dependencies = [ |
| 409 | 410 | |
| 410 | 411 | [[package]] |
| 411 | 412 | name = "deranged" |
| 412 | version = "0.4.0" | |
| 413 | version = "0.5.3" | |
| 413 | 414 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 414 | checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" | |
| 415 | checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc" | |
| 415 | 416 | dependencies = [ |
| 416 | 417 | "powerfmt", |
| 417 | 418 | ] |
| 418 | 419 | |
| 419 | 420 | [[package]] |
| 420 | 421 | name = "derive-where" |
| 421 | version = "1.5.0" | |
| 422 | version = "1.6.0" | |
| 422 | 423 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 423 | checksum = "510c292c8cf384b1a340b816a9a6cf2599eb8f566a44949024af88418000c50b" | |
| 424 | checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f" | |
| 424 | 425 | dependencies = [ |
| 425 | 426 | "proc-macro2", |
| 426 | 427 | "quote", |
| ... | ... | @@ -429,9 +430,9 @@ dependencies = [ |
| 429 | 430 | |
| 430 | 431 | [[package]] |
| 431 | 432 | name = "derive_arbitrary" |
| 432 | version = "1.4.1" | |
| 433 | version = "1.4.2" | |
| 433 | 434 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 434 | checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" | |
| 435 | checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" | |
| 435 | 436 | dependencies = [ |
| 436 | 437 | "proc-macro2", |
| 437 | 438 | "quote", |
| ... | ... | @@ -456,9 +457,15 @@ dependencies = [ |
| 456 | 457 | "libc", |
| 457 | 458 | "option-ext", |
| 458 | 459 | "redox_users", |
| 459 | "windows-sys 0.60.2", | |
| 460 | "windows-sys 0.61.0", | |
| 460 | 461 | ] |
| 461 | 462 | |
| 463 | [[package]] | |
| 464 | name = "dispatch" | |
| 465 | version = "0.2.0" | |
| 466 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 467 | checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" | |
| 468 | ||
| 462 | 469 | [[package]] |
| 463 | 470 | name = "displaydoc" |
| 464 | 471 | version = "0.2.5" |
| ... | ... | @@ -515,11 +522,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" |
| 515 | 522 | |
| 516 | 523 | [[package]] |
| 517 | 524 | name = "erased-serde" |
| 518 | version = "0.4.6" | |
| 525 | version = "0.4.8" | |
| 519 | 526 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 520 | checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7" | |
| 527 | checksum = "259d404d09818dec19332e31d94558aeb442fea04c817006456c24b5460bbd4b" | |
| 521 | 528 | dependencies = [ |
| 522 | 529 | "serde", |
| 530 | "serde_core", | |
| 523 | 531 | "typeid", |
| 524 | 532 | ] |
| 525 | 533 | |
| ... | ... | @@ -534,16 +542,10 @@ dependencies = [ |
| 534 | 542 | ] |
| 535 | 543 | |
| 536 | 544 | [[package]] |
| 537 | name = "filetime" | |
| 538 | version = "0.2.25" | |
| 545 | name = "find-msvc-tools" | |
| 546 | version = "0.1.2" | |
| 539 | 547 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 540 | checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" | |
| 541 | dependencies = [ | |
| 542 | "cfg-if", | |
| 543 | "libc", | |
| 544 | "libredox", | |
| 545 | "windows-sys 0.59.0", | |
| 546 | ] | |
| 548 | checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959" | |
| 547 | 549 | |
| 548 | 550 | [[package]] |
| 549 | 551 | name = "fixedbitset" |
| ... | ... | @@ -569,9 +571,9 @@ checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" |
| 569 | 571 | |
| 570 | 572 | [[package]] |
| 571 | 573 | name = "form_urlencoded" |
| 572 | version = "1.2.1" | |
| 574 | version = "1.2.2" | |
| 573 | 575 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 574 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" | |
| 576 | checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" | |
| 575 | 577 | dependencies = [ |
| 576 | 578 | "percent-encoding", |
| 577 | 579 | ] |
| ... | ... | @@ -625,22 +627,28 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" |
| 625 | 627 | |
| 626 | 628 | [[package]] |
| 627 | 629 | name = "hashbrown" |
| 628 | version = "0.15.4" | |
| 630 | version = "0.15.5" | |
| 629 | 631 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 630 | checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" | |
| 632 | checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" | |
| 631 | 633 | dependencies = [ |
| 632 | 634 | "allocator-api2", |
| 633 | 635 | "equivalent", |
| 634 | 636 | "foldhash", |
| 635 | 637 | ] |
| 636 | 638 | |
| 639 | [[package]] | |
| 640 | name = "hashbrown" | |
| 641 | version = "0.16.0" | |
| 642 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 643 | checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" | |
| 644 | ||
| 637 | 645 | [[package]] |
| 638 | 646 | name = "hashlink" |
| 639 | 647 | version = "0.10.0" |
| 640 | 648 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 641 | 649 | checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" |
| 642 | 650 | dependencies = [ |
| 643 | "hashbrown 0.15.4", | |
| 651 | "hashbrown 0.15.5", | |
| 644 | 652 | ] |
| 645 | 653 | |
| 646 | 654 | [[package]] |
| ... | ... | @@ -700,7 +708,7 @@ version = "0.0.0" |
| 700 | 708 | dependencies = [ |
| 701 | 709 | "arrayvec", |
| 702 | 710 | "base-db", |
| 703 | "bitflags 2.9.1", | |
| 711 | "bitflags 2.9.4", | |
| 704 | 712 | "cfg", |
| 705 | 713 | "cov-mark", |
| 706 | 714 | "drop_bomb", |
| ... | ... | @@ -767,7 +775,7 @@ version = "0.0.0" |
| 767 | 775 | dependencies = [ |
| 768 | 776 | "arrayvec", |
| 769 | 777 | "base-db", |
| 770 | "bitflags 2.9.1", | |
| 778 | "bitflags 2.9.4", | |
| 771 | 779 | "chalk-derive", |
| 772 | 780 | "chalk-ir", |
| 773 | 781 | "cov-mark", |
| ... | ... | @@ -780,6 +788,7 @@ dependencies = [ |
| 780 | 788 | "intern", |
| 781 | 789 | "itertools", |
| 782 | 790 | "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", |
| 791 | "macros", | |
| 783 | 792 | "oorandom", |
| 784 | 793 | "petgraph", |
| 785 | 794 | "project-model", |
| ... | ... | @@ -980,7 +989,7 @@ version = "0.0.0" |
| 980 | 989 | dependencies = [ |
| 981 | 990 | "arrayvec", |
| 982 | 991 | "base-db", |
| 983 | "bitflags 2.9.1", | |
| 992 | "bitflags 2.9.4", | |
| 984 | 993 | "cov-mark", |
| 985 | 994 | "crossbeam-channel", |
| 986 | 995 | "either", |
| ... | ... | @@ -1047,9 +1056,9 @@ dependencies = [ |
| 1047 | 1056 | |
| 1048 | 1057 | [[package]] |
| 1049 | 1058 | name = "idna" |
| 1050 | version = "1.0.3" | |
| 1059 | version = "1.1.0" | |
| 1051 | 1060 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1052 | checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" | |
| 1061 | checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" | |
| 1053 | 1062 | dependencies = [ |
| 1054 | 1063 | "idna_adapter", |
| 1055 | 1064 | "smallvec", |
| ... | ... | @@ -1068,13 +1077,14 @@ dependencies = [ |
| 1068 | 1077 | |
| 1069 | 1078 | [[package]] |
| 1070 | 1079 | name = "indexmap" |
| 1071 | version = "2.9.0" | |
| 1080 | version = "2.11.4" | |
| 1072 | 1081 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1073 | checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" | |
| 1082 | checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" | |
| 1074 | 1083 | dependencies = [ |
| 1075 | 1084 | "equivalent", |
| 1076 | "hashbrown 0.15.4", | |
| 1085 | "hashbrown 0.16.0", | |
| 1077 | 1086 | "serde", |
| 1087 | "serde_core", | |
| 1078 | 1088 | ] |
| 1079 | 1089 | |
| 1080 | 1090 | [[package]] |
| ... | ... | @@ -1083,7 +1093,7 @@ version = "0.11.0" |
| 1083 | 1093 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1084 | 1094 | checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" |
| 1085 | 1095 | dependencies = [ |
| 1086 | "bitflags 2.9.1", | |
| 1096 | "bitflags 2.9.4", | |
| 1087 | 1097 | "inotify-sys", |
| 1088 | 1098 | "libc", |
| 1089 | 1099 | ] |
| ... | ... | @@ -1116,6 +1126,15 @@ dependencies = [ |
| 1116 | 1126 | "memoffset", |
| 1117 | 1127 | ] |
| 1118 | 1128 | |
| 1129 | [[package]] | |
| 1130 | name = "inventory" | |
| 1131 | version = "0.3.21" | |
| 1132 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1133 | checksum = "bc61209c082fbeb19919bee74b176221b27223e27b65d781eb91af24eb1fb46e" | |
| 1134 | dependencies = [ | |
| 1135 | "rustversion", | |
| 1136 | ] | |
| 1137 | ||
| 1119 | 1138 | [[package]] |
| 1120 | 1139 | name = "itertools" |
| 1121 | 1140 | version = "0.14.0" |
| ... | ... | @@ -1175,25 +1194,25 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" |
| 1175 | 1194 | |
| 1176 | 1195 | [[package]] |
| 1177 | 1196 | name = "libc" |
| 1178 | version = "0.2.172" | |
| 1197 | version = "0.2.175" | |
| 1179 | 1198 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1180 | checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" | |
| 1199 | checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" | |
| 1181 | 1200 | |
| 1182 | 1201 | [[package]] |
| 1183 | 1202 | name = "libloading" |
| 1184 | version = "0.8.8" | |
| 1203 | version = "0.8.9" | |
| 1185 | 1204 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1186 | checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" | |
| 1205 | checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" | |
| 1187 | 1206 | dependencies = [ |
| 1188 | 1207 | "cfg-if", |
| 1189 | "windows-targets 0.53.2", | |
| 1208 | "windows-link 0.2.0", | |
| 1190 | 1209 | ] |
| 1191 | 1210 | |
| 1192 | 1211 | [[package]] |
| 1193 | 1212 | name = "libmimalloc-sys" |
| 1194 | version = "0.1.42" | |
| 1213 | version = "0.1.44" | |
| 1195 | 1214 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1196 | checksum = "ec9d6fac27761dabcd4ee73571cdb06b7022dc99089acbe5435691edffaac0f4" | |
| 1215 | checksum = "667f4fec20f29dfc6bc7357c582d91796c169ad7e2fce709468aefeb2c099870" | |
| 1197 | 1216 | dependencies = [ |
| 1198 | 1217 | "cc", |
| 1199 | 1218 | "libc", |
| ... | ... | @@ -1201,13 +1220,12 @@ dependencies = [ |
| 1201 | 1220 | |
| 1202 | 1221 | [[package]] |
| 1203 | 1222 | name = "libredox" |
| 1204 | version = "0.1.3" | |
| 1223 | version = "0.1.10" | |
| 1205 | 1224 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1206 | checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" | |
| 1225 | checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" | |
| 1207 | 1226 | dependencies = [ |
| 1208 | "bitflags 2.9.1", | |
| 1227 | "bitflags 2.9.4", | |
| 1209 | 1228 | "libc", |
| 1210 | "redox_syscall", | |
| 1211 | 1229 | ] |
| 1212 | 1230 | |
| 1213 | 1231 | [[package]] |
| ... | ... | @@ -1266,9 +1284,9 @@ dependencies = [ |
| 1266 | 1284 | |
| 1267 | 1285 | [[package]] |
| 1268 | 1286 | name = "log" |
| 1269 | version = "0.4.27" | |
| 1287 | version = "0.4.28" | |
| 1270 | 1288 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1271 | checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" | |
| 1289 | checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" | |
| 1272 | 1290 | |
| 1273 | 1291 | [[package]] |
| 1274 | 1292 | name = "lsp-server" |
| ... | ... | @@ -1312,6 +1330,16 @@ dependencies = [ |
| 1312 | 1330 | "url", |
| 1313 | 1331 | ] |
| 1314 | 1332 | |
| 1333 | [[package]] | |
| 1334 | name = "macros" | |
| 1335 | version = "0.0.0" | |
| 1336 | dependencies = [ | |
| 1337 | "proc-macro2", | |
| 1338 | "quote", | |
| 1339 | "syn", | |
| 1340 | "synstructure", | |
| 1341 | ] | |
| 1342 | ||
| 1315 | 1343 | [[package]] |
| 1316 | 1344 | name = "mbe" |
| 1317 | 1345 | version = "0.0.0" |
| ... | ... | @@ -1340,9 +1368,9 @@ checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" |
| 1340 | 1368 | |
| 1341 | 1369 | [[package]] |
| 1342 | 1370 | name = "memmap2" |
| 1343 | version = "0.9.5" | |
| 1371 | version = "0.9.8" | |
| 1344 | 1372 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1345 | checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" | |
| 1373 | checksum = "843a98750cd611cc2965a8213b53b43e715f13c37a9e096c6408e69990961db7" | |
| 1346 | 1374 | dependencies = [ |
| 1347 | 1375 | "libc", |
| 1348 | 1376 | ] |
| ... | ... | @@ -1358,9 +1386,9 @@ dependencies = [ |
| 1358 | 1386 | |
| 1359 | 1387 | [[package]] |
| 1360 | 1388 | name = "mimalloc" |
| 1361 | version = "0.1.46" | |
| 1389 | version = "0.1.48" | |
| 1362 | 1390 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1363 | checksum = "995942f432bbb4822a7e9c3faa87a695185b0d09273ba85f097b54f4e458f2af" | |
| 1391 | checksum = "e1ee66a4b64c74f4ef288bcbb9192ad9c3feaad75193129ac8509af543894fd8" | |
| 1364 | 1392 | dependencies = [ |
| 1365 | 1393 | "libmimalloc-sys", |
| 1366 | 1394 | ] |
| ... | ... | @@ -1388,11 +1416,11 @@ dependencies = [ |
| 1388 | 1416 | |
| 1389 | 1417 | [[package]] |
| 1390 | 1418 | name = "miow" |
| 1391 | version = "0.6.0" | |
| 1419 | version = "0.6.1" | |
| 1392 | 1420 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1393 | checksum = "359f76430b20a79f9e20e115b3428614e654f04fab314482fc0fda0ebd3c6044" | |
| 1421 | checksum = "536bfad37a309d62069485248eeaba1e8d9853aaf951caaeaed0585a95346f08" | |
| 1394 | 1422 | dependencies = [ |
| 1395 | "windows-sys 0.48.0", | |
| 1423 | "windows-sys 0.61.0", | |
| 1396 | 1424 | ] |
| 1397 | 1425 | |
| 1398 | 1426 | [[package]] |
| ... | ... | @@ -1401,7 +1429,7 @@ version = "0.30.1" |
| 1401 | 1429 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1402 | 1430 | checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" |
| 1403 | 1431 | dependencies = [ |
| 1404 | "bitflags 2.9.1", | |
| 1432 | "bitflags 2.9.4", | |
| 1405 | 1433 | "cfg-if", |
| 1406 | 1434 | "cfg_aliases", |
| 1407 | 1435 | "libc", |
| ... | ... | @@ -1415,12 +1443,11 @@ checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" |
| 1415 | 1443 | |
| 1416 | 1444 | [[package]] |
| 1417 | 1445 | name = "notify" |
| 1418 | version = "8.0.0" | |
| 1446 | version = "8.2.0" | |
| 1419 | 1447 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1420 | checksum = "2fee8403b3d66ac7b26aee6e40a897d85dc5ce26f44da36b8b73e987cc52e943" | |
| 1448 | checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" | |
| 1421 | 1449 | dependencies = [ |
| 1422 | "bitflags 2.9.1", | |
| 1423 | "filetime", | |
| 1450 | "bitflags 2.9.4", | |
| 1424 | 1451 | "fsevent-sys", |
| 1425 | 1452 | "inotify", |
| 1426 | 1453 | "kqueue", |
| ... | ... | @@ -1429,7 +1456,7 @@ dependencies = [ |
| 1429 | 1456 | "mio", |
| 1430 | 1457 | "notify-types", |
| 1431 | 1458 | "walkdir", |
| 1432 | "windows-sys 0.59.0", | |
| 1459 | "windows-sys 0.60.2", | |
| 1433 | 1460 | ] |
| 1434 | 1461 | |
| 1435 | 1462 | [[package]] |
| ... | ... | @@ -1517,16 +1544,6 @@ dependencies = [ |
| 1517 | 1544 | "num-traits", |
| 1518 | 1545 | ] |
| 1519 | 1546 | |
| 1520 | [[package]] | |
| 1521 | name = "papaya" | |
| 1522 | version = "0.2.3" | |
| 1523 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1524 | checksum = "f92dd0b07c53a0a0c764db2ace8c541dc47320dad97c2200c2a637ab9dd2328f" | |
| 1525 | dependencies = [ | |
| 1526 | "equivalent", | |
| 1527 | "seize", | |
| 1528 | ] | |
| 1529 | ||
| 1530 | 1547 | [[package]] |
| 1531 | 1548 | name = "parking_lot" |
| 1532 | 1549 | version = "0.12.4" |
| ... | ... | @@ -1578,9 +1595,9 @@ dependencies = [ |
| 1578 | 1595 | |
| 1579 | 1596 | [[package]] |
| 1580 | 1597 | name = "percent-encoding" |
| 1581 | version = "2.3.1" | |
| 1598 | version = "2.3.2" | |
| 1582 | 1599 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1583 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" | |
| 1600 | checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" | |
| 1584 | 1601 | |
| 1585 | 1602 | [[package]] |
| 1586 | 1603 | name = "perf-event" |
| ... | ... | @@ -1608,7 +1625,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1608 | 1625 | checksum = "54acf3a685220b533e437e264e4d932cfbdc4cc7ec0cd232ed73c08d03b8a7ca" |
| 1609 | 1626 | dependencies = [ |
| 1610 | 1627 | "fixedbitset", |
| 1611 | "hashbrown 0.15.4", | |
| 1628 | "hashbrown 0.15.5", | |
| 1612 | 1629 | "indexmap", |
| 1613 | 1630 | ] |
| 1614 | 1631 | |
| ... | ... | @@ -1637,9 +1654,9 @@ dependencies = [ |
| 1637 | 1654 | |
| 1638 | 1655 | [[package]] |
| 1639 | 1656 | name = "potential_utf" |
| 1640 | version = "0.1.2" | |
| 1657 | version = "0.1.3" | |
| 1641 | 1658 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1642 | checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" | |
| 1659 | checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" | |
| 1643 | 1660 | dependencies = [ |
| 1644 | 1661 | "zerovec", |
| 1645 | 1662 | ] |
| ... | ... | @@ -1706,9 +1723,9 @@ dependencies = [ |
| 1706 | 1723 | |
| 1707 | 1724 | [[package]] |
| 1708 | 1725 | name = "proc-macro2" |
| 1709 | version = "1.0.95" | |
| 1726 | version = "1.0.101" | |
| 1710 | 1727 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1711 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" | |
| 1728 | checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" | |
| 1712 | 1729 | dependencies = [ |
| 1713 | 1730 | "unicode-ident", |
| 1714 | 1731 | ] |
| ... | ... | @@ -1788,7 +1805,7 @@ version = "0.9.6" |
| 1788 | 1805 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1789 | 1806 | checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" |
| 1790 | 1807 | dependencies = [ |
| 1791 | "bitflags 2.9.1", | |
| 1808 | "bitflags 2.9.4", | |
| 1792 | 1809 | "memchr", |
| 1793 | 1810 | "unicase", |
| 1794 | 1811 | ] |
| ... | ... | @@ -1825,11 +1842,11 @@ dependencies = [ |
| 1825 | 1842 | |
| 1826 | 1843 | [[package]] |
| 1827 | 1844 | name = "ra-ap-rustc_abi" |
| 1828 | version = "0.132.0" | |
| 1845 | version = "0.133.0" | |
| 1829 | 1846 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1830 | checksum = "597bb303548ddcca3a2eb05af254508aaf39cf334d4350bb5da51de1eb728859" | |
| 1847 | checksum = "c063a7fef3c49d03837ee9a5d988aad83630c3460b03b32355c279d3fafa7d07" | |
| 1831 | 1848 | dependencies = [ |
| 1832 | "bitflags 2.9.1", | |
| 1849 | "bitflags 2.9.4", | |
| 1833 | 1850 | "ra-ap-rustc_hashes", |
| 1834 | 1851 | "ra-ap-rustc_index", |
| 1835 | 1852 | "tracing", |
| ... | ... | @@ -1837,24 +1854,24 @@ dependencies = [ |
| 1837 | 1854 | |
| 1838 | 1855 | [[package]] |
| 1839 | 1856 | name = "ra-ap-rustc_ast_ir" |
| 1840 | version = "0.132.0" | |
| 1857 | version = "0.133.0" | |
| 1841 | 1858 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1842 | checksum = "78982b4e4432ee4b938e47bb5c8f1a5a5a88c27c782f193aefcc12a3250bd2e2" | |
| 1859 | checksum = "a210dbd77e794b33ff17d2d15750dee44eeabd1330685d69a6bad272d515892a" | |
| 1843 | 1860 | |
| 1844 | 1861 | [[package]] |
| 1845 | 1862 | name = "ra-ap-rustc_hashes" |
| 1846 | version = "0.132.0" | |
| 1863 | version = "0.133.0" | |
| 1847 | 1864 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1848 | checksum = "2f7f33a422f724cc1ab43972cdd76a556b17fc256f301d23be620adfc8351df7" | |
| 1865 | checksum = "dea031ea45bb92cd346ed222b35c812e355f304183096ee91bb437b3813c6348" | |
| 1849 | 1866 | dependencies = [ |
| 1850 | 1867 | "rustc-stable-hash", |
| 1851 | 1868 | ] |
| 1852 | 1869 | |
| 1853 | 1870 | [[package]] |
| 1854 | 1871 | name = "ra-ap-rustc_index" |
| 1855 | version = "0.132.0" | |
| 1872 | version = "0.133.0" | |
| 1856 | 1873 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1857 | checksum = "8a6006023c8be18c3ac225d69c1b42f55b3f597f3db03fb40764b4cf1454fd13" | |
| 1874 | checksum = "db0114f842b20cba9beb2d9002ca31ae706b47f28ba2d6a49cbf9fd65fa72b9d" | |
| 1858 | 1875 | dependencies = [ |
| 1859 | 1876 | "ra-ap-rustc_index_macros", |
| 1860 | 1877 | "smallvec", |
| ... | ... | @@ -1862,9 +1879,9 @@ dependencies = [ |
| 1862 | 1879 | |
| 1863 | 1880 | [[package]] |
| 1864 | 1881 | name = "ra-ap-rustc_index_macros" |
| 1865 | version = "0.132.0" | |
| 1882 | version = "0.133.0" | |
| 1866 | 1883 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1867 | checksum = "9217c29f7fcc30d07ed13a62262144f665410ef1460202599ae924f9ae47ad78" | |
| 1884 | checksum = "bc738a5bb06fb3893725fbeb3640ff1822bb2aae3f416c4a49f0a706ba89d1cc" | |
| 1868 | 1885 | dependencies = [ |
| 1869 | 1886 | "proc-macro2", |
| 1870 | 1887 | "quote", |
| ... | ... | @@ -1873,9 +1890,9 @@ dependencies = [ |
| 1873 | 1890 | |
| 1874 | 1891 | [[package]] |
| 1875 | 1892 | name = "ra-ap-rustc_lexer" |
| 1876 | version = "0.132.0" | |
| 1893 | version = "0.133.0" | |
| 1877 | 1894 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1878 | checksum = "573ad4f5da620e8ba1849d8862866abd7bc765c3d81cb2488c3ecbef33ce2c69" | |
| 1895 | checksum = "31c35b3d812cfc101d3f534640c13f24c0ec50ee2249685e4c20b2868609c9ee" | |
| 1879 | 1896 | dependencies = [ |
| 1880 | 1897 | "memchr", |
| 1881 | 1898 | "unicode-properties", |
| ... | ... | @@ -1884,9 +1901,9 @@ dependencies = [ |
| 1884 | 1901 | |
| 1885 | 1902 | [[package]] |
| 1886 | 1903 | name = "ra-ap-rustc_next_trait_solver" |
| 1887 | version = "0.132.0" | |
| 1904 | version = "0.133.0" | |
| 1888 | 1905 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1889 | checksum = "0d42b095b99e988aeb94622ae62ebda4b7de55d7d98846eec352b8a5a2b8a858" | |
| 1906 | checksum = "e7b0fa6fb8e0717ebd0836f8de4a6efc954fca1a8652980fd2584dbe448c7d95" | |
| 1890 | 1907 | dependencies = [ |
| 1891 | 1908 | "derive-where", |
| 1892 | 1909 | "ra-ap-rustc_index", |
| ... | ... | @@ -1897,9 +1914,9 @@ dependencies = [ |
| 1897 | 1914 | |
| 1898 | 1915 | [[package]] |
| 1899 | 1916 | name = "ra-ap-rustc_parse_format" |
| 1900 | version = "0.132.0" | |
| 1917 | version = "0.133.0" | |
| 1901 | 1918 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1902 | checksum = "a21b4e95cb45f840c172493c05f5b9471cf44adb2eccf95d76a0d76e88007870" | |
| 1919 | checksum = "33d01bad23470cc749ef607476890aabcc8993ca3ef87d4241d0f6a08c6f9402" | |
| 1903 | 1920 | dependencies = [ |
| 1904 | 1921 | "ra-ap-rustc_lexer", |
| 1905 | 1922 | "rustc-literal-escaper 0.0.5", |
| ... | ... | @@ -1907,9 +1924,9 @@ dependencies = [ |
| 1907 | 1924 | |
| 1908 | 1925 | [[package]] |
| 1909 | 1926 | name = "ra-ap-rustc_pattern_analysis" |
| 1910 | version = "0.132.0" | |
| 1927 | version = "0.133.0" | |
| 1911 | 1928 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1912 | checksum = "b6aeacef1248066f7b67e7296ef135eeab6446d5d2a5c7f02b8d7b747b41e39b" | |
| 1929 | checksum = "8a181cf7943dc16e888046584d6172be95818811b25d695dbacbb4dd71973cc3" | |
| 1913 | 1930 | dependencies = [ |
| 1914 | 1931 | "ra-ap-rustc_index", |
| 1915 | 1932 | "rustc-hash 2.1.1", |
| ... | ... | @@ -1920,12 +1937,12 @@ dependencies = [ |
| 1920 | 1937 | |
| 1921 | 1938 | [[package]] |
| 1922 | 1939 | name = "ra-ap-rustc_type_ir" |
| 1923 | version = "0.132.0" | |
| 1940 | version = "0.133.0" | |
| 1924 | 1941 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1925 | checksum = "52e35ee9e052406035016b8e6d54ca202bc39ccba1702780b33b2d5fb10d1da8" | |
| 1942 | checksum = "87c99f33be18d9e50cefef5442822da1f0b416e9a17a483879a9704e08a6a6e6" | |
| 1926 | 1943 | dependencies = [ |
| 1927 | 1944 | "arrayvec", |
| 1928 | "bitflags 2.9.1", | |
| 1945 | "bitflags 2.9.4", | |
| 1929 | 1946 | "derive-where", |
| 1930 | 1947 | "ena", |
| 1931 | 1948 | "indexmap", |
| ... | ... | @@ -1940,9 +1957,9 @@ dependencies = [ |
| 1940 | 1957 | |
| 1941 | 1958 | [[package]] |
| 1942 | 1959 | name = "ra-ap-rustc_type_ir_macros" |
| 1943 | version = "0.132.0" | |
| 1960 | version = "0.133.0" | |
| 1944 | 1961 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1945 | checksum = "9b934c956b0c88df8176803416b69d85d2c392a69c8aa794a4c338f22c527d38" | |
| 1962 | checksum = "77b162d65e058abfc058e6b67ae68156cc282fbd78da148c1a7ec77b4230661e" | |
| 1946 | 1963 | dependencies = [ |
| 1947 | 1964 | "proc-macro2", |
| 1948 | 1965 | "quote", |
| ... | ... | @@ -1952,9 +1969,9 @@ dependencies = [ |
| 1952 | 1969 | |
| 1953 | 1970 | [[package]] |
| 1954 | 1971 | name = "rayon" |
| 1955 | version = "1.10.0" | |
| 1972 | version = "1.11.0" | |
| 1956 | 1973 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1957 | checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" | |
| 1974 | checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" | |
| 1958 | 1975 | dependencies = [ |
| 1959 | 1976 | "either", |
| 1960 | 1977 | "rayon-core", |
| ... | ... | @@ -1962,9 +1979,9 @@ dependencies = [ |
| 1962 | 1979 | |
| 1963 | 1980 | [[package]] |
| 1964 | 1981 | name = "rayon-core" |
| 1965 | version = "1.12.1" | |
| 1982 | version = "1.13.0" | |
| 1966 | 1983 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1967 | checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" | |
| 1984 | checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" | |
| 1968 | 1985 | dependencies = [ |
| 1969 | 1986 | "crossbeam-deque", |
| 1970 | 1987 | "crossbeam-utils", |
| ... | ... | @@ -1972,22 +1989,22 @@ dependencies = [ |
| 1972 | 1989 | |
| 1973 | 1990 | [[package]] |
| 1974 | 1991 | name = "redox_syscall" |
| 1975 | version = "0.5.13" | |
| 1992 | version = "0.5.17" | |
| 1976 | 1993 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1977 | checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" | |
| 1994 | checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" | |
| 1978 | 1995 | dependencies = [ |
| 1979 | "bitflags 2.9.1", | |
| 1996 | "bitflags 2.9.4", | |
| 1980 | 1997 | ] |
| 1981 | 1998 | |
| 1982 | 1999 | [[package]] |
| 1983 | 2000 | name = "redox_users" |
| 1984 | version = "0.5.0" | |
| 2001 | version = "0.5.2" | |
| 1985 | 2002 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1986 | checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" | |
| 2003 | checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" | |
| 1987 | 2004 | dependencies = [ |
| 1988 | 2005 | "getrandom", |
| 1989 | 2006 | "libredox", |
| 1990 | "thiserror 2.0.12", | |
| 2007 | "thiserror 2.0.16", | |
| 1991 | 2008 | ] |
| 1992 | 2009 | |
| 1993 | 2010 | [[package]] |
| ... | ... | @@ -2040,6 +2057,7 @@ dependencies = [ |
| 2040 | 2057 | "process-wrap", |
| 2041 | 2058 | "profile", |
| 2042 | 2059 | "project-model", |
| 2060 | "ra-ap-rustc_type_ir", | |
| 2043 | 2061 | "rayon", |
| 2044 | 2062 | "rustc-hash 2.1.1", |
| 2045 | 2063 | "scip", |
| ... | ... | @@ -2070,9 +2088,9 @@ dependencies = [ |
| 2070 | 2088 | |
| 2071 | 2089 | [[package]] |
| 2072 | 2090 | name = "rustc-demangle" |
| 2073 | version = "0.1.25" | |
| 2091 | version = "0.1.26" | |
| 2074 | 2092 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2075 | checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" | |
| 2093 | checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" | |
| 2076 | 2094 | |
| 2077 | 2095 | [[package]] |
| 2078 | 2096 | name = "rustc-hash" |
| ... | ... | @@ -2110,7 +2128,7 @@ version = "0.2.3+llvm-462a31f5a5ab" |
| 2110 | 2128 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2111 | 2129 | checksum = "486c2179b4796f65bfe2ee33679acf0927ac83ecf583ad6c91c3b4570911b9ad" |
| 2112 | 2130 | dependencies = [ |
| 2113 | "bitflags 2.9.1", | |
| 2131 | "bitflags 2.9.4", | |
| 2114 | 2132 | "smallvec", |
| 2115 | 2133 | ] |
| 2116 | 2134 | |
| ... | ... | @@ -2123,6 +2141,12 @@ dependencies = [ |
| 2123 | 2141 | "semver", |
| 2124 | 2142 | ] |
| 2125 | 2143 | |
| 2144 | [[package]] | |
| 2145 | name = "rustversion" | |
| 2146 | version = "1.0.22" | |
| 2147 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 2148 | checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" | |
| 2149 | ||
| 2126 | 2150 | [[package]] |
| 2127 | 2151 | name = "ryu" |
| 2128 | 2152 | version = "1.0.20" |
| ... | ... | @@ -2131,18 +2155,18 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" |
| 2131 | 2155 | |
| 2132 | 2156 | [[package]] |
| 2133 | 2157 | name = "salsa" |
| 2134 | version = "0.23.0" | |
| 2158 | version = "0.24.0" | |
| 2135 | 2159 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2136 | checksum = "2e235afdb8e510f38a07138fbe5a0b64691894358a9c0cbd813b1aade110efc9" | |
| 2160 | checksum = "27956164373aeec733ac24ff1736de8541234e3a8e7e6f916b28175b5752af3b" | |
| 2137 | 2161 | dependencies = [ |
| 2138 | 2162 | "boxcar", |
| 2139 | 2163 | "crossbeam-queue", |
| 2140 | 2164 | "crossbeam-utils", |
| 2141 | "hashbrown 0.15.4", | |
| 2165 | "hashbrown 0.15.5", | |
| 2142 | 2166 | "hashlink", |
| 2143 | 2167 | "indexmap", |
| 2144 | 2168 | "intrusive-collections", |
| 2145 | "papaya", | |
| 2169 | "inventory", | |
| 2146 | 2170 | "parking_lot", |
| 2147 | 2171 | "portable-atomic", |
| 2148 | 2172 | "rayon", |
| ... | ... | @@ -2156,15 +2180,15 @@ dependencies = [ |
| 2156 | 2180 | |
| 2157 | 2181 | [[package]] |
| 2158 | 2182 | name = "salsa-macro-rules" |
| 2159 | version = "0.23.0" | |
| 2183 | version = "0.24.0" | |
| 2160 | 2184 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2161 | checksum = "2edb86a7e9c91f6d30c9ce054312721dbe773a162db27bbfae834d16177b30ce" | |
| 2185 | checksum = "6ca3b9d6e47c08b5de4b218e0c5f7ec910b51bce6314e651c8e7b9d154d174da" | |
| 2162 | 2186 | |
| 2163 | 2187 | [[package]] |
| 2164 | 2188 | name = "salsa-macros" |
| 2165 | version = "0.23.0" | |
| 2189 | version = "0.24.0" | |
| 2166 | 2190 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2167 | checksum = "d0778d6e209051bc4e75acfe83bcd7848601ec3dbe9c3dbb982829020e9128af" | |
| 2191 | checksum = "6337b62f2968be6b8afa30017d7564ecbde6832ada47ed2261fb14d0fd402ff4" | |
| 2168 | 2192 | dependencies = [ |
| 2169 | 2193 | "proc-macro2", |
| 2170 | 2194 | "quote", |
| ... | ... | @@ -2202,42 +2226,35 @@ version = "1.2.0" |
| 2202 | 2226 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2203 | 2227 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" |
| 2204 | 2228 | |
| 2205 | [[package]] | |
| 2206 | name = "seize" | |
| 2207 | version = "0.5.0" | |
| 2208 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 2209 | checksum = "e4b8d813387d566f627f3ea1b914c068aac94c40ae27ec43f5f33bde65abefe7" | |
| 2210 | dependencies = [ | |
| 2211 | "libc", | |
| 2212 | "windows-sys 0.52.0", | |
| 2213 | ] | |
| 2214 | ||
| 2215 | 2229 | [[package]] |
| 2216 | 2230 | name = "semver" |
| 2217 | version = "1.0.26" | |
| 2231 | version = "1.0.27" | |
| 2218 | 2232 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2219 | checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" | |
| 2233 | checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" | |
| 2220 | 2234 | dependencies = [ |
| 2221 | 2235 | "serde", |
| 2236 | "serde_core", | |
| 2222 | 2237 | ] |
| 2223 | 2238 | |
| 2224 | 2239 | [[package]] |
| 2225 | 2240 | name = "serde" |
| 2226 | version = "1.0.219" | |
| 2241 | version = "1.0.226" | |
| 2227 | 2242 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2228 | checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" | |
| 2243 | checksum = "0dca6411025b24b60bfa7ec1fe1f8e710ac09782dca409ee8237ba74b51295fd" | |
| 2229 | 2244 | dependencies = [ |
| 2245 | "serde_core", | |
| 2230 | 2246 | "serde_derive", |
| 2231 | 2247 | ] |
| 2232 | 2248 | |
| 2233 | 2249 | [[package]] |
| 2234 | 2250 | name = "serde-untagged" |
| 2235 | version = "0.1.7" | |
| 2251 | version = "0.1.9" | |
| 2236 | 2252 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2237 | checksum = "299d9c19d7d466db4ab10addd5703e4c615dec2a5a16dbbafe191045e87ee66e" | |
| 2253 | checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058" | |
| 2238 | 2254 | dependencies = [ |
| 2239 | 2255 | "erased-serde", |
| 2240 | 2256 | "serde", |
| 2257 | "serde_core", | |
| 2241 | 2258 | "typeid", |
| 2242 | 2259 | ] |
| 2243 | 2260 | |
| ... | ... | @@ -2251,11 +2268,20 @@ dependencies = [ |
| 2251 | 2268 | "serde", |
| 2252 | 2269 | ] |
| 2253 | 2270 | |
| 2271 | [[package]] | |
| 2272 | name = "serde_core" | |
| 2273 | version = "1.0.226" | |
| 2274 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 2275 | checksum = "ba2ba63999edb9dac981fb34b3e5c0d111a69b0924e253ed29d83f7c99e966a4" | |
| 2276 | dependencies = [ | |
| 2277 | "serde_derive", | |
| 2278 | ] | |
| 2279 | ||
| 2254 | 2280 | [[package]] |
| 2255 | 2281 | name = "serde_derive" |
| 2256 | version = "1.0.219" | |
| 2282 | version = "1.0.226" | |
| 2257 | 2283 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2258 | checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" | |
| 2284 | checksum = "8db53ae22f34573731bafa1db20f04027b2d25e02d8205921b569171699cdb33" | |
| 2259 | 2285 | dependencies = [ |
| 2260 | 2286 | "proc-macro2", |
| 2261 | 2287 | "quote", |
| ... | ... | @@ -2264,15 +2290,16 @@ dependencies = [ |
| 2264 | 2290 | |
| 2265 | 2291 | [[package]] |
| 2266 | 2292 | name = "serde_json" |
| 2267 | version = "1.0.140" | |
| 2293 | version = "1.0.145" | |
| 2268 | 2294 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2269 | checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" | |
| 2295 | checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" | |
| 2270 | 2296 | dependencies = [ |
| 2271 | 2297 | "indexmap", |
| 2272 | 2298 | "itoa", |
| 2273 | 2299 | "memchr", |
| 2274 | 2300 | "ryu", |
| 2275 | 2301 | "serde", |
| 2302 | "serde_core", | |
| 2276 | 2303 | ] |
| 2277 | 2304 | |
| 2278 | 2305 | [[package]] |
| ... | ... | @@ -2372,9 +2399,9 @@ dependencies = [ |
| 2372 | 2399 | |
| 2373 | 2400 | [[package]] |
| 2374 | 2401 | name = "syn" |
| 2375 | version = "2.0.103" | |
| 2402 | version = "2.0.106" | |
| 2376 | 2403 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2377 | checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8" | |
| 2404 | checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" | |
| 2378 | 2405 | dependencies = [ |
| 2379 | 2406 | "proc-macro2", |
| 2380 | 2407 | "quote", |
| ... | ... | @@ -2490,11 +2517,11 @@ dependencies = [ |
| 2490 | 2517 | |
| 2491 | 2518 | [[package]] |
| 2492 | 2519 | name = "thiserror" |
| 2493 | version = "2.0.12" | |
| 2520 | version = "2.0.16" | |
| 2494 | 2521 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2495 | checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" | |
| 2522 | checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" | |
| 2496 | 2523 | dependencies = [ |
| 2497 | "thiserror-impl 2.0.12", | |
| 2524 | "thiserror-impl 2.0.16", | |
| 2498 | 2525 | ] |
| 2499 | 2526 | |
| 2500 | 2527 | [[package]] |
| ... | ... | @@ -2510,9 +2537,9 @@ dependencies = [ |
| 2510 | 2537 | |
| 2511 | 2538 | [[package]] |
| 2512 | 2539 | name = "thiserror-impl" |
| 2513 | version = "2.0.12" | |
| 2540 | version = "2.0.16" | |
| 2514 | 2541 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2515 | checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" | |
| 2542 | checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" | |
| 2516 | 2543 | dependencies = [ |
| 2517 | 2544 | "proc-macro2", |
| 2518 | 2545 | "quote", |
| ... | ... | @@ -2561,9 +2588,9 @@ dependencies = [ |
| 2561 | 2588 | |
| 2562 | 2589 | [[package]] |
| 2563 | 2590 | name = "time" |
| 2564 | version = "0.3.41" | |
| 2591 | version = "0.3.44" | |
| 2565 | 2592 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2566 | checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" | |
| 2593 | checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" | |
| 2567 | 2594 | dependencies = [ |
| 2568 | 2595 | "deranged", |
| 2569 | 2596 | "itoa", |
| ... | ... | @@ -2578,15 +2605,15 @@ dependencies = [ |
| 2578 | 2605 | |
| 2579 | 2606 | [[package]] |
| 2580 | 2607 | name = "time-core" |
| 2581 | version = "0.1.4" | |
| 2608 | version = "0.1.6" | |
| 2582 | 2609 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2583 | checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" | |
| 2610 | checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" | |
| 2584 | 2611 | |
| 2585 | 2612 | [[package]] |
| 2586 | 2613 | name = "time-macros" |
| 2587 | version = "0.2.22" | |
| 2614 | version = "0.2.24" | |
| 2588 | 2615 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2589 | checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" | |
| 2616 | checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" | |
| 2590 | 2617 | dependencies = [ |
| 2591 | 2618 | "num-conv", |
| 2592 | 2619 | "time-core", |
| ... | ... | @@ -2664,9 +2691,9 @@ dependencies = [ |
| 2664 | 2691 | |
| 2665 | 2692 | [[package]] |
| 2666 | 2693 | name = "tracing-attributes" |
| 2667 | version = "0.1.29" | |
| 2694 | version = "0.1.30" | |
| 2668 | 2695 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2669 | checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662" | |
| 2696 | checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" | |
| 2670 | 2697 | dependencies = [ |
| 2671 | 2698 | "proc-macro2", |
| 2672 | 2699 | "quote", |
| ... | ... | @@ -2762,9 +2789,9 @@ checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" |
| 2762 | 2789 | |
| 2763 | 2790 | [[package]] |
| 2764 | 2791 | name = "unicode-ident" |
| 2765 | version = "1.0.18" | |
| 2792 | version = "1.0.19" | |
| 2766 | 2793 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2767 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" | |
| 2794 | checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" | |
| 2768 | 2795 | |
| 2769 | 2796 | [[package]] |
| 2770 | 2797 | name = "unicode-properties" |
| ... | ... | @@ -2780,9 +2807,9 @@ checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" |
| 2780 | 2807 | |
| 2781 | 2808 | [[package]] |
| 2782 | 2809 | name = "url" |
| 2783 | version = "2.5.4" | |
| 2810 | version = "2.5.7" | |
| 2784 | 2811 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2785 | checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" | |
| 2812 | checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" | |
| 2786 | 2813 | dependencies = [ |
| 2787 | 2814 | "form_urlencoded", |
| 2788 | 2815 | "idna", |
| ... | ... | @@ -2849,11 +2876,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" |
| 2849 | 2876 | |
| 2850 | 2877 | [[package]] |
| 2851 | 2878 | name = "winapi-util" |
| 2852 | version = "0.1.9" | |
| 2879 | version = "0.1.11" | |
| 2853 | 2880 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2854 | checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" | |
| 2881 | checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" | |
| 2855 | 2882 | dependencies = [ |
| 2856 | "windows-sys 0.59.0", | |
| 2883 | "windows-sys 0.61.0", | |
| 2857 | 2884 | ] |
| 2858 | 2885 | |
| 2859 | 2886 | [[package]] |
| ... | ... | @@ -2865,7 +2892,7 @@ dependencies = [ |
| 2865 | 2892 | "windows-collections", |
| 2866 | 2893 | "windows-core", |
| 2867 | 2894 | "windows-future", |
| 2868 | "windows-link", | |
| 2895 | "windows-link 0.1.3", | |
| 2869 | 2896 | "windows-numerics", |
| 2870 | 2897 | ] |
| 2871 | 2898 | |
| ... | ... | @@ -2886,7 +2913,7 @@ checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" |
| 2886 | 2913 | dependencies = [ |
| 2887 | 2914 | "windows-implement", |
| 2888 | 2915 | "windows-interface", |
| 2889 | "windows-link", | |
| 2916 | "windows-link 0.1.3", | |
| 2890 | 2917 | "windows-result", |
| 2891 | 2918 | "windows-strings", |
| 2892 | 2919 | ] |
| ... | ... | @@ -2898,7 +2925,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2898 | 2925 | checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" |
| 2899 | 2926 | dependencies = [ |
| 2900 | 2927 | "windows-core", |
| 2901 | "windows-link", | |
| 2928 | "windows-link 0.1.3", | |
| 2902 | 2929 | "windows-threading", |
| 2903 | 2930 | ] |
| 2904 | 2931 | |
| ... | ... | @@ -2930,6 +2957,12 @@ version = "0.1.3" |
| 2930 | 2957 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2931 | 2958 | checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" |
| 2932 | 2959 | |
| 2960 | [[package]] | |
| 2961 | name = "windows-link" | |
| 2962 | version = "0.2.0" | |
| 2963 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 2964 | checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" | |
| 2965 | ||
| 2933 | 2966 | [[package]] |
| 2934 | 2967 | name = "windows-numerics" |
| 2935 | 2968 | version = "0.2.0" |
| ... | ... | @@ -2937,7 +2970,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2937 | 2970 | checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" |
| 2938 | 2971 | dependencies = [ |
| 2939 | 2972 | "windows-core", |
| 2940 | "windows-link", | |
| 2973 | "windows-link 0.1.3", | |
| 2941 | 2974 | ] |
| 2942 | 2975 | |
| 2943 | 2976 | [[package]] |
| ... | ... | @@ -2946,7 +2979,7 @@ version = "0.3.4" |
| 2946 | 2979 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2947 | 2980 | checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" |
| 2948 | 2981 | dependencies = [ |
| 2949 | "windows-link", | |
| 2982 | "windows-link 0.1.3", | |
| 2950 | 2983 | ] |
| 2951 | 2984 | |
| 2952 | 2985 | [[package]] |
| ... | ... | @@ -2955,16 +2988,7 @@ version = "0.4.2" |
| 2955 | 2988 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2956 | 2989 | checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" |
| 2957 | 2990 | dependencies = [ |
| 2958 | "windows-link", | |
| 2959 | ] | |
| 2960 | ||
| 2961 | [[package]] | |
| 2962 | name = "windows-sys" | |
| 2963 | version = "0.48.0" | |
| 2964 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 2965 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" | |
| 2966 | dependencies = [ | |
| 2967 | "windows-targets 0.48.5", | |
| 2991 | "windows-link 0.1.3", | |
| 2968 | 2992 | ] |
| 2969 | 2993 | |
| 2970 | 2994 | [[package]] |
| ... | ... | @@ -2991,22 +3015,16 @@ version = "0.60.2" |
| 2991 | 3015 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2992 | 3016 | checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" |
| 2993 | 3017 | dependencies = [ |
| 2994 | "windows-targets 0.53.2", | |
| 3018 | "windows-targets 0.53.3", | |
| 2995 | 3019 | ] |
| 2996 | 3020 | |
| 2997 | 3021 | [[package]] |
| 2998 | name = "windows-targets" | |
| 2999 | version = "0.48.5" | |
| 3022 | name = "windows-sys" | |
| 3023 | version = "0.61.0" | |
| 3000 | 3024 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 3001 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" | |
| 3025 | checksum = "e201184e40b2ede64bc2ea34968b28e33622acdbbf37104f0e4a33f7abe657aa" | |
| 3002 | 3026 | dependencies = [ |
| 3003 | "windows_aarch64_gnullvm 0.48.5", | |
| 3004 | "windows_aarch64_msvc 0.48.5", | |
| 3005 | "windows_i686_gnu 0.48.5", | |
| 3006 | "windows_i686_msvc 0.48.5", | |
| 3007 | "windows_x86_64_gnu 0.48.5", | |
| 3008 | "windows_x86_64_gnullvm 0.48.5", | |
| 3009 | "windows_x86_64_msvc 0.48.5", | |
| 3027 | "windows-link 0.2.0", | |
| 3010 | 3028 | ] |
| 3011 | 3029 | |
| 3012 | 3030 | [[package]] |
| ... | ... | @@ -3027,10 +3045,11 @@ dependencies = [ |
| 3027 | 3045 | |
| 3028 | 3046 | [[package]] |
| 3029 | 3047 | name = "windows-targets" |
| 3030 | version = "0.53.2" | |
| 3048 | version = "0.53.3" | |
| 3031 | 3049 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 3032 | checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" | |
| 3050 | checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" | |
| 3033 | 3051 | dependencies = [ |
| 3052 | "windows-link 0.1.3", | |
| 3034 | 3053 | "windows_aarch64_gnullvm 0.53.0", |
| 3035 | 3054 | "windows_aarch64_msvc 0.53.0", |
| 3036 | 3055 | "windows_i686_gnu 0.53.0", |
| ... | ... | @@ -3047,15 +3066,9 @@ version = "0.1.0" |
| 3047 | 3066 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 3048 | 3067 | checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" |
| 3049 | 3068 | dependencies = [ |
| 3050 | "windows-link", | |
| 3069 | "windows-link 0.1.3", | |
| 3051 | 3070 | ] |
| 3052 | 3071 | |
| 3053 | [[package]] | |
| 3054 | name = "windows_aarch64_gnullvm" | |
| 3055 | version = "0.48.5" | |
| 3056 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 3057 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" | |
| 3058 | ||
| 3059 | 3072 | [[package]] |
| 3060 | 3073 | name = "windows_aarch64_gnullvm" |
| 3061 | 3074 | version = "0.52.6" |
| ... | ... | @@ -3068,12 +3081,6 @@ version = "0.53.0" |
| 3068 | 3081 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 3069 | 3082 | checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" |
| 3070 | 3083 | |
| 3071 | [[package]] | |
| 3072 | name = "windows_aarch64_msvc" | |
| 3073 | version = "0.48.5" | |
| 3074 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 3075 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" | |
| 3076 | ||
| 3077 | 3084 | [[package]] |
| 3078 | 3085 | name = "windows_aarch64_msvc" |
| 3079 | 3086 | version = "0.52.6" |
| ... | ... | @@ -3086,12 +3093,6 @@ version = "0.53.0" |
| 3086 | 3093 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 3087 | 3094 | checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" |
| 3088 | 3095 | |
| 3089 | [[package]] | |
| 3090 | name = "windows_i686_gnu" | |
| 3091 | version = "0.48.5" | |
| 3092 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 3093 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" | |
| 3094 | ||
| 3095 | 3096 | [[package]] |
| 3096 | 3097 | name = "windows_i686_gnu" |
| 3097 | 3098 | version = "0.52.6" |
| ... | ... | @@ -3116,12 +3117,6 @@ version = "0.53.0" |
| 3116 | 3117 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 3117 | 3118 | checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" |
| 3118 | 3119 | |
| 3119 | [[package]] | |
| 3120 | name = "windows_i686_msvc" | |
| 3121 | version = "0.48.5" | |
| 3122 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 3123 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" | |
| 3124 | ||
| 3125 | 3120 | [[package]] |
| 3126 | 3121 | name = "windows_i686_msvc" |
| 3127 | 3122 | version = "0.52.6" |
| ... | ... | @@ -3134,12 +3129,6 @@ version = "0.53.0" |
| 3134 | 3129 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 3135 | 3130 | checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" |
| 3136 | 3131 | |
| 3137 | [[package]] | |
| 3138 | name = "windows_x86_64_gnu" | |
| 3139 | version = "0.48.5" | |
| 3140 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 3141 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" | |
| 3142 | ||
| 3143 | 3132 | [[package]] |
| 3144 | 3133 | name = "windows_x86_64_gnu" |
| 3145 | 3134 | version = "0.52.6" |
| ... | ... | @@ -3152,12 +3141,6 @@ version = "0.53.0" |
| 3152 | 3141 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 3153 | 3142 | checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" |
| 3154 | 3143 | |
| 3155 | [[package]] | |
| 3156 | name = "windows_x86_64_gnullvm" | |
| 3157 | version = "0.48.5" | |
| 3158 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 3159 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" | |
| 3160 | ||
| 3161 | 3144 | [[package]] |
| 3162 | 3145 | name = "windows_x86_64_gnullvm" |
| 3163 | 3146 | version = "0.52.6" |
| ... | ... | @@ -3170,12 +3153,6 @@ version = "0.53.0" |
| 3170 | 3153 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 3171 | 3154 | checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" |
| 3172 | 3155 | |
| 3173 | [[package]] | |
| 3174 | name = "windows_x86_64_msvc" | |
| 3175 | version = "0.48.5" | |
| 3176 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 3177 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" | |
| 3178 | ||
| 3179 | 3156 | [[package]] |
| 3180 | 3157 | name = "windows_x86_64_msvc" |
| 3181 | 3158 | version = "0.52.6" |
| ... | ... | @@ -3190,9 +3167,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" |
| 3190 | 3167 | |
| 3191 | 3168 | [[package]] |
| 3192 | 3169 | name = "winnow" |
| 3193 | version = "0.7.11" | |
| 3170 | version = "0.7.13" | |
| 3194 | 3171 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 3195 | checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" | |
| 3172 | checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" | |
| 3196 | 3173 | dependencies = [ |
| 3197 | 3174 | "memchr", |
| 3198 | 3175 | ] |
| ... | ... | @@ -3317,9 +3294,9 @@ dependencies = [ |
| 3317 | 3294 | |
| 3318 | 3295 | [[package]] |
| 3319 | 3296 | name = "zerovec" |
| 3320 | version = "0.11.2" | |
| 3297 | version = "0.11.4" | |
| 3321 | 3298 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 3322 | checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" | |
| 3299 | checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" | |
| 3323 | 3300 | dependencies = [ |
| 3324 | 3301 | "yoke", |
| 3325 | 3302 | "zerofrom", |
| ... | ... | @@ -3339,9 +3316,9 @@ dependencies = [ |
| 3339 | 3316 | |
| 3340 | 3317 | [[package]] |
| 3341 | 3318 | name = "zip" |
| 3342 | version = "4.0.0" | |
| 3319 | version = "4.6.1" | |
| 3343 | 3320 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 3344 | checksum = "153a6fff49d264c4babdcfa6b4d534747f520e56e8f0f384f3b808c4b64cc1fd" | |
| 3321 | checksum = "caa8cd6af31c3b31c6631b8f483848b91589021b28fffe50adada48d4f4d2ed1" | |
| 3345 | 3322 | dependencies = [ |
| 3346 | 3323 | "arbitrary", |
| 3347 | 3324 | "crc32fast", |
src/tools/rust-analyzer/Cargo.toml+11-10| ... | ... | @@ -52,6 +52,7 @@ debug = 2 |
| 52 | 52 | |
| 53 | 53 | [workspace.dependencies] |
| 54 | 54 | # local crates |
| 55 | macros = { path = "./crates/macros", version = "0.0.0" } | |
| 55 | 56 | base-db = { path = "./crates/base-db", version = "0.0.0" } |
| 56 | 57 | cfg = { path = "./crates/cfg", version = "0.0.0", features = ["tt"] } |
| 57 | 58 | hir = { path = "./crates/hir", version = "0.0.0" } |
| ... | ... | @@ -87,14 +88,14 @@ vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" } |
| 87 | 88 | vfs = { path = "./crates/vfs", version = "0.0.0" } |
| 88 | 89 | edition = { path = "./crates/edition", version = "0.0.0" } |
| 89 | 90 | |
| 90 | ra-ap-rustc_lexer = { version = "0.132", default-features = false } | |
| 91 | ra-ap-rustc_parse_format = { version = "0.132", default-features = false } | |
| 92 | ra-ap-rustc_index = { version = "0.132", default-features = false } | |
| 93 | ra-ap-rustc_abi = { version = "0.132", default-features = false } | |
| 94 | ra-ap-rustc_pattern_analysis = { version = "0.132", default-features = false } | |
| 95 | ra-ap-rustc_ast_ir = { version = "0.132", default-features = false } | |
| 96 | ra-ap-rustc_type_ir = { version = "0.132", default-features = false } | |
| 97 | ra-ap-rustc_next_trait_solver = { version = "0.132", default-features = false } | |
| 91 | ra-ap-rustc_lexer = { version = "0.133", default-features = false } | |
| 92 | ra-ap-rustc_parse_format = { version = "0.133", default-features = false } | |
| 93 | ra-ap-rustc_index = { version = "0.133", default-features = false } | |
| 94 | ra-ap-rustc_abi = { version = "0.133", default-features = false } | |
| 95 | ra-ap-rustc_pattern_analysis = { version = "0.133", default-features = false } | |
| 96 | ra-ap-rustc_ast_ir = { version = "0.133", default-features = false } | |
| 97 | ra-ap-rustc_type_ir = { version = "0.133", default-features = false } | |
| 98 | ra-ap-rustc_next_trait_solver = { version = "0.133", default-features = false } | |
| 98 | 99 | |
| 99 | 100 | # local crates that aren't published to crates.io. These should not have versions. |
| 100 | 101 | |
| ... | ... | @@ -137,12 +138,12 @@ rayon = "1.10.0" |
| 137 | 138 | rowan = "=0.15.15" |
| 138 | 139 | # Ideally we'd not enable the macros feature but unfortunately the `tracked` attribute does not work |
| 139 | 140 | # on impls without it |
| 140 | salsa = { version = "0.23.0", default-features = true, features = [ | |
| 141 | salsa = { version = "0.24.0", default-features = true, features = [ | |
| 141 | 142 | "rayon", |
| 142 | 143 | "salsa_unstable", |
| 143 | 144 | "macros", |
| 144 | 145 | ] } |
| 145 | salsa-macros = "0.23.0" | |
| 146 | salsa-macros = "0.24.0" | |
| 146 | 147 | semver = "1.0.26" |
| 147 | 148 | serde = { version = "1.0.219" } |
| 148 | 149 | serde_derive = { version = "1.0.219" } |
src/tools/rust-analyzer/README.md+1-1| ... | ... | @@ -61,4 +61,4 @@ https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frust-analyzer |
| 61 | 61 | rust-analyzer is primarily distributed under the terms of both the MIT |
| 62 | 62 | license and the Apache License (Version 2.0). |
| 63 | 63 | |
| 64 | See LICENSE-APACHE and LICENSE-MIT for details. | |
| 64 | See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT) for details. |
src/tools/rust-analyzer/crates/cfg/Cargo.toml+1-5| ... | ... | @@ -23,11 +23,7 @@ intern.workspace = true |
| 23 | 23 | [dev-dependencies] |
| 24 | 24 | expect-test = "1.5.1" |
| 25 | 25 | oorandom = "11.1.5" |
| 26 | # We depend on both individually instead of using `features = ["derive"]` to microoptimize the | |
| 27 | # build graph: if the feature was enabled, syn would be built early on in the graph if `smolstr` | |
| 28 | # supports `arbitrary`. This way, we avoid feature unification. | |
| 29 | arbitrary = "1.4.1" | |
| 30 | derive_arbitrary = "1.4.1" | |
| 26 | arbitrary = { version = "1.4.1", features = ["derive"] } | |
| 31 | 27 | |
| 32 | 28 | # local deps |
| 33 | 29 | syntax-bridge.workspace = true |
src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs+1-1| ... | ... | @@ -47,7 +47,7 @@ impl fmt::Display for CfgAtom { |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | 49 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
| 50 | #[cfg_attr(test, derive(derive_arbitrary::Arbitrary))] | |
| 50 | #[cfg_attr(test, derive(arbitrary::Arbitrary))] | |
| 51 | 51 | pub enum CfgExpr { |
| 52 | 52 | Invalid, |
| 53 | 53 | Atom(CfgAtom), |
src/tools/rust-analyzer/crates/hir-def/src/expr_store/path.rs+1-1| ... | ... | @@ -88,7 +88,7 @@ pub struct AssociatedTypeBinding { |
| 88 | 88 | } |
| 89 | 89 | |
| 90 | 90 | /// A single generic argument. |
| 91 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | |
| 91 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | |
| 92 | 92 | pub enum GenericArg { |
| 93 | 93 | Type(TypeRefId), |
| 94 | 94 | Lifetime(LifetimeRefId), |
src/tools/rust-analyzer/crates/hir-def/src/signatures.rs+14| ... | ... | @@ -349,6 +349,7 @@ bitflags::bitflags! { |
| 349 | 349 | #[derive(Debug, Clone, Copy, Eq, PartialEq, Default)] |
| 350 | 350 | pub struct ImplFlags: u8 { |
| 351 | 351 | const NEGATIVE = 1 << 1; |
| 352 | const DEFAULT = 1 << 2; | |
| 352 | 353 | const UNSAFE = 1 << 3; |
| 353 | 354 | } |
| 354 | 355 | } |
| ... | ... | @@ -374,6 +375,9 @@ impl ImplSignature { |
| 374 | 375 | if src.value.excl_token().is_some() { |
| 375 | 376 | flags.insert(ImplFlags::NEGATIVE); |
| 376 | 377 | } |
| 378 | if src.value.default_token().is_some() { | |
| 379 | flags.insert(ImplFlags::DEFAULT); | |
| 380 | } | |
| 377 | 381 | |
| 378 | 382 | let (store, source_map, self_ty, target_trait, generic_params) = |
| 379 | 383 | crate::expr_store::lower::lower_impl(db, loc.container, src, id); |
| ... | ... | @@ -389,6 +393,16 @@ impl ImplSignature { |
| 389 | 393 | Arc::new(source_map), |
| 390 | 394 | ) |
| 391 | 395 | } |
| 396 | ||
| 397 | #[inline] | |
| 398 | pub fn is_negative(&self) -> bool { | |
| 399 | self.flags.contains(ImplFlags::NEGATIVE) | |
| 400 | } | |
| 401 | ||
| 402 | #[inline] | |
| 403 | pub fn is_default(&self) -> bool { | |
| 404 | self.flags.contains(ImplFlags::DEFAULT) | |
| 405 | } | |
| 392 | 406 | } |
| 393 | 407 | |
| 394 | 408 | bitflags::bitflags! { |
src/tools/rust-analyzer/crates/hir-def/src/test_db.rs+2-3| ... | ... | @@ -7,7 +7,7 @@ use base_db::{ |
| 7 | 7 | SourceDatabase, SourceRoot, SourceRootId, SourceRootInput, |
| 8 | 8 | }; |
| 9 | 9 | use hir_expand::{InFile, files::FilePosition}; |
| 10 | use salsa::{AsDynDatabase, Durability}; | |
| 10 | use salsa::Durability; | |
| 11 | 11 | use span::FileId; |
| 12 | 12 | use syntax::{AstNode, algo, ast}; |
| 13 | 13 | use triomphe::Arc; |
| ... | ... | @@ -303,8 +303,7 @@ impl TestDB { |
| 303 | 303 | // This is pretty horrible, but `Debug` is the only way to inspect |
| 304 | 304 | // QueryDescriptor at the moment. |
| 305 | 305 | salsa::EventKind::WillExecute { database_key } => { |
| 306 | let ingredient = self | |
| 307 | .as_dyn_database() | |
| 306 | let ingredient = (self as &dyn salsa::Database) | |
| 308 | 307 | .ingredient_debug_name(database_key.ingredient_index()); |
| 309 | 308 | Some(ingredient.to_string()) |
| 310 | 309 | } |
src/tools/rust-analyzer/crates/hir-ty/Cargo.toml+1| ... | ... | @@ -50,6 +50,7 @@ tracing-tree.workspace = true |
| 50 | 50 | |
| 51 | 51 | # local deps |
| 52 | 52 | stdx.workspace = true |
| 53 | macros.workspace = true | |
| 53 | 54 | intern.workspace = true |
| 54 | 55 | hir-def.workspace = true |
| 55 | 56 | hir-expand.workspace = true |
src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs+44-21| ... | ... | @@ -5,20 +5,21 @@ |
| 5 | 5 | |
| 6 | 6 | use std::fmt; |
| 7 | 7 | |
| 8 | use hir_def::{TypeAliasId, lang_item::LangItem}; | |
| 8 | use hir_def::{TraitId, TypeAliasId, lang_item::LangItem}; | |
| 9 | 9 | use rustc_type_ir::inherent::{IntoKind, Ty as _}; |
| 10 | 10 | use tracing::debug; |
| 11 | 11 | use triomphe::Arc; |
| 12 | 12 | |
| 13 | use crate::next_solver::infer::InferOk; | |
| 14 | 13 | use crate::{ |
| 15 | 14 | TraitEnvironment, |
| 16 | 15 | db::HirDatabase, |
| 17 | 16 | infer::unify::InferenceTable, |
| 18 | 17 | next_solver::{ |
| 19 | Ty, TyKind, | |
| 20 | infer::traits::{ObligationCause, PredicateObligations}, | |
| 21 | mapping::{ChalkToNextSolver, NextSolverToChalk}, | |
| 18 | Canonical, TraitRef, Ty, TyKind, | |
| 19 | infer::{ | |
| 20 | InferOk, | |
| 21 | traits::{Obligation, ObligationCause, PredicateObligations}, | |
| 22 | }, | |
| 22 | 23 | obligation_ctxt::ObligationCtxt, |
| 23 | 24 | }, |
| 24 | 25 | }; |
| ... | ... | @@ -35,17 +36,16 @@ const AUTODEREF_RECURSION_LIMIT: usize = 20; |
| 35 | 36 | pub fn autoderef<'db>( |
| 36 | 37 | db: &'db dyn HirDatabase, |
| 37 | 38 | env: Arc<TraitEnvironment<'db>>, |
| 38 | ty: crate::Canonical<crate::Ty>, | |
| 39 | ) -> impl Iterator<Item = crate::Ty> + use<> { | |
| 39 | ty: Canonical<'db, Ty<'db>>, | |
| 40 | ) -> impl Iterator<Item = Ty<'db>> + use<'db> { | |
| 40 | 41 | let mut table = InferenceTable::new(db, env); |
| 41 | let interner = table.interner; | |
| 42 | 42 | let ty = table.instantiate_canonical(ty); |
| 43 | let mut autoderef = Autoderef::new_no_tracking(&mut table, ty.to_nextsolver(interner)); | |
| 43 | let mut autoderef = Autoderef::new_no_tracking(&mut table, ty); | |
| 44 | 44 | let mut v = Vec::new(); |
| 45 | 45 | while let Some((ty, _steps)) = autoderef.next() { |
| 46 | 46 | // `ty` may contain unresolved inference variables. Since there's no chance they would be |
| 47 | 47 | // resolved, just replace with fallback type. |
| 48 | let resolved = autoderef.table.resolve_completely(ty.to_chalk(interner)); | |
| 48 | let resolved = autoderef.table.resolve_completely(ty); | |
| 49 | 49 | |
| 50 | 50 | // If the deref chain contains a cycle (e.g. `A` derefs to `B` and `B` derefs to `A`), we |
| 51 | 51 | // would revisit some already visited types. Stop here to avoid duplication. |
| ... | ... | @@ -101,6 +101,7 @@ struct AutoderefSnapshot<'db, Steps> { |
| 101 | 101 | |
| 102 | 102 | #[derive(Clone, Copy)] |
| 103 | 103 | struct AutoderefTraits { |
| 104 | trait_: TraitId, | |
| 104 | 105 | trait_target: TypeAliasId, |
| 105 | 106 | } |
| 106 | 107 | |
| ... | ... | @@ -215,16 +216,26 @@ impl<'a, 'db, Steps: TrackAutoderefSteps<'db>> Autoderef<'a, 'db, Steps> { |
| 215 | 216 | Some(it) => Some(*it), |
| 216 | 217 | None => { |
| 217 | 218 | let traits = if self.use_receiver_trait { |
| 218 | AutoderefTraits { | |
| 219 | trait_target: LangItem::ReceiverTarget | |
| 220 | .resolve_type_alias(self.table.db, self.table.trait_env.krate) | |
| 221 | .or_else(|| { | |
| 222 | LangItem::DerefTarget | |
| 223 | .resolve_type_alias(self.table.db, self.table.trait_env.krate) | |
| 224 | })?, | |
| 225 | } | |
| 219 | (|| { | |
| 220 | Some(AutoderefTraits { | |
| 221 | trait_: LangItem::Receiver | |
| 222 | .resolve_trait(self.table.db, self.table.trait_env.krate)?, | |
| 223 | trait_target: LangItem::ReceiverTarget | |
| 224 | .resolve_type_alias(self.table.db, self.table.trait_env.krate)?, | |
| 225 | }) | |
| 226 | })() | |
| 227 | .or_else(|| { | |
| 228 | Some(AutoderefTraits { | |
| 229 | trait_: LangItem::Deref | |
| 230 | .resolve_trait(self.table.db, self.table.trait_env.krate)?, | |
| 231 | trait_target: LangItem::DerefTarget | |
| 232 | .resolve_type_alias(self.table.db, self.table.trait_env.krate)?, | |
| 233 | }) | |
| 234 | })? | |
| 226 | 235 | } else { |
| 227 | 236 | AutoderefTraits { |
| 237 | trait_: LangItem::Deref | |
| 238 | .resolve_trait(self.table.db, self.table.trait_env.krate)?, | |
| 228 | 239 | trait_target: LangItem::DerefTarget |
| 229 | 240 | .resolve_type_alias(self.table.db, self.table.trait_env.krate)?, |
| 230 | 241 | } |
| ... | ... | @@ -236,10 +247,22 @@ impl<'a, 'db, Steps: TrackAutoderefSteps<'db>> Autoderef<'a, 'db, Steps> { |
| 236 | 247 | |
| 237 | 248 | fn overloaded_deref_ty(&mut self, ty: Ty<'db>) -> Option<Ty<'db>> { |
| 238 | 249 | debug!("overloaded_deref_ty({:?})", ty); |
| 239 | let interner = self.table.interner; | |
| 250 | let interner = self.table.interner(); | |
| 240 | 251 | |
| 241 | 252 | // <ty as Deref>, or whatever the equivalent trait is that we've been asked to walk. |
| 242 | let AutoderefTraits { trait_target } = self.autoderef_traits()?; | |
| 253 | let AutoderefTraits { trait_, trait_target } = self.autoderef_traits()?; | |
| 254 | ||
| 255 | let trait_ref = TraitRef::new(interner, trait_.into(), [ty]); | |
| 256 | let obligation = | |
| 257 | Obligation::new(interner, ObligationCause::new(), self.table.trait_env.env, trait_ref); | |
| 258 | // We detect whether the self type implements `Deref` before trying to | |
| 259 | // structurally normalize. We use `predicate_may_hold_opaque_types_jank` | |
| 260 | // to support not-yet-defined opaque types. It will succeed for `impl Deref` | |
| 261 | // but fail for `impl OtherTrait`. | |
| 262 | if !self.table.infer_ctxt.predicate_may_hold_opaque_types_jank(&obligation) { | |
| 263 | debug!("overloaded_deref_ty: cannot match obligation"); | |
| 264 | return None; | |
| 265 | } | |
| 243 | 266 | |
| 244 | 267 | let (normalized_ty, obligations) = structurally_normalize_ty( |
| 245 | 268 | self.table, |
| ... | ... | @@ -316,7 +339,7 @@ pub(crate) fn overloaded_deref_ty<'db>( |
| 316 | 339 | table: &InferenceTable<'db>, |
| 317 | 340 | ty: Ty<'db>, |
| 318 | 341 | ) -> Option<InferOk<'db, Ty<'db>>> { |
| 319 | let interner = table.interner; | |
| 342 | let interner = table.interner(); | |
| 320 | 343 | |
| 321 | 344 | let trait_target = LangItem::DerefTarget.resolve_type_alias(table.db, table.trait_env.krate)?; |
| 322 | 345 |
src/tools/rust-analyzer/crates/hir-ty/src/builder.rs+23-8| ... | ... | @@ -15,7 +15,10 @@ use crate::{ |
| 15 | 15 | error_lifetime, |
| 16 | 16 | generics::generics, |
| 17 | 17 | infer::unify::InferenceTable, |
| 18 | next_solver::{DbInterner, EarlyBinder, mapping::ChalkToNextSolver}, | |
| 18 | next_solver::{ | |
| 19 | DbInterner, EarlyBinder, | |
| 20 | mapping::{ChalkToNextSolver, NextSolverToChalk}, | |
| 21 | }, | |
| 19 | 22 | primitive, to_assoc_type_id, to_chalk_trait_id, |
| 20 | 23 | }; |
| 21 | 24 | |
| ... | ... | @@ -127,11 +130,14 @@ impl<D> TyBuilder<D> { |
| 127 | 130 | } |
| 128 | 131 | |
| 129 | 132 | pub fn fill_with_unknown(self) -> Self { |
| 133 | let interner = DbInterner::conjure(); | |
| 130 | 134 | // self.fill is inlined to make borrow checker happy |
| 131 | 135 | let mut this = self; |
| 132 | 136 | let filler = this.param_kinds[this.vec.len()..].iter().map(|x| match x { |
| 133 | 137 | ParamKind::Type => TyKind::Error.intern(Interner).cast(Interner), |
| 134 | ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()), | |
| 138 | ParamKind::Const(ty) => { | |
| 139 | unknown_const_as_generic(ty.to_nextsolver(interner)).to_chalk(interner) | |
| 140 | } | |
| 135 | 141 | ParamKind::Lifetime => error_lifetime().cast(Interner), |
| 136 | 142 | }); |
| 137 | 143 | this.vec.extend(filler.casted(Interner)); |
| ... | ... | @@ -141,10 +147,13 @@ impl<D> TyBuilder<D> { |
| 141 | 147 | |
| 142 | 148 | #[tracing::instrument(skip_all)] |
| 143 | 149 | pub(crate) fn fill_with_inference_vars(self, table: &mut InferenceTable<'_>) -> Self { |
| 144 | self.fill(|x| match x { | |
| 145 | ParamKind::Type => table.new_type_var().cast(Interner), | |
| 146 | ParamKind::Const(ty) => table.new_const_var(ty.clone()).cast(Interner), | |
| 147 | ParamKind::Lifetime => table.new_lifetime_var().cast(Interner), | |
| 150 | self.fill(|x| { | |
| 151 | match x { | |
| 152 | ParamKind::Type => crate::next_solver::GenericArg::Ty(table.next_ty_var()), | |
| 153 | ParamKind::Const(_) => table.next_const_var().into(), | |
| 154 | ParamKind::Lifetime => table.next_region_var().into(), | |
| 155 | } | |
| 156 | .to_chalk(table.interner()) | |
| 148 | 157 | }) |
| 149 | 158 | } |
| 150 | 159 | |
| ... | ... | @@ -213,13 +222,16 @@ impl TyBuilder<()> { |
| 213 | 222 | } |
| 214 | 223 | |
| 215 | 224 | pub fn unknown_subst(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> Substitution { |
| 225 | let interner = DbInterner::conjure(); | |
| 216 | 226 | let params = generics(db, def.into()); |
| 217 | 227 | Substitution::from_iter( |
| 218 | 228 | Interner, |
| 219 | 229 | params.iter_id().map(|id| match id { |
| 220 | 230 | GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner), |
| 221 | 231 | GenericParamId::ConstParamId(id) => { |
| 222 | unknown_const_as_generic(db.const_param_ty(id)).cast(Interner) | |
| 232 | unknown_const_as_generic(db.const_param_ty_ns(id)) | |
| 233 | .to_chalk(interner) | |
| 234 | .cast(Interner) | |
| 223 | 235 | } |
| 224 | 236 | GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner), |
| 225 | 237 | }), |
| ... | ... | @@ -261,6 +273,7 @@ impl TyBuilder<hir_def::AdtId> { |
| 261 | 273 | db: &dyn HirDatabase, |
| 262 | 274 | mut fallback: impl FnMut() -> Ty, |
| 263 | 275 | ) -> Self { |
| 276 | let interner = DbInterner::conjure(); | |
| 264 | 277 | // Note that we're building ADT, so we never have parent generic parameters. |
| 265 | 278 | let defaults = db.generic_defaults(self.data.into()); |
| 266 | 279 | |
| ... | ... | @@ -281,7 +294,9 @@ impl TyBuilder<hir_def::AdtId> { |
| 281 | 294 | // The defaults may be missing if no param has default, so fill that. |
| 282 | 295 | let filler = self.param_kinds[self.vec.len()..].iter().map(|x| match x { |
| 283 | 296 | ParamKind::Type => fallback().cast(Interner), |
| 284 | ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()), | |
| 297 | ParamKind::Const(ty) => { | |
| 298 | unknown_const_as_generic(ty.to_nextsolver(interner)).to_chalk(interner) | |
| 299 | } | |
| 285 | 300 | ParamKind::Lifetime => error_lifetime().cast(Interner), |
| 286 | 301 | }); |
| 287 | 302 | self.vec.extend(filler.casted(Interner)); |
src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs+1-14| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | //! about the code that Chalk needs. |
| 3 | 3 | use hir_def::{CallableDefId, GenericDefId}; |
| 4 | 4 | |
| 5 | use crate::{Interner, Substitution, db::HirDatabase, mapping::from_chalk}; | |
| 5 | use crate::{Interner, db::HirDatabase, mapping::from_chalk}; | |
| 6 | 6 | |
| 7 | 7 | pub(crate) type AssocTypeId = chalk_ir::AssocTypeId<Interner>; |
| 8 | 8 | pub(crate) type TraitId = chalk_ir::TraitId<Interner>; |
| ... | ... | @@ -53,16 +53,3 @@ pub(crate) fn adt_variance_query(db: &dyn HirDatabase, adt_id: hir_def::AdtId) - |
| 53 | 53 | }), |
| 54 | 54 | ) |
| 55 | 55 | } |
| 56 | ||
| 57 | /// Returns instantiated predicates. | |
| 58 | pub(super) fn convert_where_clauses( | |
| 59 | db: &dyn HirDatabase, | |
| 60 | def: GenericDefId, | |
| 61 | substs: &Substitution, | |
| 62 | ) -> Vec<chalk_ir::QuantifiedWhereClause<Interner>> { | |
| 63 | db.generic_predicates(def) | |
| 64 | .iter() | |
| 65 | .cloned() | |
| 66 | .map(|pred| pred.substitute(Interner, substs)) | |
| 67 | .collect() | |
| 68 | } |
src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs+7-320| ... | ... | @@ -1,66 +1,32 @@ |
| 1 | 1 | //! Various extensions traits for Chalk types. |
| 2 | 2 | |
| 3 | use chalk_ir::{ | |
| 4 | FloatTy, IntTy, Mutability, Scalar, TyVariableKind, TypeOutlives, UintTy, cast::Cast, | |
| 5 | }; | |
| 6 | use hir_def::{ | |
| 7 | DefWithBodyId, FunctionId, GenericDefId, HasModule, ItemContainerId, Lookup, TraitId, | |
| 8 | builtin_type::{BuiltinFloat, BuiltinInt, BuiltinType, BuiltinUint}, | |
| 9 | hir::generics::{TypeOrConstParamData, TypeParamProvenance}, | |
| 10 | lang_item::LangItem, | |
| 11 | type_ref::Rawness, | |
| 12 | }; | |
| 3 | use chalk_ir::Mutability; | |
| 4 | use hir_def::{FunctionId, ItemContainerId, Lookup, TraitId}; | |
| 13 | 5 | |
| 14 | 6 | use crate::{ |
| 15 | AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, | |
| 16 | ClosureId, DynTy, FnPointer, ImplTraitId, InEnvironment, Interner, Lifetime, ProjectionTy, | |
| 17 | QuantifiedWhereClause, Substitution, ToChalk, TraitRef, Ty, TyBuilder, TyKind, TypeFlags, | |
| 18 | WhereClause, | |
| 19 | db::HirDatabase, | |
| 20 | from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx, | |
| 21 | generics::generics, | |
| 22 | next_solver::{DbInterner, mapping::NextSolverToChalk}, | |
| 23 | to_chalk_trait_id, | |
| 7 | AdtId, Binders, CallableDefId, CallableSig, DynTy, Interner, Lifetime, ProjectionTy, | |
| 8 | Substitution, ToChalk, TraitRef, Ty, TyKind, TypeFlags, WhereClause, db::HirDatabase, | |
| 9 | from_assoc_type_id, from_chalk_trait_id, generics::generics, to_chalk_trait_id, | |
| 24 | 10 | utils::ClosureSubst, |
| 25 | 11 | }; |
| 26 | 12 | |
| 27 | pub trait TyExt { | |
| 13 | pub(crate) trait TyExt { | |
| 28 | 14 | fn is_unit(&self) -> bool; |
| 29 | fn is_integral(&self) -> bool; | |
| 30 | fn is_scalar(&self) -> bool; | |
| 31 | fn is_floating_point(&self) -> bool; | |
| 32 | fn is_never(&self) -> bool; | |
| 33 | fn is_str(&self) -> bool; | |
| 34 | 15 | fn is_unknown(&self) -> bool; |
| 35 | 16 | fn contains_unknown(&self) -> bool; |
| 36 | fn is_ty_var(&self) -> bool; | |
| 37 | fn is_union(&self) -> bool; | |
| 38 | 17 | |
| 39 | 18 | fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)>; |
| 40 | fn as_builtin(&self) -> Option<BuiltinType>; | |
| 41 | 19 | fn as_tuple(&self) -> Option<&Substitution>; |
| 42 | fn as_closure(&self) -> Option<ClosureId>; | |
| 43 | 20 | fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId>; |
| 44 | 21 | fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)>; |
| 45 | fn as_raw_ptr(&self) -> Option<(&Ty, Mutability)>; | |
| 46 | fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)>; | |
| 47 | fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId>; | |
| 48 | 22 | |
| 49 | 23 | fn callable_def(&self, db: &dyn HirDatabase) -> Option<CallableDefId>; |
| 50 | 24 | fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig>; |
| 51 | 25 | |
| 52 | 26 | fn strip_references(&self) -> &Ty; |
| 53 | fn strip_reference(&self) -> &Ty; | |
| 54 | 27 | |
| 55 | 28 | /// If this is a `dyn Trait`, returns that trait. |
| 56 | 29 | fn dyn_trait(&self) -> Option<TraitId>; |
| 57 | ||
| 58 | fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>>; | |
| 59 | fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId>; | |
| 60 | fn is_copy(self, db: &dyn HirDatabase, owner: DefWithBodyId) -> bool; | |
| 61 | ||
| 62 | /// FIXME: Get rid of this, it's not a good abstraction | |
| 63 | fn equals_ctor(&self, other: &Ty) -> bool; | |
| 64 | 30 | } |
| 65 | 31 | |
| 66 | 32 | impl TyExt for Ty { |
| ... | ... | @@ -68,33 +34,6 @@ impl TyExt for Ty { |
| 68 | 34 | matches!(self.kind(Interner), TyKind::Tuple(0, _)) |
| 69 | 35 | } |
| 70 | 36 | |
| 71 | fn is_integral(&self) -> bool { | |
| 72 | matches!( | |
| 73 | self.kind(Interner), | |
| 74 | TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_)) | |
| 75 | | TyKind::InferenceVar(_, TyVariableKind::Integer) | |
| 76 | ) | |
| 77 | } | |
| 78 | ||
| 79 | fn is_scalar(&self) -> bool { | |
| 80 | matches!(self.kind(Interner), TyKind::Scalar(_)) | |
| 81 | } | |
| 82 | ||
| 83 | fn is_floating_point(&self) -> bool { | |
| 84 | matches!( | |
| 85 | self.kind(Interner), | |
| 86 | TyKind::Scalar(Scalar::Float(_)) | TyKind::InferenceVar(_, TyVariableKind::Float) | |
| 87 | ) | |
| 88 | } | |
| 89 | ||
| 90 | fn is_never(&self) -> bool { | |
| 91 | matches!(self.kind(Interner), TyKind::Never) | |
| 92 | } | |
| 93 | ||
| 94 | fn is_str(&self) -> bool { | |
| 95 | matches!(self.kind(Interner), TyKind::Str) | |
| 96 | } | |
| 97 | ||
| 98 | 37 | fn is_unknown(&self) -> bool { |
| 99 | 38 | matches!(self.kind(Interner), TyKind::Error) |
| 100 | 39 | } |
| ... | ... | @@ -103,14 +42,6 @@ impl TyExt for Ty { |
| 103 | 42 | self.data(Interner).flags.contains(TypeFlags::HAS_ERROR) |
| 104 | 43 | } |
| 105 | 44 | |
| 106 | fn is_ty_var(&self) -> bool { | |
| 107 | matches!(self.kind(Interner), TyKind::InferenceVar(_, _)) | |
| 108 | } | |
| 109 | ||
| 110 | fn is_union(&self) -> bool { | |
| 111 | matches!(self.adt_id(Interner), Some(AdtId(hir_def::AdtId::UnionId(_)))) | |
| 112 | } | |
| 113 | ||
| 114 | 45 | fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)> { |
| 115 | 46 | match self.kind(Interner) { |
| 116 | 47 | TyKind::Adt(AdtId(adt), parameters) => Some((*adt, parameters)), |
| ... | ... | @@ -118,37 +49,6 @@ impl TyExt for Ty { |
| 118 | 49 | } |
| 119 | 50 | } |
| 120 | 51 | |
| 121 | fn as_builtin(&self) -> Option<BuiltinType> { | |
| 122 | match self.kind(Interner) { | |
| 123 | TyKind::Str => Some(BuiltinType::Str), | |
| 124 | TyKind::Scalar(Scalar::Bool) => Some(BuiltinType::Bool), | |
| 125 | TyKind::Scalar(Scalar::Char) => Some(BuiltinType::Char), | |
| 126 | TyKind::Scalar(Scalar::Float(fty)) => Some(BuiltinType::Float(match fty { | |
| 127 | FloatTy::F128 => BuiltinFloat::F128, | |
| 128 | FloatTy::F64 => BuiltinFloat::F64, | |
| 129 | FloatTy::F32 => BuiltinFloat::F32, | |
| 130 | FloatTy::F16 => BuiltinFloat::F16, | |
| 131 | })), | |
| 132 | TyKind::Scalar(Scalar::Int(ity)) => Some(BuiltinType::Int(match ity { | |
| 133 | IntTy::Isize => BuiltinInt::Isize, | |
| 134 | IntTy::I8 => BuiltinInt::I8, | |
| 135 | IntTy::I16 => BuiltinInt::I16, | |
| 136 | IntTy::I32 => BuiltinInt::I32, | |
| 137 | IntTy::I64 => BuiltinInt::I64, | |
| 138 | IntTy::I128 => BuiltinInt::I128, | |
| 139 | })), | |
| 140 | TyKind::Scalar(Scalar::Uint(ity)) => Some(BuiltinType::Uint(match ity { | |
| 141 | UintTy::Usize => BuiltinUint::Usize, | |
| 142 | UintTy::U8 => BuiltinUint::U8, | |
| 143 | UintTy::U16 => BuiltinUint::U16, | |
| 144 | UintTy::U32 => BuiltinUint::U32, | |
| 145 | UintTy::U64 => BuiltinUint::U64, | |
| 146 | UintTy::U128 => BuiltinUint::U128, | |
| 147 | })), | |
| 148 | _ => None, | |
| 149 | } | |
| 150 | } | |
| 151 | ||
| 152 | 52 | fn as_tuple(&self) -> Option<&Substitution> { |
| 153 | 53 | match self.kind(Interner) { |
| 154 | 54 | TyKind::Tuple(_, substs) => Some(substs), |
| ... | ... | @@ -156,13 +56,6 @@ impl TyExt for Ty { |
| 156 | 56 | } |
| 157 | 57 | } |
| 158 | 58 | |
| 159 | fn as_closure(&self) -> Option<ClosureId> { | |
| 160 | match self.kind(Interner) { | |
| 161 | TyKind::Closure(id, _) => Some(*id), | |
| 162 | _ => None, | |
| 163 | } | |
| 164 | } | |
| 165 | ||
| 166 | 59 | fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId> { |
| 167 | 60 | match self.callable_def(db) { |
| 168 | 61 | Some(CallableDefId::FunctionId(func)) => Some(func), |
| ... | ... | @@ -177,33 +70,6 @@ impl TyExt for Ty { |
| 177 | 70 | } |
| 178 | 71 | } |
| 179 | 72 | |
| 180 | fn as_raw_ptr(&self) -> Option<(&Ty, Mutability)> { | |
| 181 | match self.kind(Interner) { | |
| 182 | TyKind::Raw(mutability, ty) => Some((ty, *mutability)), | |
| 183 | _ => None, | |
| 184 | } | |
| 185 | } | |
| 186 | ||
| 187 | fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> { | |
| 188 | match self.kind(Interner) { | |
| 189 | TyKind::Ref(mutability, _, ty) => Some((ty, Rawness::Ref, *mutability)), | |
| 190 | TyKind::Raw(mutability, ty) => Some((ty, Rawness::RawPtr, *mutability)), | |
| 191 | _ => None, | |
| 192 | } | |
| 193 | } | |
| 194 | ||
| 195 | fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId> { | |
| 196 | match *self.kind(Interner) { | |
| 197 | TyKind::Adt(AdtId(adt), ..) => Some(adt.into()), | |
| 198 | TyKind::FnDef(callable, ..) => { | |
| 199 | Some(GenericDefId::from_callable(db, ToChalk::from_chalk(db, callable))) | |
| 200 | } | |
| 201 | TyKind::AssociatedType(type_alias, ..) => Some(from_assoc_type_id(type_alias).into()), | |
| 202 | TyKind::Foreign(type_alias, ..) => Some(from_foreign_def_id(type_alias).into()), | |
| 203 | _ => None, | |
| 204 | } | |
| 205 | } | |
| 206 | ||
| 207 | 73 | fn callable_def(&self, db: &dyn HirDatabase) -> Option<CallableDefId> { |
| 208 | 74 | match self.kind(Interner) { |
| 209 | 75 | &TyKind::FnDef(def, ..) => Some(ToChalk::from_chalk(db, def)), |
| ... | ... | @@ -244,177 +110,6 @@ impl TyExt for Ty { |
| 244 | 110 | } |
| 245 | 111 | t |
| 246 | 112 | } |
| 247 | ||
| 248 | fn strip_reference(&self) -> &Ty { | |
| 249 | self.as_reference().map_or(self, |(ty, _, _)| ty) | |
| 250 | } | |
| 251 | ||
| 252 | fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> { | |
| 253 | let handle_async_block_type_impl_trait = |def: DefWithBodyId| { | |
| 254 | let krate = def.module(db).krate(); | |
| 255 | if let Some(future_trait) = LangItem::Future.resolve_trait(db, krate) { | |
| 256 | // This is only used by type walking. | |
| 257 | // Parameters will be walked outside, and projection predicate is not used. | |
| 258 | // So just provide the Future trait. | |
| 259 | let impl_bound = Binders::empty( | |
| 260 | Interner, | |
| 261 | WhereClause::Implemented(TraitRef { | |
| 262 | trait_id: to_chalk_trait_id(future_trait), | |
| 263 | substitution: Substitution::empty(Interner), | |
| 264 | }), | |
| 265 | ); | |
| 266 | Some(vec![impl_bound]) | |
| 267 | } else { | |
| 268 | None | |
| 269 | } | |
| 270 | }; | |
| 271 | ||
| 272 | match self.kind(Interner) { | |
| 273 | TyKind::OpaqueType(opaque_ty_id, subst) => { | |
| 274 | match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) { | |
| 275 | ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => { | |
| 276 | handle_async_block_type_impl_trait(def) | |
| 277 | } | |
| 278 | ImplTraitId::ReturnTypeImplTrait(func, idx) => { | |
| 279 | db.return_type_impl_traits(func).map(|it| { | |
| 280 | let data = | |
| 281 | (*it).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone()); | |
| 282 | data.substitute(Interner, &subst).into_value_and_skipped_binders().0 | |
| 283 | }) | |
| 284 | } | |
| 285 | ImplTraitId::TypeAliasImplTrait(alias, idx) => { | |
| 286 | db.type_alias_impl_traits(alias).map(|it| { | |
| 287 | let data = | |
| 288 | (*it).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone()); | |
| 289 | data.substitute(Interner, &subst).into_value_and_skipped_binders().0 | |
| 290 | }) | |
| 291 | } | |
| 292 | } | |
| 293 | } | |
| 294 | TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { | |
| 295 | let predicates = match db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into()) | |
| 296 | { | |
| 297 | ImplTraitId::ReturnTypeImplTrait(func, idx) => { | |
| 298 | db.return_type_impl_traits(func).map(|it| { | |
| 299 | let data = | |
| 300 | (*it).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone()); | |
| 301 | data.substitute(Interner, &opaque_ty.substitution) | |
| 302 | }) | |
| 303 | } | |
| 304 | ImplTraitId::TypeAliasImplTrait(alias, idx) => { | |
| 305 | db.type_alias_impl_traits(alias).map(|it| { | |
| 306 | let data = | |
| 307 | (*it).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone()); | |
| 308 | data.substitute(Interner, &opaque_ty.substitution) | |
| 309 | }) | |
| 310 | } | |
| 311 | ImplTraitId::AsyncBlockTypeImplTrait(def, _) => { | |
| 312 | return handle_async_block_type_impl_trait(def); | |
| 313 | } | |
| 314 | }; | |
| 315 | ||
| 316 | predicates.map(|it| it.into_value_and_skipped_binders().0) | |
| 317 | } | |
| 318 | TyKind::Placeholder(idx) => { | |
| 319 | let id = from_placeholder_idx(db, *idx).0; | |
| 320 | let generic_params = db.generic_params(id.parent); | |
| 321 | let param_data = &generic_params[id.local_id]; | |
| 322 | match param_data { | |
| 323 | TypeOrConstParamData::TypeParamData(p) => match p.provenance { | |
| 324 | TypeParamProvenance::ArgumentImplTrait => { | |
| 325 | let substs = TyBuilder::placeholder_subst(db, id.parent); | |
| 326 | let predicates = db | |
| 327 | .generic_predicates(id.parent) | |
| 328 | .iter() | |
| 329 | .map(|pred| pred.clone().substitute(Interner, &substs)) | |
| 330 | .filter(|wc| match wc.skip_binders() { | |
| 331 | WhereClause::Implemented(tr) => { | |
| 332 | &tr.self_type_parameter(Interner) == self | |
| 333 | } | |
| 334 | WhereClause::AliasEq(AliasEq { | |
| 335 | alias: AliasTy::Projection(proj), | |
| 336 | ty: _, | |
| 337 | }) => &proj.self_type_parameter(db) == self, | |
| 338 | WhereClause::TypeOutlives(TypeOutlives { ty, lifetime: _ }) => { | |
| 339 | ty == self | |
| 340 | } | |
| 341 | _ => false, | |
| 342 | }) | |
| 343 | .collect::<Vec<_>>(); | |
| 344 | ||
| 345 | Some(predicates) | |
| 346 | } | |
| 347 | _ => None, | |
| 348 | }, | |
| 349 | _ => None, | |
| 350 | } | |
| 351 | } | |
| 352 | _ => None, | |
| 353 | } | |
| 354 | } | |
| 355 | ||
| 356 | fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> { | |
| 357 | match self.kind(Interner) { | |
| 358 | TyKind::AssociatedType(id, ..) => match from_assoc_type_id(*id).lookup(db).container { | |
| 359 | ItemContainerId::TraitId(trait_id) => Some(trait_id), | |
| 360 | _ => None, | |
| 361 | }, | |
| 362 | TyKind::Alias(AliasTy::Projection(projection_ty)) => { | |
| 363 | match from_assoc_type_id(projection_ty.associated_ty_id).lookup(db).container { | |
| 364 | ItemContainerId::TraitId(trait_id) => Some(trait_id), | |
| 365 | _ => None, | |
| 366 | } | |
| 367 | } | |
| 368 | _ => None, | |
| 369 | } | |
| 370 | } | |
| 371 | ||
| 372 | fn is_copy(self, db: &dyn HirDatabase, owner: DefWithBodyId) -> bool { | |
| 373 | let crate_id = owner.module(db).krate(); | |
| 374 | let Some(copy_trait) = LangItem::Copy.resolve_trait(db, crate_id) else { | |
| 375 | return false; | |
| 376 | }; | |
| 377 | let trait_ref = TyBuilder::trait_ref(db, copy_trait).push(self).build(); | |
| 378 | let env = db.trait_environment_for_body(owner); | |
| 379 | let goal = Canonical { | |
| 380 | value: InEnvironment::new( | |
| 381 | &env.env.to_chalk(DbInterner::new_with(db, Some(env.krate), env.block)), | |
| 382 | trait_ref.cast(Interner), | |
| 383 | ), | |
| 384 | binders: CanonicalVarKinds::empty(Interner), | |
| 385 | }; | |
| 386 | !db.trait_solve(crate_id, None, goal).no_solution() | |
| 387 | } | |
| 388 | ||
| 389 | fn equals_ctor(&self, other: &Ty) -> bool { | |
| 390 | match (self.kind(Interner), other.kind(Interner)) { | |
| 391 | (TyKind::Adt(adt, ..), TyKind::Adt(adt2, ..)) => adt == adt2, | |
| 392 | (TyKind::Slice(_), TyKind::Slice(_)) | (TyKind::Array(_, _), TyKind::Array(_, _)) => { | |
| 393 | true | |
| 394 | } | |
| 395 | (TyKind::FnDef(def_id, ..), TyKind::FnDef(def_id2, ..)) => def_id == def_id2, | |
| 396 | (TyKind::OpaqueType(ty_id, ..), TyKind::OpaqueType(ty_id2, ..)) => ty_id == ty_id2, | |
| 397 | (TyKind::AssociatedType(ty_id, ..), TyKind::AssociatedType(ty_id2, ..)) => { | |
| 398 | ty_id == ty_id2 | |
| 399 | } | |
| 400 | (TyKind::Foreign(ty_id, ..), TyKind::Foreign(ty_id2, ..)) => ty_id == ty_id2, | |
| 401 | (TyKind::Closure(id1, _), TyKind::Closure(id2, _)) => id1 == id2, | |
| 402 | (TyKind::Ref(mutability, ..), TyKind::Ref(mutability2, ..)) | |
| 403 | | (TyKind::Raw(mutability, ..), TyKind::Raw(mutability2, ..)) => { | |
| 404 | mutability == mutability2 | |
| 405 | } | |
| 406 | ( | |
| 407 | TyKind::Function(FnPointer { num_binders, sig, .. }), | |
| 408 | TyKind::Function(FnPointer { num_binders: num_binders2, sig: sig2, .. }), | |
| 409 | ) => num_binders == num_binders2 && sig == sig2, | |
| 410 | (TyKind::Tuple(cardinality, _), TyKind::Tuple(cardinality2, _)) => { | |
| 411 | cardinality == cardinality2 | |
| 412 | } | |
| 413 | (TyKind::Str, TyKind::Str) | (TyKind::Never, TyKind::Never) => true, | |
| 414 | (TyKind::Scalar(scalar), TyKind::Scalar(scalar2)) => scalar == scalar2, | |
| 415 | _ => false, | |
| 416 | } | |
| 417 | } | |
| 418 | 113 | } |
| 419 | 114 | |
| 420 | 115 | pub trait ProjectionTyExt { |
| ... | ... | @@ -445,9 +140,8 @@ impl ProjectionTyExt for ProjectionTy { |
| 445 | 140 | } |
| 446 | 141 | } |
| 447 | 142 | |
| 448 | pub trait DynTyExt { | |
| 143 | pub(crate) trait DynTyExt { | |
| 449 | 144 | fn principal(&self) -> Option<Binders<Binders<&TraitRef>>>; |
| 450 | fn principal_id(&self) -> Option<chalk_ir::TraitId<Interner>>; | |
| 451 | 145 | } |
| 452 | 146 | |
| 453 | 147 | impl DynTyExt for DynTy { |
| ... | ... | @@ -461,13 +155,6 @@ impl DynTyExt for DynTy { |
| 461 | 155 | }) |
| 462 | 156 | }) |
| 463 | 157 | } |
| 464 | ||
| 465 | fn principal_id(&self) -> Option<chalk_ir::TraitId<Interner>> { | |
| 466 | self.bounds.skip_binders().interned().first().and_then(|b| match b.skip_binders() { | |
| 467 | crate::WhereClause::Implemented(trait_ref) => Some(trait_ref.trait_id), | |
| 468 | _ => None, | |
| 469 | }) | |
| 470 | } | |
| 471 | 158 | } |
| 472 | 159 | |
| 473 | 160 | pub trait TraitRefExt { |
src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs+208-218| ... | ... | @@ -1,67 +1,95 @@ |
| 1 | 1 | //! Constant evaluation details |
| 2 | 2 | |
| 3 | #[cfg(test)] | |
| 4 | mod tests; | |
| 5 | ||
| 3 | 6 | use base_db::Crate; |
| 4 | use chalk_ir::{BoundVar, DebruijnIndex, cast::Cast}; | |
| 5 | 7 | use hir_def::{ |
| 6 | EnumVariantId, GeneralConstId, HasModule as _, StaticId, | |
| 8 | EnumVariantId, GeneralConstId, | |
| 7 | 9 | expr_store::{Body, HygieneId, path::Path}, |
| 8 | 10 | hir::{Expr, ExprId}, |
| 9 | 11 | resolver::{Resolver, ValueNs}, |
| 10 | 12 | type_ref::LiteralConstRef, |
| 11 | 13 | }; |
| 14 | use hir_def::{HasModule, StaticId}; | |
| 12 | 15 | use hir_expand::Lookup; |
| 16 | use rustc_type_ir::{UnevaluatedConst, inherent::IntoKind}; | |
| 13 | 17 | use stdx::never; |
| 14 | 18 | use triomphe::Arc; |
| 15 | 19 | |
| 16 | 20 | use crate::{ |
| 17 | Const, ConstData, ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, Substitution, | |
| 18 | TraitEnvironment, Ty, TyBuilder, | |
| 21 | MemoryMap, TraitEnvironment, | |
| 19 | 22 | db::HirDatabase, |
| 20 | 23 | display::DisplayTarget, |
| 21 | 24 | generics::Generics, |
| 22 | 25 | infer::InferenceContext, |
| 23 | lower::ParamLoweringMode, | |
| 24 | next_solver::{DbInterner, mapping::ChalkToNextSolver}, | |
| 25 | to_placeholder_idx, | |
| 26 | mir::{MirEvalError, MirLowerError}, | |
| 27 | next_solver::{ | |
| 28 | Const, ConstBytes, ConstKind, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, | |
| 29 | ParamConst, SolverDefId, Ty, ValueConst, | |
| 30 | }, | |
| 26 | 31 | }; |
| 27 | 32 | |
| 28 | use super::mir::{MirEvalError, MirLowerError, interpret_mir, lower_to_mir, pad16}; | |
| 29 | ||
| 30 | /// Extension trait for [`Const`] | |
| 31 | pub trait ConstExt { | |
| 32 | /// Is a [`Const`] unknown? | |
| 33 | fn is_unknown(&self) -> bool; | |
| 34 | } | |
| 35 | ||
| 36 | impl ConstExt for Const { | |
| 37 | fn is_unknown(&self) -> bool { | |
| 38 | match self.data(Interner).value { | |
| 39 | // interned Unknown | |
| 40 | chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { | |
| 41 | interned: ConstScalar::Unknown, | |
| 42 | }) => true, | |
| 33 | use super::mir::{interpret_mir, lower_to_mir, pad16}; | |
| 43 | 34 | |
| 44 | // interned concrete anything else | |
| 45 | chalk_ir::ConstValue::Concrete(..) => false, | |
| 46 | ||
| 47 | _ => { | |
| 48 | tracing::error!( | |
| 49 | "is_unknown was called on a non-concrete constant value! {:?}", | |
| 50 | self | |
| 51 | ); | |
| 52 | true | |
| 35 | pub(crate) fn path_to_const<'a, 'g>( | |
| 36 | db: &'a dyn HirDatabase, | |
| 37 | resolver: &Resolver<'a>, | |
| 38 | path: &Path, | |
| 39 | args: impl FnOnce() -> &'g Generics, | |
| 40 | _expected_ty: Ty<'a>, | |
| 41 | ) -> Option<Const<'a>> { | |
| 42 | let interner = DbInterner::new_with(db, Some(resolver.krate()), None); | |
| 43 | match resolver.resolve_path_in_value_ns_fully(db, path, HygieneId::ROOT) { | |
| 44 | Some(ValueNs::GenericParam(p)) => { | |
| 45 | let args = args(); | |
| 46 | match args | |
| 47 | .type_or_const_param(p.into()) | |
| 48 | .and_then(|(idx, p)| p.const_param().map(|p| (idx, p.clone()))) | |
| 49 | { | |
| 50 | Some((idx, _param)) => { | |
| 51 | Some(Const::new_param(interner, ParamConst { index: idx as u32, id: p })) | |
| 52 | } | |
| 53 | None => { | |
| 54 | never!( | |
| 55 | "Generic list doesn't contain this param: {:?}, {:?}, {:?}", | |
| 56 | args, | |
| 57 | path, | |
| 58 | p | |
| 59 | ); | |
| 60 | None | |
| 61 | } | |
| 53 | 62 | } |
| 54 | 63 | } |
| 64 | Some(ValueNs::ConstId(c)) => { | |
| 65 | let args = GenericArgs::new_from_iter(interner, []); | |
| 66 | Some(Const::new( | |
| 67 | interner, | |
| 68 | rustc_type_ir::ConstKind::Unevaluated(UnevaluatedConst::new( | |
| 69 | SolverDefId::ConstId(c), | |
| 70 | args, | |
| 71 | )), | |
| 72 | )) | |
| 73 | } | |
| 74 | _ => None, | |
| 55 | 75 | } |
| 56 | 76 | } |
| 57 | 77 | |
| 78 | pub fn unknown_const<'db>(_ty: Ty<'db>) -> Const<'db> { | |
| 79 | Const::new(DbInterner::conjure(), rustc_type_ir::ConstKind::Error(ErrorGuaranteed)) | |
| 80 | } | |
| 81 | ||
| 82 | pub fn unknown_const_as_generic<'db>(ty: Ty<'db>) -> GenericArg<'db> { | |
| 83 | unknown_const(ty).into() | |
| 84 | } | |
| 85 | ||
| 58 | 86 | #[derive(Debug, Clone, PartialEq, Eq)] |
| 59 | pub enum ConstEvalError { | |
| 60 | MirLowerError(MirLowerError), | |
| 61 | MirEvalError(MirEvalError), | |
| 87 | pub enum ConstEvalError<'db> { | |
| 88 | MirLowerError(MirLowerError<'db>), | |
| 89 | MirEvalError(MirEvalError<'db>), | |
| 62 | 90 | } |
| 63 | 91 | |
| 64 | impl ConstEvalError { | |
| 92 | impl ConstEvalError<'_> { | |
| 65 | 93 | pub fn pretty_print( |
| 66 | 94 | &self, |
| 67 | 95 | f: &mut String, |
| ... | ... | @@ -80,8 +108,8 @@ impl ConstEvalError { |
| 80 | 108 | } |
| 81 | 109 | } |
| 82 | 110 | |
| 83 | impl From<MirLowerError> for ConstEvalError { | |
| 84 | fn from(value: MirLowerError) -> Self { | |
| 111 | impl<'db> From<MirLowerError<'db>> for ConstEvalError<'db> { | |
| 112 | fn from(value: MirLowerError<'db>) -> Self { | |
| 85 | 113 | match value { |
| 86 | 114 | MirLowerError::ConstEvalError(_, e) => *e, |
| 87 | 115 | _ => ConstEvalError::MirLowerError(value), |
| ... | ... | @@ -89,201 +117,118 @@ impl From<MirLowerError> for ConstEvalError { |
| 89 | 117 | } |
| 90 | 118 | } |
| 91 | 119 | |
| 92 | impl From<MirEvalError> for ConstEvalError { | |
| 93 | fn from(value: MirEvalError) -> Self { | |
| 120 | impl<'db> From<MirEvalError<'db>> for ConstEvalError<'db> { | |
| 121 | fn from(value: MirEvalError<'db>) -> Self { | |
| 94 | 122 | ConstEvalError::MirEvalError(value) |
| 95 | 123 | } |
| 96 | 124 | } |
| 97 | 125 | |
| 98 | pub(crate) fn path_to_const<'g>( | |
| 99 | db: &dyn HirDatabase, | |
| 100 | resolver: &Resolver<'_>, | |
| 101 | path: &Path, | |
| 102 | mode: ParamLoweringMode, | |
| 103 | args: impl FnOnce() -> &'g Generics, | |
| 104 | debruijn: DebruijnIndex, | |
| 105 | expected_ty: Ty, | |
| 106 | ) -> Option<Const> { | |
| 107 | match resolver.resolve_path_in_value_ns_fully(db, path, HygieneId::ROOT) { | |
| 108 | Some(ValueNs::GenericParam(p)) => { | |
| 109 | let ty = db.const_param_ty(p); | |
| 110 | let args = args(); | |
| 111 | let value = match mode { | |
| 112 | ParamLoweringMode::Placeholder => { | |
| 113 | let idx = args.type_or_const_param_idx(p.into()).unwrap(); | |
| 114 | ConstValue::Placeholder(to_placeholder_idx(db, p.into(), idx as u32)) | |
| 115 | } | |
| 116 | ParamLoweringMode::Variable => match args.type_or_const_param_idx(p.into()) { | |
| 117 | Some(it) => ConstValue::BoundVar(BoundVar::new(debruijn, it)), | |
| 118 | None => { | |
| 119 | never!( | |
| 120 | "Generic list doesn't contain this param: {:?}, {:?}, {:?}", | |
| 121 | args, | |
| 122 | path, | |
| 123 | p | |
| 124 | ); | |
| 125 | return None; | |
| 126 | } | |
| 127 | }, | |
| 128 | }; | |
| 129 | Some(ConstData { ty, value }.intern(Interner)) | |
| 130 | } | |
| 131 | Some(ValueNs::ConstId(c)) => Some(intern_const_scalar( | |
| 132 | ConstScalar::UnevaluatedConst(c.into(), Substitution::empty(Interner)), | |
| 133 | expected_ty, | |
| 134 | )), | |
| 135 | // FIXME: With feature(adt_const_params), we also need to consider other things here, e.g. struct constructors. | |
| 136 | _ => None, | |
| 137 | } | |
| 138 | } | |
| 139 | ||
| 140 | pub fn unknown_const(ty: Ty) -> Const { | |
| 141 | ConstData { | |
| 142 | ty, | |
| 143 | value: ConstValue::Concrete(chalk_ir::ConcreteConst { interned: ConstScalar::Unknown }), | |
| 144 | } | |
| 145 | .intern(Interner) | |
| 146 | } | |
| 147 | ||
| 148 | pub fn unknown_const_as_generic(ty: Ty) -> GenericArg { | |
| 149 | unknown_const(ty).cast(Interner) | |
| 150 | } | |
| 151 | ||
| 152 | 126 | /// Interns a constant scalar with the given type |
| 153 | pub fn intern_const_scalar(value: ConstScalar, ty: Ty) -> Const { | |
| 154 | ConstData { ty, value: ConstValue::Concrete(chalk_ir::ConcreteConst { interned: value }) } | |
| 155 | .intern(Interner) | |
| 156 | } | |
| 157 | ||
| 158 | /// Interns a constant scalar with the given type | |
| 159 | pub fn intern_const_ref( | |
| 160 | db: &dyn HirDatabase, | |
| 127 | pub fn intern_const_ref<'a>( | |
| 128 | db: &'a dyn HirDatabase, | |
| 161 | 129 | value: &LiteralConstRef, |
| 162 | ty: Ty, | |
| 130 | ty: Ty<'a>, | |
| 163 | 131 | krate: Crate, |
| 164 | ) -> Const { | |
| 132 | ) -> Const<'a> { | |
| 165 | 133 | let interner = DbInterner::new_with(db, Some(krate), None); |
| 166 | let layout = || db.layout_of_ty(ty.to_nextsolver(interner), TraitEnvironment::empty(krate)); | |
| 167 | let bytes = match value { | |
| 134 | let layout = db.layout_of_ty(ty, TraitEnvironment::empty(krate)); | |
| 135 | let kind = match value { | |
| 168 | 136 | LiteralConstRef::Int(i) => { |
| 169 | 137 | // FIXME: We should handle failure of layout better. |
| 170 | let size = layout().map(|it| it.size.bytes_usize()).unwrap_or(16); | |
| 171 | ConstScalar::Bytes(i.to_le_bytes()[0..size].into(), MemoryMap::default()) | |
| 138 | let size = layout.map(|it| it.size.bytes_usize()).unwrap_or(16); | |
| 139 | rustc_type_ir::ConstKind::Value(ValueConst::new( | |
| 140 | ty, | |
| 141 | ConstBytes { | |
| 142 | memory: i.to_le_bytes()[0..size].into(), | |
| 143 | memory_map: MemoryMap::default(), | |
| 144 | }, | |
| 145 | )) | |
| 172 | 146 | } |
| 173 | 147 | LiteralConstRef::UInt(i) => { |
| 174 | let size = layout().map(|it| it.size.bytes_usize()).unwrap_or(16); | |
| 175 | ConstScalar::Bytes(i.to_le_bytes()[0..size].into(), MemoryMap::default()) | |
| 176 | } | |
| 177 | LiteralConstRef::Bool(b) => ConstScalar::Bytes(Box::new([*b as u8]), MemoryMap::default()), | |
| 178 | LiteralConstRef::Char(c) => { | |
| 179 | ConstScalar::Bytes((*c as u32).to_le_bytes().into(), MemoryMap::default()) | |
| 148 | let size = layout.map(|it| it.size.bytes_usize()).unwrap_or(16); | |
| 149 | rustc_type_ir::ConstKind::Value(ValueConst::new( | |
| 150 | ty, | |
| 151 | ConstBytes { | |
| 152 | memory: i.to_le_bytes()[0..size].into(), | |
| 153 | memory_map: MemoryMap::default(), | |
| 154 | }, | |
| 155 | )) | |
| 180 | 156 | } |
| 181 | LiteralConstRef::Unknown => ConstScalar::Unknown, | |
| 157 | LiteralConstRef::Bool(b) => rustc_type_ir::ConstKind::Value(ValueConst::new( | |
| 158 | ty, | |
| 159 | ConstBytes { memory: Box::new([*b as u8]), memory_map: MemoryMap::default() }, | |
| 160 | )), | |
| 161 | LiteralConstRef::Char(c) => rustc_type_ir::ConstKind::Value(ValueConst::new( | |
| 162 | ty, | |
| 163 | ConstBytes { | |
| 164 | memory: (*c as u32).to_le_bytes().into(), | |
| 165 | memory_map: MemoryMap::default(), | |
| 166 | }, | |
| 167 | )), | |
| 168 | LiteralConstRef::Unknown => rustc_type_ir::ConstKind::Error(ErrorGuaranteed), | |
| 182 | 169 | }; |
| 183 | intern_const_scalar(bytes, ty) | |
| 170 | Const::new(interner, kind) | |
| 184 | 171 | } |
| 185 | 172 | |
| 186 | 173 | /// Interns a possibly-unknown target usize |
| 187 | pub fn usize_const(db: &dyn HirDatabase, value: Option<u128>, krate: Crate) -> Const { | |
| 174 | pub fn usize_const<'db>(db: &'db dyn HirDatabase, value: Option<u128>, krate: Crate) -> Const<'db> { | |
| 188 | 175 | intern_const_ref( |
| 189 | 176 | db, |
| 190 | 177 | &value.map_or(LiteralConstRef::Unknown, LiteralConstRef::UInt), |
| 191 | TyBuilder::usize(), | |
| 178 | Ty::new_uint(DbInterner::new_with(db, Some(krate), None), rustc_type_ir::UintTy::Usize), | |
| 192 | 179 | krate, |
| 193 | 180 | ) |
| 194 | 181 | } |
| 195 | 182 | |
| 196 | pub fn try_const_usize(db: &dyn HirDatabase, c: &Const) -> Option<u128> { | |
| 197 | match &c.data(Interner).value { | |
| 198 | chalk_ir::ConstValue::BoundVar(_) => None, | |
| 199 | chalk_ir::ConstValue::InferenceVar(_) => None, | |
| 200 | chalk_ir::ConstValue::Placeholder(_) => None, | |
| 201 | chalk_ir::ConstValue::Concrete(c) => match &c.interned { | |
| 202 | ConstScalar::Bytes(it, _) => Some(u128::from_le_bytes(pad16(it, false))), | |
| 203 | ConstScalar::UnevaluatedConst(c, subst) => { | |
| 204 | let ec = db.const_eval(*c, subst.clone(), None).ok()?; | |
| 205 | try_const_usize(db, &ec) | |
| 206 | } | |
| 207 | _ => None, | |
| 208 | }, | |
| 209 | } | |
| 210 | } | |
| 211 | ||
| 212 | pub fn try_const_isize(db: &dyn HirDatabase, c: &Const) -> Option<i128> { | |
| 213 | match &c.data(Interner).value { | |
| 214 | chalk_ir::ConstValue::BoundVar(_) => None, | |
| 215 | chalk_ir::ConstValue::InferenceVar(_) => None, | |
| 216 | chalk_ir::ConstValue::Placeholder(_) => None, | |
| 217 | chalk_ir::ConstValue::Concrete(c) => match &c.interned { | |
| 218 | ConstScalar::Bytes(it, _) => Some(i128::from_le_bytes(pad16(it, true))), | |
| 219 | ConstScalar::UnevaluatedConst(c, subst) => { | |
| 220 | let ec = db.const_eval(*c, subst.clone(), None).ok()?; | |
| 221 | try_const_isize(db, &ec) | |
| 222 | } | |
| 223 | _ => None, | |
| 224 | }, | |
| 183 | pub fn try_const_usize<'db>(db: &'db dyn HirDatabase, c: Const<'db>) -> Option<u128> { | |
| 184 | match c.kind() { | |
| 185 | ConstKind::Param(_) => None, | |
| 186 | ConstKind::Infer(_) => None, | |
| 187 | ConstKind::Bound(_, _) => None, | |
| 188 | ConstKind::Placeholder(_) => None, | |
| 189 | ConstKind::Unevaluated(unevaluated_const) => { | |
| 190 | let c = match unevaluated_const.def { | |
| 191 | SolverDefId::ConstId(id) => GeneralConstId::ConstId(id), | |
| 192 | SolverDefId::StaticId(id) => GeneralConstId::StaticId(id), | |
| 193 | _ => unreachable!(), | |
| 194 | }; | |
| 195 | let subst = unevaluated_const.args; | |
| 196 | let ec = db.const_eval(c, subst, None).ok()?; | |
| 197 | try_const_usize(db, ec) | |
| 198 | } | |
| 199 | ConstKind::Value(val) => Some(u128::from_le_bytes(pad16(&val.value.inner().memory, false))), | |
| 200 | ConstKind::Error(_) => None, | |
| 201 | ConstKind::Expr(_) => None, | |
| 225 | 202 | } |
| 226 | 203 | } |
| 227 | 204 | |
| 228 | pub(crate) fn const_eval_cycle_result( | |
| 229 | _: &dyn HirDatabase, | |
| 230 | _: GeneralConstId, | |
| 231 | _: Substitution, | |
| 232 | _: Option<Arc<TraitEnvironment<'_>>>, | |
| 233 | ) -> Result<Const, ConstEvalError> { | |
| 234 | Err(ConstEvalError::MirLowerError(MirLowerError::Loop)) | |
| 235 | } | |
| 236 | ||
| 237 | pub(crate) fn const_eval_static_cycle_result( | |
| 238 | _: &dyn HirDatabase, | |
| 239 | _: StaticId, | |
| 240 | ) -> Result<Const, ConstEvalError> { | |
| 241 | Err(ConstEvalError::MirLowerError(MirLowerError::Loop)) | |
| 242 | } | |
| 243 | ||
| 244 | pub(crate) fn const_eval_discriminant_cycle_result( | |
| 245 | _: &dyn HirDatabase, | |
| 246 | _: EnumVariantId, | |
| 247 | ) -> Result<i128, ConstEvalError> { | |
| 248 | Err(ConstEvalError::MirLowerError(MirLowerError::Loop)) | |
| 249 | } | |
| 250 | ||
| 251 | pub(crate) fn const_eval_query( | |
| 252 | db: &dyn HirDatabase, | |
| 253 | def: GeneralConstId, | |
| 254 | subst: Substitution, | |
| 255 | trait_env: Option<Arc<TraitEnvironment<'_>>>, | |
| 256 | ) -> Result<Const, ConstEvalError> { | |
| 257 | let body = match def { | |
| 258 | GeneralConstId::ConstId(c) => { | |
| 259 | db.monomorphized_mir_body(c.into(), subst, db.trait_environment(c.into()))? | |
| 260 | } | |
| 261 | GeneralConstId::StaticId(s) => { | |
| 262 | let krate = s.module(db).krate(); | |
| 263 | db.monomorphized_mir_body(s.into(), subst, TraitEnvironment::empty(krate))? | |
| 205 | pub fn try_const_isize<'db>(db: &'db dyn HirDatabase, c: &Const<'db>) -> Option<i128> { | |
| 206 | match (*c).kind() { | |
| 207 | ConstKind::Param(_) => None, | |
| 208 | ConstKind::Infer(_) => None, | |
| 209 | ConstKind::Bound(_, _) => None, | |
| 210 | ConstKind::Placeholder(_) => None, | |
| 211 | ConstKind::Unevaluated(unevaluated_const) => { | |
| 212 | let c = match unevaluated_const.def { | |
| 213 | SolverDefId::ConstId(id) => GeneralConstId::ConstId(id), | |
| 214 | SolverDefId::StaticId(id) => GeneralConstId::StaticId(id), | |
| 215 | _ => unreachable!(), | |
| 216 | }; | |
| 217 | let subst = unevaluated_const.args; | |
| 218 | let ec = db.const_eval(c, subst, None).ok()?; | |
| 219 | try_const_isize(db, &ec) | |
| 264 | 220 | } |
| 265 | }; | |
| 266 | let c = interpret_mir(db, body, false, trait_env)?.0?; | |
| 267 | Ok(c) | |
| 268 | } | |
| 269 | ||
| 270 | pub(crate) fn const_eval_static_query( | |
| 271 | db: &dyn HirDatabase, | |
| 272 | def: StaticId, | |
| 273 | ) -> Result<Const, ConstEvalError> { | |
| 274 | let body = db.monomorphized_mir_body( | |
| 275 | def.into(), | |
| 276 | Substitution::empty(Interner), | |
| 277 | db.trait_environment_for_body(def.into()), | |
| 278 | )?; | |
| 279 | let c = interpret_mir(db, body, false, None)?.0?; | |
| 280 | Ok(c) | |
| 221 | ConstKind::Value(val) => Some(i128::from_le_bytes(pad16(&val.value.inner().memory, true))), | |
| 222 | ConstKind::Error(_) => None, | |
| 223 | ConstKind::Expr(_) => None, | |
| 224 | } | |
| 281 | 225 | } |
| 282 | 226 | |
| 283 | pub(crate) fn const_eval_discriminant_variant( | |
| 284 | db: &dyn HirDatabase, | |
| 227 | pub(crate) fn const_eval_discriminant_variant<'db>( | |
| 228 | db: &'db dyn HirDatabase, | |
| 285 | 229 | variant_id: EnumVariantId, |
| 286 | ) -> Result<i128, ConstEvalError> { | |
| 230 | ) -> Result<i128, ConstEvalError<'db>> { | |
| 231 | let interner = DbInterner::new_with(db, None, None); | |
| 287 | 232 | let def = variant_id.into(); |
| 288 | 233 | let body = db.body(def); |
| 289 | 234 | let loc = variant_id.lookup(db); |
| ... | ... | @@ -305,14 +250,14 @@ pub(crate) fn const_eval_discriminant_variant( |
| 305 | 250 | |
| 306 | 251 | let mir_body = db.monomorphized_mir_body( |
| 307 | 252 | def, |
| 308 | Substitution::empty(Interner), | |
| 253 | GenericArgs::new_from_iter(interner, []), | |
| 309 | 254 | db.trait_environment_for_body(def), |
| 310 | 255 | )?; |
| 311 | 256 | let c = interpret_mir(db, mir_body, false, None)?.0?; |
| 312 | 257 | let c = if is_signed { |
| 313 | 258 | try_const_isize(db, &c).unwrap() |
| 314 | 259 | } else { |
| 315 | try_const_usize(db, &c).unwrap() as i128 | |
| 260 | try_const_usize(db, c).unwrap() as i128 | |
| 316 | 261 | }; |
| 317 | 262 | Ok(c) |
| 318 | 263 | } |
| ... | ... | @@ -320,13 +265,7 @@ pub(crate) fn const_eval_discriminant_variant( |
| 320 | 265 | // FIXME: Ideally constants in const eval should have separate body (issue #7434), and this function should |
| 321 | 266 | // get an `InferenceResult` instead of an `InferenceContext`. And we should remove `ctx.clone().resolve_all()` here |
| 322 | 267 | // and make this function private. See the fixme comment on `InferenceContext::resolve_all`. |
| 323 | pub(crate) fn eval_to_const( | |
| 324 | expr: ExprId, | |
| 325 | mode: ParamLoweringMode, | |
| 326 | ctx: &mut InferenceContext<'_>, | |
| 327 | debruijn: DebruijnIndex, | |
| 328 | ) -> Const { | |
| 329 | let db = ctx.db; | |
| 268 | pub(crate) fn eval_to_const<'db>(expr: ExprId, ctx: &mut InferenceContext<'_, 'db>) -> Const<'db> { | |
| 330 | 269 | let infer = ctx.fixme_resolve_all_clone(); |
| 331 | 270 | fn has_closure(body: &Body, expr: ExprId) -> bool { |
| 332 | 271 | if matches!(body[expr], Expr::Closure { .. }) { |
| ... | ... | @@ -338,23 +277,74 @@ pub(crate) fn eval_to_const( |
| 338 | 277 | } |
| 339 | 278 | if has_closure(ctx.body, expr) { |
| 340 | 279 | // Type checking clousres need an isolated body (See the above FIXME). Bail out early to prevent panic. |
| 341 | return unknown_const(infer[expr].clone()); | |
| 280 | return unknown_const(infer[expr]); | |
| 342 | 281 | } |
| 343 | 282 | if let Expr::Path(p) = &ctx.body[expr] { |
| 344 | 283 | let resolver = &ctx.resolver; |
| 345 | if let Some(c) = | |
| 346 | path_to_const(db, resolver, p, mode, || ctx.generics(), debruijn, infer[expr].clone()) | |
| 347 | { | |
| 284 | if let Some(c) = path_to_const(ctx.db, resolver, p, || ctx.generics(), infer[expr]) { | |
| 348 | 285 | return c; |
| 349 | 286 | } |
| 350 | 287 | } |
| 351 | 288 | if let Ok(mir_body) = lower_to_mir(ctx.db, ctx.owner, ctx.body, &infer, expr) |
| 352 | && let Ok((Ok(result), _)) = interpret_mir(db, Arc::new(mir_body), true, None) | |
| 289 | && let Ok((Ok(result), _)) = interpret_mir(ctx.db, Arc::new(mir_body), true, None) | |
| 353 | 290 | { |
| 354 | 291 | return result; |
| 355 | 292 | } |
| 356 | unknown_const(infer[expr].clone()) | |
| 293 | unknown_const(infer[expr]) | |
| 357 | 294 | } |
| 358 | 295 | |
| 359 | #[cfg(test)] | |
| 360 | mod tests; | |
| 296 | pub(crate) fn const_eval_cycle_result<'db>( | |
| 297 | _: &'db dyn HirDatabase, | |
| 298 | _: GeneralConstId, | |
| 299 | _: GenericArgs<'db>, | |
| 300 | _: Option<Arc<TraitEnvironment<'db>>>, | |
| 301 | ) -> Result<Const<'db>, ConstEvalError<'db>> { | |
| 302 | Err(ConstEvalError::MirLowerError(MirLowerError::Loop)) | |
| 303 | } | |
| 304 | ||
| 305 | pub(crate) fn const_eval_static_cycle_result<'db>( | |
| 306 | _: &'db dyn HirDatabase, | |
| 307 | _: StaticId, | |
| 308 | ) -> Result<Const<'db>, ConstEvalError<'db>> { | |
| 309 | Err(ConstEvalError::MirLowerError(MirLowerError::Loop)) | |
| 310 | } | |
| 311 | ||
| 312 | pub(crate) fn const_eval_discriminant_cycle_result<'db>( | |
| 313 | _: &'db dyn HirDatabase, | |
| 314 | _: EnumVariantId, | |
| 315 | ) -> Result<i128, ConstEvalError<'db>> { | |
| 316 | Err(ConstEvalError::MirLowerError(MirLowerError::Loop)) | |
| 317 | } | |
| 318 | ||
| 319 | pub(crate) fn const_eval_query<'db>( | |
| 320 | db: &'db dyn HirDatabase, | |
| 321 | def: GeneralConstId, | |
| 322 | subst: GenericArgs<'db>, | |
| 323 | trait_env: Option<Arc<TraitEnvironment<'db>>>, | |
| 324 | ) -> Result<Const<'db>, ConstEvalError<'db>> { | |
| 325 | let body = match def { | |
| 326 | GeneralConstId::ConstId(c) => { | |
| 327 | db.monomorphized_mir_body(c.into(), subst, db.trait_environment(c.into()))? | |
| 328 | } | |
| 329 | GeneralConstId::StaticId(s) => { | |
| 330 | let krate = s.module(db).krate(); | |
| 331 | db.monomorphized_mir_body(s.into(), subst, TraitEnvironment::empty(krate))? | |
| 332 | } | |
| 333 | }; | |
| 334 | let c = interpret_mir(db, body, false, trait_env)?.0?; | |
| 335 | Ok(c) | |
| 336 | } | |
| 337 | ||
| 338 | pub(crate) fn const_eval_static_query<'db>( | |
| 339 | db: &'db dyn HirDatabase, | |
| 340 | def: StaticId, | |
| 341 | ) -> Result<Const<'db>, ConstEvalError<'db>> { | |
| 342 | let interner = DbInterner::new_with(db, None, None); | |
| 343 | let body = db.monomorphized_mir_body( | |
| 344 | def.into(), | |
| 345 | GenericArgs::new_from_iter(interner, []), | |
| 346 | db.trait_environment_for_body(def.into()), | |
| 347 | )?; | |
| 348 | let c = interpret_mir(db, body, false, None)?.0?; | |
| 349 | Ok(c) | |
| 350 | } |
src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs+27-20| ... | ... | @@ -1,17 +1,23 @@ |
| 1 | 1 | use base_db::RootQueryDb; |
| 2 | use chalk_ir::Substitution; | |
| 3 | 2 | use hir_def::db::DefDatabase; |
| 4 | 3 | use hir_expand::EditionedFileId; |
| 5 | 4 | use rustc_apfloat::{ |
| 6 | 5 | Float, |
| 7 | 6 | ieee::{Half as f16, Quad as f128}, |
| 8 | 7 | }; |
| 8 | use rustc_type_ir::inherent::IntoKind; | |
| 9 | 9 | use test_fixture::WithFixture; |
| 10 | 10 | use test_utils::skip_slow_tests; |
| 11 | 11 | |
| 12 | 12 | use crate::{ |
| 13 | Const, ConstScalar, Interner, MemoryMap, consteval::try_const_usize, db::HirDatabase, | |
| 14 | display::DisplayTarget, mir::pad16, setup_tracing, test_db::TestDB, | |
| 13 | MemoryMap, | |
| 14 | consteval::try_const_usize, | |
| 15 | db::HirDatabase, | |
| 16 | display::DisplayTarget, | |
| 17 | mir::pad16, | |
| 18 | next_solver::{Const, ConstBytes, ConstKind, DbInterner, GenericArgs}, | |
| 19 | setup_tracing, | |
| 20 | test_db::TestDB, | |
| 15 | 21 | }; |
| 16 | 22 | |
| 17 | 23 | use super::{ |
| ... | ... | @@ -21,7 +27,7 @@ use super::{ |
| 21 | 27 | |
| 22 | 28 | mod intrinsics; |
| 23 | 29 | |
| 24 | fn simplify(e: ConstEvalError) -> ConstEvalError { | |
| 30 | fn simplify(e: ConstEvalError<'_>) -> ConstEvalError<'_> { | |
| 25 | 31 | match e { |
| 26 | 32 | ConstEvalError::MirEvalError(MirEvalError::InFunction(e, _)) => { |
| 27 | 33 | simplify(ConstEvalError::MirEvalError(*e)) |
| ... | ... | @@ -33,10 +39,10 @@ fn simplify(e: ConstEvalError) -> ConstEvalError { |
| 33 | 39 | #[track_caller] |
| 34 | 40 | fn check_fail( |
| 35 | 41 | #[rust_analyzer::rust_fixture] ra_fixture: &str, |
| 36 | error: impl FnOnce(ConstEvalError) -> bool, | |
| 42 | error: impl FnOnce(ConstEvalError<'_>) -> bool, | |
| 37 | 43 | ) { |
| 38 | 44 | let (db, file_id) = TestDB::with_single_file(ra_fixture); |
| 39 | salsa::attach(&db, || match eval_goal(&db, file_id) { | |
| 45 | crate::attach_db(&db, || match eval_goal(&db, file_id) { | |
| 40 | 46 | Ok(_) => panic!("Expected fail, but it succeeded"), |
| 41 | 47 | Err(e) => { |
| 42 | 48 | assert!(error(simplify(e.clone())), "Actual error was: {}", pretty_print_err(e, &db)) |
| ... | ... | @@ -79,7 +85,7 @@ fn check_answer( |
| 79 | 85 | check: impl FnOnce(&[u8], &MemoryMap<'_>), |
| 80 | 86 | ) { |
| 81 | 87 | let (db, file_ids) = TestDB::with_many_files(ra_fixture); |
| 82 | salsa::attach(&db, || { | |
| 88 | crate::attach_db(&db, || { | |
| 83 | 89 | let file_id = *file_ids.last().unwrap(); |
| 84 | 90 | let r = match eval_goal(&db, file_id) { |
| 85 | 91 | Ok(t) => t, |
| ... | ... | @@ -88,19 +94,17 @@ fn check_answer( |
| 88 | 94 | panic!("Error in evaluating goal: {err}"); |
| 89 | 95 | } |
| 90 | 96 | }; |
| 91 | match &r.data(Interner).value { | |
| 92 | chalk_ir::ConstValue::Concrete(c) => match &c.interned { | |
| 93 | ConstScalar::Bytes(b, mm) => { | |
| 94 | check(b, mm); | |
| 95 | } | |
| 96 | x => panic!("Expected number but found {x:?}"), | |
| 97 | }, | |
| 98 | _ => panic!("result of const eval wasn't a concrete const"), | |
| 97 | match r.kind() { | |
| 98 | ConstKind::Value(value) => { | |
| 99 | let ConstBytes { memory, memory_map } = value.value.inner(); | |
| 100 | check(memory, memory_map); | |
| 101 | } | |
| 102 | _ => panic!("Expected number but found {r:?}"), | |
| 99 | 103 | } |
| 100 | 104 | }); |
| 101 | 105 | } |
| 102 | 106 | |
| 103 | fn pretty_print_err(e: ConstEvalError, db: &TestDB) -> String { | |
| 107 | fn pretty_print_err(e: ConstEvalError<'_>, db: &TestDB) -> String { | |
| 104 | 108 | let mut err = String::new(); |
| 105 | 109 | let span_formatter = |file, range| format!("{file:?} {range:?}"); |
| 106 | 110 | let display_target = |
| ... | ... | @@ -117,8 +121,9 @@ fn pretty_print_err(e: ConstEvalError, db: &TestDB) -> String { |
| 117 | 121 | err |
| 118 | 122 | } |
| 119 | 123 | |
| 120 | fn eval_goal(db: &TestDB, file_id: EditionedFileId) -> Result<Const, ConstEvalError> { | |
| 124 | fn eval_goal(db: &TestDB, file_id: EditionedFileId) -> Result<Const<'_>, ConstEvalError<'_>> { | |
| 121 | 125 | let _tracing = setup_tracing(); |
| 126 | let interner = DbInterner::new_with(db, None, None); | |
| 122 | 127 | let module_id = db.module_for_file(file_id.file_id(db)); |
| 123 | 128 | let def_map = module_id.def_map(db); |
| 124 | 129 | let scope = &def_map[module_id.local_id].scope; |
| ... | ... | @@ -137,7 +142,7 @@ fn eval_goal(db: &TestDB, file_id: EditionedFileId) -> Result<Const, ConstEvalEr |
| 137 | 142 | _ => None, |
| 138 | 143 | }) |
| 139 | 144 | .expect("No const named GOAL found in the test"); |
| 140 | db.const_eval(const_id.into(), Substitution::empty(Interner), None) | |
| 145 | db.const_eval(const_id.into(), GenericArgs::new_from_iter(interner, []), None) | |
| 141 | 146 | } |
| 142 | 147 | |
| 143 | 148 | #[test] |
| ... | ... | @@ -2506,8 +2511,10 @@ fn enums() { |
| 2506 | 2511 | const GOAL: E = E::A; |
| 2507 | 2512 | "#, |
| 2508 | 2513 | ); |
| 2509 | let r = eval_goal(&db, file_id).unwrap(); | |
| 2510 | assert_eq!(try_const_usize(&db, &r), Some(1)); | |
| 2514 | crate::attach_db(&db, || { | |
| 2515 | let r = eval_goal(&db, file_id).unwrap(); | |
| 2516 | assert_eq!(try_const_usize(&db, r), Some(1)); | |
| 2517 | }) | |
| 2511 | 2518 | } |
| 2512 | 2519 | |
| 2513 | 2520 | #[test] |
src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs+6-3| ... | ... | @@ -354,8 +354,9 @@ fn overflowing_add() { |
| 354 | 354 | fn needs_drop() { |
| 355 | 355 | check_number( |
| 356 | 356 | r#" |
| 357 | //- minicore: drop, manually_drop, copy, sized | |
| 357 | //- minicore: drop, manually_drop, copy, sized, phantom_data | |
| 358 | 358 | use core::mem::ManuallyDrop; |
| 359 | use core::marker::PhantomData; | |
| 359 | 360 | extern "rust-intrinsic" { |
| 360 | 361 | pub fn needs_drop<T: ?Sized>() -> bool; |
| 361 | 362 | } |
| ... | ... | @@ -380,17 +381,19 @@ fn needs_drop() { |
| 380 | 381 | const fn opaque_copy() -> impl Sized + Copy { |
| 381 | 382 | || {} |
| 382 | 383 | } |
| 384 | struct RecursiveType(RecursiveType); | |
| 383 | 385 | trait Everything {} |
| 384 | 386 | impl<T> Everything for T {} |
| 385 | 387 | const GOAL: bool = !needs_drop::<i32>() && !needs_drop::<X>() |
| 386 | 388 | && needs_drop::<NeedsDrop>() && !needs_drop::<ManuallyDrop<NeedsDrop>>() |
| 387 | 389 | && needs_drop::<[NeedsDrop; 1]>() && !needs_drop::<[NeedsDrop; 0]>() |
| 388 | && needs_drop::<(X, NeedsDrop)>() | |
| 390 | && needs_drop::<(X, NeedsDrop)>() && !needs_drop::<PhantomData<NeedsDrop>>() | |
| 389 | 391 | && needs_drop::<Enum<NeedsDrop>>() && !needs_drop::<Enum<X>>() |
| 390 | 392 | && closure_needs_drop() |
| 391 | 393 | && !val_needs_drop(opaque()) && !val_needs_drop(opaque_copy()) |
| 392 | 394 | && needs_drop::<[NeedsDrop]>() && needs_drop::<dyn Everything>() |
| 393 | && !needs_drop::<&dyn Everything>() && !needs_drop::<str>(); | |
| 395 | && !needs_drop::<&dyn Everything>() && !needs_drop::<str>() | |
| 396 | && !needs_drop::<RecursiveType>(); | |
| 394 | 397 | "#, |
| 395 | 398 | 1, |
| 396 | 399 | ); |
src/tools/rust-analyzer/crates/hir-ty/src/consteval_chalk.rs created+108| ... | ... | @@ -0,0 +1,108 @@ |
| 1 | //! Constant evaluation details | |
| 2 | ||
| 3 | use base_db::Crate; | |
| 4 | use chalk_ir::{BoundVar, DebruijnIndex, cast::Cast}; | |
| 5 | use hir_def::{ | |
| 6 | expr_store::{HygieneId, path::Path}, | |
| 7 | resolver::{Resolver, ValueNs}, | |
| 8 | type_ref::LiteralConstRef, | |
| 9 | }; | |
| 10 | use stdx::never; | |
| 11 | ||
| 12 | use crate::{ | |
| 13 | Const, ConstData, ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, Substitution, | |
| 14 | TraitEnvironment, Ty, | |
| 15 | db::HirDatabase, | |
| 16 | generics::Generics, | |
| 17 | lower::ParamLoweringMode, | |
| 18 | next_solver::{DbInterner, mapping::ChalkToNextSolver}, | |
| 19 | to_placeholder_idx, | |
| 20 | }; | |
| 21 | ||
| 22 | pub(crate) fn path_to_const<'g>( | |
| 23 | db: &dyn HirDatabase, | |
| 24 | resolver: &Resolver<'_>, | |
| 25 | path: &Path, | |
| 26 | mode: ParamLoweringMode, | |
| 27 | args: impl FnOnce() -> &'g Generics, | |
| 28 | debruijn: DebruijnIndex, | |
| 29 | expected_ty: Ty, | |
| 30 | ) -> Option<Const> { | |
| 31 | match resolver.resolve_path_in_value_ns_fully(db, path, HygieneId::ROOT) { | |
| 32 | Some(ValueNs::GenericParam(p)) => { | |
| 33 | let ty = db.const_param_ty(p); | |
| 34 | let args = args(); | |
| 35 | let value = match mode { | |
| 36 | ParamLoweringMode::Placeholder => { | |
| 37 | let idx = args.type_or_const_param_idx(p.into()).unwrap(); | |
| 38 | ConstValue::Placeholder(to_placeholder_idx(db, p.into(), idx as u32)) | |
| 39 | } | |
| 40 | ParamLoweringMode::Variable => match args.type_or_const_param_idx(p.into()) { | |
| 41 | Some(it) => ConstValue::BoundVar(BoundVar::new(debruijn, it)), | |
| 42 | None => { | |
| 43 | never!( | |
| 44 | "Generic list doesn't contain this param: {:?}, {:?}, {:?}", | |
| 45 | args, | |
| 46 | path, | |
| 47 | p | |
| 48 | ); | |
| 49 | return None; | |
| 50 | } | |
| 51 | }, | |
| 52 | }; | |
| 53 | Some(ConstData { ty, value }.intern(Interner)) | |
| 54 | } | |
| 55 | Some(ValueNs::ConstId(c)) => Some(intern_const_scalar( | |
| 56 | ConstScalar::UnevaluatedConst(c.into(), Substitution::empty(Interner)), | |
| 57 | expected_ty, | |
| 58 | )), | |
| 59 | // FIXME: With feature(adt_const_params), we also need to consider other things here, e.g. struct constructors. | |
| 60 | _ => None, | |
| 61 | } | |
| 62 | } | |
| 63 | ||
| 64 | pub(crate) fn unknown_const(ty: Ty) -> Const { | |
| 65 | ConstData { | |
| 66 | ty, | |
| 67 | value: ConstValue::Concrete(chalk_ir::ConcreteConst { interned: ConstScalar::Unknown }), | |
| 68 | } | |
| 69 | .intern(Interner) | |
| 70 | } | |
| 71 | ||
| 72 | pub(crate) fn unknown_const_as_generic(ty: Ty) -> GenericArg { | |
| 73 | unknown_const(ty).cast(Interner) | |
| 74 | } | |
| 75 | ||
| 76 | /// Interns a constant scalar with the given type | |
| 77 | pub(crate) fn intern_const_scalar(value: ConstScalar, ty: Ty) -> Const { | |
| 78 | ConstData { ty, value: ConstValue::Concrete(chalk_ir::ConcreteConst { interned: value }) } | |
| 79 | .intern(Interner) | |
| 80 | } | |
| 81 | ||
| 82 | /// Interns a constant scalar with the given type | |
| 83 | pub(crate) fn intern_const_ref( | |
| 84 | db: &dyn HirDatabase, | |
| 85 | value: &LiteralConstRef, | |
| 86 | ty: Ty, | |
| 87 | krate: Crate, | |
| 88 | ) -> Const { | |
| 89 | let interner = DbInterner::new_with(db, Some(krate), None); | |
| 90 | let layout = || db.layout_of_ty(ty.to_nextsolver(interner), TraitEnvironment::empty(krate)); | |
| 91 | let bytes = match value { | |
| 92 | LiteralConstRef::Int(i) => { | |
| 93 | // FIXME: We should handle failure of layout better. | |
| 94 | let size = layout().map(|it| it.size.bytes_usize()).unwrap_or(16); | |
| 95 | ConstScalar::Bytes(i.to_le_bytes()[0..size].into(), MemoryMap::default()) | |
| 96 | } | |
| 97 | LiteralConstRef::UInt(i) => { | |
| 98 | let size = layout().map(|it| it.size.bytes_usize()).unwrap_or(16); | |
| 99 | ConstScalar::Bytes(i.to_le_bytes()[0..size].into(), MemoryMap::default()) | |
| 100 | } | |
| 101 | LiteralConstRef::Bool(b) => ConstScalar::Bytes(Box::new([*b as u8]), MemoryMap::default()), | |
| 102 | LiteralConstRef::Char(c) => { | |
| 103 | ConstScalar::Bytes((*c as u32).to_le_bytes().into(), MemoryMap::default()) | |
| 104 | } | |
| 105 | LiteralConstRef::Unknown => ConstScalar::Unknown, | |
| 106 | }; | |
| 107 | intern_const_scalar(bytes, ty) | |
| 108 | } |
src/tools/rust-analyzer/crates/hir-ty/src/consteval_nextsolver.rs deleted-256| ... | ... | @@ -1,256 +0,0 @@ |
| 1 | //! Constant evaluation details | |
| 2 | // FIXME(next-solver): this should get removed as things get moved to rustc_type_ir from chalk_ir | |
| 3 | #![allow(unused)] | |
| 4 | ||
| 5 | use base_db::Crate; | |
| 6 | use hir_def::{ | |
| 7 | EnumVariantId, GeneralConstId, | |
| 8 | expr_store::{Body, HygieneId, path::Path}, | |
| 9 | hir::{Expr, ExprId}, | |
| 10 | resolver::{Resolver, ValueNs}, | |
| 11 | type_ref::LiteralConstRef, | |
| 12 | }; | |
| 13 | use hir_expand::Lookup; | |
| 14 | use rustc_type_ir::{ | |
| 15 | UnevaluatedConst, | |
| 16 | inherent::{IntoKind, SliceLike}, | |
| 17 | }; | |
| 18 | use stdx::never; | |
| 19 | use triomphe::Arc; | |
| 20 | ||
| 21 | use crate::{ | |
| 22 | ConstScalar, Interner, MemoryMap, Substitution, TraitEnvironment, | |
| 23 | consteval::ConstEvalError, | |
| 24 | db::HirDatabase, | |
| 25 | generics::Generics, | |
| 26 | infer::InferenceContext, | |
| 27 | next_solver::{ | |
| 28 | Const, ConstBytes, ConstKind, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, | |
| 29 | ParamConst, SolverDefId, Ty, ValueConst, | |
| 30 | mapping::{ChalkToNextSolver, NextSolverToChalk, convert_binder_to_early_binder}, | |
| 31 | }, | |
| 32 | }; | |
| 33 | ||
| 34 | use super::mir::{interpret_mir, lower_to_mir, pad16}; | |
| 35 | ||
| 36 | pub(crate) fn path_to_const<'a, 'g>( | |
| 37 | db: &'a dyn HirDatabase, | |
| 38 | resolver: &Resolver<'a>, | |
| 39 | path: &Path, | |
| 40 | args: impl FnOnce() -> &'g Generics, | |
| 41 | expected_ty: Ty<'a>, | |
| 42 | ) -> Option<Const<'a>> { | |
| 43 | let interner = DbInterner::new_with(db, Some(resolver.krate()), None); | |
| 44 | match resolver.resolve_path_in_value_ns_fully(db, path, HygieneId::ROOT) { | |
| 45 | Some(ValueNs::GenericParam(p)) => { | |
| 46 | let args = args(); | |
| 47 | match args | |
| 48 | .type_or_const_param(p.into()) | |
| 49 | .and_then(|(idx, p)| p.const_param().map(|p| (idx, p.clone()))) | |
| 50 | { | |
| 51 | Some((idx, _param)) => { | |
| 52 | Some(Const::new_param(interner, ParamConst { index: idx as u32, id: p })) | |
| 53 | } | |
| 54 | None => { | |
| 55 | never!( | |
| 56 | "Generic list doesn't contain this param: {:?}, {:?}, {:?}", | |
| 57 | args, | |
| 58 | path, | |
| 59 | p | |
| 60 | ); | |
| 61 | None | |
| 62 | } | |
| 63 | } | |
| 64 | } | |
| 65 | Some(ValueNs::ConstId(c)) => { | |
| 66 | let args = GenericArgs::new_from_iter(interner, []); | |
| 67 | Some(Const::new( | |
| 68 | interner, | |
| 69 | rustc_type_ir::ConstKind::Unevaluated(UnevaluatedConst::new( | |
| 70 | SolverDefId::ConstId(c), | |
| 71 | args, | |
| 72 | )), | |
| 73 | )) | |
| 74 | } | |
| 75 | _ => None, | |
| 76 | } | |
| 77 | } | |
| 78 | ||
| 79 | pub fn unknown_const<'db>(ty: Ty<'db>) -> Const<'db> { | |
| 80 | Const::new(DbInterner::conjure(), rustc_type_ir::ConstKind::Error(ErrorGuaranteed)) | |
| 81 | } | |
| 82 | ||
| 83 | pub fn unknown_const_as_generic<'db>(ty: Ty<'db>) -> GenericArg<'db> { | |
| 84 | unknown_const(ty).into() | |
| 85 | } | |
| 86 | ||
| 87 | /// Interns a constant scalar with the given type | |
| 88 | pub fn intern_const_ref<'a>( | |
| 89 | db: &'a dyn HirDatabase, | |
| 90 | value: &LiteralConstRef, | |
| 91 | ty: Ty<'a>, | |
| 92 | krate: Crate, | |
| 93 | ) -> Const<'a> { | |
| 94 | let interner = DbInterner::new_with(db, Some(krate), None); | |
| 95 | let layout = db.layout_of_ty(ty, TraitEnvironment::empty(krate)); | |
| 96 | let kind = match value { | |
| 97 | LiteralConstRef::Int(i) => { | |
| 98 | // FIXME: We should handle failure of layout better. | |
| 99 | let size = layout.map(|it| it.size.bytes_usize()).unwrap_or(16); | |
| 100 | rustc_type_ir::ConstKind::Value(ValueConst::new( | |
| 101 | ty, | |
| 102 | ConstBytes(i.to_le_bytes()[0..size].into(), MemoryMap::default()), | |
| 103 | )) | |
| 104 | } | |
| 105 | LiteralConstRef::UInt(i) => { | |
| 106 | let size = layout.map(|it| it.size.bytes_usize()).unwrap_or(16); | |
| 107 | rustc_type_ir::ConstKind::Value(ValueConst::new( | |
| 108 | ty, | |
| 109 | ConstBytes(i.to_le_bytes()[0..size].into(), MemoryMap::default()), | |
| 110 | )) | |
| 111 | } | |
| 112 | LiteralConstRef::Bool(b) => rustc_type_ir::ConstKind::Value(ValueConst::new( | |
| 113 | ty, | |
| 114 | ConstBytes(Box::new([*b as u8]), MemoryMap::default()), | |
| 115 | )), | |
| 116 | LiteralConstRef::Char(c) => rustc_type_ir::ConstKind::Value(ValueConst::new( | |
| 117 | ty, | |
| 118 | ConstBytes((*c as u32).to_le_bytes().into(), MemoryMap::default()), | |
| 119 | )), | |
| 120 | LiteralConstRef::Unknown => rustc_type_ir::ConstKind::Error(ErrorGuaranteed), | |
| 121 | }; | |
| 122 | Const::new(interner, kind) | |
| 123 | } | |
| 124 | ||
| 125 | /// Interns a possibly-unknown target usize | |
| 126 | pub fn usize_const<'db>(db: &'db dyn HirDatabase, value: Option<u128>, krate: Crate) -> Const<'db> { | |
| 127 | intern_const_ref( | |
| 128 | db, | |
| 129 | &value.map_or(LiteralConstRef::Unknown, LiteralConstRef::UInt), | |
| 130 | Ty::new_uint(DbInterner::new_with(db, Some(krate), None), rustc_type_ir::UintTy::Usize), | |
| 131 | krate, | |
| 132 | ) | |
| 133 | } | |
| 134 | ||
| 135 | pub fn try_const_usize<'db>(db: &'db dyn HirDatabase, c: Const<'db>) -> Option<u128> { | |
| 136 | let interner = DbInterner::new_with(db, None, None); | |
| 137 | match c.kind() { | |
| 138 | ConstKind::Param(_) => None, | |
| 139 | ConstKind::Infer(_) => None, | |
| 140 | ConstKind::Bound(_, _) => None, | |
| 141 | ConstKind::Placeholder(_) => None, | |
| 142 | ConstKind::Unevaluated(unevaluated_const) => { | |
| 143 | let c = match unevaluated_const.def { | |
| 144 | SolverDefId::ConstId(id) => GeneralConstId::ConstId(id), | |
| 145 | SolverDefId::StaticId(id) => GeneralConstId::StaticId(id), | |
| 146 | _ => unreachable!(), | |
| 147 | }; | |
| 148 | let subst = unevaluated_const.args.to_chalk(interner); | |
| 149 | let ec = db.const_eval(c, subst, None).ok()?.to_nextsolver(interner); | |
| 150 | try_const_usize(db, ec) | |
| 151 | } | |
| 152 | ConstKind::Value(val) => Some(u128::from_le_bytes(pad16(&val.value.inner().0, false))), | |
| 153 | ConstKind::Error(_) => None, | |
| 154 | ConstKind::Expr(_) => None, | |
| 155 | } | |
| 156 | } | |
| 157 | ||
| 158 | pub fn try_const_isize<'db>(db: &'db dyn HirDatabase, c: &Const<'db>) -> Option<i128> { | |
| 159 | let interner = DbInterner::new_with(db, None, None); | |
| 160 | match (*c).kind() { | |
| 161 | ConstKind::Param(_) => None, | |
| 162 | ConstKind::Infer(_) => None, | |
| 163 | ConstKind::Bound(_, _) => None, | |
| 164 | ConstKind::Placeholder(_) => None, | |
| 165 | ConstKind::Unevaluated(unevaluated_const) => { | |
| 166 | let c = match unevaluated_const.def { | |
| 167 | SolverDefId::ConstId(id) => GeneralConstId::ConstId(id), | |
| 168 | SolverDefId::StaticId(id) => GeneralConstId::StaticId(id), | |
| 169 | _ => unreachable!(), | |
| 170 | }; | |
| 171 | let subst = unevaluated_const.args.to_chalk(interner); | |
| 172 | let ec = db.const_eval(c, subst, None).ok()?.to_nextsolver(interner); | |
| 173 | try_const_isize(db, &ec) | |
| 174 | } | |
| 175 | ConstKind::Value(val) => Some(i128::from_le_bytes(pad16(&val.value.inner().0, true))), | |
| 176 | ConstKind::Error(_) => None, | |
| 177 | ConstKind::Expr(_) => None, | |
| 178 | } | |
| 179 | } | |
| 180 | ||
| 181 | pub(crate) fn const_eval_discriminant_variant( | |
| 182 | db: &dyn HirDatabase, | |
| 183 | variant_id: EnumVariantId, | |
| 184 | ) -> Result<i128, ConstEvalError> { | |
| 185 | let interner = DbInterner::new_with(db, None, None); | |
| 186 | let def = variant_id.into(); | |
| 187 | let body = db.body(def); | |
| 188 | let loc = variant_id.lookup(db); | |
| 189 | if matches!(body[body.body_expr], Expr::Missing) { | |
| 190 | let prev_idx = loc.index.checked_sub(1); | |
| 191 | let value = match prev_idx { | |
| 192 | Some(prev_idx) => { | |
| 193 | 1 + db.const_eval_discriminant( | |
| 194 | loc.parent.enum_variants(db).variants[prev_idx as usize].0, | |
| 195 | )? | |
| 196 | } | |
| 197 | _ => 0, | |
| 198 | }; | |
| 199 | return Ok(value); | |
| 200 | } | |
| 201 | ||
| 202 | let repr = db.enum_signature(loc.parent).repr; | |
| 203 | let is_signed = repr.and_then(|repr| repr.int).is_none_or(|int| int.is_signed()); | |
| 204 | ||
| 205 | let mir_body = db.monomorphized_mir_body( | |
| 206 | def, | |
| 207 | Substitution::empty(Interner), | |
| 208 | db.trait_environment_for_body(def), | |
| 209 | )?; | |
| 210 | let c = interpret_mir(db, mir_body, false, None)?.0?; | |
| 211 | let c = c.to_nextsolver(interner); | |
| 212 | let c = if is_signed { | |
| 213 | try_const_isize(db, &c).unwrap() | |
| 214 | } else { | |
| 215 | try_const_usize(db, c).unwrap() as i128 | |
| 216 | }; | |
| 217 | Ok(c) | |
| 218 | } | |
| 219 | ||
| 220 | // FIXME: Ideally constants in const eval should have separate body (issue #7434), and this function should | |
| 221 | // get an `InferenceResult` instead of an `InferenceContext`. And we should remove `ctx.clone().resolve_all()` here | |
| 222 | // and make this function private. See the fixme comment on `InferenceContext::resolve_all`. | |
| 223 | pub(crate) fn eval_to_const<'db>(expr: ExprId, ctx: &mut InferenceContext<'db>) -> Const<'db> { | |
| 224 | let interner = DbInterner::new_with(ctx.db, None, None); | |
| 225 | let infer = ctx.fixme_resolve_all_clone(); | |
| 226 | fn has_closure(body: &Body, expr: ExprId) -> bool { | |
| 227 | if matches!(body[expr], Expr::Closure { .. }) { | |
| 228 | return true; | |
| 229 | } | |
| 230 | let mut r = false; | |
| 231 | body.walk_child_exprs(expr, |idx| r |= has_closure(body, idx)); | |
| 232 | r | |
| 233 | } | |
| 234 | if has_closure(ctx.body, expr) { | |
| 235 | // Type checking clousres need an isolated body (See the above FIXME). Bail out early to prevent panic. | |
| 236 | return unknown_const(infer[expr].clone().to_nextsolver(interner)); | |
| 237 | } | |
| 238 | if let Expr::Path(p) = &ctx.body[expr] { | |
| 239 | let resolver = &ctx.resolver; | |
| 240 | if let Some(c) = path_to_const( | |
| 241 | ctx.db, | |
| 242 | resolver, | |
| 243 | p, | |
| 244 | || ctx.generics(), | |
| 245 | infer[expr].to_nextsolver(interner), | |
| 246 | ) { | |
| 247 | return c; | |
| 248 | } | |
| 249 | } | |
| 250 | if let Ok(mir_body) = lower_to_mir(ctx.db, ctx.owner, ctx.body, &infer, expr) | |
| 251 | && let Ok((Ok(result), _)) = interpret_mir(ctx.db, Arc::new(mir_body), true, None) | |
| 252 | { | |
| 253 | return result.to_nextsolver(interner); | |
| 254 | } | |
| 255 | unknown_const(infer[expr].to_nextsolver(interner)) | |
| 256 | } |
src/tools/rust-analyzer/crates/hir-ty/src/db.rs+60-33| ... | ... | @@ -16,10 +16,9 @@ use smallvec::SmallVec; |
| 16 | 16 | use triomphe::Arc; |
| 17 | 17 | |
| 18 | 18 | use crate::{ |
| 19 | Binders, Const, ImplTraitId, ImplTraits, InferenceResult, Substitution, TraitEnvironment, Ty, | |
| 20 | TyDefId, ValueTyDefId, chalk_db, | |
| 19 | Binders, ImplTraitId, ImplTraits, InferenceResult, TraitEnvironment, Ty, TyDefId, ValueTyDefId, | |
| 20 | chalk_db, | |
| 21 | 21 | consteval::ConstEvalError, |
| 22 | drop::DropGlue, | |
| 23 | 22 | dyn_compatibility::DynCompatibilityViolation, |
| 24 | 23 | layout::{Layout, LayoutError}, |
| 25 | 24 | lower::{Diagnostics, GenericDefaults, GenericPredicates}, |
| ... | ... | @@ -32,62 +31,77 @@ use crate::{ |
| 32 | 31 | pub trait HirDatabase: DefDatabase + std::fmt::Debug { |
| 33 | 32 | #[salsa::invoke(crate::infer::infer_query)] |
| 34 | 33 | #[salsa::cycle(cycle_result = crate::infer::infer_cycle_result)] |
| 35 | fn infer(&self, def: DefWithBodyId) -> Arc<InferenceResult>; | |
| 34 | fn infer<'db>(&'db self, def: DefWithBodyId) -> Arc<InferenceResult<'db>>; | |
| 36 | 35 | |
| 37 | 36 | // region:mir |
| 38 | 37 | |
| 39 | 38 | #[salsa::invoke(crate::mir::mir_body_query)] |
| 40 | 39 | #[salsa::cycle(cycle_result = crate::mir::mir_body_cycle_result)] |
| 41 | fn mir_body(&self, def: DefWithBodyId) -> Result<Arc<MirBody>, MirLowerError>; | |
| 40 | fn mir_body<'db>( | |
| 41 | &'db self, | |
| 42 | def: DefWithBodyId, | |
| 43 | ) -> Result<Arc<MirBody<'db>>, MirLowerError<'db>>; | |
| 42 | 44 | |
| 43 | 45 | #[salsa::invoke(crate::mir::mir_body_for_closure_query)] |
| 44 | fn mir_body_for_closure(&self, def: InternedClosureId) -> Result<Arc<MirBody>, MirLowerError>; | |
| 46 | fn mir_body_for_closure<'db>( | |
| 47 | &'db self, | |
| 48 | def: InternedClosureId, | |
| 49 | ) -> Result<Arc<MirBody<'db>>, MirLowerError<'db>>; | |
| 45 | 50 | |
| 46 | 51 | #[salsa::invoke(crate::mir::monomorphized_mir_body_query)] |
| 47 | 52 | #[salsa::cycle(cycle_result = crate::mir::monomorphized_mir_body_cycle_result)] |
| 48 | fn monomorphized_mir_body( | |
| 49 | &self, | |
| 53 | fn monomorphized_mir_body<'db>( | |
| 54 | &'db self, | |
| 50 | 55 | def: DefWithBodyId, |
| 51 | subst: Substitution, | |
| 52 | env: Arc<TraitEnvironment<'_>>, | |
| 53 | ) -> Result<Arc<MirBody>, MirLowerError>; | |
| 56 | subst: crate::next_solver::GenericArgs<'db>, | |
| 57 | env: Arc<TraitEnvironment<'db>>, | |
| 58 | ) -> Result<Arc<MirBody<'db>>, MirLowerError<'db>>; | |
| 54 | 59 | |
| 55 | 60 | #[salsa::invoke(crate::mir::monomorphized_mir_body_for_closure_query)] |
| 56 | fn monomorphized_mir_body_for_closure( | |
| 57 | &self, | |
| 61 | fn monomorphized_mir_body_for_closure<'db>( | |
| 62 | &'db self, | |
| 58 | 63 | def: InternedClosureId, |
| 59 | subst: Substitution, | |
| 60 | env: Arc<TraitEnvironment<'_>>, | |
| 61 | ) -> Result<Arc<MirBody>, MirLowerError>; | |
| 64 | subst: crate::next_solver::GenericArgs<'db>, | |
| 65 | env: Arc<TraitEnvironment<'db>>, | |
| 66 | ) -> Result<Arc<MirBody<'db>>, MirLowerError<'db>>; | |
| 62 | 67 | |
| 63 | 68 | #[salsa::invoke(crate::mir::borrowck_query)] |
| 64 | 69 | #[salsa::lru(2024)] |
| 65 | fn borrowck(&self, def: DefWithBodyId) -> Result<Arc<[BorrowckResult]>, MirLowerError>; | |
| 70 | fn borrowck<'db>( | |
| 71 | &'db self, | |
| 72 | def: DefWithBodyId, | |
| 73 | ) -> Result<Arc<[BorrowckResult<'db>]>, MirLowerError<'db>>; | |
| 66 | 74 | |
| 67 | 75 | #[salsa::invoke(crate::consteval::const_eval_query)] |
| 68 | 76 | #[salsa::cycle(cycle_result = crate::consteval::const_eval_cycle_result)] |
| 69 | fn const_eval( | |
| 70 | &self, | |
| 77 | fn const_eval<'db>( | |
| 78 | &'db self, | |
| 71 | 79 | def: GeneralConstId, |
| 72 | subst: Substitution, | |
| 73 | trait_env: Option<Arc<TraitEnvironment<'_>>>, | |
| 74 | ) -> Result<Const, ConstEvalError>; | |
| 80 | subst: crate::next_solver::GenericArgs<'db>, | |
| 81 | trait_env: Option<Arc<TraitEnvironment<'db>>>, | |
| 82 | ) -> Result<crate::next_solver::Const<'db>, ConstEvalError<'db>>; | |
| 75 | 83 | |
| 76 | 84 | #[salsa::invoke(crate::consteval::const_eval_static_query)] |
| 77 | 85 | #[salsa::cycle(cycle_result = crate::consteval::const_eval_static_cycle_result)] |
| 78 | fn const_eval_static(&self, def: StaticId) -> Result<Const, ConstEvalError>; | |
| 86 | fn const_eval_static<'db>( | |
| 87 | &'db self, | |
| 88 | def: StaticId, | |
| 89 | ) -> Result<crate::next_solver::Const<'db>, ConstEvalError<'db>>; | |
| 79 | 90 | |
| 80 | 91 | #[salsa::invoke(crate::consteval::const_eval_discriminant_variant)] |
| 81 | 92 | #[salsa::cycle(cycle_result = crate::consteval::const_eval_discriminant_cycle_result)] |
| 82 | fn const_eval_discriminant(&self, def: EnumVariantId) -> Result<i128, ConstEvalError>; | |
| 93 | fn const_eval_discriminant<'db>( | |
| 94 | &'db self, | |
| 95 | def: EnumVariantId, | |
| 96 | ) -> Result<i128, ConstEvalError<'db>>; | |
| 83 | 97 | |
| 84 | 98 | #[salsa::invoke(crate::method_resolution::lookup_impl_method_query)] |
| 85 | fn lookup_impl_method( | |
| 86 | &self, | |
| 87 | env: Arc<TraitEnvironment<'_>>, | |
| 99 | fn lookup_impl_method<'db>( | |
| 100 | &'db self, | |
| 101 | env: Arc<TraitEnvironment<'db>>, | |
| 88 | 102 | func: FunctionId, |
| 89 | fn_subst: Substitution, | |
| 90 | ) -> (FunctionId, Substitution); | |
| 103 | fn_subst: crate::next_solver::GenericArgs<'db>, | |
| 104 | ) -> (FunctionId, crate::next_solver::GenericArgs<'db>); | |
| 91 | 105 | |
| 92 | 106 | // endregion:mir |
| 93 | 107 | |
| ... | ... | @@ -325,10 +339,6 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { |
| 325 | 339 | goal: crate::Canonical<crate::InEnvironment<crate::Goal>>, |
| 326 | 340 | ) -> NextTraitSolveResult; |
| 327 | 341 | |
| 328 | #[salsa::invoke(crate::drop::has_drop_glue)] | |
| 329 | #[salsa::cycle(cycle_result = crate::drop::has_drop_glue_cycle_result)] | |
| 330 | fn has_drop_glue(&self, ty: Ty, env: Arc<TraitEnvironment<'_>>) -> DropGlue; | |
| 331 | ||
| 332 | 342 | // next trait solver |
| 333 | 343 | |
| 334 | 344 | #[salsa::invoke(crate::lower_nextsolver::const_param_ty_query)] |
| ... | ... | @@ -370,6 +380,23 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { |
| 370 | 380 | &'db self, |
| 371 | 381 | def: GenericDefId, |
| 372 | 382 | ) -> crate::lower_nextsolver::GenericPredicates<'db>; |
| 383 | ||
| 384 | #[salsa::invoke(crate::lower_nextsolver::generic_defaults_with_diagnostics_query)] | |
| 385 | #[salsa::cycle(cycle_result = crate::lower_nextsolver::generic_defaults_with_diagnostics_cycle_result)] | |
| 386 | fn generic_defaults_ns_with_diagnostics<'db>( | |
| 387 | &'db self, | |
| 388 | def: GenericDefId, | |
| 389 | ) -> (crate::lower_nextsolver::GenericDefaults<'db>, Diagnostics); | |
| 390 | ||
| 391 | /// This returns an empty list if no parameter has default. | |
| 392 | /// | |
| 393 | /// The binders of the returned defaults are only up to (not including) this parameter. | |
| 394 | #[salsa::invoke(crate::lower_nextsolver::generic_defaults_query)] | |
| 395 | #[salsa::transparent] | |
| 396 | fn generic_defaults_ns<'db>( | |
| 397 | &'db self, | |
| 398 | def: GenericDefId, | |
| 399 | ) -> crate::lower_nextsolver::GenericDefaults<'db>; | |
| 373 | 400 | } |
| 374 | 401 | |
| 375 | 402 | #[test] |
src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs+31-15| ... | ... | @@ -23,6 +23,8 @@ use tracing::debug; |
| 23 | 23 | use triomphe::Arc; |
| 24 | 24 | use typed_arena::Arena; |
| 25 | 25 | |
| 26 | use crate::next_solver::DbInterner; | |
| 27 | use crate::next_solver::mapping::NextSolverToChalk; | |
| 26 | 28 | use crate::{ |
| 27 | 29 | Adjust, InferenceResult, Interner, TraitEnvironment, Ty, TyExt, TyKind, |
| 28 | 30 | db::HirDatabase, |
| ... | ... | @@ -74,8 +76,16 @@ impl BodyValidationDiagnostic { |
| 74 | 76 | let infer = db.infer(owner); |
| 75 | 77 | let body = db.body(owner); |
| 76 | 78 | let env = db.trait_environment_for_body(owner); |
| 77 | let mut validator = | |
| 78 | ExprValidator { owner, body, infer, diagnostics: Vec::new(), validate_lints, env }; | |
| 79 | let interner = DbInterner::new_with(db, Some(env.krate), env.block); | |
| 80 | let mut validator = ExprValidator { | |
| 81 | owner, | |
| 82 | body, | |
| 83 | infer, | |
| 84 | diagnostics: Vec::new(), | |
| 85 | validate_lints, | |
| 86 | env, | |
| 87 | interner, | |
| 88 | }; | |
| 79 | 89 | validator.validate_body(db); |
| 80 | 90 | validator.diagnostics |
| 81 | 91 | } |
| ... | ... | @@ -84,10 +94,11 @@ impl BodyValidationDiagnostic { |
| 84 | 94 | struct ExprValidator<'db> { |
| 85 | 95 | owner: DefWithBodyId, |
| 86 | 96 | body: Arc<Body>, |
| 87 | infer: Arc<InferenceResult>, | |
| 97 | infer: Arc<InferenceResult<'db>>, | |
| 88 | 98 | env: Arc<TraitEnvironment<'db>>, |
| 89 | 99 | diagnostics: Vec<BodyValidationDiagnostic>, |
| 90 | 100 | validate_lints: bool, |
| 101 | interner: DbInterner<'db>, | |
| 91 | 102 | } |
| 92 | 103 | |
| 93 | 104 | impl<'db> ExprValidator<'db> { |
| ... | ... | @@ -175,7 +186,7 @@ impl<'db> ExprValidator<'db> { |
| 175 | 186 | } |
| 176 | 187 | |
| 177 | 188 | if let Some(receiver_ty) = self.infer.type_of_expr_with_adjust(*receiver) { |
| 178 | checker.prev_receiver_ty = Some(receiver_ty.clone()); | |
| 189 | checker.prev_receiver_ty = Some(receiver_ty.to_chalk(self.interner)); | |
| 179 | 190 | } |
| 180 | 191 | } |
| 181 | 192 | } |
| ... | ... | @@ -190,6 +201,7 @@ impl<'db> ExprValidator<'db> { |
| 190 | 201 | let Some(scrut_ty) = self.infer.type_of_expr_with_adjust(scrutinee_expr) else { |
| 191 | 202 | return; |
| 192 | 203 | }; |
| 204 | let scrut_ty = scrut_ty.to_chalk(self.interner); | |
| 193 | 205 | if scrut_ty.contains_unknown() { |
| 194 | 206 | return; |
| 195 | 207 | } |
| ... | ... | @@ -205,6 +217,7 @@ impl<'db> ExprValidator<'db> { |
| 205 | 217 | let Some(pat_ty) = self.infer.type_of_pat_with_adjust(arm.pat) else { |
| 206 | 218 | return; |
| 207 | 219 | }; |
| 220 | let pat_ty = pat_ty.to_chalk(self.interner); | |
| 208 | 221 | if pat_ty.contains_unknown() { |
| 209 | 222 | return; |
| 210 | 223 | } |
| ... | ... | @@ -222,7 +235,7 @@ impl<'db> ExprValidator<'db> { |
| 222 | 235 | if (pat_ty == scrut_ty |
| 223 | 236 | || scrut_ty |
| 224 | 237 | .as_reference() |
| 225 | .map(|(match_expr_ty, ..)| match_expr_ty == pat_ty) | |
| 238 | .map(|(match_expr_ty, ..)| *match_expr_ty == pat_ty) | |
| 226 | 239 | .unwrap_or(false)) |
| 227 | 240 | && types_of_subpatterns_do_match(arm.pat, &self.body, &self.infer) |
| 228 | 241 | { |
| ... | ... | @@ -264,7 +277,7 @@ impl<'db> ExprValidator<'db> { |
| 264 | 277 | match_expr, |
| 265 | 278 | uncovered_patterns: missing_match_arms( |
| 266 | 279 | &cx, |
| 267 | scrut_ty, | |
| 280 | &scrut_ty, | |
| 268 | 281 | witnesses, |
| 269 | 282 | m_arms.is_empty(), |
| 270 | 283 | self.owner.krate(db), |
| ... | ... | @@ -298,10 +311,12 @@ impl<'db> ExprValidator<'db> { |
| 298 | 311 | ); |
| 299 | 312 | value_or_partial.is_none_or(|v| !matches!(v, ValueNs::StaticId(_))) |
| 300 | 313 | } |
| 301 | Expr::Field { expr, .. } => match self.infer.type_of_expr[*expr].kind(Interner) { | |
| 302 | TyKind::Adt(adt, ..) if matches!(adt.0, AdtId::UnionId(_)) => false, | |
| 303 | _ => self.is_known_valid_scrutinee(*expr, db), | |
| 304 | }, | |
| 314 | Expr::Field { expr, .. } => { | |
| 315 | match self.infer.type_of_expr[*expr].to_chalk(self.interner).kind(Interner) { | |
| 316 | TyKind::Adt(adt, ..) if matches!(adt.0, AdtId::UnionId(_)) => false, | |
| 317 | _ => self.is_known_valid_scrutinee(*expr, db), | |
| 318 | } | |
| 319 | } | |
| 305 | 320 | Expr::Index { base, .. } => self.is_known_valid_scrutinee(*base, db), |
| 306 | 321 | Expr::Cast { expr, .. } => self.is_known_valid_scrutinee(*expr, db), |
| 307 | 322 | Expr::Missing => false, |
| ... | ... | @@ -327,6 +342,7 @@ impl<'db> ExprValidator<'db> { |
| 327 | 342 | } |
| 328 | 343 | let Some(initializer) = initializer else { continue }; |
| 329 | 344 | let Some(ty) = self.infer.type_of_expr_with_adjust(initializer) else { continue }; |
| 345 | let ty = ty.to_chalk(self.interner); | |
| 330 | 346 | if ty.contains_unknown() { |
| 331 | 347 | continue; |
| 332 | 348 | } |
| ... | ... | @@ -357,7 +373,7 @@ impl<'db> ExprValidator<'db> { |
| 357 | 373 | pat, |
| 358 | 374 | uncovered_patterns: missing_match_arms( |
| 359 | 375 | &cx, |
| 360 | ty, | |
| 376 | &ty, | |
| 361 | 377 | witnesses, |
| 362 | 378 | false, |
| 363 | 379 | self.owner.krate(db), |
| ... | ... | @@ -542,7 +558,7 @@ impl FilterMapNextChecker { |
| 542 | 558 | |
| 543 | 559 | pub fn record_literal_missing_fields( |
| 544 | 560 | db: &dyn HirDatabase, |
| 545 | infer: &InferenceResult, | |
| 561 | infer: &InferenceResult<'_>, | |
| 546 | 562 | id: ExprId, |
| 547 | 563 | expr: &Expr, |
| 548 | 564 | ) -> Option<(VariantId, Vec<LocalFieldId>, /*exhaustive*/ bool)> { |
| ... | ... | @@ -572,7 +588,7 @@ pub fn record_literal_missing_fields( |
| 572 | 588 | |
| 573 | 589 | pub fn record_pattern_missing_fields( |
| 574 | 590 | db: &dyn HirDatabase, |
| 575 | infer: &InferenceResult, | |
| 591 | infer: &InferenceResult<'_>, | |
| 576 | 592 | id: PatId, |
| 577 | 593 | pat: &Pat, |
| 578 | 594 | ) -> Option<(VariantId, Vec<LocalFieldId>, /*exhaustive*/ bool)> { |
| ... | ... | @@ -600,8 +616,8 @@ pub fn record_pattern_missing_fields( |
| 600 | 616 | Some((variant_def, missed_fields, exhaustive)) |
| 601 | 617 | } |
| 602 | 618 | |
| 603 | fn types_of_subpatterns_do_match(pat: PatId, body: &Body, infer: &InferenceResult) -> bool { | |
| 604 | fn walk(pat: PatId, body: &Body, infer: &InferenceResult, has_type_mismatches: &mut bool) { | |
| 619 | fn types_of_subpatterns_do_match(pat: PatId, body: &Body, infer: &InferenceResult<'_>) -> bool { | |
| 620 | fn walk(pat: PatId, body: &Body, infer: &InferenceResult<'_>, has_type_mismatches: &mut bool) { | |
| 605 | 621 | match infer.type_mismatch_for_pat(pat) { |
| 606 | 622 | Some(_) => *has_type_mismatches = true, |
| 607 | 623 | None if *has_type_mismatches => (), |
src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs+22-15| ... | ... | @@ -20,6 +20,8 @@ use hir_expand::name::Name; |
| 20 | 20 | use span::Edition; |
| 21 | 21 | use stdx::{always, never}; |
| 22 | 22 | |
| 23 | use crate::next_solver::DbInterner; | |
| 24 | use crate::next_solver::mapping::NextSolverToChalk; | |
| 23 | 25 | use crate::{ |
| 24 | 26 | InferenceResult, Interner, Substitution, Ty, TyExt, TyKind, |
| 25 | 27 | db::HirDatabase, |
| ... | ... | @@ -93,16 +95,21 @@ pub(crate) enum PatKind { |
| 93 | 95 | }, |
| 94 | 96 | } |
| 95 | 97 | |
| 96 | pub(crate) struct PatCtxt<'a> { | |
| 97 | db: &'a dyn HirDatabase, | |
| 98 | infer: &'a InferenceResult, | |
| 99 | body: &'a Body, | |
| 98 | pub(crate) struct PatCtxt<'db> { | |
| 99 | db: &'db dyn HirDatabase, | |
| 100 | infer: &'db InferenceResult<'db>, | |
| 101 | body: &'db Body, | |
| 100 | 102 | pub(crate) errors: Vec<PatternError>, |
| 103 | interner: DbInterner<'db>, | |
| 101 | 104 | } |
| 102 | 105 | |
| 103 | 106 | impl<'a> PatCtxt<'a> { |
| 104 | pub(crate) fn new(db: &'a dyn HirDatabase, infer: &'a InferenceResult, body: &'a Body) -> Self { | |
| 105 | Self { db, infer, body, errors: Vec::new() } | |
| 107 | pub(crate) fn new( | |
| 108 | db: &'a dyn HirDatabase, | |
| 109 | infer: &'a InferenceResult<'a>, | |
| 110 | body: &'a Body, | |
| 111 | ) -> Self { | |
| 112 | Self { db, infer, body, errors: Vec::new(), interner: DbInterner::new_with(db, None, None) } | |
| 106 | 113 | } |
| 107 | 114 | |
| 108 | 115 | pub(crate) fn lower_pattern(&mut self, pat: PatId) -> Pat { |
| ... | ... | @@ -115,14 +122,14 @@ impl<'a> PatCtxt<'a> { |
| 115 | 122 | self.infer.pat_adjustments.get(&pat).map(|it| &**it).unwrap_or_default().iter().rev().fold( |
| 116 | 123 | unadjusted_pat, |
| 117 | 124 | |subpattern, ref_ty| Pat { |
| 118 | ty: ref_ty.clone(), | |
| 125 | ty: ref_ty.to_chalk(self.interner).clone(), | |
| 119 | 126 | kind: Box::new(PatKind::Deref { subpattern }), |
| 120 | 127 | }, |
| 121 | 128 | ) |
| 122 | 129 | } |
| 123 | 130 | |
| 124 | 131 | fn lower_pattern_unadjusted(&mut self, pat: PatId) -> Pat { |
| 125 | let mut ty = &self.infer[pat]; | |
| 132 | let mut ty = self.infer[pat].to_chalk(self.interner); | |
| 126 | 133 | let variant = self.infer.variant_resolution_for_pat(pat); |
| 127 | 134 | |
| 128 | 135 | let kind = match self.body[pat] { |
| ... | ... | @@ -140,7 +147,7 @@ impl<'a> PatCtxt<'a> { |
| 140 | 147 | _ => { |
| 141 | 148 | never!("unexpected type for tuple pattern: {:?}", ty); |
| 142 | 149 | self.errors.push(PatternError::UnexpectedType); |
| 143 | return Pat { ty: ty.clone(), kind: PatKind::Wild.into() }; | |
| 150 | return Pat { ty, kind: PatKind::Wild.into() }; | |
| 144 | 151 | } |
| 145 | 152 | }; |
| 146 | 153 | let subpatterns = self.lower_tuple_subpats(args, arity, ellipsis); |
| ... | ... | @@ -149,10 +156,10 @@ impl<'a> PatCtxt<'a> { |
| 149 | 156 | |
| 150 | 157 | hir_def::hir::Pat::Bind { id, subpat, .. } => { |
| 151 | 158 | let bm = self.infer.binding_modes[pat]; |
| 152 | ty = &self.infer[id]; | |
| 159 | ty = self.infer[id].to_chalk(self.interner); | |
| 153 | 160 | let name = &self.body[id].name; |
| 154 | 161 | match (bm, ty.kind(Interner)) { |
| 155 | (BindingMode::Ref(_), TyKind::Ref(.., rty)) => ty = rty, | |
| 162 | (BindingMode::Ref(_), TyKind::Ref(.., rty)) => ty = rty.clone(), | |
| 156 | 163 | (BindingMode::Ref(_), _) => { |
| 157 | 164 | never!( |
| 158 | 165 | "`ref {}` has wrong type {:?}", |
| ... | ... | @@ -170,7 +177,7 @@ impl<'a> PatCtxt<'a> { |
| 170 | 177 | hir_def::hir::Pat::TupleStruct { ref args, ellipsis, .. } if variant.is_some() => { |
| 171 | 178 | let expected_len = variant.unwrap().fields(self.db).fields().len(); |
| 172 | 179 | let subpatterns = self.lower_tuple_subpats(args, expected_len, ellipsis); |
| 173 | self.lower_variant_or_leaf(pat, ty, subpatterns) | |
| 180 | self.lower_variant_or_leaf(pat, &ty, subpatterns) | |
| 174 | 181 | } |
| 175 | 182 | |
| 176 | 183 | hir_def::hir::Pat::Record { ref args, .. } if variant.is_some() => { |
| ... | ... | @@ -186,7 +193,7 @@ impl<'a> PatCtxt<'a> { |
| 186 | 193 | }) |
| 187 | 194 | .collect(); |
| 188 | 195 | match subpatterns { |
| 189 | Some(subpatterns) => self.lower_variant_or_leaf(pat, ty, subpatterns), | |
| 196 | Some(subpatterns) => self.lower_variant_or_leaf(pat, &ty, subpatterns), | |
| 190 | 197 | None => { |
| 191 | 198 | self.errors.push(PatternError::MissingField); |
| 192 | 199 | PatKind::Wild |
| ... | ... | @@ -271,12 +278,12 @@ impl<'a> PatCtxt<'a> { |
| 271 | 278 | } |
| 272 | 279 | |
| 273 | 280 | fn lower_path(&mut self, pat: PatId, _path: &Path) -> Pat { |
| 274 | let ty = &self.infer[pat]; | |
| 281 | let ty = self.infer[pat].to_chalk(self.interner); | |
| 275 | 282 | |
| 276 | 283 | let pat_from_kind = |kind| Pat { ty: ty.clone(), kind: Box::new(kind) }; |
| 277 | 284 | |
| 278 | 285 | match self.infer.variant_resolution_for_pat(pat) { |
| 279 | Some(_) => pat_from_kind(self.lower_variant_or_leaf(pat, ty, Vec::new())), | |
| 286 | Some(_) => pat_from_kind(self.lower_variant_or_leaf(pat, &ty, Vec::new())), | |
| 280 | 287 | None => { |
| 281 | 288 | self.errors.push(PatternError::UnresolvedVariant); |
| 282 | 289 | pat_from_kind(PatKind::Wild) |
src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs+14-10| ... | ... | @@ -14,6 +14,8 @@ use hir_def::{ |
| 14 | 14 | }; |
| 15 | 15 | use span::Edition; |
| 16 | 16 | |
| 17 | use crate::next_solver::DbInterner; | |
| 18 | use crate::next_solver::mapping::NextSolverToChalk; | |
| 17 | 19 | use crate::utils::TargetFeatureIsSafeInTarget; |
| 18 | 20 | use crate::{ |
| 19 | 21 | InferenceResult, Interner, TargetFeatures, TyExt, TyKind, |
| ... | ... | @@ -96,9 +98,9 @@ enum UnsafeDiagnostic { |
| 96 | 98 | DeprecatedSafe2024 { node: ExprId, inside_unsafe_block: InsideUnsafeBlock }, |
| 97 | 99 | } |
| 98 | 100 | |
| 99 | pub fn unsafe_operations_for_body( | |
| 100 | db: &dyn HirDatabase, | |
| 101 | infer: &InferenceResult, | |
| 101 | pub fn unsafe_operations_for_body<'db>( | |
| 102 | db: &'db dyn HirDatabase, | |
| 103 | infer: &InferenceResult<'db>, | |
| 102 | 104 | def: DefWithBodyId, |
| 103 | 105 | body: &Body, |
| 104 | 106 | callback: &mut dyn FnMut(ExprOrPatId), |
| ... | ... | @@ -115,9 +117,9 @@ pub fn unsafe_operations_for_body( |
| 115 | 117 | } |
| 116 | 118 | } |
| 117 | 119 | |
| 118 | pub fn unsafe_operations( | |
| 119 | db: &dyn HirDatabase, | |
| 120 | infer: &InferenceResult, | |
| 120 | pub fn unsafe_operations<'db>( | |
| 121 | db: &'db dyn HirDatabase, | |
| 122 | infer: &InferenceResult<'db>, | |
| 121 | 123 | def: DefWithBodyId, |
| 122 | 124 | body: &Body, |
| 123 | 125 | current: ExprId, |
| ... | ... | @@ -135,7 +137,7 @@ pub fn unsafe_operations( |
| 135 | 137 | |
| 136 | 138 | struct UnsafeVisitor<'db> { |
| 137 | 139 | db: &'db dyn HirDatabase, |
| 138 | infer: &'db InferenceResult, | |
| 140 | infer: &'db InferenceResult<'db>, | |
| 139 | 141 | body: &'db Body, |
| 140 | 142 | resolver: Resolver<'db>, |
| 141 | 143 | def: DefWithBodyId, |
| ... | ... | @@ -149,12 +151,13 @@ struct UnsafeVisitor<'db> { |
| 149 | 151 | /// On some targets (WASM), calling safe functions with `#[target_feature]` is always safe, even when |
| 150 | 152 | /// the target feature is not enabled. This flag encodes that. |
| 151 | 153 | target_feature_is_safe: TargetFeatureIsSafeInTarget, |
| 154 | interner: DbInterner<'db>, | |
| 152 | 155 | } |
| 153 | 156 | |
| 154 | 157 | impl<'db> UnsafeVisitor<'db> { |
| 155 | 158 | fn new( |
| 156 | 159 | db: &'db dyn HirDatabase, |
| 157 | infer: &'db InferenceResult, | |
| 160 | infer: &'db InferenceResult<'db>, | |
| 158 | 161 | body: &'db Body, |
| 159 | 162 | def: DefWithBodyId, |
| 160 | 163 | unsafe_expr_cb: &'db mut dyn FnMut(UnsafeDiagnostic), |
| ... | ... | @@ -183,6 +186,7 @@ impl<'db> UnsafeVisitor<'db> { |
| 183 | 186 | def_target_features, |
| 184 | 187 | edition, |
| 185 | 188 | target_feature_is_safe, |
| 189 | interner: DbInterner::new_with(db, None, None), | |
| 186 | 190 | } |
| 187 | 191 | } |
| 188 | 192 | |
| ... | ... | @@ -285,7 +289,7 @@ impl<'db> UnsafeVisitor<'db> { |
| 285 | 289 | let inside_assignment = mem::replace(&mut self.inside_assignment, false); |
| 286 | 290 | match expr { |
| 287 | 291 | &Expr::Call { callee, .. } => { |
| 288 | let callee = &self.infer[callee]; | |
| 292 | let callee = self.infer[callee].to_chalk(self.interner); | |
| 289 | 293 | if let Some(func) = callee.as_fn_def(self.db) { |
| 290 | 294 | self.check_call(current, func); |
| 291 | 295 | } |
| ... | ... | @@ -338,7 +342,7 @@ impl<'db> UnsafeVisitor<'db> { |
| 338 | 342 | } |
| 339 | 343 | } |
| 340 | 344 | Expr::UnaryOp { expr, op: UnaryOp::Deref } => { |
| 341 | if let TyKind::Raw(..) = &self.infer[*expr].kind(Interner) { | |
| 345 | if let TyKind::Raw(..) = &self.infer[*expr].to_chalk(self.interner).kind(Interner) { | |
| 342 | 346 | self.on_unsafe_op(current.into(), UnsafetyReason::RawPtrDeref); |
| 343 | 347 | } |
| 344 | 348 | } |
src/tools/rust-analyzer/crates/hir-ty/src/display.rs+11-8| ... | ... | @@ -52,7 +52,7 @@ use crate::{ |
| 52 | 52 | AliasEq, AliasTy, Binders, CallableDefId, CallableSig, ConcreteConst, Const, ConstScalar, |
| 53 | 53 | ConstValue, DomainGoal, FnAbi, GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData, |
| 54 | 54 | LifetimeOutlives, MemoryMap, OpaqueTy, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, |
| 55 | TraitEnvironment, TraitRef, TraitRefExt, Ty, TyExt, WhereClause, consteval_nextsolver, | |
| 55 | TraitEnvironment, TraitRef, TraitRefExt, Ty, TyExt, WhereClause, consteval, | |
| 56 | 56 | db::{HirDatabase, InternedClosure}, |
| 57 | 57 | from_assoc_type_id, from_placeholder_idx, |
| 58 | 58 | generics::generics, |
| ... | ... | @@ -750,8 +750,8 @@ impl<'db> HirDisplay for crate::next_solver::Const<'db> { |
| 750 | 750 | } |
| 751 | 751 | rustc_type_ir::ConstKind::Value(const_bytes) => render_const_scalar_ns( |
| 752 | 752 | f, |
| 753 | &const_bytes.value.inner().0, | |
| 754 | &const_bytes.value.inner().1, | |
| 753 | &const_bytes.value.inner().memory, | |
| 754 | &const_bytes.value.inner().memory_map, | |
| 755 | 755 | const_bytes.ty, |
| 756 | 756 | ), |
| 757 | 757 | rustc_type_ir::ConstKind::Unevaluated(unev) => { |
| ... | ... | @@ -1025,7 +1025,7 @@ fn render_const_scalar_inner<'db>( |
| 1025 | 1025 | ty.hir_fmt(f) |
| 1026 | 1026 | } |
| 1027 | 1027 | TyKind::Array(ty, len) => { |
| 1028 | let Some(len) = consteval_nextsolver::try_const_usize(f.db, len) else { | |
| 1028 | let Some(len) = consteval::try_const_usize(f.db, len) else { | |
| 1029 | 1029 | return f.write_str("<unknown-array-len>"); |
| 1030 | 1030 | }; |
| 1031 | 1031 | let Ok(layout) = f.db.layout_of_ty(ty, trait_env) else { |
| ... | ... | @@ -1545,14 +1545,17 @@ impl<'db> HirDisplay for crate::next_solver::Ty<'db> { |
| 1545 | 1545 | never!("Only `impl Fn` is valid for displaying closures in source code"); |
| 1546 | 1546 | } |
| 1547 | 1547 | } |
| 1548 | let chalk_id: chalk_ir::ClosureId<_> = id.into(); | |
| 1549 | 1548 | match f.closure_style { |
| 1550 | 1549 | ClosureStyle::Hide => return write!(f, "{TYPE_HINT_TRUNCATION}"), |
| 1551 | 1550 | ClosureStyle::ClosureWithId => { |
| 1552 | return write!(f, "{{closure#{:?}}}", chalk_id.0.index()); | |
| 1551 | return write!( | |
| 1552 | f, | |
| 1553 | "{{closure#{:?}}}", | |
| 1554 | salsa::plumbing::AsId::as_id(&id).index() | |
| 1555 | ); | |
| 1553 | 1556 | } |
| 1554 | 1557 | ClosureStyle::ClosureWithSubst => { |
| 1555 | write!(f, "{{closure#{:?}}}", chalk_id.0.index())?; | |
| 1558 | write!(f, "{{closure#{:?}}}", salsa::plumbing::AsId::as_id(&id).index())?; | |
| 1556 | 1559 | return hir_fmt_generics(f, substs.as_slice(Interner), None, None); |
| 1557 | 1560 | } |
| 1558 | 1561 | _ => (), |
| ... | ... | @@ -1561,7 +1564,7 @@ impl<'db> HirDisplay for crate::next_solver::Ty<'db> { |
| 1561 | 1564 | if let Some(sig) = sig { |
| 1562 | 1565 | let InternedClosure(def, _) = db.lookup_intern_closure(id); |
| 1563 | 1566 | let infer = db.infer(def); |
| 1564 | let (_, kind) = infer.closure_info(&chalk_id); | |
| 1567 | let (_, kind) = infer.closure_info(id); | |
| 1565 | 1568 | match f.closure_style { |
| 1566 | 1569 | ClosureStyle::ImplFn => write!(f, "impl {kind:?}(")?, |
| 1567 | 1570 | ClosureStyle::RANotation => write!(f, "|")?, |
src/tools/rust-analyzer/crates/hir-ty/src/drop.rs+87-104| ... | ... | @@ -1,18 +1,20 @@ |
| 1 | 1 | //! Utilities for computing drop info about types. |
| 2 | 2 | |
| 3 | use chalk_ir::cast::Cast; | |
| 4 | use hir_def::AdtId; | |
| 5 | use hir_def::lang_item::LangItem; | |
| 6 | use hir_def::signatures::StructFlags; | |
| 3 | use hir_def::{AdtId, lang_item::LangItem, signatures::StructFlags}; | |
| 4 | use rustc_hash::FxHashSet; | |
| 5 | use rustc_type_ir::inherent::{AdtDef, IntoKind, SliceLike}; | |
| 7 | 6 | use stdx::never; |
| 8 | 7 | use triomphe::Arc; |
| 9 | 8 | |
| 10 | use crate::next_solver::DbInterner; | |
| 11 | use crate::next_solver::mapping::NextSolverToChalk; | |
| 12 | 9 | use crate::{ |
| 13 | AliasTy, Canonical, CanonicalVarKinds, ConcreteConst, ConstScalar, ConstValue, InEnvironment, | |
| 14 | Interner, ProjectionTy, TraitEnvironment, Ty, TyBuilder, TyKind, db::HirDatabase, | |
| 10 | TraitEnvironment, consteval, | |
| 11 | db::HirDatabase, | |
| 15 | 12 | method_resolution::TyFingerprint, |
| 13 | next_solver::{ | |
| 14 | Ty, TyKind, | |
| 15 | infer::{InferCtxt, traits::ObligationCause}, | |
| 16 | obligation_ctxt::ObligationCtxt, | |
| 17 | }, | |
| 16 | 18 | }; |
| 17 | 19 | |
| 18 | 20 | fn has_destructor(db: &dyn HirDatabase, adt: AdtId) -> bool { |
| ... | ... | @@ -45,27 +47,52 @@ pub enum DropGlue { |
| 45 | 47 | HasDropGlue, |
| 46 | 48 | } |
| 47 | 49 | |
| 48 | pub(crate) fn has_drop_glue( | |
| 49 | db: &dyn HirDatabase, | |
| 50 | ty: Ty, | |
| 51 | env: Arc<TraitEnvironment<'_>>, | |
| 50 | pub fn has_drop_glue<'db>( | |
| 51 | infcx: &InferCtxt<'db>, | |
| 52 | ty: Ty<'db>, | |
| 53 | env: Arc<TraitEnvironment<'db>>, | |
| 52 | 54 | ) -> DropGlue { |
| 53 | match ty.kind(Interner) { | |
| 54 | TyKind::Adt(adt, subst) => { | |
| 55 | if has_destructor(db, adt.0) { | |
| 55 | has_drop_glue_impl(infcx, ty, env, &mut FxHashSet::default()) | |
| 56 | } | |
| 57 | ||
| 58 | fn has_drop_glue_impl<'db>( | |
| 59 | infcx: &InferCtxt<'db>, | |
| 60 | ty: Ty<'db>, | |
| 61 | env: Arc<TraitEnvironment<'db>>, | |
| 62 | visited: &mut FxHashSet<Ty<'db>>, | |
| 63 | ) -> DropGlue { | |
| 64 | let mut ocx = ObligationCtxt::new(infcx); | |
| 65 | let ty = ocx.structurally_normalize_ty(&ObligationCause::dummy(), env.env, ty).unwrap_or(ty); | |
| 66 | ||
| 67 | if !visited.insert(ty) { | |
| 68 | // Recursive type. | |
| 69 | return DropGlue::None; | |
| 70 | } | |
| 71 | ||
| 72 | let db = infcx.interner.db; | |
| 73 | match ty.kind() { | |
| 74 | TyKind::Adt(adt_def, subst) => { | |
| 75 | let adt_id = adt_def.def_id().0; | |
| 76 | if has_destructor(db, adt_id) { | |
| 56 | 77 | return DropGlue::HasDropGlue; |
| 57 | 78 | } |
| 58 | match adt.0 { | |
| 79 | match adt_id { | |
| 59 | 80 | AdtId::StructId(id) => { |
| 60 | if db.struct_signature(id).flags.contains(StructFlags::IS_MANUALLY_DROP) { | |
| 81 | if db | |
| 82 | .struct_signature(id) | |
| 83 | .flags | |
| 84 | .intersects(StructFlags::IS_MANUALLY_DROP | StructFlags::IS_PHANTOM_DATA) | |
| 85 | { | |
| 61 | 86 | return DropGlue::None; |
| 62 | 87 | } |
| 63 | db.field_types(id.into()) | |
| 88 | db.field_types_ns(id.into()) | |
| 64 | 89 | .iter() |
| 65 | 90 | .map(|(_, field_ty)| { |
| 66 | db.has_drop_glue( | |
| 67 | field_ty.clone().substitute(Interner, subst), | |
| 91 | has_drop_glue_impl( | |
| 92 | infcx, | |
| 93 | field_ty.instantiate(infcx.interner, subst), | |
| 68 | 94 | env.clone(), |
| 95 | visited, | |
| 69 | 96 | ) |
| 70 | 97 | }) |
| 71 | 98 | .max() |
| ... | ... | @@ -78,12 +105,14 @@ pub(crate) fn has_drop_glue( |
| 78 | 105 | .variants |
| 79 | 106 | .iter() |
| 80 | 107 | .map(|&(variant, _, _)| { |
| 81 | db.field_types(variant.into()) | |
| 108 | db.field_types_ns(variant.into()) | |
| 82 | 109 | .iter() |
| 83 | 110 | .map(|(_, field_ty)| { |
| 84 | db.has_drop_glue( | |
| 85 | field_ty.clone().substitute(Interner, subst), | |
| 111 | has_drop_glue_impl( | |
| 112 | infcx, | |
| 113 | field_ty.instantiate(infcx.interner, subst), | |
| 86 | 114 | env.clone(), |
| 115 | visited, | |
| 87 | 116 | ) |
| 88 | 117 | }) |
| 89 | 118 | .max() |
| ... | ... | @@ -93,116 +122,70 @@ pub(crate) fn has_drop_glue( |
| 93 | 122 | .unwrap_or(DropGlue::None), |
| 94 | 123 | } |
| 95 | 124 | } |
| 96 | TyKind::Tuple(_, subst) => subst | |
| 97 | .iter(Interner) | |
| 98 | .map(|ty| ty.assert_ty_ref(Interner)) | |
| 99 | .map(|ty| db.has_drop_glue(ty.clone(), env.clone())) | |
| 125 | TyKind::Tuple(tys) => tys | |
| 126 | .iter() | |
| 127 | .map(|ty| has_drop_glue_impl(infcx, ty, env.clone(), visited)) | |
| 100 | 128 | .max() |
| 101 | 129 | .unwrap_or(DropGlue::None), |
| 102 | 130 | TyKind::Array(ty, len) => { |
| 103 | if let ConstValue::Concrete(ConcreteConst { interned: ConstScalar::Bytes(len, _) }) = | |
| 104 | &len.data(Interner).value | |
| 105 | { | |
| 106 | match (&**len).try_into() { | |
| 107 | Ok(len) => { | |
| 108 | let len = usize::from_le_bytes(len); | |
| 109 | if len == 0 { | |
| 110 | // Arrays of size 0 don't have drop glue. | |
| 111 | return DropGlue::None; | |
| 112 | } | |
| 113 | } | |
| 114 | Err(_) => { | |
| 115 | never!("const array size with non-usize len"); | |
| 116 | } | |
| 117 | } | |
| 131 | if consteval::try_const_usize(db, len) == Some(0) { | |
| 132 | // Arrays of size 0 don't have drop glue. | |
| 133 | return DropGlue::None; | |
| 118 | 134 | } |
| 119 | db.has_drop_glue(ty.clone(), env) | |
| 135 | has_drop_glue_impl(infcx, ty, env, visited) | |
| 120 | 136 | } |
| 121 | TyKind::Slice(ty) => db.has_drop_glue(ty.clone(), env), | |
| 137 | TyKind::Slice(ty) => has_drop_glue_impl(infcx, ty, env, visited), | |
| 122 | 138 | TyKind::Closure(closure_id, subst) => { |
| 123 | let owner = db.lookup_intern_closure((*closure_id).into()).0; | |
| 139 | let owner = db.lookup_intern_closure(closure_id.0).0; | |
| 124 | 140 | let infer = db.infer(owner); |
| 125 | let (captures, _) = infer.closure_info(closure_id); | |
| 141 | let (captures, _) = infer.closure_info(closure_id.0); | |
| 126 | 142 | let env = db.trait_environment_for_body(owner); |
| 127 | 143 | captures |
| 128 | 144 | .iter() |
| 129 | .map(|capture| db.has_drop_glue(capture.ty(db, subst), env.clone())) | |
| 145 | .map(|capture| { | |
| 146 | has_drop_glue_impl(infcx, capture.ty(db, subst), env.clone(), visited) | |
| 147 | }) | |
| 130 | 148 | .max() |
| 131 | 149 | .unwrap_or(DropGlue::None) |
| 132 | 150 | } |
| 133 | 151 | // FIXME: Handle coroutines. |
| 134 | TyKind::Coroutine(..) | TyKind::CoroutineWitness(..) => DropGlue::None, | |
| 152 | TyKind::Coroutine(..) | TyKind::CoroutineWitness(..) | TyKind::CoroutineClosure(..) => { | |
| 153 | DropGlue::None | |
| 154 | } | |
| 135 | 155 | TyKind::Ref(..) |
| 136 | | TyKind::Raw(..) | |
| 156 | | TyKind::RawPtr(..) | |
| 137 | 157 | | TyKind::FnDef(..) |
| 138 | 158 | | TyKind::Str |
| 139 | 159 | | TyKind::Never |
| 140 | | TyKind::Scalar(_) | |
| 141 | | TyKind::Function(_) | |
| 160 | | TyKind::Bool | |
| 161 | | TyKind::Char | |
| 162 | | TyKind::Int(_) | |
| 163 | | TyKind::Uint(_) | |
| 164 | | TyKind::Float(_) | |
| 165 | | TyKind::FnPtr(..) | |
| 142 | 166 | | TyKind::Foreign(_) |
| 143 | | TyKind::Error => DropGlue::None, | |
| 144 | TyKind::Dyn(_) => DropGlue::HasDropGlue, | |
| 145 | TyKind::AssociatedType(assoc_type_id, subst) => projection_has_drop_glue( | |
| 146 | db, | |
| 147 | env, | |
| 148 | ProjectionTy { associated_ty_id: *assoc_type_id, substitution: subst.clone() }, | |
| 149 | ty, | |
| 150 | ), | |
| 151 | TyKind::Alias(AliasTy::Projection(projection)) => { | |
| 152 | projection_has_drop_glue(db, env, projection.clone(), ty) | |
| 153 | } | |
| 154 | TyKind::OpaqueType(..) | TyKind::Alias(AliasTy::Opaque(_)) => { | |
| 155 | if is_copy(db, ty, env) { | |
| 167 | | TyKind::Error(_) | |
| 168 | | TyKind::Bound(..) | |
| 169 | | TyKind::Placeholder(..) => DropGlue::None, | |
| 170 | TyKind::Dynamic(..) => DropGlue::HasDropGlue, | |
| 171 | TyKind::Alias(..) => { | |
| 172 | if infcx.type_is_copy_modulo_regions(env.env, ty) { | |
| 156 | 173 | DropGlue::None |
| 157 | 174 | } else { |
| 158 | 175 | DropGlue::HasDropGlue |
| 159 | 176 | } |
| 160 | 177 | } |
| 161 | TyKind::Placeholder(_) | TyKind::BoundVar(_) => { | |
| 162 | if is_copy(db, ty, env) { | |
| 178 | TyKind::Param(_) => { | |
| 179 | if infcx.type_is_copy_modulo_regions(env.env, ty) { | |
| 163 | 180 | DropGlue::None |
| 164 | 181 | } else { |
| 165 | 182 | DropGlue::DependOnParams |
| 166 | 183 | } |
| 167 | 184 | } |
| 168 | TyKind::InferenceVar(..) => unreachable!("inference vars shouldn't exist out of inference"), | |
| 169 | } | |
| 170 | } | |
| 171 | ||
| 172 | fn projection_has_drop_glue( | |
| 173 | db: &dyn HirDatabase, | |
| 174 | env: Arc<TraitEnvironment<'_>>, | |
| 175 | projection: ProjectionTy, | |
| 176 | ty: Ty, | |
| 177 | ) -> DropGlue { | |
| 178 | let normalized = db.normalize_projection(projection, env.clone()); | |
| 179 | match normalized.kind(Interner) { | |
| 180 | TyKind::Alias(AliasTy::Projection(_)) | TyKind::AssociatedType(..) => { | |
| 181 | if is_copy(db, ty, env) { DropGlue::None } else { DropGlue::DependOnParams } | |
| 185 | TyKind::Infer(..) => unreachable!("inference vars shouldn't exist out of inference"), | |
| 186 | TyKind::Pat(..) | TyKind::UnsafeBinder(..) => { | |
| 187 | never!("we do not handle pattern and unsafe binder types"); | |
| 188 | DropGlue::None | |
| 182 | 189 | } |
| 183 | _ => db.has_drop_glue(normalized, env), | |
| 184 | 190 | } |
| 185 | 191 | } |
| 186 | ||
| 187 | fn is_copy(db: &dyn HirDatabase, ty: Ty, env: Arc<TraitEnvironment<'_>>) -> bool { | |
| 188 | let Some(copy_trait) = LangItem::Copy.resolve_trait(db, env.krate) else { | |
| 189 | return false; | |
| 190 | }; | |
| 191 | let trait_ref = TyBuilder::trait_ref(db, copy_trait).push(ty).build(); | |
| 192 | let goal = Canonical { | |
| 193 | value: InEnvironment::new( | |
| 194 | &env.env.to_chalk(DbInterner::new_with(db, Some(env.krate), env.block)), | |
| 195 | trait_ref.cast(Interner), | |
| 196 | ), | |
| 197 | binders: CanonicalVarKinds::empty(Interner), | |
| 198 | }; | |
| 199 | db.trait_solve(env.krate, env.block, goal).certain() | |
| 200 | } | |
| 201 | ||
| 202 | pub(crate) fn has_drop_glue_cycle_result( | |
| 203 | _db: &dyn HirDatabase, | |
| 204 | _ty: Ty, | |
| 205 | _env: Arc<TraitEnvironment<'_>>, | |
| 206 | ) -> DropGlue { | |
| 207 | DropGlue::None | |
| 208 | } |
src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs+1-1| ... | ... | @@ -57,7 +57,7 @@ fn check_dyn_compatibility<'a>( |
| 57 | 57 | }; |
| 58 | 58 | let mut osvs = FxHashSet::default(); |
| 59 | 59 | let db = &db; |
| 60 | salsa::attach(db, || { | |
| 60 | crate::attach_db(db, || { | |
| 61 | 61 | _ = dyn_compatibility_with_callback(db, trait_id, &mut |osv| { |
| 62 | 62 | osvs.insert(match osv { |
| 63 | 63 | DynCompatibilityViolation::SizedSelf => SizedSelf, |
src/tools/rust-analyzer/crates/hir-ty/src/infer.rs+536-710| ... | ... | @@ -28,19 +28,11 @@ pub(crate) mod unify; |
| 28 | 28 | use std::{cell::OnceCell, convert::identity, iter, ops::Index}; |
| 29 | 29 | |
| 30 | 30 | use base_db::Crate; |
| 31 | use chalk_ir::{ | |
| 32 | DebruijnIndex, Mutability, Safety, Scalar, TyKind, TypeFlags, Variance, | |
| 33 | cast::Cast, | |
| 34 | fold::TypeFoldable, | |
| 35 | interner::HasInterner, | |
| 36 | visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}, | |
| 37 | }; | |
| 38 | 31 | use either::Either; |
| 39 | 32 | use hir_def::{ |
| 40 | 33 | AdtId, AssocItemId, ConstId, DefWithBodyId, FieldId, FunctionId, GenericDefId, GenericParamId, |
| 41 | 34 | ImplId, ItemContainerId, LocalFieldId, Lookup, TraitId, TupleFieldId, TupleId, TypeAliasId, |
| 42 | 35 | VariantId, |
| 43 | builtin_type::{BuiltinInt, BuiltinType, BuiltinUint}, | |
| 44 | 36 | expr_store::{Body, ExpressionStore, HygieneId, path::Path}, |
| 45 | 37 | hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, PatId}, |
| 46 | 38 | lang_item::{LangItem, LangItemTarget, lang_item}, |
| ... | ... | @@ -53,18 +45,19 @@ use hir_expand::{mod_path::ModPath, name::Name}; |
| 53 | 45 | use indexmap::IndexSet; |
| 54 | 46 | use intern::sym; |
| 55 | 47 | use la_arena::{ArenaMap, Entry}; |
| 48 | use rustc_ast_ir::Mutability; | |
| 56 | 49 | use rustc_hash::{FxHashMap, FxHashSet}; |
| 57 | use rustc_type_ir::inherent::Ty as _; | |
| 58 | use stdx::{always, never}; | |
| 50 | use rustc_type_ir::{ | |
| 51 | AliasTyKind, Flags, TypeFlags, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, | |
| 52 | inherent::{AdtDef, IntoKind, Region as _, SliceLike, Ty as _}, | |
| 53 | }; | |
| 54 | use stdx::never; | |
| 59 | 55 | use triomphe::Arc; |
| 60 | 56 | |
| 61 | 57 | use crate::{ |
| 62 | AliasEq, AliasTy, Binders, ClosureId, Const, DomainGoal, GenericArg, ImplTraitId, ImplTraitIdx, | |
| 63 | IncorrectGenericsLenKind, Interner, Lifetime, OpaqueTyId, ParamLoweringMode, | |
| 64 | PathLoweringDiagnostic, ProjectionTy, Substitution, TargetFeatures, TraitEnvironment, Ty, | |
| 65 | TyBuilder, TyExt, | |
| 66 | db::{HirDatabase, InternedClosureId}, | |
| 67 | fold_tys, | |
| 58 | ImplTraitId, IncorrectGenericsLenKind, Interner, PathLoweringDiagnostic, TargetFeatures, | |
| 59 | TraitEnvironment, | |
| 60 | db::{HirDatabase, InternedClosureId, InternedOpaqueTyId}, | |
| 68 | 61 | generics::Generics, |
| 69 | 62 | infer::{ |
| 70 | 63 | coerce::{CoerceMany, DynamicCoerceMany}, |
| ... | ... | @@ -72,16 +65,22 @@ use crate::{ |
| 72 | 65 | expr::ExprIsRead, |
| 73 | 66 | unify::InferenceTable, |
| 74 | 67 | }, |
| 75 | lower::{ImplTraitLoweringMode, LifetimeElisionKind, diagnostics::TyLoweringDiagnostic}, | |
| 68 | lower::diagnostics::TyLoweringDiagnostic, | |
| 69 | lower_nextsolver::{ImplTraitIdx, ImplTraitLoweringMode, LifetimeElisionKind}, | |
| 76 | 70 | mir::MirSpan, |
| 77 | 71 | next_solver::{ |
| 78 | self, DbInterner, | |
| 79 | infer::{DefineOpaqueTypes, traits::ObligationCause}, | |
| 72 | AliasTy, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, Region, Ty, TyKind, | |
| 73 | Tys, | |
| 74 | abi::Safety, | |
| 75 | fold::fold_tys, | |
| 76 | infer::{ | |
| 77 | DefineOpaqueTypes, | |
| 78 | traits::{Obligation, ObligationCause}, | |
| 79 | }, | |
| 80 | 80 | mapping::{ChalkToNextSolver, NextSolverToChalk}, |
| 81 | 81 | }, |
| 82 | static_lifetime, to_assoc_type_id, | |
| 83 | 82 | traits::FnTrait, |
| 84 | utils::{TargetFeatureIsSafeInTarget, UnevaluatedConstEvaluatorFolder}, | |
| 83 | utils::TargetFeatureIsSafeInTarget, | |
| 85 | 84 | }; |
| 86 | 85 | |
| 87 | 86 | // This lint has a false positive here. See the link below for details. |
| ... | ... | @@ -96,7 +95,7 @@ use cast::{CastCheck, CastError}; |
| 96 | 95 | pub(crate) use closure::analysis::{CaptureKind, CapturedItem, CapturedItemWithoutTy}; |
| 97 | 96 | |
| 98 | 97 | /// The entry point of type inference. |
| 99 | pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> { | |
| 98 | pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult<'_>> { | |
| 100 | 99 | let _p = tracing::info_span!("infer_query").entered(); |
| 101 | 100 | let resolver = def.resolver(db); |
| 102 | 101 | let body = db.body(def); |
| ... | ... | @@ -109,30 +108,28 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<Infer |
| 109 | 108 | DefWithBodyId::ConstId(c) => ctx.collect_const(c, &db.const_signature(c)), |
| 110 | 109 | DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_signature(s)), |
| 111 | 110 | DefWithBodyId::VariantId(v) => { |
| 112 | ctx.return_ty = TyBuilder::builtin( | |
| 113 | match db.enum_signature(v.lookup(db).parent).variant_body_type() { | |
| 114 | hir_def::layout::IntegerType::Pointer(signed) => match signed { | |
| 115 | true => BuiltinType::Int(BuiltinInt::Isize), | |
| 116 | false => BuiltinType::Uint(BuiltinUint::Usize), | |
| 111 | ctx.return_ty = match db.enum_signature(v.lookup(db).parent).variant_body_type() { | |
| 112 | hir_def::layout::IntegerType::Pointer(signed) => match signed { | |
| 113 | true => ctx.types.isize, | |
| 114 | false => ctx.types.usize, | |
| 115 | }, | |
| 116 | hir_def::layout::IntegerType::Fixed(size, signed) => match signed { | |
| 117 | true => match size { | |
| 118 | Integer::I8 => ctx.types.i8, | |
| 119 | Integer::I16 => ctx.types.i16, | |
| 120 | Integer::I32 => ctx.types.i32, | |
| 121 | Integer::I64 => ctx.types.i64, | |
| 122 | Integer::I128 => ctx.types.i128, | |
| 117 | 123 | }, |
| 118 | hir_def::layout::IntegerType::Fixed(size, signed) => match signed { | |
| 119 | true => BuiltinType::Int(match size { | |
| 120 | Integer::I8 => BuiltinInt::I8, | |
| 121 | Integer::I16 => BuiltinInt::I16, | |
| 122 | Integer::I32 => BuiltinInt::I32, | |
| 123 | Integer::I64 => BuiltinInt::I64, | |
| 124 | Integer::I128 => BuiltinInt::I128, | |
| 125 | }), | |
| 126 | false => BuiltinType::Uint(match size { | |
| 127 | Integer::I8 => BuiltinUint::U8, | |
| 128 | Integer::I16 => BuiltinUint::U16, | |
| 129 | Integer::I32 => BuiltinUint::U32, | |
| 130 | Integer::I64 => BuiltinUint::U64, | |
| 131 | Integer::I128 => BuiltinUint::U128, | |
| 132 | }), | |
| 124 | false => match size { | |
| 125 | Integer::I8 => ctx.types.u8, | |
| 126 | Integer::I16 => ctx.types.u16, | |
| 127 | Integer::I32 => ctx.types.u32, | |
| 128 | Integer::I64 => ctx.types.u64, | |
| 129 | Integer::I128 => ctx.types.u128, | |
| 133 | 130 | }, |
| 134 | 131 | }, |
| 135 | ); | |
| 132 | }; | |
| 136 | 133 | } |
| 137 | 134 | } |
| 138 | 135 | |
| ... | ... | @@ -159,8 +156,14 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<Infer |
| 159 | 156 | Arc::new(ctx.resolve_all()) |
| 160 | 157 | } |
| 161 | 158 | |
| 162 | pub(crate) fn infer_cycle_result(_: &dyn HirDatabase, _: DefWithBodyId) -> Arc<InferenceResult> { | |
| 163 | Arc::new(InferenceResult { has_errors: true, ..Default::default() }) | |
| 159 | pub(crate) fn infer_cycle_result( | |
| 160 | db: &dyn HirDatabase, | |
| 161 | _: DefWithBodyId, | |
| 162 | ) -> Arc<InferenceResult<'_>> { | |
| 163 | Arc::new(InferenceResult { | |
| 164 | has_errors: true, | |
| 165 | ..InferenceResult::new(Ty::new_error(DbInterner::new_with(db, None, None), ErrorGuaranteed)) | |
| 166 | }) | |
| 164 | 167 | } |
| 165 | 168 | |
| 166 | 169 | /// Fully normalize all the types found within `ty` in context of `owner` body definition. |
| ... | ... | @@ -168,20 +171,24 @@ pub(crate) fn infer_cycle_result(_: &dyn HirDatabase, _: DefWithBodyId) -> Arc<I |
| 168 | 171 | /// This is appropriate to use only after type-check: it assumes |
| 169 | 172 | /// that normalization will succeed, for example. |
| 170 | 173 | #[tracing::instrument(level = "debug", skip(db))] |
| 171 | pub(crate) fn normalize(db: &dyn HirDatabase, trait_env: Arc<TraitEnvironment<'_>>, ty: Ty) -> Ty { | |
| 174 | pub(crate) fn normalize( | |
| 175 | db: &dyn HirDatabase, | |
| 176 | trait_env: Arc<TraitEnvironment<'_>>, | |
| 177 | ty: crate::Ty, | |
| 178 | ) -> crate::Ty { | |
| 172 | 179 | // FIXME: TypeFlags::HAS_CT_PROJECTION is not implemented in chalk, so TypeFlags::HAS_PROJECTION only |
| 173 | 180 | // works for the type case, so we check array unconditionally. Remove the array part |
| 174 | 181 | // when the bug in chalk becomes fixed. |
| 175 | if !ty.data(Interner).flags.intersects(TypeFlags::HAS_PROJECTION) | |
| 176 | && !matches!(ty.kind(Interner), TyKind::Array(..)) | |
| 182 | if !ty.data(Interner).flags.intersects(crate::TypeFlags::HAS_PROJECTION) | |
| 183 | && !matches!(ty.kind(Interner), crate::TyKind::Array(..)) | |
| 177 | 184 | { |
| 178 | 185 | return ty; |
| 179 | 186 | } |
| 180 | 187 | let mut table = unify::InferenceTable::new(db, trait_env); |
| 181 | 188 | |
| 182 | let ty_with_vars = table.normalize_associated_types_in(ty); | |
| 189 | let ty_with_vars = table.normalize_associated_types_in(ty.to_nextsolver(table.interner())); | |
| 183 | 190 | table.select_obligations_where_possible(); |
| 184 | table.resolve_completely(ty_with_vars) | |
| 191 | table.resolve_completely(ty_with_vars).to_chalk(table.interner()) | |
| 185 | 192 | } |
| 186 | 193 | |
| 187 | 194 | /// Binding modes inferred for patterns. |
| ... | ... | @@ -203,14 +210,6 @@ impl BindingMode { |
| 203 | 210 | } |
| 204 | 211 | } |
| 205 | 212 | |
| 206 | // FIXME: Remove this `InferOk`, switch all code to the second one, that uses `Obligation` instead of `Goal`. | |
| 207 | #[derive(Debug)] | |
| 208 | pub(crate) struct InferOk<'db, T> { | |
| 209 | #[allow(dead_code)] | |
| 210 | value: T, | |
| 211 | goals: Vec<next_solver::Goal<'db, next_solver::Predicate<'db>>>, | |
| 212 | } | |
| 213 | ||
| 214 | 213 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] |
| 215 | 214 | pub enum InferenceTyDiagnosticSource { |
| 216 | 215 | /// Diagnostics that come from types in the body. |
| ... | ... | @@ -219,12 +218,8 @@ pub enum InferenceTyDiagnosticSource { |
| 219 | 218 | Signature, |
| 220 | 219 | } |
| 221 | 220 | |
| 222 | #[derive(Debug)] | |
| 223 | pub(crate) struct TypeError; | |
| 224 | pub(crate) type InferResult<'db, T> = Result<InferOk<'db, T>, TypeError>; | |
| 225 | ||
| 226 | 221 | #[derive(Debug, PartialEq, Eq, Clone)] |
| 227 | pub enum InferenceDiagnostic { | |
| 222 | pub enum InferenceDiagnostic<'db> { | |
| 228 | 223 | NoSuchField { |
| 229 | 224 | field: ExprOrPatId, |
| 230 | 225 | private: Option<LocalFieldId>, |
| ... | ... | @@ -240,16 +235,16 @@ pub enum InferenceDiagnostic { |
| 240 | 235 | }, |
| 241 | 236 | UnresolvedField { |
| 242 | 237 | expr: ExprId, |
| 243 | receiver: Ty, | |
| 238 | receiver: Ty<'db>, | |
| 244 | 239 | name: Name, |
| 245 | 240 | method_with_same_name_exists: bool, |
| 246 | 241 | }, |
| 247 | 242 | UnresolvedMethodCall { |
| 248 | 243 | expr: ExprId, |
| 249 | receiver: Ty, | |
| 244 | receiver: Ty<'db>, | |
| 250 | 245 | name: Name, |
| 251 | 246 | /// Contains the type the field resolves to |
| 252 | field_with_same_name: Option<Ty>, | |
| 247 | field_with_same_name: Option<Ty<'db>>, | |
| 253 | 248 | assoc_func_with_same_name: Option<FunctionId>, |
| 254 | 249 | }, |
| 255 | 250 | UnresolvedAssocItem { |
| ... | ... | @@ -276,21 +271,21 @@ pub enum InferenceDiagnostic { |
| 276 | 271 | }, |
| 277 | 272 | ExpectedFunction { |
| 278 | 273 | call_expr: ExprId, |
| 279 | found: Ty, | |
| 274 | found: Ty<'db>, | |
| 280 | 275 | }, |
| 281 | 276 | TypedHole { |
| 282 | 277 | expr: ExprId, |
| 283 | expected: Ty, | |
| 278 | expected: Ty<'db>, | |
| 284 | 279 | }, |
| 285 | 280 | CastToUnsized { |
| 286 | 281 | expr: ExprId, |
| 287 | cast_ty: Ty, | |
| 282 | cast_ty: Ty<'db>, | |
| 288 | 283 | }, |
| 289 | 284 | InvalidCast { |
| 290 | 285 | expr: ExprId, |
| 291 | 286 | error: CastError, |
| 292 | expr_ty: Ty, | |
| 293 | cast_ty: Ty, | |
| 287 | expr_ty: Ty<'db>, | |
| 288 | cast_ty: Ty<'db>, | |
| 294 | 289 | }, |
| 295 | 290 | TyDiagnostic { |
| 296 | 291 | source: InferenceTyDiagnosticSource, |
| ... | ... | @@ -318,29 +313,11 @@ pub enum InferenceDiagnostic { |
| 318 | 313 | |
| 319 | 314 | /// A mismatch between an expected and an inferred type. |
| 320 | 315 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
| 321 | pub struct TypeMismatch { | |
| 322 | pub expected: Ty, | |
| 323 | pub actual: Ty, | |
| 316 | pub struct TypeMismatch<'db> { | |
| 317 | pub expected: Ty<'db>, | |
| 318 | pub actual: Ty<'db>, | |
| 324 | 319 | } |
| 325 | 320 | |
| 326 | #[derive(Clone, PartialEq, Eq, Debug)] | |
| 327 | struct InternedStandardTypes { | |
| 328 | unknown: Ty, | |
| 329 | bool_: Ty, | |
| 330 | unit: Ty, | |
| 331 | never: Ty, | |
| 332 | } | |
| 333 | ||
| 334 | impl Default for InternedStandardTypes { | |
| 335 | fn default() -> Self { | |
| 336 | InternedStandardTypes { | |
| 337 | unknown: TyKind::Error.intern(Interner), | |
| 338 | bool_: TyKind::Scalar(Scalar::Bool).intern(Interner), | |
| 339 | unit: TyKind::Tuple(0, Substitution::empty(Interner)).intern(Interner), | |
| 340 | never: TyKind::Never.intern(Interner), | |
| 341 | } | |
| 342 | } | |
| 343 | } | |
| 344 | 321 | /// Represents coercing a value to a different type of value. |
| 345 | 322 | /// |
| 346 | 323 | /// We transform values by following a number of `Adjust` steps in order. |
| ... | ... | @@ -382,14 +359,14 @@ impl Default for InternedStandardTypes { |
| 382 | 359 | /// case this is analogous to transforming a struct. E.g., Box<[i32; 4]> -> |
| 383 | 360 | /// Box<[i32]> is an `Adjust::Unsize` with the target `Box<[i32]>`. |
| 384 | 361 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] |
| 385 | pub struct Adjustment { | |
| 386 | pub kind: Adjust, | |
| 387 | pub target: Ty, | |
| 362 | pub struct Adjustment<'db> { | |
| 363 | pub kind: Adjust<'db>, | |
| 364 | pub target: Ty<'db>, | |
| 388 | 365 | } |
| 389 | 366 | |
| 390 | impl Adjustment { | |
| 391 | pub fn borrow(m: Mutability, ty: Ty, lt: Lifetime) -> Self { | |
| 392 | let ty = TyKind::Ref(m, lt.clone(), ty).intern(Interner); | |
| 367 | impl<'db> Adjustment<'db> { | |
| 368 | pub fn borrow(interner: DbInterner<'db>, m: Mutability, ty: Ty<'db>, lt: Region<'db>) -> Self { | |
| 369 | let ty = Ty::new_ref(interner, lt, ty, m); | |
| 393 | 370 | Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(lt, m)), target: ty } |
| 394 | 371 | } |
| 395 | 372 | } |
| ... | ... | @@ -415,13 +392,13 @@ pub(crate) enum AllowTwoPhase { |
| 415 | 392 | } |
| 416 | 393 | |
| 417 | 394 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] |
| 418 | pub enum Adjust { | |
| 395 | pub enum Adjust<'db> { | |
| 419 | 396 | /// Go from ! to any type. |
| 420 | 397 | NeverToAny, |
| 421 | 398 | /// Dereference once, producing a place. |
| 422 | 399 | Deref(Option<OverloadedDeref>), |
| 423 | 400 | /// Take the address and produce either a `&` or `*` pointer. |
| 424 | Borrow(AutoBorrow), | |
| 401 | Borrow(AutoBorrow<'db>), | |
| 425 | 402 | Pointer(PointerCast), |
| 426 | 403 | } |
| 427 | 404 | |
| ... | ... | @@ -433,14 +410,14 @@ pub enum Adjust { |
| 433 | 410 | pub struct OverloadedDeref(pub Option<Mutability>); |
| 434 | 411 | |
| 435 | 412 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] |
| 436 | pub enum AutoBorrow { | |
| 413 | pub enum AutoBorrow<'db> { | |
| 437 | 414 | /// Converts from T to &T. |
| 438 | Ref(Lifetime, Mutability), | |
| 415 | Ref(Region<'db>, Mutability), | |
| 439 | 416 | /// Converts from T to *T. |
| 440 | 417 | RawPtr(Mutability), |
| 441 | 418 | } |
| 442 | 419 | |
| 443 | impl AutoBorrow { | |
| 420 | impl<'db> AutoBorrow<'db> { | |
| 444 | 421 | fn mutability(&self) -> Mutability { |
| 445 | 422 | let (AutoBorrow::Ref(_, m) | AutoBorrow::RawPtr(m)) = self; |
| 446 | 423 | *m |
| ... | ... | @@ -484,41 +461,41 @@ pub enum PointerCast { |
| 484 | 461 | /// When you add a field that stores types (including `Substitution` and the like), don't forget |
| 485 | 462 | /// `resolve_completely()`'ing them in `InferenceContext::resolve_all()`. Inference variables must |
| 486 | 463 | /// not appear in the final inference result. |
| 487 | #[derive(Clone, PartialEq, Eq, Debug, Default)] | |
| 488 | pub struct InferenceResult { | |
| 464 | #[derive(Clone, PartialEq, Eq, Debug)] | |
| 465 | pub struct InferenceResult<'db> { | |
| 489 | 466 | /// For each method call expr, records the function it resolves to. |
| 490 | method_resolutions: FxHashMap<ExprId, (FunctionId, Substitution)>, | |
| 467 | method_resolutions: FxHashMap<ExprId, (FunctionId, GenericArgs<'db>)>, | |
| 491 | 468 | /// For each field access expr, records the field it resolves to. |
| 492 | 469 | field_resolutions: FxHashMap<ExprId, Either<FieldId, TupleFieldId>>, |
| 493 | 470 | /// For each struct literal or pattern, records the variant it resolves to. |
| 494 | 471 | variant_resolutions: FxHashMap<ExprOrPatId, VariantId>, |
| 495 | 472 | /// For each associated item record what it resolves to |
| 496 | assoc_resolutions: FxHashMap<ExprOrPatId, (AssocItemId, Substitution)>, | |
| 473 | assoc_resolutions: FxHashMap<ExprOrPatId, (AssocItemId, GenericArgs<'db>)>, | |
| 497 | 474 | /// Whenever a tuple field expression access a tuple field, we allocate a tuple id in |
| 498 | 475 | /// [`InferenceContext`] and store the tuples substitution there. This map is the reverse of |
| 499 | 476 | /// that which allows us to resolve a [`TupleFieldId`]s type. |
| 500 | tuple_field_access_types: FxHashMap<TupleId, Substitution>, | |
| 477 | tuple_field_access_types: FxHashMap<TupleId, Tys<'db>>, | |
| 501 | 478 | /// During inference this field is empty and [`InferenceContext::diagnostics`] is filled instead. |
| 502 | diagnostics: Vec<InferenceDiagnostic>, | |
| 503 | pub(crate) type_of_expr: ArenaMap<ExprId, Ty>, | |
| 479 | diagnostics: Vec<InferenceDiagnostic<'db>>, | |
| 480 | pub(crate) type_of_expr: ArenaMap<ExprId, Ty<'db>>, | |
| 504 | 481 | /// For each pattern record the type it resolves to. |
| 505 | 482 | /// |
| 506 | 483 | /// **Note**: When a pattern type is resolved it may still contain |
| 507 | 484 | /// unresolved or missing subpatterns or subpatterns of mismatched types. |
| 508 | pub(crate) type_of_pat: ArenaMap<PatId, Ty>, | |
| 509 | pub(crate) type_of_binding: ArenaMap<BindingId, Ty>, | |
| 510 | pub(crate) type_of_rpit: ArenaMap<ImplTraitIdx, Ty>, | |
| 511 | type_mismatches: FxHashMap<ExprOrPatId, TypeMismatch>, | |
| 485 | pub(crate) type_of_pat: ArenaMap<PatId, Ty<'db>>, | |
| 486 | pub(crate) type_of_binding: ArenaMap<BindingId, Ty<'db>>, | |
| 487 | pub(crate) type_of_rpit: ArenaMap<ImplTraitIdx<'db>, Ty<'db>>, | |
| 488 | type_mismatches: FxHashMap<ExprOrPatId, TypeMismatch<'db>>, | |
| 512 | 489 | /// Whether there are any type-mismatching errors in the result. |
| 513 | 490 | // FIXME: This isn't as useful as initially thought due to us falling back placeholders to |
| 514 | 491 | // `TyKind::Error`. |
| 515 | 492 | // Which will then mark this field. |
| 516 | 493 | pub(crate) has_errors: bool, |
| 517 | /// Interned common types to return references to. | |
| 518 | // FIXME: Move this into `InferenceContext` | |
| 519 | standard_types: InternedStandardTypes, | |
| 494 | /// Interned `Error` type to return references to. | |
| 495 | // FIXME: Remove this. | |
| 496 | error_ty: Ty<'db>, | |
| 520 | 497 | /// Stores the types which were implicitly dereferenced in pattern binding modes. |
| 521 | pub(crate) pat_adjustments: FxHashMap<PatId, Vec<Ty>>, | |
| 498 | pub(crate) pat_adjustments: FxHashMap<PatId, Vec<Ty<'db>>>, | |
| 522 | 499 | /// Stores the binding mode (`ref` in `let ref x = 2`) of bindings. |
| 523 | 500 | /// |
| 524 | 501 | /// This one is tied to the `PatId` instead of `BindingId`, because in some rare cases, a binding in an |
| ... | ... | @@ -533,16 +510,40 @@ pub struct InferenceResult { |
| 533 | 510 | /// ``` |
| 534 | 511 | /// the first `rest` has implicit `ref` binding mode, but the second `rest` binding mode is `move`. |
| 535 | 512 | pub(crate) binding_modes: ArenaMap<PatId, BindingMode>, |
| 536 | pub(crate) expr_adjustments: FxHashMap<ExprId, Box<[Adjustment]>>, | |
| 537 | pub(crate) closure_info: FxHashMap<ClosureId, (Vec<CapturedItem>, FnTrait)>, | |
| 513 | pub(crate) expr_adjustments: FxHashMap<ExprId, Box<[Adjustment<'db>]>>, | |
| 514 | pub(crate) closure_info: FxHashMap<InternedClosureId, (Vec<CapturedItem<'db>>, FnTrait)>, | |
| 538 | 515 | // FIXME: remove this field |
| 539 | 516 | pub mutated_bindings_in_closure: FxHashSet<BindingId>, |
| 540 | 517 | pub(crate) coercion_casts: FxHashSet<ExprId>, |
| 541 | 518 | } |
| 542 | 519 | |
| 543 | impl InferenceResult { | |
| 544 | pub fn method_resolution(&self, expr: ExprId) -> Option<(FunctionId, Substitution)> { | |
| 545 | self.method_resolutions.get(&expr).cloned() | |
| 520 | impl<'db> InferenceResult<'db> { | |
| 521 | fn new(error_ty: Ty<'db>) -> Self { | |
| 522 | Self { | |
| 523 | method_resolutions: Default::default(), | |
| 524 | field_resolutions: Default::default(), | |
| 525 | variant_resolutions: Default::default(), | |
| 526 | assoc_resolutions: Default::default(), | |
| 527 | tuple_field_access_types: Default::default(), | |
| 528 | diagnostics: Default::default(), | |
| 529 | type_of_expr: Default::default(), | |
| 530 | type_of_pat: Default::default(), | |
| 531 | type_of_binding: Default::default(), | |
| 532 | type_of_rpit: Default::default(), | |
| 533 | type_mismatches: Default::default(), | |
| 534 | has_errors: Default::default(), | |
| 535 | error_ty, | |
| 536 | pat_adjustments: Default::default(), | |
| 537 | binding_modes: Default::default(), | |
| 538 | expr_adjustments: Default::default(), | |
| 539 | closure_info: Default::default(), | |
| 540 | mutated_bindings_in_closure: Default::default(), | |
| 541 | coercion_casts: Default::default(), | |
| 542 | } | |
| 543 | } | |
| 544 | ||
| 545 | pub fn method_resolution(&self, expr: ExprId) -> Option<(FunctionId, GenericArgs<'db>)> { | |
| 546 | self.method_resolutions.get(&expr).copied() | |
| 546 | 547 | } |
| 547 | 548 | pub fn field_resolution(&self, expr: ExprId) -> Option<Either<FieldId, TupleFieldId>> { |
| 548 | 549 | self.field_resolutions.get(&expr).copied() |
| ... | ... | @@ -559,46 +560,49 @@ impl InferenceResult { |
| 559 | 560 | ExprOrPatId::PatId(id) => self.variant_resolution_for_pat(id), |
| 560 | 561 | } |
| 561 | 562 | } |
| 562 | pub fn assoc_resolutions_for_expr(&self, id: ExprId) -> Option<(AssocItemId, Substitution)> { | |
| 563 | self.assoc_resolutions.get(&id.into()).cloned() | |
| 563 | pub fn assoc_resolutions_for_expr( | |
| 564 | &self, | |
| 565 | id: ExprId, | |
| 566 | ) -> Option<(AssocItemId, GenericArgs<'db>)> { | |
| 567 | self.assoc_resolutions.get(&id.into()).copied() | |
| 564 | 568 | } |
| 565 | pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<(AssocItemId, Substitution)> { | |
| 566 | self.assoc_resolutions.get(&id.into()).cloned() | |
| 569 | pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<(AssocItemId, GenericArgs<'db>)> { | |
| 570 | self.assoc_resolutions.get(&id.into()).copied() | |
| 567 | 571 | } |
| 568 | 572 | pub fn assoc_resolutions_for_expr_or_pat( |
| 569 | 573 | &self, |
| 570 | 574 | id: ExprOrPatId, |
| 571 | ) -> Option<(AssocItemId, Substitution)> { | |
| 575 | ) -> Option<(AssocItemId, GenericArgs<'db>)> { | |
| 572 | 576 | match id { |
| 573 | 577 | ExprOrPatId::ExprId(id) => self.assoc_resolutions_for_expr(id), |
| 574 | 578 | ExprOrPatId::PatId(id) => self.assoc_resolutions_for_pat(id), |
| 575 | 579 | } |
| 576 | 580 | } |
| 577 | pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch> { | |
| 581 | pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch<'db>> { | |
| 578 | 582 | self.type_mismatches.get(&expr.into()) |
| 579 | 583 | } |
| 580 | pub fn type_mismatch_for_pat(&self, pat: PatId) -> Option<&TypeMismatch> { | |
| 584 | pub fn type_mismatch_for_pat(&self, pat: PatId) -> Option<&TypeMismatch<'db>> { | |
| 581 | 585 | self.type_mismatches.get(&pat.into()) |
| 582 | 586 | } |
| 583 | pub fn type_mismatches(&self) -> impl Iterator<Item = (ExprOrPatId, &TypeMismatch)> { | |
| 587 | pub fn type_mismatches(&self) -> impl Iterator<Item = (ExprOrPatId, &TypeMismatch<'db>)> { | |
| 584 | 588 | self.type_mismatches.iter().map(|(expr_or_pat, mismatch)| (*expr_or_pat, mismatch)) |
| 585 | 589 | } |
| 586 | pub fn expr_type_mismatches(&self) -> impl Iterator<Item = (ExprId, &TypeMismatch)> { | |
| 590 | pub fn expr_type_mismatches(&self) -> impl Iterator<Item = (ExprId, &TypeMismatch<'db>)> { | |
| 587 | 591 | self.type_mismatches.iter().filter_map(|(expr_or_pat, mismatch)| match *expr_or_pat { |
| 588 | 592 | ExprOrPatId::ExprId(expr) => Some((expr, mismatch)), |
| 589 | 593 | _ => None, |
| 590 | 594 | }) |
| 591 | 595 | } |
| 592 | pub fn closure_info(&self, closure: &ClosureId) -> &(Vec<CapturedItem>, FnTrait) { | |
| 593 | self.closure_info.get(closure).unwrap() | |
| 596 | pub fn closure_info(&self, closure: InternedClosureId) -> &(Vec<CapturedItem<'db>>, FnTrait) { | |
| 597 | self.closure_info.get(&closure).unwrap() | |
| 594 | 598 | } |
| 595 | pub fn type_of_expr_or_pat(&self, id: ExprOrPatId) -> Option<&Ty> { | |
| 599 | pub fn type_of_expr_or_pat(&self, id: ExprOrPatId) -> Option<Ty<'db>> { | |
| 596 | 600 | match id { |
| 597 | ExprOrPatId::ExprId(id) => self.type_of_expr.get(id), | |
| 598 | ExprOrPatId::PatId(id) => self.type_of_pat.get(id), | |
| 601 | ExprOrPatId::ExprId(id) => self.type_of_expr.get(id).copied(), | |
| 602 | ExprOrPatId::PatId(id) => self.type_of_pat.get(id).copied(), | |
| 599 | 603 | } |
| 600 | 604 | } |
| 601 | pub fn type_of_expr_with_adjust(&self, id: ExprId) -> Option<&Ty> { | |
| 605 | pub fn type_of_expr_with_adjust(&self, id: ExprId) -> Option<Ty<'db>> { | |
| 602 | 606 | match self.expr_adjustments.get(&id).and_then(|adjustments| { |
| 603 | 607 | adjustments |
| 604 | 608 | .iter() |
| ... | ... | @@ -614,33 +618,33 @@ impl InferenceResult { |
| 614 | 618 | }) |
| 615 | 619 | .next_back() |
| 616 | 620 | }) { |
| 617 | Some(adjustment) => Some(&adjustment.target), | |
| 618 | None => self.type_of_expr.get(id), | |
| 621 | Some(adjustment) => Some(adjustment.target), | |
| 622 | None => self.type_of_expr.get(id).copied(), | |
| 619 | 623 | } |
| 620 | 624 | } |
| 621 | pub fn type_of_pat_with_adjust(&self, id: PatId) -> Option<&Ty> { | |
| 625 | pub fn type_of_pat_with_adjust(&self, id: PatId) -> Option<Ty<'db>> { | |
| 622 | 626 | match self.pat_adjustments.get(&id).and_then(|adjustments| adjustments.last()) { |
| 623 | adjusted @ Some(_) => adjusted, | |
| 624 | None => self.type_of_pat.get(id), | |
| 627 | Some(adjusted) => Some(*adjusted), | |
| 628 | None => self.type_of_pat.get(id).copied(), | |
| 625 | 629 | } |
| 626 | 630 | } |
| 627 | 631 | pub fn is_erroneous(&self) -> bool { |
| 628 | 632 | self.has_errors && self.type_of_expr.iter().count() == 0 |
| 629 | 633 | } |
| 630 | 634 | |
| 631 | pub fn diagnostics(&self) -> &[InferenceDiagnostic] { | |
| 635 | pub fn diagnostics(&self) -> &[InferenceDiagnostic<'db>] { | |
| 632 | 636 | &self.diagnostics |
| 633 | 637 | } |
| 634 | 638 | |
| 635 | pub fn tuple_field_access_type(&self, id: TupleId) -> &Substitution { | |
| 636 | &self.tuple_field_access_types[&id] | |
| 639 | pub fn tuple_field_access_type(&self, id: TupleId) -> Tys<'db> { | |
| 640 | self.tuple_field_access_types[&id] | |
| 637 | 641 | } |
| 638 | 642 | |
| 639 | pub fn pat_adjustment(&self, id: PatId) -> Option<&[Ty]> { | |
| 643 | pub fn pat_adjustment(&self, id: PatId) -> Option<&[Ty<'db>]> { | |
| 640 | 644 | self.pat_adjustments.get(&id).map(|it| &**it) |
| 641 | 645 | } |
| 642 | 646 | |
| 643 | pub fn expr_adjustment(&self, id: ExprId) -> Option<&[Adjustment]> { | |
| 647 | pub fn expr_adjustment(&self, id: ExprId) -> Option<&[Adjustment<'db>]> { | |
| 644 | 648 | self.expr_adjustments.get(&id).map(|it| &**it) |
| 645 | 649 | } |
| 646 | 650 | |
| ... | ... | @@ -649,83 +653,138 @@ impl InferenceResult { |
| 649 | 653 | } |
| 650 | 654 | |
| 651 | 655 | // This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please. |
| 652 | pub fn expression_types(&self) -> impl Iterator<Item = (ExprId, &Ty)> { | |
| 653 | self.type_of_expr.iter() | |
| 656 | pub fn expression_types(&self) -> impl Iterator<Item = (ExprId, Ty<'db>)> { | |
| 657 | self.type_of_expr.iter().map(|(k, v)| (k, *v)) | |
| 654 | 658 | } |
| 655 | 659 | |
| 656 | 660 | // This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please. |
| 657 | pub fn pattern_types(&self) -> impl Iterator<Item = (PatId, &Ty)> { | |
| 658 | self.type_of_pat.iter() | |
| 661 | pub fn pattern_types(&self) -> impl Iterator<Item = (PatId, Ty<'db>)> { | |
| 662 | self.type_of_pat.iter().map(|(k, v)| (k, *v)) | |
| 659 | 663 | } |
| 660 | 664 | |
| 661 | 665 | // This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please. |
| 662 | pub fn binding_types(&self) -> impl Iterator<Item = (BindingId, &Ty)> { | |
| 663 | self.type_of_binding.iter() | |
| 666 | pub fn binding_types(&self) -> impl Iterator<Item = (BindingId, Ty<'db>)> { | |
| 667 | self.type_of_binding.iter().map(|(k, v)| (k, *v)) | |
| 664 | 668 | } |
| 665 | 669 | |
| 666 | 670 | // This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please. |
| 667 | pub fn return_position_impl_trait_types(&self) -> impl Iterator<Item = (ImplTraitIdx, &Ty)> { | |
| 668 | self.type_of_rpit.iter() | |
| 671 | pub fn return_position_impl_trait_types( | |
| 672 | &self, | |
| 673 | ) -> impl Iterator<Item = (ImplTraitIdx<'db>, Ty<'db>)> { | |
| 674 | self.type_of_rpit.iter().map(|(k, v)| (k, *v)) | |
| 669 | 675 | } |
| 670 | 676 | } |
| 671 | 677 | |
| 672 | impl Index<ExprId> for InferenceResult { | |
| 673 | type Output = Ty; | |
| 678 | impl<'db> Index<ExprId> for InferenceResult<'db> { | |
| 679 | type Output = Ty<'db>; | |
| 674 | 680 | |
| 675 | fn index(&self, expr: ExprId) -> &Ty { | |
| 676 | self.type_of_expr.get(expr).unwrap_or(&self.standard_types.unknown) | |
| 681 | fn index(&self, expr: ExprId) -> &Ty<'db> { | |
| 682 | self.type_of_expr.get(expr).unwrap_or(&self.error_ty) | |
| 677 | 683 | } |
| 678 | 684 | } |
| 679 | 685 | |
| 680 | impl Index<PatId> for InferenceResult { | |
| 681 | type Output = Ty; | |
| 686 | impl<'db> Index<PatId> for InferenceResult<'db> { | |
| 687 | type Output = Ty<'db>; | |
| 682 | 688 | |
| 683 | fn index(&self, pat: PatId) -> &Ty { | |
| 684 | self.type_of_pat.get(pat).unwrap_or(&self.standard_types.unknown) | |
| 689 | fn index(&self, pat: PatId) -> &Ty<'db> { | |
| 690 | self.type_of_pat.get(pat).unwrap_or(&self.error_ty) | |
| 685 | 691 | } |
| 686 | 692 | } |
| 687 | 693 | |
| 688 | impl Index<ExprOrPatId> for InferenceResult { | |
| 689 | type Output = Ty; | |
| 694 | impl<'db> Index<ExprOrPatId> for InferenceResult<'db> { | |
| 695 | type Output = Ty<'db>; | |
| 690 | 696 | |
| 691 | fn index(&self, id: ExprOrPatId) -> &Ty { | |
| 692 | self.type_of_expr_or_pat(id).unwrap_or(&self.standard_types.unknown) | |
| 697 | fn index(&self, id: ExprOrPatId) -> &Ty<'db> { | |
| 698 | match id { | |
| 699 | ExprOrPatId::ExprId(id) => &self[id], | |
| 700 | ExprOrPatId::PatId(id) => &self[id], | |
| 701 | } | |
| 693 | 702 | } |
| 694 | 703 | } |
| 695 | 704 | |
| 696 | impl Index<BindingId> for InferenceResult { | |
| 697 | type Output = Ty; | |
| 705 | impl<'db> Index<BindingId> for InferenceResult<'db> { | |
| 706 | type Output = Ty<'db>; | |
| 698 | 707 | |
| 699 | fn index(&self, b: BindingId) -> &Ty { | |
| 700 | self.type_of_binding.get(b).unwrap_or(&self.standard_types.unknown) | |
| 708 | fn index(&self, b: BindingId) -> &Ty<'db> { | |
| 709 | self.type_of_binding.get(b).unwrap_or(&self.error_ty) | |
| 701 | 710 | } |
| 702 | 711 | } |
| 703 | 712 | |
| 704 | 713 | #[derive(Debug, Clone)] |
| 705 | struct InternedStandardTypesNextSolver<'db> { | |
| 706 | unit: crate::next_solver::Ty<'db>, | |
| 707 | never: crate::next_solver::Ty<'db>, | |
| 708 | i32: crate::next_solver::Ty<'db>, | |
| 709 | f64: crate::next_solver::Ty<'db>, | |
| 714 | struct InternedStandardTypes<'db> { | |
| 715 | unit: Ty<'db>, | |
| 716 | never: Ty<'db>, | |
| 717 | char: Ty<'db>, | |
| 718 | bool: Ty<'db>, | |
| 719 | i8: Ty<'db>, | |
| 720 | i16: Ty<'db>, | |
| 721 | i32: Ty<'db>, | |
| 722 | i64: Ty<'db>, | |
| 723 | i128: Ty<'db>, | |
| 724 | isize: Ty<'db>, | |
| 725 | u8: Ty<'db>, | |
| 726 | u16: Ty<'db>, | |
| 727 | u32: Ty<'db>, | |
| 728 | u64: Ty<'db>, | |
| 729 | u128: Ty<'db>, | |
| 730 | usize: Ty<'db>, | |
| 731 | f16: Ty<'db>, | |
| 732 | f32: Ty<'db>, | |
| 733 | f64: Ty<'db>, | |
| 734 | f128: Ty<'db>, | |
| 735 | static_str_ref: Ty<'db>, | |
| 736 | error: Ty<'db>, | |
| 737 | ||
| 738 | re_static: Region<'db>, | |
| 739 | re_error: Region<'db>, | |
| 740 | ||
| 741 | empty_args: GenericArgs<'db>, | |
| 742 | empty_tys: Tys<'db>, | |
| 710 | 743 | } |
| 711 | 744 | |
| 712 | impl<'db> InternedStandardTypesNextSolver<'db> { | |
| 745 | impl<'db> InternedStandardTypes<'db> { | |
| 713 | 746 | fn new(interner: DbInterner<'db>) -> Self { |
| 747 | let str = Ty::new(interner, rustc_type_ir::TyKind::Str); | |
| 748 | let re_static = Region::new_static(interner); | |
| 714 | 749 | Self { |
| 715 | unit: crate::next_solver::Ty::new_unit(interner), | |
| 716 | never: crate::next_solver::Ty::new(interner, crate::next_solver::TyKind::Never), | |
| 717 | i32: crate::next_solver::Ty::new_int(interner, rustc_type_ir::IntTy::I32), | |
| 718 | f64: crate::next_solver::Ty::new_float(interner, rustc_type_ir::FloatTy::F64), | |
| 750 | unit: Ty::new_unit(interner), | |
| 751 | never: Ty::new(interner, TyKind::Never), | |
| 752 | char: Ty::new(interner, TyKind::Char), | |
| 753 | bool: Ty::new(interner, TyKind::Bool), | |
| 754 | i8: Ty::new_int(interner, rustc_type_ir::IntTy::I8), | |
| 755 | i16: Ty::new_int(interner, rustc_type_ir::IntTy::I16), | |
| 756 | i32: Ty::new_int(interner, rustc_type_ir::IntTy::I32), | |
| 757 | i64: Ty::new_int(interner, rustc_type_ir::IntTy::I64), | |
| 758 | i128: Ty::new_int(interner, rustc_type_ir::IntTy::I128), | |
| 759 | isize: Ty::new_int(interner, rustc_type_ir::IntTy::Isize), | |
| 760 | u8: Ty::new_uint(interner, rustc_type_ir::UintTy::U8), | |
| 761 | u16: Ty::new_uint(interner, rustc_type_ir::UintTy::U16), | |
| 762 | u32: Ty::new_uint(interner, rustc_type_ir::UintTy::U32), | |
| 763 | u64: Ty::new_uint(interner, rustc_type_ir::UintTy::U64), | |
| 764 | u128: Ty::new_uint(interner, rustc_type_ir::UintTy::U128), | |
| 765 | usize: Ty::new_uint(interner, rustc_type_ir::UintTy::Usize), | |
| 766 | f16: Ty::new_float(interner, rustc_type_ir::FloatTy::F16), | |
| 767 | f32: Ty::new_float(interner, rustc_type_ir::FloatTy::F32), | |
| 768 | f64: Ty::new_float(interner, rustc_type_ir::FloatTy::F64), | |
| 769 | f128: Ty::new_float(interner, rustc_type_ir::FloatTy::F128), | |
| 770 | static_str_ref: Ty::new_ref(interner, re_static, str, Mutability::Not), | |
| 771 | error: Ty::new_error(interner, ErrorGuaranteed), | |
| 772 | ||
| 773 | re_static, | |
| 774 | re_error: Region::error(interner), | |
| 775 | ||
| 776 | empty_args: GenericArgs::new_from_iter(interner, []), | |
| 777 | empty_tys: Tys::new_from_iter(interner, []), | |
| 719 | 778 | } |
| 720 | 779 | } |
| 721 | 780 | } |
| 722 | 781 | |
| 723 | 782 | /// The inference context contains all information needed during type inference. |
| 724 | 783 | #[derive(Clone, Debug)] |
| 725 | pub(crate) struct InferenceContext<'db> { | |
| 784 | pub(crate) struct InferenceContext<'body, 'db> { | |
| 726 | 785 | pub(crate) db: &'db dyn HirDatabase, |
| 727 | 786 | pub(crate) owner: DefWithBodyId, |
| 728 | pub(crate) body: &'db Body, | |
| 787 | pub(crate) body: &'body Body, | |
| 729 | 788 | /// Generally you should not resolve things via this resolver. Instead create a TyLoweringContext |
| 730 | 789 | /// and resolve the path via its methods. This will ensure proper error reporting. |
| 731 | 790 | pub(crate) resolver: Resolver<'db>, |
| ... | ... | @@ -735,32 +794,32 @@ pub(crate) struct InferenceContext<'db> { |
| 735 | 794 | table: unify::InferenceTable<'db>, |
| 736 | 795 | /// The traits in scope, disregarding block modules. This is used for caching purposes. |
| 737 | 796 | traits_in_scope: FxHashSet<TraitId>, |
| 738 | pub(crate) result: InferenceResult, | |
| 797 | pub(crate) result: InferenceResult<'db>, | |
| 739 | 798 | tuple_field_accesses_rev: |
| 740 | IndexSet<Substitution, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>, | |
| 799 | IndexSet<Tys<'db>, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>, | |
| 741 | 800 | /// The return type of the function being inferred, the closure or async block if we're |
| 742 | 801 | /// currently within one. |
| 743 | 802 | /// |
| 744 | 803 | /// We might consider using a nested inference context for checking |
| 745 | 804 | /// closures so we can swap all shared things out at once. |
| 746 | return_ty: Ty, | |
| 805 | return_ty: Ty<'db>, | |
| 747 | 806 | /// If `Some`, this stores coercion information for returned |
| 748 | 807 | /// expressions. If `None`, this is in a context where return is |
| 749 | 808 | /// inappropriate, such as a const expression. |
| 750 | 809 | return_coercion: Option<DynamicCoerceMany<'db>>, |
| 751 | 810 | /// The resume type and the yield type, respectively, of the coroutine being inferred. |
| 752 | resume_yield_tys: Option<(Ty, Ty)>, | |
| 811 | resume_yield_tys: Option<(Ty<'db>, Ty<'db>)>, | |
| 753 | 812 | diverges: Diverges, |
| 754 | 813 | breakables: Vec<BreakableContext<'db>>, |
| 755 | types: InternedStandardTypesNextSolver<'db>, | |
| 814 | types: InternedStandardTypes<'db>, | |
| 756 | 815 | |
| 757 | 816 | /// Whether we are inside the pattern of a destructuring assignment. |
| 758 | 817 | inside_assignment: bool, |
| 759 | 818 | |
| 760 | deferred_cast_checks: Vec<CastCheck>, | |
| 819 | deferred_cast_checks: Vec<CastCheck<'db>>, | |
| 761 | 820 | |
| 762 | 821 | // fields related to closure capture |
| 763 | current_captures: Vec<CapturedItemWithoutTy>, | |
| 822 | current_captures: Vec<CapturedItemWithoutTy<'db>>, | |
| 764 | 823 | /// A stack that has an entry for each projection in the current capture. |
| 765 | 824 | /// |
| 766 | 825 | /// For example, in `a.b.c`, we capture the spans of `a`, `a.b`, and `a.b.c`. |
| ... | ... | @@ -771,9 +830,9 @@ pub(crate) struct InferenceContext<'db> { |
| 771 | 830 | /// Stores the list of closure ids that need to be analyzed before this closure. See the |
| 772 | 831 | /// comment on `InferenceContext::sort_closures` |
| 773 | 832 | closure_dependencies: FxHashMap<InternedClosureId, Vec<InternedClosureId>>, |
| 774 | deferred_closures: FxHashMap<InternedClosureId, Vec<(Ty, Ty, Vec<Ty>, ExprId)>>, | |
| 833 | deferred_closures: FxHashMap<InternedClosureId, Vec<(Ty<'db>, Ty<'db>, Vec<Ty<'db>>, ExprId)>>, | |
| 775 | 834 | |
| 776 | diagnostics: Diagnostics, | |
| 835 | diagnostics: Diagnostics<'db>, | |
| 777 | 836 | } |
| 778 | 837 | |
| 779 | 838 | #[derive(Clone, Debug)] |
| ... | ... | @@ -820,28 +879,29 @@ fn find_continuable<'a, 'db>( |
| 820 | 879 | } |
| 821 | 880 | } |
| 822 | 881 | |
| 823 | enum ImplTraitReplacingMode { | |
| 824 | ReturnPosition(FxHashSet<Ty>), | |
| 882 | enum ImplTraitReplacingMode<'db> { | |
| 883 | ReturnPosition(FxHashSet<Ty<'db>>), | |
| 825 | 884 | TypeAlias, |
| 826 | 885 | } |
| 827 | 886 | |
| 828 | impl<'db> InferenceContext<'db> { | |
| 887 | impl<'body, 'db> InferenceContext<'body, 'db> { | |
| 829 | 888 | fn new( |
| 830 | 889 | db: &'db dyn HirDatabase, |
| 831 | 890 | owner: DefWithBodyId, |
| 832 | body: &'db Body, | |
| 891 | body: &'body Body, | |
| 833 | 892 | resolver: Resolver<'db>, |
| 834 | 893 | ) -> Self { |
| 835 | 894 | let trait_env = db.trait_environment_for_body(owner); |
| 836 | 895 | let table = unify::InferenceTable::new(db, trait_env); |
| 896 | let types = InternedStandardTypes::new(table.interner()); | |
| 837 | 897 | InferenceContext { |
| 838 | types: InternedStandardTypesNextSolver::new(table.interner), | |
| 898 | result: InferenceResult::new(types.error), | |
| 899 | return_ty: types.error, // set in collect_* calls | |
| 900 | types, | |
| 839 | 901 | target_features: OnceCell::new(), |
| 840 | 902 | generics: OnceCell::new(), |
| 841 | result: InferenceResult::default(), | |
| 842 | 903 | table, |
| 843 | 904 | tuple_field_accesses_rev: Default::default(), |
| 844 | return_ty: TyKind::Error.intern(Interner), // set in collect_* calls | |
| 845 | 905 | resume_yield_tys: None, |
| 846 | 906 | return_coercion: None, |
| 847 | 907 | db, |
| ... | ... | @@ -904,7 +964,7 @@ impl<'db> InferenceContext<'db> { |
| 904 | 964 | |
| 905 | 965 | /// Clones `self` and calls `resolve_all()` on it. |
| 906 | 966 | // FIXME: Remove this. |
| 907 | pub(crate) fn fixme_resolve_all_clone(&self) -> InferenceResult { | |
| 967 | pub(crate) fn fixme_resolve_all_clone(&self) -> InferenceResult<'db> { | |
| 908 | 968 | let mut ctx = self.clone(); |
| 909 | 969 | |
| 910 | 970 | ctx.type_inference_fallback(); |
| ... | ... | @@ -928,7 +988,7 @@ impl<'db> InferenceContext<'db> { |
| 928 | 988 | // `InferenceResult` in the middle of inference. See the fixme comment in `consteval::eval_to_const`. If you |
| 929 | 989 | // used this function for another workaround, mention it here. If you really need this function and believe that |
| 930 | 990 | // there is no problem in it being `pub(crate)`, remove this comment. |
| 931 | pub(crate) fn resolve_all(self) -> InferenceResult { | |
| 991 | pub(crate) fn resolve_all(self) -> InferenceResult<'db> { | |
| 932 | 992 | let InferenceContext { |
| 933 | 993 | mut table, mut result, tuple_field_accesses_rev, diagnostics, .. |
| 934 | 994 | } = self; |
| ... | ... | @@ -946,7 +1006,7 @@ impl<'db> InferenceContext<'db> { |
| 946 | 1006 | type_of_rpit, |
| 947 | 1007 | type_mismatches, |
| 948 | 1008 | has_errors, |
| 949 | standard_types: _, | |
| 1009 | error_ty: _, | |
| 950 | 1010 | pat_adjustments, |
| 951 | 1011 | binding_modes: _, |
| 952 | 1012 | expr_adjustments, |
| ... | ... | @@ -961,39 +1021,32 @@ impl<'db> InferenceContext<'db> { |
| 961 | 1021 | } = &mut result; |
| 962 | 1022 | |
| 963 | 1023 | for ty in type_of_expr.values_mut() { |
| 964 | *ty = table.resolve_completely(ty.clone()); | |
| 965 | *has_errors = *has_errors || ty.contains_unknown(); | |
| 1024 | *ty = table.resolve_completely(*ty); | |
| 1025 | *has_errors = *has_errors || ty.references_non_lt_error(); | |
| 966 | 1026 | } |
| 967 | 1027 | type_of_expr.shrink_to_fit(); |
| 968 | 1028 | for ty in type_of_pat.values_mut() { |
| 969 | *ty = table.resolve_completely(ty.clone()); | |
| 970 | *has_errors = *has_errors || ty.contains_unknown(); | |
| 1029 | *ty = table.resolve_completely(*ty); | |
| 1030 | *has_errors = *has_errors || ty.references_non_lt_error(); | |
| 971 | 1031 | } |
| 972 | 1032 | type_of_pat.shrink_to_fit(); |
| 973 | 1033 | for ty in type_of_binding.values_mut() { |
| 974 | *ty = table.resolve_completely(ty.clone()); | |
| 975 | *has_errors = *has_errors || ty.contains_unknown(); | |
| 1034 | *ty = table.resolve_completely(*ty); | |
| 1035 | *has_errors = *has_errors || ty.references_non_lt_error(); | |
| 976 | 1036 | } |
| 977 | 1037 | type_of_binding.shrink_to_fit(); |
| 978 | 1038 | for ty in type_of_rpit.values_mut() { |
| 979 | *ty = table.resolve_completely(ty.clone()); | |
| 980 | *has_errors = *has_errors || ty.contains_unknown(); | |
| 1039 | *ty = table.resolve_completely(*ty); | |
| 1040 | *has_errors = *has_errors || ty.references_non_lt_error(); | |
| 981 | 1041 | } |
| 982 | 1042 | type_of_rpit.shrink_to_fit(); |
| 983 | 1043 | |
| 984 | 1044 | *has_errors |= !type_mismatches.is_empty(); |
| 985 | 1045 | |
| 986 | type_mismatches.retain(|_, mismatch| { | |
| 987 | mismatch.expected = table.resolve_completely(mismatch.expected.clone()); | |
| 988 | mismatch.actual = table.resolve_completely(mismatch.actual.clone()); | |
| 989 | chalk_ir::zip::Zip::zip_with( | |
| 990 | &mut UnknownMismatch(self.db), | |
| 991 | Variance::Invariant, | |
| 992 | &mismatch.expected, | |
| 993 | &mismatch.actual, | |
| 994 | ) | |
| 995 | .is_ok() | |
| 996 | }); | |
| 1046 | for mismatch in (*type_mismatches).values_mut() { | |
| 1047 | mismatch.expected = table.resolve_completely(mismatch.expected); | |
| 1048 | mismatch.actual = table.resolve_completely(mismatch.actual); | |
| 1049 | } | |
| 997 | 1050 | type_mismatches.shrink_to_fit(); |
| 998 | 1051 | diagnostics.retain_mut(|diagnostic| { |
| 999 | 1052 | use InferenceDiagnostic::*; |
| ... | ... | @@ -1001,23 +1054,23 @@ impl<'db> InferenceContext<'db> { |
| 1001 | 1054 | ExpectedFunction { found: ty, .. } |
| 1002 | 1055 | | UnresolvedField { receiver: ty, .. } |
| 1003 | 1056 | | UnresolvedMethodCall { receiver: ty, .. } => { |
| 1004 | *ty = table.resolve_completely(ty.clone()); | |
| 1057 | *ty = table.resolve_completely(*ty); | |
| 1005 | 1058 | // FIXME: Remove this when we are on par with rustc in terms of inference |
| 1006 | if ty.contains_unknown() { | |
| 1059 | if ty.references_non_lt_error() { | |
| 1007 | 1060 | return false; |
| 1008 | 1061 | } |
| 1009 | 1062 | |
| 1010 | 1063 | if let UnresolvedMethodCall { field_with_same_name, .. } = diagnostic |
| 1011 | 1064 | && let Some(ty) = field_with_same_name |
| 1012 | 1065 | { |
| 1013 | *ty = table.resolve_completely(ty.clone()); | |
| 1014 | if ty.contains_unknown() { | |
| 1066 | *ty = table.resolve_completely(*ty); | |
| 1067 | if ty.references_non_lt_error() { | |
| 1015 | 1068 | *field_with_same_name = None; |
| 1016 | 1069 | } |
| 1017 | 1070 | } |
| 1018 | 1071 | } |
| 1019 | 1072 | TypedHole { expected: ty, .. } => { |
| 1020 | *ty = table.resolve_completely(ty.clone()); | |
| 1073 | *ty = table.resolve_completely(*ty); | |
| 1021 | 1074 | } |
| 1022 | 1075 | _ => (), |
| 1023 | 1076 | } |
| ... | ... | @@ -1025,41 +1078,31 @@ impl<'db> InferenceContext<'db> { |
| 1025 | 1078 | }); |
| 1026 | 1079 | diagnostics.shrink_to_fit(); |
| 1027 | 1080 | for (_, subst) in method_resolutions.values_mut() { |
| 1028 | *subst = | |
| 1029 | table.resolve_completely::<_, crate::next_solver::GenericArgs<'db>>(subst.clone()); | |
| 1030 | *has_errors = | |
| 1031 | *has_errors || subst.type_parameters(Interner).any(|ty| ty.contains_unknown()); | |
| 1081 | *subst = table.resolve_completely(*subst); | |
| 1082 | *has_errors = *has_errors || subst.types().any(|ty| ty.references_non_lt_error()); | |
| 1032 | 1083 | } |
| 1033 | 1084 | method_resolutions.shrink_to_fit(); |
| 1034 | 1085 | for (_, subst) in assoc_resolutions.values_mut() { |
| 1035 | *subst = | |
| 1036 | table.resolve_completely::<_, crate::next_solver::GenericArgs<'db>>(subst.clone()); | |
| 1037 | *has_errors = | |
| 1038 | *has_errors || subst.type_parameters(Interner).any(|ty| ty.contains_unknown()); | |
| 1086 | *subst = table.resolve_completely(*subst); | |
| 1087 | *has_errors = *has_errors || subst.types().any(|ty| ty.references_non_lt_error()); | |
| 1039 | 1088 | } |
| 1040 | 1089 | assoc_resolutions.shrink_to_fit(); |
| 1041 | 1090 | for adjustment in expr_adjustments.values_mut().flatten() { |
| 1042 | adjustment.target = table.resolve_completely(adjustment.target.clone()); | |
| 1043 | *has_errors = *has_errors || adjustment.target.contains_unknown(); | |
| 1091 | adjustment.target = table.resolve_completely(adjustment.target); | |
| 1092 | *has_errors = *has_errors || adjustment.target.references_non_lt_error(); | |
| 1044 | 1093 | } |
| 1045 | 1094 | expr_adjustments.shrink_to_fit(); |
| 1046 | 1095 | for adjustment in pat_adjustments.values_mut().flatten() { |
| 1047 | *adjustment = table.resolve_completely(adjustment.clone()); | |
| 1048 | *has_errors = *has_errors || adjustment.contains_unknown(); | |
| 1096 | *adjustment = table.resolve_completely(*adjustment); | |
| 1097 | *has_errors = *has_errors || adjustment.references_non_lt_error(); | |
| 1049 | 1098 | } |
| 1050 | 1099 | pat_adjustments.shrink_to_fit(); |
| 1051 | 1100 | result.tuple_field_access_types = tuple_field_accesses_rev |
| 1052 | 1101 | .into_iter() |
| 1053 | 1102 | .enumerate() |
| 1054 | .map(|(idx, subst)| { | |
| 1055 | ( | |
| 1056 | TupleId(idx as u32), | |
| 1057 | table.resolve_completely::<_, crate::next_solver::GenericArgs<'db>>(subst), | |
| 1058 | ) | |
| 1059 | }) | |
| 1103 | .map(|(idx, subst)| (TupleId(idx as u32), table.resolve_completely(subst))) | |
| 1060 | 1104 | .inspect(|(_, subst)| { |
| 1061 | *has_errors = | |
| 1062 | *has_errors || subst.type_parameters(Interner).any(|ty| ty.contains_unknown()); | |
| 1105 | *has_errors = *has_errors || subst.iter().any(|ty| ty.references_non_lt_error()); | |
| 1063 | 1106 | }) |
| 1064 | 1107 | .collect(); |
| 1065 | 1108 | result.tuple_field_access_types.shrink_to_fit(); |
| ... | ... | @@ -1074,11 +1117,11 @@ impl<'db> InferenceContext<'db> { |
| 1074 | 1117 | data.type_ref, |
| 1075 | 1118 | &data.store, |
| 1076 | 1119 | InferenceTyDiagnosticSource::Signature, |
| 1077 | LifetimeElisionKind::for_const(id.loc(self.db).container), | |
| 1120 | LifetimeElisionKind::for_const(self.interner(), id.loc(self.db).container), | |
| 1078 | 1121 | ); |
| 1079 | 1122 | |
| 1080 | 1123 | // Constants might be defining usage sites of TAITs. |
| 1081 | self.make_tait_coercion_table(iter::once(&return_ty)); | |
| 1124 | self.make_tait_coercion_table(iter::once(return_ty)); | |
| 1082 | 1125 | |
| 1083 | 1126 | self.return_ty = return_ty; |
| 1084 | 1127 | } |
| ... | ... | @@ -1088,11 +1131,11 @@ impl<'db> InferenceContext<'db> { |
| 1088 | 1131 | data.type_ref, |
| 1089 | 1132 | &data.store, |
| 1090 | 1133 | InferenceTyDiagnosticSource::Signature, |
| 1091 | LifetimeElisionKind::Elided(static_lifetime()), | |
| 1134 | LifetimeElisionKind::Elided(self.types.re_static), | |
| 1092 | 1135 | ); |
| 1093 | 1136 | |
| 1094 | 1137 | // Statics might be defining usage sites of TAITs. |
| 1095 | self.make_tait_coercion_table(iter::once(&return_ty)); | |
| 1138 | self.make_tait_coercion_table(iter::once(return_ty)); | |
| 1096 | 1139 | |
| 1097 | 1140 | self.return_ty = return_ty; |
| 1098 | 1141 | } |
| ... | ... | @@ -1103,25 +1146,28 @@ impl<'db> InferenceContext<'db> { |
| 1103 | 1146 | &data.store, |
| 1104 | 1147 | InferenceTyDiagnosticSource::Signature, |
| 1105 | 1148 | LifetimeElisionKind::for_fn_params(&data), |
| 1106 | |ctx| { | |
| 1107 | ctx.type_param_mode(ParamLoweringMode::Placeholder); | |
| 1108 | data.params.iter().map(|&type_ref| ctx.lower_ty(type_ref)).collect::<Vec<_>>() | |
| 1109 | }, | |
| 1149 | |ctx| data.params.iter().map(|&type_ref| ctx.lower_ty(type_ref)).collect::<Vec<_>>(), | |
| 1110 | 1150 | ); |
| 1111 | 1151 | |
| 1112 | 1152 | // Check if function contains a va_list, if it does then we append it to the parameter types |
| 1113 | 1153 | // that are collected from the function data |
| 1114 | 1154 | if data.is_varargs() { |
| 1115 | 1155 | let va_list_ty = match self.resolve_va_list() { |
| 1116 | Some(va_list) => TyBuilder::adt(self.db, va_list) | |
| 1117 | .fill_with_defaults(self.db, || self.table.new_type_var()) | |
| 1118 | .build(), | |
| 1156 | Some(va_list) => Ty::new_adt( | |
| 1157 | self.interner(), | |
| 1158 | va_list, | |
| 1159 | GenericArgs::for_item_with_defaults( | |
| 1160 | self.interner(), | |
| 1161 | va_list.into(), | |
| 1162 | |_, _, id, _| self.table.next_var_for_param(id), | |
| 1163 | ), | |
| 1164 | ), | |
| 1119 | 1165 | None => self.err_ty(), |
| 1120 | 1166 | }; |
| 1121 | 1167 | |
| 1122 | 1168 | param_tys.push(va_list_ty); |
| 1123 | 1169 | } |
| 1124 | let mut param_tys = param_tys.into_iter().chain(iter::repeat(self.table.new_type_var())); | |
| 1170 | let mut param_tys = param_tys.into_iter().chain(iter::repeat(self.table.next_ty_var())); | |
| 1125 | 1171 | if let Some(self_param) = self.body.self_param |
| 1126 | 1172 | && let Some(ty) = param_tys.next() |
| 1127 | 1173 | { |
| ... | ... | @@ -1132,12 +1178,8 @@ impl<'db> InferenceContext<'db> { |
| 1132 | 1178 | for (ty, pat) in param_tys.zip(&*self.body.params) { |
| 1133 | 1179 | let ty = self.process_user_written_ty(ty); |
| 1134 | 1180 | |
| 1135 | self.infer_top_pat(*pat, &ty, None); | |
| 1136 | if ty | |
| 1137 | .data(Interner) | |
| 1138 | .flags | |
| 1139 | .intersects(TypeFlags::HAS_TY_OPAQUE.union(TypeFlags::HAS_TY_INFER)) | |
| 1140 | { | |
| 1181 | self.infer_top_pat(*pat, ty, None); | |
| 1182 | if ty.flags().intersects(TypeFlags::HAS_TY_OPAQUE.union(TypeFlags::HAS_TY_INFER)) { | |
| 1141 | 1183 | tait_candidates.insert(ty); |
| 1142 | 1184 | } |
| 1143 | 1185 | } |
| ... | ... | @@ -1146,31 +1188,24 @@ impl<'db> InferenceContext<'db> { |
| 1146 | 1188 | let return_ty = self.with_ty_lowering( |
| 1147 | 1189 | &data.store, |
| 1148 | 1190 | InferenceTyDiagnosticSource::Signature, |
| 1149 | LifetimeElisionKind::for_fn_ret(), | |
| 1191 | LifetimeElisionKind::for_fn_ret(self.interner()), | |
| 1150 | 1192 | |ctx| { |
| 1151 | ctx.type_param_mode(ParamLoweringMode::Placeholder) | |
| 1152 | .impl_trait_mode(ImplTraitLoweringMode::Opaque); | |
| 1193 | ctx.impl_trait_mode(ImplTraitLoweringMode::Opaque); | |
| 1153 | 1194 | ctx.lower_ty(return_ty) |
| 1154 | 1195 | }, |
| 1155 | 1196 | ); |
| 1156 | 1197 | let return_ty = self.insert_type_vars(return_ty); |
| 1157 | if let Some(rpits) = self.db.return_type_impl_traits(func) { | |
| 1158 | // RPIT opaque types use substitution of their parent function. | |
| 1159 | let fn_placeholders = TyBuilder::placeholder_subst(self.db, func); | |
| 1198 | if let Some(rpits) = self.db.return_type_impl_traits_ns(func) { | |
| 1160 | 1199 | let mut mode = ImplTraitReplacingMode::ReturnPosition(FxHashSet::default()); |
| 1161 | let result = self.insert_inference_vars_for_impl_trait( | |
| 1162 | return_ty, | |
| 1163 | fn_placeholders, | |
| 1164 | &mut mode, | |
| 1165 | ); | |
| 1200 | let result = self.insert_inference_vars_for_impl_trait(return_ty, &mut mode); | |
| 1166 | 1201 | if let ImplTraitReplacingMode::ReturnPosition(taits) = mode { |
| 1167 | 1202 | tait_candidates.extend(taits); |
| 1168 | 1203 | } |
| 1169 | let rpits = rpits.skip_binders(); | |
| 1204 | let rpits = (*rpits).as_ref().skip_binder(); | |
| 1170 | 1205 | for (id, _) in rpits.impl_traits.iter() { |
| 1171 | 1206 | if let Entry::Vacant(e) = self.result.type_of_rpit.entry(id) { |
| 1172 | 1207 | never!("Missed RPIT in `insert_inference_vars_for_rpit`"); |
| 1173 | e.insert(TyKind::Error.intern(Interner)); | |
| 1208 | e.insert(self.types.error); | |
| 1174 | 1209 | } |
| 1175 | 1210 | } |
| 1176 | 1211 | result |
| ... | ... | @@ -1178,111 +1213,97 @@ impl<'db> InferenceContext<'db> { |
| 1178 | 1213 | return_ty |
| 1179 | 1214 | } |
| 1180 | 1215 | } |
| 1181 | None => self.result.standard_types.unit.clone(), | |
| 1216 | None => self.types.unit, | |
| 1182 | 1217 | }; |
| 1183 | 1218 | |
| 1184 | 1219 | self.return_ty = self.process_user_written_ty(return_ty); |
| 1185 | self.return_coercion = | |
| 1186 | Some(CoerceMany::new(self.return_ty.to_nextsolver(self.table.interner))); | |
| 1220 | self.return_coercion = Some(CoerceMany::new(self.return_ty)); | |
| 1187 | 1221 | |
| 1188 | 1222 | // Functions might be defining usage sites of TAITs. |
| 1189 | 1223 | // To define an TAITs, that TAIT must appear in the function's signatures. |
| 1190 | 1224 | // So, it suffices to check for params and return types. |
| 1191 | fold_tys( | |
| 1192 | self.return_ty.clone(), | |
| 1193 | |ty, _| { | |
| 1194 | match ty.kind(Interner) { | |
| 1195 | TyKind::OpaqueType(..) | |
| 1196 | | TyKind::Alias(AliasTy::Opaque(..)) | |
| 1197 | | TyKind::InferenceVar(..) => { | |
| 1198 | tait_candidates.insert(self.return_ty.clone()); | |
| 1199 | } | |
| 1200 | _ => {} | |
| 1225 | fold_tys(self.interner(), self.return_ty, |ty| { | |
| 1226 | match ty.kind() { | |
| 1227 | TyKind::Alias(AliasTyKind::Opaque, _) | TyKind::Infer(..) => { | |
| 1228 | tait_candidates.insert(self.return_ty); | |
| 1201 | 1229 | } |
| 1202 | ty | |
| 1203 | }, | |
| 1204 | DebruijnIndex::INNERMOST, | |
| 1205 | ); | |
| 1230 | _ => {} | |
| 1231 | } | |
| 1232 | ty | |
| 1233 | }); | |
| 1234 | ||
| 1235 | self.make_tait_coercion_table(tait_candidates.iter().copied()); | |
| 1236 | } | |
| 1206 | 1237 | |
| 1207 | self.make_tait_coercion_table(tait_candidates.iter()); | |
| 1238 | #[inline] | |
| 1239 | pub(crate) fn interner(&self) -> DbInterner<'db> { | |
| 1240 | self.table.interner() | |
| 1208 | 1241 | } |
| 1209 | 1242 | |
| 1210 | 1243 | fn insert_inference_vars_for_impl_trait<T>( |
| 1211 | 1244 | &mut self, |
| 1212 | 1245 | t: T, |
| 1213 | placeholders: Substitution, | |
| 1214 | mode: &mut ImplTraitReplacingMode, | |
| 1246 | mode: &mut ImplTraitReplacingMode<'db>, | |
| 1215 | 1247 | ) -> T |
| 1216 | 1248 | where |
| 1217 | T: crate::HasInterner<Interner = Interner> + crate::TypeFoldable<Interner>, | |
| 1249 | T: TypeFoldable<DbInterner<'db>>, | |
| 1218 | 1250 | { |
| 1219 | fold_tys( | |
| 1220 | t, | |
| 1221 | |ty, _| { | |
| 1222 | let ty = self.table.structurally_resolve_type(&ty); | |
| 1223 | let opaque_ty_id = match ty.kind(Interner) { | |
| 1224 | TyKind::OpaqueType(opaque_ty_id, _) | |
| 1225 | | TyKind::Alias(AliasTy::Opaque(crate::OpaqueTy { opaque_ty_id, .. })) => { | |
| 1226 | *opaque_ty_id | |
| 1227 | } | |
| 1228 | _ => return ty, | |
| 1229 | }; | |
| 1230 | let (impl_traits, idx) = | |
| 1231 | match self.db.lookup_intern_impl_trait_id(opaque_ty_id.into()) { | |
| 1232 | // We don't replace opaque types from other kind with inference vars | |
| 1233 | // because `insert_inference_vars_for_impl_traits` for each kinds | |
| 1234 | // and unreplaced opaque types of other kind are resolved while | |
| 1235 | // inferencing because of `tait_coercion_table`. | |
| 1236 | // Moreover, calling `insert_inference_vars_for_impl_traits` with same | |
| 1237 | // `placeholders` for other kind may cause trouble because | |
| 1238 | // the substs for the bounds of each impl traits do not match | |
| 1239 | ImplTraitId::ReturnTypeImplTrait(def, idx) => { | |
| 1240 | if matches!(mode, ImplTraitReplacingMode::TypeAlias) { | |
| 1241 | // RPITs don't have `tait_coercion_table`, so use inserted inference | |
| 1242 | // vars for them. | |
| 1243 | if let Some(ty) = self.result.type_of_rpit.get(idx) { | |
| 1244 | return ty.clone(); | |
| 1245 | } | |
| 1246 | return ty; | |
| 1247 | } | |
| 1248 | (self.db.return_type_impl_traits(def), idx) | |
| 1249 | } | |
| 1250 | ImplTraitId::TypeAliasImplTrait(def, idx) => { | |
| 1251 | if let ImplTraitReplacingMode::ReturnPosition(taits) = mode { | |
| 1252 | // Gather TAITs while replacing RPITs because TAITs inside RPITs | |
| 1253 | // may not visited while replacing TAITs | |
| 1254 | taits.insert(ty.clone()); | |
| 1255 | return ty; | |
| 1256 | } | |
| 1257 | (self.db.type_alias_impl_traits(def), idx) | |
| 1251 | fold_tys(self.interner(), t, |ty| { | |
| 1252 | let ty = self.table.try_structurally_resolve_type(ty); | |
| 1253 | let opaque_ty_id = match ty.kind() { | |
| 1254 | TyKind::Alias(AliasTyKind::Opaque, alias_ty) => alias_ty.def_id.expect_opaque_ty(), | |
| 1255 | _ => return ty, | |
| 1256 | }; | |
| 1257 | let (impl_traits, idx) = match self.db.lookup_intern_impl_trait_id(opaque_ty_id) { | |
| 1258 | // We don't replace opaque types from other kind with inference vars | |
| 1259 | // because `insert_inference_vars_for_impl_traits` for each kinds | |
| 1260 | // and unreplaced opaque types of other kind are resolved while | |
| 1261 | // inferencing because of `tait_coercion_table`. | |
| 1262 | ImplTraitId::ReturnTypeImplTrait(def, idx) => { | |
| 1263 | if matches!(mode, ImplTraitReplacingMode::TypeAlias) { | |
| 1264 | // RPITs don't have `tait_coercion_table`, so use inserted inference | |
| 1265 | // vars for them. | |
| 1266 | if let Some(ty) = | |
| 1267 | self.result.type_of_rpit.get(idx.to_nextsolver(self.interner())) | |
| 1268 | { | |
| 1269 | return *ty; | |
| 1258 | 1270 | } |
| 1259 | _ => unreachable!(), | |
| 1260 | }; | |
| 1261 | let Some(impl_traits) = impl_traits else { | |
| 1262 | return ty; | |
| 1263 | }; | |
| 1264 | let bounds = (*impl_traits) | |
| 1265 | .map_ref(|its| its.impl_traits[idx].bounds.map_ref(|it| it.iter())); | |
| 1266 | let var = self.table.new_type_var(); | |
| 1267 | let var_subst = Substitution::from1(Interner, var.clone()); | |
| 1268 | for bound in bounds { | |
| 1269 | let predicate = bound.map(|it| it.cloned()); | |
| 1270 | let predicate = predicate.substitute(Interner, &placeholders); | |
| 1271 | let (var_predicate, binders) = | |
| 1272 | predicate.substitute(Interner, &var_subst).into_value_and_skipped_binders(); | |
| 1273 | always!(binders.is_empty(Interner)); // quantified where clauses not yet handled | |
| 1274 | let var_predicate = self.insert_inference_vars_for_impl_trait( | |
| 1275 | var_predicate, | |
| 1276 | placeholders.clone(), | |
| 1277 | mode, | |
| 1278 | ); | |
| 1279 | self.push_obligation(var_predicate.cast(Interner)); | |
| 1271 | return ty; | |
| 1272 | } | |
| 1273 | (self.db.return_type_impl_traits_ns(def), idx) | |
| 1280 | 1274 | } |
| 1281 | self.result.type_of_rpit.insert(idx, var.clone()); | |
| 1282 | var | |
| 1283 | }, | |
| 1284 | DebruijnIndex::INNERMOST, | |
| 1285 | ) | |
| 1275 | ImplTraitId::TypeAliasImplTrait(def, idx) => { | |
| 1276 | if let ImplTraitReplacingMode::ReturnPosition(taits) = mode { | |
| 1277 | // Gather TAITs while replacing RPITs because TAITs inside RPITs | |
| 1278 | // may not visited while replacing TAITs | |
| 1279 | taits.insert(ty); | |
| 1280 | return ty; | |
| 1281 | } | |
| 1282 | (self.db.type_alias_impl_traits_ns(def), idx) | |
| 1283 | } | |
| 1284 | _ => unreachable!(), | |
| 1285 | }; | |
| 1286 | let Some(impl_traits) = impl_traits else { | |
| 1287 | return ty; | |
| 1288 | }; | |
| 1289 | let bounds = (*impl_traits).as_ref().map_bound(|its| { | |
| 1290 | its.impl_traits[idx.to_nextsolver(self.interner())].predicates.as_slice() | |
| 1291 | }); | |
| 1292 | let var = match self.result.type_of_rpit.entry(idx.to_nextsolver(self.interner())) { | |
| 1293 | Entry::Occupied(entry) => return *entry.get(), | |
| 1294 | Entry::Vacant(entry) => *entry.insert(self.table.next_ty_var()), | |
| 1295 | }; | |
| 1296 | for clause in bounds.iter_identity_copied() { | |
| 1297 | let clause = self.insert_inference_vars_for_impl_trait(clause, mode); | |
| 1298 | self.table.register_predicate(Obligation::new( | |
| 1299 | self.interner(), | |
| 1300 | ObligationCause::new(), | |
| 1301 | self.table.trait_env.env, | |
| 1302 | clause, | |
| 1303 | )); | |
| 1304 | } | |
| 1305 | var | |
| 1306 | }) | |
| 1286 | 1307 | } |
| 1287 | 1308 | |
| 1288 | 1309 | /// The coercion of a non-inference var into an opaque type should fail, |
| ... | ... | @@ -1296,51 +1317,38 @@ impl<'db> InferenceContext<'db> { |
| 1296 | 1317 | /// - We are pushing `impl Trait` bounds into it |
| 1297 | 1318 | /// |
| 1298 | 1319 | /// This function inserts a map that maps the opaque type to that proxy inference var. |
| 1299 | fn make_tait_coercion_table<'b>(&mut self, tait_candidates: impl Iterator<Item = &'b Ty>) { | |
| 1300 | struct TypeAliasImplTraitCollector<'a, 'b> { | |
| 1301 | db: &'b dyn HirDatabase, | |
| 1302 | table: &'b mut InferenceTable<'a>, | |
| 1303 | assocs: FxHashMap<OpaqueTyId, (ImplId, Ty)>, | |
| 1304 | non_assocs: FxHashMap<OpaqueTyId, Ty>, | |
| 1320 | fn make_tait_coercion_table(&mut self, tait_candidates: impl Iterator<Item = Ty<'db>>) { | |
| 1321 | struct TypeAliasImplTraitCollector<'a, 'db> { | |
| 1322 | db: &'a dyn HirDatabase, | |
| 1323 | table: &'a mut InferenceTable<'db>, | |
| 1324 | assocs: FxHashMap<InternedOpaqueTyId, (ImplId, Ty<'db>)>, | |
| 1325 | non_assocs: FxHashMap<InternedOpaqueTyId, Ty<'db>>, | |
| 1305 | 1326 | } |
| 1306 | 1327 | |
| 1307 | impl TypeVisitor<Interner> for TypeAliasImplTraitCollector<'_, '_> { | |
| 1308 | type BreakTy = (); | |
| 1309 | ||
| 1310 | fn as_dyn(&mut self) -> &mut dyn TypeVisitor<Interner, BreakTy = Self::BreakTy> { | |
| 1311 | self | |
| 1312 | } | |
| 1313 | ||
| 1314 | fn interner(&self) -> Interner { | |
| 1315 | Interner | |
| 1316 | } | |
| 1328 | impl<'db> TypeVisitor<DbInterner<'db>> for TypeAliasImplTraitCollector<'_, 'db> { | |
| 1329 | type Result = (); | |
| 1317 | 1330 | |
| 1318 | fn visit_ty( | |
| 1319 | &mut self, | |
| 1320 | ty: &chalk_ir::Ty<Interner>, | |
| 1321 | outer_binder: DebruijnIndex, | |
| 1322 | ) -> std::ops::ControlFlow<Self::BreakTy> { | |
| 1323 | let ty = self.table.structurally_resolve_type(ty); | |
| 1331 | fn visit_ty(&mut self, ty: Ty<'db>) { | |
| 1332 | let ty = self.table.try_structurally_resolve_type(ty); | |
| 1324 | 1333 | |
| 1325 | if let TyKind::OpaqueType(id, _) | |
| 1326 | | TyKind::Alias(AliasTy::Opaque(crate::OpaqueTy { opaque_ty_id: id, .. })) = | |
| 1327 | ty.kind(Interner) | |
| 1334 | if let TyKind::Alias(AliasTyKind::Opaque, alias_ty) = ty.kind() | |
| 1335 | && let id = alias_ty.def_id.expect_opaque_ty() | |
| 1328 | 1336 | && let ImplTraitId::TypeAliasImplTrait(alias_id, _) = |
| 1329 | self.db.lookup_intern_impl_trait_id((*id).into()) | |
| 1337 | self.db.lookup_intern_impl_trait_id(id) | |
| 1330 | 1338 | { |
| 1331 | 1339 | let loc = self.db.lookup_intern_type_alias(alias_id); |
| 1332 | 1340 | match loc.container { |
| 1333 | 1341 | ItemContainerId::ImplId(impl_id) => { |
| 1334 | self.assocs.insert(*id, (impl_id, ty.clone())); | |
| 1342 | self.assocs.insert(id, (impl_id, ty)); | |
| 1335 | 1343 | } |
| 1336 | 1344 | ItemContainerId::ModuleId(..) | ItemContainerId::ExternBlockId(..) => { |
| 1337 | self.non_assocs.insert(*id, ty.clone()); | |
| 1345 | self.non_assocs.insert(id, ty); | |
| 1338 | 1346 | } |
| 1339 | 1347 | _ => {} |
| 1340 | 1348 | } |
| 1341 | 1349 | } |
| 1342 | 1350 | |
| 1343 | ty.super_visit_with(self, outer_binder) | |
| 1351 | ty.super_visit_with(self) | |
| 1344 | 1352 | } |
| 1345 | 1353 | } |
| 1346 | 1354 | |
| ... | ... | @@ -1351,7 +1359,7 @@ impl<'db> InferenceContext<'db> { |
| 1351 | 1359 | non_assocs: FxHashMap::default(), |
| 1352 | 1360 | }; |
| 1353 | 1361 | for ty in tait_candidates { |
| 1354 | _ = ty.visit_with(collector.as_dyn(), DebruijnIndex::INNERMOST); | |
| 1362 | ty.visit_with(&mut collector); | |
| 1355 | 1363 | } |
| 1356 | 1364 | |
| 1357 | 1365 | // Non-assoc TAITs can be define-used everywhere as long as they are |
| ... | ... | @@ -1405,13 +1413,10 @@ impl<'db> InferenceContext<'db> { |
| 1405 | 1413 | let tait_coercion_table: FxHashMap<_, _> = taits |
| 1406 | 1414 | .into_iter() |
| 1407 | 1415 | .filter_map(|(id, ty)| { |
| 1408 | if let ImplTraitId::TypeAliasImplTrait(alias_id, _) = | |
| 1409 | self.db.lookup_intern_impl_trait_id(id.into()) | |
| 1416 | if let ImplTraitId::TypeAliasImplTrait(..) = self.db.lookup_intern_impl_trait_id(id) | |
| 1410 | 1417 | { |
| 1411 | let subst = TyBuilder::placeholder_subst(self.db, alias_id); | |
| 1412 | 1418 | let ty = self.insert_inference_vars_for_impl_trait( |
| 1413 | 1419 | ty, |
| 1414 | subst, | |
| 1415 | 1420 | &mut ImplTraitReplacingMode::TypeAlias, |
| 1416 | 1421 | ); |
| 1417 | 1422 | Some((id, ty)) |
| ... | ... | @@ -1432,18 +1437,18 @@ impl<'db> InferenceContext<'db> { |
| 1432 | 1437 | None => { |
| 1433 | 1438 | _ = self.infer_expr_coerce( |
| 1434 | 1439 | self.body.body_expr, |
| 1435 | &Expectation::has_type(self.return_ty.clone()), | |
| 1440 | &Expectation::has_type(self.return_ty), | |
| 1436 | 1441 | ExprIsRead::Yes, |
| 1437 | 1442 | ) |
| 1438 | 1443 | } |
| 1439 | 1444 | } |
| 1440 | 1445 | } |
| 1441 | 1446 | |
| 1442 | fn write_expr_ty(&mut self, expr: ExprId, ty: Ty) { | |
| 1447 | fn write_expr_ty(&mut self, expr: ExprId, ty: Ty<'db>) { | |
| 1443 | 1448 | self.result.type_of_expr.insert(expr, ty); |
| 1444 | 1449 | } |
| 1445 | 1450 | |
| 1446 | fn write_expr_adj(&mut self, expr: ExprId, adjustments: Box<[Adjustment]>) { | |
| 1451 | fn write_expr_adj(&mut self, expr: ExprId, adjustments: Box<[Adjustment<'db>]>) { | |
| 1447 | 1452 | if adjustments.is_empty() { |
| 1448 | 1453 | return; |
| 1449 | 1454 | } |
| ... | ... | @@ -1456,7 +1461,7 @@ impl<'db> InferenceContext<'db> { |
| 1456 | 1461 | ) => { |
| 1457 | 1462 | // NeverToAny coercion can target any type, so instead of adding a new |
| 1458 | 1463 | // adjustment on top we can change the target. |
| 1459 | *target = new_target.clone(); | |
| 1464 | *target = *new_target; | |
| 1460 | 1465 | } |
| 1461 | 1466 | _ => { |
| 1462 | 1467 | *entry.get_mut() = adjustments; |
| ... | ... | @@ -1469,14 +1474,14 @@ impl<'db> InferenceContext<'db> { |
| 1469 | 1474 | } |
| 1470 | 1475 | } |
| 1471 | 1476 | |
| 1472 | fn write_pat_adj(&mut self, pat: PatId, adjustments: Box<[Ty]>) { | |
| 1477 | fn write_pat_adj(&mut self, pat: PatId, adjustments: Box<[Ty<'db>]>) { | |
| 1473 | 1478 | if adjustments.is_empty() { |
| 1474 | 1479 | return; |
| 1475 | 1480 | } |
| 1476 | 1481 | self.result.pat_adjustments.entry(pat).or_default().extend(adjustments); |
| 1477 | 1482 | } |
| 1478 | 1483 | |
| 1479 | fn write_method_resolution(&mut self, expr: ExprId, func: FunctionId, subst: Substitution) { | |
| 1484 | fn write_method_resolution(&mut self, expr: ExprId, func: FunctionId, subst: GenericArgs<'db>) { | |
| 1480 | 1485 | self.result.method_resolutions.insert(expr, (func, subst)); |
| 1481 | 1486 | } |
| 1482 | 1487 | |
| ... | ... | @@ -1484,19 +1489,24 @@ impl<'db> InferenceContext<'db> { |
| 1484 | 1489 | self.result.variant_resolutions.insert(id, variant); |
| 1485 | 1490 | } |
| 1486 | 1491 | |
| 1487 | fn write_assoc_resolution(&mut self, id: ExprOrPatId, item: AssocItemId, subs: Substitution) { | |
| 1492 | fn write_assoc_resolution( | |
| 1493 | &mut self, | |
| 1494 | id: ExprOrPatId, | |
| 1495 | item: AssocItemId, | |
| 1496 | subs: GenericArgs<'db>, | |
| 1497 | ) { | |
| 1488 | 1498 | self.result.assoc_resolutions.insert(id, (item, subs)); |
| 1489 | 1499 | } |
| 1490 | 1500 | |
| 1491 | fn write_pat_ty(&mut self, pat: PatId, ty: Ty) { | |
| 1501 | fn write_pat_ty(&mut self, pat: PatId, ty: Ty<'db>) { | |
| 1492 | 1502 | self.result.type_of_pat.insert(pat, ty); |
| 1493 | 1503 | } |
| 1494 | 1504 | |
| 1495 | fn write_binding_ty(&mut self, id: BindingId, ty: Ty) { | |
| 1505 | fn write_binding_ty(&mut self, id: BindingId, ty: Ty<'db>) { | |
| 1496 | 1506 | self.result.type_of_binding.insert(id, ty); |
| 1497 | 1507 | } |
| 1498 | 1508 | |
| 1499 | fn push_diagnostic(&self, diagnostic: InferenceDiagnostic) { | |
| 1509 | fn push_diagnostic(&self, diagnostic: InferenceDiagnostic<'db>) { | |
| 1500 | 1510 | self.diagnostics.push(diagnostic); |
| 1501 | 1511 | } |
| 1502 | 1512 | |
| ... | ... | @@ -1504,8 +1514,8 @@ impl<'db> InferenceContext<'db> { |
| 1504 | 1514 | &mut self, |
| 1505 | 1515 | store: &ExpressionStore, |
| 1506 | 1516 | types_source: InferenceTyDiagnosticSource, |
| 1507 | lifetime_elision: LifetimeElisionKind, | |
| 1508 | f: impl FnOnce(&mut TyLoweringContext<'_>) -> R, | |
| 1517 | lifetime_elision: LifetimeElisionKind<'db>, | |
| 1518 | f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> R, | |
| 1509 | 1519 | ) -> R { |
| 1510 | 1520 | let mut ctx = TyLoweringContext::new( |
| 1511 | 1521 | self.db, |
| ... | ... | @@ -1519,7 +1529,10 @@ impl<'db> InferenceContext<'db> { |
| 1519 | 1529 | f(&mut ctx) |
| 1520 | 1530 | } |
| 1521 | 1531 | |
| 1522 | fn with_body_ty_lowering<R>(&mut self, f: impl FnOnce(&mut TyLoweringContext<'_>) -> R) -> R { | |
| 1532 | fn with_body_ty_lowering<R>( | |
| 1533 | &mut self, | |
| 1534 | f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> R, | |
| 1535 | ) -> R { | |
| 1523 | 1536 | self.with_ty_lowering( |
| 1524 | 1537 | self.body, |
| 1525 | 1538 | InferenceTyDiagnosticSource::Body, |
| ... | ... | @@ -1533,14 +1546,14 @@ impl<'db> InferenceContext<'db> { |
| 1533 | 1546 | type_ref: TypeRefId, |
| 1534 | 1547 | store: &ExpressionStore, |
| 1535 | 1548 | type_source: InferenceTyDiagnosticSource, |
| 1536 | lifetime_elision: LifetimeElisionKind, | |
| 1537 | ) -> Ty { | |
| 1549 | lifetime_elision: LifetimeElisionKind<'db>, | |
| 1550 | ) -> Ty<'db> { | |
| 1538 | 1551 | let ty = self |
| 1539 | 1552 | .with_ty_lowering(store, type_source, lifetime_elision, |ctx| ctx.lower_ty(type_ref)); |
| 1540 | 1553 | self.process_user_written_ty(ty) |
| 1541 | 1554 | } |
| 1542 | 1555 | |
| 1543 | fn make_body_ty(&mut self, type_ref: TypeRefId) -> Ty { | |
| 1556 | fn make_body_ty(&mut self, type_ref: TypeRefId) -> Ty<'db> { | |
| 1544 | 1557 | self.make_ty( |
| 1545 | 1558 | type_ref, |
| 1546 | 1559 | self.body, |
| ... | ... | @@ -1549,37 +1562,31 @@ impl<'db> InferenceContext<'db> { |
| 1549 | 1562 | ) |
| 1550 | 1563 | } |
| 1551 | 1564 | |
| 1552 | fn make_body_const(&mut self, const_ref: ConstRef, ty: Ty) -> Const { | |
| 1565 | fn make_body_const(&mut self, const_ref: ConstRef, ty: Ty<'db>) -> Const<'db> { | |
| 1553 | 1566 | let const_ = self.with_ty_lowering( |
| 1554 | 1567 | self.body, |
| 1555 | 1568 | InferenceTyDiagnosticSource::Body, |
| 1556 | 1569 | LifetimeElisionKind::Infer, |
| 1557 | |ctx| { | |
| 1558 | ctx.type_param_mode = ParamLoweringMode::Placeholder; | |
| 1559 | ctx.lower_const(&const_ref, ty) | |
| 1560 | }, | |
| 1570 | |ctx| ctx.lower_const(const_ref, ty), | |
| 1561 | 1571 | ); |
| 1562 | 1572 | self.insert_type_vars(const_) |
| 1563 | 1573 | } |
| 1564 | 1574 | |
| 1565 | fn make_path_as_body_const(&mut self, path: &Path, ty: Ty) -> Const { | |
| 1575 | fn make_path_as_body_const(&mut self, path: &Path, ty: Ty<'db>) -> Const<'db> { | |
| 1566 | 1576 | let const_ = self.with_ty_lowering( |
| 1567 | 1577 | self.body, |
| 1568 | 1578 | InferenceTyDiagnosticSource::Body, |
| 1569 | 1579 | LifetimeElisionKind::Infer, |
| 1570 | |ctx| { | |
| 1571 | ctx.type_param_mode = ParamLoweringMode::Placeholder; | |
| 1572 | ctx.lower_path_as_const(path, ty) | |
| 1573 | }, | |
| 1580 | |ctx| ctx.lower_path_as_const(path, ty), | |
| 1574 | 1581 | ); |
| 1575 | 1582 | self.insert_type_vars(const_) |
| 1576 | 1583 | } |
| 1577 | 1584 | |
| 1578 | fn err_ty(&self) -> Ty { | |
| 1579 | self.result.standard_types.unknown.clone() | |
| 1585 | fn err_ty(&self) -> Ty<'db> { | |
| 1586 | self.types.error | |
| 1580 | 1587 | } |
| 1581 | 1588 | |
| 1582 | fn make_body_lifetime(&mut self, lifetime_ref: LifetimeRefId) -> Lifetime { | |
| 1589 | fn make_body_lifetime(&mut self, lifetime_ref: LifetimeRefId) -> Region<'db> { | |
| 1583 | 1590 | let lt = self.with_ty_lowering( |
| 1584 | 1591 | self.body, |
| 1585 | 1592 | InferenceTyDiagnosticSource::Body, |
| ... | ... | @@ -1590,44 +1597,25 @@ impl<'db> InferenceContext<'db> { |
| 1590 | 1597 | } |
| 1591 | 1598 | |
| 1592 | 1599 | /// Replaces `Ty::Error` by a new type var, so we can maybe still infer it. |
| 1593 | fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { | |
| 1600 | fn insert_type_vars_shallow(&mut self, ty: Ty<'db>) -> Ty<'db> { | |
| 1594 | 1601 | self.table.insert_type_vars_shallow(ty) |
| 1595 | 1602 | } |
| 1596 | 1603 | |
| 1597 | 1604 | fn insert_type_vars<T>(&mut self, ty: T) -> T |
| 1598 | 1605 | where |
| 1599 | T: HasInterner<Interner = Interner> + TypeFoldable<Interner>, | |
| 1606 | T: TypeFoldable<DbInterner<'db>>, | |
| 1600 | 1607 | { |
| 1601 | 1608 | self.table.insert_type_vars(ty) |
| 1602 | 1609 | } |
| 1603 | 1610 | |
| 1604 | fn push_obligation(&mut self, o: DomainGoal) { | |
| 1605 | let goal: crate::Goal = o.cast(Interner); | |
| 1606 | self.table.register_obligation(goal.to_nextsolver(self.table.interner)); | |
| 1607 | } | |
| 1608 | ||
| 1609 | fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { | |
| 1610 | let ty1 = ty1 | |
| 1611 | .clone() | |
| 1612 | .try_fold_with( | |
| 1613 | &mut UnevaluatedConstEvaluatorFolder { db: self.db }, | |
| 1614 | DebruijnIndex::INNERMOST, | |
| 1615 | ) | |
| 1616 | .unwrap(); | |
| 1617 | let ty2 = ty2 | |
| 1618 | .clone() | |
| 1619 | .try_fold_with( | |
| 1620 | &mut UnevaluatedConstEvaluatorFolder { db: self.db }, | |
| 1621 | DebruijnIndex::INNERMOST, | |
| 1622 | ) | |
| 1623 | .unwrap(); | |
| 1624 | self.table.unify(&ty1, &ty2) | |
| 1611 | fn unify(&mut self, ty1: Ty<'db>, ty2: Ty<'db>) -> bool { | |
| 1612 | self.table.unify(ty1, ty2) | |
| 1625 | 1613 | } |
| 1626 | 1614 | |
| 1627 | 1615 | /// Attempts to returns the deeply last field of nested structures, but |
| 1628 | 1616 | /// does not apply any normalization in its search. Returns the same type |
| 1629 | 1617 | /// if input `ty` is not a structure at all. |
| 1630 | fn struct_tail_without_normalization(&mut self, ty: Ty) -> Ty { | |
| 1618 | fn struct_tail_without_normalization(&mut self, ty: Ty<'db>) -> Ty<'db> { | |
| 1631 | 1619 | self.struct_tail_with_normalize(ty, identity) |
| 1632 | 1620 | } |
| 1633 | 1621 | |
| ... | ... | @@ -1640,37 +1628,34 @@ impl<'db> InferenceContext<'db> { |
| 1640 | 1628 | /// function to indicate no normalization should take place. |
| 1641 | 1629 | fn struct_tail_with_normalize( |
| 1642 | 1630 | &mut self, |
| 1643 | mut ty: Ty, | |
| 1644 | mut normalize: impl FnMut(Ty) -> Ty, | |
| 1645 | ) -> Ty { | |
| 1631 | mut ty: Ty<'db>, | |
| 1632 | mut normalize: impl FnMut(Ty<'db>) -> Ty<'db>, | |
| 1633 | ) -> Ty<'db> { | |
| 1646 | 1634 | // FIXME: fetch the limit properly |
| 1647 | 1635 | let recursion_limit = 10; |
| 1648 | 1636 | for iteration in 0.. { |
| 1649 | 1637 | if iteration > recursion_limit { |
| 1650 | 1638 | return self.err_ty(); |
| 1651 | 1639 | } |
| 1652 | match ty.kind(Interner) { | |
| 1653 | TyKind::Adt(chalk_ir::AdtId(hir_def::AdtId::StructId(struct_id)), substs) => { | |
| 1654 | match self.db.field_types((*struct_id).into()).values().next_back().cloned() { | |
| 1655 | Some(field) => { | |
| 1656 | ty = field.substitute(Interner, substs); | |
| 1640 | match ty.kind() { | |
| 1641 | TyKind::Adt(adt_def, substs) => match adt_def.def_id().0 { | |
| 1642 | AdtId::StructId(struct_id) => { | |
| 1643 | match self.db.field_types_ns(struct_id.into()).values().next_back().copied() | |
| 1644 | { | |
| 1645 | Some(field) => { | |
| 1646 | ty = field.instantiate(self.interner(), substs); | |
| 1647 | } | |
| 1648 | None => break, | |
| 1657 | 1649 | } |
| 1658 | None => break, | |
| 1659 | } | |
| 1660 | } | |
| 1661 | TyKind::Adt(..) => break, | |
| 1662 | TyKind::Tuple(_, substs) => { | |
| 1663 | match substs | |
| 1664 | .as_slice(Interner) | |
| 1665 | .split_last() | |
| 1666 | .and_then(|(last_ty, _)| last_ty.ty(Interner)) | |
| 1667 | { | |
| 1668 | Some(last_ty) => ty = last_ty.clone(), | |
| 1669 | None => break, | |
| 1670 | 1650 | } |
| 1671 | } | |
| 1651 | _ => break, | |
| 1652 | }, | |
| 1653 | TyKind::Tuple(substs) => match substs.as_slice().split_last() { | |
| 1654 | Some((last_ty, _)) => ty = *last_ty, | |
| 1655 | None => break, | |
| 1656 | }, | |
| 1672 | 1657 | TyKind::Alias(..) => { |
| 1673 | let normalized = normalize(ty.clone()); | |
| 1658 | let normalized = normalize(ty); | |
| 1674 | 1659 | if ty == normalized { |
| 1675 | 1660 | return ty; |
| 1676 | 1661 | } else { |
| ... | ... | @@ -1684,41 +1669,35 @@ impl<'db> InferenceContext<'db> { |
| 1684 | 1669 | } |
| 1685 | 1670 | |
| 1686 | 1671 | /// Whenever you lower a user-written type, you should call this. |
| 1687 | fn process_user_written_ty<T, U>(&mut self, ty: T) -> T | |
| 1672 | fn process_user_written_ty<T>(&mut self, ty: T) -> T | |
| 1688 | 1673 | where |
| 1689 | T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + ChalkToNextSolver<'db, U>, | |
| 1690 | U: NextSolverToChalk<'db, T> + rustc_type_ir::TypeFoldable<DbInterner<'db>>, | |
| 1674 | T: TypeFoldable<DbInterner<'db>>, | |
| 1691 | 1675 | { |
| 1692 | 1676 | self.table.process_user_written_ty(ty) |
| 1693 | 1677 | } |
| 1694 | 1678 | |
| 1695 | 1679 | /// The difference of this method from `process_user_written_ty()` is that this method doesn't register a well-formed obligation, |
| 1696 | 1680 | /// while `process_user_written_ty()` should (but doesn't currently). |
| 1697 | fn process_remote_user_written_ty<T, U>(&mut self, ty: T) -> T | |
| 1681 | fn process_remote_user_written_ty<T>(&mut self, ty: T) -> T | |
| 1698 | 1682 | where |
| 1699 | T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + ChalkToNextSolver<'db, U>, | |
| 1700 | U: NextSolverToChalk<'db, T> + rustc_type_ir::TypeFoldable<DbInterner<'db>>, | |
| 1683 | T: TypeFoldable<DbInterner<'db>>, | |
| 1701 | 1684 | { |
| 1702 | 1685 | self.table.process_remote_user_written_ty(ty) |
| 1703 | 1686 | } |
| 1704 | 1687 | |
| 1705 | fn resolve_ty_shallow(&mut self, ty: &Ty) -> Ty { | |
| 1706 | self.table.resolve_ty_shallow(ty) | |
| 1707 | } | |
| 1708 | ||
| 1709 | fn shallow_resolve(&self, ty: crate::next_solver::Ty<'db>) -> crate::next_solver::Ty<'db> { | |
| 1688 | fn shallow_resolve(&self, ty: Ty<'db>) -> Ty<'db> { | |
| 1710 | 1689 | self.table.shallow_resolve(ty) |
| 1711 | 1690 | } |
| 1712 | 1691 | |
| 1713 | fn resolve_associated_type(&mut self, inner_ty: Ty, assoc_ty: Option<TypeAliasId>) -> Ty { | |
| 1692 | fn resolve_associated_type( | |
| 1693 | &mut self, | |
| 1694 | inner_ty: Ty<'db>, | |
| 1695 | assoc_ty: Option<TypeAliasId>, | |
| 1696 | ) -> Ty<'db> { | |
| 1714 | 1697 | self.resolve_associated_type_with_params(inner_ty, assoc_ty, &[]) |
| 1715 | 1698 | } |
| 1716 | 1699 | |
| 1717 | fn demand_eqtype( | |
| 1718 | &mut self, | |
| 1719 | expected: crate::next_solver::Ty<'db>, | |
| 1720 | actual: crate::next_solver::Ty<'db>, | |
| 1721 | ) { | |
| 1700 | fn demand_eqtype(&mut self, expected: Ty<'db>, actual: Ty<'db>) { | |
| 1722 | 1701 | let result = self |
| 1723 | 1702 | .table |
| 1724 | 1703 | .infer_ctxt |
| ... | ... | @@ -1732,34 +1711,24 @@ impl<'db> InferenceContext<'db> { |
| 1732 | 1711 | |
| 1733 | 1712 | fn resolve_associated_type_with_params( |
| 1734 | 1713 | &mut self, |
| 1735 | inner_ty: Ty, | |
| 1714 | inner_ty: Ty<'db>, | |
| 1736 | 1715 | assoc_ty: Option<TypeAliasId>, |
| 1737 | 1716 | // FIXME(GATs): these are args for the trait ref, args for assoc type itself should be |
| 1738 | 1717 | // handled when we support them. |
| 1739 | params: &[GenericArg], | |
| 1740 | ) -> Ty { | |
| 1718 | params: &[GenericArg<'db>], | |
| 1719 | ) -> Ty<'db> { | |
| 1741 | 1720 | match assoc_ty { |
| 1742 | 1721 | Some(res_assoc_ty) => { |
| 1743 | let trait_ = match res_assoc_ty.lookup(self.db).container { | |
| 1744 | hir_def::ItemContainerId::TraitId(trait_) => trait_, | |
| 1745 | _ => panic!("resolve_associated_type called with non-associated type"), | |
| 1746 | }; | |
| 1747 | let ty = self.table.new_type_var(); | |
| 1748 | let mut param_iter = params.iter().cloned(); | |
| 1749 | let trait_ref = TyBuilder::trait_ref(self.db, trait_) | |
| 1750 | .push(inner_ty) | |
| 1751 | .fill(|_| param_iter.next().unwrap()) | |
| 1752 | .build(); | |
| 1753 | let alias_eq = AliasEq { | |
| 1754 | alias: AliasTy::Projection(ProjectionTy { | |
| 1755 | associated_ty_id: to_assoc_type_id(res_assoc_ty), | |
| 1756 | substitution: trait_ref.substitution.clone(), | |
| 1757 | }), | |
| 1758 | ty: ty.clone(), | |
| 1759 | }; | |
| 1760 | self.push_obligation(trait_ref.cast(Interner)); | |
| 1761 | self.push_obligation(alias_eq.cast(Interner)); | |
| 1762 | ty | |
| 1722 | let alias = Ty::new_alias( | |
| 1723 | self.interner(), | |
| 1724 | AliasTyKind::Projection, | |
| 1725 | AliasTy::new( | |
| 1726 | self.interner(), | |
| 1727 | res_assoc_ty.into(), | |
| 1728 | iter::once(inner_ty.into()).chain(params.iter().copied()), | |
| 1729 | ), | |
| 1730 | ); | |
| 1731 | self.table.try_structurally_resolve_type(alias) | |
| 1763 | 1732 | } |
| 1764 | 1733 | None => self.err_ty(), |
| 1765 | 1734 | } |
| ... | ... | @@ -1770,7 +1739,7 @@ impl<'db> InferenceContext<'db> { |
| 1770 | 1739 | node: ExprOrPatId, |
| 1771 | 1740 | path: Option<&Path>, |
| 1772 | 1741 | value_ns: bool, |
| 1773 | ) -> (Ty, Option<VariantId>) { | |
| 1742 | ) -> (Ty<'db>, Option<VariantId>) { | |
| 1774 | 1743 | let path = match path { |
| 1775 | 1744 | Some(path) => path, |
| 1776 | 1745 | None => return (self.err_ty(), None), |
| ... | ... | @@ -1793,28 +1762,19 @@ impl<'db> InferenceContext<'db> { |
| 1793 | 1762 | match res { |
| 1794 | 1763 | ResolveValueResult::ValueNs(value, _) => match value { |
| 1795 | 1764 | ValueNs::EnumVariantId(var) => { |
| 1796 | let substs = path_ctx.substs_from_path(var.into(), true, false); | |
| 1765 | let args = path_ctx.substs_from_path(var.into(), true, false); | |
| 1797 | 1766 | drop(ctx); |
| 1798 | let args: crate::next_solver::GenericArgs<'_> = | |
| 1799 | substs.to_nextsolver(interner); | |
| 1800 | 1767 | let ty = self |
| 1801 | 1768 | .db |
| 1802 | 1769 | .ty(var.lookup(self.db).parent.into()) |
| 1803 | .instantiate(interner, args) | |
| 1804 | .to_chalk(interner); | |
| 1770 | .instantiate(interner, args); | |
| 1805 | 1771 | let ty = self.insert_type_vars(ty); |
| 1806 | 1772 | return (ty, Some(var.into())); |
| 1807 | 1773 | } |
| 1808 | 1774 | ValueNs::StructId(strukt) => { |
| 1809 | let substs = path_ctx.substs_from_path(strukt.into(), true, false); | |
| 1775 | let args = path_ctx.substs_from_path(strukt.into(), true, false); | |
| 1810 | 1776 | drop(ctx); |
| 1811 | let args: crate::next_solver::GenericArgs<'_> = | |
| 1812 | substs.to_nextsolver(interner); | |
| 1813 | let ty = self | |
| 1814 | .db | |
| 1815 | .ty(strukt.into()) | |
| 1816 | .instantiate(interner, args) | |
| 1817 | .to_chalk(interner); | |
| 1777 | let ty = self.db.ty(strukt.into()).instantiate(interner, args); | |
| 1818 | 1778 | let ty = self.insert_type_vars(ty); |
| 1819 | 1779 | return (ty, Some(strukt.into())); |
| 1820 | 1780 | } |
| ... | ... | @@ -1834,39 +1794,28 @@ impl<'db> InferenceContext<'db> { |
| 1834 | 1794 | }; |
| 1835 | 1795 | return match resolution { |
| 1836 | 1796 | TypeNs::AdtId(AdtId::StructId(strukt)) => { |
| 1837 | let substs = path_ctx.substs_from_path(strukt.into(), true, false); | |
| 1797 | let args = path_ctx.substs_from_path(strukt.into(), true, false); | |
| 1838 | 1798 | drop(ctx); |
| 1839 | let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 1840 | let ty = self.db.ty(strukt.into()).instantiate(interner, args).to_chalk(interner); | |
| 1799 | let ty = self.db.ty(strukt.into()).instantiate(interner, args); | |
| 1841 | 1800 | let ty = self.insert_type_vars(ty); |
| 1842 | forbid_unresolved_segments((ty, Some(strukt.into())), unresolved) | |
| 1801 | forbid_unresolved_segments(self, (ty, Some(strukt.into())), unresolved) | |
| 1843 | 1802 | } |
| 1844 | 1803 | TypeNs::AdtId(AdtId::UnionId(u)) => { |
| 1845 | let substs = path_ctx.substs_from_path(u.into(), true, false); | |
| 1804 | let args = path_ctx.substs_from_path(u.into(), true, false); | |
| 1846 | 1805 | drop(ctx); |
| 1847 | let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 1848 | let ty = self.db.ty(u.into()).instantiate(interner, args).to_chalk(interner); | |
| 1806 | let ty = self.db.ty(u.into()).instantiate(interner, args); | |
| 1849 | 1807 | let ty = self.insert_type_vars(ty); |
| 1850 | forbid_unresolved_segments((ty, Some(u.into())), unresolved) | |
| 1808 | forbid_unresolved_segments(self, (ty, Some(u.into())), unresolved) | |
| 1851 | 1809 | } |
| 1852 | 1810 | TypeNs::EnumVariantId(var) => { |
| 1853 | let substs = path_ctx.substs_from_path(var.into(), true, false); | |
| 1811 | let args = path_ctx.substs_from_path(var.into(), true, false); | |
| 1854 | 1812 | drop(ctx); |
| 1855 | let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 1856 | let ty = self | |
| 1857 | .db | |
| 1858 | .ty(var.lookup(self.db).parent.into()) | |
| 1859 | .instantiate(interner, args) | |
| 1860 | .to_chalk(interner); | |
| 1813 | let ty = self.db.ty(var.lookup(self.db).parent.into()).instantiate(interner, args); | |
| 1861 | 1814 | let ty = self.insert_type_vars(ty); |
| 1862 | forbid_unresolved_segments((ty, Some(var.into())), unresolved) | |
| 1815 | forbid_unresolved_segments(self, (ty, Some(var.into())), unresolved) | |
| 1863 | 1816 | } |
| 1864 | 1817 | TypeNs::SelfType(impl_id) => { |
| 1865 | let generics = crate::generics::generics(self.db, impl_id.into()); | |
| 1866 | let substs = generics.placeholder_subst(self.db); | |
| 1867 | let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 1868 | let mut ty = | |
| 1869 | self.db.impl_self_ty(impl_id).instantiate(interner, args).to_chalk(interner); | |
| 1818 | let mut ty = self.db.impl_self_ty(impl_id).instantiate_identity(); | |
| 1870 | 1819 | |
| 1871 | 1820 | let Some(remaining_idx) = unresolved else { |
| 1872 | 1821 | drop(ctx); |
| ... | ... | @@ -1889,7 +1838,9 @@ impl<'db> InferenceContext<'db> { |
| 1889 | 1838 | while let Some(current_segment) = remaining_segments.first() { |
| 1890 | 1839 | // If we can resolve to an enum variant, it takes priority over associated type |
| 1891 | 1840 | // of the same name. |
| 1892 | if let Some((AdtId::EnumId(id), _)) = ty.as_adt() { | |
| 1841 | if let TyKind::Adt(adt_def, _) = ty.kind() | |
| 1842 | && let AdtId::EnumId(id) = adt_def.def_id().0 | |
| 1843 | { | |
| 1893 | 1844 | let enum_data = id.enum_variants(self.db); |
| 1894 | 1845 | if let Some(variant) = enum_data.variant(current_segment.name) { |
| 1895 | 1846 | return if remaining_segments.len() == 1 { |
| ... | ... | @@ -1917,8 +1868,8 @@ impl<'db> InferenceContext<'db> { |
| 1917 | 1868 | |
| 1918 | 1869 | ty = self.table.insert_type_vars(ty); |
| 1919 | 1870 | ty = self.table.normalize_associated_types_in(ty); |
| 1920 | ty = self.table.structurally_resolve_type(&ty); | |
| 1921 | if ty.is_unknown() { | |
| 1871 | ty = self.table.structurally_resolve_type(ty); | |
| 1872 | if ty.is_ty_error() { | |
| 1922 | 1873 | return (self.err_ty(), None); |
| 1923 | 1874 | } |
| 1924 | 1875 | |
| ... | ... | @@ -1941,11 +1892,10 @@ impl<'db> InferenceContext<'db> { |
| 1941 | 1892 | never!("resolver should always resolve lang item paths"); |
| 1942 | 1893 | return (self.err_ty(), None); |
| 1943 | 1894 | }; |
| 1944 | let substs = path_ctx.substs_from_path_segment(it.into(), true, None, false); | |
| 1895 | let args = path_ctx.substs_from_path_segment(it.into(), true, None, false); | |
| 1945 | 1896 | drop(ctx); |
| 1946 | 1897 | let interner = DbInterner::conjure(); |
| 1947 | let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 1948 | let ty = self.db.ty(it.into()).instantiate(interner, args).to_chalk(interner); | |
| 1898 | let ty = self.db.ty(it.into()).instantiate(interner, args); | |
| 1949 | 1899 | let ty = self.insert_type_vars(ty); |
| 1950 | 1900 | |
| 1951 | 1901 | self.resolve_variant_on_alias(ty, unresolved, mod_path) |
| ... | ... | @@ -1967,33 +1917,28 @@ impl<'db> InferenceContext<'db> { |
| 1967 | 1917 | } |
| 1968 | 1918 | }; |
| 1969 | 1919 | |
| 1970 | fn forbid_unresolved_segments( | |
| 1971 | result: (Ty, Option<VariantId>), | |
| 1920 | fn forbid_unresolved_segments<'db>( | |
| 1921 | ctx: &InferenceContext<'_, 'db>, | |
| 1922 | result: (Ty<'db>, Option<VariantId>), | |
| 1972 | 1923 | unresolved: Option<usize>, |
| 1973 | ) -> (Ty, Option<VariantId>) { | |
| 1924 | ) -> (Ty<'db>, Option<VariantId>) { | |
| 1974 | 1925 | if unresolved.is_none() { |
| 1975 | 1926 | result |
| 1976 | 1927 | } else { |
| 1977 | 1928 | // FIXME diagnostic |
| 1978 | (TyKind::Error.intern(Interner), None) | |
| 1929 | (ctx.types.error, None) | |
| 1979 | 1930 | } |
| 1980 | 1931 | } |
| 1981 | 1932 | } |
| 1982 | 1933 | |
| 1983 | 1934 | fn resolve_variant_on_alias( |
| 1984 | 1935 | &mut self, |
| 1985 | ty: Ty, | |
| 1936 | ty: Ty<'db>, | |
| 1986 | 1937 | unresolved: Option<usize>, |
| 1987 | 1938 | path: &ModPath, |
| 1988 | ) -> (Ty, Option<VariantId>) { | |
| 1939 | ) -> (Ty<'db>, Option<VariantId>) { | |
| 1989 | 1940 | let remaining = unresolved.map(|it| path.segments()[it..].len()).filter(|it| it > &0); |
| 1990 | let ty = match ty.kind(Interner) { | |
| 1991 | TyKind::Alias(AliasTy::Projection(proj_ty)) => { | |
| 1992 | let ty = self.table.normalize_projection_ty(proj_ty.clone()); | |
| 1993 | self.table.structurally_resolve_type(&ty) | |
| 1994 | } | |
| 1995 | _ => ty, | |
| 1996 | }; | |
| 1941 | let ty = self.table.try_structurally_resolve_type(ty); | |
| 1997 | 1942 | match remaining { |
| 1998 | 1943 | None => { |
| 1999 | 1944 | let variant = ty.as_adt().and_then(|(adt_id, _)| match adt_id { |
| ... | ... | @@ -2115,19 +2060,18 @@ impl<'db> InferenceContext<'db> { |
| 2115 | 2060 | /// When inferring an expression, we propagate downward whatever type hint we |
| 2116 | 2061 | /// are able in the form of an `Expectation`. |
| 2117 | 2062 | #[derive(Clone, PartialEq, Eq, Debug)] |
| 2118 | pub(crate) enum Expectation { | |
| 2063 | pub(crate) enum Expectation<'db> { | |
| 2119 | 2064 | None, |
| 2120 | HasType(Ty), | |
| 2121 | #[allow(dead_code)] | |
| 2122 | Castable(Ty), | |
| 2123 | RValueLikeUnsized(Ty), | |
| 2065 | HasType(Ty<'db>), | |
| 2066 | Castable(Ty<'db>), | |
| 2067 | RValueLikeUnsized(Ty<'db>), | |
| 2124 | 2068 | } |
| 2125 | 2069 | |
| 2126 | impl Expectation { | |
| 2070 | impl<'db> Expectation<'db> { | |
| 2127 | 2071 | /// The expectation that the type of the expression needs to equal the given |
| 2128 | 2072 | /// type. |
| 2129 | fn has_type(ty: Ty) -> Self { | |
| 2130 | if ty.is_unknown() { | |
| 2073 | fn has_type(ty: Ty<'db>) -> Self { | |
| 2074 | if ty.is_ty_error() { | |
| 2131 | 2075 | // FIXME: get rid of this? |
| 2132 | 2076 | Expectation::None |
| 2133 | 2077 | } else { |
| ... | ... | @@ -2155,9 +2099,11 @@ impl Expectation { |
| 2155 | 2099 | /// which still is useful, because it informs integer literals and the like. |
| 2156 | 2100 | /// See the test case `test/ui/coerce-expect-unsized.rs` and #20169 |
| 2157 | 2101 | /// for examples of where this comes up,. |
| 2158 | fn rvalue_hint(ctx: &mut InferenceContext<'_>, ty: Ty) -> Self { | |
| 2159 | match ctx.struct_tail_without_normalization(ty.clone()).kind(Interner) { | |
| 2160 | TyKind::Slice(_) | TyKind::Str | TyKind::Dyn(_) => Expectation::RValueLikeUnsized(ty), | |
| 2102 | fn rvalue_hint(ctx: &mut InferenceContext<'_, 'db>, ty: Ty<'db>) -> Self { | |
| 2103 | match ctx.struct_tail_without_normalization(ty).kind() { | |
| 2104 | TyKind::Slice(_) | TyKind::Str | TyKind::Dynamic(..) => { | |
| 2105 | Expectation::RValueLikeUnsized(ty) | |
| 2106 | } | |
| 2161 | 2107 | _ => Expectation::has_type(ty), |
| 2162 | 2108 | } |
| 2163 | 2109 | } |
| ... | ... | @@ -2167,18 +2113,18 @@ impl Expectation { |
| 2167 | 2113 | Expectation::None |
| 2168 | 2114 | } |
| 2169 | 2115 | |
| 2170 | fn resolve(&self, table: &mut unify::InferenceTable<'_>) -> Expectation { | |
| 2116 | fn resolve(&self, table: &mut unify::InferenceTable<'db>) -> Expectation<'db> { | |
| 2171 | 2117 | match self { |
| 2172 | 2118 | Expectation::None => Expectation::None, |
| 2173 | Expectation::HasType(t) => Expectation::HasType(table.resolve_ty_shallow(t)), | |
| 2174 | Expectation::Castable(t) => Expectation::Castable(table.resolve_ty_shallow(t)), | |
| 2119 | Expectation::HasType(t) => Expectation::HasType(table.shallow_resolve(*t)), | |
| 2120 | Expectation::Castable(t) => Expectation::Castable(table.shallow_resolve(*t)), | |
| 2175 | 2121 | Expectation::RValueLikeUnsized(t) => { |
| 2176 | Expectation::RValueLikeUnsized(table.resolve_ty_shallow(t)) | |
| 2122 | Expectation::RValueLikeUnsized(table.shallow_resolve(*t)) | |
| 2177 | 2123 | } |
| 2178 | 2124 | } |
| 2179 | 2125 | } |
| 2180 | 2126 | |
| 2181 | fn to_option(&self, table: &mut unify::InferenceTable<'_>) -> Option<Ty> { | |
| 2127 | fn to_option(&self, table: &mut unify::InferenceTable<'db>) -> Option<Ty<'db>> { | |
| 2182 | 2128 | match self.resolve(table) { |
| 2183 | 2129 | Expectation::None => None, |
| 2184 | 2130 | Expectation::HasType(t) |
| ... | ... | @@ -2187,17 +2133,17 @@ impl Expectation { |
| 2187 | 2133 | } |
| 2188 | 2134 | } |
| 2189 | 2135 | |
| 2190 | fn only_has_type(&self, table: &mut unify::InferenceTable<'_>) -> Option<Ty> { | |
| 2136 | fn only_has_type(&self, table: &mut unify::InferenceTable<'db>) -> Option<Ty<'db>> { | |
| 2191 | 2137 | match self { |
| 2192 | Expectation::HasType(t) => Some(table.resolve_ty_shallow(t)), | |
| 2138 | Expectation::HasType(t) => Some(table.shallow_resolve(*t)), | |
| 2193 | 2139 | Expectation::Castable(_) | Expectation::RValueLikeUnsized(_) | Expectation::None => { |
| 2194 | 2140 | None |
| 2195 | 2141 | } |
| 2196 | 2142 | } |
| 2197 | 2143 | } |
| 2198 | 2144 | |
| 2199 | fn coercion_target_type(&self, table: &mut unify::InferenceTable<'_>) -> Ty { | |
| 2200 | self.only_has_type(table).unwrap_or_else(|| table.new_type_var()) | |
| 2145 | fn coercion_target_type(&self, table: &mut unify::InferenceTable<'db>) -> Ty<'db> { | |
| 2146 | self.only_has_type(table).unwrap_or_else(|| table.next_ty_var()) | |
| 2201 | 2147 | } |
| 2202 | 2148 | |
| 2203 | 2149 | /// Comment copied from rustc: |
| ... | ... | @@ -2217,13 +2163,13 @@ impl Expectation { |
| 2217 | 2163 | /// an expected type. Otherwise, we might write parts of the type |
| 2218 | 2164 | /// when checking the 'then' block which are incompatible with the |
| 2219 | 2165 | /// 'else' branch. |
| 2220 | fn adjust_for_branches(&self, table: &mut unify::InferenceTable<'_>) -> Expectation { | |
| 2221 | match self { | |
| 2166 | fn adjust_for_branches(&self, table: &mut unify::InferenceTable<'db>) -> Expectation<'db> { | |
| 2167 | match *self { | |
| 2222 | 2168 | Expectation::HasType(ety) => { |
| 2223 | 2169 | let ety = table.structurally_resolve_type(ety); |
| 2224 | 2170 | if ety.is_ty_var() { Expectation::None } else { Expectation::HasType(ety) } |
| 2225 | 2171 | } |
| 2226 | Expectation::RValueLikeUnsized(ety) => Expectation::RValueLikeUnsized(ety.clone()), | |
| 2172 | Expectation::RValueLikeUnsized(ety) => Expectation::RValueLikeUnsized(ety), | |
| 2227 | 2173 | _ => Expectation::None, |
| 2228 | 2174 | } |
| 2229 | 2175 | } |
| ... | ... | @@ -2266,123 +2212,3 @@ impl std::ops::BitOrAssign for Diverges { |
| 2266 | 2212 | *self = *self | other; |
| 2267 | 2213 | } |
| 2268 | 2214 | } |
| 2269 | ||
| 2270 | /// A zipper that checks for unequal occurrences of `{unknown}` and unresolved projections | |
| 2271 | /// in the two types. Used to filter out mismatch diagnostics that only differ in | |
| 2272 | /// `{unknown}` and unresolved projections. These mismatches are usually not helpful. | |
| 2273 | /// As the cause is usually an underlying name resolution problem | |
| 2274 | struct UnknownMismatch<'db>(&'db dyn HirDatabase); | |
| 2275 | impl chalk_ir::zip::Zipper<Interner> for UnknownMismatch<'_> { | |
| 2276 | fn zip_tys(&mut self, variance: Variance, a: &Ty, b: &Ty) -> chalk_ir::Fallible<()> { | |
| 2277 | let zip_substs = |this: &mut Self, | |
| 2278 | variances, | |
| 2279 | sub_a: &Substitution, | |
| 2280 | sub_b: &Substitution| { | |
| 2281 | this.zip_substs(variance, variances, sub_a.as_slice(Interner), sub_b.as_slice(Interner)) | |
| 2282 | }; | |
| 2283 | match (a.kind(Interner), b.kind(Interner)) { | |
| 2284 | (TyKind::Adt(id_a, sub_a), TyKind::Adt(id_b, sub_b)) if id_a == id_b => zip_substs( | |
| 2285 | self, | |
| 2286 | Some(self.unification_database().adt_variance(*id_a)), | |
| 2287 | sub_a, | |
| 2288 | sub_b, | |
| 2289 | )?, | |
| 2290 | ( | |
| 2291 | TyKind::AssociatedType(assoc_ty_a, sub_a), | |
| 2292 | TyKind::AssociatedType(assoc_ty_b, sub_b), | |
| 2293 | ) if assoc_ty_a == assoc_ty_b => zip_substs(self, None, sub_a, sub_b)?, | |
| 2294 | (TyKind::Tuple(arity_a, sub_a), TyKind::Tuple(arity_b, sub_b)) | |
| 2295 | if arity_a == arity_b => | |
| 2296 | { | |
| 2297 | zip_substs(self, None, sub_a, sub_b)? | |
| 2298 | } | |
| 2299 | (TyKind::OpaqueType(opaque_ty_a, sub_a), TyKind::OpaqueType(opaque_ty_b, sub_b)) | |
| 2300 | if opaque_ty_a == opaque_ty_b => | |
| 2301 | { | |
| 2302 | zip_substs(self, None, sub_a, sub_b)? | |
| 2303 | } | |
| 2304 | (TyKind::Slice(ty_a), TyKind::Slice(ty_b)) => self.zip_tys(variance, ty_a, ty_b)?, | |
| 2305 | (TyKind::FnDef(fn_def_a, sub_a), TyKind::FnDef(fn_def_b, sub_b)) | |
| 2306 | if fn_def_a == fn_def_b => | |
| 2307 | { | |
| 2308 | zip_substs( | |
| 2309 | self, | |
| 2310 | Some(self.unification_database().fn_def_variance(*fn_def_a)), | |
| 2311 | sub_a, | |
| 2312 | sub_b, | |
| 2313 | )? | |
| 2314 | } | |
| 2315 | (TyKind::Ref(mutability_a, _, ty_a), TyKind::Ref(mutability_b, _, ty_b)) | |
| 2316 | if mutability_a == mutability_b => | |
| 2317 | { | |
| 2318 | self.zip_tys(variance, ty_a, ty_b)? | |
| 2319 | } | |
| 2320 | (TyKind::Raw(mutability_a, ty_a), TyKind::Raw(mutability_b, ty_b)) | |
| 2321 | if mutability_a == mutability_b => | |
| 2322 | { | |
| 2323 | self.zip_tys(variance, ty_a, ty_b)? | |
| 2324 | } | |
| 2325 | (TyKind::Array(ty_a, const_a), TyKind::Array(ty_b, const_b)) if const_a == const_b => { | |
| 2326 | self.zip_tys(variance, ty_a, ty_b)? | |
| 2327 | } | |
| 2328 | (TyKind::Closure(id_a, sub_a), TyKind::Closure(id_b, sub_b)) if id_a == id_b => { | |
| 2329 | zip_substs(self, None, sub_a, sub_b)? | |
| 2330 | } | |
| 2331 | (TyKind::Coroutine(coroutine_a, sub_a), TyKind::Coroutine(coroutine_b, sub_b)) | |
| 2332 | if coroutine_a == coroutine_b => | |
| 2333 | { | |
| 2334 | zip_substs(self, None, sub_a, sub_b)? | |
| 2335 | } | |
| 2336 | ( | |
| 2337 | TyKind::CoroutineWitness(coroutine_a, sub_a), | |
| 2338 | TyKind::CoroutineWitness(coroutine_b, sub_b), | |
| 2339 | ) if coroutine_a == coroutine_b => zip_substs(self, None, sub_a, sub_b)?, | |
| 2340 | (TyKind::Function(fn_ptr_a), TyKind::Function(fn_ptr_b)) | |
| 2341 | if fn_ptr_a.sig == fn_ptr_b.sig && fn_ptr_a.num_binders == fn_ptr_b.num_binders => | |
| 2342 | { | |
| 2343 | zip_substs(self, None, &fn_ptr_a.substitution.0, &fn_ptr_b.substitution.0)? | |
| 2344 | } | |
| 2345 | (TyKind::Error, TyKind::Error) => (), | |
| 2346 | (TyKind::Error, _) | |
| 2347 | | (_, TyKind::Error) | |
| 2348 | | (TyKind::Alias(AliasTy::Projection(_)) | TyKind::AssociatedType(_, _), _) | |
| 2349 | | (_, TyKind::Alias(AliasTy::Projection(_)) | TyKind::AssociatedType(_, _)) => { | |
| 2350 | return Err(chalk_ir::NoSolution); | |
| 2351 | } | |
| 2352 | _ => (), | |
| 2353 | } | |
| 2354 | ||
| 2355 | Ok(()) | |
| 2356 | } | |
| 2357 | ||
| 2358 | fn zip_lifetimes(&mut self, _: Variance, _: &Lifetime, _: &Lifetime) -> chalk_ir::Fallible<()> { | |
| 2359 | Ok(()) | |
| 2360 | } | |
| 2361 | ||
| 2362 | fn zip_consts(&mut self, _: Variance, _: &Const, _: &Const) -> chalk_ir::Fallible<()> { | |
| 2363 | Ok(()) | |
| 2364 | } | |
| 2365 | ||
| 2366 | fn zip_binders<T>( | |
| 2367 | &mut self, | |
| 2368 | variance: Variance, | |
| 2369 | a: &Binders<T>, | |
| 2370 | b: &Binders<T>, | |
| 2371 | ) -> chalk_ir::Fallible<()> | |
| 2372 | where | |
| 2373 | T: Clone | |
| 2374 | + HasInterner<Interner = Interner> | |
| 2375 | + chalk_ir::zip::Zip<Interner> | |
| 2376 | + TypeFoldable<Interner>, | |
| 2377 | { | |
| 2378 | chalk_ir::zip::Zip::zip_with(self, variance, a.skip_binders(), b.skip_binders()) | |
| 2379 | } | |
| 2380 | ||
| 2381 | fn interner(&self) -> Interner { | |
| 2382 | Interner | |
| 2383 | } | |
| 2384 | ||
| 2385 | fn unification_database(&self) -> &dyn chalk_ir::UnificationDatabase<Interner> { | |
| 2386 | &self.0 | |
| 2387 | } | |
| 2388 | } |
src/tools/rust-analyzer/crates/hir-ty/src/infer/autoderef.rs+6-8| ... | ... | @@ -2,6 +2,8 @@ |
| 2 | 2 | |
| 3 | 3 | use std::iter; |
| 4 | 4 | |
| 5 | use rustc_ast_ir::Mutability; | |
| 6 | ||
| 5 | 7 | use crate::{ |
| 6 | 8 | Adjust, Adjustment, OverloadedDeref, |
| 7 | 9 | autoderef::{Autoderef, AutoderefKind}, |
| ... | ... | @@ -9,7 +11,6 @@ use crate::{ |
| 9 | 11 | next_solver::{ |
| 10 | 12 | Ty, |
| 11 | 13 | infer::{InferOk, traits::PredicateObligations}, |
| 12 | mapping::NextSolverToChalk, | |
| 13 | 14 | }, |
| 14 | 15 | }; |
| 15 | 16 | |
| ... | ... | @@ -21,12 +22,12 @@ impl<'db> InferenceTable<'db> { |
| 21 | 22 | |
| 22 | 23 | impl<'db> Autoderef<'_, 'db> { |
| 23 | 24 | /// Returns the adjustment steps. |
| 24 | pub(crate) fn adjust_steps(mut self) -> Vec<Adjustment> { | |
| 25 | pub(crate) fn adjust_steps(mut self) -> Vec<Adjustment<'db>> { | |
| 25 | 26 | let infer_ok = self.adjust_steps_as_infer_ok(); |
| 26 | 27 | self.table.register_infer_ok(infer_ok) |
| 27 | 28 | } |
| 28 | 29 | |
| 29 | pub(crate) fn adjust_steps_as_infer_ok(&mut self) -> InferOk<'db, Vec<Adjustment>> { | |
| 30 | pub(crate) fn adjust_steps_as_infer_ok(&mut self) -> InferOk<'db, Vec<Adjustment<'db>>> { | |
| 30 | 31 | let steps = self.steps(); |
| 31 | 32 | if steps.is_empty() { |
| 32 | 33 | return InferOk { obligations: PredicateObligations::new(), value: vec![] }; |
| ... | ... | @@ -37,16 +38,13 @@ impl<'db> Autoderef<'_, 'db> { |
| 37 | 38 | .iter() |
| 38 | 39 | .map(|&(_source, kind)| { |
| 39 | 40 | if let AutoderefKind::Overloaded = kind { |
| 40 | Some(OverloadedDeref(Some(chalk_ir::Mutability::Not))) | |
| 41 | Some(OverloadedDeref(Some(Mutability::Not))) | |
| 41 | 42 | } else { |
| 42 | 43 | None |
| 43 | 44 | } |
| 44 | 45 | }) |
| 45 | 46 | .zip(targets) |
| 46 | .map(|(autoderef, target)| Adjustment { | |
| 47 | kind: Adjust::Deref(autoderef), | |
| 48 | target: target.to_chalk(self.table.interner), | |
| 49 | }) | |
| 47 | .map(|(autoderef, target)| Adjustment { kind: Adjust::Deref(autoderef), target }) | |
| 50 | 48 | .collect(); |
| 51 | 49 | |
| 52 | 50 | InferOk { obligations: self.take_obligations(), value: steps } |
src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs+169-178| ... | ... | @@ -1,17 +1,18 @@ |
| 1 | 1 | //! Type cast logic. Basically coercion + additional casts. |
| 2 | 2 | |
| 3 | use chalk_ir::{Mutability, Scalar, TyVariableKind, UintTy}; | |
| 4 | 3 | use hir_def::{AdtId, hir::ExprId, signatures::TraitFlags}; |
| 4 | use rustc_ast_ir::Mutability; | |
| 5 | use rustc_type_ir::{ | |
| 6 | Flags, InferTy, TypeFlags, UintTy, | |
| 7 | inherent::{AdtDef, BoundExistentialPredicates as _, IntoKind, SliceLike, Ty as _}, | |
| 8 | }; | |
| 5 | 9 | use stdx::never; |
| 6 | 10 | |
| 7 | use crate::infer::coerce::CoerceNever; | |
| 8 | 11 | use crate::{ |
| 9 | Binders, DynTy, InferenceDiagnostic, Interner, PlaceholderIndex, QuantifiedWhereClauses, Ty, | |
| 10 | TyExt, TyKind, TypeFlags, WhereClause, | |
| 12 | InferenceDiagnostic, | |
| 11 | 13 | db::HirDatabase, |
| 12 | from_chalk_trait_id, | |
| 13 | infer::{AllowTwoPhase, InferenceContext}, | |
| 14 | next_solver::mapping::ChalkToNextSolver, | |
| 14 | infer::{AllowTwoPhase, InferenceContext, coerce::CoerceNever}, | |
| 15 | next_solver::{BoundExistentialPredicates, DbInterner, ParamTy, Ty, TyKind}, | |
| 15 | 16 | }; |
| 16 | 17 | |
| 17 | 18 | #[derive(Debug)] |
| ... | ... | @@ -25,24 +26,24 @@ pub(crate) enum Int { |
| 25 | 26 | } |
| 26 | 27 | |
| 27 | 28 | #[derive(Debug)] |
| 28 | pub(crate) enum CastTy { | |
| 29 | pub(crate) enum CastTy<'db> { | |
| 29 | 30 | Int(Int), |
| 30 | 31 | Float, |
| 31 | 32 | FnPtr, |
| 32 | Ptr(Ty, Mutability), | |
| 33 | Ptr(Ty<'db>, Mutability), | |
| 33 | 34 | // `DynStar` is Not supported yet in r-a |
| 34 | 35 | } |
| 35 | 36 | |
| 36 | impl CastTy { | |
| 37 | pub(crate) fn from_ty(db: &dyn HirDatabase, t: &Ty) -> Option<Self> { | |
| 38 | match t.kind(Interner) { | |
| 39 | TyKind::Scalar(Scalar::Bool) => Some(Self::Int(Int::Bool)), | |
| 40 | TyKind::Scalar(Scalar::Char) => Some(Self::Int(Int::Char)), | |
| 41 | TyKind::Scalar(Scalar::Int(_)) => Some(Self::Int(Int::I)), | |
| 42 | TyKind::Scalar(Scalar::Uint(it)) => Some(Self::Int(Int::U(*it))), | |
| 43 | TyKind::InferenceVar(_, TyVariableKind::Integer) => Some(Self::Int(Int::InferenceVar)), | |
| 44 | TyKind::InferenceVar(_, TyVariableKind::Float) => Some(Self::Float), | |
| 45 | TyKind::Scalar(Scalar::Float(_)) => Some(Self::Float), | |
| 37 | impl<'db> CastTy<'db> { | |
| 38 | pub(crate) fn from_ty(db: &dyn HirDatabase, t: Ty<'db>) -> Option<Self> { | |
| 39 | match t.kind() { | |
| 40 | TyKind::Bool => Some(Self::Int(Int::Bool)), | |
| 41 | TyKind::Char => Some(Self::Int(Int::Char)), | |
| 42 | TyKind::Int(_) => Some(Self::Int(Int::I)), | |
| 43 | TyKind::Uint(it) => Some(Self::Int(Int::U(it))), | |
| 44 | TyKind::Infer(InferTy::IntVar(_)) => Some(Self::Int(Int::InferenceVar)), | |
| 45 | TyKind::Infer(InferTy::FloatVar(_)) => Some(Self::Float), | |
| 46 | TyKind::Float(_) => Some(Self::Float), | |
| 46 | 47 | TyKind::Adt(..) => { |
| 47 | 48 | let (AdtId::EnumId(id), _) = t.as_adt()? else { |
| 48 | 49 | return None; |
| ... | ... | @@ -50,8 +51,8 @@ impl CastTy { |
| 50 | 51 | let enum_data = id.enum_variants(db); |
| 51 | 52 | if enum_data.is_payload_free(db) { Some(Self::Int(Int::CEnum)) } else { None } |
| 52 | 53 | } |
| 53 | TyKind::Raw(m, ty) => Some(Self::Ptr(ty.clone(), *m)), | |
| 54 | TyKind::Function(_) => Some(Self::FnPtr), | |
| 54 | TyKind::RawPtr(ty, m) => Some(Self::Ptr(ty, m)), | |
| 55 | TyKind::FnPtr(..) => Some(Self::FnPtr), | |
| 55 | 56 | _ => None, |
| 56 | 57 | } |
| 57 | 58 | } |
| ... | ... | @@ -77,37 +78,47 @@ pub enum CastError { |
| 77 | 78 | } |
| 78 | 79 | |
| 79 | 80 | impl CastError { |
| 80 | fn into_diagnostic(self, expr: ExprId, expr_ty: Ty, cast_ty: Ty) -> InferenceDiagnostic { | |
| 81 | fn into_diagnostic<'db>( | |
| 82 | self, | |
| 83 | expr: ExprId, | |
| 84 | expr_ty: Ty<'db>, | |
| 85 | cast_ty: Ty<'db>, | |
| 86 | ) -> InferenceDiagnostic<'db> { | |
| 81 | 87 | InferenceDiagnostic::InvalidCast { expr, error: self, expr_ty, cast_ty } |
| 82 | 88 | } |
| 83 | 89 | } |
| 84 | 90 | |
| 85 | 91 | #[derive(Clone, Debug)] |
| 86 | pub(super) struct CastCheck { | |
| 92 | pub(super) struct CastCheck<'db> { | |
| 87 | 93 | expr: ExprId, |
| 88 | 94 | source_expr: ExprId, |
| 89 | expr_ty: Ty, | |
| 90 | cast_ty: Ty, | |
| 95 | expr_ty: Ty<'db>, | |
| 96 | cast_ty: Ty<'db>, | |
| 91 | 97 | } |
| 92 | 98 | |
| 93 | impl CastCheck { | |
| 94 | pub(super) fn new(expr: ExprId, source_expr: ExprId, expr_ty: Ty, cast_ty: Ty) -> Self { | |
| 99 | impl<'db> CastCheck<'db> { | |
| 100 | pub(super) fn new( | |
| 101 | expr: ExprId, | |
| 102 | source_expr: ExprId, | |
| 103 | expr_ty: Ty<'db>, | |
| 104 | cast_ty: Ty<'db>, | |
| 105 | ) -> Self { | |
| 95 | 106 | Self { expr, source_expr, expr_ty, cast_ty } |
| 96 | 107 | } |
| 97 | 108 | |
| 98 | 109 | pub(super) fn check( |
| 99 | 110 | &mut self, |
| 100 | ctx: &mut InferenceContext<'_>, | |
| 101 | ) -> Result<(), InferenceDiagnostic> { | |
| 102 | self.expr_ty = ctx.table.eagerly_normalize_and_resolve_shallow_in(self.expr_ty.clone()); | |
| 103 | self.cast_ty = ctx.table.eagerly_normalize_and_resolve_shallow_in(self.cast_ty.clone()); | |
| 111 | ctx: &mut InferenceContext<'_, 'db>, | |
| 112 | ) -> Result<(), InferenceDiagnostic<'db>> { | |
| 113 | self.expr_ty = ctx.table.eagerly_normalize_and_resolve_shallow_in(self.expr_ty); | |
| 114 | self.cast_ty = ctx.table.eagerly_normalize_and_resolve_shallow_in(self.cast_ty); | |
| 104 | 115 | |
| 105 | 116 | // This should always come first so that we apply the coercion, which impacts infer vars. |
| 106 | 117 | if ctx |
| 107 | 118 | .coerce( |
| 108 | 119 | self.source_expr.into(), |
| 109 | self.expr_ty.to_nextsolver(ctx.table.interner), | |
| 110 | self.cast_ty.to_nextsolver(ctx.table.interner), | |
| 120 | self.expr_ty, | |
| 121 | self.cast_ty, | |
| 111 | 122 | AllowTwoPhase::No, |
| 112 | 123 | CoerceNever::Yes, |
| 113 | 124 | ) |
| ... | ... | @@ -117,83 +128,82 @@ impl CastCheck { |
| 117 | 128 | return Ok(()); |
| 118 | 129 | } |
| 119 | 130 | |
| 120 | if self.expr_ty.contains_unknown() || self.cast_ty.contains_unknown() { | |
| 131 | if self.expr_ty.references_non_lt_error() || self.cast_ty.references_non_lt_error() { | |
| 121 | 132 | return Ok(()); |
| 122 | 133 | } |
| 123 | 134 | |
| 124 | if !self.cast_ty.data(Interner).flags.contains(TypeFlags::HAS_TY_INFER) | |
| 125 | && !ctx.table.is_sized(&self.cast_ty) | |
| 135 | if !self.cast_ty.flags().contains(TypeFlags::HAS_TY_INFER) | |
| 136 | && !ctx.table.is_sized(self.cast_ty) | |
| 126 | 137 | { |
| 127 | 138 | return Err(InferenceDiagnostic::CastToUnsized { |
| 128 | 139 | expr: self.expr, |
| 129 | cast_ty: self.cast_ty.clone(), | |
| 140 | cast_ty: self.cast_ty, | |
| 130 | 141 | }); |
| 131 | 142 | } |
| 132 | 143 | |
| 133 | 144 | // Chalk doesn't support trait upcasting and fails to solve some obvious goals |
| 134 | 145 | // when the trait environment contains some recursive traits (See issue #18047) |
| 135 | 146 | // We skip cast checks for such cases for now, until the next-gen solver. |
| 136 | if contains_dyn_trait(&self.cast_ty) { | |
| 147 | if contains_dyn_trait(self.cast_ty) { | |
| 137 | 148 | return Ok(()); |
| 138 | 149 | } |
| 139 | 150 | |
| 140 | self.do_check(ctx) | |
| 141 | .map_err(|e| e.into_diagnostic(self.expr, self.expr_ty.clone(), self.cast_ty.clone())) | |
| 151 | self.do_check(ctx).map_err(|e| e.into_diagnostic(self.expr, self.expr_ty, self.cast_ty)) | |
| 142 | 152 | } |
| 143 | 153 | |
| 144 | fn do_check(&self, ctx: &mut InferenceContext<'_>) -> Result<(), CastError> { | |
| 145 | let (t_from, t_cast) = match ( | |
| 146 | CastTy::from_ty(ctx.db, &self.expr_ty), | |
| 147 | CastTy::from_ty(ctx.db, &self.cast_ty), | |
| 148 | ) { | |
| 149 | (Some(t_from), Some(t_cast)) => (t_from, t_cast), | |
| 150 | (None, Some(t_cast)) => match self.expr_ty.kind(Interner) { | |
| 151 | TyKind::FnDef(..) => { | |
| 152 | let sig = self.expr_ty.callable_sig(ctx.db).expect("FnDef had no sig"); | |
| 153 | let sig = ctx.table.eagerly_normalize_and_resolve_shallow_in(sig); | |
| 154 | let fn_ptr = TyKind::Function(sig.to_fn_ptr()).intern(Interner); | |
| 155 | if ctx | |
| 156 | .coerce( | |
| 157 | self.source_expr.into(), | |
| 158 | self.expr_ty.to_nextsolver(ctx.table.interner), | |
| 159 | fn_ptr.to_nextsolver(ctx.table.interner), | |
| 160 | AllowTwoPhase::No, | |
| 161 | CoerceNever::Yes, | |
| 162 | ) | |
| 163 | .is_ok() | |
| 164 | { | |
| 165 | } else { | |
| 166 | return Err(CastError::IllegalCast); | |
| 167 | } | |
| 154 | fn do_check(&self, ctx: &mut InferenceContext<'_, 'db>) -> Result<(), CastError> { | |
| 155 | let (t_from, t_cast) = | |
| 156 | match (CastTy::from_ty(ctx.db, self.expr_ty), CastTy::from_ty(ctx.db, self.cast_ty)) { | |
| 157 | (Some(t_from), Some(t_cast)) => (t_from, t_cast), | |
| 158 | (None, Some(t_cast)) => match self.expr_ty.kind() { | |
| 159 | TyKind::FnDef(..) => { | |
| 160 | let sig = | |
| 161 | self.expr_ty.callable_sig(ctx.interner()).expect("FnDef had no sig"); | |
| 162 | let sig = ctx.table.eagerly_normalize_and_resolve_shallow_in(sig); | |
| 163 | let fn_ptr = Ty::new_fn_ptr(ctx.interner(), sig); | |
| 164 | if ctx | |
| 165 | .coerce( | |
| 166 | self.source_expr.into(), | |
| 167 | self.expr_ty, | |
| 168 | fn_ptr, | |
| 169 | AllowTwoPhase::No, | |
| 170 | CoerceNever::Yes, | |
| 171 | ) | |
| 172 | .is_ok() | |
| 173 | { | |
| 174 | } else { | |
| 175 | return Err(CastError::IllegalCast); | |
| 176 | } | |
| 168 | 177 | |
| 169 | (CastTy::FnPtr, t_cast) | |
| 170 | } | |
| 171 | TyKind::Ref(mutbl, _, inner_ty) => { | |
| 172 | return match t_cast { | |
| 173 | CastTy::Int(_) | CastTy::Float => match inner_ty.kind(Interner) { | |
| 174 | TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_) | Scalar::Float(_)) | |
| 175 | | TyKind::InferenceVar( | |
| 176 | _, | |
| 177 | TyVariableKind::Integer | TyVariableKind::Float, | |
| 178 | ) => Err(CastError::NeedDeref), | |
| 179 | ||
| 180 | _ => Err(CastError::NeedViaPtr), | |
| 181 | }, | |
| 182 | // array-ptr-cast | |
| 183 | CastTy::Ptr(t, m) => { | |
| 184 | let t = ctx.table.eagerly_normalize_and_resolve_shallow_in(t); | |
| 185 | if !ctx.table.is_sized(&t) { | |
| 186 | return Err(CastError::IllegalCast); | |
| 178 | (CastTy::FnPtr, t_cast) | |
| 179 | } | |
| 180 | TyKind::Ref(_, inner_ty, mutbl) => { | |
| 181 | return match t_cast { | |
| 182 | CastTy::Int(_) | CastTy::Float => match inner_ty.kind() { | |
| 183 | TyKind::Int(_) | |
| 184 | | TyKind::Uint(_) | |
| 185 | | TyKind::Float(_) | |
| 186 | | TyKind::Infer(InferTy::IntVar(_) | InferTy::FloatVar(_)) => { | |
| 187 | Err(CastError::NeedDeref) | |
| 188 | } | |
| 189 | ||
| 190 | _ => Err(CastError::NeedViaPtr), | |
| 191 | }, | |
| 192 | // array-ptr-cast | |
| 193 | CastTy::Ptr(t, m) => { | |
| 194 | let t = ctx.table.eagerly_normalize_and_resolve_shallow_in(t); | |
| 195 | if !ctx.table.is_sized(t) { | |
| 196 | return Err(CastError::IllegalCast); | |
| 197 | } | |
| 198 | self.check_ref_cast(ctx, inner_ty, mutbl, t, m) | |
| 187 | 199 | } |
| 188 | self.check_ref_cast(ctx, inner_ty, *mutbl, &t, m) | |
| 189 | } | |
| 190 | _ => Err(CastError::NonScalar), | |
| 191 | }; | |
| 192 | } | |
| 200 | _ => Err(CastError::NonScalar), | |
| 201 | }; | |
| 202 | } | |
| 203 | _ => return Err(CastError::NonScalar), | |
| 204 | }, | |
| 193 | 205 | _ => return Err(CastError::NonScalar), |
| 194 | }, | |
| 195 | _ => return Err(CastError::NonScalar), | |
| 196 | }; | |
| 206 | }; | |
| 197 | 207 | |
| 198 | 208 | // rustc checks whether the `expr_ty` is foreign adt with `non_exhaustive` sym |
| 199 | 209 | |
| ... | ... | @@ -207,10 +217,10 @@ impl CastCheck { |
| 207 | 217 | } |
| 208 | 218 | (CastTy::Int(Int::Bool | Int::CEnum | Int::Char) | CastTy::Float, CastTy::Ptr(..)) |
| 209 | 219 | | (CastTy::Ptr(..) | CastTy::FnPtr, CastTy::Float) => Err(CastError::IllegalCast), |
| 210 | (CastTy::Ptr(src, _), CastTy::Ptr(dst, _)) => self.check_ptr_ptr_cast(ctx, &src, &dst), | |
| 211 | (CastTy::Ptr(src, _), CastTy::Int(_)) => self.check_ptr_addr_cast(ctx, &src), | |
| 212 | (CastTy::Int(_), CastTy::Ptr(dst, _)) => self.check_addr_ptr_cast(ctx, &dst), | |
| 213 | (CastTy::FnPtr, CastTy::Ptr(dst, _)) => self.check_fptr_ptr_cast(ctx, &dst), | |
| 220 | (CastTy::Ptr(src, _), CastTy::Ptr(dst, _)) => self.check_ptr_ptr_cast(ctx, src, dst), | |
| 221 | (CastTy::Ptr(src, _), CastTy::Int(_)) => self.check_ptr_addr_cast(ctx, src), | |
| 222 | (CastTy::Int(_), CastTy::Ptr(dst, _)) => self.check_addr_ptr_cast(ctx, dst), | |
| 223 | (CastTy::FnPtr, CastTy::Ptr(dst, _)) => self.check_fptr_ptr_cast(ctx, dst), | |
| 214 | 224 | (CastTy::Int(Int::CEnum), CastTy::Int(_)) => Ok(()), |
| 215 | 225 | (CastTy::Int(Int::Char | Int::Bool), CastTy::Int(_)) => Ok(()), |
| 216 | 226 | (CastTy::Int(_) | CastTy::Float, CastTy::Int(_) | CastTy::Float) => Ok(()), |
| ... | ... | @@ -220,23 +230,23 @@ impl CastCheck { |
| 220 | 230 | |
| 221 | 231 | fn check_ref_cast( |
| 222 | 232 | &self, |
| 223 | ctx: &mut InferenceContext<'_>, | |
| 224 | t_expr: &Ty, | |
| 233 | ctx: &mut InferenceContext<'_, 'db>, | |
| 234 | t_expr: Ty<'db>, | |
| 225 | 235 | m_expr: Mutability, |
| 226 | t_cast: &Ty, | |
| 236 | t_cast: Ty<'db>, | |
| 227 | 237 | m_cast: Mutability, |
| 228 | 238 | ) -> Result<(), CastError> { |
| 229 | 239 | // Mutability order is opposite to rustc. `Mut < Not` |
| 230 | 240 | if m_expr <= m_cast |
| 231 | && let TyKind::Array(ety, _) = t_expr.kind(Interner) | |
| 241 | && let TyKind::Array(ety, _) = t_expr.kind() | |
| 232 | 242 | { |
| 233 | 243 | // Coerce to a raw pointer so that we generate RawPtr in MIR. |
| 234 | let array_ptr_type = TyKind::Raw(m_expr, t_expr.clone()).intern(Interner); | |
| 244 | let array_ptr_type = Ty::new_ptr(ctx.interner(), t_expr, m_expr); | |
| 235 | 245 | if ctx |
| 236 | 246 | .coerce( |
| 237 | 247 | self.source_expr.into(), |
| 238 | self.expr_ty.to_nextsolver(ctx.table.interner), | |
| 239 | array_ptr_type.to_nextsolver(ctx.table.interner), | |
| 248 | self.expr_ty, | |
| 249 | array_ptr_type, | |
| 240 | 250 | AllowTwoPhase::No, |
| 241 | 251 | CoerceNever::Yes, |
| 242 | 252 | ) |
| ... | ... | @@ -253,13 +263,7 @@ impl CastCheck { |
| 253 | 263 | // This is a less strict condition than rustc's `demand_eqtype`, |
| 254 | 264 | // but false negative is better than false positive |
| 255 | 265 | if ctx |
| 256 | .coerce( | |
| 257 | self.source_expr.into(), | |
| 258 | ety.to_nextsolver(ctx.table.interner), | |
| 259 | t_cast.to_nextsolver(ctx.table.interner), | |
| 260 | AllowTwoPhase::No, | |
| 261 | CoerceNever::Yes, | |
| 262 | ) | |
| 266 | .coerce(self.source_expr.into(), ety, t_cast, AllowTwoPhase::No, CoerceNever::Yes) | |
| 263 | 267 | .is_ok() |
| 264 | 268 | { |
| 265 | 269 | return Ok(()); |
| ... | ... | @@ -271,9 +275,9 @@ impl CastCheck { |
| 271 | 275 | |
| 272 | 276 | fn check_ptr_ptr_cast( |
| 273 | 277 | &self, |
| 274 | ctx: &mut InferenceContext<'_>, | |
| 275 | src: &Ty, | |
| 276 | dst: &Ty, | |
| 278 | ctx: &mut InferenceContext<'_, 'db>, | |
| 279 | src: Ty<'db>, | |
| 280 | dst: Ty<'db>, | |
| 277 | 281 | ) -> Result<(), CastError> { |
| 278 | 282 | let src_kind = pointer_kind(src, ctx).map_err(|_| CastError::Unknown)?; |
| 279 | 283 | let dst_kind = pointer_kind(dst, ctx).map_err(|_| CastError::Unknown)?; |
| ... | ... | @@ -286,24 +290,13 @@ impl CastCheck { |
| 286 | 290 | (_, Some(PointerKind::Thin)) => Ok(()), |
| 287 | 291 | (Some(PointerKind::Thin), _) => Err(CastError::SizedUnsizedCast), |
| 288 | 292 | (Some(PointerKind::VTable(src_tty)), Some(PointerKind::VTable(dst_tty))) => { |
| 289 | let principal = |tty: &Binders<QuantifiedWhereClauses>| { | |
| 290 | tty.skip_binders().as_slice(Interner).first().and_then(|pred| { | |
| 291 | if let WhereClause::Implemented(tr) = pred.skip_binders() { | |
| 292 | Some(tr.trait_id) | |
| 293 | } else { | |
| 294 | None | |
| 295 | } | |
| 296 | }) | |
| 297 | }; | |
| 298 | match (principal(&src_tty), principal(&dst_tty)) { | |
| 293 | match (src_tty.principal_def_id(), dst_tty.principal_def_id()) { | |
| 299 | 294 | (Some(src_principal), Some(dst_principal)) => { |
| 300 | 295 | if src_principal == dst_principal { |
| 301 | 296 | return Ok(()); |
| 302 | 297 | } |
| 303 | let src_principal = | |
| 304 | ctx.db.trait_signature(from_chalk_trait_id(src_principal)); | |
| 305 | let dst_principal = | |
| 306 | ctx.db.trait_signature(from_chalk_trait_id(dst_principal)); | |
| 298 | let src_principal = ctx.db.trait_signature(src_principal.0); | |
| 299 | let dst_principal = ctx.db.trait_signature(dst_principal.0); | |
| 307 | 300 | if src_principal.flags.contains(TraitFlags::AUTO) |
| 308 | 301 | && dst_principal.flags.contains(TraitFlags::AUTO) |
| 309 | 302 | { |
| ... | ... | @@ -322,8 +315,8 @@ impl CastCheck { |
| 322 | 315 | |
| 323 | 316 | fn check_ptr_addr_cast( |
| 324 | 317 | &self, |
| 325 | ctx: &mut InferenceContext<'_>, | |
| 326 | expr_ty: &Ty, | |
| 318 | ctx: &mut InferenceContext<'_, 'db>, | |
| 319 | expr_ty: Ty<'db>, | |
| 327 | 320 | ) -> Result<(), CastError> { |
| 328 | 321 | match pointer_kind(expr_ty, ctx).map_err(|_| CastError::Unknown)? { |
| 329 | 322 | // None => Err(CastError::UnknownExprPtrKind), |
| ... | ... | @@ -336,8 +329,8 @@ impl CastCheck { |
| 336 | 329 | |
| 337 | 330 | fn check_addr_ptr_cast( |
| 338 | 331 | &self, |
| 339 | ctx: &mut InferenceContext<'_>, | |
| 340 | cast_ty: &Ty, | |
| 332 | ctx: &mut InferenceContext<'_, 'db>, | |
| 333 | cast_ty: Ty<'db>, | |
| 341 | 334 | ) -> Result<(), CastError> { |
| 342 | 335 | match pointer_kind(cast_ty, ctx).map_err(|_| CastError::Unknown)? { |
| 343 | 336 | // None => Err(CastError::UnknownCastPtrKind), |
| ... | ... | @@ -352,8 +345,8 @@ impl CastCheck { |
| 352 | 345 | |
| 353 | 346 | fn check_fptr_ptr_cast( |
| 354 | 347 | &self, |
| 355 | ctx: &mut InferenceContext<'_>, | |
| 356 | cast_ty: &Ty, | |
| 348 | ctx: &mut InferenceContext<'_, 'db>, | |
| 349 | cast_ty: Ty<'db>, | |
| 357 | 350 | ) -> Result<(), CastError> { |
| 358 | 351 | match pointer_kind(cast_ty, ctx).map_err(|_| CastError::Unknown)? { |
| 359 | 352 | // None => Err(CastError::UnknownCastPtrKind), |
| ... | ... | @@ -366,30 +359,34 @@ impl CastCheck { |
| 366 | 359 | } |
| 367 | 360 | |
| 368 | 361 | #[derive(Debug, PartialEq, Eq)] |
| 369 | enum PointerKind { | |
| 362 | enum PointerKind<'db> { | |
| 370 | 363 | // thin pointer |
| 371 | 364 | Thin, |
| 372 | 365 | // trait object |
| 373 | VTable(Binders<QuantifiedWhereClauses>), | |
| 366 | VTable(BoundExistentialPredicates<'db>), | |
| 374 | 367 | // slice |
| 375 | 368 | Length, |
| 376 | 369 | OfAlias, |
| 377 | OfParam(PlaceholderIndex), | |
| 370 | OfParam(ParamTy), | |
| 378 | 371 | Error, |
| 379 | 372 | } |
| 380 | 373 | |
| 381 | fn pointer_kind(ty: &Ty, ctx: &mut InferenceContext<'_>) -> Result<Option<PointerKind>, ()> { | |
| 382 | let ty = ctx.table.eagerly_normalize_and_resolve_shallow_in(ty.clone()); | |
| 374 | fn pointer_kind<'db>( | |
| 375 | ty: Ty<'db>, | |
| 376 | ctx: &mut InferenceContext<'_, 'db>, | |
| 377 | ) -> Result<Option<PointerKind<'db>>, ()> { | |
| 378 | let ty = ctx.table.eagerly_normalize_and_resolve_shallow_in(ty); | |
| 383 | 379 | |
| 384 | if ctx.table.is_sized(&ty) { | |
| 380 | if ctx.table.is_sized(ty) { | |
| 385 | 381 | return Ok(Some(PointerKind::Thin)); |
| 386 | 382 | } |
| 387 | 383 | |
| 388 | match ty.kind(Interner) { | |
| 384 | match ty.kind() { | |
| 389 | 385 | TyKind::Slice(_) | TyKind::Str => Ok(Some(PointerKind::Length)), |
| 390 | TyKind::Dyn(DynTy { bounds, .. }) => Ok(Some(PointerKind::VTable(bounds.clone()))), | |
| 391 | TyKind::Adt(chalk_ir::AdtId(id), subst) => { | |
| 392 | let AdtId::StructId(id) = *id else { | |
| 386 | TyKind::Dynamic(bounds, _) => Ok(Some(PointerKind::VTable(bounds))), | |
| 387 | TyKind::Adt(adt_def, subst) => { | |
| 388 | let id = adt_def.def_id().0; | |
| 389 | let AdtId::StructId(id) = id else { | |
| 393 | 390 | never!("`{:?}` should be sized but is not?", ty); |
| 394 | 391 | return Err(()); |
| 395 | 392 | }; |
| ... | ... | @@ -397,69 +394,63 @@ fn pointer_kind(ty: &Ty, ctx: &mut InferenceContext<'_>) -> Result<Option<Pointe |
| 397 | 394 | let struct_data = id.fields(ctx.db); |
| 398 | 395 | if let Some((last_field, _)) = struct_data.fields().iter().last() { |
| 399 | 396 | let last_field_ty = |
| 400 | ctx.db.field_types(id.into())[last_field].clone().substitute(Interner, subst); | |
| 401 | pointer_kind(&last_field_ty, ctx) | |
| 397 | ctx.db.field_types_ns(id.into())[last_field].instantiate(ctx.interner(), subst); | |
| 398 | pointer_kind(last_field_ty, ctx) | |
| 402 | 399 | } else { |
| 403 | 400 | Ok(Some(PointerKind::Thin)) |
| 404 | 401 | } |
| 405 | 402 | } |
| 406 | TyKind::Tuple(_, subst) => { | |
| 407 | match subst.iter(Interner).last().and_then(|arg| arg.ty(Interner)) { | |
| 408 | None => Ok(Some(PointerKind::Thin)), | |
| 409 | Some(ty) => pointer_kind(ty, ctx), | |
| 410 | } | |
| 411 | } | |
| 403 | TyKind::Tuple(subst) => match subst.iter().next_back() { | |
| 404 | None => Ok(Some(PointerKind::Thin)), | |
| 405 | Some(ty) => pointer_kind(ty, ctx), | |
| 406 | }, | |
| 412 | 407 | TyKind::Foreign(_) => Ok(Some(PointerKind::Thin)), |
| 413 | TyKind::Alias(_) | TyKind::AssociatedType(..) | TyKind::OpaqueType(..) => { | |
| 414 | Ok(Some(PointerKind::OfAlias)) | |
| 415 | } | |
| 416 | TyKind::Error => Ok(Some(PointerKind::Error)), | |
| 417 | TyKind::Placeholder(idx) => Ok(Some(PointerKind::OfParam(*idx))), | |
| 418 | TyKind::BoundVar(_) | TyKind::InferenceVar(..) => Ok(None), | |
| 419 | TyKind::Scalar(_) | |
| 408 | TyKind::Alias(..) => Ok(Some(PointerKind::OfAlias)), | |
| 409 | TyKind::Error(_) => Ok(Some(PointerKind::Error)), | |
| 410 | TyKind::Param(idx) => Ok(Some(PointerKind::OfParam(idx))), | |
| 411 | TyKind::Bound(..) | TyKind::Placeholder(..) | TyKind::Infer(..) => Ok(None), | |
| 412 | TyKind::Int(_) | |
| 413 | | TyKind::Uint(_) | |
| 414 | | TyKind::Float(_) | |
| 415 | | TyKind::Bool | |
| 416 | | TyKind::Char | |
| 420 | 417 | | TyKind::Array(..) |
| 421 | 418 | | TyKind::CoroutineWitness(..) |
| 422 | | TyKind::Raw(..) | |
| 419 | | TyKind::RawPtr(..) | |
| 423 | 420 | | TyKind::Ref(..) |
| 424 | 421 | | TyKind::FnDef(..) |
| 425 | | TyKind::Function(_) | |
| 422 | | TyKind::FnPtr(..) | |
| 426 | 423 | | TyKind::Closure(..) |
| 427 | 424 | | TyKind::Coroutine(..) |
| 425 | | TyKind::CoroutineClosure(..) | |
| 428 | 426 | | TyKind::Never => { |
| 429 | 427 | never!("`{:?}` should be sized but is not?", ty); |
| 430 | 428 | Err(()) |
| 431 | 429 | } |
| 430 | TyKind::UnsafeBinder(..) | TyKind::Pat(..) => { | |
| 431 | never!("we don't produce these types: {ty:?}"); | |
| 432 | Err(()) | |
| 433 | } | |
| 432 | 434 | } |
| 433 | 435 | } |
| 434 | 436 | |
| 435 | fn contains_dyn_trait(ty: &Ty) -> bool { | |
| 437 | fn contains_dyn_trait<'db>(ty: Ty<'db>) -> bool { | |
| 436 | 438 | use std::ops::ControlFlow; |
| 437 | 439 | |
| 438 | use chalk_ir::{ | |
| 439 | DebruijnIndex, | |
| 440 | visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}, | |
| 441 | }; | |
| 440 | use rustc_type_ir::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; | |
| 442 | 441 | |
| 443 | 442 | struct DynTraitVisitor; |
| 444 | 443 | |
| 445 | impl TypeVisitor<Interner> for DynTraitVisitor { | |
| 446 | type BreakTy = (); | |
| 447 | ||
| 448 | fn as_dyn(&mut self) -> &mut dyn TypeVisitor<Interner, BreakTy = Self::BreakTy> { | |
| 449 | self | |
| 450 | } | |
| 451 | ||
| 452 | fn interner(&self) -> Interner { | |
| 453 | Interner | |
| 454 | } | |
| 444 | impl<'db> TypeVisitor<DbInterner<'db>> for DynTraitVisitor { | |
| 445 | type Result = ControlFlow<()>; | |
| 455 | 446 | |
| 456 | fn visit_ty(&mut self, ty: &Ty, outer_binder: DebruijnIndex) -> ControlFlow<Self::BreakTy> { | |
| 457 | match ty.kind(Interner) { | |
| 458 | TyKind::Dyn(_) => ControlFlow::Break(()), | |
| 459 | _ => ty.super_visit_with(self.as_dyn(), outer_binder), | |
| 447 | fn visit_ty(&mut self, ty: Ty<'db>) -> ControlFlow<()> { | |
| 448 | match ty.kind() { | |
| 449 | TyKind::Dynamic(..) => ControlFlow::Break(()), | |
| 450 | _ => ty.super_visit_with(self), | |
| 460 | 451 | } |
| 461 | 452 | } |
| 462 | 453 | } |
| 463 | 454 | |
| 464 | ty.visit_with(DynTraitVisitor.as_dyn(), DebruijnIndex::INNERMOST).is_break() | |
| 455 | ty.visit_with(&mut DynTraitVisitor).is_break() | |
| 465 | 456 | } |
src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs+33-45| ... | ... | @@ -2,8 +2,7 @@ |
| 2 | 2 | |
| 3 | 3 | pub(crate) mod analysis; |
| 4 | 4 | |
| 5 | use std::ops::ControlFlow; | |
| 6 | use std::{iter, mem}; | |
| 5 | use std::{iter, mem, ops::ControlFlow}; | |
| 7 | 6 | |
| 8 | 7 | use hir_def::{ |
| 9 | 8 | TraitId, |
| ... | ... | @@ -18,7 +17,6 @@ use rustc_type_ir::{ |
| 18 | 17 | }; |
| 19 | 18 | use tracing::debug; |
| 20 | 19 | |
| 21 | use crate::traits::FnTrait; | |
| 22 | 20 | use crate::{ |
| 23 | 21 | FnAbi, |
| 24 | 22 | db::{InternedClosure, InternedCoroutine}, |
| ... | ... | @@ -31,25 +29,25 @@ use crate::{ |
| 31 | 29 | BoundRegionConversionTime, DefineOpaqueTypes, InferOk, InferResult, |
| 32 | 30 | traits::{ObligationCause, PredicateObligations}, |
| 33 | 31 | }, |
| 34 | mapping::{ChalkToNextSolver, NextSolverToChalk}, | |
| 35 | 32 | util::explicit_item_bounds, |
| 36 | 33 | }, |
| 34 | traits::FnTrait, | |
| 37 | 35 | }; |
| 38 | 36 | |
| 39 | 37 | use super::{Expectation, InferenceContext}; |
| 40 | 38 | |
| 41 | 39 | #[derive(Debug)] |
| 42 | struct ClosureSignatures<'tcx> { | |
| 40 | struct ClosureSignatures<'db> { | |
| 43 | 41 | /// The signature users of the closure see. |
| 44 | bound_sig: PolyFnSig<'tcx>, | |
| 42 | bound_sig: PolyFnSig<'db>, | |
| 45 | 43 | /// The signature within the function body. |
| 46 | 44 | /// This mostly differs in the sense that lifetimes are now early bound and any |
| 47 | 45 | /// opaque types from the signature expectation are overridden in case there are |
| 48 | 46 | /// explicit hidden types written by the user in the closure signature. |
| 49 | liberated_sig: FnSig<'tcx>, | |
| 47 | liberated_sig: FnSig<'db>, | |
| 50 | 48 | } |
| 51 | 49 | |
| 52 | impl<'db> InferenceContext<'db> { | |
| 50 | impl<'db> InferenceContext<'_, 'db> { | |
| 53 | 51 | pub(super) fn infer_closure( |
| 54 | 52 | &mut self, |
| 55 | 53 | body: ExprId, |
| ... | ... | @@ -58,15 +56,13 @@ impl<'db> InferenceContext<'db> { |
| 58 | 56 | arg_types: &[Option<TypeRefId>], |
| 59 | 57 | closure_kind: ClosureKind, |
| 60 | 58 | tgt_expr: ExprId, |
| 61 | expected: &Expectation, | |
| 62 | ) -> crate::Ty { | |
| 59 | expected: &Expectation<'db>, | |
| 60 | ) -> Ty<'db> { | |
| 63 | 61 | assert_eq!(args.len(), arg_types.len()); |
| 64 | 62 | |
| 65 | let interner = self.table.interner; | |
| 63 | let interner = self.interner(); | |
| 66 | 64 | let (expected_sig, expected_kind) = match expected.to_option(&mut self.table) { |
| 67 | Some(expected_ty) => { | |
| 68 | self.deduce_closure_signature(expected_ty.to_nextsolver(interner), closure_kind) | |
| 69 | } | |
| 65 | Some(expected_ty) => self.deduce_closure_signature(expected_ty, closure_kind), | |
| 70 | 66 | None => (None, None), |
| 71 | 67 | }; |
| 72 | 68 | |
| ... | ... | @@ -79,10 +75,7 @@ impl<'db> InferenceContext<'db> { |
| 79 | 75 | let (id, ty, resume_yield_tys) = match closure_kind { |
| 80 | 76 | ClosureKind::Coroutine(_) => { |
| 81 | 77 | let yield_ty = self.table.next_ty_var(); |
| 82 | let resume_ty = liberated_sig | |
| 83 | .inputs() | |
| 84 | .get(0) | |
| 85 | .unwrap_or(self.result.standard_types.unit.to_nextsolver(interner)); | |
| 78 | let resume_ty = liberated_sig.inputs().get(0).unwrap_or(self.types.unit); | |
| 86 | 79 | |
| 87 | 80 | // FIXME: Infer the upvars later. |
| 88 | 81 | let parts = CoroutineArgsParts { |
| ... | ... | @@ -102,11 +95,7 @@ impl<'db> InferenceContext<'db> { |
| 102 | 95 | CoroutineArgs::new(interner, parts).args, |
| 103 | 96 | ); |
| 104 | 97 | |
| 105 | ( | |
| 106 | None, | |
| 107 | coroutine_ty, | |
| 108 | Some((resume_ty.to_chalk(interner), yield_ty.to_chalk(interner))), | |
| 109 | ) | |
| 98 | (None, coroutine_ty, Some((resume_ty, yield_ty))) | |
| 110 | 99 | } |
| 111 | 100 | // FIXME(next-solver): `ClosureKind::Async` should really be a separate arm that creates a `CoroutineClosure`. |
| 112 | 101 | // But for now we treat it as a closure. |
| ... | ... | @@ -115,7 +104,7 @@ impl<'db> InferenceContext<'db> { |
| 115 | 104 | match expected_kind { |
| 116 | 105 | Some(kind) => { |
| 117 | 106 | self.result.closure_info.insert( |
| 118 | closure_id.into(), | |
| 107 | closure_id, | |
| 119 | 108 | ( |
| 120 | 109 | Vec::new(), |
| 121 | 110 | match kind { |
| ... | ... | @@ -151,13 +140,13 @@ impl<'db> InferenceContext<'db> { |
| 151 | 140 | |
| 152 | 141 | // Now go through the argument patterns |
| 153 | 142 | for (arg_pat, arg_ty) in args.iter().zip(bound_sig.skip_binder().inputs()) { |
| 154 | self.infer_top_pat(*arg_pat, &arg_ty.to_chalk(interner), None); | |
| 143 | self.infer_top_pat(*arg_pat, arg_ty, None); | |
| 155 | 144 | } |
| 156 | 145 | |
| 157 | 146 | // FIXME: lift these out into a struct |
| 158 | 147 | let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); |
| 159 | 148 | let prev_closure = mem::replace(&mut self.current_closure, id); |
| 160 | let prev_ret_ty = mem::replace(&mut self.return_ty, body_ret_ty.to_chalk(interner)); | |
| 149 | let prev_ret_ty = mem::replace(&mut self.return_ty, body_ret_ty); | |
| 161 | 150 | let prev_ret_coercion = self.return_coercion.replace(CoerceMany::new(body_ret_ty)); |
| 162 | 151 | let prev_resume_yield_tys = mem::replace(&mut self.resume_yield_tys, resume_yield_tys); |
| 163 | 152 | |
| ... | ... | @@ -171,7 +160,7 @@ impl<'db> InferenceContext<'db> { |
| 171 | 160 | self.current_closure = prev_closure; |
| 172 | 161 | self.resume_yield_tys = prev_resume_yield_tys; |
| 173 | 162 | |
| 174 | ty.to_chalk(interner) | |
| 163 | ty | |
| 175 | 164 | } |
| 176 | 165 | |
| 177 | 166 | fn fn_trait_kind_from_def_id(&self, trait_id: TraitId) -> Option<rustc_type_ir::ClosureKind> { |
| ... | ... | @@ -209,14 +198,13 @@ impl<'db> InferenceContext<'db> { |
| 209 | 198 | .deduce_closure_signature_from_predicates( |
| 210 | 199 | expected_ty, |
| 211 | 200 | closure_kind, |
| 212 | explicit_item_bounds(self.table.interner, def_id) | |
| 213 | .iter_instantiated(self.table.interner, args) | |
| 201 | explicit_item_bounds(self.interner(), def_id) | |
| 202 | .iter_instantiated(self.interner(), args) | |
| 214 | 203 | .map(|clause| clause.as_predicate()), |
| 215 | 204 | ), |
| 216 | 205 | TyKind::Dynamic(object_type, ..) => { |
| 217 | 206 | let sig = object_type.projection_bounds().into_iter().find_map(|pb| { |
| 218 | let pb = | |
| 219 | pb.with_self_ty(self.table.interner, Ty::new_unit(self.table.interner)); | |
| 207 | let pb = pb.with_self_ty(self.interner(), Ty::new_unit(self.interner())); | |
| 220 | 208 | self.deduce_sig_from_projection(closure_kind, pb) |
| 221 | 209 | }); |
| 222 | 210 | let kind = object_type |
| ... | ... | @@ -226,7 +214,7 @@ impl<'db> InferenceContext<'db> { |
| 226 | 214 | } |
| 227 | 215 | TyKind::Infer(rustc_type_ir::TyVar(vid)) => self |
| 228 | 216 | .deduce_closure_signature_from_predicates( |
| 229 | Ty::new_var(self.table.interner, self.table.infer_ctxt.root_var(vid)), | |
| 217 | Ty::new_var(self.interner(), self.table.infer_ctxt.root_var(vid)), | |
| 230 | 218 | closure_kind, |
| 231 | 219 | self.table.obligations_for_self_ty(vid).into_iter().map(|obl| obl.predicate), |
| 232 | 220 | ), |
| ... | ... | @@ -251,7 +239,7 @@ impl<'db> InferenceContext<'db> { |
| 251 | 239 | let mut expected_kind = None; |
| 252 | 240 | |
| 253 | 241 | for pred in rustc_type_ir::elaborate::elaborate( |
| 254 | self.table.interner, | |
| 242 | self.interner(), | |
| 255 | 243 | // Reverse the obligations here, since `elaborate_*` uses a stack, |
| 256 | 244 | // and we want to keep inference generally in the same order of |
| 257 | 245 | // the registered obligations. |
| ... | ... | @@ -313,7 +301,7 @@ impl<'db> InferenceContext<'db> { |
| 313 | 301 | // even though the normalized form may not name `expected_ty`. However, this matches the existing |
| 314 | 302 | // behaviour of the old solver and would be technically a breaking change to fix. |
| 315 | 303 | let generalized_fnptr_sig = self.table.next_ty_var(); |
| 316 | let inferred_fnptr_sig = Ty::new_fn_ptr(self.table.interner, inferred_sig); | |
| 304 | let inferred_fnptr_sig = Ty::new_fn_ptr(self.interner(), inferred_sig); | |
| 317 | 305 | // FIXME: Report diagnostics. |
| 318 | 306 | _ = self |
| 319 | 307 | .table |
| ... | ... | @@ -326,7 +314,7 @@ impl<'db> InferenceContext<'db> { |
| 326 | 314 | self.table.infer_ctxt.resolve_vars_if_possible(generalized_fnptr_sig); |
| 327 | 315 | |
| 328 | 316 | if resolved_sig.visit_with(&mut MentionsTy { expected_ty }).is_continue() { |
| 329 | expected_sig = Some(resolved_sig.fn_sig(self.table.interner)); | |
| 317 | expected_sig = Some(resolved_sig.fn_sig(self.interner())); | |
| 330 | 318 | } |
| 331 | 319 | } else if inferred_sig.visit_with(&mut MentionsTy { expected_ty }).is_continue() { |
| 332 | 320 | expected_sig = inferred_sig; |
| ... | ... | @@ -339,7 +327,7 @@ impl<'db> InferenceContext<'db> { |
| 339 | 327 | // many viable options, so pick the most restrictive. |
| 340 | 328 | let trait_def_id = match bound_predicate.skip_binder() { |
| 341 | 329 | PredicateKind::Clause(ClauseKind::Projection(data)) => { |
| 342 | Some(data.projection_term.trait_def_id(self.table.interner).0) | |
| 330 | Some(data.projection_term.trait_def_id(self.interner()).0) | |
| 343 | 331 | } |
| 344 | 332 | PredicateKind::Clause(ClauseKind::Trait(data)) => Some(data.def_id().0), |
| 345 | 333 | _ => None, |
| ... | ... | @@ -427,7 +415,7 @@ impl<'db> InferenceContext<'db> { |
| 427 | 415 | let ret_param_ty = projection.skip_binder().term.expect_type(); |
| 428 | 416 | debug!(?ret_param_ty); |
| 429 | 417 | |
| 430 | let sig = projection.rebind(self.table.interner.mk_fn_sig( | |
| 418 | let sig = projection.rebind(self.interner().mk_fn_sig( | |
| 431 | 419 | input_tys, |
| 432 | 420 | ret_param_ty, |
| 433 | 421 | false, |
| ... | ... | @@ -515,7 +503,7 @@ impl<'db> InferenceContext<'db> { |
| 515 | 503 | // that does not misuse a `FnSig` type, but that can be done separately. |
| 516 | 504 | let return_ty = return_ty.unwrap_or_else(|| self.table.next_ty_var()); |
| 517 | 505 | |
| 518 | let sig = projection.rebind(self.table.interner.mk_fn_sig( | |
| 506 | let sig = projection.rebind(self.interner().mk_fn_sig( | |
| 519 | 507 | input_tys, |
| 520 | 508 | return_ty, |
| 521 | 509 | false, |
| ... | ... | @@ -619,7 +607,7 @@ impl<'db> InferenceContext<'db> { |
| 619 | 607 | // in this binder we are creating. |
| 620 | 608 | assert!(!expected_sig.skip_binder().has_vars_bound_above(rustc_type_ir::INNERMOST)); |
| 621 | 609 | let bound_sig = expected_sig.map_bound(|sig| { |
| 622 | self.table.interner.mk_fn_sig( | |
| 610 | self.interner().mk_fn_sig( | |
| 623 | 611 | sig.inputs(), |
| 624 | 612 | sig.output(), |
| 625 | 613 | sig.c_variadic, |
| ... | ... | @@ -631,7 +619,7 @@ impl<'db> InferenceContext<'db> { |
| 631 | 619 | // `deduce_expectations_from_expected_type` introduces |
| 632 | 620 | // late-bound lifetimes defined elsewhere, which we now |
| 633 | 621 | // anonymize away, so as not to confuse the user. |
| 634 | let bound_sig = self.table.interner.anonymize_bound_vars(bound_sig); | |
| 622 | let bound_sig = self.interner().anonymize_bound_vars(bound_sig); | |
| 635 | 623 | |
| 636 | 624 | let closure_sigs = self.closure_sigs(bound_sig); |
| 637 | 625 | |
| ... | ... | @@ -723,7 +711,7 @@ impl<'db> InferenceContext<'db> { |
| 723 | 711 | .into_iter() |
| 724 | 712 | .map(|ty| table.infer_ctxt.resolve_vars_if_possible(ty)); |
| 725 | 713 | |
| 726 | expected_sigs.liberated_sig = table.interner.mk_fn_sig( | |
| 714 | expected_sigs.liberated_sig = table.interner().mk_fn_sig( | |
| 727 | 715 | inputs, |
| 728 | 716 | supplied_output_ty, |
| 729 | 717 | expected_sigs.liberated_sig.c_variadic, |
| ... | ... | @@ -744,12 +732,12 @@ impl<'db> InferenceContext<'db> { |
| 744 | 732 | decl_inputs: &[Option<TypeRefId>], |
| 745 | 733 | decl_output: Option<TypeRefId>, |
| 746 | 734 | ) -> PolyFnSig<'db> { |
| 747 | let interner = self.table.interner; | |
| 735 | let interner = self.interner(); | |
| 748 | 736 | |
| 749 | 737 | let supplied_return = match decl_output { |
| 750 | 738 | Some(output) => { |
| 751 | 739 | let output = self.make_body_ty(output); |
| 752 | self.process_user_written_ty(output).to_nextsolver(interner) | |
| 740 | self.process_user_written_ty(output) | |
| 753 | 741 | } |
| 754 | 742 | None => self.table.next_ty_var(), |
| 755 | 743 | }; |
| ... | ... | @@ -757,7 +745,7 @@ impl<'db> InferenceContext<'db> { |
| 757 | 745 | let supplied_arguments = decl_inputs.iter().map(|&input| match input { |
| 758 | 746 | Some(input) => { |
| 759 | 747 | let input = self.make_body_ty(input); |
| 760 | self.process_user_written_ty(input).to_nextsolver(interner) | |
| 748 | self.process_user_written_ty(input) | |
| 761 | 749 | } |
| 762 | 750 | None => self.table.next_ty_var(), |
| 763 | 751 | }); |
| ... | ... | @@ -779,7 +767,7 @@ impl<'db> InferenceContext<'db> { |
| 779 | 767 | decl_inputs: &[Option<TypeRefId>], |
| 780 | 768 | decl_output: Option<TypeRefId>, |
| 781 | 769 | ) -> PolyFnSig<'db> { |
| 782 | let interner = self.table.interner; | |
| 770 | let interner = self.interner(); | |
| 783 | 771 | let err_ty = Ty::new_error(interner, ErrorGuaranteed); |
| 784 | 772 | |
| 785 | 773 | if let Some(output) = decl_output { |
src/tools/rust-analyzer/crates/hir-ty/src/infer/closure/analysis.rs+96-133| ... | ... | @@ -2,10 +2,6 @@ |
| 2 | 2 | |
| 3 | 3 | use std::{cmp, convert::Infallible, mem}; |
| 4 | 4 | |
| 5 | use chalk_ir::{ | |
| 6 | BoundVar, DebruijnIndex, Mutability, TyKind, | |
| 7 | fold::{FallibleTypeFolder, TypeFoldable}, | |
| 8 | }; | |
| 9 | 5 | use either::Either; |
| 10 | 6 | use hir_def::{ |
| 11 | 7 | DefWithBodyId, FieldId, HasModule, TupleFieldId, TupleId, VariantId, |
| ... | ... | @@ -20,39 +16,37 @@ use hir_def::{ |
| 20 | 16 | }; |
| 21 | 17 | use hir_expand::name::Name; |
| 22 | 18 | use intern::sym; |
| 19 | use rustc_ast_ir::Mutability; | |
| 23 | 20 | use rustc_hash::{FxHashMap, FxHashSet}; |
| 21 | use rustc_type_ir::inherent::{IntoKind, SliceLike, Ty as _}; | |
| 24 | 22 | use smallvec::{SmallVec, smallvec}; |
| 25 | 23 | use stdx::{format_to, never}; |
| 26 | 24 | use syntax::utils::is_raw_identifier; |
| 27 | 25 | |
| 28 | use crate::db::InternedClosureId; | |
| 29 | use crate::infer::InferenceContext; | |
| 30 | 26 | use crate::{ |
| 31 | Adjust, Adjustment, Binders, BindingMode, ClosureId, Interner, Substitution, Ty, TyExt, | |
| 32 | db::{HirDatabase, InternedClosure}, | |
| 33 | error_lifetime, from_placeholder_idx, | |
| 34 | generics::Generics, | |
| 35 | make_binders, | |
| 27 | Adjust, Adjustment, BindingMode, | |
| 28 | db::{HirDatabase, InternedClosure, InternedClosureId}, | |
| 29 | infer::InferenceContext, | |
| 36 | 30 | mir::{BorrowKind, MirSpan, MutBorrowKind, ProjectionElem}, |
| 31 | next_solver::{DbInterner, EarlyBinder, GenericArgs, Ty, TyKind}, | |
| 37 | 32 | traits::FnTrait, |
| 38 | utils, | |
| 39 | 33 | }; |
| 40 | 34 | |
| 41 | 35 | // The below functions handle capture and closure kind (Fn, FnMut, ..) |
| 42 | 36 | |
| 43 | 37 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
| 44 | pub(crate) struct HirPlace { | |
| 38 | pub(crate) struct HirPlace<'db> { | |
| 45 | 39 | pub(crate) local: BindingId, |
| 46 | pub(crate) projections: Vec<ProjectionElem<Infallible, Ty>>, | |
| 40 | pub(crate) projections: Vec<ProjectionElem<Infallible, Ty<'db>>>, | |
| 47 | 41 | } |
| 48 | 42 | |
| 49 | impl HirPlace { | |
| 50 | fn ty(&self, ctx: &mut InferenceContext<'_>) -> Ty { | |
| 51 | let mut ty = ctx.table.resolve_completely(ctx.result[self.local].clone()); | |
| 43 | impl<'db> HirPlace<'db> { | |
| 44 | fn ty(&self, ctx: &mut InferenceContext<'_, 'db>) -> Ty<'db> { | |
| 45 | let mut ty = ctx.table.resolve_completely(ctx.result[self.local]); | |
| 52 | 46 | for p in &self.projections { |
| 53 | 47 | ty = p.projected_ty( |
| 48 | &ctx.table.infer_ctxt, | |
| 54 | 49 | ty, |
| 55 | ctx.db, | |
| 56 | 50 | |_, _, _| { |
| 57 | 51 | unreachable!("Closure field only happens in MIR"); |
| 58 | 52 | }, |
| ... | ... | @@ -86,8 +80,8 @@ pub enum CaptureKind { |
| 86 | 80 | } |
| 87 | 81 | |
| 88 | 82 | #[derive(Debug, Clone, PartialEq, Eq)] |
| 89 | pub struct CapturedItem { | |
| 90 | pub(crate) place: HirPlace, | |
| 83 | pub struct CapturedItem<'db> { | |
| 84 | pub(crate) place: HirPlace<'db>, | |
| 91 | 85 | pub(crate) kind: CaptureKind, |
| 92 | 86 | /// The inner vec is the stacks; the outer vec is for each capture reference. |
| 93 | 87 | /// |
| ... | ... | @@ -96,10 +90,10 @@ pub struct CapturedItem { |
| 96 | 90 | /// copy all captures of the inner closure to the outer closure, and then we may |
| 97 | 91 | /// truncate them, and we want the correct span to be reported. |
| 98 | 92 | span_stacks: SmallVec<[SmallVec<[MirSpan; 3]>; 3]>, |
| 99 | pub(crate) ty: Binders<Ty>, | |
| 93 | pub(crate) ty: EarlyBinder<'db, Ty<'db>>, | |
| 100 | 94 | } |
| 101 | 95 | |
| 102 | impl CapturedItem { | |
| 96 | impl<'db> CapturedItem<'db> { | |
| 103 | 97 | pub fn local(&self) -> BindingId { |
| 104 | 98 | self.place.local |
| 105 | 99 | } |
| ... | ... | @@ -109,8 +103,9 @@ impl CapturedItem { |
| 109 | 103 | self.place.projections.iter().any(|it| !matches!(it, ProjectionElem::Deref)) |
| 110 | 104 | } |
| 111 | 105 | |
| 112 | pub fn ty(&self, db: &dyn HirDatabase, subst: &Substitution) -> Ty { | |
| 113 | self.ty.clone().substitute(Interner, &utils::ClosureSubst(subst).parent_subst(db)) | |
| 106 | pub fn ty(&self, db: &'db dyn HirDatabase, subst: GenericArgs<'db>) -> Ty<'db> { | |
| 107 | let interner = DbInterner::new_with(db, None, None); | |
| 108 | self.ty.instantiate(interner, subst.split_closure_args_untupled().parent_args) | |
| 114 | 109 | } |
| 115 | 110 | |
| 116 | 111 | pub fn kind(&self) -> CaptureKind { |
| ... | ... | @@ -279,15 +274,15 @@ impl CapturedItem { |
| 279 | 274 | } |
| 280 | 275 | |
| 281 | 276 | #[derive(Debug, Clone, PartialEq, Eq)] |
| 282 | pub(crate) struct CapturedItemWithoutTy { | |
| 283 | pub(crate) place: HirPlace, | |
| 277 | pub(crate) struct CapturedItemWithoutTy<'db> { | |
| 278 | pub(crate) place: HirPlace<'db>, | |
| 284 | 279 | pub(crate) kind: CaptureKind, |
| 285 | 280 | /// The inner vec is the stacks; the outer vec is for each capture reference. |
| 286 | 281 | pub(crate) span_stacks: SmallVec<[SmallVec<[MirSpan; 3]>; 3]>, |
| 287 | 282 | } |
| 288 | 283 | |
| 289 | impl CapturedItemWithoutTy { | |
| 290 | fn with_ty(self, ctx: &mut InferenceContext<'_>) -> CapturedItem { | |
| 284 | impl<'db> CapturedItemWithoutTy<'db> { | |
| 285 | fn with_ty(self, ctx: &mut InferenceContext<'_, 'db>) -> CapturedItem<'db> { | |
| 291 | 286 | let ty = self.place.ty(ctx); |
| 292 | 287 | let ty = match &self.kind { |
| 293 | 288 | CaptureKind::ByValue => ty, |
| ... | ... | @@ -296,66 +291,20 @@ impl CapturedItemWithoutTy { |
| 296 | 291 | BorrowKind::Mut { .. } => Mutability::Mut, |
| 297 | 292 | _ => Mutability::Not, |
| 298 | 293 | }; |
| 299 | TyKind::Ref(m, error_lifetime(), ty).intern(Interner) | |
| 294 | Ty::new_ref(ctx.interner(), ctx.types.re_error, ty, m) | |
| 300 | 295 | } |
| 301 | 296 | }; |
| 302 | return CapturedItem { | |
| 297 | CapturedItem { | |
| 303 | 298 | place: self.place, |
| 304 | 299 | kind: self.kind, |
| 305 | 300 | span_stacks: self.span_stacks, |
| 306 | ty: replace_placeholder_with_binder(ctx, ty), | |
| 307 | }; | |
| 308 | ||
| 309 | fn replace_placeholder_with_binder(ctx: &mut InferenceContext<'_>, ty: Ty) -> Binders<Ty> { | |
| 310 | struct Filler<'a> { | |
| 311 | db: &'a dyn HirDatabase, | |
| 312 | generics: &'a Generics, | |
| 313 | } | |
| 314 | impl FallibleTypeFolder<Interner> for Filler<'_> { | |
| 315 | type Error = (); | |
| 316 | ||
| 317 | fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder<Interner, Error = Self::Error> { | |
| 318 | self | |
| 319 | } | |
| 320 | ||
| 321 | fn interner(&self) -> Interner { | |
| 322 | Interner | |
| 323 | } | |
| 324 | ||
| 325 | fn try_fold_free_placeholder_const( | |
| 326 | &mut self, | |
| 327 | ty: chalk_ir::Ty<Interner>, | |
| 328 | idx: chalk_ir::PlaceholderIndex, | |
| 329 | outer_binder: DebruijnIndex, | |
| 330 | ) -> Result<chalk_ir::Const<Interner>, Self::Error> { | |
| 331 | let x = from_placeholder_idx(self.db, idx).0; | |
| 332 | let Some(idx) = self.generics.type_or_const_param_idx(x) else { | |
| 333 | return Err(()); | |
| 334 | }; | |
| 335 | Ok(BoundVar::new(outer_binder, idx).to_const(Interner, ty)) | |
| 336 | } | |
| 337 | ||
| 338 | fn try_fold_free_placeholder_ty( | |
| 339 | &mut self, | |
| 340 | idx: chalk_ir::PlaceholderIndex, | |
| 341 | outer_binder: DebruijnIndex, | |
| 342 | ) -> std::result::Result<Ty, Self::Error> { | |
| 343 | let x = from_placeholder_idx(self.db, idx).0; | |
| 344 | let Some(idx) = self.generics.type_or_const_param_idx(x) else { | |
| 345 | return Err(()); | |
| 346 | }; | |
| 347 | Ok(BoundVar::new(outer_binder, idx).to_ty(Interner)) | |
| 348 | } | |
| 349 | } | |
| 350 | let filler = &mut Filler { db: ctx.db, generics: ctx.generics() }; | |
| 351 | let result = ty.clone().try_fold_with(filler, DebruijnIndex::INNERMOST).unwrap_or(ty); | |
| 352 | make_binders(ctx.db, filler.generics, result) | |
| 301 | ty: EarlyBinder::bind(ty), | |
| 353 | 302 | } |
| 354 | 303 | } |
| 355 | 304 | } |
| 356 | 305 | |
| 357 | impl InferenceContext<'_> { | |
| 358 | fn place_of_expr(&mut self, tgt_expr: ExprId) -> Option<HirPlace> { | |
| 306 | impl<'db> InferenceContext<'_, 'db> { | |
| 307 | fn place_of_expr(&mut self, tgt_expr: ExprId) -> Option<HirPlace<'db>> { | |
| 359 | 308 | let r = self.place_of_expr_without_adjust(tgt_expr)?; |
| 360 | 309 | let adjustments = |
| 361 | 310 | self.result.expr_adjustments.get(&tgt_expr).map(|it| &**it).unwrap_or_default(); |
| ... | ... | @@ -363,7 +312,7 @@ impl InferenceContext<'_> { |
| 363 | 312 | } |
| 364 | 313 | |
| 365 | 314 | /// Pushes the span into `current_capture_span_stack`, *without clearing it first*. |
| 366 | fn path_place(&mut self, path: &Path, id: ExprOrPatId) -> Option<HirPlace> { | |
| 315 | fn path_place(&mut self, path: &Path, id: ExprOrPatId) -> Option<HirPlace<'db>> { | |
| 367 | 316 | if path.type_anchor().is_some() { |
| 368 | 317 | return None; |
| 369 | 318 | } |
| ... | ... | @@ -384,7 +333,7 @@ impl InferenceContext<'_> { |
| 384 | 333 | } |
| 385 | 334 | |
| 386 | 335 | /// Changes `current_capture_span_stack` to contain the stack of spans for this expr. |
| 387 | fn place_of_expr_without_adjust(&mut self, tgt_expr: ExprId) -> Option<HirPlace> { | |
| 336 | fn place_of_expr_without_adjust(&mut self, tgt_expr: ExprId) -> Option<HirPlace<'db>> { | |
| 388 | 337 | self.current_capture_span_stack.clear(); |
| 389 | 338 | match &self.body[tgt_expr] { |
| 390 | 339 | Expr::Path(p) => { |
| ... | ... | @@ -403,8 +352,8 @@ impl InferenceContext<'_> { |
| 403 | 352 | } |
| 404 | 353 | Expr::UnaryOp { expr, op: UnaryOp::Deref } => { |
| 405 | 354 | if matches!( |
| 406 | self.expr_ty_after_adjustments(*expr).kind(Interner), | |
| 407 | TyKind::Ref(..) | TyKind::Raw(..) | |
| 355 | self.expr_ty_after_adjustments(*expr).kind(), | |
| 356 | TyKind::Ref(..) | TyKind::RawPtr(..) | |
| 408 | 357 | ) { |
| 409 | 358 | let mut place = self.place_of_expr(*expr)?; |
| 410 | 359 | self.current_capture_span_stack.push(MirSpan::ExprId(tgt_expr)); |
| ... | ... | @@ -417,7 +366,7 @@ impl InferenceContext<'_> { |
| 417 | 366 | None |
| 418 | 367 | } |
| 419 | 368 | |
| 420 | fn push_capture(&mut self, place: HirPlace, kind: CaptureKind) { | |
| 369 | fn push_capture(&mut self, place: HirPlace<'db>, kind: CaptureKind) { | |
| 421 | 370 | self.current_captures.push(CapturedItemWithoutTy { |
| 422 | 371 | place, |
| 423 | 372 | kind, |
| ... | ... | @@ -425,7 +374,11 @@ impl InferenceContext<'_> { |
| 425 | 374 | }); |
| 426 | 375 | } |
| 427 | 376 | |
| 428 | fn truncate_capture_spans(&self, capture: &mut CapturedItemWithoutTy, mut truncate_to: usize) { | |
| 377 | fn truncate_capture_spans( | |
| 378 | &self, | |
| 379 | capture: &mut CapturedItemWithoutTy<'db>, | |
| 380 | mut truncate_to: usize, | |
| 381 | ) { | |
| 429 | 382 | // The first span is the identifier, and it must always remain. |
| 430 | 383 | truncate_to += 1; |
| 431 | 384 | for span_stack in &mut capture.span_stacks { |
| ... | ... | @@ -450,14 +403,14 @@ impl InferenceContext<'_> { |
| 450 | 403 | } |
| 451 | 404 | } |
| 452 | 405 | |
| 453 | fn ref_expr(&mut self, expr: ExprId, place: Option<HirPlace>) { | |
| 406 | fn ref_expr(&mut self, expr: ExprId, place: Option<HirPlace<'db>>) { | |
| 454 | 407 | if let Some(place) = place { |
| 455 | 408 | self.add_capture(place, CaptureKind::ByRef(BorrowKind::Shared)); |
| 456 | 409 | } |
| 457 | 410 | self.walk_expr(expr); |
| 458 | 411 | } |
| 459 | 412 | |
| 460 | fn add_capture(&mut self, place: HirPlace, kind: CaptureKind) { | |
| 413 | fn add_capture(&mut self, place: HirPlace<'db>, kind: CaptureKind) { | |
| 461 | 414 | if self.is_upvar(&place) { |
| 462 | 415 | self.push_capture(place, kind); |
| 463 | 416 | } |
| ... | ... | @@ -473,7 +426,7 @@ impl InferenceContext<'_> { |
| 473 | 426 | } |
| 474 | 427 | } |
| 475 | 428 | |
| 476 | fn mutate_expr(&mut self, expr: ExprId, place: Option<HirPlace>) { | |
| 429 | fn mutate_expr(&mut self, expr: ExprId, place: Option<HirPlace<'db>>) { | |
| 477 | 430 | if let Some(place) = place { |
| 478 | 431 | self.add_capture( |
| 479 | 432 | place, |
| ... | ... | @@ -490,7 +443,7 @@ impl InferenceContext<'_> { |
| 490 | 443 | self.walk_expr(expr); |
| 491 | 444 | } |
| 492 | 445 | |
| 493 | fn consume_place(&mut self, place: HirPlace) { | |
| 446 | fn consume_place(&mut self, place: HirPlace<'db>) { | |
| 494 | 447 | if self.is_upvar(&place) { |
| 495 | 448 | let ty = place.ty(self); |
| 496 | 449 | let kind = if self.is_ty_copy(ty) { |
| ... | ... | @@ -502,7 +455,7 @@ impl InferenceContext<'_> { |
| 502 | 455 | } |
| 503 | 456 | } |
| 504 | 457 | |
| 505 | fn walk_expr_with_adjust(&mut self, tgt_expr: ExprId, adjustment: &[Adjustment]) { | |
| 458 | fn walk_expr_with_adjust(&mut self, tgt_expr: ExprId, adjustment: &[Adjustment<'db>]) { | |
| 506 | 459 | if let Some((last, rest)) = adjustment.split_last() { |
| 507 | 460 | match &last.kind { |
| 508 | 461 | Adjust::NeverToAny | Adjust::Deref(None) | Adjust::Pointer(_) => { |
| ... | ... | @@ -523,7 +476,12 @@ impl InferenceContext<'_> { |
| 523 | 476 | } |
| 524 | 477 | } |
| 525 | 478 | |
| 526 | fn ref_capture_with_adjusts(&mut self, m: Mutability, tgt_expr: ExprId, rest: &[Adjustment]) { | |
| 479 | fn ref_capture_with_adjusts( | |
| 480 | &mut self, | |
| 481 | m: Mutability, | |
| 482 | tgt_expr: ExprId, | |
| 483 | rest: &[Adjustment<'db>], | |
| 484 | ) { | |
| 527 | 485 | let capture_kind = match m { |
| 528 | 486 | Mutability::Mut => CaptureKind::ByRef(BorrowKind::Mut { kind: MutBorrowKind::Default }), |
| 529 | 487 | Mutability::Not => CaptureKind::ByRef(BorrowKind::Shared), |
| ... | ... | @@ -652,8 +610,8 @@ impl InferenceContext<'_> { |
| 652 | 610 | Expr::Field { expr, name: _ } => self.select_from_expr(*expr), |
| 653 | 611 | Expr::UnaryOp { expr, op: UnaryOp::Deref } => { |
| 654 | 612 | if matches!( |
| 655 | self.expr_ty_after_adjustments(*expr).kind(Interner), | |
| 656 | TyKind::Ref(..) | TyKind::Raw(..) | |
| 613 | self.expr_ty_after_adjustments(*expr).kind(), | |
| 614 | TyKind::Ref(..) | TyKind::RawPtr(..) | |
| 657 | 615 | ) { |
| 658 | 616 | self.select_from_expr(*expr); |
| 659 | 617 | } else if let Some((f, _)) = self.result.method_resolution(tgt_expr) { |
| ... | ... | @@ -728,12 +686,12 @@ impl InferenceContext<'_> { |
| 728 | 686 | } |
| 729 | 687 | Expr::Closure { .. } => { |
| 730 | 688 | let ty = self.expr_ty(tgt_expr); |
| 731 | let TyKind::Closure(id, _) = ty.kind(Interner) else { | |
| 689 | let TyKind::Closure(id, _) = ty.kind() else { | |
| 732 | 690 | never!("closure type is always closure"); |
| 733 | 691 | return; |
| 734 | 692 | }; |
| 735 | 693 | let (captures, _) = |
| 736 | self.result.closure_info.get(id).expect( | |
| 694 | self.result.closure_info.get(&id.0).expect( | |
| 737 | 695 | "We sort closures, so we should always have data for inner closures", |
| 738 | 696 | ); |
| 739 | 697 | let mut cc = mem::take(&mut self.current_captures); |
| ... | ... | @@ -830,7 +788,7 @@ impl InferenceContext<'_> { |
| 830 | 788 | } |
| 831 | 789 | Pat::Bind { id, .. } => match self.result.binding_modes[p] { |
| 832 | 790 | crate::BindingMode::Move => { |
| 833 | if self.is_ty_copy(self.result.type_of_binding[*id].clone()) { | |
| 791 | if self.is_ty_copy(self.result.type_of_binding[*id]) { | |
| 834 | 792 | update_result(CaptureKind::ByRef(BorrowKind::Shared)); |
| 835 | 793 | } else { |
| 836 | 794 | update_result(CaptureKind::ByValue); |
| ... | ... | @@ -848,21 +806,21 @@ impl InferenceContext<'_> { |
| 848 | 806 | self.body.walk_pats_shallow(p, |p| self.walk_pat_inner(p, update_result, for_mut)); |
| 849 | 807 | } |
| 850 | 808 | |
| 851 | fn expr_ty(&self, expr: ExprId) -> Ty { | |
| 852 | self.result[expr].clone() | |
| 809 | fn expr_ty(&self, expr: ExprId) -> Ty<'db> { | |
| 810 | self.result[expr] | |
| 853 | 811 | } |
| 854 | 812 | |
| 855 | fn expr_ty_after_adjustments(&self, e: ExprId) -> Ty { | |
| 813 | fn expr_ty_after_adjustments(&self, e: ExprId) -> Ty<'db> { | |
| 856 | 814 | let mut ty = None; |
| 857 | 815 | if let Some(it) = self.result.expr_adjustments.get(&e) |
| 858 | 816 | && let Some(it) = it.last() |
| 859 | 817 | { |
| 860 | ty = Some(it.target.clone()); | |
| 818 | ty = Some(it.target); | |
| 861 | 819 | } |
| 862 | 820 | ty.unwrap_or_else(|| self.expr_ty(e)) |
| 863 | 821 | } |
| 864 | 822 | |
| 865 | fn is_upvar(&self, place: &HirPlace) -> bool { | |
| 823 | fn is_upvar(&self, place: &HirPlace<'db>) -> bool { | |
| 866 | 824 | if let Some(c) = self.current_closure { |
| 867 | 825 | let InternedClosure(_, root) = self.db.lookup_intern_closure(c); |
| 868 | 826 | return self.body.is_binding_upvar(place.local, root); |
| ... | ... | @@ -870,14 +828,20 @@ impl InferenceContext<'_> { |
| 870 | 828 | false |
| 871 | 829 | } |
| 872 | 830 | |
| 873 | fn is_ty_copy(&mut self, ty: Ty) -> bool { | |
| 874 | if let TyKind::Closure(id, _) = ty.kind(Interner) { | |
| 831 | fn is_ty_copy(&mut self, ty: Ty<'db>) -> bool { | |
| 832 | if let TyKind::Closure(id, _) = ty.kind() { | |
| 875 | 833 | // FIXME: We handle closure as a special case, since chalk consider every closure as copy. We |
| 876 | 834 | // should probably let chalk know which closures are copy, but I don't know how doing it |
| 877 | 835 | // without creating query cycles. |
| 878 | return self.result.closure_info.get(id).map(|it| it.1 == FnTrait::Fn).unwrap_or(true); | |
| 836 | return self | |
| 837 | .result | |
| 838 | .closure_info | |
| 839 | .get(&id.0) | |
| 840 | .map(|it| it.1 == FnTrait::Fn) | |
| 841 | .unwrap_or(true); | |
| 879 | 842 | } |
| 880 | self.table.resolve_completely(ty).is_copy(self.db, self.owner) | |
| 843 | let ty = self.table.resolve_completely(ty); | |
| 844 | self.table.type_is_copy_modulo_regions(ty) | |
| 881 | 845 | } |
| 882 | 846 | |
| 883 | 847 | fn select_from_expr(&mut self, expr: ExprId) { |
| ... | ... | @@ -888,8 +852,8 @@ impl InferenceContext<'_> { |
| 888 | 852 | // FIXME: Borrow checker problems without this. |
| 889 | 853 | let mut current_captures = std::mem::take(&mut self.current_captures); |
| 890 | 854 | for capture in &mut current_captures { |
| 891 | let mut ty = self.table.resolve_completely(self.result[capture.place.local].clone()); | |
| 892 | if ty.as_raw_ptr().is_some() || ty.is_union() { | |
| 855 | let mut ty = self.table.resolve_completely(self.result[capture.place.local]); | |
| 856 | if ty.is_raw_ptr() || ty.is_union() { | |
| 893 | 857 | capture.kind = CaptureKind::ByRef(BorrowKind::Shared); |
| 894 | 858 | self.truncate_capture_spans(capture, 0); |
| 895 | 859 | capture.place.projections.truncate(0); |
| ... | ... | @@ -897,14 +861,14 @@ impl InferenceContext<'_> { |
| 897 | 861 | } |
| 898 | 862 | for (i, p) in capture.place.projections.iter().enumerate() { |
| 899 | 863 | ty = p.projected_ty( |
| 864 | &self.table.infer_ctxt, | |
| 900 | 865 | ty, |
| 901 | self.db, | |
| 902 | 866 | |_, _, _| { |
| 903 | 867 | unreachable!("Closure field only happens in MIR"); |
| 904 | 868 | }, |
| 905 | 869 | self.owner.module(self.db).krate(), |
| 906 | 870 | ); |
| 907 | if ty.as_raw_ptr().is_some() || ty.is_union() { | |
| 871 | if ty.is_raw_ptr() || ty.is_union() { | |
| 908 | 872 | capture.kind = CaptureKind::ByRef(BorrowKind::Shared); |
| 909 | 873 | self.truncate_capture_spans(capture, i + 1); |
| 910 | 874 | capture.place.projections.truncate(i + 1); |
| ... | ... | @@ -932,7 +896,7 @@ impl InferenceContext<'_> { |
| 932 | 896 | |
| 933 | 897 | fn minimize_captures(&mut self) { |
| 934 | 898 | self.current_captures.sort_unstable_by_key(|it| it.place.projections.len()); |
| 935 | let mut hash_map = FxHashMap::<HirPlace, usize>::default(); | |
| 899 | let mut hash_map = FxHashMap::<HirPlace<'db>, usize>::default(); | |
| 936 | 900 | let result = mem::take(&mut self.current_captures); |
| 937 | 901 | for mut item in result { |
| 938 | 902 | let mut lookup_place = HirPlace { local: item.place.local, projections: vec![] }; |
| ... | ... | @@ -967,7 +931,7 @@ impl InferenceContext<'_> { |
| 967 | 931 | } |
| 968 | 932 | } |
| 969 | 933 | |
| 970 | fn consume_with_pat(&mut self, mut place: HirPlace, tgt_pat: PatId) { | |
| 934 | fn consume_with_pat(&mut self, mut place: HirPlace<'db>, tgt_pat: PatId) { | |
| 971 | 935 | let adjustments_count = |
| 972 | 936 | self.result.pat_adjustments.get(&tgt_pat).map(|it| it.len()).unwrap_or_default(); |
| 973 | 937 | place.projections.extend((0..adjustments_count).map(|_| ProjectionElem::Deref)); |
| ... | ... | @@ -978,8 +942,8 @@ impl InferenceContext<'_> { |
| 978 | 942 | Pat::Missing | Pat::Wild => (), |
| 979 | 943 | Pat::Tuple { args, ellipsis } => { |
| 980 | 944 | let (al, ar) = args.split_at(ellipsis.map_or(args.len(), |it| it as usize)); |
| 981 | let field_count = match self.result[tgt_pat].kind(Interner) { | |
| 982 | TyKind::Tuple(_, s) => s.len(Interner), | |
| 945 | let field_count = match self.result[tgt_pat].kind() { | |
| 946 | TyKind::Tuple(s) => s.len(), | |
| 983 | 947 | _ => break 'reset_span_stack, |
| 984 | 948 | }; |
| 985 | 949 | let fields = 0..field_count; |
| ... | ... | @@ -1125,9 +1089,9 @@ impl InferenceContext<'_> { |
| 1125 | 1089 | r |
| 1126 | 1090 | } |
| 1127 | 1091 | |
| 1128 | fn analyze_closure(&mut self, closure: ClosureId) -> FnTrait { | |
| 1129 | let InternedClosure(_, root) = self.db.lookup_intern_closure(closure.into()); | |
| 1130 | self.current_closure = Some(closure.into()); | |
| 1092 | fn analyze_closure(&mut self, closure: InternedClosureId) -> FnTrait { | |
| 1093 | let InternedClosure(_, root) = self.db.lookup_intern_closure(closure); | |
| 1094 | self.current_closure = Some(closure); | |
| 1131 | 1095 | let Expr::Closure { body, capture_by, .. } = &self.body[root] else { |
| 1132 | 1096 | unreachable!("Closure expression id is always closure"); |
| 1133 | 1097 | }; |
| ... | ... | @@ -1193,9 +1157,9 @@ impl InferenceContext<'_> { |
| 1193 | 1157 | self.result.expr_adjustments.remove(&callee).unwrap_or_default().into_vec(); |
| 1194 | 1158 | self.write_fn_trait_method_resolution( |
| 1195 | 1159 | kind, |
| 1196 | &derefed_callee, | |
| 1160 | derefed_callee, | |
| 1197 | 1161 | &mut adjustments, |
| 1198 | &callee_ty, | |
| 1162 | callee_ty, | |
| 1199 | 1163 | &params, |
| 1200 | 1164 | expr, |
| 1201 | 1165 | ); |
| ... | ... | @@ -1213,27 +1177,26 @@ impl InferenceContext<'_> { |
| 1213 | 1177 | /// |
| 1214 | 1178 | /// These dependencies are collected in the main inference. We do a topological sort in this function. It |
| 1215 | 1179 | /// will consume the `deferred_closures` field and return its content in a sorted vector. |
| 1216 | fn sort_closures(&mut self) -> Vec<(ClosureId, Vec<(Ty, Ty, Vec<Ty>, ExprId)>)> { | |
| 1180 | fn sort_closures( | |
| 1181 | &mut self, | |
| 1182 | ) -> Vec<(InternedClosureId, Vec<(Ty<'db>, Ty<'db>, Vec<Ty<'db>>, ExprId)>)> { | |
| 1217 | 1183 | let mut deferred_closures = mem::take(&mut self.deferred_closures); |
| 1218 | let mut dependents_count: FxHashMap<ClosureId, usize> = | |
| 1219 | deferred_closures.keys().map(|it| ((*it).into(), 0)).collect(); | |
| 1184 | let mut dependents_count: FxHashMap<InternedClosureId, usize> = | |
| 1185 | deferred_closures.keys().map(|it| (*it, 0)).collect(); | |
| 1220 | 1186 | for deps in self.closure_dependencies.values() { |
| 1221 | 1187 | for dep in deps { |
| 1222 | *dependents_count.entry((*dep).into()).or_default() += 1; | |
| 1188 | *dependents_count.entry(*dep).or_default() += 1; | |
| 1223 | 1189 | } |
| 1224 | 1190 | } |
| 1225 | let mut queue: Vec<_> = deferred_closures | |
| 1226 | .keys() | |
| 1227 | .copied() | |
| 1228 | .filter(|&it| dependents_count[&it.into()] == 0) | |
| 1229 | .collect(); | |
| 1191 | let mut queue: Vec<_> = | |
| 1192 | deferred_closures.keys().copied().filter(|&it| dependents_count[&it] == 0).collect(); | |
| 1230 | 1193 | let mut result = vec![]; |
| 1231 | 1194 | while let Some(it) = queue.pop() { |
| 1232 | 1195 | if let Some(d) = deferred_closures.remove(&it) { |
| 1233 | result.push((it.into(), d)); | |
| 1196 | result.push((it, d)); | |
| 1234 | 1197 | } |
| 1235 | 1198 | for &dep in self.closure_dependencies.get(&it).into_iter().flat_map(|it| it.iter()) { |
| 1236 | let cnt = dependents_count.get_mut(&dep.into()).unwrap(); | |
| 1199 | let cnt = dependents_count.get_mut(&dep).unwrap(); | |
| 1237 | 1200 | *cnt -= 1; |
| 1238 | 1201 | if *cnt == 0 { |
| 1239 | 1202 | queue.push(dep); |
| ... | ... | @@ -1279,11 +1242,11 @@ impl InferenceContext<'_> { |
| 1279 | 1242 | } |
| 1280 | 1243 | |
| 1281 | 1244 | /// Call this only when the last span in the stack isn't a split. |
| 1282 | fn apply_adjusts_to_place( | |
| 1245 | fn apply_adjusts_to_place<'db>( | |
| 1283 | 1246 | current_capture_span_stack: &mut Vec<MirSpan>, |
| 1284 | mut r: HirPlace, | |
| 1285 | adjustments: &[Adjustment], | |
| 1286 | ) -> Option<HirPlace> { | |
| 1247 | mut r: HirPlace<'db>, | |
| 1248 | adjustments: &[Adjustment<'db>], | |
| 1249 | ) -> Option<HirPlace<'db>> { | |
| 1287 | 1250 | let span = *current_capture_span_stack.last().expect("empty capture span stack"); |
| 1288 | 1251 | for adj in adjustments { |
| 1289 | 1252 | match &adj.kind { |
src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs+115-130| ... | ... | @@ -35,7 +35,6 @@ |
| 35 | 35 | //! // and are then unable to coerce `&7i32` to `&mut i32`. |
| 36 | 36 | //! ``` |
| 37 | 37 | |
| 38 | use chalk_ir::cast::Cast; | |
| 39 | 38 | use hir_def::{ |
| 40 | 39 | CallableDefId, |
| 41 | 40 | hir::{ExprId, ExprOrPatId}, |
| ... | ... | @@ -45,29 +44,30 @@ use hir_def::{ |
| 45 | 44 | use intern::sym; |
| 46 | 45 | use rustc_ast_ir::Mutability; |
| 47 | 46 | use rustc_type_ir::{ |
| 48 | TypeAndMut, | |
| 47 | BoundVar, TypeAndMut, | |
| 49 | 48 | error::TypeError, |
| 50 | inherent::{IntoKind, Safety, Ty as _}, | |
| 49 | inherent::{Const as _, GenericArg as _, IntoKind, Safety, SliceLike, Ty as _}, | |
| 51 | 50 | }; |
| 52 | 51 | use smallvec::{SmallVec, smallvec}; |
| 53 | 52 | use tracing::{debug, instrument}; |
| 54 | 53 | use triomphe::Arc; |
| 55 | 54 | |
| 56 | 55 | use crate::{ |
| 57 | Adjust, Adjustment, AutoBorrow, Interner, PointerCast, TargetFeatures, TraitEnvironment, | |
| 56 | Adjust, Adjustment, AutoBorrow, PointerCast, TargetFeatures, TraitEnvironment, | |
| 58 | 57 | autoderef::Autoderef, |
| 59 | 58 | db::{HirDatabase, InternedClosureId}, |
| 60 | 59 | infer::{AllowTwoPhase, InferenceContext, TypeMismatch, unify::InferenceTable}, |
| 61 | 60 | next_solver::{ |
| 62 | Binder, CallableIdWrapper, ClauseKind, CoercePredicate, DbInterner, ErrorGuaranteed, | |
| 63 | GenericArgs, PolyFnSig, PredicateKind, Region, SolverDefId, TraitRef, Ty, TyKind, | |
| 61 | Binder, BoundConst, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, CallableIdWrapper, | |
| 62 | Canonical, ClauseKind, CoercePredicate, Const, ConstKind, DbInterner, ErrorGuaranteed, | |
| 63 | GenericArgs, PolyFnSig, PredicateKind, Region, RegionKind, SolverDefId, TraitRef, Ty, | |
| 64 | TyKind, | |
| 64 | 65 | infer::{ |
| 65 | 66 | DefineOpaqueTypes, InferCtxt, InferOk, InferResult, |
| 66 | 67 | relate::RelateResult, |
| 67 | 68 | select::{ImplSource, SelectionError}, |
| 68 | 69 | traits::{Obligation, ObligationCause, PredicateObligation, PredicateObligations}, |
| 69 | 70 | }, |
| 70 | mapping::{ChalkToNextSolver, NextSolverToChalk}, | |
| 71 | 71 | obligation_ctxt::ObligationCtxt, |
| 72 | 72 | }, |
| 73 | 73 | utils::TargetFeatureIsSafeInTarget, |
| ... | ... | @@ -93,7 +93,7 @@ struct Coerce<'a, 'b, 'db> { |
| 93 | 93 | cause: ObligationCause, |
| 94 | 94 | } |
| 95 | 95 | |
| 96 | type CoerceResult<'db> = InferResult<'db, (Vec<Adjustment>, Ty<'db>)>; | |
| 96 | type CoerceResult<'db> = InferResult<'db, (Vec<Adjustment<'db>>, Ty<'db>)>; | |
| 97 | 97 | |
| 98 | 98 | /// Coercing a mutable reference to an immutable works, while |
| 99 | 99 | /// coercing `&T` to `&mut T` should be forbidden. |
| ... | ... | @@ -103,7 +103,7 @@ fn coerce_mutbls<'db>(from_mutbl: Mutability, to_mutbl: Mutability) -> RelateRes |
| 103 | 103 | |
| 104 | 104 | /// This always returns `Ok(...)`. |
| 105 | 105 | fn success<'db>( |
| 106 | adj: Vec<Adjustment>, | |
| 106 | adj: Vec<Adjustment<'db>>, | |
| 107 | 107 | target: Ty<'db>, |
| 108 | 108 | obligations: PredicateObligations<'db>, |
| 109 | 109 | ) -> CoerceResult<'db> { |
| ... | ... | @@ -118,7 +118,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> { |
| 118 | 118 | |
| 119 | 119 | #[inline] |
| 120 | 120 | fn interner(&self) -> DbInterner<'db> { |
| 121 | self.table.interner | |
| 121 | self.table.interner() | |
| 122 | 122 | } |
| 123 | 123 | |
| 124 | 124 | #[inline] |
| ... | ... | @@ -182,17 +182,14 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> { |
| 182 | 182 | &mut self, |
| 183 | 183 | a: Ty<'db>, |
| 184 | 184 | b: Ty<'db>, |
| 185 | adjustments: impl IntoIterator<Item = Adjustment>, | |
| 186 | final_adjustment: Adjust, | |
| 185 | adjustments: impl IntoIterator<Item = Adjustment<'db>>, | |
| 186 | final_adjustment: Adjust<'db>, | |
| 187 | 187 | ) -> CoerceResult<'db> { |
| 188 | 188 | self.unify_raw(a, b).and_then(|InferOk { value: ty, obligations }| { |
| 189 | 189 | success( |
| 190 | 190 | adjustments |
| 191 | 191 | .into_iter() |
| 192 | .chain(std::iter::once(Adjustment { | |
| 193 | target: ty.to_chalk(self.interner()), | |
| 194 | kind: final_adjustment, | |
| 195 | })) | |
| 192 | .chain(std::iter::once(Adjustment { target: ty, kind: final_adjustment })) | |
| 196 | 193 | .collect(), |
| 197 | 194 | ty, |
| 198 | 195 | obligations, |
| ... | ... | @@ -216,10 +213,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> { |
| 216 | 213 | |
| 217 | 214 | if self.coerce_never { |
| 218 | 215 | return success( |
| 219 | vec![Adjustment { | |
| 220 | kind: Adjust::NeverToAny, | |
| 221 | target: b.to_chalk(self.interner()), | |
| 222 | }], | |
| 216 | vec![Adjustment { kind: Adjust::NeverToAny, target: b }], | |
| 223 | 217 | b, |
| 224 | 218 | PredicateObligations::new(), |
| 225 | 219 | ); |
| ... | ... | @@ -241,10 +235,9 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> { |
| 241 | 235 | && let TyKind::Alias(rustc_type_ir::Opaque, opaque_ty) = b.kind() |
| 242 | 236 | && let SolverDefId::InternedOpaqueTyId(opaque_ty_id) = opaque_ty.def_id |
| 243 | 237 | && !matches!(a.kind(), TyKind::Infer(..) | TyKind::Alias(rustc_type_ir::Opaque, _)) |
| 244 | && let Some(ty) = tait_table.get(&opaque_ty_id.into()) | |
| 238 | && let Some(ty) = tait_table.get(&opaque_ty_id) | |
| 245 | 239 | { |
| 246 | b = ty.to_nextsolver(self.interner()); | |
| 247 | b = self.table.shallow_resolve(b); | |
| 240 | b = self.table.shallow_resolve(*ty); | |
| 248 | 241 | } |
| 249 | 242 | let b = b; |
| 250 | 243 | |
| ... | ... | @@ -474,7 +467,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> { |
| 474 | 467 | r_borrow_var.unwrap() |
| 475 | 468 | }; |
| 476 | 469 | let derefd_ty_a = Ty::new_ref( |
| 477 | autoderef.table.interner, | |
| 470 | autoderef.table.interner(), | |
| 478 | 471 | r, |
| 479 | 472 | referent_ty, |
| 480 | 473 | mutbl_b, // [1] above |
| ... | ... | @@ -547,11 +540,8 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> { |
| 547 | 540 | panic!("expected a ref type, got {:?}", ty); |
| 548 | 541 | }; |
| 549 | 542 | adjustments.push(Adjustment { |
| 550 | kind: Adjust::Borrow(AutoBorrow::Ref( | |
| 551 | region.to_chalk(self.interner()), | |
| 552 | mutbl_b.to_chalk(self.interner()), | |
| 553 | )), | |
| 554 | target: ty.to_chalk(self.interner()), | |
| 543 | kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl_b)), | |
| 544 | target: ty, | |
| 555 | 545 | }); |
| 556 | 546 | |
| 557 | 547 | debug!("coerce_borrowed_pointer: succeeded ty={:?} adjustments={:?}", ty, adjustments); |
| ... | ... | @@ -655,20 +645,13 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> { |
| 655 | 645 | // implementation. If it happens that this coercion is a function argument, |
| 656 | 646 | // the reborrow in coerce_borrowed_ptr will pick it up. |
| 657 | 647 | // let mutbl = AutoBorrowMutability::new(mutbl_b, AllowTwoPhase::No); |
| 658 | let mutbl = mutbl_b.to_chalk(self.interner()); | |
| 648 | let mutbl = mutbl_b; | |
| 659 | 649 | |
| 660 | 650 | Some(( |
| 651 | Adjustment { kind: Adjust::Deref(None), target: ty_a }, | |
| 661 | 652 | Adjustment { |
| 662 | kind: Adjust::Deref(None), | |
| 663 | target: ty_a.to_chalk(self.interner()), | |
| 664 | }, | |
| 665 | Adjustment { | |
| 666 | kind: Adjust::Borrow(AutoBorrow::Ref( | |
| 667 | r_borrow.to_chalk(self.interner()), | |
| 668 | mutbl, | |
| 669 | )), | |
| 670 | target: Ty::new_ref(self.interner(), r_borrow, ty_a, mutbl_b) | |
| 671 | .to_chalk(self.interner()), | |
| 653 | kind: Adjust::Borrow(AutoBorrow::Ref(r_borrow, mutbl)), | |
| 654 | target: Ty::new_ref(self.interner(), r_borrow, ty_a, mutbl_b), | |
| 672 | 655 | }, |
| 673 | 656 | )) |
| 674 | 657 | } |
| ... | ... | @@ -676,20 +659,16 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> { |
| 676 | 659 | coerce_mutbls(mt_a, mt_b)?; |
| 677 | 660 | |
| 678 | 661 | Some(( |
| 662 | Adjustment { kind: Adjust::Deref(None), target: ty_a }, | |
| 679 | 663 | Adjustment { |
| 680 | kind: Adjust::Deref(None), | |
| 681 | target: ty_a.to_chalk(self.interner()), | |
| 682 | }, | |
| 683 | Adjustment { | |
| 684 | kind: Adjust::Borrow(AutoBorrow::RawPtr(mt_b.to_chalk(self.interner()))), | |
| 685 | target: Ty::new_ptr(self.interner(), ty_a, mt_b).to_chalk(self.interner()), | |
| 664 | kind: Adjust::Borrow(AutoBorrow::RawPtr(mt_b)), | |
| 665 | target: Ty::new_ptr(self.interner(), ty_a, mt_b), | |
| 686 | 666 | }, |
| 687 | 667 | )) |
| 688 | 668 | } |
| 689 | 669 | _ => None, |
| 690 | 670 | }; |
| 691 | let coerce_source = | |
| 692 | reborrow.as_ref().map_or(source, |(_, r)| r.target.to_nextsolver(self.interner())); | |
| 671 | let coerce_source = reborrow.as_ref().map_or(source, |(_, r)| r.target); | |
| 693 | 672 | |
| 694 | 673 | // Setup either a subtyping or a LUB relationship between |
| 695 | 674 | // the `CoerceUnsized` target type and the expected type. |
| ... | ... | @@ -834,7 +813,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> { |
| 834 | 813 | &mut self, |
| 835 | 814 | fn_ty_a: PolyFnSig<'db>, |
| 836 | 815 | b: Ty<'db>, |
| 837 | adjustment: Option<Adjust>, | |
| 816 | adjustment: Option<Adjust<'db>>, | |
| 838 | 817 | ) -> CoerceResult<'db> { |
| 839 | 818 | debug_assert!(self.table.shallow_resolve(b) == b); |
| 840 | 819 | |
| ... | ... | @@ -849,7 +828,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> { |
| 849 | 828 | b, |
| 850 | 829 | adjustment.map(|kind| Adjustment { |
| 851 | 830 | kind, |
| 852 | target: Ty::new_fn_ptr(this.interner(), fn_ty_a).to_chalk(this.interner()), | |
| 831 | target: Ty::new_fn_ptr(this.interner(), fn_ty_a), | |
| 853 | 832 | }), |
| 854 | 833 | Adjust::Pointer(PointerCast::UnsafeFnPointer), |
| 855 | 834 | ) |
| ... | ... | @@ -961,9 +940,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> { |
| 961 | 940 | pointer_ty, |
| 962 | 941 | b, |
| 963 | 942 | [], |
| 964 | Adjust::Pointer(PointerCast::ClosureFnPointer( | |
| 965 | safety.to_chalk(self.interner()), | |
| 966 | )), | |
| 943 | Adjust::Pointer(PointerCast::ClosureFnPointer(safety)), | |
| 967 | 944 | ) |
| 968 | 945 | } |
| 969 | 946 | _ => self.unify(a, b), |
| ... | ... | @@ -991,11 +968,8 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> { |
| 991 | 968 | self.unify_and( |
| 992 | 969 | a_raw, |
| 993 | 970 | b, |
| 994 | [Adjustment { | |
| 995 | kind: Adjust::Deref(None), | |
| 996 | target: mt_a.ty.to_chalk(self.interner()), | |
| 997 | }], | |
| 998 | Adjust::Borrow(AutoBorrow::RawPtr(mutbl_b.to_chalk(self.interner()))), | |
| 971 | [Adjustment { kind: Adjust::Deref(None), target: mt_a.ty }], | |
| 972 | Adjust::Borrow(AutoBorrow::RawPtr(mutbl_b)), | |
| 999 | 973 | ) |
| 1000 | 974 | } else if mt_a.mutbl != mutbl_b { |
| 1001 | 975 | self.unify_and(a_raw, b, [], Adjust::Pointer(PointerCast::MutToConstPointer)) |
| ... | ... | @@ -1011,7 +985,7 @@ pub(crate) enum CoerceNever { |
| 1011 | 985 | Yes, |
| 1012 | 986 | } |
| 1013 | 987 | |
| 1014 | impl<'db> InferenceContext<'db> { | |
| 988 | impl<'db> InferenceContext<'_, 'db> { | |
| 1015 | 989 | /// Attempt to coerce an expression to a type, and return the |
| 1016 | 990 | /// adjusted type of the expression, if successful. |
| 1017 | 991 | /// Adjustments are only recorded if the coercion succeeded. |
| ... | ... | @@ -1128,13 +1102,13 @@ impl<'db> InferenceContext<'db> { |
| 1128 | 1102 | // We have a LUB of prev_ty and new_ty, just return it. |
| 1129 | 1103 | Ok(ok) => return Ok(self.table.register_infer_ok(ok)), |
| 1130 | 1104 | Err(_) => ( |
| 1131 | Some(prev_ty.fn_sig(self.table.interner)), | |
| 1132 | Some(new_ty.fn_sig(self.table.interner)), | |
| 1105 | Some(prev_ty.fn_sig(self.table.interner())), | |
| 1106 | Some(new_ty.fn_sig(self.table.interner())), | |
| 1133 | 1107 | ), |
| 1134 | 1108 | } |
| 1135 | 1109 | } |
| 1136 | 1110 | (TyKind::Closure(_, args), TyKind::FnDef(..)) => { |
| 1137 | let b_sig = new_ty.fn_sig(self.table.interner); | |
| 1111 | let b_sig = new_ty.fn_sig(self.table.interner()); | |
| 1138 | 1112 | let a_sig = args.closure_sig_untupled().map_bound(|mut sig| { |
| 1139 | 1113 | sig.safety = b_sig.safety(); |
| 1140 | 1114 | sig |
| ... | ... | @@ -1142,7 +1116,7 @@ impl<'db> InferenceContext<'db> { |
| 1142 | 1116 | (Some(a_sig), Some(b_sig)) |
| 1143 | 1117 | } |
| 1144 | 1118 | (TyKind::FnDef(..), TyKind::Closure(_, args)) => { |
| 1145 | let a_sig = prev_ty.fn_sig(self.table.interner); | |
| 1119 | let a_sig = prev_ty.fn_sig(self.table.interner()); | |
| 1146 | 1120 | let b_sig = args.closure_sig_untupled().map_bound(|mut sig| { |
| 1147 | 1121 | sig.safety = a_sig.safety(); |
| 1148 | 1122 | sig |
| ... | ... | @@ -1166,36 +1140,30 @@ impl<'db> InferenceContext<'db> { |
| 1166 | 1140 | .map(|ok| self.table.register_infer_ok(ok))?; |
| 1167 | 1141 | |
| 1168 | 1142 | // Reify both sides and return the reified fn pointer type. |
| 1169 | let fn_ptr = Ty::new_fn_ptr(self.table.interner, sig); | |
| 1143 | let fn_ptr = Ty::new_fn_ptr(self.table.interner(), sig); | |
| 1170 | 1144 | let prev_adjustment = match prev_ty.kind() { |
| 1171 | TyKind::Closure(..) => Adjust::Pointer(PointerCast::ClosureFnPointer( | |
| 1172 | a_sig.safety().to_chalk(self.table.interner), | |
| 1173 | )), | |
| 1145 | TyKind::Closure(..) => { | |
| 1146 | Adjust::Pointer(PointerCast::ClosureFnPointer(a_sig.safety())) | |
| 1147 | } | |
| 1174 | 1148 | TyKind::FnDef(..) => Adjust::Pointer(PointerCast::ReifyFnPointer), |
| 1175 | 1149 | _ => panic!("should not try to coerce a {prev_ty:?} to a fn pointer"), |
| 1176 | 1150 | }; |
| 1177 | 1151 | let next_adjustment = match new_ty.kind() { |
| 1178 | TyKind::Closure(..) => Adjust::Pointer(PointerCast::ClosureFnPointer( | |
| 1179 | b_sig.safety().to_chalk(self.table.interner), | |
| 1180 | )), | |
| 1152 | TyKind::Closure(..) => { | |
| 1153 | Adjust::Pointer(PointerCast::ClosureFnPointer(b_sig.safety())) | |
| 1154 | } | |
| 1181 | 1155 | TyKind::FnDef(..) => Adjust::Pointer(PointerCast::ReifyFnPointer), |
| 1182 | 1156 | _ => panic!("should not try to coerce a {new_ty:?} to a fn pointer"), |
| 1183 | 1157 | }; |
| 1184 | 1158 | for &expr in exprs { |
| 1185 | 1159 | self.write_expr_adj( |
| 1186 | 1160 | expr, |
| 1187 | Box::new([Adjustment { | |
| 1188 | kind: prev_adjustment.clone(), | |
| 1189 | target: fn_ptr.to_chalk(self.table.interner), | |
| 1190 | }]), | |
| 1161 | Box::new([Adjustment { kind: prev_adjustment.clone(), target: fn_ptr }]), | |
| 1191 | 1162 | ); |
| 1192 | 1163 | } |
| 1193 | 1164 | self.write_expr_adj( |
| 1194 | 1165 | new, |
| 1195 | Box::new([Adjustment { | |
| 1196 | kind: next_adjustment, | |
| 1197 | target: fn_ptr.to_chalk(self.table.interner), | |
| 1198 | }]), | |
| 1166 | Box::new([Adjustment { kind: next_adjustment, target: fn_ptr }]), | |
| 1199 | 1167 | ); |
| 1200 | 1168 | return Ok(fn_ptr); |
| 1201 | 1169 | } |
| ... | ... | @@ -1382,7 +1350,7 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> { |
| 1382 | 1350 | /// if necessary. |
| 1383 | 1351 | pub(crate) fn coerce( |
| 1384 | 1352 | &mut self, |
| 1385 | icx: &mut InferenceContext<'db>, | |
| 1353 | icx: &mut InferenceContext<'_, 'db>, | |
| 1386 | 1354 | cause: &ObligationCause, |
| 1387 | 1355 | expression: ExprId, |
| 1388 | 1356 | expression_ty: Ty<'db>, |
| ... | ... | @@ -1404,19 +1372,12 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> { |
| 1404 | 1372 | /// removing a `;`). |
| 1405 | 1373 | pub(crate) fn coerce_forced_unit( |
| 1406 | 1374 | &mut self, |
| 1407 | icx: &mut InferenceContext<'db>, | |
| 1375 | icx: &mut InferenceContext<'_, 'db>, | |
| 1408 | 1376 | expr: ExprId, |
| 1409 | 1377 | cause: &ObligationCause, |
| 1410 | 1378 | label_unit_as_expected: bool, |
| 1411 | 1379 | ) { |
| 1412 | self.coerce_inner( | |
| 1413 | icx, | |
| 1414 | cause, | |
| 1415 | expr, | |
| 1416 | icx.result.standard_types.unit.to_nextsolver(icx.table.interner), | |
| 1417 | true, | |
| 1418 | label_unit_as_expected, | |
| 1419 | ) | |
| 1380 | self.coerce_inner(icx, cause, expr, icx.types.unit, true, label_unit_as_expected) | |
| 1420 | 1381 | } |
| 1421 | 1382 | |
| 1422 | 1383 | /// The inner coercion "engine". If `expression` is `None`, this |
| ... | ... | @@ -1424,7 +1385,7 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> { |
| 1424 | 1385 | /// `Nil`. |
| 1425 | 1386 | pub(crate) fn coerce_inner( |
| 1426 | 1387 | &mut self, |
| 1427 | icx: &mut InferenceContext<'db>, | |
| 1388 | icx: &mut InferenceContext<'_, 'db>, | |
| 1428 | 1389 | cause: &ObligationCause, |
| 1429 | 1390 | expression: ExprId, |
| 1430 | 1391 | mut expression_ty: Ty<'db>, |
| ... | ... | @@ -1533,20 +1494,14 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> { |
| 1533 | 1494 | // emit or provide suggestions on how to fix the initial error. |
| 1534 | 1495 | icx.set_tainted_by_errors(); |
| 1535 | 1496 | |
| 1536 | self.final_ty = Some(Ty::new_error(icx.table.interner, ErrorGuaranteed)); | |
| 1497 | self.final_ty = Some(icx.types.error); | |
| 1537 | 1498 | |
| 1538 | 1499 | icx.result.type_mismatches.insert( |
| 1539 | 1500 | expression.into(), |
| 1540 | 1501 | if label_expression_as_expected { |
| 1541 | TypeMismatch { | |
| 1542 | expected: found.to_chalk(icx.table.interner), | |
| 1543 | actual: expected.to_chalk(icx.table.interner), | |
| 1544 | } | |
| 1502 | TypeMismatch { expected: found, actual: expected } | |
| 1545 | 1503 | } else { |
| 1546 | TypeMismatch { | |
| 1547 | expected: expected.to_chalk(icx.table.interner), | |
| 1548 | actual: found.to_chalk(icx.table.interner), | |
| 1549 | } | |
| 1504 | TypeMismatch { expected, actual: found } | |
| 1550 | 1505 | }, |
| 1551 | 1506 | ); |
| 1552 | 1507 | } |
| ... | ... | @@ -1555,14 +1510,14 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> { |
| 1555 | 1510 | self.pushed += 1; |
| 1556 | 1511 | } |
| 1557 | 1512 | |
| 1558 | pub(crate) fn complete(self, icx: &mut InferenceContext<'db>) -> Ty<'db> { | |
| 1513 | pub(crate) fn complete(self, icx: &mut InferenceContext<'_, 'db>) -> Ty<'db> { | |
| 1559 | 1514 | if let Some(final_ty) = self.final_ty { |
| 1560 | 1515 | final_ty |
| 1561 | 1516 | } else { |
| 1562 | 1517 | // If we only had inputs that were of type `!` (or no |
| 1563 | 1518 | // inputs at all), then the final type is `!`. |
| 1564 | 1519 | assert_eq!(self.pushed, 0); |
| 1565 | icx.result.standard_types.never.to_nextsolver(icx.table.interner) | |
| 1520 | icx.types.never | |
| 1566 | 1521 | } |
| 1567 | 1522 | } |
| 1568 | 1523 | } |
| ... | ... | @@ -1570,7 +1525,7 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> { |
| 1570 | 1525 | pub fn could_coerce<'db>( |
| 1571 | 1526 | db: &'db dyn HirDatabase, |
| 1572 | 1527 | env: Arc<TraitEnvironment<'db>>, |
| 1573 | tys: &crate::Canonical<(crate::Ty, crate::Ty)>, | |
| 1528 | tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>, | |
| 1574 | 1529 | ) -> bool { |
| 1575 | 1530 | coerce(db, env, tys).is_ok() |
| 1576 | 1531 | } |
| ... | ... | @@ -1578,12 +1533,11 @@ pub fn could_coerce<'db>( |
| 1578 | 1533 | fn coerce<'db>( |
| 1579 | 1534 | db: &'db dyn HirDatabase, |
| 1580 | 1535 | env: Arc<TraitEnvironment<'db>>, |
| 1581 | tys: &crate::Canonical<(crate::Ty, crate::Ty)>, | |
| 1582 | ) -> Result<(Vec<Adjustment>, crate::Ty), TypeError<DbInterner<'db>>> { | |
| 1536 | tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>, | |
| 1537 | ) -> Result<(Vec<Adjustment<'db>>, Ty<'db>), TypeError<DbInterner<'db>>> { | |
| 1583 | 1538 | let mut table = InferenceTable::new(db, env); |
| 1584 | let vars = table.fresh_subst(tys.binders.as_slice(Interner)); | |
| 1585 | let ty1_with_vars = vars.apply(tys.value.0.clone(), Interner); | |
| 1586 | let ty2_with_vars = vars.apply(tys.value.1.clone(), Interner); | |
| 1539 | let interner = table.interner(); | |
| 1540 | let ((ty1_with_vars, ty2_with_vars), vars) = table.infer_ctxt.instantiate_canonical(tys); | |
| 1587 | 1541 | |
| 1588 | 1542 | let cause = ObligationCause::new(); |
| 1589 | 1543 | // FIXME: Target features. |
| ... | ... | @@ -1597,36 +1551,67 @@ fn coerce<'db>( |
| 1597 | 1551 | use_lub: false, |
| 1598 | 1552 | target_features: &mut || (&target_features, TargetFeatureIsSafeInTarget::No), |
| 1599 | 1553 | }; |
| 1600 | let InferOk { value: (adjustments, ty), obligations } = coerce.coerce( | |
| 1601 | ty1_with_vars.to_nextsolver(coerce.table.interner), | |
| 1602 | ty2_with_vars.to_nextsolver(coerce.table.interner), | |
| 1603 | )?; | |
| 1554 | let InferOk { value: (adjustments, ty), obligations } = | |
| 1555 | coerce.coerce(ty1_with_vars, ty2_with_vars)?; | |
| 1604 | 1556 | table.register_predicates(obligations); |
| 1605 | 1557 | |
| 1606 | 1558 | // default any type vars that weren't unified back to their original bound vars |
| 1607 | 1559 | // (kind of hacky) |
| 1608 | let find_var = |iv| { | |
| 1609 | vars.iter(Interner).position(|v| match v.interned() { | |
| 1610 | chalk_ir::GenericArgData::Ty(ty) => ty.inference_var(Interner), | |
| 1611 | chalk_ir::GenericArgData::Lifetime(lt) => lt.inference_var(Interner), | |
| 1612 | chalk_ir::GenericArgData::Const(c) => c.inference_var(Interner), | |
| 1613 | } == Some(iv)) | |
| 1560 | let mut fallback_ty = |debruijn, infer| { | |
| 1561 | let var = vars.var_values.iter().position(|arg| { | |
| 1562 | arg.as_type().is_some_and(|ty| match ty.kind() { | |
| 1563 | TyKind::Infer(it) => infer == it, | |
| 1564 | _ => false, | |
| 1565 | }) | |
| 1566 | }); | |
| 1567 | var.map_or_else( | |
| 1568 | || Ty::new_error(interner, ErrorGuaranteed), | |
| 1569 | |i| { | |
| 1570 | Ty::new_bound( | |
| 1571 | interner, | |
| 1572 | debruijn, | |
| 1573 | BoundTy { kind: BoundTyKind::Anon, var: BoundVar::from_usize(i) }, | |
| 1574 | ) | |
| 1575 | }, | |
| 1576 | ) | |
| 1577 | }; | |
| 1578 | let mut fallback_const = |debruijn, infer| { | |
| 1579 | let var = vars.var_values.iter().position(|arg| { | |
| 1580 | arg.as_const().is_some_and(|ty| match ty.kind() { | |
| 1581 | ConstKind::Infer(it) => infer == it, | |
| 1582 | _ => false, | |
| 1583 | }) | |
| 1584 | }); | |
| 1585 | var.map_or_else( | |
| 1586 | || Const::new_error(interner, ErrorGuaranteed), | |
| 1587 | |i| Const::new_bound(interner, debruijn, BoundConst { var: BoundVar::from_usize(i) }), | |
| 1588 | ) | |
| 1614 | 1589 | }; |
| 1615 | let fallback = |iv, kind, binder| match kind { | |
| 1616 | chalk_ir::VariableKind::Ty(_ty_kind) => find_var(iv).map_or_else( | |
| 1617 | || chalk_ir::TyKind::Error.intern(Interner).cast(Interner), | |
| 1618 | |i| crate::BoundVar::new(binder, i).to_ty(Interner).cast(Interner), | |
| 1619 | ), | |
| 1620 | chalk_ir::VariableKind::Lifetime => find_var(iv).map_or_else( | |
| 1621 | || crate::LifetimeData::Error.intern(Interner).cast(Interner), | |
| 1622 | |i| crate::BoundVar::new(binder, i).to_lifetime(Interner).cast(Interner), | |
| 1623 | ), | |
| 1624 | chalk_ir::VariableKind::Const(ty) => find_var(iv).map_or_else( | |
| 1625 | || crate::unknown_const(ty.clone()).cast(Interner), | |
| 1626 | |i| crate::BoundVar::new(binder, i).to_const(Interner, ty.clone()).cast(Interner), | |
| 1627 | ), | |
| 1590 | let mut fallback_region = |debruijn, infer| { | |
| 1591 | let var = vars.var_values.iter().position(|arg| { | |
| 1592 | arg.as_region().is_some_and(|ty| match ty.kind() { | |
| 1593 | RegionKind::ReVar(it) => infer == it, | |
| 1594 | _ => false, | |
| 1595 | }) | |
| 1596 | }); | |
| 1597 | var.map_or_else( | |
| 1598 | || Region::error(interner), | |
| 1599 | |i| { | |
| 1600 | Region::new_bound( | |
| 1601 | interner, | |
| 1602 | debruijn, | |
| 1603 | BoundRegion { kind: BoundRegionKind::Anon, var: BoundVar::from_usize(i) }, | |
| 1604 | ) | |
| 1605 | }, | |
| 1606 | ) | |
| 1628 | 1607 | }; |
| 1629 | 1608 | // FIXME also map the types in the adjustments |
| 1630 | 1609 | // FIXME: We don't fallback correctly since this is done on `InferenceContext` and we only have `InferenceTable`. |
| 1631 | Ok((adjustments, table.resolve_with_fallback(ty.to_chalk(table.interner), &fallback))) | |
| 1610 | let ty = table.resolve_with_fallback( | |
| 1611 | ty, | |
| 1612 | &mut fallback_ty, | |
| 1613 | &mut fallback_const, | |
| 1614 | &mut fallback_region, | |
| 1615 | ); | |
| 1616 | Ok((adjustments, ty)) | |
| 1632 | 1617 | } |
src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs+23-23| ... | ... | @@ -12,11 +12,11 @@ use hir_def::expr_store::path::Path; |
| 12 | 12 | use hir_def::{hir::ExprOrPatId, resolver::Resolver}; |
| 13 | 13 | use la_arena::{Idx, RawIdx}; |
| 14 | 14 | |
| 15 | use crate::lower::LifetimeElisionKind; | |
| 16 | 15 | use crate::{ |
| 17 | InferenceDiagnostic, InferenceTyDiagnosticSource, TyLoweringContext, TyLoweringDiagnostic, | |
| 16 | InferenceDiagnostic, InferenceTyDiagnosticSource, TyLoweringDiagnostic, | |
| 18 | 17 | db::HirDatabase, |
| 19 | lower::path::{PathDiagnosticCallback, PathLoweringContext}, | |
| 18 | lower_nextsolver::path::{PathDiagnosticCallback, PathLoweringContext}, | |
| 19 | lower_nextsolver::{LifetimeElisionKind, TyLoweringContext}, | |
| 20 | 20 | }; |
| 21 | 21 | |
| 22 | 22 | // Unfortunately, this struct needs to use interior mutability (but we encapsulate it) |
| ... | ... | @@ -24,10 +24,10 @@ use crate::{ |
| 24 | 24 | // to our resolver and so we cannot have mutable reference, but we really want to have |
| 25 | 25 | // ability to dispatch diagnostics during this work otherwise the code becomes a complete mess. |
| 26 | 26 | #[derive(Debug, Default, Clone)] |
| 27 | pub(super) struct Diagnostics(RefCell<Vec<InferenceDiagnostic>>); | |
| 27 | pub(super) struct Diagnostics<'db>(RefCell<Vec<InferenceDiagnostic<'db>>>); | |
| 28 | 28 | |
| 29 | impl Diagnostics { | |
| 30 | pub(super) fn push(&self, diagnostic: InferenceDiagnostic) { | |
| 29 | impl<'db> Diagnostics<'db> { | |
| 30 | pub(super) fn push(&self, diagnostic: InferenceDiagnostic<'db>) { | |
| 31 | 31 | self.0.borrow_mut().push(diagnostic); |
| 32 | 32 | } |
| 33 | 33 | |
| ... | ... | @@ -41,32 +41,32 @@ impl Diagnostics { |
| 41 | 41 | ); |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | pub(super) fn finish(self) -> Vec<InferenceDiagnostic> { | |
| 44 | pub(super) fn finish(self) -> Vec<InferenceDiagnostic<'db>> { | |
| 45 | 45 | self.0.into_inner() |
| 46 | 46 | } |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | pub(crate) struct PathDiagnosticCallbackData<'a> { | |
| 49 | pub(crate) struct PathDiagnosticCallbackData<'a, 'db> { | |
| 50 | 50 | node: ExprOrPatId, |
| 51 | diagnostics: &'a Diagnostics, | |
| 51 | diagnostics: &'a Diagnostics<'db>, | |
| 52 | 52 | } |
| 53 | 53 | |
| 54 | pub(super) struct InferenceTyLoweringContext<'a> { | |
| 55 | ctx: TyLoweringContext<'a>, | |
| 56 | diagnostics: &'a Diagnostics, | |
| 54 | pub(super) struct InferenceTyLoweringContext<'db, 'a> { | |
| 55 | ctx: TyLoweringContext<'db, 'a>, | |
| 56 | diagnostics: &'a Diagnostics<'db>, | |
| 57 | 57 | source: InferenceTyDiagnosticSource, |
| 58 | 58 | } |
| 59 | 59 | |
| 60 | impl<'a> InferenceTyLoweringContext<'a> { | |
| 60 | impl<'db, 'a> InferenceTyLoweringContext<'db, 'a> { | |
| 61 | 61 | #[inline] |
| 62 | 62 | pub(super) fn new( |
| 63 | db: &'a dyn HirDatabase, | |
| 64 | resolver: &'a Resolver<'_>, | |
| 63 | db: &'db dyn HirDatabase, | |
| 64 | resolver: &'a Resolver<'db>, | |
| 65 | 65 | store: &'a ExpressionStore, |
| 66 | diagnostics: &'a Diagnostics, | |
| 66 | diagnostics: &'a Diagnostics<'db>, | |
| 67 | 67 | source: InferenceTyDiagnosticSource, |
| 68 | 68 | generic_def: GenericDefId, |
| 69 | lifetime_elision: LifetimeElisionKind, | |
| 69 | lifetime_elision: LifetimeElisionKind<'db>, | |
| 70 | 70 | ) -> Self { |
| 71 | 71 | Self { |
| 72 | 72 | ctx: TyLoweringContext::new(db, resolver, store, generic_def, lifetime_elision), |
| ... | ... | @@ -80,7 +80,7 @@ impl<'a> InferenceTyLoweringContext<'a> { |
| 80 | 80 | &'b mut self, |
| 81 | 81 | path: &'b Path, |
| 82 | 82 | node: ExprOrPatId, |
| 83 | ) -> PathLoweringContext<'b, 'a> { | |
| 83 | ) -> PathLoweringContext<'b, 'a, 'db> { | |
| 84 | 84 | let on_diagnostic = PathDiagnosticCallback { |
| 85 | 85 | data: Either::Right(PathDiagnosticCallbackData { diagnostics: self.diagnostics, node }), |
| 86 | 86 | callback: |data, _, diag| { |
| ... | ... | @@ -96,7 +96,7 @@ impl<'a> InferenceTyLoweringContext<'a> { |
| 96 | 96 | pub(super) fn at_path_forget_diagnostics<'b>( |
| 97 | 97 | &'b mut self, |
| 98 | 98 | path: &'b Path, |
| 99 | ) -> PathLoweringContext<'b, 'a> { | |
| 99 | ) -> PathLoweringContext<'b, 'a, 'db> { | |
| 100 | 100 | let on_diagnostic = PathDiagnosticCallback { |
| 101 | 101 | data: Either::Right(PathDiagnosticCallbackData { |
| 102 | 102 | diagnostics: self.diagnostics, |
| ... | ... | @@ -113,8 +113,8 @@ impl<'a> InferenceTyLoweringContext<'a> { |
| 113 | 113 | } |
| 114 | 114 | } |
| 115 | 115 | |
| 116 | impl<'a> Deref for InferenceTyLoweringContext<'a> { | |
| 117 | type Target = TyLoweringContext<'a>; | |
| 116 | impl<'db, 'a> Deref for InferenceTyLoweringContext<'db, 'a> { | |
| 117 | type Target = TyLoweringContext<'db, 'a>; | |
| 118 | 118 | |
| 119 | 119 | #[inline] |
| 120 | 120 | fn deref(&self) -> &Self::Target { |
| ... | ... | @@ -122,14 +122,14 @@ impl<'a> Deref for InferenceTyLoweringContext<'a> { |
| 122 | 122 | } |
| 123 | 123 | } |
| 124 | 124 | |
| 125 | impl DerefMut for InferenceTyLoweringContext<'_> { | |
| 125 | impl DerefMut for InferenceTyLoweringContext<'_, '_> { | |
| 126 | 126 | #[inline] |
| 127 | 127 | fn deref_mut(&mut self) -> &mut Self::Target { |
| 128 | 128 | &mut self.ctx |
| 129 | 129 | } |
| 130 | 130 | } |
| 131 | 131 | |
| 132 | impl Drop for InferenceTyLoweringContext<'_> { | |
| 132 | impl Drop for InferenceTyLoweringContext<'_, '_> { | |
| 133 | 133 | #[inline] |
| 134 | 134 | fn drop(&mut self) { |
| 135 | 135 | self.diagnostics |
src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs+531-707| ... | ... | @@ -2,12 +2,11 @@ |
| 2 | 2 | |
| 3 | 3 | use std::{iter::repeat_with, mem}; |
| 4 | 4 | |
| 5 | use chalk_ir::{DebruijnIndex, Mutability, TyVariableKind, cast::Cast}; | |
| 6 | 5 | use either::Either; |
| 7 | 6 | use hir_def::hir::ClosureKind; |
| 8 | 7 | use hir_def::{ |
| 9 | 8 | BlockId, FieldId, GenericDefId, GenericParamId, ItemContainerId, Lookup, TupleFieldId, TupleId, |
| 10 | expr_store::path::{GenericArg, GenericArgs, Path}, | |
| 9 | expr_store::path::{GenericArg as HirGenericArg, GenericArgs as HirGenericArgs, Path}, | |
| 11 | 10 | hir::{ |
| 12 | 11 | ArithOp, Array, AsmOperand, AsmOptions, BinaryOp, Expr, ExprId, ExprOrPatId, LabelId, |
| 13 | 12 | Literal, Pat, PatId, Statement, UnaryOp, generics::GenericParamDataRef, |
| ... | ... | @@ -17,19 +16,19 @@ use hir_def::{ |
| 17 | 16 | }; |
| 18 | 17 | use hir_expand::name::Name; |
| 19 | 18 | use intern::sym; |
| 20 | use rustc_type_ir::inherent::{AdtDef, IntoKind, SliceLike, Ty as _}; | |
| 21 | use stdx::always; | |
| 19 | use rustc_ast_ir::Mutability; | |
| 20 | use rustc_type_ir::{ | |
| 21 | AliasTyKind, InferTy, Interner, | |
| 22 | inherent::{AdtDef, GenericArgs as _, IntoKind, SliceLike, Ty as _}, | |
| 23 | }; | |
| 22 | 24 | use syntax::ast::RangeOp; |
| 23 | 25 | use tracing::debug; |
| 24 | 26 | |
| 25 | use crate::autoderef::overloaded_deref_ty; | |
| 26 | use crate::next_solver::infer::DefineOpaqueTypes; | |
| 27 | use crate::next_solver::obligation_ctxt::ObligationCtxt; | |
| 28 | use crate::next_solver::{DbInterner, ErrorGuaranteed}; | |
| 29 | 27 | use crate::{ |
| 30 | Adjust, Adjustment, AdtId, AutoBorrow, CallableDefId, CallableSig, DeclContext, DeclOrigin, | |
| 31 | IncorrectGenericsLenKind, Interner, LifetimeElisionKind, Rawness, Scalar, Substitution, | |
| 32 | TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, TyKind, consteval, | |
| 28 | Adjust, Adjustment, AutoBorrow, CallableDefId, DeclContext, DeclOrigin, | |
| 29 | IncorrectGenericsLenKind, Rawness, TraitEnvironment, | |
| 30 | autoderef::overloaded_deref_ty, | |
| 31 | consteval, | |
| 33 | 32 | generics::generics, |
| 34 | 33 | infer::{ |
| 35 | 34 | AllowTwoPhase, BreakableKind, |
| ... | ... | @@ -38,18 +37,20 @@ use crate::{ |
| 38 | 37 | pat::contains_explicit_ref_binding, |
| 39 | 38 | }, |
| 40 | 39 | lang_items::lang_items_for_bin_op, |
| 41 | lower::{ | |
| 42 | ParamLoweringMode, lower_to_chalk_mutability, | |
| 40 | lower_nextsolver::{ | |
| 41 | LifetimeElisionKind, lower_mutability, | |
| 43 | 42 | path::{GenericArgsLowerer, TypeLikeConst, substs_from_args_and_bindings}, |
| 44 | 43 | }, |
| 45 | mapping::{ToChalk, from_chalk}, | |
| 46 | 44 | method_resolution::{self, VisibleFromModule}, |
| 47 | 45 | next_solver::{ |
| 48 | infer::traits::ObligationCause, | |
| 49 | mapping::{ChalkToNextSolver, NextSolverToChalk}, | |
| 46 | AliasTy, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, TraitRef, Ty, TyKind, | |
| 47 | TypeError, | |
| 48 | infer::{ | |
| 49 | DefineOpaqueTypes, InferOk, | |
| 50 | traits::{Obligation, ObligationCause}, | |
| 51 | }, | |
| 52 | obligation_ctxt::ObligationCtxt, | |
| 50 | 53 | }, |
| 51 | primitive::{self, UintTy}, | |
| 52 | static_lifetime, to_chalk_trait_id, | |
| 53 | 54 | traits::FnTrait, |
| 54 | 55 | }; |
| 55 | 56 | |
| ... | ... | @@ -64,27 +65,30 @@ pub(crate) enum ExprIsRead { |
| 64 | 65 | No, |
| 65 | 66 | } |
| 66 | 67 | |
| 67 | impl<'db> InferenceContext<'db> { | |
| 68 | impl<'db> InferenceContext<'_, 'db> { | |
| 68 | 69 | pub(crate) fn infer_expr( |
| 69 | 70 | &mut self, |
| 70 | 71 | tgt_expr: ExprId, |
| 71 | expected: &Expectation, | |
| 72 | expected: &Expectation<'db>, | |
| 72 | 73 | is_read: ExprIsRead, |
| 73 | ) -> Ty { | |
| 74 | ) -> Ty<'db> { | |
| 74 | 75 | let ty = self.infer_expr_inner(tgt_expr, expected, is_read); |
| 75 | 76 | if let Some(expected_ty) = expected.only_has_type(&mut self.table) { |
| 76 | let could_unify = self.unify(&ty, &expected_ty); | |
| 77 | let could_unify = self.unify(ty, expected_ty); | |
| 77 | 78 | if !could_unify { |
| 78 | self.result.type_mismatches.insert( | |
| 79 | tgt_expr.into(), | |
| 80 | TypeMismatch { expected: expected_ty, actual: ty.clone() }, | |
| 81 | ); | |
| 79 | self.result | |
| 80 | .type_mismatches | |
| 81 | .insert(tgt_expr.into(), TypeMismatch { expected: expected_ty, actual: ty }); | |
| 82 | 82 | } |
| 83 | 83 | } |
| 84 | 84 | ty |
| 85 | 85 | } |
| 86 | 86 | |
| 87 | pub(crate) fn infer_expr_no_expect(&mut self, tgt_expr: ExprId, is_read: ExprIsRead) -> Ty { | |
| 87 | pub(crate) fn infer_expr_no_expect( | |
| 88 | &mut self, | |
| 89 | tgt_expr: ExprId, | |
| 90 | is_read: ExprIsRead, | |
| 91 | ) -> Ty<'db> { | |
| 88 | 92 | self.infer_expr_inner(tgt_expr, &Expectation::None, is_read) |
| 89 | 93 | } |
| 90 | 94 | |
| ... | ... | @@ -93,9 +97,9 @@ impl<'db> InferenceContext<'db> { |
| 93 | 97 | pub(super) fn infer_expr_coerce( |
| 94 | 98 | &mut self, |
| 95 | 99 | expr: ExprId, |
| 96 | expected: &Expectation, | |
| 100 | expected: &Expectation<'db>, | |
| 97 | 101 | is_read: ExprIsRead, |
| 98 | ) -> Ty { | |
| 102 | ) -> Ty<'db> { | |
| 99 | 103 | let ty = self.infer_expr_inner(expr, expected, is_read); |
| 100 | 104 | if let Some(target) = expected.only_has_type(&mut self.table) { |
| 101 | 105 | let coerce_never = if self.expr_guaranteed_to_constitute_read_for_never(expr, is_read) { |
| ... | ... | @@ -103,19 +107,12 @@ impl<'db> InferenceContext<'db> { |
| 103 | 107 | } else { |
| 104 | 108 | CoerceNever::No |
| 105 | 109 | }; |
| 106 | match self.coerce( | |
| 107 | expr.into(), | |
| 108 | ty.to_nextsolver(self.table.interner), | |
| 109 | target.to_nextsolver(self.table.interner), | |
| 110 | AllowTwoPhase::No, | |
| 111 | coerce_never, | |
| 112 | ) { | |
| 113 | Ok(res) => res.to_chalk(self.table.interner), | |
| 110 | match self.coerce(expr.into(), ty, target, AllowTwoPhase::No, coerce_never) { | |
| 111 | Ok(res) => res, | |
| 114 | 112 | Err(_) => { |
| 115 | self.result.type_mismatches.insert( | |
| 116 | expr.into(), | |
| 117 | TypeMismatch { expected: target.clone(), actual: ty.clone() }, | |
| 118 | ); | |
| 113 | self.result | |
| 114 | .type_mismatches | |
| 115 | .insert(expr.into(), TypeMismatch { expected: target, actual: ty }); | |
| 119 | 116 | target |
| 120 | 117 | } |
| 121 | 118 | } |
| ... | ... | @@ -255,42 +252,34 @@ impl<'db> InferenceContext<'db> { |
| 255 | 252 | fn infer_expr_coerce_never( |
| 256 | 253 | &mut self, |
| 257 | 254 | expr: ExprId, |
| 258 | expected: &Expectation, | |
| 255 | expected: &Expectation<'db>, | |
| 259 | 256 | is_read: ExprIsRead, |
| 260 | ) -> Ty { | |
| 257 | ) -> Ty<'db> { | |
| 261 | 258 | let ty = self.infer_expr_inner(expr, expected, is_read); |
| 262 | 259 | // While we don't allow *arbitrary* coercions here, we *do* allow |
| 263 | 260 | // coercions from `!` to `expected`. |
| 264 | 261 | if ty.is_never() { |
| 265 | 262 | if let Some(adjustments) = self.result.expr_adjustments.get(&expr) { |
| 266 | 263 | return if let [Adjustment { kind: Adjust::NeverToAny, target }] = &**adjustments { |
| 267 | target.clone() | |
| 264 | *target | |
| 268 | 265 | } else { |
| 269 | 266 | self.err_ty() |
| 270 | 267 | }; |
| 271 | 268 | } |
| 272 | 269 | |
| 273 | 270 | if let Some(target) = expected.only_has_type(&mut self.table) { |
| 274 | self.coerce( | |
| 275 | expr.into(), | |
| 276 | ty.to_nextsolver(self.table.interner), | |
| 277 | target.to_nextsolver(self.table.interner), | |
| 278 | AllowTwoPhase::No, | |
| 279 | CoerceNever::Yes, | |
| 280 | ) | |
| 281 | .expect("never-to-any coercion should always succeed") | |
| 282 | .to_chalk(self.table.interner) | |
| 271 | self.coerce(expr.into(), ty, target, AllowTwoPhase::No, CoerceNever::Yes) | |
| 272 | .expect("never-to-any coercion should always succeed") | |
| 283 | 273 | } else { |
| 284 | 274 | ty |
| 285 | 275 | } |
| 286 | 276 | } else { |
| 287 | 277 | if let Some(expected_ty) = expected.only_has_type(&mut self.table) { |
| 288 | let could_unify = self.unify(&ty, &expected_ty); | |
| 278 | let could_unify = self.unify(ty, expected_ty); | |
| 289 | 279 | if !could_unify { |
| 290 | self.result.type_mismatches.insert( | |
| 291 | expr.into(), | |
| 292 | TypeMismatch { expected: expected_ty, actual: ty.clone() }, | |
| 293 | ); | |
| 280 | self.result | |
| 281 | .type_mismatches | |
| 282 | .insert(expr.into(), TypeMismatch { expected: expected_ty, actual: ty }); | |
| 294 | 283 | } |
| 295 | 284 | } |
| 296 | 285 | ty |
| ... | ... | @@ -301,9 +290,9 @@ impl<'db> InferenceContext<'db> { |
| 301 | 290 | fn infer_expr_inner( |
| 302 | 291 | &mut self, |
| 303 | 292 | tgt_expr: ExprId, |
| 304 | expected: &Expectation, | |
| 293 | expected: &Expectation<'db>, | |
| 305 | 294 | is_read: ExprIsRead, |
| 306 | ) -> Ty { | |
| 295 | ) -> Ty<'db> { | |
| 307 | 296 | self.db.unwind_if_revision_cancelled(); |
| 308 | 297 | |
| 309 | 298 | let expr = &self.body[tgt_expr]; |
| ... | ... | @@ -314,7 +303,7 @@ impl<'db> InferenceContext<'db> { |
| 314 | 303 | let expected = &expected.adjust_for_branches(&mut self.table); |
| 315 | 304 | self.infer_expr_coerce_never( |
| 316 | 305 | condition, |
| 317 | &Expectation::HasType(self.result.standard_types.bool_.clone()), | |
| 306 | &Expectation::HasType(self.types.bool), | |
| 318 | 307 | ExprIsRead::Yes, |
| 319 | 308 | ); |
| 320 | 309 | |
| ... | ... | @@ -327,27 +316,15 @@ impl<'db> InferenceContext<'db> { |
| 327 | 316 | coercion_sites[1] = else_branch; |
| 328 | 317 | } |
| 329 | 318 | let mut coerce = CoerceMany::with_coercion_sites( |
| 330 | expected | |
| 331 | .coercion_target_type(&mut self.table) | |
| 332 | .to_nextsolver(self.table.interner), | |
| 319 | expected.coercion_target_type(&mut self.table), | |
| 333 | 320 | &coercion_sites, |
| 334 | 321 | ); |
| 335 | coerce.coerce( | |
| 336 | self, | |
| 337 | &ObligationCause::new(), | |
| 338 | then_branch, | |
| 339 | then_ty.to_nextsolver(self.table.interner), | |
| 340 | ); | |
| 322 | coerce.coerce(self, &ObligationCause::new(), then_branch, then_ty); | |
| 341 | 323 | match else_branch { |
| 342 | 324 | Some(else_branch) => { |
| 343 | 325 | let else_ty = self.infer_expr_inner(else_branch, expected, ExprIsRead::Yes); |
| 344 | 326 | let else_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); |
| 345 | coerce.coerce( | |
| 346 | self, | |
| 347 | &ObligationCause::new(), | |
| 348 | else_branch, | |
| 349 | else_ty.to_nextsolver(self.table.interner), | |
| 350 | ); | |
| 327 | coerce.coerce(self, &ObligationCause::new(), else_branch, else_ty); | |
| 351 | 328 | self.diverges = condition_diverges | then_diverges & else_diverges; |
| 352 | 329 | } |
| 353 | 330 | None => { |
| ... | ... | @@ -356,7 +333,7 @@ impl<'db> InferenceContext<'db> { |
| 356 | 333 | } |
| 357 | 334 | } |
| 358 | 335 | |
| 359 | coerce.complete(self).to_chalk(self.table.interner) | |
| 336 | coerce.complete(self) | |
| 360 | 337 | } |
| 361 | 338 | &Expr::Let { pat, expr } => { |
| 362 | 339 | let child_is_read = if self.pat_guaranteed_to_constitute_read_for_never(pat) { |
| ... | ... | @@ -367,10 +344,10 @@ impl<'db> InferenceContext<'db> { |
| 367 | 344 | let input_ty = self.infer_expr(expr, &Expectation::none(), child_is_read); |
| 368 | 345 | self.infer_top_pat( |
| 369 | 346 | pat, |
| 370 | &input_ty, | |
| 347 | input_ty, | |
| 371 | 348 | Some(DeclContext { origin: DeclOrigin::LetExpr }), |
| 372 | 349 | ); |
| 373 | self.result.standard_types.bool_.clone() | |
| 350 | self.types.bool | |
| 374 | 351 | } |
| 375 | 352 | Expr::Block { statements, tail, label, id } => { |
| 376 | 353 | self.infer_block(tgt_expr, *id, statements, *tail, *label, expected) |
| ... | ... | @@ -390,12 +367,12 @@ impl<'db> InferenceContext<'db> { |
| 390 | 367 | &Expr::Loop { body, label } => { |
| 391 | 368 | // FIXME: should be: |
| 392 | 369 | // let ty = expected.coercion_target_type(&mut self.table); |
| 393 | let ty = self.table.new_type_var(); | |
| 370 | let ty = self.table.next_ty_var(); | |
| 394 | 371 | let (breaks, ()) = |
| 395 | 372 | self.with_breakable_ctx(BreakableKind::Loop, Some(ty), label, |this| { |
| 396 | 373 | this.infer_expr( |
| 397 | 374 | body, |
| 398 | &Expectation::HasType(TyBuilder::unit()), | |
| 375 | &Expectation::HasType(this.types.unit), | |
| 399 | 376 | ExprIsRead::Yes, |
| 400 | 377 | ); |
| 401 | 378 | }); |
| ... | ... | @@ -405,7 +382,7 @@ impl<'db> InferenceContext<'db> { |
| 405 | 382 | self.diverges = Diverges::Maybe; |
| 406 | 383 | breaks |
| 407 | 384 | } |
| 408 | None => self.result.standard_types.never.clone(), | |
| 385 | None => self.types.never, | |
| 409 | 386 | } |
| 410 | 387 | } |
| 411 | 388 | Expr::Closure { body, args, ret_type, arg_types, closure_kind, capture_by: _ } => self |
| ... | ... | @@ -438,32 +415,30 @@ impl<'db> InferenceContext<'db> { |
| 438 | 415 | |
| 439 | 416 | if arms.is_empty() { |
| 440 | 417 | self.diverges = Diverges::Always; |
| 441 | self.result.standard_types.never.clone() | |
| 418 | self.types.never | |
| 442 | 419 | } else { |
| 443 | 420 | let matchee_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); |
| 444 | 421 | let mut all_arms_diverge = Diverges::Always; |
| 445 | 422 | for arm in arms.iter() { |
| 446 | let input_ty = self.table.structurally_resolve_type(&input_ty); | |
| 447 | self.infer_top_pat(arm.pat, &input_ty, None); | |
| 423 | let input_ty = self.table.structurally_resolve_type(input_ty); | |
| 424 | self.infer_top_pat(arm.pat, input_ty, None); | |
| 448 | 425 | } |
| 449 | 426 | |
| 450 | 427 | let expected = expected.adjust_for_branches(&mut self.table); |
| 451 | 428 | let result_ty = match &expected { |
| 452 | 429 | // We don't coerce to `()` so that if the match expression is a |
| 453 | 430 | // statement it's branches can have any consistent type. |
| 454 | Expectation::HasType(ty) if *ty != self.result.standard_types.unit => { | |
| 455 | ty.clone() | |
| 456 | } | |
| 457 | _ => self.table.new_type_var(), | |
| 431 | Expectation::HasType(ty) if *ty != self.types.unit => *ty, | |
| 432 | _ => self.table.next_ty_var(), | |
| 458 | 433 | }; |
| 459 | let mut coerce = CoerceMany::new(result_ty.to_nextsolver(self.table.interner)); | |
| 434 | let mut coerce = CoerceMany::new(result_ty); | |
| 460 | 435 | |
| 461 | 436 | for arm in arms.iter() { |
| 462 | 437 | if let Some(guard_expr) = arm.guard { |
| 463 | 438 | self.diverges = Diverges::Maybe; |
| 464 | 439 | self.infer_expr_coerce_never( |
| 465 | 440 | guard_expr, |
| 466 | &Expectation::HasType(self.result.standard_types.bool_.clone()), | |
| 441 | &Expectation::HasType(self.types.bool), | |
| 467 | 442 | ExprIsRead::Yes, |
| 468 | 443 | ); |
| 469 | 444 | } |
| ... | ... | @@ -471,17 +446,12 @@ impl<'db> InferenceContext<'db> { |
| 471 | 446 | |
| 472 | 447 | let arm_ty = self.infer_expr_inner(arm.expr, &expected, ExprIsRead::Yes); |
| 473 | 448 | all_arms_diverge &= self.diverges; |
| 474 | coerce.coerce( | |
| 475 | self, | |
| 476 | &ObligationCause::new(), | |
| 477 | arm.expr, | |
| 478 | arm_ty.to_nextsolver(self.table.interner), | |
| 479 | ); | |
| 449 | coerce.coerce(self, &ObligationCause::new(), arm.expr, arm_ty); | |
| 480 | 450 | } |
| 481 | 451 | |
| 482 | 452 | self.diverges = matchee_diverges | all_arms_diverge; |
| 483 | 453 | |
| 484 | coerce.complete(self).to_chalk(self.table.interner) | |
| 454 | coerce.complete(self) | |
| 485 | 455 | } |
| 486 | 456 | } |
| 487 | 457 | Expr::Path(p) => self.infer_expr_path(p, tgt_expr.into(), tgt_expr), |
| ... | ... | @@ -493,13 +463,13 @@ impl<'db> InferenceContext<'db> { |
| 493 | 463 | bad_value_break: false, |
| 494 | 464 | }); |
| 495 | 465 | }; |
| 496 | self.result.standard_types.never.clone() | |
| 466 | self.types.never | |
| 497 | 467 | } |
| 498 | 468 | &Expr::Break { expr, label } => { |
| 499 | 469 | let val_ty = if let Some(expr) = expr { |
| 500 | 470 | let opt_coerce_to = match find_breakable(&mut self.breakables, label) { |
| 501 | 471 | Some(ctxt) => match &ctxt.coerce { |
| 502 | Some(coerce) => coerce.expected_ty().to_chalk(self.table.interner), | |
| 472 | Some(coerce) => coerce.expected_ty(), | |
| 503 | 473 | None => { |
| 504 | 474 | self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop { |
| 505 | 475 | expr: tgt_expr, |
| ... | ... | @@ -517,7 +487,7 @@ impl<'db> InferenceContext<'db> { |
| 517 | 487 | ExprIsRead::Yes, |
| 518 | 488 | ) |
| 519 | 489 | } else { |
| 520 | TyBuilder::unit() | |
| 490 | self.types.unit | |
| 521 | 491 | }; |
| 522 | 492 | |
| 523 | 493 | match find_breakable(&mut self.breakables, label) { |
| ... | ... | @@ -527,7 +497,7 @@ impl<'db> InferenceContext<'db> { |
| 527 | 497 | self, |
| 528 | 498 | &ObligationCause::new(), |
| 529 | 499 | expr.unwrap_or(tgt_expr), |
| 530 | val_ty.to_nextsolver(self.table.interner), | |
| 500 | val_ty, | |
| 531 | 501 | ); |
| 532 | 502 | |
| 533 | 503 | // Avoiding borrowck |
| ... | ... | @@ -546,12 +516,12 @@ impl<'db> InferenceContext<'db> { |
| 546 | 516 | }); |
| 547 | 517 | } |
| 548 | 518 | } |
| 549 | self.result.standard_types.never.clone() | |
| 519 | self.types.never | |
| 550 | 520 | } |
| 551 | 521 | &Expr::Return { expr } => self.infer_expr_return(tgt_expr, expr), |
| 552 | 522 | &Expr::Become { expr } => self.infer_expr_become(expr), |
| 553 | 523 | Expr::Yield { expr } => { |
| 554 | if let Some((resume_ty, yield_ty)) = self.resume_yield_tys.clone() { | |
| 524 | if let Some((resume_ty, yield_ty)) = self.resume_yield_tys { | |
| 555 | 525 | if let Some(expr) = expr { |
| 556 | 526 | self.infer_expr_coerce( |
| 557 | 527 | *expr, |
| ... | ... | @@ -559,11 +529,11 @@ impl<'db> InferenceContext<'db> { |
| 559 | 529 | ExprIsRead::Yes, |
| 560 | 530 | ); |
| 561 | 531 | } else { |
| 562 | let unit = self.result.standard_types.unit.clone(); | |
| 532 | let unit = self.types.unit; | |
| 563 | 533 | let _ = self.coerce( |
| 564 | 534 | tgt_expr.into(), |
| 565 | unit.to_nextsolver(self.table.interner), | |
| 566 | yield_ty.to_nextsolver(self.table.interner), | |
| 535 | unit, | |
| 536 | yield_ty, | |
| 567 | 537 | AllowTwoPhase::No, |
| 568 | 538 | CoerceNever::Yes, |
| 569 | 539 | ); |
| ... | ... | @@ -571,33 +541,30 @@ impl<'db> InferenceContext<'db> { |
| 571 | 541 | resume_ty |
| 572 | 542 | } else { |
| 573 | 543 | // FIXME: report error (yield expr in non-coroutine) |
| 574 | self.result.standard_types.unknown.clone() | |
| 544 | self.types.error | |
| 575 | 545 | } |
| 576 | 546 | } |
| 577 | 547 | Expr::Yeet { expr } => { |
| 578 | 548 | if let &Some(expr) = expr { |
| 579 | 549 | self.infer_expr_no_expect(expr, ExprIsRead::Yes); |
| 580 | 550 | } |
| 581 | self.result.standard_types.never.clone() | |
| 551 | self.types.never | |
| 582 | 552 | } |
| 583 | 553 | Expr::RecordLit { path, fields, spread, .. } => { |
| 584 | 554 | let (ty, def_id) = self.resolve_variant(tgt_expr.into(), path.as_deref(), false); |
| 585 | 555 | |
| 586 | 556 | if let Some(t) = expected.only_has_type(&mut self.table) { |
| 587 | self.unify(&ty, &t); | |
| 557 | self.unify(ty, t); | |
| 588 | 558 | } |
| 589 | 559 | |
| 590 | let substs = ty | |
| 591 | .as_adt() | |
| 592 | .map(|(_, s)| s.clone()) | |
| 593 | .unwrap_or_else(|| Substitution::empty(Interner)); | |
| 560 | let substs = ty.as_adt().map(|(_, s)| s).unwrap_or(self.types.empty_args); | |
| 594 | 561 | if let Some(variant) = def_id { |
| 595 | 562 | self.write_variant_resolution(tgt_expr.into(), variant); |
| 596 | 563 | } |
| 597 | 564 | match def_id { |
| 598 | 565 | _ if fields.is_empty() => {} |
| 599 | 566 | Some(def) => { |
| 600 | let field_types = self.db.field_types(def); | |
| 567 | let field_types = self.db.field_types_ns(def); | |
| 601 | 568 | let variant_data = def.fields(self.db); |
| 602 | 569 | let visibilities = self.db.field_visibilities(def); |
| 603 | 570 | for field in fields.iter() { |
| ... | ... | @@ -628,7 +595,7 @@ impl<'db> InferenceContext<'db> { |
| 628 | 595 | } |
| 629 | 596 | }; |
| 630 | 597 | let field_ty = field_def.map_or(self.err_ty(), |it| { |
| 631 | field_types[it].clone().substitute(Interner, &substs) | |
| 598 | field_types[it].instantiate(self.interner(), &substs) | |
| 632 | 599 | }); |
| 633 | 600 | |
| 634 | 601 | // Field type might have some unknown types |
| ... | ... | @@ -649,7 +616,7 @@ impl<'db> InferenceContext<'db> { |
| 649 | 616 | } |
| 650 | 617 | } |
| 651 | 618 | if let Some(expr) = spread { |
| 652 | self.infer_expr(*expr, &Expectation::has_type(ty.clone()), ExprIsRead::Yes); | |
| 619 | self.infer_expr(*expr, &Expectation::has_type(ty), ExprIsRead::Yes); | |
| 653 | 620 | } |
| 654 | 621 | ty |
| 655 | 622 | } |
| ... | ... | @@ -660,21 +627,13 @@ impl<'db> InferenceContext<'db> { |
| 660 | 627 | } |
| 661 | 628 | Expr::Cast { expr, type_ref } => { |
| 662 | 629 | let cast_ty = self.make_body_ty(*type_ref); |
| 663 | let expr_ty = self.infer_expr( | |
| 664 | *expr, | |
| 665 | &Expectation::Castable(cast_ty.clone()), | |
| 666 | ExprIsRead::Yes, | |
| 667 | ); | |
| 668 | self.deferred_cast_checks.push(CastCheck::new( | |
| 669 | tgt_expr, | |
| 670 | *expr, | |
| 671 | expr_ty, | |
| 672 | cast_ty.clone(), | |
| 673 | )); | |
| 630 | let expr_ty = | |
| 631 | self.infer_expr(*expr, &Expectation::Castable(cast_ty), ExprIsRead::Yes); | |
| 632 | self.deferred_cast_checks.push(CastCheck::new(tgt_expr, *expr, expr_ty, cast_ty)); | |
| 674 | 633 | cast_ty |
| 675 | 634 | } |
| 676 | 635 | Expr::Ref { expr, rawness, mutability } => { |
| 677 | let mutability = lower_to_chalk_mutability(*mutability); | |
| 636 | let mutability = lower_mutability(*mutability); | |
| 678 | 637 | let expectation = if let Some((exp_inner, exp_rawness, exp_mutability)) = expected |
| 679 | 638 | .only_has_type(&mut self.table) |
| 680 | 639 | .as_ref() |
| ... | ... | @@ -688,24 +647,23 @@ impl<'db> InferenceContext<'db> { |
| 688 | 647 | // FIXME: record type error - expected reference but found ptr, |
| 689 | 648 | // which cannot be coerced |
| 690 | 649 | } |
| 691 | Expectation::rvalue_hint(self, Ty::clone(exp_inner)) | |
| 650 | Expectation::rvalue_hint(self, exp_inner) | |
| 692 | 651 | } else { |
| 693 | 652 | Expectation::none() |
| 694 | 653 | }; |
| 695 | 654 | let inner_ty = self.infer_expr_inner(*expr, &expectation, ExprIsRead::Yes); |
| 696 | 655 | match rawness { |
| 697 | Rawness::RawPtr => TyKind::Raw(mutability, inner_ty), | |
| 656 | Rawness::RawPtr => Ty::new_ptr(self.interner(), inner_ty, mutability), | |
| 698 | 657 | Rawness::Ref => { |
| 699 | let lt = self.table.new_lifetime_var(); | |
| 700 | TyKind::Ref(mutability, lt, inner_ty) | |
| 658 | let lt = self.table.next_region_var(); | |
| 659 | Ty::new_ref(self.interner(), lt, inner_ty, mutability) | |
| 701 | 660 | } |
| 702 | 661 | } |
| 703 | .intern(Interner) | |
| 704 | 662 | } |
| 705 | 663 | &Expr::Box { expr } => self.infer_expr_box(expr, expected), |
| 706 | 664 | Expr::UnaryOp { expr, op } => { |
| 707 | 665 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none(), ExprIsRead::Yes); |
| 708 | let inner_ty = self.table.structurally_resolve_type(&inner_ty); | |
| 666 | let inner_ty = self.table.try_structurally_resolve_type(inner_ty); | |
| 709 | 667 | // FIXME: Note down method resolution her |
| 710 | 668 | match op { |
| 711 | 669 | UnaryOp::Deref => { |
| ... | ... | @@ -716,49 +674,38 @@ impl<'db> InferenceContext<'db> { |
| 716 | 674 | { |
| 717 | 675 | // FIXME: this is wrong in multiple ways, subst is empty, and we emit it even for builtin deref (note that |
| 718 | 676 | // the mutability is not wrong, and will be fixed in `self.infer_mut`). |
| 719 | self.write_method_resolution( | |
| 720 | tgt_expr, | |
| 721 | deref_fn, | |
| 722 | Substitution::empty(Interner), | |
| 723 | ); | |
| 677 | self.write_method_resolution(tgt_expr, deref_fn, self.types.empty_args); | |
| 724 | 678 | } |
| 725 | if let Some(derefed) = | |
| 726 | inner_ty.to_nextsolver(self.table.interner).builtin_deref(self.db, true) | |
| 727 | { | |
| 728 | self.table | |
| 729 | .structurally_resolve_type(&derefed.to_chalk(self.table.interner)) | |
| 679 | if let Some(derefed) = inner_ty.builtin_deref(self.db, true) { | |
| 680 | self.table.try_structurally_resolve_type(derefed) | |
| 730 | 681 | } else { |
| 731 | let infer_ok = overloaded_deref_ty( | |
| 732 | &self.table, | |
| 733 | inner_ty.to_nextsolver(self.table.interner), | |
| 734 | ); | |
| 682 | let infer_ok = overloaded_deref_ty(&self.table, inner_ty); | |
| 735 | 683 | match infer_ok { |
| 736 | Some(infer_ok) => self | |
| 737 | .table | |
| 738 | .register_infer_ok(infer_ok) | |
| 739 | .to_chalk(self.table.interner), | |
| 684 | Some(infer_ok) => self.table.register_infer_ok(infer_ok), | |
| 740 | 685 | None => self.err_ty(), |
| 741 | 686 | } |
| 742 | 687 | } |
| 743 | 688 | } |
| 744 | 689 | UnaryOp::Neg => { |
| 745 | match inner_ty.kind(Interner) { | |
| 690 | match inner_ty.kind() { | |
| 746 | 691 | // Fast path for builtins |
| 747 | TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_) | Scalar::Float(_)) | |
| 748 | | TyKind::InferenceVar( | |
| 749 | _, | |
| 750 | TyVariableKind::Integer | TyVariableKind::Float, | |
| 751 | ) => inner_ty, | |
| 692 | TyKind::Int(_) | |
| 693 | | TyKind::Uint(_) | |
| 694 | | TyKind::Float(_) | |
| 695 | | TyKind::Infer(InferTy::IntVar(_) | InferTy::FloatVar(_)) => inner_ty, | |
| 752 | 696 | // Otherwise we resolve via the std::ops::Neg trait |
| 753 | 697 | _ => self |
| 754 | 698 | .resolve_associated_type(inner_ty, self.resolve_ops_neg_output()), |
| 755 | 699 | } |
| 756 | 700 | } |
| 757 | 701 | UnaryOp::Not => { |
| 758 | match inner_ty.kind(Interner) { | |
| 702 | match inner_ty.kind() { | |
| 759 | 703 | // Fast path for builtins |
| 760 | TyKind::Scalar(Scalar::Bool | Scalar::Int(_) | Scalar::Uint(_)) | |
| 761 | | TyKind::InferenceVar(_, TyVariableKind::Integer) => inner_ty, | |
| 704 | TyKind::Bool | |
| 705 | | TyKind::Int(_) | |
| 706 | | TyKind::Uint(_) | |
| 707 | | TyKind::Float(_) | |
| 708 | | TyKind::Infer(InferTy::IntVar(_) | InferTy::FloatVar(_)) => inner_ty, | |
| 762 | 709 | // Otherwise we resolve via the std::ops::Not trait |
| 763 | 710 | _ => self |
| 764 | 711 | .resolve_associated_type(inner_ty, self.resolve_ops_not_output()), |
| ... | ... | @@ -768,18 +715,10 @@ impl<'db> InferenceContext<'db> { |
| 768 | 715 | } |
| 769 | 716 | Expr::BinaryOp { lhs, rhs, op } => match op { |
| 770 | 717 | Some(BinaryOp::LogicOp(_)) => { |
| 771 | let bool_ty = self.result.standard_types.bool_.clone(); | |
| 772 | self.infer_expr_coerce( | |
| 773 | *lhs, | |
| 774 | &Expectation::HasType(bool_ty.clone()), | |
| 775 | ExprIsRead::Yes, | |
| 776 | ); | |
| 718 | let bool_ty = self.types.bool; | |
| 719 | self.infer_expr_coerce(*lhs, &Expectation::HasType(bool_ty), ExprIsRead::Yes); | |
| 777 | 720 | let lhs_diverges = self.diverges; |
| 778 | self.infer_expr_coerce( | |
| 779 | *rhs, | |
| 780 | &Expectation::HasType(bool_ty.clone()), | |
| 781 | ExprIsRead::Yes, | |
| 782 | ); | |
| 721 | self.infer_expr_coerce(*rhs, &Expectation::HasType(bool_ty), ExprIsRead::Yes); | |
| 783 | 722 | // Depending on the LHS' value, the RHS can never execute. |
| 784 | 723 | self.diverges = lhs_diverges; |
| 785 | 724 | bool_ty |
| ... | ... | @@ -826,14 +765,14 @@ impl<'db> InferenceContext<'db> { |
| 826 | 765 | let is_destructuring_assignment = lhs_ty.is_none(); |
| 827 | 766 | |
| 828 | 767 | if let Some(lhs_ty) = lhs_ty { |
| 829 | self.write_pat_ty(target, lhs_ty.clone()); | |
| 768 | self.write_pat_ty(target, lhs_ty); | |
| 830 | 769 | self.infer_expr_coerce(value, &Expectation::has_type(lhs_ty), ExprIsRead::No); |
| 831 | 770 | } else { |
| 832 | 771 | let rhs_ty = self.infer_expr(value, &Expectation::none(), ExprIsRead::Yes); |
| 833 | 772 | let resolver_guard = |
| 834 | 773 | self.resolver.update_to_inner_scope(self.db, self.owner, tgt_expr); |
| 835 | 774 | self.inside_assignment = true; |
| 836 | self.infer_top_pat(target, &rhs_ty, None); | |
| 775 | self.infer_top_pat(target, rhs_ty, None); | |
| 837 | 776 | self.inside_assignment = false; |
| 838 | 777 | self.resolver.reset_to_guard(resolver_guard); |
| 839 | 778 | } |
| ... | ... | @@ -844,43 +783,49 @@ impl<'db> InferenceContext<'db> { |
| 844 | 783 | // assignments into blocks. |
| 845 | 784 | self.table.new_maybe_never_var() |
| 846 | 785 | } else { |
| 847 | self.result.standard_types.unit.clone() | |
| 786 | self.types.unit | |
| 848 | 787 | } |
| 849 | 788 | } |
| 850 | 789 | Expr::Range { lhs, rhs, range_type } => { |
| 851 | 790 | let lhs_ty = |
| 852 | 791 | lhs.map(|e| self.infer_expr_inner(e, &Expectation::none(), ExprIsRead::Yes)); |
| 853 | let rhs_expect = lhs_ty | |
| 854 | .as_ref() | |
| 855 | .map_or_else(Expectation::none, |ty| Expectation::has_type(ty.clone())); | |
| 792 | let rhs_expect = | |
| 793 | lhs_ty.as_ref().map_or_else(Expectation::none, |ty| Expectation::has_type(*ty)); | |
| 856 | 794 | let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect, ExprIsRead::Yes)); |
| 795 | let single_arg_adt = |adt, ty: Ty<'db>| { | |
| 796 | Ty::new_adt( | |
| 797 | self.interner(), | |
| 798 | adt, | |
| 799 | GenericArgs::new_from_iter(self.interner(), [ty.into()]), | |
| 800 | ) | |
| 801 | }; | |
| 857 | 802 | match (range_type, lhs_ty, rhs_ty) { |
| 858 | 803 | (RangeOp::Exclusive, None, None) => match self.resolve_range_full() { |
| 859 | Some(adt) => TyBuilder::adt(self.db, adt).build(), | |
| 804 | Some(adt) => Ty::new_adt(self.interner(), adt, self.types.empty_args), | |
| 860 | 805 | None => self.err_ty(), |
| 861 | 806 | }, |
| 862 | 807 | (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() { |
| 863 | Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(), | |
| 808 | Some(adt) => single_arg_adt(adt, ty), | |
| 864 | 809 | None => self.err_ty(), |
| 865 | 810 | }, |
| 866 | 811 | (RangeOp::Inclusive, None, Some(ty)) => { |
| 867 | 812 | match self.resolve_range_to_inclusive() { |
| 868 | Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(), | |
| 813 | Some(adt) => single_arg_adt(adt, ty), | |
| 869 | 814 | None => self.err_ty(), |
| 870 | 815 | } |
| 871 | 816 | } |
| 872 | 817 | (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() { |
| 873 | Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(), | |
| 818 | Some(adt) => single_arg_adt(adt, ty), | |
| 874 | 819 | None => self.err_ty(), |
| 875 | 820 | }, |
| 876 | 821 | (RangeOp::Inclusive, Some(_), Some(ty)) => { |
| 877 | 822 | match self.resolve_range_inclusive() { |
| 878 | Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(), | |
| 823 | Some(adt) => single_arg_adt(adt, ty), | |
| 879 | 824 | None => self.err_ty(), |
| 880 | 825 | } |
| 881 | 826 | } |
| 882 | 827 | (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() { |
| 883 | Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(), | |
| 828 | Some(adt) => single_arg_adt(adt, ty), | |
| 884 | 829 | None => self.err_ty(), |
| 885 | 830 | }, |
| 886 | 831 | (RangeOp::Inclusive, _, None) => self.err_ty(), |
| ... | ... | @@ -891,8 +836,7 @@ impl<'db> InferenceContext<'db> { |
| 891 | 836 | let index_ty = self.infer_expr(*index, &Expectation::none(), ExprIsRead::Yes); |
| 892 | 837 | |
| 893 | 838 | if let Some(index_trait) = self.resolve_lang_trait(LangItem::Index) { |
| 894 | let canonicalized = | |
| 895 | self.canonicalize(base_ty.clone().to_nextsolver(self.table.interner)); | |
| 839 | let canonicalized = self.canonicalize(base_ty); | |
| 896 | 840 | let receiver_adjustments = method_resolution::resolve_indexing_op( |
| 897 | 841 | &mut self.table, |
| 898 | 842 | canonicalized, |
| ... | ... | @@ -905,66 +849,52 @@ impl<'db> InferenceContext<'db> { |
| 905 | 849 | |
| 906 | 850 | // mutability will be fixed up in `InferenceContext::infer_mut`; |
| 907 | 851 | adj.push(Adjustment::borrow( |
| 852 | self.interner(), | |
| 908 | 853 | Mutability::Not, |
| 909 | self_ty.clone(), | |
| 910 | self.table.new_lifetime_var(), | |
| 854 | self_ty, | |
| 855 | self.table.next_region_var(), | |
| 911 | 856 | )); |
| 912 | 857 | self.write_expr_adj(*base, adj.into_boxed_slice()); |
| 913 | 858 | if let Some(func) = index_trait |
| 914 | 859 | .trait_items(self.db) |
| 915 | 860 | .method_by_name(&Name::new_symbol_root(sym::index)) |
| 916 | 861 | { |
| 917 | let subst = TyBuilder::subst_for_def(self.db, index_trait, None); | |
| 918 | if subst.remaining() != 2 { | |
| 919 | return self.err_ty(); | |
| 920 | } | |
| 921 | let subst = subst.push(self_ty.clone()).push(index_ty.clone()).build(); | |
| 862 | let subst = GenericArgs::new_from_iter( | |
| 863 | self.interner(), | |
| 864 | [self_ty.into(), index_ty.into()], | |
| 865 | ); | |
| 922 | 866 | self.write_method_resolution(tgt_expr, func, subst); |
| 923 | 867 | } |
| 924 | 868 | let assoc = self.resolve_ops_index_output(); |
| 925 | self.resolve_associated_type_with_params( | |
| 926 | self_ty, | |
| 927 | assoc, | |
| 928 | &[index_ty.cast(Interner)], | |
| 929 | ) | |
| 869 | self.resolve_associated_type_with_params(self_ty, assoc, &[index_ty.into()]) | |
| 930 | 870 | } else { |
| 931 | 871 | self.err_ty() |
| 932 | 872 | } |
| 933 | 873 | } |
| 934 | 874 | Expr::Tuple { exprs, .. } => { |
| 935 | let mut tys = match expected | |
| 936 | .only_has_type(&mut self.table) | |
| 937 | .as_ref() | |
| 938 | .map(|t| t.kind(Interner)) | |
| 939 | { | |
| 940 | Some(TyKind::Tuple(_, substs)) => substs | |
| 941 | .iter(Interner) | |
| 942 | .map(|a| a.assert_ty_ref(Interner).clone()) | |
| 943 | .chain(repeat_with(|| self.table.new_type_var())) | |
| 944 | .take(exprs.len()) | |
| 945 | .collect::<Vec<_>>(), | |
| 946 | _ => (0..exprs.len()).map(|_| self.table.new_type_var()).collect(), | |
| 947 | }; | |
| 875 | let mut tys = | |
| 876 | match expected.only_has_type(&mut self.table).as_ref().map(|t| t.kind()) { | |
| 877 | Some(TyKind::Tuple(substs)) => substs | |
| 878 | .iter() | |
| 879 | .chain(repeat_with(|| self.table.next_ty_var())) | |
| 880 | .take(exprs.len()) | |
| 881 | .collect::<Vec<_>>(), | |
| 882 | _ => (0..exprs.len()).map(|_| self.table.next_ty_var()).collect(), | |
| 883 | }; | |
| 948 | 884 | |
| 949 | 885 | for (expr, ty) in exprs.iter().zip(tys.iter_mut()) { |
| 950 | *ty = self.infer_expr_coerce( | |
| 951 | *expr, | |
| 952 | &Expectation::has_type(ty.clone()), | |
| 953 | ExprIsRead::Yes, | |
| 954 | ); | |
| 886 | *ty = | |
| 887 | self.infer_expr_coerce(*expr, &Expectation::has_type(*ty), ExprIsRead::Yes); | |
| 955 | 888 | } |
| 956 | 889 | |
| 957 | TyKind::Tuple(tys.len(), Substitution::from_iter(Interner, tys)).intern(Interner) | |
| 890 | Ty::new_tup(self.interner(), &tys) | |
| 958 | 891 | } |
| 959 | 892 | Expr::Array(array) => self.infer_expr_array(array, expected), |
| 960 | 893 | Expr::Literal(lit) => match lit { |
| 961 | Literal::Bool(..) => self.result.standard_types.bool_.clone(), | |
| 962 | Literal::String(..) => { | |
| 963 | TyKind::Ref(Mutability::Not, static_lifetime(), TyKind::Str.intern(Interner)) | |
| 964 | .intern(Interner) | |
| 965 | } | |
| 894 | Literal::Bool(..) => self.types.bool, | |
| 895 | Literal::String(..) => self.types.static_str_ref, | |
| 966 | 896 | Literal::ByteString(bs) => { |
| 967 | let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(Interner); | |
| 897 | let byte_type = self.types.u8; | |
| 968 | 898 | |
| 969 | 899 | let len = consteval::usize_const( |
| 970 | 900 | self.db, |
| ... | ... | @@ -972,75 +902,80 @@ impl<'db> InferenceContext<'db> { |
| 972 | 902 | self.resolver.krate(), |
| 973 | 903 | ); |
| 974 | 904 | |
| 975 | let array_type = TyKind::Array(byte_type, len).intern(Interner); | |
| 976 | TyKind::Ref(Mutability::Not, static_lifetime(), array_type).intern(Interner) | |
| 905 | let array_type = Ty::new_array_with_const_len(self.interner(), byte_type, len); | |
| 906 | Ty::new_ref(self.interner(), self.types.re_static, array_type, Mutability::Not) | |
| 977 | 907 | } |
| 978 | Literal::CString(..) => TyKind::Ref( | |
| 979 | Mutability::Not, | |
| 980 | static_lifetime(), | |
| 908 | Literal::CString(..) => Ty::new_ref( | |
| 909 | self.interner(), | |
| 910 | self.types.re_static, | |
| 981 | 911 | self.resolve_lang_item(LangItem::CStr) |
| 982 | 912 | .and_then(LangItemTarget::as_struct) |
| 983 | 913 | .map_or_else( |
| 984 | 914 | || self.err_ty(), |
| 985 | 915 | |strukt| { |
| 986 | TyKind::Adt(AdtId(strukt.into()), Substitution::empty(Interner)) | |
| 987 | .intern(Interner) | |
| 916 | Ty::new_adt(self.interner(), strukt.into(), self.types.empty_args) | |
| 988 | 917 | }, |
| 989 | 918 | ), |
| 990 | ) | |
| 991 | .intern(Interner), | |
| 992 | Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(Interner), | |
| 919 | Mutability::Not, | |
| 920 | ), | |
| 921 | Literal::Char(..) => self.types.char, | |
| 993 | 922 | Literal::Int(_v, ty) => match ty { |
| 994 | Some(int_ty) => { | |
| 995 | TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(*int_ty))) | |
| 996 | .intern(Interner) | |
| 997 | } | |
| 923 | Some(int_ty) => match int_ty { | |
| 924 | hir_def::builtin_type::BuiltinInt::Isize => self.types.isize, | |
| 925 | hir_def::builtin_type::BuiltinInt::I8 => self.types.i8, | |
| 926 | hir_def::builtin_type::BuiltinInt::I16 => self.types.i16, | |
| 927 | hir_def::builtin_type::BuiltinInt::I32 => self.types.i32, | |
| 928 | hir_def::builtin_type::BuiltinInt::I64 => self.types.i64, | |
| 929 | hir_def::builtin_type::BuiltinInt::I128 => self.types.i128, | |
| 930 | }, | |
| 998 | 931 | None => { |
| 999 | 932 | let expected_ty = expected.to_option(&mut self.table); |
| 1000 | 933 | tracing::debug!(?expected_ty); |
| 1001 | let opt_ty = match expected_ty.as_ref().map(|it| it.kind(Interner)) { | |
| 1002 | Some(TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_))) => expected_ty, | |
| 1003 | Some(TyKind::Scalar(Scalar::Char)) => { | |
| 1004 | Some(TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(Interner)) | |
| 1005 | } | |
| 1006 | Some(TyKind::Raw(..) | TyKind::FnDef(..) | TyKind::Function(..)) => { | |
| 1007 | Some(TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner)) | |
| 934 | let opt_ty = match expected_ty.as_ref().map(|it| it.kind()) { | |
| 935 | Some(TyKind::Int(_) | TyKind::Uint(_)) => expected_ty, | |
| 936 | Some(TyKind::Char) => Some(self.types.u8), | |
| 937 | Some(TyKind::RawPtr(..) | TyKind::FnDef(..) | TyKind::FnPtr(..)) => { | |
| 938 | Some(self.types.usize) | |
| 1008 | 939 | } |
| 1009 | 940 | _ => None, |
| 1010 | 941 | }; |
| 1011 | opt_ty.unwrap_or_else(|| self.table.new_integer_var()) | |
| 942 | opt_ty.unwrap_or_else(|| self.table.next_int_var()) | |
| 1012 | 943 | } |
| 1013 | 944 | }, |
| 1014 | 945 | Literal::Uint(_v, ty) => match ty { |
| 1015 | Some(int_ty) => { | |
| 1016 | TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(*int_ty))) | |
| 1017 | .intern(Interner) | |
| 1018 | } | |
| 946 | Some(int_ty) => match int_ty { | |
| 947 | hir_def::builtin_type::BuiltinUint::Usize => self.types.usize, | |
| 948 | hir_def::builtin_type::BuiltinUint::U8 => self.types.u8, | |
| 949 | hir_def::builtin_type::BuiltinUint::U16 => self.types.u16, | |
| 950 | hir_def::builtin_type::BuiltinUint::U32 => self.types.u32, | |
| 951 | hir_def::builtin_type::BuiltinUint::U64 => self.types.u64, | |
| 952 | hir_def::builtin_type::BuiltinUint::U128 => self.types.u128, | |
| 953 | }, | |
| 1019 | 954 | None => { |
| 1020 | 955 | let expected_ty = expected.to_option(&mut self.table); |
| 1021 | let opt_ty = match expected_ty.as_ref().map(|it| it.kind(Interner)) { | |
| 1022 | Some(TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_))) => expected_ty, | |
| 1023 | Some(TyKind::Scalar(Scalar::Char)) => { | |
| 1024 | Some(TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(Interner)) | |
| 1025 | } | |
| 1026 | Some(TyKind::Raw(..) | TyKind::FnDef(..) | TyKind::Function(..)) => { | |
| 1027 | Some(TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner)) | |
| 956 | let opt_ty = match expected_ty.as_ref().map(|it| it.kind()) { | |
| 957 | Some(TyKind::Int(_) | TyKind::Uint(_)) => expected_ty, | |
| 958 | Some(TyKind::Char) => Some(self.types.u8), | |
| 959 | Some(TyKind::RawPtr(..) | TyKind::FnDef(..) | TyKind::FnPtr(..)) => { | |
| 960 | Some(self.types.usize) | |
| 1028 | 961 | } |
| 1029 | 962 | _ => None, |
| 1030 | 963 | }; |
| 1031 | opt_ty.unwrap_or_else(|| self.table.new_integer_var()) | |
| 964 | opt_ty.unwrap_or_else(|| self.table.next_int_var()) | |
| 1032 | 965 | } |
| 1033 | 966 | }, |
| 1034 | 967 | Literal::Float(_v, ty) => match ty { |
| 1035 | Some(float_ty) => { | |
| 1036 | TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(*float_ty))) | |
| 1037 | .intern(Interner) | |
| 1038 | } | |
| 968 | Some(float_ty) => match float_ty { | |
| 969 | hir_def::builtin_type::BuiltinFloat::F16 => self.types.f16, | |
| 970 | hir_def::builtin_type::BuiltinFloat::F32 => self.types.f32, | |
| 971 | hir_def::builtin_type::BuiltinFloat::F64 => self.types.f64, | |
| 972 | hir_def::builtin_type::BuiltinFloat::F128 => self.types.f128, | |
| 973 | }, | |
| 1039 | 974 | None => { |
| 1040 | let opt_ty = expected.to_option(&mut self.table).filter(|ty| { | |
| 1041 | matches!(ty.kind(Interner), TyKind::Scalar(Scalar::Float(_))) | |
| 1042 | }); | |
| 1043 | opt_ty.unwrap_or_else(|| self.table.new_float_var()) | |
| 975 | let opt_ty = expected | |
| 976 | .to_option(&mut self.table) | |
| 977 | .filter(|ty| matches!(ty.kind(), TyKind::Float(_))); | |
| 978 | opt_ty.unwrap_or_else(|| self.table.next_float_var()) | |
| 1044 | 979 | } |
| 1045 | 980 | }, |
| 1046 | 981 | }, |
| ... | ... | @@ -1048,13 +983,10 @@ impl<'db> InferenceContext<'db> { |
| 1048 | 983 | // Underscore expression is an error, we render a specialized diagnostic |
| 1049 | 984 | // to let the user know what type is expected though. |
| 1050 | 985 | let expected = expected.to_option(&mut self.table).unwrap_or_else(|| self.err_ty()); |
| 1051 | self.push_diagnostic(InferenceDiagnostic::TypedHole { | |
| 1052 | expr: tgt_expr, | |
| 1053 | expected: expected.clone(), | |
| 1054 | }); | |
| 986 | self.push_diagnostic(InferenceDiagnostic::TypedHole { expr: tgt_expr, expected }); | |
| 1055 | 987 | expected |
| 1056 | 988 | } |
| 1057 | Expr::OffsetOf(_) => TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner), | |
| 989 | Expr::OffsetOf(_) => self.types.usize, | |
| 1058 | 990 | Expr::InlineAsm(asm) => { |
| 1059 | 991 | let check_expr_asm_operand = |this: &mut Self, expr, is_input: bool| { |
| 1060 | 992 | let ty = this.infer_expr_no_expect(expr, ExprIsRead::Yes); |
| ... | ... | @@ -1067,27 +999,29 @@ impl<'db> InferenceContext<'db> { |
| 1067 | 999 | // allows them to be inferred based on how they are used later in the |
| 1068 | 1000 | // function. |
| 1069 | 1001 | if is_input { |
| 1070 | let ty = this.table.structurally_resolve_type(&ty); | |
| 1071 | match ty.kind(Interner) { | |
| 1002 | let ty = this.table.structurally_resolve_type(ty); | |
| 1003 | match ty.kind() { | |
| 1072 | 1004 | TyKind::FnDef(def, parameters) => { |
| 1073 | let fnptr_ty = TyKind::Function( | |
| 1074 | CallableSig::from_def(this.db, *def, parameters).to_fn_ptr(), | |
| 1075 | ) | |
| 1076 | .intern(Interner); | |
| 1005 | let fnptr_ty = Ty::new_fn_ptr( | |
| 1006 | this.interner(), | |
| 1007 | this.interner() | |
| 1008 | .fn_sig(def) | |
| 1009 | .instantiate(this.interner(), parameters), | |
| 1010 | ); | |
| 1077 | 1011 | _ = this.coerce( |
| 1078 | 1012 | expr.into(), |
| 1079 | ty.to_nextsolver(this.table.interner), | |
| 1080 | fnptr_ty.to_nextsolver(this.table.interner), | |
| 1013 | ty, | |
| 1014 | fnptr_ty, | |
| 1081 | 1015 | AllowTwoPhase::No, |
| 1082 | 1016 | CoerceNever::Yes, |
| 1083 | 1017 | ); |
| 1084 | 1018 | } |
| 1085 | TyKind::Ref(mutbl, _, base_ty) => { | |
| 1086 | let ptr_ty = TyKind::Raw(*mutbl, base_ty.clone()).intern(Interner); | |
| 1019 | TyKind::Ref(_, base_ty, mutbl) => { | |
| 1020 | let ptr_ty = Ty::new_ptr(this.interner(), base_ty, mutbl); | |
| 1087 | 1021 | _ = this.coerce( |
| 1088 | 1022 | expr.into(), |
| 1089 | ty.to_nextsolver(this.table.interner), | |
| 1090 | ptr_ty.to_nextsolver(this.table.interner), | |
| 1023 | ty, | |
| 1024 | ptr_ty, | |
| 1091 | 1025 | AllowTwoPhase::No, |
| 1092 | 1026 | CoerceNever::Yes, |
| 1093 | 1027 | ); |
| ... | ... | @@ -1113,7 +1047,7 @@ impl<'db> InferenceContext<'db> { |
| 1113 | 1047 | AsmOperand::Label(expr) => { |
| 1114 | 1048 | self.infer_expr( |
| 1115 | 1049 | expr, |
| 1116 | &Expectation::HasType(self.result.standard_types.unit.clone()), | |
| 1050 | &Expectation::HasType(self.types.unit), | |
| 1117 | 1051 | ExprIsRead::No, |
| 1118 | 1052 | ); |
| 1119 | 1053 | } |
| ... | ... | @@ -1123,17 +1057,13 @@ impl<'db> InferenceContext<'db> { |
| 1123 | 1057 | // FIXME: `sym` should report for things that are not functions or statics. |
| 1124 | 1058 | AsmOperand::Sym(_) => (), |
| 1125 | 1059 | }); |
| 1126 | if diverge { | |
| 1127 | self.result.standard_types.never.clone() | |
| 1128 | } else { | |
| 1129 | self.result.standard_types.unit.clone() | |
| 1130 | } | |
| 1060 | if diverge { self.types.never } else { self.types.unit } | |
| 1131 | 1061 | } |
| 1132 | 1062 | }; |
| 1133 | 1063 | // use a new type variable if we got unknown here |
| 1134 | 1064 | let ty = self.insert_type_vars_shallow(ty); |
| 1135 | self.write_expr_ty(tgt_expr, ty.clone()); | |
| 1136 | if self.resolve_ty_shallow(&ty).is_never() | |
| 1065 | self.write_expr_ty(tgt_expr, ty); | |
| 1066 | if self.shallow_resolve(ty).is_never() | |
| 1137 | 1067 | && self.expr_guaranteed_to_constitute_read_for_never(tgt_expr, is_read) |
| 1138 | 1068 | { |
| 1139 | 1069 | // Any expression that produces a value of type `!` must have diverged |
| ... | ... | @@ -1142,7 +1072,7 @@ impl<'db> InferenceContext<'db> { |
| 1142 | 1072 | ty |
| 1143 | 1073 | } |
| 1144 | 1074 | |
| 1145 | fn infer_expr_path(&mut self, path: &Path, id: ExprOrPatId, scope_id: ExprId) -> Ty { | |
| 1075 | fn infer_expr_path(&mut self, path: &Path, id: ExprOrPatId, scope_id: ExprId) -> Ty<'db> { | |
| 1146 | 1076 | let g = self.resolver.update_to_inner_scope(self.db, self.owner, scope_id); |
| 1147 | 1077 | let ty = match self.infer_path(path, id) { |
| 1148 | 1078 | Some(ty) => ty, |
| ... | ... | @@ -1164,32 +1094,24 @@ impl<'db> InferenceContext<'db> { |
| 1164 | 1094 | id: &Option<BlockId>, |
| 1165 | 1095 | statements: &[Statement], |
| 1166 | 1096 | tail: &Option<ExprId>, |
| 1167 | ) -> Ty { | |
| 1168 | let ret_ty = self.table.new_type_var(); | |
| 1097 | ) -> Ty<'db> { | |
| 1098 | let ret_ty = self.table.next_ty_var(); | |
| 1169 | 1099 | let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); |
| 1170 | let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone()); | |
| 1171 | let prev_ret_coercion = self | |
| 1172 | .return_coercion | |
| 1173 | .replace(CoerceMany::new(ret_ty.to_nextsolver(self.table.interner))); | |
| 1100 | let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty); | |
| 1101 | let prev_ret_coercion = self.return_coercion.replace(CoerceMany::new(ret_ty)); | |
| 1174 | 1102 | |
| 1175 | 1103 | // FIXME: We should handle async blocks like we handle closures |
| 1176 | 1104 | let expected = &Expectation::has_type(ret_ty); |
| 1177 | 1105 | let (_, inner_ty) = self.with_breakable_ctx(BreakableKind::Border, None, None, |this| { |
| 1178 | 1106 | let ty = this.infer_block(tgt_expr, *id, statements, *tail, None, expected); |
| 1179 | 1107 | if let Some(target) = expected.only_has_type(&mut this.table) { |
| 1180 | match this.coerce( | |
| 1181 | tgt_expr.into(), | |
| 1182 | ty.to_nextsolver(this.table.interner), | |
| 1183 | target.to_nextsolver(this.table.interner), | |
| 1184 | AllowTwoPhase::No, | |
| 1185 | CoerceNever::Yes, | |
| 1186 | ) { | |
| 1187 | Ok(res) => res.to_chalk(this.table.interner), | |
| 1108 | match this.coerce(tgt_expr.into(), ty, target, AllowTwoPhase::No, CoerceNever::Yes) | |
| 1109 | { | |
| 1110 | Ok(res) => res, | |
| 1188 | 1111 | Err(_) => { |
| 1189 | this.result.type_mismatches.insert( | |
| 1190 | tgt_expr.into(), | |
| 1191 | TypeMismatch { expected: target.clone(), actual: ty.clone() }, | |
| 1192 | ); | |
| 1112 | this.result | |
| 1113 | .type_mismatches | |
| 1114 | .insert(tgt_expr.into(), TypeMismatch { expected: target, actual: ty }); | |
| 1193 | 1115 | target |
| 1194 | 1116 | } |
| 1195 | 1117 | } |
| ... | ... | @@ -1207,57 +1129,67 @@ impl<'db> InferenceContext<'db> { |
| 1207 | 1129 | |
| 1208 | 1130 | pub(crate) fn lower_async_block_type_impl_trait( |
| 1209 | 1131 | &mut self, |
| 1210 | inner_ty: Ty, | |
| 1132 | inner_ty: Ty<'db>, | |
| 1211 | 1133 | tgt_expr: ExprId, |
| 1212 | ) -> Ty { | |
| 1134 | ) -> Ty<'db> { | |
| 1213 | 1135 | // Use the first type parameter as the output type of future. |
| 1214 | 1136 | // existential type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType> |
| 1215 | 1137 | let impl_trait_id = crate::ImplTraitId::AsyncBlockTypeImplTrait(self.owner, tgt_expr); |
| 1216 | 1138 | let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into(); |
| 1217 | TyKind::OpaqueType(opaque_ty_id, Substitution::from1(Interner, inner_ty)).intern(Interner) | |
| 1139 | Ty::new_alias( | |
| 1140 | self.interner(), | |
| 1141 | AliasTyKind::Opaque, | |
| 1142 | AliasTy::new( | |
| 1143 | self.interner(), | |
| 1144 | opaque_ty_id, | |
| 1145 | GenericArgs::new_from_iter(self.interner(), [inner_ty.into()]), | |
| 1146 | ), | |
| 1147 | ) | |
| 1218 | 1148 | } |
| 1219 | 1149 | |
| 1220 | 1150 | pub(crate) fn write_fn_trait_method_resolution( |
| 1221 | 1151 | &mut self, |
| 1222 | 1152 | fn_x: FnTrait, |
| 1223 | derefed_callee: &Ty, | |
| 1224 | adjustments: &mut Vec<Adjustment>, | |
| 1225 | callee_ty: &Ty, | |
| 1226 | params: &[Ty], | |
| 1153 | derefed_callee: Ty<'db>, | |
| 1154 | adjustments: &mut Vec<Adjustment<'db>>, | |
| 1155 | callee_ty: Ty<'db>, | |
| 1156 | params: &[Ty<'db>], | |
| 1227 | 1157 | tgt_expr: ExprId, |
| 1228 | 1158 | ) { |
| 1229 | 1159 | match fn_x { |
| 1230 | 1160 | FnTrait::FnOnce | FnTrait::AsyncFnOnce => (), |
| 1231 | 1161 | FnTrait::FnMut | FnTrait::AsyncFnMut => { |
| 1232 | if let TyKind::Ref(Mutability::Mut, lt, inner) = derefed_callee.kind(Interner) { | |
| 1162 | if let TyKind::Ref(lt, inner, Mutability::Mut) = derefed_callee.kind() { | |
| 1233 | 1163 | if adjustments |
| 1234 | 1164 | .last() |
| 1235 | 1165 | .map(|it| matches!(it.kind, Adjust::Borrow(_))) |
| 1236 | 1166 | .unwrap_or(true) |
| 1237 | 1167 | { |
| 1238 | 1168 | // prefer reborrow to move |
| 1239 | adjustments | |
| 1240 | .push(Adjustment { kind: Adjust::Deref(None), target: inner.clone() }); | |
| 1169 | adjustments.push(Adjustment { kind: Adjust::Deref(None), target: inner }); | |
| 1241 | 1170 | adjustments.push(Adjustment::borrow( |
| 1171 | self.interner(), | |
| 1242 | 1172 | Mutability::Mut, |
| 1243 | inner.clone(), | |
| 1244 | lt.clone(), | |
| 1173 | inner, | |
| 1174 | lt, | |
| 1245 | 1175 | )) |
| 1246 | 1176 | } |
| 1247 | 1177 | } else { |
| 1248 | 1178 | adjustments.push(Adjustment::borrow( |
| 1179 | self.interner(), | |
| 1249 | 1180 | Mutability::Mut, |
| 1250 | derefed_callee.clone(), | |
| 1251 | self.table.new_lifetime_var(), | |
| 1181 | derefed_callee, | |
| 1182 | self.table.next_region_var(), | |
| 1252 | 1183 | )); |
| 1253 | 1184 | } |
| 1254 | 1185 | } |
| 1255 | 1186 | FnTrait::Fn | FnTrait::AsyncFn => { |
| 1256 | if !matches!(derefed_callee.kind(Interner), TyKind::Ref(Mutability::Not, _, _)) { | |
| 1187 | if !matches!(derefed_callee.kind(), TyKind::Ref(_, _, Mutability::Not)) { | |
| 1257 | 1188 | adjustments.push(Adjustment::borrow( |
| 1189 | self.interner(), | |
| 1258 | 1190 | Mutability::Not, |
| 1259 | derefed_callee.clone(), | |
| 1260 | self.table.new_lifetime_var(), | |
| 1191 | derefed_callee, | |
| 1192 | self.table.next_region_var(), | |
| 1261 | 1193 | )); |
| 1262 | 1194 | } |
| 1263 | 1195 | } |
| ... | ... | @@ -1267,57 +1199,48 @@ impl<'db> InferenceContext<'db> { |
| 1267 | 1199 | }; |
| 1268 | 1200 | let trait_data = trait_.trait_items(self.db); |
| 1269 | 1201 | if let Some(func) = trait_data.method_by_name(&fn_x.method_name()) { |
| 1270 | let subst = TyBuilder::subst_for_def(self.db, trait_, None) | |
| 1271 | .push(callee_ty.clone()) | |
| 1272 | .push(TyBuilder::tuple_with(params.iter().cloned())) | |
| 1273 | .build(); | |
| 1202 | let subst = GenericArgs::new_from_iter( | |
| 1203 | self.interner(), | |
| 1204 | [ | |
| 1205 | callee_ty.into(), | |
| 1206 | Ty::new_tup_from_iter(self.interner(), params.iter().copied()).into(), | |
| 1207 | ], | |
| 1208 | ); | |
| 1274 | 1209 | self.write_method_resolution(tgt_expr, func, subst); |
| 1275 | 1210 | } |
| 1276 | 1211 | } |
| 1277 | 1212 | |
| 1278 | fn infer_expr_array( | |
| 1279 | &mut self, | |
| 1280 | array: &Array, | |
| 1281 | expected: &Expectation, | |
| 1282 | ) -> chalk_ir::Ty<Interner> { | |
| 1283 | let elem_ty = match expected.to_option(&mut self.table).as_ref().map(|t| t.kind(Interner)) { | |
| 1284 | Some(TyKind::Array(st, _) | TyKind::Slice(st)) => st.clone(), | |
| 1285 | _ => self.table.new_type_var(), | |
| 1213 | fn infer_expr_array(&mut self, array: &Array, expected: &Expectation<'db>) -> Ty<'db> { | |
| 1214 | let elem_ty = match expected.to_option(&mut self.table).as_ref().map(|t| t.kind()) { | |
| 1215 | Some(TyKind::Array(st, _) | TyKind::Slice(st)) => st, | |
| 1216 | _ => self.table.next_ty_var(), | |
| 1286 | 1217 | }; |
| 1287 | 1218 | |
| 1288 | 1219 | let krate = self.resolver.krate(); |
| 1289 | 1220 | |
| 1290 | let expected = Expectation::has_type(elem_ty.clone()); | |
| 1221 | let expected = Expectation::has_type(elem_ty); | |
| 1291 | 1222 | let (elem_ty, len) = match array { |
| 1292 | 1223 | Array::ElementList { elements, .. } if elements.is_empty() => { |
| 1293 | 1224 | (elem_ty, consteval::usize_const(self.db, Some(0), krate)) |
| 1294 | 1225 | } |
| 1295 | 1226 | Array::ElementList { elements, .. } => { |
| 1296 | let mut coerce = CoerceMany::with_coercion_sites( | |
| 1297 | elem_ty.to_nextsolver(self.table.interner), | |
| 1298 | elements, | |
| 1299 | ); | |
| 1227 | let mut coerce = CoerceMany::with_coercion_sites(elem_ty, elements); | |
| 1300 | 1228 | for &expr in elements.iter() { |
| 1301 | 1229 | let cur_elem_ty = self.infer_expr_inner(expr, &expected, ExprIsRead::Yes); |
| 1302 | coerce.coerce( | |
| 1303 | self, | |
| 1304 | &ObligationCause::new(), | |
| 1305 | expr, | |
| 1306 | cur_elem_ty.to_nextsolver(self.table.interner), | |
| 1307 | ); | |
| 1230 | coerce.coerce(self, &ObligationCause::new(), expr, cur_elem_ty); | |
| 1308 | 1231 | } |
| 1309 | 1232 | ( |
| 1310 | coerce.complete(self).to_chalk(self.table.interner), | |
| 1233 | coerce.complete(self), | |
| 1311 | 1234 | consteval::usize_const(self.db, Some(elements.len() as u128), krate), |
| 1312 | 1235 | ) |
| 1313 | 1236 | } |
| 1314 | 1237 | &Array::Repeat { initializer, repeat } => { |
| 1315 | 1238 | self.infer_expr_coerce( |
| 1316 | 1239 | initializer, |
| 1317 | &Expectation::has_type(elem_ty.clone()), | |
| 1240 | &Expectation::has_type(elem_ty), | |
| 1318 | 1241 | ExprIsRead::Yes, |
| 1319 | 1242 | ); |
| 1320 | let usize = TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner); | |
| 1243 | let usize = self.types.usize; | |
| 1321 | 1244 | match self.body[repeat] { |
| 1322 | 1245 | Expr::Underscore => { |
| 1323 | 1246 | self.write_expr_ty(repeat, usize); |
| ... | ... | @@ -1325,20 +1248,12 @@ impl<'db> InferenceContext<'db> { |
| 1325 | 1248 | _ => _ = self.infer_expr(repeat, &Expectation::HasType(usize), ExprIsRead::Yes), |
| 1326 | 1249 | } |
| 1327 | 1250 | |
| 1328 | ( | |
| 1329 | elem_ty, | |
| 1330 | consteval::eval_to_const( | |
| 1331 | repeat, | |
| 1332 | ParamLoweringMode::Placeholder, | |
| 1333 | self, | |
| 1334 | DebruijnIndex::INNERMOST, | |
| 1335 | ), | |
| 1336 | ) | |
| 1251 | (elem_ty, consteval::eval_to_const(repeat, self)) | |
| 1337 | 1252 | } |
| 1338 | 1253 | }; |
| 1339 | 1254 | // Try to evaluate unevaluated constant, and insert variable if is not possible. |
| 1340 | 1255 | let len = self.table.insert_const_vars_shallow(len); |
| 1341 | TyKind::Array(elem_ty, len).intern(Interner) | |
| 1256 | Ty::new_array_with_const_len(self.interner(), elem_ty, len) | |
| 1342 | 1257 | } |
| 1343 | 1258 | |
| 1344 | 1259 | pub(super) fn infer_return(&mut self, expr: ExprId) { |
| ... | ... | @@ -1346,21 +1261,15 @@ impl<'db> InferenceContext<'db> { |
| 1346 | 1261 | .return_coercion |
| 1347 | 1262 | .as_mut() |
| 1348 | 1263 | .expect("infer_return called outside function body") |
| 1349 | .expected_ty() | |
| 1350 | .to_chalk(self.table.interner); | |
| 1264 | .expected_ty(); | |
| 1351 | 1265 | let return_expr_ty = |
| 1352 | 1266 | self.infer_expr_inner(expr, &Expectation::HasType(ret_ty), ExprIsRead::Yes); |
| 1353 | 1267 | let mut coerce_many = self.return_coercion.take().unwrap(); |
| 1354 | coerce_many.coerce( | |
| 1355 | self, | |
| 1356 | &ObligationCause::new(), | |
| 1357 | expr, | |
| 1358 | return_expr_ty.to_nextsolver(self.table.interner), | |
| 1359 | ); | |
| 1268 | coerce_many.coerce(self, &ObligationCause::new(), expr, return_expr_ty); | |
| 1360 | 1269 | self.return_coercion = Some(coerce_many); |
| 1361 | 1270 | } |
| 1362 | 1271 | |
| 1363 | fn infer_expr_return(&mut self, ret: ExprId, expr: Option<ExprId>) -> Ty { | |
| 1272 | fn infer_expr_return(&mut self, ret: ExprId, expr: Option<ExprId>) -> Ty<'db> { | |
| 1364 | 1273 | match self.return_coercion { |
| 1365 | 1274 | Some(_) => { |
| 1366 | 1275 | if let Some(expr) = expr { |
| ... | ... | @@ -1378,23 +1287,20 @@ impl<'db> InferenceContext<'db> { |
| 1378 | 1287 | } |
| 1379 | 1288 | } |
| 1380 | 1289 | } |
| 1381 | self.result.standard_types.never.clone() | |
| 1290 | self.types.never | |
| 1382 | 1291 | } |
| 1383 | 1292 | |
| 1384 | fn infer_expr_become(&mut self, expr: ExprId) -> Ty { | |
| 1293 | fn infer_expr_become(&mut self, expr: ExprId) -> Ty<'db> { | |
| 1385 | 1294 | match &self.return_coercion { |
| 1386 | 1295 | Some(return_coercion) => { |
| 1387 | let ret_ty = return_coercion.expected_ty().to_chalk(self.table.interner); | |
| 1296 | let ret_ty = return_coercion.expected_ty(); | |
| 1388 | 1297 | |
| 1389 | let call_expr_ty = self.infer_expr_inner( | |
| 1390 | expr, | |
| 1391 | &Expectation::HasType(ret_ty.clone()), | |
| 1392 | ExprIsRead::Yes, | |
| 1393 | ); | |
| 1298 | let call_expr_ty = | |
| 1299 | self.infer_expr_inner(expr, &Expectation::HasType(ret_ty), ExprIsRead::Yes); | |
| 1394 | 1300 | |
| 1395 | 1301 | // NB: this should *not* coerce. |
| 1396 | 1302 | // tail calls don't support any coercions except lifetimes ones (like `&'static u8 -> &'a u8`). |
| 1397 | self.unify(&call_expr_ty, &ret_ty); | |
| 1303 | self.unify(call_expr_ty, ret_ty); | |
| 1398 | 1304 | } |
| 1399 | 1305 | None => { |
| 1400 | 1306 | // FIXME: diagnose `become` outside of functions |
| ... | ... | @@ -1402,10 +1308,10 @@ impl<'db> InferenceContext<'db> { |
| 1402 | 1308 | } |
| 1403 | 1309 | } |
| 1404 | 1310 | |
| 1405 | self.result.standard_types.never.clone() | |
| 1311 | self.types.never | |
| 1406 | 1312 | } |
| 1407 | 1313 | |
| 1408 | fn infer_expr_box(&mut self, inner_expr: ExprId, expected: &Expectation) -> Ty { | |
| 1314 | fn infer_expr_box(&mut self, inner_expr: ExprId, expected: &Expectation<'db>) -> Ty<'db> { | |
| 1409 | 1315 | if let Some(box_id) = self.resolve_boxed_box() { |
| 1410 | 1316 | let table = &mut self.table; |
| 1411 | 1317 | let inner_exp = expected |
| ... | ... | @@ -1414,16 +1320,22 @@ impl<'db> InferenceContext<'db> { |
| 1414 | 1320 | .and_then(|e| e.as_adt()) |
| 1415 | 1321 | .filter(|(e_adt, _)| e_adt == &box_id) |
| 1416 | 1322 | .map(|(_, subts)| { |
| 1417 | let g = subts.at(Interner, 0); | |
| 1418 | Expectation::rvalue_hint(self, Ty::clone(g.assert_ty_ref(Interner))) | |
| 1323 | let g = subts.type_at(0); | |
| 1324 | Expectation::rvalue_hint(self, g) | |
| 1419 | 1325 | }) |
| 1420 | 1326 | .unwrap_or_else(Expectation::none); |
| 1421 | 1327 | |
| 1422 | 1328 | let inner_ty = self.infer_expr_inner(inner_expr, &inner_exp, ExprIsRead::Yes); |
| 1423 | TyBuilder::adt(self.db, box_id) | |
| 1424 | .push(inner_ty) | |
| 1425 | .fill_with_defaults(self.db, || self.table.new_type_var()) | |
| 1426 | .build() | |
| 1329 | Ty::new_adt( | |
| 1330 | self.interner(), | |
| 1331 | box_id, | |
| 1332 | GenericArgs::fill_with_defaults( | |
| 1333 | self.interner(), | |
| 1334 | box_id.into(), | |
| 1335 | [inner_ty.into()], | |
| 1336 | |_, _, id, _| self.table.next_var_for_param(id), | |
| 1337 | ), | |
| 1338 | ) | |
| 1427 | 1339 | } else { |
| 1428 | 1340 | self.err_ty() |
| 1429 | 1341 | } |
| ... | ... | @@ -1435,7 +1347,7 @@ impl<'db> InferenceContext<'db> { |
| 1435 | 1347 | op: BinaryOp, |
| 1436 | 1348 | rhs: ExprId, |
| 1437 | 1349 | tgt_expr: ExprId, |
| 1438 | ) -> Ty { | |
| 1350 | ) -> Ty<'db> { | |
| 1439 | 1351 | let lhs_expectation = Expectation::none(); |
| 1440 | 1352 | let is_read = if matches!(op, BinaryOp::Assignment { .. }) { |
| 1441 | 1353 | ExprIsRead::Yes |
| ... | ... | @@ -1443,24 +1355,24 @@ impl<'db> InferenceContext<'db> { |
| 1443 | 1355 | ExprIsRead::No |
| 1444 | 1356 | }; |
| 1445 | 1357 | let lhs_ty = self.infer_expr(lhs, &lhs_expectation, is_read); |
| 1446 | let rhs_ty = self.table.new_type_var(); | |
| 1358 | let rhs_ty = self.table.next_ty_var(); | |
| 1447 | 1359 | |
| 1448 | 1360 | let trait_func = lang_items_for_bin_op(op).and_then(|(name, lang_item)| { |
| 1449 | 1361 | let trait_id = self.resolve_lang_item(lang_item)?.as_trait()?; |
| 1450 | 1362 | let func = trait_id.trait_items(self.db).method_by_name(&name)?; |
| 1451 | 1363 | Some((trait_id, func)) |
| 1452 | 1364 | }); |
| 1453 | let (trait_, func) = match trait_func { | |
| 1454 | Some(it) => it, | |
| 1365 | let func = match trait_func { | |
| 1366 | Some((_, it)) => it, | |
| 1455 | 1367 | None => { |
| 1456 | 1368 | // HACK: `rhs_ty` is a general inference variable with no clue at all at this |
| 1457 | 1369 | // point. Passing `lhs_ty` as both operands just to check if `lhs_ty` is a builtin |
| 1458 | 1370 | // type applicable to `op`. |
| 1459 | let ret_ty = if self.is_builtin_binop(&lhs_ty, &lhs_ty, op) { | |
| 1371 | let ret_ty = if self.is_builtin_binop(lhs_ty, lhs_ty, op) { | |
| 1460 | 1372 | // Assume both operands are builtin so we can continue inference. No guarantee |
| 1461 | 1373 | // on the correctness, rustc would complain as necessary lang items don't seem |
| 1462 | 1374 | // to exist anyway. |
| 1463 | self.enforce_builtin_binop_types(&lhs_ty, &rhs_ty, op) | |
| 1375 | self.enforce_builtin_binop_types(lhs_ty, rhs_ty, op) | |
| 1464 | 1376 | } else { |
| 1465 | 1377 | self.err_ty() |
| 1466 | 1378 | }; |
| ... | ... | @@ -1473,59 +1385,53 @@ impl<'db> InferenceContext<'db> { |
| 1473 | 1385 | |
| 1474 | 1386 | // HACK: We can use this substitution for the function because the function itself doesn't |
| 1475 | 1387 | // have its own generic parameters. |
| 1476 | let subst = TyBuilder::subst_for_def(self.db, trait_, None); | |
| 1477 | if subst.remaining() != 2 { | |
| 1478 | return Ty::new(Interner, TyKind::Error); | |
| 1479 | } | |
| 1480 | let subst = subst.push(lhs_ty.clone()).push(rhs_ty.clone()).build(); | |
| 1388 | let args = GenericArgs::new_from_iter(self.interner(), [lhs_ty.into(), rhs_ty.into()]); | |
| 1481 | 1389 | |
| 1482 | self.write_method_resolution(tgt_expr, func, subst.clone()); | |
| 1390 | self.write_method_resolution(tgt_expr, func, args); | |
| 1483 | 1391 | |
| 1484 | let interner = DbInterner::new_with(self.db, None, None); | |
| 1485 | let args: crate::next_solver::GenericArgs<'_> = subst.to_nextsolver(interner); | |
| 1486 | let method_ty = | |
| 1487 | self.db.value_ty(func.into()).unwrap().instantiate(interner, args).to_chalk(interner); | |
| 1488 | self.register_obligations_for_call(&method_ty); | |
| 1392 | let method_ty = self.db.value_ty(func.into()).unwrap().instantiate(self.interner(), args); | |
| 1393 | self.register_obligations_for_call(method_ty); | |
| 1489 | 1394 | |
| 1490 | self.infer_expr_coerce(rhs, &Expectation::has_type(rhs_ty.clone()), ExprIsRead::Yes); | |
| 1395 | self.infer_expr_coerce(rhs, &Expectation::has_type(rhs_ty), ExprIsRead::Yes); | |
| 1491 | 1396 | |
| 1492 | let ret_ty = match method_ty.callable_sig(self.db) { | |
| 1397 | let ret_ty = match method_ty.callable_sig(self.interner()) { | |
| 1493 | 1398 | Some(sig) => { |
| 1494 | let p_left = &sig.params()[0]; | |
| 1399 | let sig = sig.skip_binder(); | |
| 1400 | let p_left = sig.inputs_and_output.as_slice()[0]; | |
| 1495 | 1401 | if matches!(op, BinaryOp::CmpOp(..) | BinaryOp::Assignment { .. }) |
| 1496 | && let TyKind::Ref(mtbl, lt, _) = p_left.kind(Interner) | |
| 1402 | && let TyKind::Ref(lt, _, mtbl) = p_left.kind() | |
| 1497 | 1403 | { |
| 1498 | 1404 | self.write_expr_adj( |
| 1499 | 1405 | lhs, |
| 1500 | 1406 | Box::new([Adjustment { |
| 1501 | kind: Adjust::Borrow(AutoBorrow::Ref(lt.clone(), *mtbl)), | |
| 1502 | target: p_left.clone(), | |
| 1407 | kind: Adjust::Borrow(AutoBorrow::Ref(lt, mtbl)), | |
| 1408 | target: p_left, | |
| 1503 | 1409 | }]), |
| 1504 | 1410 | ); |
| 1505 | 1411 | } |
| 1506 | let p_right = &sig.params()[1]; | |
| 1412 | let p_right = sig.inputs_and_output.as_slice()[1]; | |
| 1507 | 1413 | if matches!(op, BinaryOp::CmpOp(..)) |
| 1508 | && let TyKind::Ref(mtbl, lt, _) = p_right.kind(Interner) | |
| 1414 | && let TyKind::Ref(lt, _, mtbl) = p_right.kind() | |
| 1509 | 1415 | { |
| 1510 | 1416 | self.write_expr_adj( |
| 1511 | 1417 | rhs, |
| 1512 | 1418 | Box::new([Adjustment { |
| 1513 | kind: Adjust::Borrow(AutoBorrow::Ref(lt.clone(), *mtbl)), | |
| 1514 | target: p_right.clone(), | |
| 1419 | kind: Adjust::Borrow(AutoBorrow::Ref(lt, mtbl)), | |
| 1420 | target: p_right, | |
| 1515 | 1421 | }]), |
| 1516 | 1422 | ); |
| 1517 | 1423 | } |
| 1518 | sig.ret().clone() | |
| 1424 | sig.output() | |
| 1519 | 1425 | } |
| 1520 | 1426 | None => self.err_ty(), |
| 1521 | 1427 | }; |
| 1522 | 1428 | |
| 1523 | 1429 | let ret_ty = self.process_remote_user_written_ty(ret_ty); |
| 1524 | 1430 | |
| 1525 | if self.is_builtin_binop(&lhs_ty, &rhs_ty, op) { | |
| 1431 | if self.is_builtin_binop(lhs_ty, rhs_ty, op) { | |
| 1526 | 1432 | // use knowledge of built-in binary ops, which can sometimes help inference |
| 1527 | let builtin_ret = self.enforce_builtin_binop_types(&lhs_ty, &rhs_ty, op); | |
| 1528 | self.unify(&builtin_ret, &ret_ty); | |
| 1433 | let builtin_ret = self.enforce_builtin_binop_types(lhs_ty, rhs_ty, op); | |
| 1434 | self.unify(builtin_ret, ret_ty); | |
| 1529 | 1435 | builtin_ret |
| 1530 | 1436 | } else { |
| 1531 | 1437 | ret_ty |
| ... | ... | @@ -1539,8 +1445,8 @@ impl<'db> InferenceContext<'db> { |
| 1539 | 1445 | statements: &[Statement], |
| 1540 | 1446 | tail: Option<ExprId>, |
| 1541 | 1447 | label: Option<LabelId>, |
| 1542 | expected: &Expectation, | |
| 1543 | ) -> Ty { | |
| 1448 | expected: &Expectation<'db>, | |
| 1449 | ) -> Ty<'db> { | |
| 1544 | 1450 | let coerce_ty = expected.coercion_target_type(&mut self.table); |
| 1545 | 1451 | let g = self.resolver.update_to_inner_scope(self.db, self.owner, expr); |
| 1546 | 1452 | let prev_env = block_id.map(|block_id| { |
| ... | ... | @@ -1557,7 +1463,7 @@ impl<'db> InferenceContext<'db> { |
| 1557 | 1463 | let decl_ty = type_ref |
| 1558 | 1464 | .as_ref() |
| 1559 | 1465 | .map(|&tr| this.make_body_ty(tr)) |
| 1560 | .unwrap_or_else(|| this.table.new_type_var()); | |
| 1466 | .unwrap_or_else(|| this.table.next_ty_var()); | |
| 1561 | 1467 | |
| 1562 | 1468 | let ty = if let Some(expr) = initializer { |
| 1563 | 1469 | // If we have a subpattern that performs a read, we want to consider this |
| ... | ... | @@ -1571,13 +1477,13 @@ impl<'db> InferenceContext<'db> { |
| 1571 | 1477 | let ty = if contains_explicit_ref_binding(this.body, *pat) { |
| 1572 | 1478 | this.infer_expr( |
| 1573 | 1479 | *expr, |
| 1574 | &Expectation::has_type(decl_ty.clone()), | |
| 1480 | &Expectation::has_type(decl_ty), | |
| 1575 | 1481 | target_is_read, |
| 1576 | 1482 | ) |
| 1577 | 1483 | } else { |
| 1578 | 1484 | this.infer_expr_coerce( |
| 1579 | 1485 | *expr, |
| 1580 | &Expectation::has_type(decl_ty.clone()), | |
| 1486 | &Expectation::has_type(decl_ty), | |
| 1581 | 1487 | target_is_read, |
| 1582 | 1488 | ) |
| 1583 | 1489 | }; |
| ... | ... | @@ -1590,13 +1496,13 @@ impl<'db> InferenceContext<'db> { |
| 1590 | 1496 | origin: DeclOrigin::LocalDecl { has_else: else_branch.is_some() }, |
| 1591 | 1497 | }; |
| 1592 | 1498 | |
| 1593 | this.infer_top_pat(*pat, &ty, Some(decl)); | |
| 1499 | this.infer_top_pat(*pat, ty, Some(decl)); | |
| 1594 | 1500 | if let Some(expr) = else_branch { |
| 1595 | 1501 | let previous_diverges = |
| 1596 | 1502 | mem::replace(&mut this.diverges, Diverges::Maybe); |
| 1597 | 1503 | this.infer_expr_coerce( |
| 1598 | 1504 | *expr, |
| 1599 | &Expectation::HasType(this.result.standard_types.never.clone()), | |
| 1505 | &Expectation::HasType(this.types.never), | |
| 1600 | 1506 | ExprIsRead::Yes, |
| 1601 | 1507 | ); |
| 1602 | 1508 | this.diverges = previous_diverges; |
| ... | ... | @@ -1608,7 +1514,7 @@ impl<'db> InferenceContext<'db> { |
| 1608 | 1514 | } else { |
| 1609 | 1515 | this.infer_expr_coerce( |
| 1610 | 1516 | expr, |
| 1611 | &Expectation::HasType(this.result.standard_types.unit.clone()), | |
| 1517 | &Expectation::HasType(this.types.unit), | |
| 1612 | 1518 | ExprIsRead::Yes, |
| 1613 | 1519 | ); |
| 1614 | 1520 | } |
| ... | ... | @@ -1642,8 +1548,8 @@ impl<'db> InferenceContext<'db> { |
| 1642 | 1548 | if this |
| 1643 | 1549 | .coerce( |
| 1644 | 1550 | expr.into(), |
| 1645 | this.result.standard_types.unit.to_nextsolver(this.table.interner), | |
| 1646 | t.to_nextsolver(this.table.interner), | |
| 1551 | this.types.unit, | |
| 1552 | t, | |
| 1647 | 1553 | AllowTwoPhase::No, |
| 1648 | 1554 | coerce_never, |
| 1649 | 1555 | ) |
| ... | ... | @@ -1651,15 +1557,12 @@ impl<'db> InferenceContext<'db> { |
| 1651 | 1557 | { |
| 1652 | 1558 | this.result.type_mismatches.insert( |
| 1653 | 1559 | expr.into(), |
| 1654 | TypeMismatch { | |
| 1655 | expected: t.clone(), | |
| 1656 | actual: this.result.standard_types.unit.clone(), | |
| 1657 | }, | |
| 1560 | TypeMismatch { expected: t, actual: this.types.unit }, | |
| 1658 | 1561 | ); |
| 1659 | 1562 | } |
| 1660 | 1563 | t |
| 1661 | 1564 | } else { |
| 1662 | this.result.standard_types.unit.clone() | |
| 1565 | this.types.unit | |
| 1663 | 1566 | } |
| 1664 | 1567 | } |
| 1665 | 1568 | }); |
| ... | ... | @@ -1673,32 +1576,30 @@ impl<'db> InferenceContext<'db> { |
| 1673 | 1576 | |
| 1674 | 1577 | fn lookup_field( |
| 1675 | 1578 | &mut self, |
| 1676 | receiver_ty: &Ty, | |
| 1579 | receiver_ty: Ty<'db>, | |
| 1677 | 1580 | name: &Name, |
| 1678 | ) -> Option<(Ty, Either<FieldId, TupleFieldId>, Vec<Adjustment>, bool)> { | |
| 1679 | let interner = self.table.interner; | |
| 1680 | let mut autoderef = self.table.autoderef(receiver_ty.to_nextsolver(self.table.interner)); | |
| 1581 | ) -> Option<(Ty<'db>, Either<FieldId, TupleFieldId>, Vec<Adjustment<'db>>, bool)> { | |
| 1582 | let interner = self.interner(); | |
| 1583 | let mut autoderef = self.table.autoderef(receiver_ty); | |
| 1681 | 1584 | let mut private_field = None; |
| 1682 | 1585 | let res = autoderef.by_ref().find_map(|(derefed_ty, _)| { |
| 1683 | 1586 | let (field_id, parameters) = match derefed_ty.kind() { |
| 1684 | crate::next_solver::TyKind::Tuple(substs) => { | |
| 1587 | TyKind::Tuple(substs) => { | |
| 1685 | 1588 | return name.as_tuple_index().and_then(|idx| { |
| 1686 | 1589 | substs.as_slice().get(idx).copied().map(|ty| { |
| 1687 | 1590 | ( |
| 1688 | 1591 | Either::Right(TupleFieldId { |
| 1689 | 1592 | tuple: TupleId( |
| 1690 | self.tuple_field_accesses_rev | |
| 1691 | .insert_full(substs.to_chalk(interner)) | |
| 1692 | .0 as u32, | |
| 1593 | self.tuple_field_accesses_rev.insert_full(substs).0 as u32, | |
| 1693 | 1594 | ), |
| 1694 | 1595 | index: idx as u32, |
| 1695 | 1596 | }), |
| 1696 | ty.to_chalk(interner), | |
| 1597 | ty, | |
| 1697 | 1598 | ) |
| 1698 | 1599 | }) |
| 1699 | 1600 | }); |
| 1700 | 1601 | } |
| 1701 | crate::next_solver::TyKind::Adt(adt, parameters) => match adt.def_id().0 { | |
| 1602 | TyKind::Adt(adt, parameters) => match adt.def_id().0 { | |
| 1702 | 1603 | hir_def::AdtId::StructId(s) => { |
| 1703 | 1604 | let local_id = s.fields(self.db).field(name)?; |
| 1704 | 1605 | let field = FieldId { parent: s.into(), local_id }; |
| ... | ... | @@ -1713,18 +1614,16 @@ impl<'db> InferenceContext<'db> { |
| 1713 | 1614 | }, |
| 1714 | 1615 | _ => return None, |
| 1715 | 1616 | }; |
| 1716 | let parameters: crate::Substitution = parameters.to_chalk(interner); | |
| 1717 | 1617 | let is_visible = self.db.field_visibilities(field_id.parent)[field_id.local_id] |
| 1718 | 1618 | .is_visible_from(self.db, self.resolver.module()); |
| 1719 | 1619 | if !is_visible { |
| 1720 | 1620 | if private_field.is_none() { |
| 1721 | private_field = Some((field_id, parameters.clone())); | |
| 1621 | private_field = Some((field_id, parameters)); | |
| 1722 | 1622 | } |
| 1723 | 1623 | return None; |
| 1724 | 1624 | } |
| 1725 | let ty = self.db.field_types(field_id.parent)[field_id.local_id] | |
| 1726 | .clone() | |
| 1727 | .substitute(Interner, &parameters); | |
| 1625 | let ty = self.db.field_types_ns(field_id.parent)[field_id.local_id] | |
| 1626 | .instantiate(interner, parameters); | |
| 1728 | 1627 | Some((Either::Left(field_id), ty)) |
| 1729 | 1628 | }); |
| 1730 | 1629 | |
| ... | ... | @@ -1738,9 +1637,8 @@ impl<'db> InferenceContext<'db> { |
| 1738 | 1637 | None => { |
| 1739 | 1638 | let (field_id, subst) = private_field?; |
| 1740 | 1639 | let adjustments = autoderef.adjust_steps(); |
| 1741 | let ty = self.db.field_types(field_id.parent)[field_id.local_id] | |
| 1742 | .clone() | |
| 1743 | .substitute(Interner, &subst); | |
| 1640 | let ty = self.db.field_types_ns(field_id.parent)[field_id.local_id] | |
| 1641 | .instantiate(self.interner(), subst); | |
| 1744 | 1642 | let ty = self.process_remote_user_written_ty(ty); |
| 1745 | 1643 | |
| 1746 | 1644 | (ty, Either::Left(field_id), adjustments, false) |
| ... | ... | @@ -1753,8 +1651,8 @@ impl<'db> InferenceContext<'db> { |
| 1753 | 1651 | tgt_expr: ExprId, |
| 1754 | 1652 | receiver: ExprId, |
| 1755 | 1653 | name: &Name, |
| 1756 | expected: &Expectation, | |
| 1757 | ) -> Ty { | |
| 1654 | expected: &Expectation<'db>, | |
| 1655 | ) -> Ty<'db> { | |
| 1758 | 1656 | // Field projections don't constitute reads. |
| 1759 | 1657 | let receiver_ty = self.infer_expr_inner(receiver, &Expectation::none(), ExprIsRead::No); |
| 1760 | 1658 | |
| ... | ... | @@ -1764,7 +1662,7 @@ impl<'db> InferenceContext<'db> { |
| 1764 | 1662 | return self.err_ty(); |
| 1765 | 1663 | } |
| 1766 | 1664 | |
| 1767 | match self.lookup_field(&receiver_ty, name) { | |
| 1665 | match self.lookup_field(receiver_ty, name) { | |
| 1768 | 1666 | Some((ty, field_id, adjustments, is_public)) => { |
| 1769 | 1667 | self.write_expr_adj(receiver, adjustments.into_boxed_slice()); |
| 1770 | 1668 | self.result.field_resolutions.insert(tgt_expr, field_id); |
| ... | ... | @@ -1780,8 +1678,7 @@ impl<'db> InferenceContext<'db> { |
| 1780 | 1678 | None => { |
| 1781 | 1679 | // no field found, lets attempt to resolve it like a function so that IDE things |
| 1782 | 1680 | // work out while people are typing |
| 1783 | let canonicalized_receiver = | |
| 1784 | self.canonicalize(receiver_ty.clone().to_nextsolver(self.table.interner)); | |
| 1681 | let canonicalized_receiver = self.canonicalize(receiver_ty); | |
| 1785 | 1682 | let resolved = method_resolution::lookup_method( |
| 1786 | 1683 | self.db, |
| 1787 | 1684 | &canonicalized_receiver, |
| ... | ... | @@ -1792,28 +1689,24 @@ impl<'db> InferenceContext<'db> { |
| 1792 | 1689 | ); |
| 1793 | 1690 | self.push_diagnostic(InferenceDiagnostic::UnresolvedField { |
| 1794 | 1691 | expr: tgt_expr, |
| 1795 | receiver: receiver_ty.clone(), | |
| 1692 | receiver: receiver_ty, | |
| 1796 | 1693 | name: name.clone(), |
| 1797 | 1694 | method_with_same_name_exists: resolved.is_some(), |
| 1798 | 1695 | }); |
| 1799 | 1696 | match resolved { |
| 1800 | 1697 | Some((adjust, func, _)) => { |
| 1801 | 1698 | let (ty, adjustments) = adjust.apply(&mut self.table, receiver_ty); |
| 1802 | let substs = self.substs_for_method_call(tgt_expr, func.into(), None); | |
| 1699 | let args = self.substs_for_method_call(tgt_expr, func.into(), None); | |
| 1803 | 1700 | self.write_expr_adj(receiver, adjustments.into_boxed_slice()); |
| 1804 | self.write_method_resolution(tgt_expr, func, substs.clone()); | |
| 1701 | self.write_method_resolution(tgt_expr, func, args); | |
| 1805 | 1702 | |
| 1806 | let interner = DbInterner::new_with(self.db, None, None); | |
| 1807 | let args: crate::next_solver::GenericArgs<'_> = | |
| 1808 | substs.to_nextsolver(interner); | |
| 1809 | 1703 | self.check_method_call( |
| 1810 | 1704 | tgt_expr, |
| 1811 | 1705 | &[], |
| 1812 | 1706 | self.db |
| 1813 | 1707 | .value_ty(func.into()) |
| 1814 | 1708 | .unwrap() |
| 1815 | .instantiate(interner, args) | |
| 1816 | .to_chalk(interner), | |
| 1709 | .instantiate(self.interner(), args), | |
| 1817 | 1710 | ty, |
| 1818 | 1711 | expected, |
| 1819 | 1712 | ) |
| ... | ... | @@ -1829,47 +1722,42 @@ impl<'db> InferenceContext<'db> { |
| 1829 | 1722 | tgt_expr: ExprId, |
| 1830 | 1723 | callee: ExprId, |
| 1831 | 1724 | args: &[ExprId], |
| 1832 | expected: &Expectation, | |
| 1833 | ) -> Ty { | |
| 1725 | expected: &Expectation<'db>, | |
| 1726 | ) -> Ty<'db> { | |
| 1834 | 1727 | let callee_ty = self.infer_expr(callee, &Expectation::none(), ExprIsRead::Yes); |
| 1835 | let interner = self.table.interner; | |
| 1836 | let mut derefs = self.table.autoderef(callee_ty.to_nextsolver(interner)); | |
| 1728 | let interner = self.interner(); | |
| 1729 | let mut derefs = self.table.autoderef(callee_ty); | |
| 1837 | 1730 | let (res, derefed_callee) = loop { |
| 1838 | 1731 | let Some((callee_deref_ty, _)) = derefs.next() else { |
| 1839 | break (None, callee_ty.clone()); | |
| 1732 | break (None, callee_ty); | |
| 1840 | 1733 | }; |
| 1841 | let callee_deref_ty = callee_deref_ty.to_chalk(interner); | |
| 1842 | if let Some(res) = derefs.table.callable_sig(&callee_deref_ty, args.len()) { | |
| 1734 | if let Some(res) = derefs.table.callable_sig(callee_deref_ty, args.len()) { | |
| 1843 | 1735 | break (Some(res), callee_deref_ty); |
| 1844 | 1736 | } |
| 1845 | 1737 | }; |
| 1846 | 1738 | // if the function is unresolved, we use is_varargs=true to |
| 1847 | 1739 | // suppress the arg count diagnostic here |
| 1848 | let is_varargs = | |
| 1849 | derefed_callee.callable_sig(self.db).is_some_and(|sig| sig.is_varargs) || res.is_none(); | |
| 1740 | let is_varargs = derefed_callee.callable_sig(interner).is_some_and(|sig| sig.c_variadic()) | |
| 1741 | || res.is_none(); | |
| 1850 | 1742 | let (param_tys, ret_ty) = match res { |
| 1851 | 1743 | Some((func, params, ret_ty)) => { |
| 1852 | let params_chalk = | |
| 1853 | params.iter().map(|param| param.to_chalk(interner)).collect::<Vec<_>>(); | |
| 1854 | 1744 | let mut adjustments = derefs.adjust_steps(); |
| 1855 | 1745 | if let Some(fn_x) = func { |
| 1856 | 1746 | self.write_fn_trait_method_resolution( |
| 1857 | 1747 | fn_x, |
| 1858 | &derefed_callee, | |
| 1748 | derefed_callee, | |
| 1859 | 1749 | &mut adjustments, |
| 1860 | &callee_ty, | |
| 1861 | &params_chalk, | |
| 1750 | callee_ty, | |
| 1751 | &params, | |
| 1862 | 1752 | tgt_expr, |
| 1863 | 1753 | ); |
| 1864 | 1754 | } |
| 1865 | if let &TyKind::Closure(c, _) = | |
| 1866 | self.table.resolve_completely(callee_ty.clone()).kind(Interner) | |
| 1867 | { | |
| 1755 | if let TyKind::Closure(c, _) = self.table.resolve_completely(callee_ty).kind() { | |
| 1868 | 1756 | self.add_current_closure_dependency(c.into()); |
| 1869 | 1757 | self.deferred_closures.entry(c.into()).or_default().push(( |
| 1870 | derefed_callee.clone(), | |
| 1871 | callee_ty.clone(), | |
| 1872 | params_chalk, | |
| 1758 | derefed_callee, | |
| 1759 | callee_ty, | |
| 1760 | params.clone(), | |
| 1873 | 1761 | tgt_expr, |
| 1874 | 1762 | )); |
| 1875 | 1763 | } |
| ... | ... | @@ -1879,9 +1767,9 @@ impl<'db> InferenceContext<'db> { |
| 1879 | 1767 | None => { |
| 1880 | 1768 | self.push_diagnostic(InferenceDiagnostic::ExpectedFunction { |
| 1881 | 1769 | call_expr: tgt_expr, |
| 1882 | found: callee_ty.clone(), | |
| 1770 | found: callee_ty, | |
| 1883 | 1771 | }); |
| 1884 | (Vec::new(), crate::next_solver::Ty::new_error(interner, ErrorGuaranteed)) | |
| 1772 | (Vec::new(), Ty::new_error(interner, ErrorGuaranteed)) | |
| 1885 | 1773 | } |
| 1886 | 1774 | }; |
| 1887 | 1775 | let indices_to_skip = self.check_legacy_const_generics(derefed_callee, args); |
| ... | ... | @@ -1901,14 +1789,14 @@ impl<'db> InferenceContext<'db> { |
| 1901 | 1789 | &mut self, |
| 1902 | 1790 | tgt_expr: ExprId, |
| 1903 | 1791 | args: &[ExprId], |
| 1904 | callee_ty: Ty, | |
| 1905 | param_tys: &[crate::next_solver::Ty<'db>], | |
| 1906 | ret_ty: crate::next_solver::Ty<'db>, | |
| 1792 | callee_ty: Ty<'db>, | |
| 1793 | param_tys: &[Ty<'db>], | |
| 1794 | ret_ty: Ty<'db>, | |
| 1907 | 1795 | indices_to_skip: &[u32], |
| 1908 | 1796 | is_varargs: bool, |
| 1909 | expected: &Expectation, | |
| 1910 | ) -> Ty { | |
| 1911 | self.register_obligations_for_call(&callee_ty); | |
| 1797 | expected: &Expectation<'db>, | |
| 1798 | ) -> Ty<'db> { | |
| 1799 | self.register_obligations_for_call(callee_ty); | |
| 1912 | 1800 | |
| 1913 | 1801 | self.check_call_arguments( |
| 1914 | 1802 | tgt_expr, |
| ... | ... | @@ -1919,7 +1807,7 @@ impl<'db> InferenceContext<'db> { |
| 1919 | 1807 | indices_to_skip, |
| 1920 | 1808 | is_varargs, |
| 1921 | 1809 | ); |
| 1922 | self.table.normalize_associated_types_in_ns(ret_ty).to_chalk(self.table.interner) | |
| 1810 | self.table.normalize_associated_types_in(ret_ty) | |
| 1923 | 1811 | } |
| 1924 | 1812 | |
| 1925 | 1813 | fn infer_method_call( |
| ... | ... | @@ -1928,16 +1816,13 @@ impl<'db> InferenceContext<'db> { |
| 1928 | 1816 | receiver: ExprId, |
| 1929 | 1817 | args: &[ExprId], |
| 1930 | 1818 | method_name: &Name, |
| 1931 | generic_args: Option<&GenericArgs>, | |
| 1932 | expected: &Expectation, | |
| 1933 | ) -> Ty { | |
| 1819 | generic_args: Option<&HirGenericArgs>, | |
| 1820 | expected: &Expectation<'db>, | |
| 1821 | ) -> Ty<'db> { | |
| 1934 | 1822 | let receiver_ty = self.infer_expr_inner(receiver, &Expectation::none(), ExprIsRead::Yes); |
| 1935 | let receiver_ty = self.table.structurally_resolve_type(&receiver_ty); | |
| 1823 | let receiver_ty = self.table.try_structurally_resolve_type(receiver_ty); | |
| 1936 | 1824 | |
| 1937 | if matches!( | |
| 1938 | receiver_ty.kind(Interner), | |
| 1939 | TyKind::Error | TyKind::InferenceVar(_, TyVariableKind::General) | |
| 1940 | ) { | |
| 1825 | if matches!(receiver_ty.kind(), TyKind::Error(_) | TyKind::Infer(InferTy::TyVar(_))) { | |
| 1941 | 1826 | // Don't probe on error type, or on a fully unresolved infer var. |
| 1942 | 1827 | // FIXME: Emit an error if we're probing on an infer var (type annotations needed). |
| 1943 | 1828 | for &arg in args { |
| ... | ... | @@ -1947,8 +1832,7 @@ impl<'db> InferenceContext<'db> { |
| 1947 | 1832 | return receiver_ty; |
| 1948 | 1833 | } |
| 1949 | 1834 | |
| 1950 | let canonicalized_receiver = | |
| 1951 | self.canonicalize(receiver_ty.clone().to_nextsolver(self.table.interner)); | |
| 1835 | let canonicalized_receiver = self.canonicalize(receiver_ty); | |
| 1952 | 1836 | |
| 1953 | 1837 | let resolved = method_resolution::lookup_method( |
| 1954 | 1838 | self.db, |
| ... | ... | @@ -1970,18 +1854,16 @@ impl<'db> InferenceContext<'db> { |
| 1970 | 1854 | let (ty, adjustments) = adjust.apply(&mut self.table, receiver_ty); |
| 1971 | 1855 | self.write_expr_adj(receiver, adjustments.into_boxed_slice()); |
| 1972 | 1856 | |
| 1973 | let substs = self.substs_for_method_call(tgt_expr, func.into(), generic_args); | |
| 1974 | self.write_method_resolution(tgt_expr, func, substs.clone()); | |
| 1857 | let gen_args = self.substs_for_method_call(tgt_expr, func.into(), generic_args); | |
| 1858 | self.write_method_resolution(tgt_expr, func, gen_args); | |
| 1975 | 1859 | let interner = DbInterner::new_with(self.db, None, None); |
| 1976 | let gen_args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 1977 | 1860 | self.check_method_call( |
| 1978 | 1861 | tgt_expr, |
| 1979 | 1862 | args, |
| 1980 | 1863 | self.db |
| 1981 | 1864 | .value_ty(func.into()) |
| 1982 | 1865 | .expect("we have a function def") |
| 1983 | .instantiate(interner, gen_args) | |
| 1984 | .to_chalk(interner), | |
| 1866 | .instantiate(interner, gen_args), | |
| 1985 | 1867 | ty, |
| 1986 | 1868 | expected, |
| 1987 | 1869 | ) |
| ... | ... | @@ -1989,7 +1871,7 @@ impl<'db> InferenceContext<'db> { |
| 1989 | 1871 | // Failed to resolve, report diagnostic and try to resolve as call to field access or |
| 1990 | 1872 | // assoc function |
| 1991 | 1873 | None => { |
| 1992 | let field_with_same_name_exists = match self.lookup_field(&receiver_ty, method_name) | |
| 1874 | let field_with_same_name_exists = match self.lookup_field(receiver_ty, method_name) | |
| 1993 | 1875 | { |
| 1994 | 1876 | Some((ty, field_id, adjustments, _public)) => { |
| 1995 | 1877 | self.write_expr_adj(receiver, adjustments.into_boxed_slice()); |
| ... | ... | @@ -2017,48 +1899,46 @@ impl<'db> InferenceContext<'db> { |
| 2017 | 1899 | |
| 2018 | 1900 | self.push_diagnostic(InferenceDiagnostic::UnresolvedMethodCall { |
| 2019 | 1901 | expr: tgt_expr, |
| 2020 | receiver: receiver_ty.clone(), | |
| 1902 | receiver: receiver_ty, | |
| 2021 | 1903 | name: method_name.clone(), |
| 2022 | field_with_same_name: field_with_same_name_exists.clone(), | |
| 1904 | field_with_same_name: field_with_same_name_exists, | |
| 2023 | 1905 | assoc_func_with_same_name, |
| 2024 | 1906 | }); |
| 2025 | 1907 | |
| 2026 | 1908 | let recovered = match assoc_func_with_same_name { |
| 2027 | 1909 | Some(f) => { |
| 2028 | let substs = self.substs_for_method_call(tgt_expr, f.into(), generic_args); | |
| 1910 | let args = self.substs_for_method_call(tgt_expr, f.into(), generic_args); | |
| 2029 | 1911 | let interner = DbInterner::new_with(self.db, None, None); |
| 2030 | let args: crate::next_solver::GenericArgs<'_> = | |
| 2031 | substs.to_nextsolver(interner); | |
| 2032 | 1912 | let f = self |
| 2033 | 1913 | .db |
| 2034 | 1914 | .value_ty(f.into()) |
| 2035 | 1915 | .expect("we have a function def") |
| 2036 | .instantiate(interner, args) | |
| 2037 | .to_chalk(interner); | |
| 2038 | let sig = f.callable_sig(self.db).expect("we have a function def"); | |
| 1916 | .instantiate(interner, args); | |
| 1917 | let sig = f.callable_sig(self.interner()).expect("we have a function def"); | |
| 2039 | 1918 | Some((f, sig, true)) |
| 2040 | 1919 | } |
| 2041 | 1920 | None => field_with_same_name_exists.and_then(|field_ty| { |
| 2042 | let callable_sig = field_ty.callable_sig(self.db)?; | |
| 1921 | let callable_sig = field_ty.callable_sig(self.interner())?; | |
| 2043 | 1922 | Some((field_ty, callable_sig, false)) |
| 2044 | 1923 | }), |
| 2045 | 1924 | }; |
| 2046 | 1925 | match recovered { |
| 2047 | Some((callee_ty, sig, strip_first)) => self.check_call( | |
| 2048 | tgt_expr, | |
| 2049 | args, | |
| 2050 | callee_ty, | |
| 2051 | &sig.params() | |
| 2052 | .get(strip_first as usize..) | |
| 2053 | .unwrap_or(&[]) | |
| 2054 | .iter() | |
| 2055 | .map(|param| param.to_nextsolver(self.table.interner)) | |
| 2056 | .collect::<Vec<_>>(), | |
| 2057 | sig.ret().to_nextsolver(self.table.interner), | |
| 2058 | &[], | |
| 2059 | true, | |
| 2060 | expected, | |
| 2061 | ), | |
| 1926 | Some((callee_ty, sig, strip_first)) => { | |
| 1927 | let sig = sig.skip_binder(); | |
| 1928 | self.check_call( | |
| 1929 | tgt_expr, | |
| 1930 | args, | |
| 1931 | callee_ty, | |
| 1932 | sig.inputs_and_output | |
| 1933 | .inputs() | |
| 1934 | .get(strip_first as usize..) | |
| 1935 | .unwrap_or(&[]), | |
| 1936 | sig.output(), | |
| 1937 | &[], | |
| 1938 | true, | |
| 1939 | expected, | |
| 1940 | ) | |
| 1941 | } | |
| 2062 | 1942 | None => { |
| 2063 | 1943 | for &arg in args.iter() { |
| 2064 | 1944 | self.infer_expr_no_expect(arg, ExprIsRead::Yes); |
| ... | ... | @@ -2074,39 +1954,38 @@ impl<'db> InferenceContext<'db> { |
| 2074 | 1954 | &mut self, |
| 2075 | 1955 | tgt_expr: ExprId, |
| 2076 | 1956 | args: &[ExprId], |
| 2077 | method_ty: Ty, | |
| 2078 | receiver_ty: Ty, | |
| 2079 | expected: &Expectation, | |
| 2080 | ) -> Ty { | |
| 2081 | self.register_obligations_for_call(&method_ty); | |
| 2082 | let interner = self.table.interner; | |
| 1957 | method_ty: Ty<'db>, | |
| 1958 | receiver_ty: Ty<'db>, | |
| 1959 | expected: &Expectation<'db>, | |
| 1960 | ) -> Ty<'db> { | |
| 1961 | self.register_obligations_for_call(method_ty); | |
| 2083 | 1962 | let ((formal_receiver_ty, param_tys), ret_ty, is_varargs) = |
| 2084 | match method_ty.callable_sig(self.db) { | |
| 2085 | Some(sig) => ( | |
| 2086 | if !sig.params().is_empty() { | |
| 2087 | ( | |
| 2088 | sig.params()[0].to_nextsolver(interner), | |
| 2089 | sig.params()[1..] | |
| 2090 | .iter() | |
| 2091 | .map(|param| param.to_nextsolver(interner)) | |
| 2092 | .collect(), | |
| 2093 | ) | |
| 2094 | } else { | |
| 2095 | (crate::next_solver::Ty::new_error(interner, ErrorGuaranteed), Vec::new()) | |
| 2096 | }, | |
| 2097 | sig.ret().to_nextsolver(interner), | |
| 2098 | sig.is_varargs, | |
| 2099 | ), | |
| 1963 | match method_ty.callable_sig(self.interner()) { | |
| 1964 | Some(sig) => { | |
| 1965 | let sig = sig.skip_binder(); | |
| 1966 | ( | |
| 1967 | if !sig.inputs_and_output.inputs().is_empty() { | |
| 1968 | ( | |
| 1969 | sig.inputs_and_output.as_slice()[0], | |
| 1970 | sig.inputs_and_output.inputs()[1..].to_vec(), | |
| 1971 | ) | |
| 1972 | } else { | |
| 1973 | (self.types.error, Vec::new()) | |
| 1974 | }, | |
| 1975 | sig.output(), | |
| 1976 | sig.c_variadic, | |
| 1977 | ) | |
| 1978 | } | |
| 2100 | 1979 | None => { |
| 2101 | 1980 | let formal_receiver_ty = self.table.next_ty_var(); |
| 2102 | 1981 | let ret_ty = self.table.next_ty_var(); |
| 2103 | 1982 | ((formal_receiver_ty, Vec::new()), ret_ty, true) |
| 2104 | 1983 | } |
| 2105 | 1984 | }; |
| 2106 | self.table.unify_ns(formal_receiver_ty, receiver_ty.to_nextsolver(interner)); | |
| 1985 | self.table.unify(formal_receiver_ty, receiver_ty); | |
| 2107 | 1986 | |
| 2108 | 1987 | self.check_call_arguments(tgt_expr, &param_tys, ret_ty, expected, args, &[], is_varargs); |
| 2109 | self.table.normalize_associated_types_in_ns(ret_ty).to_chalk(interner) | |
| 1988 | self.table.normalize_associated_types_in(ret_ty) | |
| 2110 | 1989 | } |
| 2111 | 1990 | |
| 2112 | 1991 | /// Generic function that factors out common logic from function calls, |
| ... | ... | @@ -2115,18 +1994,16 @@ impl<'db> InferenceContext<'db> { |
| 2115 | 1994 | &mut self, |
| 2116 | 1995 | call_expr: ExprId, |
| 2117 | 1996 | // Types (as defined in the *signature* of the target function) |
| 2118 | formal_input_tys: &[crate::next_solver::Ty<'db>], | |
| 2119 | formal_output: crate::next_solver::Ty<'db>, | |
| 1997 | formal_input_tys: &[Ty<'db>], | |
| 1998 | formal_output: Ty<'db>, | |
| 2120 | 1999 | // Expected output from the parent expression or statement |
| 2121 | expectation: &Expectation, | |
| 2000 | expectation: &Expectation<'db>, | |
| 2122 | 2001 | // The expressions for each provided argument |
| 2123 | 2002 | provided_args: &[ExprId], |
| 2124 | 2003 | skip_indices: &[u32], |
| 2125 | 2004 | // Whether the function is variadic, for example when imported from C |
| 2126 | 2005 | c_variadic: bool, |
| 2127 | 2006 | ) { |
| 2128 | let interner = self.table.interner; | |
| 2129 | ||
| 2130 | 2007 | // First, let's unify the formal method signature with the expectation eagerly. |
| 2131 | 2008 | // We use this to guide coercion inference; it's output is "fudged" which means |
| 2132 | 2009 | // any remaining type variables are assigned to new, unrelated variables. This |
| ... | ... | @@ -2145,14 +2022,9 @@ impl<'db> InferenceContext<'db> { |
| 2145 | 2022 | // is polymorphic) and the expected return type. |
| 2146 | 2023 | // No argument expectations are produced if unification fails. |
| 2147 | 2024 | let origin = ObligationCause::new(); |
| 2148 | ocx.sup( | |
| 2149 | &origin, | |
| 2150 | self.table.trait_env.env, | |
| 2151 | expected_output.to_nextsolver(interner), | |
| 2152 | formal_output, | |
| 2153 | )?; | |
| 2025 | ocx.sup(&origin, self.table.trait_env.env, expected_output, formal_output)?; | |
| 2154 | 2026 | if !ocx.try_evaluate_obligations().is_empty() { |
| 2155 | return Err(crate::next_solver::TypeError::Mismatch); | |
| 2027 | return Err(TypeError::Mismatch); | |
| 2156 | 2028 | } |
| 2157 | 2029 | |
| 2158 | 2030 | // Record all the argument types, with the args |
| ... | ... | @@ -2200,9 +2072,9 @@ impl<'db> InferenceContext<'db> { |
| 2200 | 2072 | // We introduce a helper function to demand that a given argument satisfy a given input |
| 2201 | 2073 | // This is more complicated than just checking type equality, as arguments could be coerced |
| 2202 | 2074 | // This version writes those types back so further type checking uses the narrowed types |
| 2203 | let demand_compatible = |this: &mut InferenceContext<'db>, idx| { | |
| 2204 | let formal_input_ty: crate::next_solver::Ty<'db> = formal_input_tys[idx]; | |
| 2205 | let expected_input_ty: crate::next_solver::Ty<'db> = expected_input_tys[idx]; | |
| 2075 | let demand_compatible = |this: &mut InferenceContext<'_, 'db>, idx| { | |
| 2076 | let formal_input_ty: Ty<'db> = formal_input_tys[idx]; | |
| 2077 | let expected_input_ty: Ty<'db> = expected_input_tys[idx]; | |
| 2206 | 2078 | let provided_arg = provided_args[idx]; |
| 2207 | 2079 | |
| 2208 | 2080 | debug!("checking argument {}: {:?} = {:?}", idx, provided_arg, formal_input_ty); |
| ... | ... | @@ -2210,19 +2082,14 @@ impl<'db> InferenceContext<'db> { |
| 2210 | 2082 | // We're on the happy path here, so we'll do a more involved check and write back types |
| 2211 | 2083 | // To check compatibility, we'll do 3 things: |
| 2212 | 2084 | // 1. Unify the provided argument with the expected type |
| 2213 | let expectation = Expectation::rvalue_hint(this, expected_input_ty.to_chalk(interner)); | |
| 2085 | let expectation = Expectation::rvalue_hint(this, expected_input_ty); | |
| 2214 | 2086 | |
| 2215 | let checked_ty = this | |
| 2216 | .infer_expr_inner(provided_arg, &expectation, ExprIsRead::Yes) | |
| 2217 | .to_nextsolver(interner); | |
| 2087 | let checked_ty = this.infer_expr_inner(provided_arg, &expectation, ExprIsRead::Yes); | |
| 2218 | 2088 | |
| 2219 | 2089 | // 2. Coerce to the most detailed type that could be coerced |
| 2220 | 2090 | // to, which is `expected_ty` if `rvalue_hint` returns an |
| 2221 | 2091 | // `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise. |
| 2222 | let coerced_ty = expectation | |
| 2223 | .only_has_type(&mut this.table) | |
| 2224 | .map(|it| it.to_nextsolver(interner)) | |
| 2225 | .unwrap_or(formal_input_ty); | |
| 2092 | let coerced_ty = expectation.only_has_type(&mut this.table).unwrap_or(formal_input_ty); | |
| 2226 | 2093 | |
| 2227 | 2094 | // Cause selection errors caused by resolving a single argument to point at the |
| 2228 | 2095 | // argument and not the call. This lets us customize the span pointed to in the |
| ... | ... | @@ -2259,7 +2126,7 @@ impl<'db> InferenceContext<'db> { |
| 2259 | 2126 | |
| 2260 | 2127 | // If neither check failed, the types are compatible |
| 2261 | 2128 | match formal_ty_error { |
| 2262 | Ok(crate::next_solver::infer::InferOk { obligations, value: () }) => { | |
| 2129 | Ok(InferOk { obligations, value: () }) => { | |
| 2263 | 2130 | this.table.register_predicates(obligations); |
| 2264 | 2131 | Ok(()) |
| 2265 | 2132 | } |
| ... | ... | @@ -2313,13 +2180,9 @@ impl<'db> InferenceContext<'db> { |
| 2313 | 2180 | && args_count_matches |
| 2314 | 2181 | { |
| 2315 | 2182 | // Don't report type mismatches if there is a mismatch in args count. |
| 2316 | self.result.type_mismatches.insert( | |
| 2317 | (*arg).into(), | |
| 2318 | TypeMismatch { | |
| 2319 | expected: expected.to_chalk(interner), | |
| 2320 | actual: found.to_chalk(interner), | |
| 2321 | }, | |
| 2322 | ); | |
| 2183 | self.result | |
| 2184 | .type_mismatches | |
| 2185 | .insert((*arg).into(), TypeMismatch { expected, actual: found }); | |
| 2323 | 2186 | } |
| 2324 | 2187 | } |
| 2325 | 2188 | } |
| ... | ... | @@ -2331,14 +2194,14 @@ impl<'db> InferenceContext<'db> { |
| 2331 | 2194 | &mut self, |
| 2332 | 2195 | expr: ExprId, |
| 2333 | 2196 | def: GenericDefId, |
| 2334 | generic_args: Option<&GenericArgs>, | |
| 2335 | ) -> Substitution { | |
| 2336 | struct LowererCtx<'a, 'b> { | |
| 2337 | ctx: &'a mut InferenceContext<'b>, | |
| 2197 | generic_args: Option<&HirGenericArgs>, | |
| 2198 | ) -> GenericArgs<'db> { | |
| 2199 | struct LowererCtx<'a, 'b, 'db> { | |
| 2200 | ctx: &'a mut InferenceContext<'b, 'db>, | |
| 2338 | 2201 | expr: ExprId, |
| 2339 | 2202 | } |
| 2340 | 2203 | |
| 2341 | impl GenericArgsLowerer for LowererCtx<'_, '_> { | |
| 2204 | impl<'db> GenericArgsLowerer<'db> for LowererCtx<'_, '_, 'db> { | |
| 2342 | 2205 | fn report_len_mismatch( |
| 2343 | 2206 | &mut self, |
| 2344 | 2207 | def: GenericDefId, |
| ... | ... | @@ -2373,21 +2236,22 @@ impl<'db> InferenceContext<'db> { |
| 2373 | 2236 | &mut self, |
| 2374 | 2237 | param_id: GenericParamId, |
| 2375 | 2238 | param: GenericParamDataRef<'_>, |
| 2376 | arg: &GenericArg, | |
| 2377 | ) -> crate::GenericArg { | |
| 2239 | arg: &HirGenericArg, | |
| 2240 | ) -> GenericArg<'db> { | |
| 2378 | 2241 | match (param, arg) { |
| 2379 | (GenericParamDataRef::LifetimeParamData(_), GenericArg::Lifetime(lifetime)) => { | |
| 2380 | self.ctx.make_body_lifetime(*lifetime).cast(Interner) | |
| 2242 | ( | |
| 2243 | GenericParamDataRef::LifetimeParamData(_), | |
| 2244 | HirGenericArg::Lifetime(lifetime), | |
| 2245 | ) => self.ctx.make_body_lifetime(*lifetime).into(), | |
| 2246 | (GenericParamDataRef::TypeParamData(_), HirGenericArg::Type(type_ref)) => { | |
| 2247 | self.ctx.make_body_ty(*type_ref).into() | |
| 2381 | 2248 | } |
| 2382 | (GenericParamDataRef::TypeParamData(_), GenericArg::Type(type_ref)) => { | |
| 2383 | self.ctx.make_body_ty(*type_ref).cast(Interner) | |
| 2384 | } | |
| 2385 | (GenericParamDataRef::ConstParamData(_), GenericArg::Const(konst)) => { | |
| 2249 | (GenericParamDataRef::ConstParamData(_), HirGenericArg::Const(konst)) => { | |
| 2386 | 2250 | let GenericParamId::ConstParamId(const_id) = param_id else { |
| 2387 | 2251 | unreachable!("non-const param ID for const param"); |
| 2388 | 2252 | }; |
| 2389 | let const_ty = self.ctx.db.const_param_ty(const_id); | |
| 2390 | self.ctx.make_body_const(*konst, const_ty).cast(Interner) | |
| 2253 | let const_ty = self.ctx.db.const_param_ty_ns(const_id); | |
| 2254 | self.ctx.make_body_const(*konst, const_ty).into() | |
| 2391 | 2255 | } |
| 2392 | 2256 | _ => unreachable!("unmatching param kinds were passed to `provided_kind()`"), |
| 2393 | 2257 | } |
| ... | ... | @@ -2395,12 +2259,12 @@ impl<'db> InferenceContext<'db> { |
| 2395 | 2259 | |
| 2396 | 2260 | fn provided_type_like_const( |
| 2397 | 2261 | &mut self, |
| 2398 | const_ty: Ty, | |
| 2262 | const_ty: Ty<'db>, | |
| 2399 | 2263 | arg: TypeLikeConst<'_>, |
| 2400 | ) -> crate::Const { | |
| 2264 | ) -> Const<'db> { | |
| 2401 | 2265 | match arg { |
| 2402 | 2266 | TypeLikeConst::Path(path) => self.ctx.make_path_as_body_const(path, const_ty), |
| 2403 | TypeLikeConst::Infer => self.ctx.table.new_const_var(const_ty), | |
| 2267 | TypeLikeConst::Infer => self.ctx.table.next_const_var(), | |
| 2404 | 2268 | } |
| 2405 | 2269 | } |
| 2406 | 2270 | |
| ... | ... | @@ -2410,35 +2274,15 @@ impl<'db> InferenceContext<'db> { |
| 2410 | 2274 | param_id: GenericParamId, |
| 2411 | 2275 | _param: GenericParamDataRef<'_>, |
| 2412 | 2276 | _infer_args: bool, |
| 2413 | _preceding_args: &[crate::GenericArg], | |
| 2414 | ) -> crate::GenericArg { | |
| 2277 | _preceding_args: &[GenericArg<'db>], | |
| 2278 | ) -> GenericArg<'db> { | |
| 2415 | 2279 | // Always create an inference var, even when `infer_args == false`. This helps with diagnostics, |
| 2416 | 2280 | // and I think it's also required in the presence of `impl Trait` (that must be inferred). |
| 2417 | match param_id { | |
| 2418 | GenericParamId::TypeParamId(_) => self.ctx.table.new_type_var().cast(Interner), | |
| 2419 | GenericParamId::ConstParamId(const_id) => self | |
| 2420 | .ctx | |
| 2421 | .table | |
| 2422 | .new_const_var(self.ctx.db.const_param_ty(const_id)) | |
| 2423 | .cast(Interner), | |
| 2424 | GenericParamId::LifetimeParamId(_) => { | |
| 2425 | self.ctx.table.new_lifetime_var().cast(Interner) | |
| 2426 | } | |
| 2427 | } | |
| 2281 | self.ctx.table.next_var_for_param(param_id) | |
| 2428 | 2282 | } |
| 2429 | 2283 | |
| 2430 | fn parent_arg(&mut self, param_id: GenericParamId) -> crate::GenericArg { | |
| 2431 | match param_id { | |
| 2432 | GenericParamId::TypeParamId(_) => self.ctx.table.new_type_var().cast(Interner), | |
| 2433 | GenericParamId::ConstParamId(const_id) => self | |
| 2434 | .ctx | |
| 2435 | .table | |
| 2436 | .new_const_var(self.ctx.db.const_param_ty(const_id)) | |
| 2437 | .cast(Interner), | |
| 2438 | GenericParamId::LifetimeParamId(_) => { | |
| 2439 | self.ctx.table.new_lifetime_var().cast(Interner) | |
| 2440 | } | |
| 2441 | } | |
| 2284 | fn parent_arg(&mut self, param_id: GenericParamId) -> GenericArg<'db> { | |
| 2285 | self.ctx.table.next_var_for_param(param_id) | |
| 2442 | 2286 | } |
| 2443 | 2287 | |
| 2444 | 2288 | fn report_elided_lifetimes_in_path( |
| ... | ... | @@ -2472,36 +2316,34 @@ impl<'db> InferenceContext<'db> { |
| 2472 | 2316 | ) |
| 2473 | 2317 | } |
| 2474 | 2318 | |
| 2475 | fn register_obligations_for_call(&mut self, callable_ty: &Ty) { | |
| 2476 | let callable_ty = self.table.structurally_resolve_type(callable_ty); | |
| 2477 | if let TyKind::FnDef(fn_def, parameters) = callable_ty.kind(Interner) { | |
| 2478 | let def: CallableDefId = from_chalk(self.db, *fn_def); | |
| 2319 | fn register_obligations_for_call(&mut self, callable_ty: Ty<'db>) { | |
| 2320 | let callable_ty = self.table.try_structurally_resolve_type(callable_ty); | |
| 2321 | if let TyKind::FnDef(fn_def, parameters) = callable_ty.kind() { | |
| 2479 | 2322 | let generic_predicates = |
| 2480 | self.db.generic_predicates(GenericDefId::from_callable(self.db, def)); | |
| 2481 | for predicate in generic_predicates.iter() { | |
| 2482 | let (predicate, binders) = predicate | |
| 2483 | .clone() | |
| 2484 | .substitute(Interner, parameters) | |
| 2485 | .into_value_and_skipped_binders(); | |
| 2486 | always!(binders.len(Interner) == 0); // quantified where clauses not yet handled | |
| 2487 | self.push_obligation(predicate.cast(Interner)); | |
| 2323 | self.db.generic_predicates_ns(GenericDefId::from_callable(self.db, fn_def.0)); | |
| 2324 | if let Some(predicates) = generic_predicates.instantiate(self.interner(), parameters) { | |
| 2325 | let interner = self.interner(); | |
| 2326 | let param_env = self.table.trait_env.env; | |
| 2327 | self.table.register_predicates(predicates.map(|predicate| { | |
| 2328 | Obligation::new(interner, ObligationCause::new(), param_env, predicate) | |
| 2329 | })); | |
| 2488 | 2330 | } |
| 2489 | 2331 | // add obligation for trait implementation, if this is a trait method |
| 2490 | match def { | |
| 2332 | match fn_def.0 { | |
| 2491 | 2333 | CallableDefId::FunctionId(f) => { |
| 2492 | 2334 | if let ItemContainerId::TraitId(trait_) = f.lookup(self.db).container { |
| 2493 | 2335 | // construct a TraitRef |
| 2494 | 2336 | let trait_params_len = generics(self.db, trait_.into()).len(); |
| 2495 | let substs = Substitution::from_iter( | |
| 2496 | Interner, | |
| 2497 | // The generic parameters for the trait come after those for the | |
| 2498 | // function. | |
| 2499 | &parameters.as_slice(Interner)[..trait_params_len], | |
| 2500 | ); | |
| 2501 | self.push_obligation( | |
| 2502 | TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs } | |
| 2503 | .cast(Interner), | |
| 2337 | let substs = GenericArgs::new_from_iter( | |
| 2338 | self.interner(), | |
| 2339 | parameters.as_slice()[..trait_params_len].iter().copied(), | |
| 2504 | 2340 | ); |
| 2341 | self.table.register_predicate(Obligation::new( | |
| 2342 | self.interner(), | |
| 2343 | ObligationCause::new(), | |
| 2344 | self.table.trait_env.env, | |
| 2345 | TraitRef::new(self.interner(), trait_.into(), substs), | |
| 2346 | )); | |
| 2505 | 2347 | } |
| 2506 | 2348 | } |
| 2507 | 2349 | CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {} |
| ... | ... | @@ -2510,11 +2352,10 @@ impl<'db> InferenceContext<'db> { |
| 2510 | 2352 | } |
| 2511 | 2353 | |
| 2512 | 2354 | /// Returns the argument indices to skip. |
| 2513 | fn check_legacy_const_generics(&mut self, callee: Ty, args: &[ExprId]) -> Box<[u32]> { | |
| 2514 | let (func, subst) = match callee.kind(Interner) { | |
| 2515 | TyKind::FnDef(fn_id, subst) => { | |
| 2516 | let callable = CallableDefId::from_chalk(self.db, *fn_id); | |
| 2517 | let func = match callable { | |
| 2355 | fn check_legacy_const_generics(&mut self, callee: Ty<'db>, args: &[ExprId]) -> Box<[u32]> { | |
| 2356 | let (func, _subst) = match callee.kind() { | |
| 2357 | TyKind::FnDef(callable, subst) => { | |
| 2358 | let func = match callable.0 { | |
| 2518 | 2359 | CallableDefId::FunctionId(f) => f, |
| 2519 | 2360 | _ => return Default::default(), |
| 2520 | 2361 | }; |
| ... | ... | @@ -2542,15 +2383,10 @@ impl<'db> InferenceContext<'db> { |
| 2542 | 2383 | } |
| 2543 | 2384 | |
| 2544 | 2385 | // check legacy const parameters |
| 2545 | for (subst_idx, arg_idx) in legacy_const_generics_indices.iter().copied().enumerate() { | |
| 2546 | let arg = match subst.at(Interner, subst_idx).constant(Interner) { | |
| 2547 | Some(c) => c, | |
| 2548 | None => continue, // not a const parameter? | |
| 2549 | }; | |
| 2386 | for arg_idx in legacy_const_generics_indices.iter().copied() { | |
| 2550 | 2387 | if arg_idx >= args.len() as u32 { |
| 2551 | 2388 | continue; |
| 2552 | 2389 | } |
| 2553 | let _ty = arg.data(Interner).ty.clone(); | |
| 2554 | 2390 | let expected = Expectation::none(); // FIXME use actual const ty, when that is lowered correctly |
| 2555 | 2391 | self.infer_expr(args[arg_idx as usize], &expected, ExprIsRead::Yes); |
| 2556 | 2392 | // FIXME: evaluate and unify with the const |
| ... | ... | @@ -2561,17 +2397,19 @@ impl<'db> InferenceContext<'db> { |
| 2561 | 2397 | } |
| 2562 | 2398 | |
| 2563 | 2399 | /// Dereferences a single level of immutable referencing. |
| 2564 | fn deref_ty_if_possible(&mut self, ty: &Ty) -> Ty { | |
| 2565 | let ty = self.table.structurally_resolve_type(ty); | |
| 2566 | match ty.kind(Interner) { | |
| 2567 | TyKind::Ref(Mutability::Not, _, inner) => self.table.structurally_resolve_type(inner), | |
| 2400 | fn deref_ty_if_possible(&mut self, ty: Ty<'db>) -> Ty<'db> { | |
| 2401 | let ty = self.table.try_structurally_resolve_type(ty); | |
| 2402 | match ty.kind() { | |
| 2403 | TyKind::Ref(_, inner, Mutability::Not) => { | |
| 2404 | self.table.try_structurally_resolve_type(inner) | |
| 2405 | } | |
| 2568 | 2406 | _ => ty, |
| 2569 | 2407 | } |
| 2570 | 2408 | } |
| 2571 | 2409 | |
| 2572 | 2410 | /// Enforces expectations on lhs type and rhs type depending on the operator and returns the |
| 2573 | 2411 | /// output type of the binary op. |
| 2574 | fn enforce_builtin_binop_types(&mut self, lhs: &Ty, rhs: &Ty, op: BinaryOp) -> Ty { | |
| 2412 | fn enforce_builtin_binop_types(&mut self, lhs: Ty<'db>, rhs: Ty<'db>, op: BinaryOp) -> Ty<'db> { | |
| 2575 | 2413 | // Special-case a single layer of referencing, so that things like `5.0 + &6.0f32` work (See rust-lang/rust#57447). |
| 2576 | 2414 | let lhs = self.deref_ty_if_possible(lhs); |
| 2577 | 2415 | let rhs = self.deref_ty_if_possible(rhs); |
| ... | ... | @@ -2583,9 +2421,9 @@ impl<'db> InferenceContext<'db> { |
| 2583 | 2421 | |
| 2584 | 2422 | let output_ty = match op { |
| 2585 | 2423 | BinaryOp::LogicOp(_) => { |
| 2586 | let bool_ = self.result.standard_types.bool_.clone(); | |
| 2587 | self.unify(&lhs, &bool_); | |
| 2588 | self.unify(&rhs, &bool_); | |
| 2424 | let bool_ = self.types.bool; | |
| 2425 | self.unify(lhs, bool_); | |
| 2426 | self.unify(rhs, bool_); | |
| 2589 | 2427 | bool_ |
| 2590 | 2428 | } |
| 2591 | 2429 | |
| ... | ... | @@ -2596,14 +2434,14 @@ impl<'db> InferenceContext<'db> { |
| 2596 | 2434 | |
| 2597 | 2435 | BinaryOp::ArithOp(_) => { |
| 2598 | 2436 | // LHS, RHS, and result will have the same type |
| 2599 | self.unify(&lhs, &rhs); | |
| 2437 | self.unify(lhs, rhs); | |
| 2600 | 2438 | lhs |
| 2601 | 2439 | } |
| 2602 | 2440 | |
| 2603 | 2441 | BinaryOp::CmpOp(_) => { |
| 2604 | 2442 | // LHS and RHS will have the same type |
| 2605 | self.unify(&lhs, &rhs); | |
| 2606 | self.result.standard_types.bool_.clone() | |
| 2443 | self.unify(lhs, rhs); | |
| 2444 | self.types.bool | |
| 2607 | 2445 | } |
| 2608 | 2446 | |
| 2609 | 2447 | BinaryOp::Assignment { op: None } => { |
| ... | ... | @@ -2614,10 +2452,10 @@ impl<'db> InferenceContext<'db> { |
| 2614 | 2452 | BinaryOp::Assignment { .. } => unreachable!("handled above"), |
| 2615 | 2453 | }; |
| 2616 | 2454 | |
| 2617 | if is_assign { self.result.standard_types.unit.clone() } else { output_ty } | |
| 2455 | if is_assign { self.types.unit } else { output_ty } | |
| 2618 | 2456 | } |
| 2619 | 2457 | |
| 2620 | fn is_builtin_binop(&mut self, lhs: &Ty, rhs: &Ty, op: BinaryOp) -> bool { | |
| 2458 | fn is_builtin_binop(&mut self, lhs: Ty<'db>, rhs: Ty<'db>, op: BinaryOp) -> bool { | |
| 2621 | 2459 | // Special-case a single layer of referencing, so that things like `5.0 + &6.0f32` work (See rust-lang/rust#57447). |
| 2622 | 2460 | let lhs = self.deref_ty_if_possible(lhs); |
| 2623 | 2461 | let rhs = self.deref_ty_if_possible(rhs); |
| ... | ... | @@ -2644,27 +2482,25 @@ impl<'db> InferenceContext<'db> { |
| 2644 | 2482 | BinaryOp::ArithOp(ArithOp::BitAnd | ArithOp::BitOr | ArithOp::BitXor) => { |
| 2645 | 2483 | lhs.is_integral() && rhs.is_integral() |
| 2646 | 2484 | || lhs.is_floating_point() && rhs.is_floating_point() |
| 2647 | || matches!( | |
| 2648 | (lhs.kind(Interner), rhs.kind(Interner)), | |
| 2649 | (TyKind::Scalar(Scalar::Bool), TyKind::Scalar(Scalar::Bool)) | |
| 2650 | ) | |
| 2485 | || matches!((lhs.kind(), rhs.kind()), (TyKind::Bool, TyKind::Bool)) | |
| 2651 | 2486 | } |
| 2652 | 2487 | |
| 2653 | 2488 | BinaryOp::CmpOp(_) => { |
| 2654 | 2489 | let is_scalar = |kind| { |
| 2655 | 2490 | matches!( |
| 2656 | 2491 | kind, |
| 2657 | &TyKind::Scalar(_) | |
| 2492 | TyKind::Bool | |
| 2493 | | TyKind::Char | |
| 2494 | | TyKind::Int(_) | |
| 2495 | | TyKind::Uint(_) | |
| 2496 | | TyKind::Float(_) | |
| 2658 | 2497 | | TyKind::FnDef(..) |
| 2659 | | TyKind::Function(_) | |
| 2660 | | TyKind::Raw(..) | |
| 2661 | | TyKind::InferenceVar( | |
| 2662 | _, | |
| 2663 | TyVariableKind::Integer | TyVariableKind::Float | |
| 2664 | ) | |
| 2498 | | TyKind::FnPtr(..) | |
| 2499 | | TyKind::RawPtr(..) | |
| 2500 | | TyKind::Infer(InferTy::IntVar(_) | InferTy::FloatVar(_)) | |
| 2665 | 2501 | ) |
| 2666 | 2502 | }; |
| 2667 | is_scalar(lhs.kind(Interner)) && is_scalar(rhs.kind(Interner)) | |
| 2503 | is_scalar(lhs.kind()) && is_scalar(rhs.kind()) | |
| 2668 | 2504 | } |
| 2669 | 2505 | |
| 2670 | 2506 | BinaryOp::Assignment { op: None } => { |
| ... | ... | @@ -2679,27 +2515,15 @@ impl<'db> InferenceContext<'db> { |
| 2679 | 2515 | pub(super) fn with_breakable_ctx<T>( |
| 2680 | 2516 | &mut self, |
| 2681 | 2517 | kind: BreakableKind, |
| 2682 | ty: Option<Ty>, | |
| 2518 | ty: Option<Ty<'db>>, | |
| 2683 | 2519 | label: Option<LabelId>, |
| 2684 | 2520 | cb: impl FnOnce(&mut Self) -> T, |
| 2685 | ) -> (Option<Ty>, T) { | |
| 2521 | ) -> (Option<Ty<'db>>, T) { | |
| 2686 | 2522 | self.breakables.push({ |
| 2687 | BreakableContext { | |
| 2688 | kind, | |
| 2689 | may_break: false, | |
| 2690 | coerce: ty.map(|ty| CoerceMany::new(ty.to_nextsolver(self.table.interner))), | |
| 2691 | label, | |
| 2692 | } | |
| 2523 | BreakableContext { kind, may_break: false, coerce: ty.map(CoerceMany::new), label } | |
| 2693 | 2524 | }); |
| 2694 | 2525 | let res = cb(self); |
| 2695 | 2526 | let ctx = self.breakables.pop().expect("breakable stack broken"); |
| 2696 | ( | |
| 2697 | if ctx.may_break { | |
| 2698 | ctx.coerce.map(|ctx| ctx.complete(self).to_chalk(self.table.interner)) | |
| 2699 | } else { | |
| 2700 | None | |
| 2701 | }, | |
| 2702 | res, | |
| 2703 | ) | |
| 2527 | (if ctx.may_break { ctx.coerce.map(|ctx| ctx.complete(self)) } else { None }, res) | |
| 2704 | 2528 | } |
| 2705 | 2529 | } |
src/tools/rust-analyzer/crates/hir-ty/src/infer/fallback.rs+2-2| ... | ... | @@ -28,7 +28,7 @@ pub(crate) enum DivergingFallbackBehavior { |
| 28 | 28 | ToNever, |
| 29 | 29 | } |
| 30 | 30 | |
| 31 | impl<'db> InferenceContext<'db> { | |
| 31 | impl<'db> InferenceContext<'_, 'db> { | |
| 32 | 32 | pub(super) fn type_inference_fallback(&mut self) { |
| 33 | 33 | debug!( |
| 34 | 34 | "type-inference-fallback start obligations: {:#?}", |
| ... | ... | @@ -324,7 +324,7 @@ impl<'db> InferenceContext<'db> { |
| 324 | 324 | FxHashMap::with_capacity_and_hasher(diverging_vids.len(), FxBuildHasher); |
| 325 | 325 | |
| 326 | 326 | for &diverging_vid in &diverging_vids { |
| 327 | let diverging_ty = Ty::new_var(self.table.interner, diverging_vid); | |
| 327 | let diverging_ty = Ty::new_var(self.interner(), diverging_vid); | |
| 328 | 328 | let root_vid = self.table.infer_ctxt.root_var(diverging_vid); |
| 329 | 329 | let can_reach_non_diverging = Dfs::new(&coercion_graph, root_vid.as_u32().into()) |
| 330 | 330 | .iter(&coercion_graph) |
src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs+28-15| ... | ... | @@ -1,7 +1,6 @@ |
| 1 | 1 | //! Finds if an expression is an immutable context or a mutable context, which is used in selecting |
| 2 | 2 | //! between `Deref` and `DerefMut` or `Index` and `IndexMut` or similar. |
| 3 | 3 | |
| 4 | use chalk_ir::{Mutability, cast::Cast}; | |
| 5 | 4 | use hir_def::{ |
| 6 | 5 | hir::{ |
| 7 | 6 | Array, AsmOperand, BinaryOp, BindingAnnotation, Expr, ExprId, Pat, PatId, Statement, |
| ... | ... | @@ -11,14 +10,19 @@ use hir_def::{ |
| 11 | 10 | }; |
| 12 | 11 | use hir_expand::name::Name; |
| 13 | 12 | use intern::sym; |
| 13 | use rustc_ast_ir::Mutability; | |
| 14 | use rustc_type_ir::inherent::IntoKind; | |
| 14 | 15 | |
| 16 | use crate::next_solver::infer::traits::{Obligation, ObligationCause}; | |
| 17 | use crate::next_solver::{GenericArgs, TraitRef}; | |
| 15 | 18 | use crate::{ |
| 16 | Adjust, Adjustment, AutoBorrow, Interner, OverloadedDeref, TyBuilder, TyKind, | |
| 19 | Adjust, Adjustment, AutoBorrow, OverloadedDeref, | |
| 17 | 20 | infer::{Expectation, InferenceContext, expr::ExprIsRead}, |
| 18 | lower::lower_to_chalk_mutability, | |
| 21 | lower_nextsolver::lower_mutability, | |
| 22 | next_solver::TyKind, | |
| 19 | 23 | }; |
| 20 | 24 | |
| 21 | impl InferenceContext<'_> { | |
| 25 | impl<'db> InferenceContext<'_, 'db> { | |
| 22 | 26 | pub(crate) fn infer_mut_body(&mut self) { |
| 23 | 27 | self.infer_mut_expr(self.body.body_expr, Mutability::Not); |
| 24 | 28 | } |
| ... | ... | @@ -141,8 +145,8 @@ impl InferenceContext<'_> { |
| 141 | 145 | target, |
| 142 | 146 | }) = base_adjustments |
| 143 | 147 | { |
| 144 | if let TyKind::Ref(_, _, ty) = target.kind(Interner) { | |
| 145 | base_ty = Some(ty.clone()); | |
| 148 | if let TyKind::Ref(_, ty, _) = target.kind() { | |
| 149 | base_ty = Some(ty); | |
| 146 | 150 | } |
| 147 | 151 | *mutability = Mutability::Mut; |
| 148 | 152 | } |
| ... | ... | @@ -150,15 +154,24 @@ impl InferenceContext<'_> { |
| 150 | 154 | // Apply `IndexMut` obligation for non-assignee expr |
| 151 | 155 | if let Some(base_ty) = base_ty { |
| 152 | 156 | let index_ty = if let Some(ty) = self.result.type_of_expr.get(index) { |
| 153 | ty.clone() | |
| 157 | *ty | |
| 154 | 158 | } else { |
| 155 | 159 | self.infer_expr(index, &Expectation::none(), ExprIsRead::Yes) |
| 156 | 160 | }; |
| 157 | let trait_ref = TyBuilder::trait_ref(self.db, index_trait) | |
| 158 | .push(base_ty) | |
| 159 | .fill(|_| index_ty.clone().cast(Interner)) | |
| 160 | .build(); | |
| 161 | self.push_obligation(trait_ref.cast(Interner)); | |
| 161 | let trait_ref = TraitRef::new( | |
| 162 | self.interner(), | |
| 163 | index_trait.into(), | |
| 164 | GenericArgs::new_from_iter( | |
| 165 | self.interner(), | |
| 166 | [base_ty.into(), index_ty.into()], | |
| 167 | ), | |
| 168 | ); | |
| 169 | self.table.register_predicate(Obligation::new( | |
| 170 | self.interner(), | |
| 171 | ObligationCause::new(), | |
| 172 | self.table.trait_env.env, | |
| 173 | trait_ref, | |
| 174 | )); | |
| 162 | 175 | } |
| 163 | 176 | } |
| 164 | 177 | self.infer_mut_expr(base, mutability); |
| ... | ... | @@ -173,8 +186,8 @@ impl InferenceContext<'_> { |
| 173 | 186 | { |
| 174 | 187 | let ty = self.result.type_of_expr.get(*expr); |
| 175 | 188 | let is_mut_ptr = ty.is_some_and(|ty| { |
| 176 | let ty = self.table.resolve_ty_shallow(ty); | |
| 177 | matches!(ty.kind(Interner), chalk_ir::TyKind::Raw(Mutability::Mut, _)) | |
| 189 | let ty = self.table.shallow_resolve(*ty); | |
| 190 | matches!(ty.kind(), TyKind::RawPtr(_, Mutability::Mut)) | |
| 178 | 191 | }); |
| 179 | 192 | if is_mut_ptr { |
| 180 | 193 | mutability = Mutability::Not; |
| ... | ... | @@ -200,7 +213,7 @@ impl InferenceContext<'_> { |
| 200 | 213 | self.infer_mut_expr(*expr, Mutability::Not); |
| 201 | 214 | } |
| 202 | 215 | Expr::Ref { expr, rawness: _, mutability } => { |
| 203 | let mutability = lower_to_chalk_mutability(*mutability); | |
| 216 | let mutability = lower_mutability(*mutability); | |
| 204 | 217 | self.infer_mut_expr(*expr, mutability); |
| 205 | 218 | } |
| 206 | 219 | Expr::BinaryOp { lhs, rhs, op: Some(BinaryOp::Assignment { .. }) } => { |
src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs+152-161| ... | ... | @@ -8,37 +8,35 @@ use hir_def::{ |
| 8 | 8 | hir::{Binding, BindingAnnotation, BindingId, Expr, ExprId, Literal, Pat, PatId}, |
| 9 | 9 | }; |
| 10 | 10 | use hir_expand::name::Name; |
| 11 | use rustc_ast_ir::Mutability; | |
| 12 | use rustc_type_ir::inherent::{GenericArg as _, GenericArgs as _, IntoKind, SliceLike, Ty as _}; | |
| 11 | 13 | use stdx::TupleExt; |
| 12 | 14 | |
| 13 | use crate::infer::AllowTwoPhase; | |
| 14 | use crate::next_solver::mapping::{ChalkToNextSolver, NextSolverToChalk}; | |
| 15 | 15 | use crate::{ |
| 16 | DeclContext, DeclOrigin, InferenceDiagnostic, Interner, Mutability, Scalar, Substitution, Ty, | |
| 17 | TyBuilder, TyExt, TyKind, | |
| 16 | DeclContext, DeclOrigin, InferenceDiagnostic, | |
| 18 | 17 | consteval::{self, try_const_usize, usize_const}, |
| 19 | 18 | infer::{ |
| 20 | BindingMode, Expectation, InferenceContext, TypeMismatch, coerce::CoerceNever, | |
| 21 | expr::ExprIsRead, | |
| 19 | AllowTwoPhase, BindingMode, Expectation, InferenceContext, TypeMismatch, | |
| 20 | coerce::CoerceNever, expr::ExprIsRead, | |
| 22 | 21 | }, |
| 23 | lower::lower_to_chalk_mutability, | |
| 24 | primitive::UintTy, | |
| 25 | static_lifetime, | |
| 22 | lower_nextsolver::lower_mutability, | |
| 23 | next_solver::{GenericArgs, Ty, TyKind}, | |
| 26 | 24 | }; |
| 27 | 25 | |
| 28 | impl InferenceContext<'_> { | |
| 26 | impl<'db> InferenceContext<'_, 'db> { | |
| 29 | 27 | /// Infers type for tuple struct pattern or its corresponding assignee expression. |
| 30 | 28 | /// |
| 31 | 29 | /// Ellipses found in the original pattern or expression must be filtered out. |
| 32 | 30 | pub(super) fn infer_tuple_struct_pat_like( |
| 33 | 31 | &mut self, |
| 34 | 32 | path: Option<&Path>, |
| 35 | expected: &Ty, | |
| 33 | expected: Ty<'db>, | |
| 36 | 34 | default_bm: BindingMode, |
| 37 | 35 | id: PatId, |
| 38 | 36 | ellipsis: Option<u32>, |
| 39 | 37 | subs: &[PatId], |
| 40 | 38 | decl: Option<DeclContext>, |
| 41 | ) -> Ty { | |
| 39 | ) -> Ty<'db> { | |
| 42 | 40 | let (ty, def) = self.resolve_variant(id.into(), path, true); |
| 43 | 41 | let var_data = def.map(|it| it.fields(self.db)); |
| 44 | 42 | if let Some(variant) = def { |
| ... | ... | @@ -56,12 +54,12 @@ impl InferenceContext<'_> { |
| 56 | 54 | } |
| 57 | 55 | } |
| 58 | 56 | |
| 59 | self.unify(&ty, expected); | |
| 57 | self.unify(ty, expected); | |
| 60 | 58 | |
| 61 | 59 | match def { |
| 62 | 60 | _ if subs.is_empty() => {} |
| 63 | 61 | Some(def) => { |
| 64 | let field_types = self.db.field_types(def); | |
| 62 | let field_types = self.db.field_types_ns(def); | |
| 65 | 63 | let variant_data = def.fields(self.db); |
| 66 | 64 | let visibilities = self.db.field_visibilities(def); |
| 67 | 65 | |
| ... | ... | @@ -85,10 +83,10 @@ impl InferenceContext<'_> { |
| 85 | 83 | { |
| 86 | 84 | // FIXME(DIAGNOSE): private tuple field |
| 87 | 85 | } |
| 88 | let f = field_types[local_id].clone(); | |
| 86 | let f = field_types[local_id]; | |
| 89 | 87 | let expected_ty = match substs { |
| 90 | Some(substs) => f.substitute(Interner, substs), | |
| 91 | None => f.substitute(Interner, &Substitution::empty(Interner)), | |
| 88 | Some(substs) => f.instantiate(self.interner(), substs), | |
| 89 | None => f.instantiate(self.interner(), &[]), | |
| 92 | 90 | }; |
| 93 | 91 | self.process_remote_user_written_ty(expected_ty) |
| 94 | 92 | } |
| ... | ... | @@ -96,13 +94,13 @@ impl InferenceContext<'_> { |
| 96 | 94 | } |
| 97 | 95 | }; |
| 98 | 96 | |
| 99 | self.infer_pat(subpat, &expected_ty, default_bm, decl); | |
| 97 | self.infer_pat(subpat, expected_ty, default_bm, decl); | |
| 100 | 98 | } |
| 101 | 99 | } |
| 102 | 100 | None => { |
| 103 | 101 | let err_ty = self.err_ty(); |
| 104 | 102 | for &inner in subs { |
| 105 | self.infer_pat(inner, &err_ty, default_bm, decl); | |
| 103 | self.infer_pat(inner, err_ty, default_bm, decl); | |
| 106 | 104 | } |
| 107 | 105 | } |
| 108 | 106 | } |
| ... | ... | @@ -114,23 +112,23 @@ impl InferenceContext<'_> { |
| 114 | 112 | pub(super) fn infer_record_pat_like( |
| 115 | 113 | &mut self, |
| 116 | 114 | path: Option<&Path>, |
| 117 | expected: &Ty, | |
| 115 | expected: Ty<'db>, | |
| 118 | 116 | default_bm: BindingMode, |
| 119 | 117 | id: PatId, |
| 120 | 118 | subs: impl ExactSizeIterator<Item = (Name, PatId)>, |
| 121 | 119 | decl: Option<DeclContext>, |
| 122 | ) -> Ty { | |
| 120 | ) -> Ty<'db> { | |
| 123 | 121 | let (ty, def) = self.resolve_variant(id.into(), path, false); |
| 124 | 122 | if let Some(variant) = def { |
| 125 | 123 | self.write_variant_resolution(id.into(), variant); |
| 126 | 124 | } |
| 127 | 125 | |
| 128 | self.unify(&ty, expected); | |
| 126 | self.unify(ty, expected); | |
| 129 | 127 | |
| 130 | 128 | match def { |
| 131 | 129 | _ if subs.len() == 0 => {} |
| 132 | 130 | Some(def) => { |
| 133 | let field_types = self.db.field_types(def); | |
| 131 | let field_types = self.db.field_types_ns(def); | |
| 134 | 132 | let variant_data = def.fields(self.db); |
| 135 | 133 | let visibilities = self.db.field_visibilities(def); |
| 136 | 134 | |
| ... | ... | @@ -149,10 +147,10 @@ impl InferenceContext<'_> { |
| 149 | 147 | variant: def, |
| 150 | 148 | }); |
| 151 | 149 | } |
| 152 | let f = field_types[local_id].clone(); | |
| 150 | let f = field_types[local_id]; | |
| 153 | 151 | let expected_ty = match substs { |
| 154 | Some(substs) => f.substitute(Interner, substs), | |
| 155 | None => f.substitute(Interner, &Substitution::empty(Interner)), | |
| 152 | Some(substs) => f.instantiate(self.interner(), substs), | |
| 153 | None => f.instantiate(self.interner(), &[]), | |
| 156 | 154 | }; |
| 157 | 155 | self.process_remote_user_written_ty(expected_ty) |
| 158 | 156 | } |
| ... | ... | @@ -167,13 +165,13 @@ impl InferenceContext<'_> { |
| 167 | 165 | } |
| 168 | 166 | }; |
| 169 | 167 | |
| 170 | self.infer_pat(inner, &expected_ty, default_bm, decl); | |
| 168 | self.infer_pat(inner, expected_ty, default_bm, decl); | |
| 171 | 169 | } |
| 172 | 170 | } |
| 173 | 171 | None => { |
| 174 | 172 | let err_ty = self.err_ty(); |
| 175 | 173 | for (_, inner) in subs { |
| 176 | self.infer_pat(inner, &err_ty, default_bm, decl); | |
| 174 | self.infer_pat(inner, err_ty, default_bm, decl); | |
| 177 | 175 | } |
| 178 | 176 | } |
| 179 | 177 | } |
| ... | ... | @@ -186,16 +184,16 @@ impl InferenceContext<'_> { |
| 186 | 184 | /// Ellipses found in the original pattern or expression must be filtered out. |
| 187 | 185 | pub(super) fn infer_tuple_pat_like( |
| 188 | 186 | &mut self, |
| 189 | expected: &Ty, | |
| 187 | expected: Ty<'db>, | |
| 190 | 188 | default_bm: BindingMode, |
| 191 | 189 | ellipsis: Option<u32>, |
| 192 | 190 | subs: &[PatId], |
| 193 | 191 | decl: Option<DeclContext>, |
| 194 | ) -> Ty { | |
| 192 | ) -> Ty<'db> { | |
| 195 | 193 | let expected = self.table.structurally_resolve_type(expected); |
| 196 | let expectations = match expected.as_tuple() { | |
| 197 | Some(parameters) => parameters.as_slice(Interner), | |
| 198 | _ => &[], | |
| 194 | let expectations = match expected.kind() { | |
| 195 | TyKind::Tuple(parameters) => parameters, | |
| 196 | _ => self.types.empty_tys, | |
| 199 | 197 | }; |
| 200 | 198 | |
| 201 | 199 | let ((pre, post), n_uncovered_patterns) = match ellipsis { |
| ... | ... | @@ -204,10 +202,8 @@ impl InferenceContext<'_> { |
| 204 | 202 | } |
| 205 | 203 | None => ((subs, &[][..]), 0), |
| 206 | 204 | }; |
| 207 | let mut expectations_iter = expectations | |
| 208 | .iter() | |
| 209 | .map(|a| a.assert_ty_ref(Interner).clone()) | |
| 210 | .chain(repeat_with(|| self.table.new_type_var())); | |
| 205 | let mut expectations_iter = | |
| 206 | expectations.iter().chain(repeat_with(|| self.table.next_ty_var())); | |
| 211 | 207 | |
| 212 | 208 | let mut inner_tys = Vec::with_capacity(n_uncovered_patterns + subs.len()); |
| 213 | 209 | |
| ... | ... | @@ -215,31 +211,35 @@ impl InferenceContext<'_> { |
| 215 | 211 | |
| 216 | 212 | // Process pre |
| 217 | 213 | for (ty, pat) in inner_tys.iter_mut().zip(pre) { |
| 218 | *ty = self.infer_pat(*pat, ty, default_bm, decl); | |
| 214 | *ty = self.infer_pat(*pat, *ty, default_bm, decl); | |
| 219 | 215 | } |
| 220 | 216 | |
| 221 | 217 | // Process post |
| 222 | 218 | for (ty, pat) in inner_tys.iter_mut().skip(pre.len() + n_uncovered_patterns).zip(post) { |
| 223 | *ty = self.infer_pat(*pat, ty, default_bm, decl); | |
| 219 | *ty = self.infer_pat(*pat, *ty, default_bm, decl); | |
| 224 | 220 | } |
| 225 | 221 | |
| 226 | TyKind::Tuple(inner_tys.len(), Substitution::from_iter(Interner, inner_tys)) | |
| 227 | .intern(Interner) | |
| 222 | Ty::new_tup_from_iter(self.interner(), inner_tys.into_iter()) | |
| 228 | 223 | } |
| 229 | 224 | |
| 230 | 225 | /// The resolver needs to be updated to the surrounding expression when inside assignment |
| 231 | 226 | /// (because there, `Pat::Path` can refer to a variable). |
| 232 | pub(super) fn infer_top_pat(&mut self, pat: PatId, expected: &Ty, decl: Option<DeclContext>) { | |
| 227 | pub(super) fn infer_top_pat( | |
| 228 | &mut self, | |
| 229 | pat: PatId, | |
| 230 | expected: Ty<'db>, | |
| 231 | decl: Option<DeclContext>, | |
| 232 | ) { | |
| 233 | 233 | self.infer_pat(pat, expected, BindingMode::default(), decl); |
| 234 | 234 | } |
| 235 | 235 | |
| 236 | 236 | fn infer_pat( |
| 237 | 237 | &mut self, |
| 238 | 238 | pat: PatId, |
| 239 | expected: &Ty, | |
| 239 | expected: Ty<'db>, | |
| 240 | 240 | mut default_bm: BindingMode, |
| 241 | 241 | decl: Option<DeclContext>, |
| 242 | ) -> Ty { | |
| 242 | ) -> Ty<'db> { | |
| 243 | 243 | let mut expected = self.table.structurally_resolve_type(expected); |
| 244 | 244 | |
| 245 | 245 | if matches!(&self.body[pat], Pat::Ref { .. }) || self.inside_assignment { |
| ... | ... | @@ -251,9 +251,9 @@ impl InferenceContext<'_> { |
| 251 | 251 | default_bm = BindingMode::Move; |
| 252 | 252 | } else if self.is_non_ref_pat(self.body, pat) { |
| 253 | 253 | let mut pat_adjustments = Vec::new(); |
| 254 | while let Some((inner, _lifetime, mutability)) = expected.as_reference() { | |
| 255 | pat_adjustments.push(expected.clone()); | |
| 256 | expected = self.table.structurally_resolve_type(inner); | |
| 254 | while let TyKind::Ref(_lifetime, inner, mutability) = expected.kind() { | |
| 255 | pat_adjustments.push(expected); | |
| 256 | expected = self.table.try_structurally_resolve_type(inner); | |
| 257 | 257 | default_bm = match default_bm { |
| 258 | 258 | BindingMode::Move => BindingMode::Ref(mutability), |
| 259 | 259 | BindingMode::Ref(Mutability::Not) => BindingMode::Ref(Mutability::Not), |
| ... | ... | @@ -273,25 +273,21 @@ impl InferenceContext<'_> { |
| 273 | 273 | |
| 274 | 274 | let ty = match &self.body[pat] { |
| 275 | 275 | Pat::Tuple { args, ellipsis } => { |
| 276 | self.infer_tuple_pat_like(&expected, default_bm, *ellipsis, args, decl) | |
| 276 | self.infer_tuple_pat_like(expected, default_bm, *ellipsis, args, decl) | |
| 277 | 277 | } |
| 278 | 278 | Pat::Or(pats) => { |
| 279 | 279 | for pat in pats.iter() { |
| 280 | self.infer_pat(*pat, &expected, default_bm, decl); | |
| 280 | self.infer_pat(*pat, expected, default_bm, decl); | |
| 281 | 281 | } |
| 282 | expected.clone() | |
| 282 | expected | |
| 283 | } | |
| 284 | &Pat::Ref { pat, mutability } => { | |
| 285 | self.infer_ref_pat(pat, lower_mutability(mutability), expected, default_bm, decl) | |
| 283 | 286 | } |
| 284 | &Pat::Ref { pat, mutability } => self.infer_ref_pat( | |
| 285 | pat, | |
| 286 | lower_to_chalk_mutability(mutability), | |
| 287 | &expected, | |
| 288 | default_bm, | |
| 289 | decl, | |
| 290 | ), | |
| 291 | 287 | Pat::TupleStruct { path: p, args: subpats, ellipsis } => self |
| 292 | 288 | .infer_tuple_struct_pat_like( |
| 293 | 289 | p.as_deref(), |
| 294 | &expected, | |
| 290 | expected, | |
| 295 | 291 | default_bm, |
| 296 | 292 | pat, |
| 297 | 293 | *ellipsis, |
| ... | ... | @@ -300,29 +296,26 @@ impl InferenceContext<'_> { |
| 300 | 296 | ), |
| 301 | 297 | Pat::Record { path: p, args: fields, ellipsis: _ } => { |
| 302 | 298 | let subs = fields.iter().map(|f| (f.name.clone(), f.pat)); |
| 303 | self.infer_record_pat_like(p.as_deref(), &expected, default_bm, pat, subs, decl) | |
| 299 | self.infer_record_pat_like(p.as_deref(), expected, default_bm, pat, subs, decl) | |
| 304 | 300 | } |
| 305 | 301 | Pat::Path(path) => { |
| 306 | 302 | let ty = self.infer_path(path, pat.into()).unwrap_or_else(|| self.err_ty()); |
| 307 | let ty_inserted_vars = self.insert_type_vars_shallow(ty.clone()); | |
| 303 | let ty_inserted_vars = self.insert_type_vars_shallow(ty); | |
| 308 | 304 | match self.coerce( |
| 309 | 305 | pat.into(), |
| 310 | expected.to_nextsolver(self.table.interner), | |
| 311 | ty_inserted_vars.to_nextsolver(self.table.interner), | |
| 306 | expected, | |
| 307 | ty_inserted_vars, | |
| 312 | 308 | AllowTwoPhase::No, |
| 313 | 309 | CoerceNever::Yes, |
| 314 | 310 | ) { |
| 315 | 311 | Ok(coerced_ty) => { |
| 316 | self.write_pat_ty(pat, coerced_ty.to_chalk(self.table.interner)); | |
| 312 | self.write_pat_ty(pat, coerced_ty); | |
| 317 | 313 | return self.pat_ty_after_adjustment(pat); |
| 318 | 314 | } |
| 319 | 315 | Err(_) => { |
| 320 | 316 | self.result.type_mismatches.insert( |
| 321 | 317 | pat.into(), |
| 322 | TypeMismatch { | |
| 323 | expected: expected.clone(), | |
| 324 | actual: ty_inserted_vars.clone(), | |
| 325 | }, | |
| 318 | TypeMismatch { expected, actual: ty_inserted_vars }, | |
| 326 | 319 | ); |
| 327 | 320 | self.write_pat_ty(pat, ty); |
| 328 | 321 | // We return `expected` to prevent cascading errors. I guess an alternative is to |
| ... | ... | @@ -332,81 +325,77 @@ impl InferenceContext<'_> { |
| 332 | 325 | } |
| 333 | 326 | } |
| 334 | 327 | Pat::Bind { id, subpat } => { |
| 335 | return self.infer_bind_pat(pat, *id, default_bm, *subpat, &expected, decl); | |
| 328 | return self.infer_bind_pat(pat, *id, default_bm, *subpat, expected, decl); | |
| 336 | 329 | } |
| 337 | 330 | Pat::Slice { prefix, slice, suffix } => { |
| 338 | self.infer_slice_pat(&expected, prefix, slice, suffix, default_bm, decl) | |
| 331 | self.infer_slice_pat(expected, prefix, *slice, suffix, default_bm, decl) | |
| 339 | 332 | } |
| 340 | Pat::Wild => expected.clone(), | |
| 333 | Pat::Wild => expected, | |
| 341 | 334 | Pat::Range { .. } => { |
| 342 | 335 | // FIXME: do some checks here. |
| 343 | expected.clone() | |
| 336 | expected | |
| 344 | 337 | } |
| 345 | 338 | &Pat::Lit(expr) => { |
| 346 | 339 | // Don't emit type mismatches again, the expression lowering already did that. |
| 347 | let ty = self.infer_lit_pat(expr, &expected); | |
| 340 | let ty = self.infer_lit_pat(expr, expected); | |
| 348 | 341 | self.write_pat_ty(pat, ty); |
| 349 | 342 | return self.pat_ty_after_adjustment(pat); |
| 350 | 343 | } |
| 351 | 344 | Pat::Box { inner } => match self.resolve_boxed_box() { |
| 352 | 345 | Some(box_adt) => { |
| 353 | 346 | let (inner_ty, alloc_ty) = match expected.as_adt() { |
| 354 | Some((adt, subst)) if adt == box_adt => ( | |
| 355 | subst.at(Interner, 0).assert_ty_ref(Interner).clone(), | |
| 356 | subst.as_slice(Interner).get(1).and_then(|a| a.ty(Interner).cloned()), | |
| 357 | ), | |
| 358 | _ => (self.result.standard_types.unknown.clone(), None), | |
| 347 | Some((adt, subst)) if adt == box_adt => { | |
| 348 | (subst.type_at(0), subst.as_slice().get(1).and_then(|a| a.as_type())) | |
| 349 | } | |
| 350 | _ => (self.types.error, None), | |
| 359 | 351 | }; |
| 360 | 352 | |
| 361 | let inner_ty = self.infer_pat(*inner, &inner_ty, default_bm, decl); | |
| 362 | let mut b = TyBuilder::adt(self.db, box_adt).push(inner_ty); | |
| 363 | ||
| 364 | if let Some(alloc_ty) = alloc_ty { | |
| 365 | b = b.push(alloc_ty); | |
| 366 | } | |
| 367 | b.fill_with_defaults(self.db, || self.table.new_type_var()).build() | |
| 353 | let inner_ty = self.infer_pat(*inner, inner_ty, default_bm, decl); | |
| 354 | Ty::new_adt( | |
| 355 | self.interner(), | |
| 356 | box_adt, | |
| 357 | GenericArgs::fill_with_defaults( | |
| 358 | self.interner(), | |
| 359 | box_adt.into(), | |
| 360 | std::iter::once(inner_ty.into()).chain(alloc_ty.map(Into::into)), | |
| 361 | |_, _, id, _| self.table.next_var_for_param(id), | |
| 362 | ), | |
| 363 | ) | |
| 368 | 364 | } |
| 369 | 365 | None => self.err_ty(), |
| 370 | 366 | }, |
| 371 | 367 | Pat::ConstBlock(expr) => { |
| 372 | 368 | let old_inside_assign = std::mem::replace(&mut self.inside_assignment, false); |
| 373 | let result = self.infer_expr( | |
| 374 | *expr, | |
| 375 | &Expectation::has_type(expected.clone()), | |
| 376 | ExprIsRead::Yes, | |
| 377 | ); | |
| 369 | let result = | |
| 370 | self.infer_expr(*expr, &Expectation::has_type(expected), ExprIsRead::Yes); | |
| 378 | 371 | self.inside_assignment = old_inside_assign; |
| 379 | 372 | result |
| 380 | 373 | } |
| 381 | 374 | Pat::Expr(expr) => { |
| 382 | 375 | let old_inside_assign = std::mem::replace(&mut self.inside_assignment, false); |
| 383 | 376 | // LHS of assignment doesn't constitute reads. |
| 384 | let result = self.infer_expr_coerce( | |
| 385 | *expr, | |
| 386 | &Expectation::has_type(expected.clone()), | |
| 387 | ExprIsRead::No, | |
| 388 | ); | |
| 377 | let result = | |
| 378 | self.infer_expr_coerce(*expr, &Expectation::has_type(expected), ExprIsRead::No); | |
| 389 | 379 | // We are returning early to avoid the unifiability check below. |
| 390 | 380 | let lhs_ty = self.insert_type_vars_shallow(result); |
| 391 | 381 | let ty = match self.coerce( |
| 392 | 382 | pat.into(), |
| 393 | expected.to_nextsolver(self.table.interner), | |
| 394 | lhs_ty.to_nextsolver(self.table.interner), | |
| 383 | expected, | |
| 384 | lhs_ty, | |
| 395 | 385 | AllowTwoPhase::No, |
| 396 | 386 | CoerceNever::Yes, |
| 397 | 387 | ) { |
| 398 | Ok(ty) => ty.to_chalk(self.table.interner), | |
| 388 | Ok(ty) => ty, | |
| 399 | 389 | Err(_) => { |
| 400 | self.result.type_mismatches.insert( | |
| 401 | pat.into(), | |
| 402 | TypeMismatch { expected: expected.clone(), actual: lhs_ty.clone() }, | |
| 403 | ); | |
| 390 | self.result | |
| 391 | .type_mismatches | |
| 392 | .insert(pat.into(), TypeMismatch { expected, actual: lhs_ty }); | |
| 404 | 393 | // `rhs_ty` is returned so no further type mismatches are |
| 405 | 394 | // reported because of this mismatch. |
| 406 | 395 | expected |
| 407 | 396 | } |
| 408 | 397 | }; |
| 409 | self.write_pat_ty(pat, ty.clone()); | |
| 398 | self.write_pat_ty(pat, ty); | |
| 410 | 399 | self.inside_assignment = old_inside_assign; |
| 411 | 400 | return ty; |
| 412 | 401 | } |
| ... | ... | @@ -415,46 +404,43 @@ impl InferenceContext<'_> { |
| 415 | 404 | // use a new type variable if we got error type here |
| 416 | 405 | let ty = self.insert_type_vars_shallow(ty); |
| 417 | 406 | // FIXME: This never check is odd, but required with out we do inference right now |
| 418 | if !expected.is_never() && !self.unify(&ty, &expected) { | |
| 419 | self.result | |
| 420 | .type_mismatches | |
| 421 | .insert(pat.into(), TypeMismatch { expected, actual: ty.clone() }); | |
| 407 | if !expected.is_never() && !self.unify(ty, expected) { | |
| 408 | self.result.type_mismatches.insert(pat.into(), TypeMismatch { expected, actual: ty }); | |
| 422 | 409 | } |
| 423 | 410 | self.write_pat_ty(pat, ty); |
| 424 | 411 | self.pat_ty_after_adjustment(pat) |
| 425 | 412 | } |
| 426 | 413 | |
| 427 | fn pat_ty_after_adjustment(&self, pat: PatId) -> Ty { | |
| 428 | self.result | |
| 414 | fn pat_ty_after_adjustment(&self, pat: PatId) -> Ty<'db> { | |
| 415 | *self | |
| 416 | .result | |
| 429 | 417 | .pat_adjustments |
| 430 | 418 | .get(&pat) |
| 431 | 419 | .and_then(|it| it.first()) |
| 432 | 420 | .unwrap_or(&self.result.type_of_pat[pat]) |
| 433 | .clone() | |
| 434 | 421 | } |
| 435 | 422 | |
| 436 | 423 | fn infer_ref_pat( |
| 437 | 424 | &mut self, |
| 438 | 425 | inner_pat: PatId, |
| 439 | 426 | mutability: Mutability, |
| 440 | expected: &Ty, | |
| 427 | expected: Ty<'db>, | |
| 441 | 428 | default_bm: BindingMode, |
| 442 | 429 | decl: Option<DeclContext>, |
| 443 | ) -> Ty { | |
| 444 | let (expectation_type, expectation_lt) = match expected.as_reference() { | |
| 445 | Some((inner_ty, lifetime, _exp_mut)) => (inner_ty.clone(), lifetime), | |
| 446 | None => { | |
| 447 | let inner_ty = self.table.new_type_var(); | |
| 448 | let inner_lt = self.table.new_lifetime_var(); | |
| 449 | let ref_ty = | |
| 450 | TyKind::Ref(mutability, inner_lt.clone(), inner_ty.clone()).intern(Interner); | |
| 430 | ) -> Ty<'db> { | |
| 431 | let (expectation_type, expectation_lt) = match expected.kind() { | |
| 432 | TyKind::Ref(lifetime, inner_ty, _exp_mut) => (inner_ty, lifetime), | |
| 433 | _ => { | |
| 434 | let inner_ty = self.table.next_ty_var(); | |
| 435 | let inner_lt = self.table.next_region_var(); | |
| 436 | let ref_ty = Ty::new_ref(self.interner(), inner_lt, inner_ty, mutability); | |
| 451 | 437 | // Unification failure will be reported by the caller. |
| 452 | self.unify(&ref_ty, expected); | |
| 438 | self.unify(ref_ty, expected); | |
| 453 | 439 | (inner_ty, inner_lt) |
| 454 | 440 | } |
| 455 | 441 | }; |
| 456 | let subty = self.infer_pat(inner_pat, &expectation_type, default_bm, decl); | |
| 457 | TyKind::Ref(mutability, expectation_lt, subty).intern(Interner) | |
| 442 | let subty = self.infer_pat(inner_pat, expectation_type, default_bm, decl); | |
| 443 | Ty::new_ref(self.interner(), expectation_lt, subty, mutability) | |
| 458 | 444 | } |
| 459 | 445 | |
| 460 | 446 | fn infer_bind_pat( |
| ... | ... | @@ -463,9 +449,9 @@ impl InferenceContext<'_> { |
| 463 | 449 | binding: BindingId, |
| 464 | 450 | default_bm: BindingMode, |
| 465 | 451 | subpat: Option<PatId>, |
| 466 | expected: &Ty, | |
| 452 | expected: Ty<'db>, | |
| 467 | 453 | decl: Option<DeclContext>, |
| 468 | ) -> Ty { | |
| 454 | ) -> Ty<'db> { | |
| 469 | 455 | let Binding { mode, .. } = self.body[binding]; |
| 470 | 456 | let mode = if mode == BindingAnnotation::Unannotated { |
| 471 | 457 | default_bm |
| ... | ... | @@ -476,31 +462,31 @@ impl InferenceContext<'_> { |
| 476 | 462 | |
| 477 | 463 | let inner_ty = match subpat { |
| 478 | 464 | Some(subpat) => self.infer_pat(subpat, expected, default_bm, decl), |
| 479 | None => expected.clone(), | |
| 465 | None => expected, | |
| 480 | 466 | }; |
| 481 | 467 | let inner_ty = self.insert_type_vars_shallow(inner_ty); |
| 482 | 468 | |
| 483 | 469 | let bound_ty = match mode { |
| 484 | 470 | BindingMode::Ref(mutability) => { |
| 485 | let inner_lt = self.table.new_lifetime_var(); | |
| 486 | TyKind::Ref(mutability, inner_lt, inner_ty.clone()).intern(Interner) | |
| 471 | let inner_lt = self.table.next_region_var(); | |
| 472 | Ty::new_ref(self.interner(), inner_lt, inner_ty, mutability) | |
| 487 | 473 | } |
| 488 | BindingMode::Move => inner_ty.clone(), | |
| 474 | BindingMode::Move => inner_ty, | |
| 489 | 475 | }; |
| 490 | self.write_pat_ty(pat, inner_ty.clone()); | |
| 476 | self.write_pat_ty(pat, inner_ty); | |
| 491 | 477 | self.write_binding_ty(binding, bound_ty); |
| 492 | 478 | inner_ty |
| 493 | 479 | } |
| 494 | 480 | |
| 495 | 481 | fn infer_slice_pat( |
| 496 | 482 | &mut self, |
| 497 | expected: &Ty, | |
| 483 | expected: Ty<'db>, | |
| 498 | 484 | prefix: &[PatId], |
| 499 | slice: &Option<PatId>, | |
| 485 | slice: Option<PatId>, | |
| 500 | 486 | suffix: &[PatId], |
| 501 | 487 | default_bm: BindingMode, |
| 502 | 488 | decl: Option<DeclContext>, |
| 503 | ) -> Ty { | |
| 489 | ) -> Ty<'db> { | |
| 504 | 490 | let expected = self.table.structurally_resolve_type(expected); |
| 505 | 491 | |
| 506 | 492 | // If `expected` is an infer ty, we try to equate it to an array if the given pattern |
| ... | ... | @@ -510,56 +496,61 @@ impl InferenceContext<'_> { |
| 510 | 496 | && let Some(resolved_array_ty) = |
| 511 | 497 | self.try_resolve_slice_ty_to_array_ty(prefix, suffix, slice) |
| 512 | 498 | { |
| 513 | self.unify(&expected, &resolved_array_ty); | |
| 499 | self.unify(expected, resolved_array_ty); | |
| 514 | 500 | } |
| 515 | 501 | |
| 516 | let expected = self.table.structurally_resolve_type(&expected); | |
| 517 | let elem_ty = match expected.kind(Interner) { | |
| 518 | TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(), | |
| 502 | let expected = self.table.try_structurally_resolve_type(expected); | |
| 503 | let elem_ty = match expected.kind() { | |
| 504 | TyKind::Array(st, _) | TyKind::Slice(st) => st, | |
| 519 | 505 | _ => self.err_ty(), |
| 520 | 506 | }; |
| 521 | 507 | |
| 522 | 508 | for &pat_id in prefix.iter().chain(suffix.iter()) { |
| 523 | self.infer_pat(pat_id, &elem_ty, default_bm, decl); | |
| 509 | self.infer_pat(pat_id, elem_ty, default_bm, decl); | |
| 524 | 510 | } |
| 525 | 511 | |
| 526 | if let &Some(slice_pat_id) = slice { | |
| 527 | let rest_pat_ty = match expected.kind(Interner) { | |
| 512 | if let Some(slice_pat_id) = slice { | |
| 513 | let rest_pat_ty = match expected.kind() { | |
| 528 | 514 | TyKind::Array(_, length) => { |
| 529 | 515 | let len = try_const_usize(self.db, length); |
| 530 | 516 | let len = |
| 531 | 517 | len.and_then(|len| len.checked_sub((prefix.len() + suffix.len()) as u128)); |
| 532 | TyKind::Array(elem_ty.clone(), usize_const(self.db, len, self.resolver.krate())) | |
| 518 | Ty::new_array_with_const_len( | |
| 519 | self.interner(), | |
| 520 | elem_ty, | |
| 521 | usize_const(self.db, len, self.resolver.krate()), | |
| 522 | ) | |
| 533 | 523 | } |
| 534 | _ => TyKind::Slice(elem_ty.clone()), | |
| 535 | } | |
| 536 | .intern(Interner); | |
| 537 | self.infer_pat(slice_pat_id, &rest_pat_ty, default_bm, decl); | |
| 524 | _ => Ty::new_slice(self.interner(), elem_ty), | |
| 525 | }; | |
| 526 | self.infer_pat(slice_pat_id, rest_pat_ty, default_bm, decl); | |
| 538 | 527 | } |
| 539 | 528 | |
| 540 | match expected.kind(Interner) { | |
| 541 | TyKind::Array(_, const_) => TyKind::Array(elem_ty, const_.clone()), | |
| 542 | _ => TyKind::Slice(elem_ty), | |
| 529 | match expected.kind() { | |
| 530 | TyKind::Array(_, const_) => { | |
| 531 | Ty::new_array_with_const_len(self.interner(), elem_ty, const_) | |
| 532 | } | |
| 533 | _ => Ty::new_slice(self.interner(), elem_ty), | |
| 543 | 534 | } |
| 544 | .intern(Interner) | |
| 545 | 535 | } |
| 546 | 536 | |
| 547 | fn infer_lit_pat(&mut self, expr: ExprId, expected: &Ty) -> Ty { | |
| 537 | fn infer_lit_pat(&mut self, expr: ExprId, expected: Ty<'db>) -> Ty<'db> { | |
| 548 | 538 | // Like slice patterns, byte string patterns can denote both `&[u8; N]` and `&[u8]`. |
| 549 | 539 | if let Expr::Literal(Literal::ByteString(_)) = self.body[expr] |
| 550 | && let Some((inner, ..)) = expected.as_reference() | |
| 540 | && let TyKind::Ref(_, inner, _) = expected.kind() | |
| 551 | 541 | { |
| 552 | let inner = self.table.structurally_resolve_type(inner); | |
| 553 | if matches!(inner.kind(Interner), TyKind::Slice(_)) { | |
| 554 | let elem_ty = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(Interner); | |
| 555 | let slice_ty = TyKind::Slice(elem_ty).intern(Interner); | |
| 556 | let ty = TyKind::Ref(Mutability::Not, static_lifetime(), slice_ty).intern(Interner); | |
| 557 | self.write_expr_ty(expr, ty.clone()); | |
| 542 | let inner = self.table.try_structurally_resolve_type(inner); | |
| 543 | if matches!(inner.kind(), TyKind::Slice(_)) { | |
| 544 | let elem_ty = self.types.u8; | |
| 545 | let slice_ty = Ty::new_slice(self.interner(), elem_ty); | |
| 546 | let ty = | |
| 547 | Ty::new_ref(self.interner(), self.types.re_static, slice_ty, Mutability::Not); | |
| 548 | self.write_expr_ty(expr, ty); | |
| 558 | 549 | return ty; |
| 559 | 550 | } |
| 560 | 551 | } |
| 561 | 552 | |
| 562 | self.infer_expr(expr, &Expectation::has_type(expected.clone()), ExprIsRead::Yes) | |
| 553 | self.infer_expr(expr, &Expectation::has_type(expected), ExprIsRead::Yes) | |
| 563 | 554 | } |
| 564 | 555 | |
| 565 | 556 | fn is_non_ref_pat(&mut self, body: &hir_def::expr_store::Body, pat: PatId) -> bool { |
| ... | ... | @@ -593,17 +584,17 @@ impl InferenceContext<'_> { |
| 593 | 584 | &mut self, |
| 594 | 585 | before: &[PatId], |
| 595 | 586 | suffix: &[PatId], |
| 596 | slice: &Option<PatId>, | |
| 597 | ) -> Option<Ty> { | |
| 598 | if !slice.is_none() { | |
| 587 | slice: Option<PatId>, | |
| 588 | ) -> Option<Ty<'db>> { | |
| 589 | if slice.is_some() { | |
| 599 | 590 | return None; |
| 600 | 591 | } |
| 601 | 592 | |
| 602 | 593 | let len = before.len() + suffix.len(); |
| 603 | 594 | let size = consteval::usize_const(self.db, Some(len as u128), self.owner.krate(self.db)); |
| 604 | 595 | |
| 605 | let elem_ty = self.table.new_type_var(); | |
| 606 | let array_ty = TyKind::Array(elem_ty, size).intern(Interner); | |
| 596 | let elem_ty = self.table.next_ty_var(); | |
| 597 | let array_ty = Ty::new_array_with_const_len(self.interner(), elem_ty, size); | |
| 607 | 598 | Some(array_ty) |
| 608 | 599 | } |
| 609 | 600 |
src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs+106-124| ... | ... | @@ -1,52 +1,50 @@ |
| 1 | 1 | //! Path expression resolution. |
| 2 | 2 | |
| 3 | use chalk_ir::cast::Cast; | |
| 4 | 3 | use hir_def::{ |
| 5 | 4 | AdtId, AssocItemId, GenericDefId, ItemContainerId, Lookup, |
| 6 | 5 | expr_store::path::{Path, PathSegment}, |
| 7 | 6 | resolver::{ResolveValueResult, TypeNs, ValueNs}, |
| 8 | 7 | }; |
| 9 | 8 | use hir_expand::name::Name; |
| 9 | use rustc_type_ir::inherent::{SliceLike, Ty as _}; | |
| 10 | 10 | use stdx::never; |
| 11 | 11 | |
| 12 | 12 | use crate::{ |
| 13 | InferenceDiagnostic, Interner, LifetimeElisionKind, Substitution, TraitRef, TraitRefExt, Ty, | |
| 14 | TyBuilder, TyExt, TyKind, ValueTyDefId, | |
| 15 | builder::ParamKind, | |
| 16 | consteval, error_lifetime, | |
| 13 | InferenceDiagnostic, ValueTyDefId, | |
| 17 | 14 | generics::generics, |
| 18 | 15 | infer::diagnostics::InferenceTyLoweringContext as TyLoweringContext, |
| 16 | lower_nextsolver::LifetimeElisionKind, | |
| 19 | 17 | method_resolution::{self, VisibleFromModule}, |
| 20 | 18 | next_solver::{ |
| 21 | DbInterner, | |
| 22 | mapping::{ChalkToNextSolver, NextSolverToChalk}, | |
| 19 | GenericArg, GenericArgs, TraitRef, Ty, | |
| 20 | infer::traits::{Obligation, ObligationCause}, | |
| 23 | 21 | }, |
| 24 | to_chalk_trait_id, | |
| 25 | 22 | }; |
| 26 | 23 | |
| 27 | 24 | use super::{ExprOrPatId, InferenceContext, InferenceTyDiagnosticSource}; |
| 28 | 25 | |
| 29 | impl<'db> InferenceContext<'db> { | |
| 30 | pub(super) fn infer_path(&mut self, path: &Path, id: ExprOrPatId) -> Option<Ty> { | |
| 26 | impl<'db> InferenceContext<'_, 'db> { | |
| 27 | pub(super) fn infer_path(&mut self, path: &Path, id: ExprOrPatId) -> Option<Ty<'db>> { | |
| 31 | 28 | let (value_def, generic_def, substs) = match self.resolve_value_path(path, id)? { |
| 32 | 29 | ValuePathResolution::GenericDef(value_def, generic_def, substs) => { |
| 33 | 30 | (value_def, generic_def, substs) |
| 34 | 31 | } |
| 35 | 32 | ValuePathResolution::NonGeneric(ty) => return Some(ty), |
| 36 | 33 | }; |
| 37 | let substs = | |
| 38 | self.process_remote_user_written_ty::<_, crate::next_solver::GenericArgs<'db>>(substs); | |
| 34 | let args = self.process_remote_user_written_ty(substs); | |
| 39 | 35 | |
| 40 | self.add_required_obligations_for_value_path(generic_def, &substs); | |
| 36 | self.add_required_obligations_for_value_path(generic_def, args); | |
| 41 | 37 | |
| 42 | let interner = DbInterner::new_with(self.db, None, None); | |
| 43 | let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 44 | let ty = self.db.value_ty(value_def)?.instantiate(interner, args).to_chalk(interner); | |
| 38 | let ty = self.db.value_ty(value_def)?.instantiate(self.interner(), args); | |
| 45 | 39 | let ty = self.process_remote_user_written_ty(ty); |
| 46 | 40 | Some(ty) |
| 47 | 41 | } |
| 48 | 42 | |
| 49 | fn resolve_value_path(&mut self, path: &Path, id: ExprOrPatId) -> Option<ValuePathResolution> { | |
| 43 | fn resolve_value_path( | |
| 44 | &mut self, | |
| 45 | path: &Path, | |
| 46 | id: ExprOrPatId, | |
| 47 | ) -> Option<ValuePathResolution<'db>> { | |
| 50 | 48 | let (value, self_subst) = self.resolve_value_path_inner(path, id, false)?; |
| 51 | 49 | |
| 52 | 50 | let value_def: ValueTyDefId = match value { |
| ... | ... | @@ -65,7 +63,7 @@ impl<'db> InferenceContext<'db> { |
| 65 | 63 | } |
| 66 | 64 | ValueNs::LocalBinding(pat) => { |
| 67 | 65 | return match self.result.type_of_binding.get(pat) { |
| 68 | Some(ty) => Some(ValuePathResolution::NonGeneric(ty.clone())), | |
| 66 | Some(ty) => Some(ValuePathResolution::NonGeneric(*ty)), | |
| 69 | 67 | None => { |
| 70 | 68 | never!("uninferred pattern?"); |
| 71 | 69 | None |
| ... | ... | @@ -73,17 +71,12 @@ impl<'db> InferenceContext<'db> { |
| 73 | 71 | }; |
| 74 | 72 | } |
| 75 | 73 | ValueNs::ImplSelf(impl_id) => { |
| 76 | let generics = crate::generics::generics(self.db, impl_id.into()); | |
| 77 | let interner = DbInterner::new_with(self.db, None, None); | |
| 78 | let substs = generics.placeholder_subst(self.db); | |
| 79 | let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 80 | let ty = | |
| 81 | self.db.impl_self_ty(impl_id).instantiate(interner, args).to_chalk(interner); | |
| 74 | let ty = self.db.impl_self_ty(impl_id).instantiate_identity(); | |
| 82 | 75 | return if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() { |
| 83 | 76 | Some(ValuePathResolution::GenericDef( |
| 84 | 77 | struct_id.into(), |
| 85 | 78 | struct_id.into(), |
| 86 | substs.clone(), | |
| 79 | substs, | |
| 87 | 80 | )) |
| 88 | 81 | } else { |
| 89 | 82 | // FIXME: report error, invalid Self reference |
| ... | ... | @@ -91,67 +84,42 @@ impl<'db> InferenceContext<'db> { |
| 91 | 84 | }; |
| 92 | 85 | } |
| 93 | 86 | ValueNs::GenericParam(it) => { |
| 94 | return Some(ValuePathResolution::NonGeneric(self.db.const_param_ty(it))); | |
| 87 | return Some(ValuePathResolution::NonGeneric(self.db.const_param_ty_ns(it))); | |
| 95 | 88 | } |
| 96 | 89 | }; |
| 97 | 90 | |
| 98 | 91 | let generic_def = value_def.to_generic_def_id(self.db); |
| 99 | 92 | if let GenericDefId::StaticId(_) = generic_def { |
| 100 | let interner = DbInterner::new_with(self.db, None, None); | |
| 101 | 93 | // `Static` is the kind of item that can never be generic currently. We can just skip the binders to get its type. |
| 102 | let ty = self.db.value_ty(value_def)?.skip_binder().to_chalk(interner); | |
| 94 | let ty = self.db.value_ty(value_def)?.skip_binder(); | |
| 103 | 95 | return Some(ValuePathResolution::NonGeneric(ty)); |
| 104 | 96 | }; |
| 105 | 97 | |
| 106 | let substs = self.with_body_ty_lowering(|ctx| { | |
| 107 | let mut path_ctx = ctx.at_path(path, id); | |
| 108 | let last_segment = path.segments().len().checked_sub(1); | |
| 109 | if let Some(last_segment) = last_segment { | |
| 110 | path_ctx.set_current_segment(last_segment) | |
| 111 | } | |
| 112 | path_ctx.substs_from_path(value_def, true, false) | |
| 113 | }); | |
| 114 | let substs = substs.as_slice(Interner); | |
| 115 | ||
| 116 | if let ValueNs::EnumVariantId(_) = value { | |
| 117 | let mut it = substs | |
| 118 | .iter() | |
| 119 | .chain(self_subst.as_ref().map_or(&[][..], |s| s.as_slice(Interner))) | |
| 120 | .cloned(); | |
| 121 | let builder = TyBuilder::subst_for_def(self.db, generic_def, None); | |
| 122 | let substs = builder | |
| 123 | .fill(|x| { | |
| 124 | it.next().unwrap_or_else(|| match x { | |
| 125 | ParamKind::Type => { | |
| 126 | self.result.standard_types.unknown.clone().cast(Interner) | |
| 127 | } | |
| 128 | ParamKind::Const(ty) => consteval::unknown_const_as_generic(ty.clone()), | |
| 129 | ParamKind::Lifetime => error_lifetime().cast(Interner), | |
| 130 | }) | |
| 131 | }) | |
| 132 | .build(); | |
| 133 | ||
| 134 | return Some(ValuePathResolution::GenericDef(value_def, generic_def, substs)); | |
| 135 | } | |
| 136 | ||
| 137 | let parent_substs = self_subst.or_else(|| { | |
| 138 | let generics = generics(self.db, generic_def); | |
| 139 | let parent_params_len = generics.parent_generics()?.len(); | |
| 140 | let parent_args = &substs[..parent_params_len]; | |
| 141 | Some(Substitution::from_iter(Interner, parent_args)) | |
| 142 | }); | |
| 143 | let parent_substs_len = parent_substs.as_ref().map_or(0, |s| s.len(Interner)); | |
| 144 | let mut it = substs.iter().skip(parent_substs_len).cloned(); | |
| 145 | let builder = TyBuilder::subst_for_def(self.db, generic_def, parent_substs); | |
| 146 | let substs = builder | |
| 147 | .fill(|x| { | |
| 148 | it.next().unwrap_or_else(|| match x { | |
| 149 | ParamKind::Type => self.result.standard_types.unknown.clone().cast(Interner), | |
| 150 | ParamKind::Const(ty) => consteval::unknown_const_as_generic(ty.clone()), | |
| 151 | ParamKind::Lifetime => error_lifetime().cast(Interner), | |
| 152 | }) | |
| 98 | let substs = if self_subst.is_some_and(|it| !it.is_empty()) | |
| 99 | && matches!(value_def, ValueTyDefId::EnumVariantId(_)) | |
| 100 | { | |
| 101 | // This is something like `TypeAlias::<Args>::EnumVariant`. Do not call `substs_from_path()`, | |
| 102 | // as it'll try to re-lower the previous segment assuming it refers to the enum, but it refers | |
| 103 | // to the type alias and they may have different generics. | |
| 104 | self.types.empty_args | |
| 105 | } else { | |
| 106 | self.with_body_ty_lowering(|ctx| { | |
| 107 | let mut path_ctx = ctx.at_path(path, id); | |
| 108 | let last_segment = path.segments().len().checked_sub(1); | |
| 109 | if let Some(last_segment) = last_segment { | |
| 110 | path_ctx.set_current_segment(last_segment) | |
| 111 | } | |
| 112 | path_ctx.substs_from_path(value_def, true, false) | |
| 153 | 113 | }) |
| 154 | .build(); | |
| 114 | }; | |
| 115 | ||
| 116 | let parent_substs_len = self_subst.map_or(0, |it| it.len()); | |
| 117 | let substs = GenericArgs::fill_rest( | |
| 118 | self.interner(), | |
| 119 | generic_def.into(), | |
| 120 | self_subst.iter().flat_map(|it| it.iter()).chain(substs.iter().skip(parent_substs_len)), | |
| 121 | |_, _, id, _| GenericArg::error_from_id(self.interner(), id), | |
| 122 | ); | |
| 155 | 123 | |
| 156 | 124 | Some(ValuePathResolution::GenericDef(value_def, generic_def, substs)) |
| 157 | 125 | } |
| ... | ... | @@ -161,7 +129,7 @@ impl<'db> InferenceContext<'db> { |
| 161 | 129 | path: &Path, |
| 162 | 130 | id: ExprOrPatId, |
| 163 | 131 | no_diagnostics: bool, |
| 164 | ) -> Option<(ValueNs, Option<chalk_ir::Substitution<Interner>>)> { | |
| 132 | ) -> Option<(ValueNs, Option<GenericArgs<'db>>)> { | |
| 165 | 133 | // Don't use `self.make_ty()` here as we need `orig_ns`. |
| 166 | 134 | let mut ctx = TyLoweringContext::new( |
| 167 | 135 | self.db, |
| ... | ... | @@ -211,7 +179,7 @@ impl<'db> InferenceContext<'db> { |
| 211 | 179 | |
| 212 | 180 | let (resolution, substs) = match (def, is_before_last) { |
| 213 | 181 | (TypeNs::TraitId(trait_), true) => { |
| 214 | let self_ty = self.table.new_type_var(); | |
| 182 | let self_ty = self.table.next_ty_var(); | |
| 215 | 183 | let trait_ref = |
| 216 | 184 | path_ctx.lower_trait_ref_from_resolved_path(trait_, self_ty, true); |
| 217 | 185 | drop_ctx(ctx, no_diagnostics); |
| ... | ... | @@ -225,7 +193,7 @@ impl<'db> InferenceContext<'db> { |
| 225 | 193 | path_ctx.ignore_last_segment(); |
| 226 | 194 | let (ty, _) = path_ctx.lower_partly_resolved_path(def, true); |
| 227 | 195 | drop_ctx(ctx, no_diagnostics); |
| 228 | if ty.is_unknown() { | |
| 196 | if ty.is_ty_error() { | |
| 229 | 197 | return None; |
| 230 | 198 | } |
| 231 | 199 | |
| ... | ... | @@ -241,21 +209,25 @@ impl<'db> InferenceContext<'db> { |
| 241 | 209 | return Some((value, self_subst)); |
| 242 | 210 | |
| 243 | 211 | #[inline] |
| 244 | fn drop_ctx(mut ctx: TyLoweringContext<'_>, no_diagnostics: bool) { | |
| 212 | fn drop_ctx(mut ctx: TyLoweringContext<'_, '_>, no_diagnostics: bool) { | |
| 245 | 213 | if no_diagnostics { |
| 246 | 214 | ctx.forget_diagnostics(); |
| 247 | 215 | } |
| 248 | 216 | } |
| 249 | 217 | } |
| 250 | 218 | |
| 251 | fn add_required_obligations_for_value_path(&mut self, def: GenericDefId, subst: &Substitution) { | |
| 252 | let predicates = self.db.generic_predicates(def); | |
| 253 | for predicate in predicates.iter() { | |
| 254 | let (predicate, binders) = | |
| 255 | predicate.clone().substitute(Interner, &subst).into_value_and_skipped_binders(); | |
| 256 | // Quantified where clauses are not yet handled. | |
| 257 | stdx::always!(binders.is_empty(Interner)); | |
| 258 | self.push_obligation(predicate.cast(Interner)); | |
| 219 | fn add_required_obligations_for_value_path( | |
| 220 | &mut self, | |
| 221 | def: GenericDefId, | |
| 222 | subst: GenericArgs<'db>, | |
| 223 | ) { | |
| 224 | let predicates = self.db.generic_predicates_ns(def); | |
| 225 | let interner = self.interner(); | |
| 226 | let param_env = self.table.trait_env.env; | |
| 227 | if let Some(predicates) = predicates.instantiate(self.interner(), subst) { | |
| 228 | self.table.register_predicates(predicates.map(|predicate| { | |
| 229 | Obligation::new(interner, ObligationCause::new(), param_env, predicate) | |
| 230 | })); | |
| 259 | 231 | } |
| 260 | 232 | |
| 261 | 233 | // We need to add `Self: Trait` obligation when `def` is a trait assoc item. |
| ... | ... | @@ -267,21 +239,27 @@ impl<'db> InferenceContext<'db> { |
| 267 | 239 | |
| 268 | 240 | if let ItemContainerId::TraitId(trait_) = container { |
| 269 | 241 | let parent_len = generics(self.db, def).parent_generics().map_or(0, |g| g.len_self()); |
| 270 | let parent_subst = | |
| 271 | Substitution::from_iter(Interner, subst.iter(Interner).take(parent_len)); | |
| 272 | let trait_ref = | |
| 273 | TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: parent_subst }; | |
| 274 | self.push_obligation(trait_ref.cast(Interner)); | |
| 242 | let parent_subst = GenericArgs::new_from_iter( | |
| 243 | interner, | |
| 244 | subst.as_slice()[..parent_len].iter().copied(), | |
| 245 | ); | |
| 246 | let trait_ref = TraitRef::new(interner, trait_.into(), parent_subst); | |
| 247 | self.table.register_predicate(Obligation::new( | |
| 248 | interner, | |
| 249 | ObligationCause::new(), | |
| 250 | param_env, | |
| 251 | trait_ref, | |
| 252 | )); | |
| 275 | 253 | } |
| 276 | 254 | } |
| 277 | 255 | |
| 278 | 256 | fn resolve_trait_assoc_item( |
| 279 | 257 | &mut self, |
| 280 | trait_ref: TraitRef, | |
| 258 | trait_ref: TraitRef<'db>, | |
| 281 | 259 | segment: PathSegment<'_>, |
| 282 | 260 | id: ExprOrPatId, |
| 283 | ) -> Option<(ValueNs, Substitution)> { | |
| 284 | let trait_ = trait_ref.hir_trait_id(); | |
| 261 | ) -> Option<(ValueNs, GenericArgs<'db>)> { | |
| 262 | let trait_ = trait_ref.def_id.0; | |
| 285 | 263 | let item = |
| 286 | 264 | trait_.trait_items(self.db).items.iter().map(|(_name, id)| *id).find_map(|item| { |
| 287 | 265 | match item { |
| ... | ... | @@ -309,25 +287,25 @@ impl<'db> InferenceContext<'db> { |
| 309 | 287 | AssocItemId::TypeAliasId(_) => unreachable!(), |
| 310 | 288 | }; |
| 311 | 289 | |
| 312 | self.write_assoc_resolution(id, item, trait_ref.substitution.clone()); | |
| 313 | Some((def, trait_ref.substitution)) | |
| 290 | self.write_assoc_resolution(id, item, trait_ref.args); | |
| 291 | Some((def, trait_ref.args)) | |
| 314 | 292 | } |
| 315 | 293 | |
| 316 | 294 | fn resolve_ty_assoc_item( |
| 317 | 295 | &mut self, |
| 318 | ty: Ty, | |
| 296 | ty: Ty<'db>, | |
| 319 | 297 | name: &Name, |
| 320 | 298 | id: ExprOrPatId, |
| 321 | ) -> Option<(ValueNs, Substitution)> { | |
| 322 | if let TyKind::Error = ty.kind(Interner) { | |
| 299 | ) -> Option<(ValueNs, GenericArgs<'db>)> { | |
| 300 | if ty.is_ty_error() { | |
| 323 | 301 | return None; |
| 324 | 302 | } |
| 325 | 303 | |
| 326 | if let Some(result) = self.resolve_enum_variant_on_ty(&ty, name, id) { | |
| 304 | if let Some(result) = self.resolve_enum_variant_on_ty(ty, name, id) { | |
| 327 | 305 | return Some(result); |
| 328 | 306 | } |
| 329 | 307 | |
| 330 | let canonical_ty = self.canonicalize(ty.clone().to_nextsolver(self.table.interner)); | |
| 308 | let canonical_ty = self.canonicalize(ty); | |
| 331 | 309 | |
| 332 | 310 | let mut not_visible = None; |
| 333 | 311 | let res = method_resolution::iterate_method_candidates( |
| ... | ... | @@ -362,24 +340,28 @@ impl<'db> InferenceContext<'db> { |
| 362 | 340 | }; |
| 363 | 341 | let substs = match container { |
| 364 | 342 | ItemContainerId::ImplId(impl_id) => { |
| 365 | let interner = DbInterner::new_with(self.db, None, None); | |
| 366 | let impl_substs = TyBuilder::subst_for_def(self.db, impl_id, None) | |
| 367 | .fill_with_inference_vars(&mut self.table) | |
| 368 | .build(); | |
| 369 | let args: crate::next_solver::GenericArgs<'_> = impl_substs.to_nextsolver(interner); | |
| 343 | let impl_substs = self.table.fresh_args_for_item(impl_id.into()); | |
| 370 | 344 | let impl_self_ty = |
| 371 | self.db.impl_self_ty(impl_id).instantiate(interner, args).to_chalk(interner); | |
| 372 | self.unify(&impl_self_ty, &ty); | |
| 345 | self.db.impl_self_ty(impl_id).instantiate(self.interner(), impl_substs); | |
| 346 | self.unify(impl_self_ty, ty); | |
| 373 | 347 | impl_substs |
| 374 | 348 | } |
| 375 | 349 | ItemContainerId::TraitId(trait_) => { |
| 376 | 350 | // we're picking this method |
| 377 | let trait_ref = TyBuilder::trait_ref(self.db, trait_) | |
| 378 | .push(ty.clone()) | |
| 379 | .fill_with_inference_vars(&mut self.table) | |
| 380 | .build(); | |
| 381 | self.push_obligation(trait_ref.clone().cast(Interner)); | |
| 382 | trait_ref.substitution | |
| 351 | let args = GenericArgs::fill_rest( | |
| 352 | self.interner(), | |
| 353 | trait_.into(), | |
| 354 | [ty.into()], | |
| 355 | |_, _, id, _| self.table.next_var_for_param(id), | |
| 356 | ); | |
| 357 | let trait_ref = TraitRef::new(self.interner(), trait_.into(), args); | |
| 358 | self.table.register_predicate(Obligation::new( | |
| 359 | self.interner(), | |
| 360 | ObligationCause::new(), | |
| 361 | self.table.trait_env.env, | |
| 362 | trait_ref, | |
| 363 | )); | |
| 364 | args | |
| 383 | 365 | } |
| 384 | 366 | ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => { |
| 385 | 367 | never!("assoc item contained in module/extern block"); |
| ... | ... | @@ -387,7 +369,7 @@ impl<'db> InferenceContext<'db> { |
| 387 | 369 | } |
| 388 | 370 | }; |
| 389 | 371 | |
| 390 | self.write_assoc_resolution(id, item, substs.clone()); | |
| 372 | self.write_assoc_resolution(id, item, substs); | |
| 391 | 373 | if !visible { |
| 392 | 374 | self.push_diagnostic(InferenceDiagnostic::PrivateAssocItem { id, item }); |
| 393 | 375 | } |
| ... | ... | @@ -396,11 +378,11 @@ impl<'db> InferenceContext<'db> { |
| 396 | 378 | |
| 397 | 379 | fn resolve_enum_variant_on_ty( |
| 398 | 380 | &mut self, |
| 399 | ty: &Ty, | |
| 381 | ty: Ty<'db>, | |
| 400 | 382 | name: &Name, |
| 401 | 383 | id: ExprOrPatId, |
| 402 | ) -> Option<(ValueNs, Substitution)> { | |
| 403 | let ty = self.table.structurally_resolve_type(ty); | |
| 384 | ) -> Option<(ValueNs, GenericArgs<'db>)> { | |
| 385 | let ty = self.table.try_structurally_resolve_type(ty); | |
| 404 | 386 | let (enum_id, subst) = match ty.as_adt() { |
| 405 | 387 | Some((AdtId::EnumId(e), subst)) => (e, subst), |
| 406 | 388 | _ => return None, |
| ... | ... | @@ -408,14 +390,14 @@ impl<'db> InferenceContext<'db> { |
| 408 | 390 | let enum_data = enum_id.enum_variants(self.db); |
| 409 | 391 | let variant = enum_data.variant(name)?; |
| 410 | 392 | self.write_variant_resolution(id, variant.into()); |
| 411 | Some((ValueNs::EnumVariantId(variant), subst.clone())) | |
| 393 | Some((ValueNs::EnumVariantId(variant), subst)) | |
| 412 | 394 | } |
| 413 | 395 | } |
| 414 | 396 | |
| 415 | 397 | #[derive(Debug)] |
| 416 | enum ValuePathResolution { | |
| 398 | enum ValuePathResolution<'db> { | |
| 417 | 399 | // It's awkward to wrap a single ID in two enums, but we need both and this saves fallible |
| 418 | 400 | // conversion between them + `unwrap()`. |
| 419 | GenericDef(ValueTyDefId, GenericDefId, Substitution), | |
| 420 | NonGeneric(Ty), | |
| 401 | GenericDef(ValueTyDefId, GenericDefId, GenericArgs<'db>), | |
| 402 | NonGeneric(Ty<'db>), | |
| 421 | 403 | } |
src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs+276-697| ... | ... | @@ -2,49 +2,43 @@ |
| 2 | 2 | |
| 3 | 3 | use std::fmt; |
| 4 | 4 | |
| 5 | use chalk_ir::{ | |
| 6 | CanonicalVarKind, TyVariableKind, cast::Cast, fold::TypeFoldable, interner::HasInterner, | |
| 7 | }; | |
| 8 | use either::Either; | |
| 9 | use hir_def::{AdtId, lang_item::LangItem}; | |
| 5 | use hir_def::{AdtId, GenericParamId, lang_item::LangItem}; | |
| 10 | 6 | use hir_expand::name::Name; |
| 11 | 7 | use intern::sym; |
| 12 | 8 | use rustc_hash::{FxHashMap, FxHashSet}; |
| 13 | 9 | use rustc_type_ir::{ |
| 14 | TyVid, TypeVisitableExt, UpcastFrom, | |
| 15 | inherent::{IntoKind, Span, Term as _, Ty as _}, | |
| 16 | relate::{Relate, solver_relating::RelateExt}, | |
| 10 | DebruijnIndex, InferConst, InferTy, RegionVid, TyVid, TypeFoldable, TypeFolder, | |
| 11 | TypeSuperFoldable, TypeVisitableExt, UpcastFrom, | |
| 12 | inherent::{Const as _, IntoKind, Ty as _}, | |
| 17 | 13 | solve::{Certainty, GoalSource}, |
| 18 | 14 | }; |
| 19 | 15 | use smallvec::SmallVec; |
| 20 | 16 | use triomphe::Arc; |
| 21 | 17 | |
| 22 | use super::{InferResult, InferenceContext, TypeError}; | |
| 23 | 18 | use crate::{ |
| 24 | AliasTy, BoundVar, Canonical, Const, ConstValue, DebruijnIndex, GenericArg, GenericArgData, | |
| 25 | InferenceVar, Interner, Lifetime, OpaqueTyId, ProjectionTy, Substitution, TraitEnvironment, Ty, | |
| 26 | TyExt, TyKind, VariableKind, | |
| 27 | consteval::unknown_const, | |
| 28 | db::HirDatabase, | |
| 29 | fold_generic_args, fold_tys_and_consts, | |
| 19 | TraitEnvironment, | |
| 20 | db::{HirDatabase, InternedOpaqueTyId}, | |
| 21 | infer::InferenceContext, | |
| 30 | 22 | next_solver::{ |
| 31 | self, ClauseKind, DbInterner, ErrorGuaranteed, Predicate, PredicateKind, SolverDefIds, | |
| 32 | Term, TraitRef, | |
| 33 | fulfill::FulfillmentCtxt, | |
| 23 | self, AliasTy, Binder, Canonical, ClauseKind, Const, ConstKind, DbInterner, | |
| 24 | ErrorGuaranteed, GenericArg, GenericArgs, Predicate, PredicateKind, Region, RegionKind, | |
| 25 | SolverDefId, SolverDefIds, TraitRef, Ty, TyKind, TypingMode, | |
| 26 | fulfill::{FulfillmentCtxt, NextSolverError}, | |
| 34 | 27 | infer::{ |
| 35 | DbInternerInferExt, InferCtxt, InferOk, | |
| 28 | DbInternerInferExt, DefineOpaqueTypes, InferCtxt, InferOk, InferResult, | |
| 29 | at::ToTrace, | |
| 36 | 30 | snapshot::CombinedSnapshot, |
| 37 | traits::{Obligation, ObligationCause}, | |
| 31 | traits::{Obligation, ObligationCause, PredicateObligation}, | |
| 38 | 32 | }, |
| 39 | 33 | inspect::{InspectConfig, InspectGoal, ProofTreeVisitor}, |
| 40 | mapping::{ChalkToNextSolver, NextSolverToChalk}, | |
| 34 | obligation_ctxt::ObligationCtxt, | |
| 41 | 35 | }, |
| 42 | 36 | traits::{ |
| 43 | 37 | FnTrait, NextTraitSolveResult, next_trait_solve_canonical_in_ctxt, next_trait_solve_in_ctxt, |
| 44 | 38 | }, |
| 45 | 39 | }; |
| 46 | 40 | |
| 47 | impl<'db> InferenceContext<'db> { | |
| 41 | impl<'db> InferenceContext<'_, 'db> { | |
| 48 | 42 | pub(super) fn canonicalize<T>(&mut self, t: T) -> rustc_type_ir::Canonical<DbInterner<'db>, T> |
| 49 | 43 | where |
| 50 | 44 | T: rustc_type_ir::TypeFoldable<DbInterner<'db>>, |
| ... | ... | @@ -77,7 +71,7 @@ impl<'a, 'db> ProofTreeVisitor<'db> for NestedObligationsForSelfTy<'a, 'db> { |
| 77 | 71 | return; |
| 78 | 72 | } |
| 79 | 73 | |
| 80 | let db = self.ctx.interner; | |
| 74 | let db = self.ctx.interner(); | |
| 81 | 75 | let goal = inspect_goal.goal(); |
| 82 | 76 | if self.ctx.predicate_has_self_ty(goal.predicate, self.self_ty) |
| 83 | 77 | // We do not push the instantiated forms of goals as it would cause any |
| ... | ... | @@ -118,109 +112,56 @@ impl<'a, 'db> ProofTreeVisitor<'db> for NestedObligationsForSelfTy<'a, 'db> { |
| 118 | 112 | /// This means that there may be some unresolved goals that actually set bounds for the placeholder |
| 119 | 113 | /// type for the types to unify. For example `Option<T>` and `Option<U>` unify although there is |
| 120 | 114 | /// unresolved goal `T = U`. |
| 121 | pub fn could_unify( | |
| 122 | db: &dyn HirDatabase, | |
| 123 | env: Arc<TraitEnvironment<'_>>, | |
| 124 | tys: &Canonical<(Ty, Ty)>, | |
| 115 | pub fn could_unify<'db>( | |
| 116 | db: &'db dyn HirDatabase, | |
| 117 | env: Arc<TraitEnvironment<'db>>, | |
| 118 | tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>, | |
| 125 | 119 | ) -> bool { |
| 126 | unify(db, env, tys).is_some() | |
| 120 | could_unify_impl(db, env, tys, |ctxt| ctxt.try_evaluate_obligations()) | |
| 127 | 121 | } |
| 128 | 122 | |
| 129 | 123 | /// Check if types unify eagerly making sure there are no unresolved goals. |
| 130 | 124 | /// |
| 131 | 125 | /// This means that placeholder types are not considered to unify if there are any bounds set on |
| 132 | 126 | /// them. For example `Option<T>` and `Option<U>` do not unify as we cannot show that `T = U` |
| 133 | pub fn could_unify_deeply( | |
| 134 | db: &dyn HirDatabase, | |
| 135 | env: Arc<TraitEnvironment<'_>>, | |
| 136 | tys: &Canonical<(Ty, Ty)>, | |
| 127 | pub fn could_unify_deeply<'db>( | |
| 128 | db: &'db dyn HirDatabase, | |
| 129 | env: Arc<TraitEnvironment<'db>>, | |
| 130 | tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>, | |
| 137 | 131 | ) -> bool { |
| 138 | let mut table = InferenceTable::new(db, env); | |
| 139 | let vars = make_substitutions(tys, &mut table); | |
| 140 | let ty1_with_vars = vars.apply(tys.value.0.clone(), Interner); | |
| 141 | let ty2_with_vars = vars.apply(tys.value.1.clone(), Interner); | |
| 142 | let ty1_with_vars = table.normalize_associated_types_in(ty1_with_vars); | |
| 143 | let ty2_with_vars = table.normalize_associated_types_in(ty2_with_vars); | |
| 144 | table.select_obligations_where_possible(); | |
| 145 | let ty1_with_vars = table.resolve_completely(ty1_with_vars); | |
| 146 | let ty2_with_vars = table.resolve_completely(ty2_with_vars); | |
| 147 | table.unify_deeply(&ty1_with_vars, &ty2_with_vars) | |
| 132 | could_unify_impl(db, env, tys, |ctxt| ctxt.evaluate_obligations_error_on_ambiguity()) | |
| 148 | 133 | } |
| 149 | 134 | |
| 150 | pub(crate) fn unify( | |
| 151 | db: &dyn HirDatabase, | |
| 152 | env: Arc<TraitEnvironment<'_>>, | |
| 153 | tys: &Canonical<(Ty, Ty)>, | |
| 154 | ) -> Option<Substitution> { | |
| 155 | let mut table = InferenceTable::new(db, env); | |
| 156 | let vars = make_substitutions(tys, &mut table); | |
| 157 | let ty1_with_vars = vars.apply(tys.value.0.clone(), Interner); | |
| 158 | let ty2_with_vars = vars.apply(tys.value.1.clone(), Interner); | |
| 159 | if !table.unify(&ty1_with_vars, &ty2_with_vars) { | |
| 160 | return None; | |
| 161 | } | |
| 162 | // default any type vars that weren't unified back to their original bound vars | |
| 163 | // (kind of hacky) | |
| 164 | let find_var = |iv| { | |
| 165 | vars.iter(Interner).position(|v| match v.data(Interner) { | |
| 166 | GenericArgData::Ty(ty) => ty.inference_var(Interner), | |
| 167 | GenericArgData::Lifetime(lt) => lt.inference_var(Interner), | |
| 168 | GenericArgData::Const(c) => c.inference_var(Interner), | |
| 169 | } == Some(iv)) | |
| 170 | }; | |
| 171 | let fallback = |iv, kind, binder| match kind { | |
| 172 | chalk_ir::VariableKind::Ty(_ty_kind) => find_var(iv).map_or_else( | |
| 173 | || TyKind::Error.intern(Interner).cast(Interner), | |
| 174 | |i| BoundVar::new(binder, i).to_ty(Interner).cast(Interner), | |
| 175 | ), | |
| 176 | chalk_ir::VariableKind::Lifetime => find_var(iv).map_or_else( | |
| 177 | || crate::error_lifetime().cast(Interner), | |
| 178 | |i| BoundVar::new(binder, i).to_lifetime(Interner).cast(Interner), | |
| 179 | ), | |
| 180 | chalk_ir::VariableKind::Const(ty) => find_var(iv).map_or_else( | |
| 181 | || crate::unknown_const(ty.clone()).cast(Interner), | |
| 182 | |i| BoundVar::new(binder, i).to_const(Interner, ty.clone()).cast(Interner), | |
| 183 | ), | |
| 184 | }; | |
| 185 | Some(Substitution::from_iter( | |
| 186 | Interner, | |
| 187 | vars.iter(Interner).map(|v| table.resolve_with_fallback(v.clone(), &fallback)), | |
| 188 | )) | |
| 189 | } | |
| 190 | ||
| 191 | fn make_substitutions( | |
| 192 | tys: &chalk_ir::Canonical<(chalk_ir::Ty<Interner>, chalk_ir::Ty<Interner>)>, | |
| 193 | table: &mut InferenceTable<'_>, | |
| 194 | ) -> chalk_ir::Substitution<Interner> { | |
| 195 | Substitution::from_iter( | |
| 196 | Interner, | |
| 197 | tys.binders.iter(Interner).map(|it| match &it.kind { | |
| 198 | chalk_ir::VariableKind::Ty(_) => table.new_type_var().cast(Interner), | |
| 199 | // FIXME: maybe wrong? | |
| 200 | chalk_ir::VariableKind::Lifetime => table.new_type_var().cast(Interner), | |
| 201 | chalk_ir::VariableKind::Const(ty) => table.new_const_var(ty.clone()).cast(Interner), | |
| 202 | }), | |
| 203 | ) | |
| 204 | } | |
| 205 | ||
| 206 | bitflags::bitflags! { | |
| 207 | #[derive(Default, Clone, Copy)] | |
| 208 | pub(crate) struct TypeVariableFlags: u8 { | |
| 209 | const DIVERGING = 1 << 0; | |
| 210 | const INTEGER = 1 << 1; | |
| 211 | const FLOAT = 1 << 2; | |
| 212 | } | |
| 135 | fn could_unify_impl<'db>( | |
| 136 | db: &'db dyn HirDatabase, | |
| 137 | env: Arc<TraitEnvironment<'db>>, | |
| 138 | tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>, | |
| 139 | select: for<'a> fn(&mut ObligationCtxt<'a, 'db>) -> Vec<NextSolverError<'db>>, | |
| 140 | ) -> bool { | |
| 141 | let interner = DbInterner::new_with(db, Some(env.krate), env.block); | |
| 142 | // FIXME(next-solver): I believe this should use `PostAnalysis` (this is only used for IDE things), | |
| 143 | // but this causes some bug because of our incorrect impl of `type_of_opaque_hir_typeck()` for TAIT | |
| 144 | // and async blocks. | |
| 145 | let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); | |
| 146 | let cause = ObligationCause::dummy(); | |
| 147 | let at = infcx.at(&cause, env.env); | |
| 148 | let ((ty1_with_vars, ty2_with_vars), _) = infcx.instantiate_canonical(tys); | |
| 149 | let mut ctxt = ObligationCtxt::new(&infcx); | |
| 150 | let can_unify = at | |
| 151 | .eq(DefineOpaqueTypes::No, ty1_with_vars, ty2_with_vars) | |
| 152 | .map(|infer_ok| ctxt.register_infer_ok_obligations(infer_ok)) | |
| 153 | .is_ok(); | |
| 154 | can_unify && select(&mut ctxt).is_empty() | |
| 213 | 155 | } |
| 214 | 156 | |
| 215 | 157 | #[derive(Clone)] |
| 216 | 158 | pub(crate) struct InferenceTable<'db> { |
| 217 | 159 | pub(crate) db: &'db dyn HirDatabase, |
| 218 | pub(crate) interner: DbInterner<'db>, | |
| 219 | 160 | pub(crate) trait_env: Arc<TraitEnvironment<'db>>, |
| 220 | pub(crate) tait_coercion_table: Option<FxHashMap<OpaqueTyId, Ty>>, | |
| 161 | pub(crate) tait_coercion_table: Option<FxHashMap<InternedOpaqueTyId, Ty<'db>>>, | |
| 221 | 162 | pub(crate) infer_ctxt: InferCtxt<'db>, |
| 222 | 163 | pub(super) fulfillment_cx: FulfillmentCtxt<'db>, |
| 223 | pub(super) diverging_type_vars: FxHashSet<crate::next_solver::Ty<'db>>, | |
| 164 | pub(super) diverging_type_vars: FxHashSet<Ty<'db>>, | |
| 224 | 165 | } |
| 225 | 166 | |
| 226 | 167 | pub(crate) struct InferenceTableSnapshot<'db> { |
| ... | ... | @@ -236,7 +177,6 @@ impl<'db> InferenceTable<'db> { |
| 236 | 177 | }); |
| 237 | 178 | InferenceTable { |
| 238 | 179 | db, |
| 239 | interner, | |
| 240 | 180 | trait_env, |
| 241 | 181 | tait_coercion_table: None, |
| 242 | 182 | fulfillment_cx: FulfillmentCtxt::new(&infer_ctxt), |
| ... | ... | @@ -245,15 +185,22 @@ impl<'db> InferenceTable<'db> { |
| 245 | 185 | } |
| 246 | 186 | } |
| 247 | 187 | |
| 188 | #[inline] | |
| 189 | pub(crate) fn interner(&self) -> DbInterner<'db> { | |
| 190 | self.infer_ctxt.interner | |
| 191 | } | |
| 192 | ||
| 193 | pub(crate) fn type_is_copy_modulo_regions(&self, ty: Ty<'db>) -> bool { | |
| 194 | self.infer_ctxt.type_is_copy_modulo_regions(self.trait_env.env, ty) | |
| 195 | } | |
| 196 | ||
| 248 | 197 | pub(crate) fn type_var_is_sized(&self, self_ty: TyVid) -> bool { |
| 249 | 198 | let Some(sized_did) = LangItem::Sized.resolve_trait(self.db, self.trait_env.krate) else { |
| 250 | 199 | return true; |
| 251 | 200 | }; |
| 252 | 201 | self.obligations_for_self_ty(self_ty).into_iter().any(|obligation| { |
| 253 | 202 | match obligation.predicate.kind().skip_binder() { |
| 254 | crate::next_solver::PredicateKind::Clause( | |
| 255 | crate::next_solver::ClauseKind::Trait(data), | |
| 256 | ) => data.def_id().0 == sized_did, | |
| 203 | PredicateKind::Clause(ClauseKind::Trait(data)) => data.def_id().0 == sized_did, | |
| 257 | 204 | _ => false, |
| 258 | 205 | } |
| 259 | 206 | }) |
| ... | ... | @@ -309,28 +256,24 @@ impl<'db> InferenceTable<'db> { |
| 309 | 256 | } |
| 310 | 257 | } |
| 311 | 258 | |
| 312 | fn type_matches_expected_vid( | |
| 313 | &self, | |
| 314 | expected_vid: TyVid, | |
| 315 | ty: crate::next_solver::Ty<'db>, | |
| 316 | ) -> bool { | |
| 259 | fn type_matches_expected_vid(&self, expected_vid: TyVid, ty: Ty<'db>) -> bool { | |
| 317 | 260 | let ty = self.shallow_resolve(ty); |
| 318 | 261 | |
| 319 | 262 | match ty.kind() { |
| 320 | crate::next_solver::TyKind::Infer(rustc_type_ir::TyVar(found_vid)) => { | |
| 263 | TyKind::Infer(rustc_type_ir::TyVar(found_vid)) => { | |
| 321 | 264 | self.infer_ctxt.root_var(expected_vid) == self.infer_ctxt.root_var(found_vid) |
| 322 | 265 | } |
| 323 | 266 | _ => false, |
| 324 | 267 | } |
| 325 | 268 | } |
| 326 | 269 | |
| 327 | pub(super) fn set_diverging(&mut self, ty: crate::next_solver::Ty<'db>) { | |
| 270 | pub(super) fn set_diverging(&mut self, ty: Ty<'db>) { | |
| 328 | 271 | self.diverging_type_vars.insert(ty); |
| 329 | 272 | } |
| 330 | 273 | |
| 331 | 274 | pub(crate) fn canonicalize<T>(&mut self, t: T) -> rustc_type_ir::Canonical<DbInterner<'db>, T> |
| 332 | 275 | where |
| 333 | T: rustc_type_ir::TypeFoldable<DbInterner<'db>>, | |
| 276 | T: TypeFoldable<DbInterner<'db>>, | |
| 334 | 277 | { |
| 335 | 278 | // try to resolve obligations before canonicalizing, since this might |
| 336 | 279 | // result in new knowledge about variables |
| ... | ... | @@ -338,26 +281,11 @@ impl<'db> InferenceTable<'db> { |
| 338 | 281 | self.infer_ctxt.canonicalize_response(t) |
| 339 | 282 | } |
| 340 | 283 | |
| 341 | /// Recurses through the given type, normalizing associated types mentioned | |
| 342 | /// in it by replacing them by type variables and registering obligations to | |
| 343 | /// resolve later. This should be done once for every type we get from some | |
| 344 | /// type annotation (e.g. from a let type annotation, field type or function | |
| 345 | /// call). `make_ty` handles this already, but e.g. for field types we need | |
| 346 | /// to do it as well. | |
| 347 | pub(crate) fn normalize_associated_types_in<T, U>(&mut self, ty: T) -> T | |
| 348 | where | |
| 349 | T: ChalkToNextSolver<'db, U>, | |
| 350 | U: NextSolverToChalk<'db, T> + rustc_type_ir::TypeFoldable<DbInterner<'db>>, | |
| 351 | { | |
| 352 | self.normalize_associated_types_in_ns(ty.to_nextsolver(self.interner)) | |
| 353 | .to_chalk(self.interner) | |
| 354 | } | |
| 355 | ||
| 356 | 284 | // FIXME: We should get rid of this method. We cannot deeply normalize during inference, only when finishing. |
| 357 | 285 | // Inference should use shallow normalization (`try_structurally_resolve_type()`) only, when needed. |
| 358 | pub(crate) fn normalize_associated_types_in_ns<T>(&mut self, ty: T) -> T | |
| 286 | pub(crate) fn normalize_associated_types_in<T>(&mut self, ty: T) -> T | |
| 359 | 287 | where |
| 360 | T: rustc_type_ir::TypeFoldable<DbInterner<'db>> + Clone, | |
| 288 | T: TypeFoldable<DbInterner<'db>> + Clone, | |
| 361 | 289 | { |
| 362 | 290 | let ty = self.resolve_vars_with_obligations(ty); |
| 363 | 291 | self.infer_ctxt |
| ... | ... | @@ -370,176 +298,130 @@ impl<'db> InferenceTable<'db> { |
| 370 | 298 | /// the inference variables |
| 371 | 299 | pub(crate) fn eagerly_normalize_and_resolve_shallow_in<T>(&mut self, ty: T) -> T |
| 372 | 300 | where |
| 373 | T: HasInterner<Interner = Interner> + TypeFoldable<Interner>, | |
| 301 | T: TypeFoldable<DbInterner<'db>>, | |
| 374 | 302 | { |
| 375 | fn eagerly_resolve_ty<const N: usize>( | |
| 376 | table: &mut InferenceTable<'_>, | |
| 377 | ty: Ty, | |
| 378 | mut tys: SmallVec<[Ty; N]>, | |
| 379 | ) -> Ty { | |
| 380 | if tys.contains(&ty) { | |
| 381 | return ty; | |
| 382 | } | |
| 383 | tys.push(ty.clone()); | |
| 384 | ||
| 385 | match ty.kind(Interner) { | |
| 386 | TyKind::Alias(AliasTy::Projection(proj_ty)) => { | |
| 387 | let ty = table.normalize_projection_ty(proj_ty.clone()); | |
| 388 | eagerly_resolve_ty(table, ty, tys) | |
| 389 | } | |
| 390 | TyKind::InferenceVar(..) => { | |
| 391 | let ty = table.resolve_ty_shallow(&ty); | |
| 392 | eagerly_resolve_ty(table, ty, tys) | |
| 393 | } | |
| 394 | _ => ty, | |
| 395 | } | |
| 396 | } | |
| 397 | ||
| 398 | fold_tys_and_consts( | |
| 399 | ty, | |
| 400 | |e, _| match e { | |
| 401 | Either::Left(ty) => { | |
| 402 | Either::Left(eagerly_resolve_ty::<8>(self, ty, SmallVec::new())) | |
| 403 | } | |
| 404 | Either::Right(c) => Either::Right(match &c.data(Interner).value { | |
| 405 | chalk_ir::ConstValue::Concrete(cc) => match &cc.interned { | |
| 406 | crate::ConstScalar::UnevaluatedConst(c_id, subst) => { | |
| 407 | // FIXME: same as `normalize_associated_types_in` | |
| 408 | if subst.len(Interner) == 0 { | |
| 409 | if let Ok(eval) = self.db.const_eval(*c_id, subst.clone(), None) { | |
| 410 | eval | |
| 411 | } else { | |
| 412 | unknown_const(c.data(Interner).ty.clone()) | |
| 413 | } | |
| 414 | } else { | |
| 415 | unknown_const(c.data(Interner).ty.clone()) | |
| 416 | } | |
| 417 | } | |
| 418 | _ => c, | |
| 419 | }, | |
| 420 | _ => c, | |
| 421 | }), | |
| 422 | }, | |
| 423 | DebruijnIndex::INNERMOST, | |
| 424 | ) | |
| 425 | } | |
| 426 | ||
| 427 | pub(crate) fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { | |
| 428 | let ty = TyKind::Alias(chalk_ir::AliasTy::Projection(proj_ty)) | |
| 429 | .intern(Interner) | |
| 430 | .to_nextsolver(self.interner); | |
| 431 | self.normalize_alias_ty(ty).to_chalk(self.interner) | |
| 432 | } | |
| 433 | ||
| 434 | pub(crate) fn normalize_alias_ty( | |
| 435 | &mut self, | |
| 436 | alias: crate::next_solver::Ty<'db>, | |
| 437 | ) -> crate::next_solver::Ty<'db> { | |
| 438 | let infer_term = self.infer_ctxt.next_ty_var(); | |
| 439 | let obligation = crate::next_solver::Predicate::new( | |
| 440 | self.interner, | |
| 441 | crate::next_solver::Binder::dummy(crate::next_solver::PredicateKind::AliasRelate( | |
| 442 | alias.into(), | |
| 443 | infer_term.into(), | |
| 444 | rustc_type_ir::AliasRelationDirection::Equate, | |
| 445 | )), | |
| 446 | ); | |
| 447 | self.register_obligation(obligation); | |
| 448 | self.resolve_vars_with_obligations(infer_term) | |
| 449 | } | |
| 450 | ||
| 451 | fn new_var(&mut self, kind: TyVariableKind, diverging: bool) -> Ty { | |
| 452 | let var = match kind { | |
| 453 | TyVariableKind::General => { | |
| 454 | let var = self.infer_ctxt.next_ty_vid(); | |
| 455 | InferenceVar::from(var.as_u32()) | |
| 456 | } | |
| 457 | TyVariableKind::Integer => { | |
| 458 | let var = self.infer_ctxt.next_int_vid(); | |
| 459 | InferenceVar::from(var.as_u32()) | |
| 460 | } | |
| 461 | TyVariableKind::Float => { | |
| 462 | let var = self.infer_ctxt.next_float_vid(); | |
| 463 | InferenceVar::from(var.as_u32()) | |
| 464 | } | |
| 465 | }; | |
| 466 | ||
| 467 | let ty = var.to_ty(Interner, kind); | |
| 468 | if diverging { | |
| 469 | self.diverging_type_vars.insert(ty.to_nextsolver(self.interner)); | |
| 470 | } | |
| 471 | ty | |
| 303 | let ty = self.resolve_vars_with_obligations(ty); | |
| 304 | let ty = self.normalize_associated_types_in(ty); | |
| 305 | self.resolve_vars_with_obligations(ty) | |
| 472 | 306 | } |
| 473 | 307 | |
| 474 | pub(crate) fn new_type_var(&mut self) -> Ty { | |
| 475 | self.new_var(TyVariableKind::General, false) | |
| 308 | pub(crate) fn normalize_alias_ty(&mut self, alias: Ty<'db>) -> Ty<'db> { | |
| 309 | self.infer_ctxt | |
| 310 | .at(&ObligationCause::new(), self.trait_env.env) | |
| 311 | .structurally_normalize_ty(alias, &mut self.fulfillment_cx) | |
| 312 | .unwrap_or(alias) | |
| 476 | 313 | } |
| 477 | 314 | |
| 478 | pub(crate) fn next_ty_var(&mut self) -> crate::next_solver::Ty<'db> { | |
| 315 | pub(crate) fn next_ty_var(&mut self) -> Ty<'db> { | |
| 479 | 316 | self.infer_ctxt.next_ty_var() |
| 480 | 317 | } |
| 481 | 318 | |
| 482 | pub(crate) fn new_integer_var(&mut self) -> Ty { | |
| 483 | self.new_var(TyVariableKind::Integer, false) | |
| 319 | pub(crate) fn next_const_var(&mut self) -> Const<'db> { | |
| 320 | self.infer_ctxt.next_const_var() | |
| 484 | 321 | } |
| 485 | 322 | |
| 486 | pub(crate) fn new_float_var(&mut self) -> Ty { | |
| 487 | self.new_var(TyVariableKind::Float, false) | |
| 323 | pub(crate) fn next_int_var(&mut self) -> Ty<'db> { | |
| 324 | self.infer_ctxt.next_int_var() | |
| 488 | 325 | } |
| 489 | 326 | |
| 490 | pub(crate) fn new_maybe_never_var(&mut self) -> Ty { | |
| 491 | self.new_var(TyVariableKind::General, true) | |
| 327 | pub(crate) fn next_float_var(&mut self) -> Ty<'db> { | |
| 328 | self.infer_ctxt.next_float_var() | |
| 492 | 329 | } |
| 493 | 330 | |
| 494 | pub(crate) fn new_const_var(&mut self, ty: Ty) -> Const { | |
| 495 | let var = self.infer_ctxt.next_const_vid(); | |
| 496 | let var = InferenceVar::from(var.as_u32()); | |
| 497 | var.to_const(Interner, ty) | |
| 331 | pub(crate) fn new_maybe_never_var(&mut self) -> Ty<'db> { | |
| 332 | let var = self.next_ty_var(); | |
| 333 | self.set_diverging(var); | |
| 334 | var | |
| 498 | 335 | } |
| 499 | 336 | |
| 500 | pub(crate) fn new_lifetime_var(&mut self) -> Lifetime { | |
| 501 | let var = self.infer_ctxt.next_region_vid(); | |
| 502 | let var = InferenceVar::from(var.as_u32()); | |
| 503 | var.to_lifetime(Interner) | |
| 337 | pub(crate) fn next_region_var(&mut self) -> Region<'db> { | |
| 338 | self.infer_ctxt.next_region_var() | |
| 504 | 339 | } |
| 505 | 340 | |
| 506 | pub(crate) fn next_region_var(&mut self) -> crate::next_solver::Region<'db> { | |
| 507 | self.infer_ctxt.next_region_var() | |
| 341 | pub(crate) fn next_var_for_param(&mut self, id: GenericParamId) -> GenericArg<'db> { | |
| 342 | match id { | |
| 343 | GenericParamId::TypeParamId(_) => self.next_ty_var().into(), | |
| 344 | GenericParamId::ConstParamId(_) => self.next_const_var().into(), | |
| 345 | GenericParamId::LifetimeParamId(_) => self.next_region_var().into(), | |
| 346 | } | |
| 508 | 347 | } |
| 509 | 348 | |
| 510 | 349 | pub(crate) fn resolve_with_fallback<T>( |
| 511 | 350 | &mut self, |
| 512 | 351 | t: T, |
| 513 | fallback: &dyn Fn(InferenceVar, VariableKind, DebruijnIndex) -> GenericArg, | |
| 352 | fallback_ty: &mut dyn FnMut(DebruijnIndex, InferTy) -> Ty<'db>, | |
| 353 | fallback_const: &mut dyn FnMut(DebruijnIndex, InferConst) -> Const<'db>, | |
| 354 | fallback_region: &mut dyn FnMut(DebruijnIndex, RegionVid) -> Region<'db>, | |
| 514 | 355 | ) -> T |
| 515 | 356 | where |
| 516 | T: HasInterner<Interner = Interner> + TypeFoldable<Interner>, | |
| 357 | T: TypeFoldable<DbInterner<'db>>, | |
| 517 | 358 | { |
| 518 | self.resolve_with_fallback_inner(t, &fallback) | |
| 519 | } | |
| 359 | struct Resolver<'a, 'db> { | |
| 360 | table: &'a mut InferenceTable<'db>, | |
| 361 | binder: DebruijnIndex, | |
| 362 | fallback_ty: &'a mut dyn FnMut(DebruijnIndex, InferTy) -> Ty<'db>, | |
| 363 | fallback_const: &'a mut dyn FnMut(DebruijnIndex, InferConst) -> Const<'db>, | |
| 364 | fallback_region: &'a mut dyn FnMut(DebruijnIndex, RegionVid) -> Region<'db>, | |
| 365 | } | |
| 520 | 366 | |
| 521 | pub(crate) fn fresh_subst(&mut self, binders: &[CanonicalVarKind<Interner>]) -> Substitution { | |
| 522 | Substitution::from_iter( | |
| 523 | Interner, | |
| 524 | binders.iter().map(|kind| match &kind.kind { | |
| 525 | chalk_ir::VariableKind::Ty(ty_variable_kind) => { | |
| 526 | self.new_var(*ty_variable_kind, false).cast(Interner) | |
| 367 | impl<'db> TypeFolder<DbInterner<'db>> for Resolver<'_, 'db> { | |
| 368 | fn cx(&self) -> DbInterner<'db> { | |
| 369 | self.table.interner() | |
| 370 | } | |
| 371 | ||
| 372 | fn fold_binder<T>(&mut self, t: Binder<'db, T>) -> Binder<'db, T> | |
| 373 | where | |
| 374 | T: TypeFoldable<DbInterner<'db>>, | |
| 375 | { | |
| 376 | self.binder.shift_in(1); | |
| 377 | let result = t.super_fold_with(self); | |
| 378 | self.binder.shift_out(1); | |
| 379 | result | |
| 380 | } | |
| 381 | ||
| 382 | fn fold_ty(&mut self, t: Ty<'db>) -> Ty<'db> { | |
| 383 | if !t.has_infer() { | |
| 384 | return t; | |
| 527 | 385 | } |
| 528 | chalk_ir::VariableKind::Lifetime => self.new_lifetime_var().cast(Interner), | |
| 529 | chalk_ir::VariableKind::Const(ty) => self.new_const_var(ty.clone()).cast(Interner), | |
| 530 | }), | |
| 531 | ) | |
| 532 | } | |
| 533 | 386 | |
| 534 | pub(crate) fn instantiate_canonical<T>(&mut self, canonical: Canonical<T>) -> T | |
| 535 | where | |
| 536 | T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + std::fmt::Debug, | |
| 537 | { | |
| 538 | let subst = self.fresh_subst(canonical.binders.as_slice(Interner)); | |
| 539 | subst.apply(canonical.value, Interner) | |
| 387 | if let TyKind::Infer(infer) = t.kind() { | |
| 388 | (self.fallback_ty)(self.binder, infer) | |
| 389 | } else { | |
| 390 | t.super_fold_with(self) | |
| 391 | } | |
| 392 | } | |
| 393 | ||
| 394 | fn fold_const(&mut self, c: Const<'db>) -> Const<'db> { | |
| 395 | if !c.has_infer() { | |
| 396 | return c; | |
| 397 | } | |
| 398 | ||
| 399 | if let ConstKind::Infer(infer) = c.kind() { | |
| 400 | (self.fallback_const)(self.binder, infer) | |
| 401 | } else { | |
| 402 | c.super_fold_with(self) | |
| 403 | } | |
| 404 | } | |
| 405 | ||
| 406 | fn fold_region(&mut self, r: Region<'db>) -> Region<'db> { | |
| 407 | if let RegionKind::ReVar(infer) = r.kind() { | |
| 408 | (self.fallback_region)(self.binder, infer) | |
| 409 | } else { | |
| 410 | r | |
| 411 | } | |
| 412 | } | |
| 413 | } | |
| 414 | ||
| 415 | t.fold_with(&mut Resolver { | |
| 416 | table: self, | |
| 417 | binder: DebruijnIndex::ZERO, | |
| 418 | fallback_ty, | |
| 419 | fallback_const, | |
| 420 | fallback_region, | |
| 421 | }) | |
| 540 | 422 | } |
| 541 | 423 | |
| 542 | pub(crate) fn instantiate_canonical_ns<T>( | |
| 424 | pub(crate) fn instantiate_canonical<T>( | |
| 543 | 425 | &mut self, |
| 544 | 426 | canonical: rustc_type_ir::Canonical<DbInterner<'db>, T>, |
| 545 | 427 | ) -> T |
| ... | ... | @@ -549,112 +431,35 @@ impl<'db> InferenceTable<'db> { |
| 549 | 431 | self.infer_ctxt.instantiate_canonical(&canonical).0 |
| 550 | 432 | } |
| 551 | 433 | |
| 552 | fn resolve_with_fallback_inner<T>( | |
| 553 | &mut self, | |
| 554 | t: T, | |
| 555 | fallback: &dyn Fn(InferenceVar, VariableKind, DebruijnIndex) -> GenericArg, | |
| 556 | ) -> T | |
| 434 | pub(crate) fn resolve_completely<T>(&mut self, value: T) -> T | |
| 557 | 435 | where |
| 558 | T: HasInterner<Interner = Interner> + TypeFoldable<Interner>, | |
| 436 | T: TypeFoldable<DbInterner<'db>>, | |
| 559 | 437 | { |
| 560 | let var_stack = &mut vec![]; | |
| 561 | t.fold_with( | |
| 562 | &mut resolve::Resolver { table: self, var_stack, fallback }, | |
| 563 | DebruijnIndex::INNERMOST, | |
| 564 | ) | |
| 565 | } | |
| 566 | ||
| 567 | pub(crate) fn resolve_completely<T, U>(&mut self, t: T) -> T | |
| 568 | where | |
| 569 | T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + ChalkToNextSolver<'db, U>, | |
| 570 | U: NextSolverToChalk<'db, T> + rustc_type_ir::TypeFoldable<DbInterner<'db>>, | |
| 571 | { | |
| 572 | let value = t.to_nextsolver(self.interner); | |
| 573 | 438 | let value = self.infer_ctxt.resolve_vars_if_possible(value); |
| 574 | 439 | |
| 575 | 440 | let mut goals = vec![]; |
| 576 | let value = value.fold_with(&mut resolve_completely::Resolver::new(self, true, &mut goals)); | |
| 577 | 441 | |
| 578 | 442 | // FIXME(next-solver): Handle `goals`. |
| 579 | 443 | |
| 580 | value.to_chalk(self.interner) | |
| 444 | value.fold_with(&mut resolve_completely::Resolver::new(self, true, &mut goals)) | |
| 581 | 445 | } |
| 582 | 446 | |
| 583 | 447 | /// Unify two relatable values (e.g. `Ty`) and register new trait goals that arise from that. |
| 584 | pub(crate) fn unify<T: ChalkToNextSolver<'db, U>, U: Relate<DbInterner<'db>>>( | |
| 585 | &mut self, | |
| 586 | ty1: &T, | |
| 587 | ty2: &T, | |
| 588 | ) -> bool { | |
| 589 | let result = match self.try_unify(ty1, ty2) { | |
| 590 | Ok(r) => r, | |
| 591 | Err(_) => return false, | |
| 592 | }; | |
| 593 | self.register_obligations(result.goals); | |
| 594 | true | |
| 595 | } | |
| 596 | ||
| 597 | pub(crate) fn unify_ns<T: Relate<DbInterner<'db>>>(&mut self, lhs: T, rhs: T) -> bool { | |
| 598 | let Ok(infer_ok) = self.try_unify_ns(lhs, rhs) else { | |
| 599 | return false; | |
| 600 | }; | |
| 601 | self.register_obligations(infer_ok.goals); | |
| 602 | true | |
| 603 | } | |
| 604 | ||
| 605 | /// Unify two relatable values (e.g. `Ty`) and check whether trait goals which arise from that could be fulfilled | |
| 606 | pub(crate) fn unify_deeply<T: ChalkToNextSolver<'db, U>, U: Relate<DbInterner<'db>>>( | |
| 607 | &mut self, | |
| 608 | ty1: &T, | |
| 609 | ty2: &T, | |
| 610 | ) -> bool { | |
| 611 | let result = match self.try_unify(ty1, ty2) { | |
| 612 | Ok(r) => r, | |
| 613 | Err(_) => return false, | |
| 614 | }; | |
| 615 | result.goals.into_iter().all(|goal| { | |
| 616 | matches!(next_trait_solve_in_ctxt(&self.infer_ctxt, goal), Ok((_, Certainty::Yes))) | |
| 617 | }) | |
| 448 | pub(crate) fn unify<T: ToTrace<'db>>(&mut self, ty1: T, ty2: T) -> bool { | |
| 449 | self.try_unify(ty1, ty2).map(|infer_ok| self.register_infer_ok(infer_ok)).is_ok() | |
| 618 | 450 | } |
| 619 | 451 | |
| 620 | 452 | /// Unify two relatable values (e.g. `Ty`) and return new trait goals arising from it, so the |
| 621 | 453 | /// caller needs to deal with them. |
| 622 | pub(crate) fn try_unify<T: ChalkToNextSolver<'db, U>, U: Relate<DbInterner<'db>>>( | |
| 623 | &mut self, | |
| 624 | t1: &T, | |
| 625 | t2: &T, | |
| 626 | ) -> InferResult<'db, ()> { | |
| 627 | let lhs = t1.to_nextsolver(self.interner); | |
| 628 | let rhs = t2.to_nextsolver(self.interner); | |
| 629 | self.try_unify_ns(lhs, rhs) | |
| 630 | } | |
| 631 | ||
| 632 | /// Unify two relatable values (e.g. `Ty`) and return new trait goals arising from it, so the | |
| 633 | /// caller needs to deal with them. | |
| 634 | pub(crate) fn try_unify_ns<T: Relate<DbInterner<'db>>>( | |
| 635 | &mut self, | |
| 636 | lhs: T, | |
| 637 | rhs: T, | |
| 638 | ) -> InferResult<'db, ()> { | |
| 639 | let variance = rustc_type_ir::Variance::Invariant; | |
| 640 | let span = crate::next_solver::Span::dummy(); | |
| 641 | match self.infer_ctxt.relate(self.trait_env.env, lhs, variance, rhs, span) { | |
| 642 | Ok(goals) => Ok(crate::infer::InferOk { goals, value: () }), | |
| 643 | Err(_) => Err(TypeError), | |
| 644 | } | |
| 645 | } | |
| 646 | ||
| 647 | /// If `ty` is a type variable with known type, returns that type; | |
| 648 | /// otherwise, return ty. | |
| 649 | #[tracing::instrument(skip(self))] | |
| 650 | pub(crate) fn resolve_ty_shallow(&mut self, ty: &Ty) -> Ty { | |
| 651 | self.shallow_resolve(ty.to_nextsolver(self.interner)).to_chalk(self.interner) | |
| 454 | pub(crate) fn try_unify<T: ToTrace<'db>>(&mut self, t1: T, t2: T) -> InferResult<'db, ()> { | |
| 455 | self.infer_ctxt.at(&ObligationCause::new(), self.trait_env.env).eq( | |
| 456 | DefineOpaqueTypes::Yes, | |
| 457 | t1, | |
| 458 | t2, | |
| 459 | ) | |
| 652 | 460 | } |
| 653 | 461 | |
| 654 | pub(crate) fn shallow_resolve( | |
| 655 | &self, | |
| 656 | ty: crate::next_solver::Ty<'db>, | |
| 657 | ) -> crate::next_solver::Ty<'db> { | |
| 462 | pub(crate) fn shallow_resolve(&self, ty: Ty<'db>) -> Ty<'db> { | |
| 658 | 463 | self.infer_ctxt.shallow_resolve(ty) |
| 659 | 464 | } |
| 660 | 465 | |
| ... | ... | @@ -662,8 +467,6 @@ impl<'db> InferenceTable<'db> { |
| 662 | 467 | where |
| 663 | 468 | T: rustc_type_ir::TypeFoldable<DbInterner<'db>>, |
| 664 | 469 | { |
| 665 | use rustc_type_ir::TypeVisitableExt; | |
| 666 | ||
| 667 | 470 | if !t.has_non_region_infer() { |
| 668 | 471 | return t; |
| 669 | 472 | } |
| ... | ... | @@ -678,26 +481,18 @@ impl<'db> InferenceTable<'db> { |
| 678 | 481 | self.infer_ctxt.resolve_vars_if_possible(t) |
| 679 | 482 | } |
| 680 | 483 | |
| 681 | pub(crate) fn structurally_resolve_type(&mut self, ty: &Ty) -> Ty { | |
| 682 | if let TyKind::Alias(chalk_ir::AliasTy::Projection(..)) = ty.kind(Interner) { | |
| 683 | self.structurally_normalize_ty(ty) | |
| 684 | } else { | |
| 685 | self.resolve_vars_with_obligations(ty.to_nextsolver(self.interner)) | |
| 686 | .to_chalk(self.interner) | |
| 687 | } | |
| 688 | } | |
| 689 | ||
| 690 | fn structurally_normalize_ty(&mut self, ty: &Ty) -> Ty { | |
| 691 | self.structurally_normalize_term(ty.to_nextsolver(self.interner).into()) | |
| 692 | .expect_ty() | |
| 693 | .to_chalk(self.interner) | |
| 484 | /// Create a `GenericArgs` full of infer vars for `def`. | |
| 485 | pub(crate) fn fresh_args_for_item(&self, def: SolverDefId) -> GenericArgs<'db> { | |
| 486 | self.infer_ctxt.fresh_args_for_item(def) | |
| 694 | 487 | } |
| 695 | 488 | |
| 696 | fn structurally_normalize_term(&mut self, term: Term<'db>) -> Term<'db> { | |
| 697 | self.infer_ctxt | |
| 698 | .at(&ObligationCause::new(), self.trait_env.env) | |
| 699 | .structurally_normalize_term(term, &mut self.fulfillment_cx) | |
| 700 | .unwrap_or(term) | |
| 489 | /// Like `fresh_args_for_item()`, but first uses the args from `first`. | |
| 490 | pub(crate) fn fill_rest_fresh_args( | |
| 491 | &self, | |
| 492 | def_id: SolverDefId, | |
| 493 | first: impl IntoIterator<Item = GenericArg<'db>>, | |
| 494 | ) -> GenericArgs<'db> { | |
| 495 | self.infer_ctxt.fill_rest_fresh_args(def_id, first) | |
| 701 | 496 | } |
| 702 | 497 | |
| 703 | 498 | /// Try to resolve `ty` to a structural type, normalizing aliases. |
| ... | ... | @@ -705,11 +500,8 @@ impl<'db> InferenceTable<'db> { |
| 705 | 500 | /// In case there is still ambiguity, the returned type may be an inference |
| 706 | 501 | /// variable. This is different from `structurally_resolve_type` which errors |
| 707 | 502 | /// in this case. |
| 708 | pub(crate) fn try_structurally_resolve_type( | |
| 709 | &mut self, | |
| 710 | ty: crate::next_solver::Ty<'db>, | |
| 711 | ) -> crate::next_solver::Ty<'db> { | |
| 712 | if let crate::next_solver::TyKind::Alias(..) = ty.kind() { | |
| 503 | pub(crate) fn try_structurally_resolve_type(&mut self, ty: Ty<'db>) -> Ty<'db> { | |
| 504 | if let TyKind::Alias(..) = ty.kind() { | |
| 713 | 505 | // We need to use a separate variable here as otherwise the temporary for |
| 714 | 506 | // `self.fulfillment_cx.borrow_mut()` is alive in the `Err` branch, resulting |
| 715 | 507 | // in a reentrant borrow, causing an ICE. |
| ... | ... | @@ -719,13 +511,18 @@ impl<'db> InferenceTable<'db> { |
| 719 | 511 | .structurally_normalize_ty(ty, &mut self.fulfillment_cx); |
| 720 | 512 | match result { |
| 721 | 513 | Ok(normalized_ty) => normalized_ty, |
| 722 | Err(_errors) => crate::next_solver::Ty::new_error(self.interner, ErrorGuaranteed), | |
| 514 | Err(_errors) => Ty::new_error(self.interner(), ErrorGuaranteed), | |
| 723 | 515 | } |
| 724 | 516 | } else { |
| 725 | 517 | self.resolve_vars_with_obligations(ty) |
| 726 | 518 | } |
| 727 | 519 | } |
| 728 | 520 | |
| 521 | pub(crate) fn structurally_resolve_type(&mut self, ty: Ty<'db>) -> Ty<'db> { | |
| 522 | self.try_structurally_resolve_type(ty) | |
| 523 | // FIXME: Err if it still contain infer vars. | |
| 524 | } | |
| 525 | ||
| 729 | 526 | pub(crate) fn snapshot(&mut self) -> InferenceTableSnapshot<'db> { |
| 730 | 527 | let ctxt_snapshot = self.infer_ctxt.start_snapshot(); |
| 731 | 528 | let obligations = self.fulfillment_cx.clone(); |
| ... | ... | @@ -794,7 +591,7 @@ impl<'db> InferenceTable<'db> { |
| 794 | 591 | self.fulfillment_cx.register_predicate_obligation( |
| 795 | 592 | &self.infer_ctxt, |
| 796 | 593 | Obligation::new( |
| 797 | self.interner, | |
| 594 | self.interner(), | |
| 798 | 595 | ObligationCause::new(), |
| 799 | 596 | goal.param_env, |
| 800 | 597 | goal.predicate, |
| ... | ... | @@ -810,21 +607,11 @@ impl<'db> InferenceTable<'db> { |
| 810 | 607 | value |
| 811 | 608 | } |
| 812 | 609 | |
| 813 | pub(crate) fn register_obligations( | |
| 814 | &mut self, | |
| 815 | obligations: Vec<crate::next_solver::Goal<'db, crate::next_solver::Predicate<'db>>>, | |
| 816 | ) { | |
| 817 | obligations.into_iter().for_each(|goal| self.register_obligation_in_env(goal)); | |
| 818 | } | |
| 819 | ||
| 820 | 610 | pub(crate) fn select_obligations_where_possible(&mut self) { |
| 821 | 611 | self.fulfillment_cx.try_evaluate_obligations(&self.infer_ctxt); |
| 822 | 612 | } |
| 823 | 613 | |
| 824 | pub(super) fn register_predicate( | |
| 825 | &mut self, | |
| 826 | obligation: crate::next_solver::infer::traits::PredicateObligation<'db>, | |
| 827 | ) { | |
| 614 | pub(super) fn register_predicate(&mut self, obligation: PredicateObligation<'db>) { | |
| 828 | 615 | if obligation.has_escaping_bound_vars() { |
| 829 | 616 | panic!("escaping bound vars in predicate {:?}", obligation); |
| 830 | 617 | } |
| ... | ... | @@ -834,7 +621,7 @@ impl<'db> InferenceTable<'db> { |
| 834 | 621 | |
| 835 | 622 | pub(super) fn register_predicates<I>(&mut self, obligations: I) |
| 836 | 623 | where |
| 837 | I: IntoIterator<Item = crate::next_solver::infer::traits::PredicateObligation<'db>>, | |
| 624 | I: IntoIterator<Item = PredicateObligation<'db>>, | |
| 838 | 625 | { |
| 839 | 626 | obligations.into_iter().for_each(|obligation| { |
| 840 | 627 | self.register_predicate(obligation); |
| ... | ... | @@ -843,16 +630,14 @@ impl<'db> InferenceTable<'db> { |
| 843 | 630 | |
| 844 | 631 | pub(crate) fn callable_sig( |
| 845 | 632 | &mut self, |
| 846 | ty: &Ty, | |
| 633 | ty: Ty<'db>, | |
| 847 | 634 | num_args: usize, |
| 848 | ) -> Option<(Option<FnTrait>, Vec<crate::next_solver::Ty<'db>>, crate::next_solver::Ty<'db>)> | |
| 849 | { | |
| 850 | match ty.callable_sig(self.db) { | |
| 851 | Some(sig) => Some(( | |
| 852 | None, | |
| 853 | sig.params().iter().map(|param| param.to_nextsolver(self.interner)).collect(), | |
| 854 | sig.ret().to_nextsolver(self.interner), | |
| 855 | )), | |
| 635 | ) -> Option<(Option<FnTrait>, Vec<Ty<'db>>, Ty<'db>)> { | |
| 636 | match ty.callable_sig(self.interner()) { | |
| 637 | Some(sig) => { | |
| 638 | let sig = sig.skip_binder(); | |
| 639 | Some((None, sig.inputs_and_output.inputs().to_vec(), sig.output())) | |
| 640 | } | |
| 856 | 641 | None => { |
| 857 | 642 | let (f, args_ty, return_ty) = self.callable_sig_from_fn_trait(ty, num_args)?; |
| 858 | 643 | Some((Some(f), args_ty, return_ty)) |
| ... | ... | @@ -862,9 +647,9 @@ impl<'db> InferenceTable<'db> { |
| 862 | 647 | |
| 863 | 648 | fn callable_sig_from_fn_trait( |
| 864 | 649 | &mut self, |
| 865 | ty: &Ty, | |
| 650 | ty: Ty<'db>, | |
| 866 | 651 | num_args: usize, |
| 867 | ) -> Option<(FnTrait, Vec<next_solver::Ty<'db>>, next_solver::Ty<'db>)> { | |
| 652 | ) -> Option<(FnTrait, Vec<Ty<'db>>, Ty<'db>)> { | |
| 868 | 653 | for (fn_trait_name, output_assoc_name, subtraits) in [ |
| 869 | 654 | (FnTrait::FnOnce, sym::Output, &[FnTrait::Fn, FnTrait::FnMut][..]), |
| 870 | 655 | (FnTrait::AsyncFnMut, sym::CallRefFuture, &[FnTrait::AsyncFn]), |
| ... | ... | @@ -877,8 +662,8 @@ impl<'db> InferenceTable<'db> { |
| 877 | 662 | trait_data.associated_type_by_name(&Name::new_symbol_root(output_assoc_name))?; |
| 878 | 663 | |
| 879 | 664 | let mut arg_tys = Vec::with_capacity(num_args); |
| 880 | let arg_ty = next_solver::Ty::new_tup_from_iter( | |
| 881 | self.interner, | |
| 665 | let arg_ty = Ty::new_tup_from_iter( | |
| 666 | self.interner(), | |
| 882 | 667 | std::iter::repeat_with(|| { |
| 883 | 668 | let ty = self.next_ty_var(); |
| 884 | 669 | arg_tys.push(ty); |
| ... | ... | @@ -886,24 +671,23 @@ impl<'db> InferenceTable<'db> { |
| 886 | 671 | }) |
| 887 | 672 | .take(num_args), |
| 888 | 673 | ); |
| 889 | let args = [ty.to_nextsolver(self.interner), arg_ty]; | |
| 890 | let trait_ref = crate::next_solver::TraitRef::new(self.interner, fn_trait.into(), args); | |
| 674 | let args = [ty, arg_ty]; | |
| 675 | let trait_ref = TraitRef::new(self.interner(), fn_trait.into(), args); | |
| 891 | 676 | |
| 892 | let projection = crate::next_solver::Ty::new_alias( | |
| 893 | self.interner, | |
| 677 | let projection = Ty::new_alias( | |
| 678 | self.interner(), | |
| 894 | 679 | rustc_type_ir::AliasTyKind::Projection, |
| 895 | crate::next_solver::AliasTy::new(self.interner, output_assoc_type.into(), args), | |
| 680 | AliasTy::new(self.interner(), output_assoc_type.into(), args), | |
| 896 | 681 | ); |
| 897 | 682 | |
| 898 | let pred = crate::next_solver::Predicate::upcast_from(trait_ref, self.interner); | |
| 683 | let pred = Predicate::upcast_from(trait_ref, self.interner()); | |
| 899 | 684 | if !self.try_obligation(pred).no_solution() { |
| 900 | 685 | self.register_obligation(pred); |
| 901 | 686 | let return_ty = self.normalize_alias_ty(projection); |
| 902 | 687 | for &fn_x in subtraits { |
| 903 | 688 | let fn_x_trait = fn_x.get_id(self.db, krate)?; |
| 904 | let trait_ref = | |
| 905 | crate::next_solver::TraitRef::new(self.interner, fn_x_trait.into(), args); | |
| 906 | let pred = crate::next_solver::Predicate::upcast_from(trait_ref, self.interner); | |
| 689 | let trait_ref = TraitRef::new(self.interner(), fn_x_trait.into(), args); | |
| 690 | let pred = Predicate::upcast_from(trait_ref, self.interner()); | |
| 907 | 691 | if !self.try_obligation(pred).no_solution() { |
| 908 | 692 | return Some((fn_x, arg_tys, return_ty)); |
| 909 | 693 | } |
| ... | ... | @@ -916,40 +700,53 @@ impl<'db> InferenceTable<'db> { |
| 916 | 700 | |
| 917 | 701 | pub(super) fn insert_type_vars<T>(&mut self, ty: T) -> T |
| 918 | 702 | where |
| 919 | T: HasInterner<Interner = Interner> + TypeFoldable<Interner>, | |
| 703 | T: TypeFoldable<DbInterner<'db>>, | |
| 920 | 704 | { |
| 921 | fold_generic_args( | |
| 922 | ty, | |
| 923 | |arg, _| match arg { | |
| 924 | GenericArgData::Ty(ty) => GenericArgData::Ty(self.insert_type_vars_shallow(ty)), | |
| 925 | // FIXME: insert lifetime vars once LifetimeData::InferenceVar | |
| 926 | // and specific error variant for lifetimes start being constructed | |
| 927 | GenericArgData::Lifetime(lt) => GenericArgData::Lifetime(lt), | |
| 928 | GenericArgData::Const(c) => { | |
| 929 | GenericArgData::Const(self.insert_const_vars_shallow(c)) | |
| 705 | struct Folder<'a, 'db> { | |
| 706 | table: &'a mut InferenceTable<'db>, | |
| 707 | } | |
| 708 | impl<'db> TypeFolder<DbInterner<'db>> for Folder<'_, 'db> { | |
| 709 | fn cx(&self) -> DbInterner<'db> { | |
| 710 | self.table.interner() | |
| 711 | } | |
| 712 | ||
| 713 | fn fold_ty(&mut self, ty: Ty<'db>) -> Ty<'db> { | |
| 714 | if !ty.references_error() { | |
| 715 | return ty; | |
| 930 | 716 | } |
| 931 | }, | |
| 932 | DebruijnIndex::INNERMOST, | |
| 933 | ) | |
| 934 | } | |
| 935 | 717 | |
| 936 | /// Replaces `Ty::Error` by a new type var, so we can maybe still infer it. | |
| 937 | pub(super) fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { | |
| 938 | match ty.kind(Interner) { | |
| 939 | TyKind::Error => self.new_type_var(), | |
| 940 | TyKind::InferenceVar(..) => { | |
| 941 | let ty_resolved = self.structurally_resolve_type(&ty); | |
| 942 | if ty_resolved.is_unknown() { self.new_type_var() } else { ty } | |
| 718 | if ty.is_ty_error() { self.table.next_ty_var() } else { ty.super_fold_with(self) } | |
| 719 | } | |
| 720 | ||
| 721 | fn fold_const(&mut self, ct: Const<'db>) -> Const<'db> { | |
| 722 | if !ct.references_error() { | |
| 723 | return ct; | |
| 724 | } | |
| 725 | ||
| 726 | if ct.is_ct_error() { | |
| 727 | self.table.next_const_var() | |
| 728 | } else { | |
| 729 | ct.super_fold_with(self) | |
| 730 | } | |
| 731 | } | |
| 732 | ||
| 733 | fn fold_region(&mut self, r: Region<'db>) -> Region<'db> { | |
| 734 | if r.is_error() { self.table.next_region_var() } else { r } | |
| 943 | 735 | } |
| 944 | _ => ty, | |
| 945 | 736 | } |
| 737 | ||
| 738 | ty.fold_with(&mut Folder { table: self }) | |
| 739 | } | |
| 740 | ||
| 741 | /// Replaces `Ty::Error` by a new type var, so we can maybe still infer it. | |
| 742 | pub(super) fn insert_type_vars_shallow(&mut self, ty: Ty<'db>) -> Ty<'db> { | |
| 743 | if ty.is_ty_error() { self.next_ty_var() } else { ty } | |
| 946 | 744 | } |
| 947 | 745 | |
| 948 | 746 | /// Whenever you lower a user-written type, you should call this. |
| 949 | pub(crate) fn process_user_written_ty<T, U>(&mut self, ty: T) -> T | |
| 747 | pub(crate) fn process_user_written_ty<T>(&mut self, ty: T) -> T | |
| 950 | 748 | where |
| 951 | T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + ChalkToNextSolver<'db, U>, | |
| 952 | U: NextSolverToChalk<'db, T> + rustc_type_ir::TypeFoldable<DbInterner<'db>>, | |
| 749 | T: TypeFoldable<DbInterner<'db>>, | |
| 953 | 750 | { |
| 954 | 751 | self.process_remote_user_written_ty(ty) |
| 955 | 752 | // FIXME: Register a well-formed obligation. |
| ... | ... | @@ -957,10 +754,9 @@ impl<'db> InferenceTable<'db> { |
| 957 | 754 | |
| 958 | 755 | /// The difference of this method from `process_user_written_ty()` is that this method doesn't register a well-formed obligation, |
| 959 | 756 | /// while `process_user_written_ty()` should (but doesn't currently). |
| 960 | pub(crate) fn process_remote_user_written_ty<T, U>(&mut self, ty: T) -> T | |
| 757 | pub(crate) fn process_remote_user_written_ty<T>(&mut self, ty: T) -> T | |
| 961 | 758 | where |
| 962 | T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + ChalkToNextSolver<'db, U>, | |
| 963 | U: NextSolverToChalk<'db, T> + rustc_type_ir::TypeFoldable<DbInterner<'db>>, | |
| 759 | T: TypeFoldable<DbInterner<'db>>, | |
| 964 | 760 | { |
| 965 | 761 | let ty = self.insert_type_vars(ty); |
| 966 | 762 | // See https://github.com/rust-lang/rust/blob/cdb45c87e2cd43495379f7e867e3cc15dcee9f93/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs#L487-L495: |
| ... | ... | @@ -971,44 +767,33 @@ impl<'db> InferenceTable<'db> { |
| 971 | 767 | } |
| 972 | 768 | |
| 973 | 769 | /// Replaces ConstScalar::Unknown by a new type var, so we can maybe still infer it. |
| 974 | pub(super) fn insert_const_vars_shallow(&mut self, c: Const) -> Const { | |
| 975 | let data = c.data(Interner); | |
| 976 | match &data.value { | |
| 977 | ConstValue::Concrete(cc) => match &cc.interned { | |
| 978 | crate::ConstScalar::Unknown => self.new_const_var(data.ty.clone()), | |
| 979 | // try to evaluate unevaluated const. Replace with new var if const eval failed. | |
| 980 | crate::ConstScalar::UnevaluatedConst(id, subst) => { | |
| 981 | if let Ok(eval) = self.db.const_eval(*id, subst.clone(), None) { | |
| 982 | eval | |
| 983 | } else { | |
| 984 | self.new_const_var(data.ty.clone()) | |
| 985 | } | |
| 986 | } | |
| 987 | _ => c, | |
| 988 | }, | |
| 989 | _ => c, | |
| 990 | } | |
| 770 | pub(super) fn insert_const_vars_shallow(&mut self, c: Const<'db>) -> Const<'db> { | |
| 771 | if c.is_ct_error() { self.next_const_var() } else { c } | |
| 991 | 772 | } |
| 992 | 773 | |
| 993 | 774 | /// Check if given type is `Sized` or not |
| 994 | pub(crate) fn is_sized(&mut self, ty: &Ty) -> bool { | |
| 995 | fn short_circuit_trivial_tys(ty: &Ty) -> Option<bool> { | |
| 996 | match ty.kind(Interner) { | |
| 997 | TyKind::Scalar(..) | |
| 775 | pub(crate) fn is_sized(&mut self, ty: Ty<'db>) -> bool { | |
| 776 | fn short_circuit_trivial_tys(ty: Ty<'_>) -> Option<bool> { | |
| 777 | match ty.kind() { | |
| 778 | TyKind::Bool | |
| 779 | | TyKind::Char | |
| 780 | | TyKind::Int(_) | |
| 781 | | TyKind::Uint(_) | |
| 782 | | TyKind::Float(_) | |
| 998 | 783 | | TyKind::Ref(..) |
| 999 | | TyKind::Raw(..) | |
| 784 | | TyKind::RawPtr(..) | |
| 1000 | 785 | | TyKind::Never |
| 1001 | 786 | | TyKind::FnDef(..) |
| 1002 | 787 | | TyKind::Array(..) |
| 1003 | | TyKind::Function(..) => Some(true), | |
| 1004 | TyKind::Slice(..) | TyKind::Str | TyKind::Dyn(..) => Some(false), | |
| 788 | | TyKind::FnPtr(..) => Some(true), | |
| 789 | TyKind::Slice(..) | TyKind::Str | TyKind::Dynamic(..) => Some(false), | |
| 1005 | 790 | _ => None, |
| 1006 | 791 | } |
| 1007 | 792 | } |
| 1008 | 793 | |
| 1009 | let mut ty = ty.clone(); | |
| 794 | let mut ty = ty; | |
| 1010 | 795 | ty = self.eagerly_normalize_and_resolve_shallow_in(ty); |
| 1011 | if let Some(sized) = short_circuit_trivial_tys(&ty) { | |
| 796 | if let Some(sized) = short_circuit_trivial_tys(ty) { | |
| 1012 | 797 | return sized; |
| 1013 | 798 | } |
| 1014 | 799 | |
| ... | ... | @@ -1019,9 +804,8 @@ impl<'db> InferenceTable<'db> { |
| 1019 | 804 | while let Some((AdtId::StructId(id), subst)) = ty.as_adt() { |
| 1020 | 805 | let struct_data = id.fields(self.db); |
| 1021 | 806 | if let Some((last_field, _)) = struct_data.fields().iter().next_back() { |
| 1022 | let last_field_ty = self.db.field_types(id.into())[last_field] | |
| 1023 | .clone() | |
| 1024 | .substitute(Interner, subst); | |
| 807 | let last_field_ty = self.db.field_types_ns(id.into())[last_field] | |
| 808 | .instantiate(self.interner(), subst); | |
| 1025 | 809 | if structs.contains(&ty) { |
| 1026 | 810 | // A struct recursively contains itself as a tail field somewhere. |
| 1027 | 811 | return true; // Don't overload the users with too many errors. |
| ... | ... | @@ -1031,7 +815,7 @@ impl<'db> InferenceTable<'db> { |
| 1031 | 815 | // as unsized by the chalk, so we do this manually. |
| 1032 | 816 | ty = last_field_ty; |
| 1033 | 817 | ty = self.eagerly_normalize_and_resolve_shallow_in(ty); |
| 1034 | if let Some(sized) = short_circuit_trivial_tys(&ty) { | |
| 818 | if let Some(sized) = short_circuit_trivial_tys(ty) { | |
| 1035 | 819 | return sized; |
| 1036 | 820 | } |
| 1037 | 821 | } else { |
| ... | ... | @@ -1044,8 +828,8 @@ impl<'db> InferenceTable<'db> { |
| 1044 | 828 | return false; |
| 1045 | 829 | }; |
| 1046 | 830 | let sized_pred = Predicate::upcast_from( |
| 1047 | TraitRef::new(self.interner, sized.into(), [ty.to_nextsolver(self.interner)]), | |
| 1048 | self.interner, | |
| 831 | TraitRef::new(self.interner(), sized.into(), [ty]), | |
| 832 | self.interner(), | |
| 1049 | 833 | ); |
| 1050 | 834 | self.try_obligation(sized_pred).certain() |
| 1051 | 835 | } |
| ... | ... | @@ -1060,189 +844,14 @@ impl fmt::Debug for InferenceTable<'_> { |
| 1060 | 844 | } |
| 1061 | 845 | } |
| 1062 | 846 | |
| 1063 | mod resolve { | |
| 1064 | use super::InferenceTable; | |
| 1065 | use crate::{ | |
| 1066 | Const, DebruijnIndex, GenericArg, InferenceVar, Interner, Lifetime, Ty, TyVariableKind, | |
| 1067 | VariableKind, next_solver::mapping::NextSolverToChalk, | |
| 1068 | }; | |
| 1069 | use chalk_ir::fold::{TypeFoldable, TypeFolder}; | |
| 1070 | use rustc_type_ir::{FloatVid, IntVid, TyVid}; | |
| 1071 | ||
| 1072 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | |
| 1073 | pub(super) enum VarKind { | |
| 1074 | Ty(TyVariableKind), | |
| 1075 | Const, | |
| 1076 | } | |
| 1077 | ||
| 1078 | #[derive(chalk_derive::FallibleTypeFolder)] | |
| 1079 | #[has_interner(Interner)] | |
| 1080 | pub(super) struct Resolver< | |
| 1081 | 'a, | |
| 1082 | 'b, | |
| 1083 | F: Fn(InferenceVar, VariableKind, DebruijnIndex) -> GenericArg, | |
| 1084 | > { | |
| 1085 | pub(super) table: &'a mut InferenceTable<'b>, | |
| 1086 | pub(super) var_stack: &'a mut Vec<(InferenceVar, VarKind)>, | |
| 1087 | pub(super) fallback: F, | |
| 1088 | } | |
| 1089 | impl<F> TypeFolder<Interner> for Resolver<'_, '_, F> | |
| 1090 | where | |
| 1091 | F: Fn(InferenceVar, VariableKind, DebruijnIndex) -> GenericArg, | |
| 1092 | { | |
| 1093 | fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner> { | |
| 1094 | self | |
| 1095 | } | |
| 1096 | ||
| 1097 | fn interner(&self) -> Interner { | |
| 1098 | Interner | |
| 1099 | } | |
| 1100 | ||
| 1101 | fn fold_inference_ty( | |
| 1102 | &mut self, | |
| 1103 | var: InferenceVar, | |
| 1104 | kind: TyVariableKind, | |
| 1105 | outer_binder: DebruijnIndex, | |
| 1106 | ) -> Ty { | |
| 1107 | match kind { | |
| 1108 | TyVariableKind::General => { | |
| 1109 | let vid = self.table.infer_ctxt.root_var(TyVid::from(var.index())); | |
| 1110 | let var = InferenceVar::from(vid.as_u32()); | |
| 1111 | if self.var_stack.contains(&(var, VarKind::Ty(kind))) { | |
| 1112 | // recursive type | |
| 1113 | return (self.fallback)(var, VariableKind::Ty(kind), outer_binder) | |
| 1114 | .assert_ty_ref(Interner) | |
| 1115 | .clone(); | |
| 1116 | } | |
| 1117 | if let Ok(known_ty) = self.table.infer_ctxt.probe_ty_var(vid) { | |
| 1118 | let known_ty: Ty = known_ty.to_chalk(self.table.interner); | |
| 1119 | // known_ty may contain other variables that are known by now | |
| 1120 | self.var_stack.push((var, VarKind::Ty(kind))); | |
| 1121 | let result = known_ty.fold_with(self, outer_binder); | |
| 1122 | self.var_stack.pop(); | |
| 1123 | result | |
| 1124 | } else { | |
| 1125 | (self.fallback)(var, VariableKind::Ty(kind), outer_binder) | |
| 1126 | .assert_ty_ref(Interner) | |
| 1127 | .clone() | |
| 1128 | } | |
| 1129 | } | |
| 1130 | TyVariableKind::Integer => { | |
| 1131 | let vid = self | |
| 1132 | .table | |
| 1133 | .infer_ctxt | |
| 1134 | .inner | |
| 1135 | .borrow_mut() | |
| 1136 | .int_unification_table() | |
| 1137 | .find(IntVid::from(var.index())); | |
| 1138 | let var = InferenceVar::from(vid.as_u32()); | |
| 1139 | if self.var_stack.contains(&(var, VarKind::Ty(kind))) { | |
| 1140 | // recursive type | |
| 1141 | return (self.fallback)(var, VariableKind::Ty(kind), outer_binder) | |
| 1142 | .assert_ty_ref(Interner) | |
| 1143 | .clone(); | |
| 1144 | } | |
| 1145 | if let Some(known_ty) = self.table.infer_ctxt.resolve_int_var(vid) { | |
| 1146 | let known_ty: Ty = known_ty.to_chalk(self.table.interner); | |
| 1147 | // known_ty may contain other variables that are known by now | |
| 1148 | self.var_stack.push((var, VarKind::Ty(kind))); | |
| 1149 | let result = known_ty.fold_with(self, outer_binder); | |
| 1150 | self.var_stack.pop(); | |
| 1151 | result | |
| 1152 | } else { | |
| 1153 | (self.fallback)(var, VariableKind::Ty(kind), outer_binder) | |
| 1154 | .assert_ty_ref(Interner) | |
| 1155 | .clone() | |
| 1156 | } | |
| 1157 | } | |
| 1158 | TyVariableKind::Float => { | |
| 1159 | let vid = self | |
| 1160 | .table | |
| 1161 | .infer_ctxt | |
| 1162 | .inner | |
| 1163 | .borrow_mut() | |
| 1164 | .float_unification_table() | |
| 1165 | .find(FloatVid::from(var.index())); | |
| 1166 | let var = InferenceVar::from(vid.as_u32()); | |
| 1167 | if self.var_stack.contains(&(var, VarKind::Ty(kind))) { | |
| 1168 | // recursive type | |
| 1169 | return (self.fallback)(var, VariableKind::Ty(kind), outer_binder) | |
| 1170 | .assert_ty_ref(Interner) | |
| 1171 | .clone(); | |
| 1172 | } | |
| 1173 | if let Some(known_ty) = self.table.infer_ctxt.resolve_float_var(vid) { | |
| 1174 | let known_ty: Ty = known_ty.to_chalk(self.table.interner); | |
| 1175 | // known_ty may contain other variables that are known by now | |
| 1176 | self.var_stack.push((var, VarKind::Ty(kind))); | |
| 1177 | let result = known_ty.fold_with(self, outer_binder); | |
| 1178 | self.var_stack.pop(); | |
| 1179 | result | |
| 1180 | } else { | |
| 1181 | (self.fallback)(var, VariableKind::Ty(kind), outer_binder) | |
| 1182 | .assert_ty_ref(Interner) | |
| 1183 | .clone() | |
| 1184 | } | |
| 1185 | } | |
| 1186 | } | |
| 1187 | } | |
| 1188 | ||
| 1189 | fn fold_inference_const( | |
| 1190 | &mut self, | |
| 1191 | ty: Ty, | |
| 1192 | var: InferenceVar, | |
| 1193 | outer_binder: DebruijnIndex, | |
| 1194 | ) -> Const { | |
| 1195 | let vid = self | |
| 1196 | .table | |
| 1197 | .infer_ctxt | |
| 1198 | .root_const_var(rustc_type_ir::ConstVid::from_u32(var.index())); | |
| 1199 | let var = InferenceVar::from(vid.as_u32()); | |
| 1200 | if self.var_stack.contains(&(var, VarKind::Const)) { | |
| 1201 | // recursive | |
| 1202 | return (self.fallback)(var, VariableKind::Const(ty), outer_binder) | |
| 1203 | .assert_const_ref(Interner) | |
| 1204 | .clone(); | |
| 1205 | } | |
| 1206 | if let Ok(known_const) = self.table.infer_ctxt.probe_const_var(vid) { | |
| 1207 | let known_const: Const = known_const.to_chalk(self.table.interner); | |
| 1208 | // known_ty may contain other variables that are known by now | |
| 1209 | self.var_stack.push((var, VarKind::Const)); | |
| 1210 | let result = known_const.fold_with(self, outer_binder); | |
| 1211 | self.var_stack.pop(); | |
| 1212 | result | |
| 1213 | } else { | |
| 1214 | (self.fallback)(var, VariableKind::Const(ty), outer_binder) | |
| 1215 | .assert_const_ref(Interner) | |
| 1216 | .clone() | |
| 1217 | } | |
| 1218 | } | |
| 1219 | ||
| 1220 | fn fold_inference_lifetime( | |
| 1221 | &mut self, | |
| 1222 | _var: InferenceVar, | |
| 1223 | _outer_binder: DebruijnIndex, | |
| 1224 | ) -> Lifetime { | |
| 1225 | // fall back all lifetimes to 'error -- currently we don't deal | |
| 1226 | // with any lifetimes, but we can sometimes get some lifetime | |
| 1227 | // variables through Chalk's unification, and this at least makes | |
| 1228 | // sure we don't leak them outside of inference | |
| 1229 | crate::error_lifetime() | |
| 1230 | } | |
| 1231 | } | |
| 1232 | } | |
| 1233 | ||
| 1234 | 847 | mod resolve_completely { |
| 1235 | use rustc_type_ir::{ | |
| 1236 | DebruijnIndex, Flags, TypeFolder, TypeSuperFoldable, | |
| 1237 | inherent::{Const as _, Ty as _}, | |
| 1238 | }; | |
| 848 | use rustc_type_ir::{DebruijnIndex, Flags, TypeFolder, TypeSuperFoldable}; | |
| 1239 | 849 | |
| 1240 | use crate::next_solver::Region; | |
| 1241 | 850 | use crate::{ |
| 1242 | 851 | infer::unify::InferenceTable, |
| 1243 | 852 | next_solver::{ |
| 1244 | Const, DbInterner, ErrorGuaranteed, Goal, Predicate, Term, Ty, | |
| 1245 | infer::traits::ObligationCause, | |
| 853 | Const, DbInterner, Goal, Predicate, Region, Term, Ty, | |
| 854 | infer::{resolve::ReplaceInferWithError, traits::ObligationCause}, | |
| 1246 | 855 | normalize::deeply_normalize_with_skipped_universes_and_ambiguous_coroutine_goals, |
| 1247 | 856 | }, |
| 1248 | 857 | }; |
| ... | ... | @@ -1291,17 +900,17 @@ mod resolve_completely { |
| 1291 | 900 | value |
| 1292 | 901 | }; |
| 1293 | 902 | |
| 1294 | value.fold_with(&mut ReplaceInferWithError { interner: self.ctx.interner }) | |
| 903 | value.fold_with(&mut ReplaceInferWithError::new(self.ctx.interner())) | |
| 1295 | 904 | } |
| 1296 | 905 | } |
| 1297 | 906 | |
| 1298 | 907 | impl<'cx, 'db> TypeFolder<DbInterner<'db>> for Resolver<'cx, 'db> { |
| 1299 | 908 | fn cx(&self) -> DbInterner<'db> { |
| 1300 | self.ctx.interner | |
| 909 | self.ctx.interner() | |
| 1301 | 910 | } |
| 1302 | 911 | |
| 1303 | 912 | fn fold_region(&mut self, r: Region<'db>) -> Region<'db> { |
| 1304 | if r.is_var() { Region::error(self.ctx.interner) } else { r } | |
| 913 | if r.is_var() { Region::error(self.ctx.interner()) } else { r } | |
| 1305 | 914 | } |
| 1306 | 915 | |
| 1307 | 916 | fn fold_ty(&mut self, ty: Ty<'db>) -> Ty<'db> { |
| ... | ... | @@ -1320,34 +929,4 @@ mod resolve_completely { |
| 1320 | 929 | predicate.super_fold_with(self) |
| 1321 | 930 | } |
| 1322 | 931 | } |
| 1323 | ||
| 1324 | struct ReplaceInferWithError<'db> { | |
| 1325 | interner: DbInterner<'db>, | |
| 1326 | } | |
| 1327 | ||
| 1328 | impl<'db> TypeFolder<DbInterner<'db>> for ReplaceInferWithError<'db> { | |
| 1329 | fn cx(&self) -> DbInterner<'db> { | |
| 1330 | self.interner | |
| 1331 | } | |
| 1332 | ||
| 1333 | fn fold_ty(&mut self, t: Ty<'db>) -> Ty<'db> { | |
| 1334 | if t.is_infer() { | |
| 1335 | Ty::new_error(self.interner, ErrorGuaranteed) | |
| 1336 | } else { | |
| 1337 | t.super_fold_with(self) | |
| 1338 | } | |
| 1339 | } | |
| 1340 | ||
| 1341 | fn fold_const(&mut self, c: Const<'db>) -> Const<'db> { | |
| 1342 | if c.is_ct_infer() { | |
| 1343 | Const::new_error(self.interner, ErrorGuaranteed) | |
| 1344 | } else { | |
| 1345 | c.super_fold_with(self) | |
| 1346 | } | |
| 1347 | } | |
| 1348 | ||
| 1349 | fn fold_region(&mut self, r: Region<'db>) -> Region<'db> { | |
| 1350 | if r.is_var() { Region::error(self.interner) } else { r } | |
| 1351 | } | |
| 1352 | } | |
| 1353 | 932 | } |
src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs+10-5| ... | ... | @@ -11,7 +11,9 @@ use triomphe::Arc; |
| 11 | 11 | |
| 12 | 12 | use crate::{ |
| 13 | 13 | AliasTy, Binders, Interner, Substitution, TraitEnvironment, Ty, TyKind, |
| 14 | consteval::try_const_usize, db::HirDatabase, | |
| 14 | consteval::try_const_usize, | |
| 15 | db::HirDatabase, | |
| 16 | next_solver::{DbInterner, mapping::ChalkToNextSolver}, | |
| 15 | 17 | }; |
| 16 | 18 | |
| 17 | 19 | // FIXME: Turn this into a query, it can be quite slow |
| ... | ... | @@ -79,14 +81,17 @@ impl TypeVisitor<Interner> for UninhabitedFrom<'_> { |
| 79 | 81 | } |
| 80 | 82 | self.recursive_ty.insert(ty.clone()); |
| 81 | 83 | self.max_depth -= 1; |
| 84 | let interner = DbInterner::new_with(self.db, None, None); | |
| 82 | 85 | let r = match ty.kind(Interner) { |
| 83 | 86 | TyKind::Adt(adt, subst) => self.visit_adt(adt.0, subst), |
| 84 | 87 | TyKind::Never => BREAK_VISIBLY_UNINHABITED, |
| 85 | 88 | TyKind::Tuple(..) => ty.super_visit_with(self, outer_binder), |
| 86 | TyKind::Array(item_ty, len) => match try_const_usize(self.db, len) { | |
| 87 | Some(0) | None => CONTINUE_OPAQUELY_INHABITED, | |
| 88 | Some(1..) => item_ty.super_visit_with(self, outer_binder), | |
| 89 | }, | |
| 89 | TyKind::Array(item_ty, len) => { | |
| 90 | match try_const_usize(self.db, len.to_nextsolver(interner)) { | |
| 91 | Some(0) | None => CONTINUE_OPAQUELY_INHABITED, | |
| 92 | Some(1..) => item_ty.super_visit_with(self, outer_binder), | |
| 93 | } | |
| 94 | } | |
| 90 | 95 | TyKind::Alias(AliasTy::Projection(projection)) => { |
| 91 | 96 | // FIXME: I think this currently isn't used for monomorphized bodies, so there is no need to handle |
| 92 | 97 | // `TyKind::AssociatedType`, but perhaps in the future it will. |
src/tools/rust-analyzer/crates/hir-ty/src/layout.rs+6-15| ... | ... | @@ -19,15 +19,13 @@ use rustc_type_ir::{ |
| 19 | 19 | }; |
| 20 | 20 | use triomphe::Arc; |
| 21 | 21 | |
| 22 | use crate::utils::ClosureSubst; | |
| 23 | 22 | use crate::{ |
| 24 | Interner, TraitEnvironment, | |
| 25 | consteval_nextsolver::try_const_usize, | |
| 23 | TraitEnvironment, | |
| 24 | consteval::try_const_usize, | |
| 26 | 25 | db::HirDatabase, |
| 27 | 26 | next_solver::{ |
| 28 | 27 | DbInterner, GenericArgs, ParamEnv, Ty, TyKind, TypingMode, |
| 29 | 28 | infer::{DbInternerInferExt, traits::ObligationCause}, |
| 30 | mapping::{ChalkToNextSolver, convert_args_for_result}, | |
| 31 | 29 | }, |
| 32 | 30 | }; |
| 33 | 31 | |
| ... | ... | @@ -325,19 +323,12 @@ pub fn layout_of_ty_query<'db>( |
| 325 | 323 | TyKind::Closure(id, args) => { |
| 326 | 324 | let def = db.lookup_intern_closure(id.0); |
| 327 | 325 | let infer = db.infer(def.0); |
| 328 | let (captures, _) = infer.closure_info(&id.0.into()); | |
| 326 | let (captures, _) = infer.closure_info(id.0); | |
| 329 | 327 | let fields = captures |
| 330 | 328 | .iter() |
| 331 | 329 | .map(|it| { |
| 332 | let ty = it | |
| 333 | .ty | |
| 334 | .clone() | |
| 335 | .substitute( | |
| 336 | Interner, | |
| 337 | &ClosureSubst(&convert_args_for_result(interner, args.inner())) | |
| 338 | .parent_subst(db), | |
| 339 | ) | |
| 340 | .to_nextsolver(interner); | |
| 330 | let ty = | |
| 331 | it.ty.instantiate(interner, args.split_closure_args_untupled().parent_args); | |
| 341 | 332 | db.layout_of_ty(ty, trait_env.clone()) |
| 342 | 333 | }) |
| 343 | 334 | .collect::<Result<Vec<_>, _>>()?; |
| ... | ... | @@ -394,7 +385,7 @@ fn struct_tail_erasing_lifetimes<'a>(db: &'a dyn HirDatabase, pointee: Ty<'a>) - |
| 394 | 385 | } |
| 395 | 386 | } |
| 396 | 387 | TyKind::Tuple(tys) => { |
| 397 | if let Some(last_field_ty) = tys.iter().last() { | |
| 388 | if let Some(last_field_ty) = tys.iter().next_back() { | |
| 398 | 389 | struct_tail_erasing_lifetimes(db, last_field_ty) |
| 399 | 390 | } else { |
| 400 | 391 | pointee |
src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs+1-1| ... | ... | @@ -39,7 +39,7 @@ pub fn target_data_layout_query( |
| 39 | 39 | target, |
| 40 | 40 | } => format!(r#"inconsistent target specification: "data-layout" claims pointers are {pointer_size}-bit, while "target-pointer-width" is `{target}`"#), |
| 41 | 41 | TargetDataLayoutErrors::InvalidBitsSize { err } => err, |
| 42 | TargetDataLayoutErrors::UnknownPointerSpecification { err } => format!(r#"use of unknown pointer specifer in "data-layout": {err}"#), | |
| 42 | TargetDataLayoutErrors::UnknownPointerSpecification { err } => format!(r#"use of unknown pointer specifier in "data-layout": {err}"#), | |
| 43 | 43 | }.into()) |
| 44 | 44 | } |
| 45 | 45 | }, |
src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs+31-29| ... | ... | @@ -3,7 +3,7 @@ use either::Either; |
| 3 | 3 | use hir_def::db::DefDatabase; |
| 4 | 4 | use project_model::{Sysroot, toolchain_info::QueryConfig}; |
| 5 | 5 | use rustc_hash::FxHashMap; |
| 6 | use rustc_type_ir::inherent::{GenericArgs as _, Ty as _}; | |
| 6 | use rustc_type_ir::inherent::GenericArgs as _; | |
| 7 | 7 | use syntax::ToSmolStr; |
| 8 | 8 | use test_fixture::WithFixture; |
| 9 | 9 | use triomphe::Arc; |
| ... | ... | @@ -11,7 +11,7 @@ use triomphe::Arc; |
| 11 | 11 | use crate::{ |
| 12 | 12 | db::HirDatabase, |
| 13 | 13 | layout::{Layout, LayoutError}, |
| 14 | next_solver::{AdtDef, DbInterner, GenericArgs, mapping::ChalkToNextSolver}, | |
| 14 | next_solver::{DbInterner, GenericArgs}, | |
| 15 | 15 | setup_tracing, |
| 16 | 16 | test_db::TestDB, |
| 17 | 17 | }; |
| ... | ... | @@ -79,12 +79,12 @@ fn eval_goal( |
| 79 | 79 | Some(adt_or_type_alias_id) |
| 80 | 80 | }) |
| 81 | 81 | .unwrap(); |
| 82 | salsa::attach(&db, || { | |
| 82 | crate::attach_db(&db, || { | |
| 83 | 83 | let interner = DbInterner::new_with(&db, None, None); |
| 84 | 84 | let goal_ty = match adt_or_type_alias_id { |
| 85 | 85 | Either::Left(adt_id) => crate::next_solver::Ty::new_adt( |
| 86 | 86 | interner, |
| 87 | AdtDef::new(adt_id, interner), | |
| 87 | adt_id, | |
| 88 | 88 | GenericArgs::identity_for_item(interner, adt_id.into()), |
| 89 | 89 | ), |
| 90 | 90 | Either::Right(ty_id) => db.ty(ty_id.into()).instantiate_identity(), |
| ... | ... | @@ -112,31 +112,33 @@ fn eval_expr( |
| 112 | 112 | ); |
| 113 | 113 | |
| 114 | 114 | let (db, file_id) = TestDB::with_single_file(&ra_fixture); |
| 115 | let module_id = db.module_for_file(file_id.file_id(&db)); | |
| 116 | let def_map = module_id.def_map(&db); | |
| 117 | let scope = &def_map[module_id.local_id].scope; | |
| 118 | let function_id = scope | |
| 119 | .declarations() | |
| 120 | .find_map(|x| match x { | |
| 121 | hir_def::ModuleDefId::FunctionId(x) => { | |
| 122 | let name = | |
| 123 | db.function_signature(x).name.display_no_db(file_id.edition(&db)).to_smolstr(); | |
| 124 | (name == "main").then_some(x) | |
| 125 | } | |
| 126 | _ => None, | |
| 127 | }) | |
| 128 | .unwrap(); | |
| 129 | let hir_body = db.body(function_id.into()); | |
| 130 | let b = hir_body | |
| 131 | .bindings() | |
| 132 | .find(|x| x.1.name.display_no_db(file_id.edition(&db)).to_smolstr() == "goal") | |
| 133 | .unwrap() | |
| 134 | .0; | |
| 135 | let infer = db.infer(function_id.into()); | |
| 136 | let goal_ty = infer.type_of_binding[b].clone(); | |
| 137 | salsa::attach(&db, || { | |
| 138 | let interner = DbInterner::new_with(&db, None, None); | |
| 139 | db.layout_of_ty(goal_ty.to_nextsolver(interner), db.trait_environment(function_id.into())) | |
| 115 | crate::attach_db(&db, || { | |
| 116 | let module_id = db.module_for_file(file_id.file_id(&db)); | |
| 117 | let def_map = module_id.def_map(&db); | |
| 118 | let scope = &def_map[module_id.local_id].scope; | |
| 119 | let function_id = scope | |
| 120 | .declarations() | |
| 121 | .find_map(|x| match x { | |
| 122 | hir_def::ModuleDefId::FunctionId(x) => { | |
| 123 | let name = db | |
| 124 | .function_signature(x) | |
| 125 | .name | |
| 126 | .display_no_db(file_id.edition(&db)) | |
| 127 | .to_smolstr(); | |
| 128 | (name == "main").then_some(x) | |
| 129 | } | |
| 130 | _ => None, | |
| 131 | }) | |
| 132 | .unwrap(); | |
| 133 | let hir_body = db.body(function_id.into()); | |
| 134 | let b = hir_body | |
| 135 | .bindings() | |
| 136 | .find(|x| x.1.name.display_no_db(file_id.edition(&db)).to_smolstr() == "goal") | |
| 137 | .unwrap() | |
| 138 | .0; | |
| 139 | let infer = db.infer(function_id.into()); | |
| 140 | let goal_ty = infer.type_of_binding[b]; | |
| 141 | db.layout_of_ty(goal_ty, db.trait_environment(function_id.into())) | |
| 140 | 142 | }) |
| 141 | 143 | } |
| 142 | 144 |
src/tools/rust-analyzer/crates/hir-ty/src/lib.rs+217-300| ... | ... | @@ -21,10 +21,11 @@ extern crate ra_ap_rustc_type_ir as rustc_type_ir; |
| 21 | 21 | |
| 22 | 22 | extern crate ra_ap_rustc_next_trait_solver as rustc_next_trait_solver; |
| 23 | 23 | |
| 24 | extern crate self as hir_ty; | |
| 25 | ||
| 24 | 26 | mod builder; |
| 25 | 27 | mod chalk_db; |
| 26 | 28 | mod chalk_ext; |
| 27 | mod drop; | |
| 28 | 29 | mod infer; |
| 29 | 30 | mod inhabitedness; |
| 30 | 31 | mod interner; |
| ... | ... | @@ -38,10 +39,11 @@ mod utils; |
| 38 | 39 | |
| 39 | 40 | pub mod autoderef; |
| 40 | 41 | pub mod consteval; |
| 41 | pub mod consteval_nextsolver; | |
| 42 | mod consteval_chalk; | |
| 42 | 43 | pub mod db; |
| 43 | 44 | pub mod diagnostics; |
| 44 | 45 | pub mod display; |
| 46 | pub mod drop; | |
| 45 | 47 | pub mod dyn_compatibility; |
| 46 | 48 | pub mod generics; |
| 47 | 49 | pub mod lang_items; |
| ... | ... | @@ -60,11 +62,10 @@ mod variance; |
| 60 | 62 | use std::hash::Hash; |
| 61 | 63 | |
| 62 | 64 | use chalk_ir::{ |
| 63 | NoSolution, VariableKinds, | |
| 65 | VariableKinds, | |
| 64 | 66 | fold::{Shift, TypeFoldable}, |
| 65 | 67 | interner::HasInterner, |
| 66 | 68 | }; |
| 67 | use either::Either; | |
| 68 | 69 | use hir_def::{CallableDefId, GeneralConstId, TypeOrConstParamId, hir::ExprId, type_ref::Rawness}; |
| 69 | 70 | use hir_expand::name::Name; |
| 70 | 71 | use indexmap::{IndexMap, map::Entry}; |
| ... | ... | @@ -73,15 +74,16 @@ use la_arena::{Arena, Idx}; |
| 73 | 74 | use mir::{MirEvalError, VTableMap}; |
| 74 | 75 | use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet}; |
| 75 | 76 | use rustc_type_ir::{ |
| 76 | UpcastFrom, | |
| 77 | inherent::{SliceLike, Ty as _}, | |
| 77 | TypeSuperVisitable, TypeVisitableExt, UpcastFrom, | |
| 78 | inherent::{IntoKind, SliceLike, Ty as _}, | |
| 78 | 79 | }; |
| 79 | 80 | use syntax::ast::{ConstArg, make}; |
| 80 | 81 | use traits::FnTrait; |
| 81 | 82 | use triomphe::Arc; |
| 82 | 83 | |
| 84 | #[cfg(not(debug_assertions))] | |
| 85 | use crate::next_solver::ErrorGuaranteed; | |
| 83 | 86 | use crate::{ |
| 84 | consteval::unknown_const, | |
| 85 | 87 | db::HirDatabase, |
| 86 | 88 | display::{DisplayTarget, HirDisplay}, |
| 87 | 89 | generics::Generics, |
| ... | ... | @@ -95,7 +97,6 @@ use crate::{ |
| 95 | 97 | pub use autoderef::autoderef; |
| 96 | 98 | pub use builder::{ParamKind, TyBuilder}; |
| 97 | 99 | pub use chalk_ext::*; |
| 98 | pub use drop::DropGlue; | |
| 99 | 100 | pub use infer::{ |
| 100 | 101 | Adjust, Adjustment, AutoBorrow, BindingMode, InferenceDiagnostic, InferenceResult, |
| 101 | 102 | InferenceTyDiagnosticSource, OverloadedDeref, PointerCast, |
| ... | ... | @@ -104,17 +105,17 @@ pub use infer::{ |
| 104 | 105 | could_coerce, could_unify, could_unify_deeply, |
| 105 | 106 | }; |
| 106 | 107 | pub use interner::Interner; |
| 107 | pub use lower::{ | |
| 108 | ImplTraitLoweringMode, LifetimeElisionKind, ParamLoweringMode, TyDefId, TyLoweringContext, | |
| 109 | ValueTyDefId, diagnostics::*, | |
| 108 | pub use lower::{ImplTraitLoweringMode, ParamLoweringMode, TyDefId, ValueTyDefId, diagnostics::*}; | |
| 109 | pub use lower_nextsolver::{ | |
| 110 | LifetimeElisionKind, TyLoweringContext, associated_type_shorthand_candidates, | |
| 110 | 111 | }; |
| 111 | pub use lower_nextsolver::associated_type_shorthand_candidates; | |
| 112 | 112 | pub use mapping::{ |
| 113 | 113 | ToChalk, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx, |
| 114 | 114 | lt_from_placeholder_idx, lt_to_placeholder_idx, to_assoc_type_id, to_chalk_trait_id, |
| 115 | 115 | to_foreign_def_id, to_placeholder_idx, to_placeholder_idx_no_index, |
| 116 | 116 | }; |
| 117 | 117 | pub use method_resolution::check_orphan_rules; |
| 118 | pub use next_solver::interner::{attach_db, attach_db_allow_change, with_attached_db}; | |
| 118 | 119 | pub use target_feature::TargetFeatures; |
| 119 | 120 | pub use traits::TraitEnvironment; |
| 120 | 121 | pub use utils::{ |
| ... | ... | @@ -123,20 +124,16 @@ pub use utils::{ |
| 123 | 124 | }; |
| 124 | 125 | pub use variance::Variance; |
| 125 | 126 | |
| 126 | pub use chalk_ir::{ | |
| 127 | AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind, | |
| 128 | cast::Cast, | |
| 129 | visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}, | |
| 130 | }; | |
| 127 | use chalk_ir::{AdtId, BoundVar, DebruijnIndex, Safety, Scalar}; | |
| 131 | 128 | |
| 132 | pub type ForeignDefId = chalk_ir::ForeignDefId<Interner>; | |
| 133 | pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>; | |
| 134 | pub type FnDefId = chalk_ir::FnDefId<Interner>; | |
| 135 | pub type ClosureId = chalk_ir::ClosureId<Interner>; | |
| 136 | pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; | |
| 137 | pub type PlaceholderIndex = chalk_ir::PlaceholderIndex; | |
| 129 | pub(crate) type ForeignDefId = chalk_ir::ForeignDefId<Interner>; | |
| 130 | pub(crate) type AssocTypeId = chalk_ir::AssocTypeId<Interner>; | |
| 131 | pub(crate) type FnDefId = chalk_ir::FnDefId<Interner>; | |
| 132 | pub(crate) type ClosureId = chalk_ir::ClosureId<Interner>; | |
| 133 | pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; | |
| 134 | pub(crate) type PlaceholderIndex = chalk_ir::PlaceholderIndex; | |
| 138 | 135 | |
| 139 | pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>; | |
| 136 | pub(crate) type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>; | |
| 140 | 137 | |
| 141 | 138 | pub(crate) type VariableKind = chalk_ir::VariableKind<Interner>; |
| 142 | 139 | /// Represents generic parameters and an item bound by them. When the item has parent, the binders |
| ... | ... | @@ -147,49 +144,48 @@ pub(crate) type VariableKind = chalk_ir::VariableKind<Interner>; |
| 147 | 144 | /// parameters/arguments for an item MUST come before those for its parent. This is to facilitate |
| 148 | 145 | /// the integration with chalk-solve, which mildly puts constraints as such. See #13335 for its |
| 149 | 146 | /// motivation in detail. |
| 150 | pub type Binders<T> = chalk_ir::Binders<T>; | |
| 147 | pub(crate) type Binders<T> = chalk_ir::Binders<T>; | |
| 151 | 148 | /// Interned list of generic arguments for an item. When an item has parent, the `Substitution` for |
| 152 | 149 | /// it contains generic arguments for both its parent and itself. See chalk's documentation for |
| 153 | 150 | /// details. |
| 154 | 151 | /// |
| 155 | 152 | /// See `Binders` for the constraint on the ordering. |
| 156 | pub type Substitution = chalk_ir::Substitution<Interner>; | |
| 157 | pub type GenericArg = chalk_ir::GenericArg<Interner>; | |
| 158 | pub type GenericArgData = chalk_ir::GenericArgData<Interner>; | |
| 153 | pub(crate) type Substitution = chalk_ir::Substitution<Interner>; | |
| 154 | pub(crate) type GenericArg = chalk_ir::GenericArg<Interner>; | |
| 155 | pub(crate) type GenericArgData = chalk_ir::GenericArgData<Interner>; | |
| 159 | 156 | |
| 160 | pub type Ty = chalk_ir::Ty<Interner>; | |
| 157 | pub(crate) type Ty = chalk_ir::Ty<Interner>; | |
| 161 | 158 | pub type TyKind = chalk_ir::TyKind<Interner>; |
| 162 | pub type TypeFlags = chalk_ir::TypeFlags; | |
| 159 | pub(crate) type TypeFlags = chalk_ir::TypeFlags; | |
| 163 | 160 | pub(crate) type DynTy = chalk_ir::DynTy<Interner>; |
| 164 | pub type FnPointer = chalk_ir::FnPointer<Interner>; | |
| 161 | pub(crate) type FnPointer = chalk_ir::FnPointer<Interner>; | |
| 165 | 162 | pub(crate) use chalk_ir::FnSubst; // a re-export so we don't lose the tuple constructor |
| 166 | 163 | |
| 167 | 164 | pub type AliasTy = chalk_ir::AliasTy<Interner>; |
| 168 | 165 | |
| 169 | pub type ProjectionTy = chalk_ir::ProjectionTy<Interner>; | |
| 166 | pub(crate) type ProjectionTy = chalk_ir::ProjectionTy<Interner>; | |
| 170 | 167 | pub(crate) type OpaqueTy = chalk_ir::OpaqueTy<Interner>; |
| 171 | pub(crate) type InferenceVar = chalk_ir::InferenceVar; | |
| 172 | 168 | |
| 173 | 169 | pub(crate) type Lifetime = chalk_ir::Lifetime<Interner>; |
| 174 | 170 | pub(crate) type LifetimeData = chalk_ir::LifetimeData<Interner>; |
| 175 | 171 | pub(crate) type LifetimeOutlives = chalk_ir::LifetimeOutlives<Interner>; |
| 176 | 172 | |
| 177 | pub type ConstValue = chalk_ir::ConstValue<Interner>; | |
| 173 | pub(crate) type ConstValue = chalk_ir::ConstValue<Interner>; | |
| 178 | 174 | |
| 179 | pub type Const = chalk_ir::Const<Interner>; | |
| 175 | pub(crate) type Const = chalk_ir::Const<Interner>; | |
| 180 | 176 | pub(crate) type ConstData = chalk_ir::ConstData<Interner>; |
| 181 | 177 | pub(crate) type ConcreteConst = chalk_ir::ConcreteConst<Interner>; |
| 182 | 178 | |
| 183 | pub type TraitRef = chalk_ir::TraitRef<Interner>; | |
| 184 | pub type QuantifiedWhereClause = Binders<WhereClause>; | |
| 185 | pub type Canonical<T> = chalk_ir::Canonical<T>; | |
| 179 | pub(crate) type TraitRef = chalk_ir::TraitRef<Interner>; | |
| 180 | pub(crate) type QuantifiedWhereClause = Binders<WhereClause>; | |
| 181 | pub(crate) type Canonical<T> = chalk_ir::Canonical<T>; | |
| 186 | 182 | |
| 187 | 183 | pub(crate) type ChalkTraitId = chalk_ir::TraitId<Interner>; |
| 188 | 184 | pub(crate) type QuantifiedWhereClauses = chalk_ir::QuantifiedWhereClauses<Interner>; |
| 189 | 185 | |
| 190 | 186 | pub(crate) type FnSig = chalk_ir::FnSig<Interner>; |
| 191 | 187 | |
| 192 | pub type InEnvironment<T> = chalk_ir::InEnvironment<T>; | |
| 188 | pub(crate) type InEnvironment<T> = chalk_ir::InEnvironment<T>; | |
| 193 | 189 | pub type AliasEq = chalk_ir::AliasEq<Interner>; |
| 194 | 190 | pub type WhereClause = chalk_ir::WhereClause<Interner>; |
| 195 | 191 | |
| ... | ... | @@ -233,7 +229,7 @@ impl ComplexMemoryMap<'_> { |
| 233 | 229 | } |
| 234 | 230 | |
| 235 | 231 | impl<'db> MemoryMap<'db> { |
| 236 | pub fn vtable_ty(&self, id: usize) -> Result<crate::next_solver::Ty<'db>, MirEvalError> { | |
| 232 | pub fn vtable_ty(&self, id: usize) -> Result<crate::next_solver::Ty<'db>, MirEvalError<'db>> { | |
| 237 | 233 | match self { |
| 238 | 234 | MemoryMap::Empty | MemoryMap::Simple(_) => Err(MirEvalError::InvalidVTableId(id)), |
| 239 | 235 | MemoryMap::Complex(cm) => cm.vtable.ty(id), |
| ... | ... | @@ -249,8 +245,8 @@ impl<'db> MemoryMap<'db> { |
| 249 | 245 | /// allocator function as `f` and it will return a mapping of old addresses to new addresses. |
| 250 | 246 | fn transform_addresses( |
| 251 | 247 | &self, |
| 252 | mut f: impl FnMut(&[u8], usize) -> Result<usize, MirEvalError>, | |
| 253 | ) -> Result<FxHashMap<usize, usize>, MirEvalError> { | |
| 248 | mut f: impl FnMut(&[u8], usize) -> Result<usize, MirEvalError<'db>>, | |
| 249 | ) -> Result<FxHashMap<usize, usize>, MirEvalError<'db>> { | |
| 254 | 250 | let mut transform = |(addr, val): (&usize, &[u8])| { |
| 255 | 251 | let addr = *addr; |
| 256 | 252 | let align = if addr == 0 { 64 } else { (addr - (addr & (addr - 1))).min(64) }; |
| ... | ... | @@ -646,7 +642,7 @@ impl TypeFoldable<Interner> for CallableSig { |
| 646 | 642 | |
| 647 | 643 | #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] |
| 648 | 644 | pub enum ImplTraitId { |
| 649 | ReturnTypeImplTrait(hir_def::FunctionId, ImplTraitIdx), | |
| 645 | ReturnTypeImplTrait(hir_def::FunctionId, ImplTraitIdx), // FIXME(next-solver): Should be crate::nextsolver::ImplTraitIdx. | |
| 650 | 646 | TypeAliasImplTrait(hir_def::TypeAliasId, ImplTraitIdx), |
| 651 | 647 | AsyncBlockTypeImplTrait(hir_def::DefWithBodyId, ExprId), |
| 652 | 648 | } |
| ... | ... | @@ -713,219 +709,170 @@ pub(crate) fn fold_free_vars<T: HasInterner<Interner = Interner> + TypeFoldable< |
| 713 | 709 | t.fold_with(&mut FreeVarFolder(for_ty, for_const), DebruijnIndex::INNERMOST) |
| 714 | 710 | } |
| 715 | 711 | |
| 716 | pub(crate) fn fold_tys<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>>( | |
| 717 | t: T, | |
| 718 | mut for_ty: impl FnMut(Ty, DebruijnIndex) -> Ty, | |
| 719 | binders: DebruijnIndex, | |
| 720 | ) -> T { | |
| 721 | fold_tys_and_consts( | |
| 722 | t, | |
| 723 | |x, d| match x { | |
| 724 | Either::Left(x) => Either::Left(for_ty(x, d)), | |
| 725 | Either::Right(x) => Either::Right(x), | |
| 726 | }, | |
| 727 | binders, | |
| 728 | ) | |
| 729 | } | |
| 730 | ||
| 731 | pub(crate) fn fold_tys_and_consts<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>>( | |
| 732 | t: T, | |
| 733 | f: impl FnMut(Either<Ty, Const>, DebruijnIndex) -> Either<Ty, Const>, | |
| 734 | binders: DebruijnIndex, | |
| 735 | ) -> T { | |
| 736 | use chalk_ir::fold::{TypeFolder, TypeSuperFoldable}; | |
| 737 | #[derive(chalk_derive::FallibleTypeFolder)] | |
| 738 | #[has_interner(Interner)] | |
| 739 | struct TyFolder<F: FnMut(Either<Ty, Const>, DebruijnIndex) -> Either<Ty, Const>>(F); | |
| 740 | impl<F: FnMut(Either<Ty, Const>, DebruijnIndex) -> Either<Ty, Const>> TypeFolder<Interner> | |
| 741 | for TyFolder<F> | |
| 742 | { | |
| 743 | fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner> { | |
| 744 | self | |
| 745 | } | |
| 746 | ||
| 747 | fn interner(&self) -> Interner { | |
| 748 | Interner | |
| 749 | } | |
| 750 | ||
| 751 | fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Ty { | |
| 752 | let ty = ty.super_fold_with(self.as_dyn(), outer_binder); | |
| 753 | self.0(Either::Left(ty), outer_binder).left().unwrap() | |
| 754 | } | |
| 755 | ||
| 756 | fn fold_const(&mut self, c: Const, outer_binder: DebruijnIndex) -> Const { | |
| 757 | self.0(Either::Right(c), outer_binder).right().unwrap() | |
| 758 | } | |
| 759 | } | |
| 760 | t.fold_with(&mut TyFolder(f), binders) | |
| 761 | } | |
| 762 | ||
| 763 | pub(crate) fn fold_generic_args<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>>( | |
| 764 | t: T, | |
| 765 | f: impl FnMut(GenericArgData, DebruijnIndex) -> GenericArgData, | |
| 766 | binders: DebruijnIndex, | |
| 767 | ) -> T { | |
| 768 | use chalk_ir::fold::{TypeFolder, TypeSuperFoldable}; | |
| 769 | #[derive(chalk_derive::FallibleTypeFolder)] | |
| 770 | #[has_interner(Interner)] | |
| 771 | struct TyFolder<F: FnMut(GenericArgData, DebruijnIndex) -> GenericArgData>(F); | |
| 772 | impl<F: FnMut(GenericArgData, DebruijnIndex) -> GenericArgData> TypeFolder<Interner> | |
| 773 | for TyFolder<F> | |
| 774 | { | |
| 775 | fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner> { | |
| 776 | self | |
| 777 | } | |
| 778 | ||
| 779 | fn interner(&self) -> Interner { | |
| 780 | Interner | |
| 781 | } | |
| 782 | ||
| 783 | fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Ty { | |
| 784 | let ty = ty.super_fold_with(self.as_dyn(), outer_binder); | |
| 785 | self.0(GenericArgData::Ty(ty), outer_binder) | |
| 786 | .intern(Interner) | |
| 787 | .ty(Interner) | |
| 788 | .unwrap() | |
| 789 | .clone() | |
| 790 | } | |
| 791 | ||
| 792 | fn fold_const(&mut self, c: Const, outer_binder: DebruijnIndex) -> Const { | |
| 793 | self.0(GenericArgData::Const(c), outer_binder) | |
| 794 | .intern(Interner) | |
| 795 | .constant(Interner) | |
| 796 | .unwrap() | |
| 797 | .clone() | |
| 798 | } | |
| 799 | ||
| 800 | fn fold_lifetime(&mut self, lt: Lifetime, outer_binder: DebruijnIndex) -> Lifetime { | |
| 801 | let lt = lt.super_fold_with(self.as_dyn(), outer_binder); | |
| 802 | self.0(GenericArgData::Lifetime(lt), outer_binder) | |
| 803 | .intern(Interner) | |
| 804 | .lifetime(Interner) | |
| 805 | .unwrap() | |
| 806 | .clone() | |
| 807 | } | |
| 808 | } | |
| 809 | t.fold_with(&mut TyFolder(f), binders) | |
| 810 | } | |
| 811 | ||
| 812 | 712 | /// 'Canonicalizes' the `t` by replacing any errors with new variables. Also |
| 813 | 713 | /// ensures there are no unbound variables or inference variables anywhere in |
| 814 | 714 | /// the `t`. |
| 815 | pub fn replace_errors_with_variables<T>(t: &T) -> Canonical<T> | |
| 715 | pub fn replace_errors_with_variables<'db, T>( | |
| 716 | interner: DbInterner<'db>, | |
| 717 | t: &T, | |
| 718 | ) -> crate::next_solver::Canonical<'db, T> | |
| 816 | 719 | where |
| 817 | T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + Clone, | |
| 720 | T: rustc_type_ir::TypeFoldable<DbInterner<'db>> + Clone, | |
| 818 | 721 | { |
| 819 | use chalk_ir::{ | |
| 820 | Fallible, | |
| 821 | fold::{FallibleTypeFolder, TypeSuperFoldable}, | |
| 822 | }; | |
| 823 | struct ErrorReplacer { | |
| 824 | vars: usize, | |
| 722 | use rustc_type_ir::{FallibleTypeFolder, TypeSuperFoldable}; | |
| 723 | struct ErrorReplacer<'db> { | |
| 724 | interner: DbInterner<'db>, | |
| 725 | vars: Vec<crate::next_solver::CanonicalVarKind<'db>>, | |
| 726 | binder: rustc_type_ir::DebruijnIndex, | |
| 825 | 727 | } |
| 826 | impl FallibleTypeFolder<Interner> for ErrorReplacer { | |
| 827 | type Error = NoSolution; | |
| 828 | ||
| 829 | fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder<Interner, Error = Self::Error> { | |
| 830 | self | |
| 831 | } | |
| 832 | ||
| 833 | fn interner(&self) -> Interner { | |
| 834 | Interner | |
| 835 | } | |
| 728 | impl<'db> FallibleTypeFolder<DbInterner<'db>> for ErrorReplacer<'db> { | |
| 729 | #[cfg(debug_assertions)] | |
| 730 | type Error = (); | |
| 731 | #[cfg(not(debug_assertions))] | |
| 732 | type Error = std::convert::Infallible; | |
| 836 | 733 | |
| 837 | fn try_fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Fallible<Ty> { | |
| 838 | if let TyKind::Error = ty.kind(Interner) { | |
| 839 | let index = self.vars; | |
| 840 | self.vars += 1; | |
| 841 | Ok(TyKind::BoundVar(BoundVar::new(outer_binder, index)).intern(Interner)) | |
| 842 | } else { | |
| 843 | ty.try_super_fold_with(self.as_dyn(), outer_binder) | |
| 844 | } | |
| 734 | fn cx(&self) -> DbInterner<'db> { | |
| 735 | self.interner | |
| 845 | 736 | } |
| 846 | 737 | |
| 847 | fn try_fold_inference_ty( | |
| 738 | fn try_fold_binder<T>( | |
| 848 | 739 | &mut self, |
| 849 | _var: InferenceVar, | |
| 850 | _kind: TyVariableKind, | |
| 851 | _outer_binder: DebruijnIndex, | |
| 852 | ) -> Fallible<Ty> { | |
| 853 | if cfg!(debug_assertions) { | |
| 854 | // we don't want to just panic here, because then the error message | |
| 855 | // won't contain the whole thing, which would not be very helpful | |
| 856 | Err(NoSolution) | |
| 857 | } else { | |
| 858 | Ok(TyKind::Error.intern(Interner)) | |
| 859 | } | |
| 860 | } | |
| 861 | ||
| 862 | fn try_fold_free_var_ty( | |
| 740 | t: crate::next_solver::Binder<'db, T>, | |
| 741 | ) -> Result<crate::next_solver::Binder<'db, T>, Self::Error> | |
| 742 | where | |
| 743 | T: rustc_type_ir::TypeFoldable<DbInterner<'db>>, | |
| 744 | { | |
| 745 | self.binder.shift_in(1); | |
| 746 | let result = t.try_super_fold_with(self); | |
| 747 | self.binder.shift_out(1); | |
| 748 | result | |
| 749 | } | |
| 750 | ||
| 751 | fn try_fold_ty( | |
| 863 | 752 | &mut self, |
| 864 | _bound_var: BoundVar, | |
| 865 | _outer_binder: DebruijnIndex, | |
| 866 | ) -> Fallible<Ty> { | |
| 867 | if cfg!(debug_assertions) { | |
| 868 | // we don't want to just panic here, because then the error message | |
| 869 | // won't contain the whole thing, which would not be very helpful | |
| 870 | Err(NoSolution) | |
| 871 | } else { | |
| 872 | Ok(TyKind::Error.intern(Interner)) | |
| 753 | t: crate::next_solver::Ty<'db>, | |
| 754 | ) -> Result<crate::next_solver::Ty<'db>, Self::Error> { | |
| 755 | if !t.has_type_flags( | |
| 756 | rustc_type_ir::TypeFlags::HAS_ERROR | |
| 757 | | rustc_type_ir::TypeFlags::HAS_TY_INFER | |
| 758 | | rustc_type_ir::TypeFlags::HAS_CT_INFER | |
| 759 | | rustc_type_ir::TypeFlags::HAS_RE_INFER, | |
| 760 | ) { | |
| 761 | return Ok(t); | |
| 873 | 762 | } |
| 874 | } | |
| 875 | 763 | |
| 876 | fn try_fold_inference_const( | |
| 877 | &mut self, | |
| 878 | ty: Ty, | |
| 879 | _var: InferenceVar, | |
| 880 | _outer_binder: DebruijnIndex, | |
| 881 | ) -> Fallible<Const> { | |
| 882 | if cfg!(debug_assertions) { Err(NoSolution) } else { Ok(unknown_const(ty)) } | |
| 764 | #[cfg(debug_assertions)] | |
| 765 | let error = || Err(()); | |
| 766 | #[cfg(not(debug_assertions))] | |
| 767 | let error = || Ok(crate::next_solver::Ty::new_error(self.interner, ErrorGuaranteed)); | |
| 768 | ||
| 769 | match t.kind() { | |
| 770 | crate::next_solver::TyKind::Error(_) => { | |
| 771 | let var = rustc_type_ir::BoundVar::from_usize(self.vars.len()); | |
| 772 | self.vars.push(crate::next_solver::CanonicalVarKind::Ty { | |
| 773 | ui: rustc_type_ir::UniverseIndex::ZERO, | |
| 774 | sub_root: var, | |
| 775 | }); | |
| 776 | Ok(crate::next_solver::Ty::new_bound( | |
| 777 | self.interner, | |
| 778 | self.binder, | |
| 779 | crate::next_solver::BoundTy { | |
| 780 | var, | |
| 781 | kind: crate::next_solver::BoundTyKind::Anon, | |
| 782 | }, | |
| 783 | )) | |
| 784 | } | |
| 785 | crate::next_solver::TyKind::Infer(_) => error(), | |
| 786 | crate::next_solver::TyKind::Bound(index, _) if index > self.binder => error(), | |
| 787 | _ => t.try_super_fold_with(self), | |
| 788 | } | |
| 883 | 789 | } |
| 884 | 790 | |
| 885 | fn try_fold_free_var_const( | |
| 791 | fn try_fold_const( | |
| 886 | 792 | &mut self, |
| 887 | ty: Ty, | |
| 888 | _bound_var: BoundVar, | |
| 889 | _outer_binder: DebruijnIndex, | |
| 890 | ) -> Fallible<Const> { | |
| 891 | if cfg!(debug_assertions) { Err(NoSolution) } else { Ok(unknown_const(ty)) } | |
| 892 | } | |
| 793 | ct: crate::next_solver::Const<'db>, | |
| 794 | ) -> Result<crate::next_solver::Const<'db>, Self::Error> { | |
| 795 | if !ct.has_type_flags( | |
| 796 | rustc_type_ir::TypeFlags::HAS_ERROR | |
| 797 | | rustc_type_ir::TypeFlags::HAS_TY_INFER | |
| 798 | | rustc_type_ir::TypeFlags::HAS_CT_INFER | |
| 799 | | rustc_type_ir::TypeFlags::HAS_RE_INFER, | |
| 800 | ) { | |
| 801 | return Ok(ct); | |
| 802 | } | |
| 893 | 803 | |
| 894 | fn try_fold_inference_lifetime( | |
| 895 | &mut self, | |
| 896 | _var: InferenceVar, | |
| 897 | _outer_binder: DebruijnIndex, | |
| 898 | ) -> Fallible<Lifetime> { | |
| 899 | if cfg!(debug_assertions) { Err(NoSolution) } else { Ok(error_lifetime()) } | |
| 804 | #[cfg(debug_assertions)] | |
| 805 | let error = || Err(()); | |
| 806 | #[cfg(not(debug_assertions))] | |
| 807 | let error = || Ok(crate::next_solver::Const::error(self.interner)); | |
| 808 | ||
| 809 | match ct.kind() { | |
| 810 | crate::next_solver::ConstKind::Error(_) => { | |
| 811 | let var = rustc_type_ir::BoundVar::from_usize(self.vars.len()); | |
| 812 | self.vars.push(crate::next_solver::CanonicalVarKind::Const( | |
| 813 | rustc_type_ir::UniverseIndex::ZERO, | |
| 814 | )); | |
| 815 | Ok(crate::next_solver::Const::new_bound( | |
| 816 | self.interner, | |
| 817 | self.binder, | |
| 818 | crate::next_solver::BoundConst { var }, | |
| 819 | )) | |
| 820 | } | |
| 821 | crate::next_solver::ConstKind::Infer(_) => error(), | |
| 822 | crate::next_solver::ConstKind::Bound(index, _) if index > self.binder => error(), | |
| 823 | _ => ct.try_super_fold_with(self), | |
| 824 | } | |
| 900 | 825 | } |
| 901 | 826 | |
| 902 | fn try_fold_free_var_lifetime( | |
| 827 | fn try_fold_region( | |
| 903 | 828 | &mut self, |
| 904 | _bound_var: BoundVar, | |
| 905 | _outer_binder: DebruijnIndex, | |
| 906 | ) -> Fallible<Lifetime> { | |
| 907 | if cfg!(debug_assertions) { Err(NoSolution) } else { Ok(error_lifetime()) } | |
| 829 | region: crate::next_solver::Region<'db>, | |
| 830 | ) -> Result<crate::next_solver::Region<'db>, Self::Error> { | |
| 831 | #[cfg(debug_assertions)] | |
| 832 | let error = || Err(()); | |
| 833 | #[cfg(not(debug_assertions))] | |
| 834 | let error = || Ok(crate::next_solver::Region::error(self.interner)); | |
| 835 | ||
| 836 | match region.kind() { | |
| 837 | crate::next_solver::RegionKind::ReError(_) => { | |
| 838 | let var = rustc_type_ir::BoundVar::from_usize(self.vars.len()); | |
| 839 | self.vars.push(crate::next_solver::CanonicalVarKind::Region( | |
| 840 | rustc_type_ir::UniverseIndex::ZERO, | |
| 841 | )); | |
| 842 | Ok(crate::next_solver::Region::new_bound( | |
| 843 | self.interner, | |
| 844 | self.binder, | |
| 845 | crate::next_solver::BoundRegion { | |
| 846 | var, | |
| 847 | kind: crate::next_solver::BoundRegionKind::Anon, | |
| 848 | }, | |
| 849 | )) | |
| 850 | } | |
| 851 | crate::next_solver::RegionKind::ReVar(_) => error(), | |
| 852 | crate::next_solver::RegionKind::ReBound(index, _) if index > self.binder => error(), | |
| 853 | _ => Ok(region), | |
| 854 | } | |
| 908 | 855 | } |
| 909 | 856 | } |
| 910 | let mut error_replacer = ErrorReplacer { vars: 0 }; | |
| 911 | let value = match t.clone().try_fold_with(&mut error_replacer, DebruijnIndex::INNERMOST) { | |
| 857 | ||
| 858 | let mut error_replacer = | |
| 859 | ErrorReplacer { vars: Vec::new(), binder: rustc_type_ir::DebruijnIndex::ZERO, interner }; | |
| 860 | let value = match t.clone().try_fold_with(&mut error_replacer) { | |
| 912 | 861 | Ok(t) => t, |
| 913 | 862 | Err(_) => panic!("Encountered unbound or inference vars in {t:?}"), |
| 914 | 863 | }; |
| 915 | let kinds = (0..error_replacer.vars).map(|_| { | |
| 916 | chalk_ir::CanonicalVarKind::new( | |
| 917 | chalk_ir::VariableKind::Ty(TyVariableKind::General), | |
| 918 | chalk_ir::UniverseIndex::ROOT, | |
| 919 | ) | |
| 920 | }); | |
| 921 | Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(Interner, kinds) } | |
| 864 | crate::next_solver::Canonical { | |
| 865 | value, | |
| 866 | max_universe: rustc_type_ir::UniverseIndex::ZERO, | |
| 867 | variables: crate::next_solver::CanonicalVars::new_from_iter(interner, error_replacer.vars), | |
| 868 | } | |
| 922 | 869 | } |
| 923 | 870 | |
| 924 | 871 | pub fn callable_sig_from_fn_trait<'db>( |
| 925 | self_ty: &Ty, | |
| 872 | self_ty: crate::next_solver::Ty<'db>, | |
| 926 | 873 | trait_env: Arc<TraitEnvironment<'db>>, |
| 927 | 874 | db: &'db dyn HirDatabase, |
| 928 | ) -> Option<(FnTrait, CallableSig)> { | |
| 875 | ) -> Option<(FnTrait, crate::next_solver::PolyFnSig<'db>)> { | |
| 929 | 876 | let krate = trait_env.krate; |
| 930 | 877 | let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?; |
| 931 | 878 | let output_assoc_type = fn_once_trait |
| ... | ... | @@ -942,46 +889,47 @@ pub fn callable_sig_from_fn_trait<'db>( |
| 942 | 889 | // - Self: FnOnce<?args_ty> |
| 943 | 890 | // - <Self as FnOnce<?args_ty>>::Output == ?ret_ty |
| 944 | 891 | let args_ty = table.next_ty_var(); |
| 945 | let args = [self_ty.to_nextsolver(table.interner), args_ty]; | |
| 946 | let trait_ref = crate::next_solver::TraitRef::new(table.interner, fn_once_trait.into(), args); | |
| 892 | let args = [self_ty, args_ty]; | |
| 893 | let trait_ref = crate::next_solver::TraitRef::new(table.interner(), fn_once_trait.into(), args); | |
| 947 | 894 | let projection = crate::next_solver::Ty::new_alias( |
| 948 | table.interner, | |
| 895 | table.interner(), | |
| 949 | 896 | rustc_type_ir::AliasTyKind::Projection, |
| 950 | crate::next_solver::AliasTy::new(table.interner, output_assoc_type.into(), args), | |
| 897 | crate::next_solver::AliasTy::new(table.interner(), output_assoc_type.into(), args), | |
| 951 | 898 | ); |
| 952 | 899 | |
| 953 | let pred = crate::next_solver::Predicate::upcast_from(trait_ref, table.interner); | |
| 900 | let pred = crate::next_solver::Predicate::upcast_from(trait_ref, table.interner()); | |
| 954 | 901 | if !table.try_obligation(pred).no_solution() { |
| 955 | 902 | table.register_obligation(pred); |
| 956 | 903 | let return_ty = table.normalize_alias_ty(projection); |
| 957 | 904 | for fn_x in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] { |
| 958 | 905 | let fn_x_trait = fn_x.get_id(db, krate)?; |
| 959 | 906 | let trait_ref = |
| 960 | crate::next_solver::TraitRef::new(table.interner, fn_x_trait.into(), args); | |
| 907 | crate::next_solver::TraitRef::new(table.interner(), fn_x_trait.into(), args); | |
| 961 | 908 | if !table |
| 962 | 909 | .try_obligation(crate::next_solver::Predicate::upcast_from( |
| 963 | 910 | trait_ref, |
| 964 | table.interner, | |
| 911 | table.interner(), | |
| 965 | 912 | )) |
| 966 | 913 | .no_solution() |
| 967 | 914 | { |
| 968 | let ret_ty = table.resolve_completely(return_ty.to_chalk(table.interner)); | |
| 969 | let args_ty = table.resolve_completely(args_ty.to_chalk(table.interner)); | |
| 970 | let params = args_ty | |
| 971 | .as_tuple()? | |
| 972 | .iter(Interner) | |
| 973 | .map(|it| it.assert_ty_ref(Interner)) | |
| 974 | .cloned(); | |
| 915 | let ret_ty = table.resolve_completely(return_ty); | |
| 916 | let args_ty = table.resolve_completely(args_ty); | |
| 917 | let crate::next_solver::TyKind::Tuple(params) = args_ty.kind() else { | |
| 918 | return None; | |
| 919 | }; | |
| 920 | let inputs_and_output = crate::next_solver::Tys::new_from_iter( | |
| 921 | table.interner(), | |
| 922 | params.iter().chain(std::iter::once(ret_ty)), | |
| 923 | ); | |
| 975 | 924 | |
| 976 | 925 | return Some(( |
| 977 | 926 | fn_x, |
| 978 | CallableSig::from_params_and_return( | |
| 979 | params, | |
| 980 | ret_ty, | |
| 981 | false, | |
| 982 | Safety::Safe, | |
| 983 | FnAbi::RustCall, | |
| 984 | ), | |
| 927 | crate::next_solver::Binder::dummy(crate::next_solver::FnSig { | |
| 928 | inputs_and_output, | |
| 929 | c_variadic: false, | |
| 930 | safety: crate::next_solver::abi::Safety::Safe, | |
| 931 | abi: FnAbi::RustCall, | |
| 932 | }), | |
| 985 | 933 | )); |
| 986 | 934 | } |
| 987 | 935 | } |
| ... | ... | @@ -991,74 +939,43 @@ pub fn callable_sig_from_fn_trait<'db>( |
| 991 | 939 | } |
| 992 | 940 | } |
| 993 | 941 | |
| 994 | struct PlaceholderCollector<'db> { | |
| 995 | db: &'db dyn HirDatabase, | |
| 996 | placeholders: FxHashSet<TypeOrConstParamId>, | |
| 997 | } | |
| 998 | ||
| 999 | impl PlaceholderCollector<'_> { | |
| 1000 | fn collect(&mut self, idx: PlaceholderIndex) { | |
| 1001 | let id = from_placeholder_idx(self.db, idx).0; | |
| 1002 | self.placeholders.insert(id); | |
| 1003 | } | |
| 942 | struct ParamCollector { | |
| 943 | params: FxHashSet<TypeOrConstParamId>, | |
| 1004 | 944 | } |
| 1005 | 945 | |
| 1006 | impl TypeVisitor<Interner> for PlaceholderCollector<'_> { | |
| 1007 | type BreakTy = (); | |
| 1008 | ||
| 1009 | fn as_dyn(&mut self) -> &mut dyn TypeVisitor<Interner, BreakTy = Self::BreakTy> { | |
| 1010 | self | |
| 1011 | } | |
| 1012 | ||
| 1013 | fn interner(&self) -> Interner { | |
| 1014 | Interner | |
| 1015 | } | |
| 946 | impl<'db> rustc_type_ir::TypeVisitor<DbInterner<'db>> for ParamCollector { | |
| 947 | type Result = (); | |
| 1016 | 948 | |
| 1017 | fn visit_ty( | |
| 1018 | &mut self, | |
| 1019 | ty: &Ty, | |
| 1020 | outer_binder: DebruijnIndex, | |
| 1021 | ) -> std::ops::ControlFlow<Self::BreakTy> { | |
| 1022 | let has_placeholder_bits = TypeFlags::HAS_TY_PLACEHOLDER | TypeFlags::HAS_CT_PLACEHOLDER; | |
| 1023 | let chalk_ir::TyData { kind, flags } = ty.data(Interner); | |
| 1024 | ||
| 1025 | if let TyKind::Placeholder(idx) = kind { | |
| 1026 | self.collect(*idx); | |
| 1027 | } else if flags.intersects(has_placeholder_bits) { | |
| 1028 | return ty.super_visit_with(self, outer_binder); | |
| 1029 | } else { | |
| 1030 | // Fast path: don't visit inner types (e.g. generic arguments) when `flags` indicate | |
| 1031 | // that there are no placeholders. | |
| 949 | fn visit_ty(&mut self, ty: crate::next_solver::Ty<'db>) -> Self::Result { | |
| 950 | if let crate::next_solver::TyKind::Param(param) = ty.kind() { | |
| 951 | self.params.insert(param.id.into()); | |
| 1032 | 952 | } |
| 1033 | 953 | |
| 1034 | std::ops::ControlFlow::Continue(()) | |
| 954 | ty.super_visit_with(self); | |
| 1035 | 955 | } |
| 1036 | 956 | |
| 1037 | fn visit_const( | |
| 1038 | &mut self, | |
| 1039 | constant: &chalk_ir::Const<Interner>, | |
| 1040 | _outer_binder: DebruijnIndex, | |
| 1041 | ) -> std::ops::ControlFlow<Self::BreakTy> { | |
| 1042 | if let chalk_ir::ConstValue::Placeholder(idx) = constant.data(Interner).value { | |
| 1043 | self.collect(idx); | |
| 957 | fn visit_const(&mut self, konst: crate::next_solver::Const<'db>) -> Self::Result { | |
| 958 | if let crate::next_solver::ConstKind::Param(param) = konst.kind() { | |
| 959 | self.params.insert(param.id.into()); | |
| 1044 | 960 | } |
| 1045 | std::ops::ControlFlow::Continue(()) | |
| 961 | ||
| 962 | konst.super_visit_with(self); | |
| 1046 | 963 | } |
| 1047 | 964 | } |
| 1048 | 965 | |
| 1049 | /// Returns unique placeholders for types and consts contained in `value`. | |
| 1050 | pub fn collect_placeholders<T>(value: &T, db: &dyn HirDatabase) -> Vec<TypeOrConstParamId> | |
| 966 | /// Returns unique params for types and consts contained in `value`. | |
| 967 | pub fn collect_params<'db, T>(value: &T) -> Vec<TypeOrConstParamId> | |
| 1051 | 968 | where |
| 1052 | T: ?Sized + TypeVisitable<Interner>, | |
| 969 | T: ?Sized + rustc_type_ir::TypeVisitable<DbInterner<'db>>, | |
| 1053 | 970 | { |
| 1054 | let mut collector = PlaceholderCollector { db, placeholders: FxHashSet::default() }; | |
| 1055 | _ = value.visit_with(&mut collector, DebruijnIndex::INNERMOST); | |
| 1056 | collector.placeholders.into_iter().collect() | |
| 971 | let mut collector = ParamCollector { params: FxHashSet::default() }; | |
| 972 | value.visit_with(&mut collector); | |
| 973 | Vec::from_iter(collector.params) | |
| 1057 | 974 | } |
| 1058 | 975 | |
| 1059 | pub fn known_const_to_ast( | |
| 1060 | konst: &Const, | |
| 1061 | db: &dyn HirDatabase, | |
| 976 | pub fn known_const_to_ast<'db>( | |
| 977 | konst: crate::next_solver::Const<'db>, | |
| 978 | db: &'db dyn HirDatabase, | |
| 1062 | 979 | display_target: DisplayTarget, |
| 1063 | 980 | ) -> Option<ConstArg> { |
| 1064 | 981 | Some(make::expr_const_value(konst.display(db, display_target).to_string().as_str())) |
src/tools/rust-analyzer/crates/hir-ty/src/lower.rs+23-61| ... | ... | @@ -25,14 +25,14 @@ use chalk_ir::{ |
| 25 | 25 | use either::Either; |
| 26 | 26 | use hir_def::{ |
| 27 | 27 | AdtId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, |
| 28 | GenericParamId, ItemContainerId, LocalFieldId, Lookup, StaticId, StructId, TypeAliasId, | |
| 29 | TypeOrConstParamId, UnionId, VariantId, | |
| 28 | GenericParamId, LocalFieldId, Lookup, StaticId, StructId, TypeAliasId, TypeOrConstParamId, | |
| 29 | UnionId, VariantId, | |
| 30 | 30 | builtin_type::BuiltinType, |
| 31 | 31 | expr_store::{ExpressionStore, path::Path}, |
| 32 | 32 | hir::generics::{GenericParamDataRef, TypeOrConstParamData, WherePredicate}, |
| 33 | 33 | lang_item::LangItem, |
| 34 | 34 | resolver::{HasResolver, LifetimeNs, Resolver, TypeNs}, |
| 35 | signatures::{FunctionSignature, TraitFlags}, | |
| 35 | signatures::TraitFlags, | |
| 36 | 36 | type_ref::{ |
| 37 | 37 | ConstRef, LifetimeRefId, LiteralConstRef, PathId, TraitBoundModifier, TypeBound, TypeRef, |
| 38 | 38 | TypeRefId, |
| ... | ... | @@ -49,7 +49,7 @@ use crate::{ |
| 49 | 49 | ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime, LifetimeData, LifetimeOutlives, |
| 50 | 50 | QuantifiedWhereClause, QuantifiedWhereClauses, Substitution, TraitRef, TraitRefExt, Ty, |
| 51 | 51 | TyBuilder, TyKind, WhereClause, all_super_traits, |
| 52 | consteval::{intern_const_ref, path_to_const, unknown_const, unknown_const_as_generic}, | |
| 52 | consteval_chalk::{intern_const_ref, path_to_const, unknown_const, unknown_const_as_generic}, | |
| 53 | 53 | db::HirDatabase, |
| 54 | 54 | error_lifetime, |
| 55 | 55 | generics::{Generics, generics, trait_self_param_idx}, |
| ... | ... | @@ -86,7 +86,7 @@ impl ImplTraitLoweringState { |
| 86 | 86 | pub(crate) struct PathDiagnosticCallbackData(pub(crate) TypeRefId); |
| 87 | 87 | |
| 88 | 88 | #[derive(Debug, Clone)] |
| 89 | pub enum LifetimeElisionKind { | |
| 89 | pub(crate) enum LifetimeElisionKind { | |
| 90 | 90 | /// Create a new anonymous lifetime parameter and reference it. |
| 91 | 91 | /// |
| 92 | 92 | /// If `report_in_path`, report an error when encountering lifetime elision in a path: |
| ... | ... | @@ -111,39 +111,11 @@ pub enum LifetimeElisionKind { |
| 111 | 111 | /// error on default object bounds (e.g., `Box<dyn Foo>`). |
| 112 | 112 | AnonymousReportError, |
| 113 | 113 | |
| 114 | /// Resolves elided lifetimes to `'static` if there are no other lifetimes in scope, | |
| 115 | /// otherwise give a warning that the previous behavior of introducing a new early-bound | |
| 116 | /// lifetime is a bug and will be removed (if `only_lint` is enabled). | |
| 117 | StaticIfNoLifetimeInScope { only_lint: bool }, | |
| 118 | ||
| 119 | /// Signal we cannot find which should be the anonymous lifetime. | |
| 120 | ElisionFailure, | |
| 121 | ||
| 122 | 114 | /// Infer all elided lifetimes. |
| 123 | 115 | Infer, |
| 124 | 116 | } |
| 125 | 117 | |
| 126 | 118 | impl LifetimeElisionKind { |
| 127 | #[inline] | |
| 128 | pub(crate) fn for_const(const_parent: ItemContainerId) -> LifetimeElisionKind { | |
| 129 | match const_parent { | |
| 130 | ItemContainerId::ExternBlockId(_) | ItemContainerId::ModuleId(_) => { | |
| 131 | LifetimeElisionKind::Elided(static_lifetime()) | |
| 132 | } | |
| 133 | ItemContainerId::ImplId(_) => { | |
| 134 | LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: true } | |
| 135 | } | |
| 136 | ItemContainerId::TraitId(_) => { | |
| 137 | LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: false } | |
| 138 | } | |
| 139 | } | |
| 140 | } | |
| 141 | ||
| 142 | #[inline] | |
| 143 | pub(crate) fn for_fn_params(data: &FunctionSignature) -> LifetimeElisionKind { | |
| 144 | LifetimeElisionKind::AnonymousCreateParameter { report_in_path: data.is_async() } | |
| 145 | } | |
| 146 | ||
| 147 | 119 | #[inline] |
| 148 | 120 | pub(crate) fn for_fn_ret() -> LifetimeElisionKind { |
| 149 | 121 | // FIXME: We should use the elided lifetime here, or `ElisionFailure`. |
| ... | ... | @@ -152,7 +124,7 @@ impl LifetimeElisionKind { |
| 152 | 124 | } |
| 153 | 125 | |
| 154 | 126 | #[derive(Debug)] |
| 155 | pub struct TyLoweringContext<'db> { | |
| 127 | pub(crate) struct TyLoweringContext<'db> { | |
| 156 | 128 | pub db: &'db dyn HirDatabase, |
| 157 | 129 | resolver: &'db Resolver<'db>, |
| 158 | 130 | store: &'db ExpressionStore, |
| ... | ... | @@ -172,7 +144,7 @@ pub struct TyLoweringContext<'db> { |
| 172 | 144 | } |
| 173 | 145 | |
| 174 | 146 | impl<'db> TyLoweringContext<'db> { |
| 175 | pub fn new( | |
| 147 | pub(crate) fn new( | |
| 176 | 148 | db: &'db dyn HirDatabase, |
| 177 | 149 | resolver: &'db Resolver<'db>, |
| 178 | 150 | store: &'db ExpressionStore, |
| ... | ... | @@ -197,7 +169,7 @@ impl<'db> TyLoweringContext<'db> { |
| 197 | 169 | } |
| 198 | 170 | } |
| 199 | 171 | |
| 200 | pub fn with_debruijn<T>( | |
| 172 | pub(crate) fn with_debruijn<T>( | |
| 201 | 173 | &mut self, |
| 202 | 174 | debruijn: DebruijnIndex, |
| 203 | 175 | f: impl FnOnce(&mut TyLoweringContext<'_>) -> T, |
| ... | ... | @@ -208,7 +180,7 @@ impl<'db> TyLoweringContext<'db> { |
| 208 | 180 | result |
| 209 | 181 | } |
| 210 | 182 | |
| 211 | pub fn with_shifted_in<T>( | |
| 183 | pub(crate) fn with_shifted_in<T>( | |
| 212 | 184 | &mut self, |
| 213 | 185 | debruijn: DebruijnIndex, |
| 214 | 186 | f: impl FnOnce(&mut TyLoweringContext<'_>) -> T, |
| ... | ... | @@ -227,25 +199,15 @@ impl<'db> TyLoweringContext<'db> { |
| 227 | 199 | result |
| 228 | 200 | } |
| 229 | 201 | |
| 230 | pub fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self { | |
| 202 | pub(crate) fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self { | |
| 231 | 203 | Self { impl_trait_mode: ImplTraitLoweringState::new(impl_trait_mode), ..self } |
| 232 | 204 | } |
| 233 | 205 | |
| 234 | pub fn with_type_param_mode(self, type_param_mode: ParamLoweringMode) -> Self { | |
| 206 | pub(crate) fn with_type_param_mode(self, type_param_mode: ParamLoweringMode) -> Self { | |
| 235 | 207 | Self { type_param_mode, ..self } |
| 236 | 208 | } |
| 237 | 209 | |
| 238 | pub fn impl_trait_mode(&mut self, impl_trait_mode: ImplTraitLoweringMode) -> &mut Self { | |
| 239 | self.impl_trait_mode = ImplTraitLoweringState::new(impl_trait_mode); | |
| 240 | self | |
| 241 | } | |
| 242 | ||
| 243 | pub fn type_param_mode(&mut self, type_param_mode: ParamLoweringMode) -> &mut Self { | |
| 244 | self.type_param_mode = type_param_mode; | |
| 245 | self | |
| 246 | } | |
| 247 | ||
| 248 | pub fn push_diagnostic(&mut self, type_ref: TypeRefId, kind: TyLoweringDiagnosticKind) { | |
| 210 | pub(crate) fn push_diagnostic(&mut self, type_ref: TypeRefId, kind: TyLoweringDiagnosticKind) { | |
| 249 | 211 | self.diagnostics.push(TyLoweringDiagnostic { source: type_ref, kind }); |
| 250 | 212 | } |
| 251 | 213 | } |
| ... | ... | @@ -268,12 +230,12 @@ pub enum ParamLoweringMode { |
| 268 | 230 | Variable, |
| 269 | 231 | } |
| 270 | 232 | |
| 271 | impl<'a> TyLoweringContext<'a> { | |
| 272 | pub fn lower_ty(&mut self, type_ref: TypeRefId) -> Ty { | |
| 233 | impl<'db> TyLoweringContext<'db> { | |
| 234 | pub(crate) fn lower_ty(&mut self, type_ref: TypeRefId) -> Ty { | |
| 273 | 235 | self.lower_ty_ext(type_ref).0 |
| 274 | 236 | } |
| 275 | 237 | |
| 276 | pub fn lower_const(&mut self, const_ref: &ConstRef, const_type: Ty) -> Const { | |
| 238 | pub(crate) fn lower_const(&mut self, const_ref: &ConstRef, const_type: Ty) -> Const { | |
| 277 | 239 | let const_ref = &self.store[const_ref.expr]; |
| 278 | 240 | match const_ref { |
| 279 | 241 | hir_def::hir::Expr::Path(path) => path_to_const( |
| ... | ... | @@ -328,7 +290,7 @@ impl<'a> TyLoweringContext<'a> { |
| 328 | 290 | } |
| 329 | 291 | } |
| 330 | 292 | |
| 331 | pub fn lower_path_as_const(&mut self, path: &Path, const_type: Ty) -> Const { | |
| 293 | pub(crate) fn lower_path_as_const(&mut self, path: &Path, const_type: Ty) -> Const { | |
| 332 | 294 | path_to_const( |
| 333 | 295 | self.db, |
| 334 | 296 | self.resolver, |
| ... | ... | @@ -345,7 +307,7 @@ impl<'a> TyLoweringContext<'a> { |
| 345 | 307 | self.generics.get_or_init(|| generics(self.db, self.def)) |
| 346 | 308 | } |
| 347 | 309 | |
| 348 | pub fn lower_ty_ext(&mut self, type_ref_id: TypeRefId) -> (Ty, Option<TypeNs>) { | |
| 310 | pub(crate) fn lower_ty_ext(&mut self, type_ref_id: TypeRefId) -> (Ty, Option<TypeNs>) { | |
| 349 | 311 | let mut res = None; |
| 350 | 312 | let type_ref = &self.store[type_ref_id]; |
| 351 | 313 | let ty = match type_ref { |
| ... | ... | @@ -512,7 +474,7 @@ impl<'a> TyLoweringContext<'a> { |
| 512 | 474 | } |
| 513 | 475 | |
| 514 | 476 | #[inline] |
| 515 | fn on_path_diagnostic_callback(type_ref: TypeRefId) -> PathDiagnosticCallback<'static> { | |
| 477 | fn on_path_diagnostic_callback<'a>(type_ref: TypeRefId) -> PathDiagnosticCallback<'a, 'db> { | |
| 516 | 478 | PathDiagnosticCallback { |
| 517 | 479 | data: Either::Left(PathDiagnosticCallbackData(type_ref)), |
| 518 | 480 | callback: |data, this, diag| { |
| ... | ... | @@ -523,7 +485,7 @@ impl<'a> TyLoweringContext<'a> { |
| 523 | 485 | } |
| 524 | 486 | |
| 525 | 487 | #[inline] |
| 526 | fn at_path(&mut self, path_id: PathId) -> PathLoweringContext<'_, 'a> { | |
| 488 | fn at_path(&mut self, path_id: PathId) -> PathLoweringContext<'_, 'db> { | |
| 527 | 489 | PathLoweringContext::new( |
| 528 | 490 | self, |
| 529 | 491 | Self::on_path_diagnostic_callback(path_id.type_ref()), |
| ... | ... | @@ -559,7 +521,7 @@ impl<'a> TyLoweringContext<'a> { |
| 559 | 521 | &mut self, |
| 560 | 522 | path_id: PathId, |
| 561 | 523 | explicit_self_ty: Ty, |
| 562 | ) -> Option<(TraitRef, PathLoweringContext<'_, 'a>)> { | |
| 524 | ) -> Option<(TraitRef, PathLoweringContext<'_, 'db>)> { | |
| 563 | 525 | let mut ctx = self.at_path(path_id); |
| 564 | 526 | let resolved = match ctx.resolve_path_in_type_ns_fully()? { |
| 565 | 527 | // FIXME(trait_alias): We need to handle trait alias here. |
| ... | ... | @@ -576,7 +538,7 @@ impl<'a> TyLoweringContext<'a> { |
| 576 | 538 | &'b mut self, |
| 577 | 539 | where_predicate: &'b WherePredicate, |
| 578 | 540 | ignore_bindings: bool, |
| 579 | ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'a, 'b> { | |
| 541 | ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'db, 'b> { | |
| 580 | 542 | match where_predicate { |
| 581 | 543 | WherePredicate::ForLifetime { target, bound, .. } |
| 582 | 544 | | WherePredicate::TypeBound { target, bound } => { |
| ... | ... | @@ -598,7 +560,7 @@ impl<'a> TyLoweringContext<'a> { |
| 598 | 560 | bound: &'b TypeBound, |
| 599 | 561 | self_ty: Ty, |
| 600 | 562 | ignore_bindings: bool, |
| 601 | ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'b, 'a> { | |
| 563 | ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'b, 'db> { | |
| 602 | 564 | let mut assoc_bounds = None; |
| 603 | 565 | let mut clause = None; |
| 604 | 566 | match bound { |
| ... | ... | @@ -794,7 +756,7 @@ impl<'a> TyLoweringContext<'a> { |
| 794 | 756 | ImplTrait { bounds: crate::make_single_type_binders(predicates) } |
| 795 | 757 | } |
| 796 | 758 | |
| 797 | pub fn lower_lifetime(&self, lifetime: LifetimeRefId) -> Lifetime { | |
| 759 | pub(crate) fn lower_lifetime(&self, lifetime: LifetimeRefId) -> Lifetime { | |
| 798 | 760 | match self.resolver.resolve_lifetime(&self.store[lifetime]) { |
| 799 | 761 | Some(resolution) => match resolution { |
| 800 | 762 | LifetimeNs::Static => static_lifetime(), |
src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs+16-204| ... | ... | @@ -3,15 +3,15 @@ |
| 3 | 3 | use chalk_ir::{BoundVar, cast::Cast, fold::Shift}; |
| 4 | 4 | use either::Either; |
| 5 | 5 | use hir_def::{ |
| 6 | GenericDefId, GenericParamId, Lookup, TraitId, | |
| 6 | GenericDefId, GenericParamId, TraitId, | |
| 7 | 7 | expr_store::{ |
| 8 | ExpressionStore, HygieneId, | |
| 8 | ExpressionStore, | |
| 9 | 9 | path::{GenericArg, GenericArgs, GenericArgsParentheses, Path, PathSegment, PathSegments}, |
| 10 | 10 | }, |
| 11 | 11 | hir::generics::{ |
| 12 | 12 | GenericParamDataRef, TypeOrConstParamData, TypeParamData, TypeParamProvenance, |
| 13 | 13 | }, |
| 14 | resolver::{ResolveValueResult, TypeNs, ValueNs}, | |
| 14 | resolver::TypeNs, | |
| 15 | 15 | signatures::TraitFlags, |
| 16 | 16 | type_ref::{TypeRef, TypeRefId}, |
| 17 | 17 | }; |
| ... | ... | @@ -21,36 +21,36 @@ use stdx::never; |
| 21 | 21 | use crate::{ |
| 22 | 22 | AliasEq, AliasTy, GenericArgsProhibitedReason, ImplTraitLoweringMode, IncorrectGenericsLenKind, |
| 23 | 23 | Interner, ParamLoweringMode, PathGenericsSource, PathLoweringDiagnostic, ProjectionTy, |
| 24 | QuantifiedWhereClause, Substitution, TraitRef, Ty, TyBuilder, TyDefId, TyKind, | |
| 25 | TyLoweringContext, ValueTyDefId, WhereClause, | |
| 26 | consteval::{unknown_const, unknown_const_as_generic}, | |
| 24 | QuantifiedWhereClause, Substitution, TraitRef, Ty, TyBuilder, TyDefId, TyKind, WhereClause, | |
| 25 | consteval_chalk::{unknown_const, unknown_const_as_generic}, | |
| 27 | 26 | db::HirDatabase, |
| 28 | 27 | error_lifetime, |
| 29 | 28 | generics::{Generics, generics}, |
| 30 | lower::{LifetimeElisionKind, named_associated_type_shorthand_candidates}, | |
| 29 | lower::{LifetimeElisionKind, TyLoweringContext, named_associated_type_shorthand_candidates}, | |
| 31 | 30 | next_solver::{ |
| 32 | 31 | DbInterner, |
| 33 | 32 | mapping::{ChalkToNextSolver, NextSolverToChalk}, |
| 34 | 33 | }, |
| 35 | static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, | |
| 34 | to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, | |
| 36 | 35 | utils::associated_type_by_name_including_super_traits, |
| 37 | 36 | }; |
| 38 | 37 | |
| 39 | type CallbackData<'a> = Either< | |
| 38 | type CallbackData<'a, 'db> = Either< | |
| 40 | 39 | super::PathDiagnosticCallbackData, |
| 41 | crate::infer::diagnostics::PathDiagnosticCallbackData<'a>, | |
| 40 | crate::infer::diagnostics::PathDiagnosticCallbackData<'a, 'db>, | |
| 42 | 41 | >; |
| 43 | 42 | |
| 44 | 43 | // We cannot use `&mut dyn FnMut()` because of lifetime issues, and we don't want to use `Box<dyn FnMut()>` |
| 45 | 44 | // because of the allocation, so we create a lifetime-less callback, tailored for our needs. |
| 46 | pub(crate) struct PathDiagnosticCallback<'a> { | |
| 47 | pub(crate) data: CallbackData<'a>, | |
| 48 | pub(crate) callback: fn(&CallbackData<'_>, &mut TyLoweringContext<'_>, PathLoweringDiagnostic), | |
| 45 | pub(crate) struct PathDiagnosticCallback<'a, 'db> { | |
| 46 | pub(crate) data: CallbackData<'a, 'db>, | |
| 47 | pub(crate) callback: | |
| 48 | fn(&CallbackData<'_, 'db>, &mut TyLoweringContext<'_>, PathLoweringDiagnostic), | |
| 49 | 49 | } |
| 50 | 50 | |
| 51 | 51 | pub(crate) struct PathLoweringContext<'a, 'b> { |
| 52 | 52 | ctx: &'a mut TyLoweringContext<'b>, |
| 53 | on_diagnostic: PathDiagnosticCallback<'a>, | |
| 53 | on_diagnostic: PathDiagnosticCallback<'a, 'b>, | |
| 54 | 54 | path: &'a Path, |
| 55 | 55 | segments: PathSegments<'a>, |
| 56 | 56 | current_segment_idx: usize, |
| ... | ... | @@ -62,7 +62,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { |
| 62 | 62 | #[inline] |
| 63 | 63 | pub(crate) fn new( |
| 64 | 64 | ctx: &'a mut TyLoweringContext<'b>, |
| 65 | on_diagnostic: PathDiagnosticCallback<'a>, | |
| 65 | on_diagnostic: PathDiagnosticCallback<'a, 'b>, | |
| 66 | 66 | path: &'a Path, |
| 67 | 67 | ) -> Self { |
| 68 | 68 | let segments = path.segments(); |
| ... | ... | @@ -109,20 +109,6 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { |
| 109 | 109 | self.segments.get(self.current_segment_idx).unwrap_or(self.current_or_prev_segment); |
| 110 | 110 | } |
| 111 | 111 | |
| 112 | #[inline] | |
| 113 | pub(crate) fn ignore_last_segment(&mut self) { | |
| 114 | self.segments = self.segments.strip_last(); | |
| 115 | } | |
| 116 | ||
| 117 | #[inline] | |
| 118 | pub(crate) fn set_current_segment(&mut self, segment: usize) { | |
| 119 | self.current_segment_idx = segment; | |
| 120 | self.current_or_prev_segment = self | |
| 121 | .segments | |
| 122 | .get(segment) | |
| 123 | .expect("invalid segment passed to PathLoweringContext::set_current_segment()"); | |
| 124 | } | |
| 125 | ||
| 126 | 112 | #[inline] |
| 127 | 113 | fn with_lifetime_elision<T>( |
| 128 | 114 | &mut self, |
| ... | ... | @@ -390,103 +376,6 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { |
| 390 | 376 | Some((resolution, remaining_index)) |
| 391 | 377 | } |
| 392 | 378 | |
| 393 | pub(crate) fn resolve_path_in_value_ns( | |
| 394 | &mut self, | |
| 395 | hygiene_id: HygieneId, | |
| 396 | ) -> Option<ResolveValueResult> { | |
| 397 | let (res, prefix_info) = self.ctx.resolver.resolve_path_in_value_ns_with_prefix_info( | |
| 398 | self.ctx.db, | |
| 399 | self.path, | |
| 400 | hygiene_id, | |
| 401 | )?; | |
| 402 | ||
| 403 | let segments = self.segments; | |
| 404 | if segments.is_empty() || matches!(self.path, Path::LangItem(..)) { | |
| 405 | // `segments.is_empty()` can occur with `self`. | |
| 406 | return Some(res); | |
| 407 | } | |
| 408 | ||
| 409 | let (mod_segments, enum_segment, resolved_segment_idx) = match res { | |
| 410 | ResolveValueResult::Partial(_, unresolved_segment, _) => { | |
| 411 | (segments.take(unresolved_segment - 1), None, unresolved_segment - 1) | |
| 412 | } | |
| 413 | ResolveValueResult::ValueNs(ValueNs::EnumVariantId(_), _) | |
| 414 | if prefix_info.enum_variant => | |
| 415 | { | |
| 416 | (segments.strip_last_two(), segments.len().checked_sub(2), segments.len() - 1) | |
| 417 | } | |
| 418 | ResolveValueResult::ValueNs(..) => (segments.strip_last(), None, segments.len() - 1), | |
| 419 | }; | |
| 420 | ||
| 421 | self.current_segment_idx = resolved_segment_idx; | |
| 422 | self.current_or_prev_segment = | |
| 423 | segments.get(resolved_segment_idx).expect("should have resolved segment"); | |
| 424 | ||
| 425 | for (i, mod_segment) in mod_segments.iter().enumerate() { | |
| 426 | if mod_segment.args_and_bindings.is_some() { | |
| 427 | self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited { | |
| 428 | segment: i as u32, | |
| 429 | reason: GenericArgsProhibitedReason::Module, | |
| 430 | }); | |
| 431 | } | |
| 432 | } | |
| 433 | ||
| 434 | if let Some(enum_segment) = enum_segment | |
| 435 | && segments.get(enum_segment).is_some_and(|it| it.args_and_bindings.is_some()) | |
| 436 | && segments.get(enum_segment + 1).is_some_and(|it| it.args_and_bindings.is_some()) | |
| 437 | { | |
| 438 | self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited { | |
| 439 | segment: (enum_segment + 1) as u32, | |
| 440 | reason: GenericArgsProhibitedReason::EnumVariant, | |
| 441 | }); | |
| 442 | } | |
| 443 | ||
| 444 | match &res { | |
| 445 | ResolveValueResult::ValueNs(resolution, _) => { | |
| 446 | let resolved_segment_idx = self.current_segment_u32(); | |
| 447 | let resolved_segment = self.current_or_prev_segment; | |
| 448 | ||
| 449 | let mut prohibit_generics_on_resolved = |reason| { | |
| 450 | if resolved_segment.args_and_bindings.is_some() { | |
| 451 | self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited { | |
| 452 | segment: resolved_segment_idx, | |
| 453 | reason, | |
| 454 | }); | |
| 455 | } | |
| 456 | }; | |
| 457 | ||
| 458 | match resolution { | |
| 459 | ValueNs::ImplSelf(_) => { | |
| 460 | prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy) | |
| 461 | } | |
| 462 | // FIXME: rustc generates E0107 (incorrect number of generic arguments) and not | |
| 463 | // E0109 (generic arguments provided for a type that doesn't accept them) for | |
| 464 | // consts and statics, presumably as a defense against future in which consts | |
| 465 | // and statics can be generic, or just because it was easier for rustc implementors. | |
| 466 | // That means we'll show the wrong error code. Because of us it's easier to do it | |
| 467 | // this way :) | |
| 468 | ValueNs::GenericParam(_) => { | |
| 469 | prohibit_generics_on_resolved(GenericArgsProhibitedReason::Const) | |
| 470 | } | |
| 471 | ValueNs::StaticId(_) => { | |
| 472 | prohibit_generics_on_resolved(GenericArgsProhibitedReason::Static) | |
| 473 | } | |
| 474 | ValueNs::LocalBinding(_) => { | |
| 475 | prohibit_generics_on_resolved(GenericArgsProhibitedReason::LocalVariable) | |
| 476 | } | |
| 477 | ValueNs::FunctionId(_) | |
| 478 | | ValueNs::StructId(_) | |
| 479 | | ValueNs::EnumVariantId(_) | |
| 480 | | ValueNs::ConstId(_) => {} | |
| 481 | } | |
| 482 | } | |
| 483 | ResolveValueResult::Partial(resolution, _, _) => { | |
| 484 | self.handle_type_ns_resolution(resolution); | |
| 485 | } | |
| 486 | }; | |
| 487 | Some(res) | |
| 488 | } | |
| 489 | ||
| 490 | 379 | fn select_associated_type(&mut self, res: Option<TypeNs>, infer_args: bool) -> Ty { |
| 491 | 380 | let Some(res) = res else { |
| 492 | 381 | return TyKind::Error.intern(Interner); |
| ... | ... | @@ -556,62 +445,6 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { |
| 556 | 445 | self.ctx.db.ty(typeable).instantiate(interner, args).to_chalk(interner) |
| 557 | 446 | } |
| 558 | 447 | |
| 559 | /// Collect generic arguments from a path into a `Substs`. See also | |
| 560 | /// `create_substs_for_ast_path` and `def_to_ty` in rustc. | |
| 561 | pub(crate) fn substs_from_path( | |
| 562 | &mut self, | |
| 563 | // Note that we don't call `db.value_type(resolved)` here, | |
| 564 | // `ValueTyDefId` is just a convenient way to pass generics and | |
| 565 | // special-case enum variants | |
| 566 | resolved: ValueTyDefId, | |
| 567 | infer_args: bool, | |
| 568 | lowering_assoc_type_generics: bool, | |
| 569 | ) -> Substitution { | |
| 570 | let prev_current_segment_idx = self.current_segment_idx; | |
| 571 | let prev_current_segment = self.current_or_prev_segment; | |
| 572 | ||
| 573 | let generic_def = match resolved { | |
| 574 | ValueTyDefId::FunctionId(it) => it.into(), | |
| 575 | ValueTyDefId::StructId(it) => it.into(), | |
| 576 | ValueTyDefId::UnionId(it) => it.into(), | |
| 577 | ValueTyDefId::ConstId(it) => it.into(), | |
| 578 | ValueTyDefId::StaticId(_) => return Substitution::empty(Interner), | |
| 579 | ValueTyDefId::EnumVariantId(var) => { | |
| 580 | // the generic args for an enum variant may be either specified | |
| 581 | // on the segment referring to the enum, or on the segment | |
| 582 | // referring to the variant. So `Option::<T>::None` and | |
| 583 | // `Option::None::<T>` are both allowed (though the former is | |
| 584 | // FIXME: This isn't strictly correct, enum variants may be used not through the enum | |
| 585 | // (via `use Enum::Variant`). The resolver returns whether they were, but we don't have its result | |
| 586 | // available here. The worst that can happen is that we will show some confusing diagnostics to the user, | |
| 587 | // if generics exist on the module and they don't match with the variant. | |
| 588 | // preferred). See also `def_ids_for_path_segments` in rustc. | |
| 589 | // | |
| 590 | // `wrapping_sub(1)` will return a number which `get` will return None for if current_segment_idx<2. | |
| 591 | // This simplifies the code a bit. | |
| 592 | let penultimate_idx = self.current_segment_idx.wrapping_sub(1); | |
| 593 | let penultimate = self.segments.get(penultimate_idx); | |
| 594 | if let Some(penultimate) = penultimate | |
| 595 | && self.current_or_prev_segment.args_and_bindings.is_none() | |
| 596 | && penultimate.args_and_bindings.is_some() | |
| 597 | { | |
| 598 | self.current_segment_idx = penultimate_idx; | |
| 599 | self.current_or_prev_segment = penultimate; | |
| 600 | } | |
| 601 | var.lookup(self.ctx.db).parent.into() | |
| 602 | } | |
| 603 | }; | |
| 604 | let result = self.substs_from_path_segment( | |
| 605 | generic_def, | |
| 606 | infer_args, | |
| 607 | None, | |
| 608 | lowering_assoc_type_generics, | |
| 609 | ); | |
| 610 | self.current_segment_idx = prev_current_segment_idx; | |
| 611 | self.current_or_prev_segment = prev_current_segment; | |
| 612 | result | |
| 613 | } | |
| 614 | ||
| 615 | 448 | pub(crate) fn substs_from_path_segment( |
| 616 | 449 | &mut self, |
| 617 | 450 | def: GenericDefId, |
| ... | ... | @@ -816,14 +649,6 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { |
| 816 | 649 | }); |
| 817 | 650 | } |
| 818 | 651 | |
| 819 | fn report_elision_failure(&mut self, def: GenericDefId, expected_count: u32) { | |
| 820 | self.ctx.on_diagnostic(PathLoweringDiagnostic::ElisionFailure { | |
| 821 | generics_source: self.generics_source, | |
| 822 | def, | |
| 823 | expected_count, | |
| 824 | }); | |
| 825 | } | |
| 826 | ||
| 827 | 652 | fn report_missing_lifetime(&mut self, def: GenericDefId, expected_count: u32) { |
| 828 | 653 | self.ctx.on_diagnostic(PathLoweringDiagnostic::MissingLifetime { |
| 829 | 654 | generics_source: self.generics_source, |
| ... | ... | @@ -976,8 +801,6 @@ pub(crate) trait GenericArgsLowerer { |
| 976 | 801 | hard_error: bool, |
| 977 | 802 | ); |
| 978 | 803 | |
| 979 | fn report_elision_failure(&mut self, def: GenericDefId, expected_count: u32); | |
| 980 | ||
| 981 | 804 | fn report_missing_lifetime(&mut self, def: GenericDefId, expected_count: u32); |
| 982 | 805 | |
| 983 | 806 | fn report_len_mismatch( |
| ... | ... | @@ -1050,13 +873,6 @@ fn check_generic_args_len( |
| 1050 | 873 | ctx.report_missing_lifetime(def, lifetime_args_len as u32); |
| 1051 | 874 | had_error = true |
| 1052 | 875 | } |
| 1053 | LifetimeElisionKind::ElisionFailure => { | |
| 1054 | ctx.report_elision_failure(def, lifetime_args_len as u32); | |
| 1055 | had_error = true; | |
| 1056 | } | |
| 1057 | LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: _ } => { | |
| 1058 | // FIXME: Check there are other lifetimes in scope, and error/lint. | |
| 1059 | } | |
| 1060 | 876 | LifetimeElisionKind::Elided(_) => { |
| 1061 | 877 | ctx.report_elided_lifetimes_in_path(def, lifetime_args_len as u32, false); |
| 1062 | 878 | } |
| ... | ... | @@ -1265,15 +1081,11 @@ pub(crate) fn substs_from_args_and_bindings( |
| 1265 | 1081 | // If there are fewer arguments than parameters, it means we're inferring the remaining arguments. |
| 1266 | 1082 | let param = if let GenericParamId::LifetimeParamId(_) = param_id { |
| 1267 | 1083 | match &lifetime_elision { |
| 1268 | LifetimeElisionKind::ElisionFailure | |
| 1269 | | LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true } | |
| 1084 | LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true } | |
| 1270 | 1085 | | LifetimeElisionKind::AnonymousReportError => { |
| 1271 | 1086 | assert!(had_count_error); |
| 1272 | 1087 | ctx.inferred_kind(def, param_id, param, infer_args, &substs) |
| 1273 | 1088 | } |
| 1274 | LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: _ } => { | |
| 1275 | static_lifetime().cast(Interner) | |
| 1276 | } | |
| 1277 | 1089 | LifetimeElisionKind::Elided(lifetime) => lifetime.clone().cast(Interner), |
| 1278 | 1090 | LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false } |
| 1279 | 1091 | | LifetimeElisionKind::Infer => { |
src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver.rs+173-28| ... | ... | @@ -17,6 +17,7 @@ use std::{ |
| 17 | 17 | |
| 18 | 18 | use base_db::Crate; |
| 19 | 19 | use either::Either; |
| 20 | use hir_def::hir::generics::GenericParamDataRef; | |
| 20 | 21 | use hir_def::item_tree::FieldsShape; |
| 21 | 22 | use hir_def::{ |
| 22 | 23 | AdtId, AssocItemId, CallableDefId, ConstParamId, DefWithBodyId, EnumVariantId, FunctionId, |
| ... | ... | @@ -35,11 +36,11 @@ use hir_def::{ |
| 35 | 36 | TraitRef as HirTraitRef, TypeBound, TypeRef, TypeRefId, |
| 36 | 37 | }, |
| 37 | 38 | }; |
| 38 | use hir_def::{ConstId, StaticId}; | |
| 39 | use hir_def::{ConstId, LifetimeParamId, StaticId, TypeParamId}; | |
| 39 | 40 | use hir_expand::name::Name; |
| 40 | use intern::sym; | |
| 41 | use intern::{Symbol, sym}; | |
| 41 | 42 | use la_arena::{Arena, ArenaMap, Idx}; |
| 42 | use path::{PathDiagnosticCallback, PathLoweringContext, builtin}; | |
| 43 | use path::{PathDiagnosticCallback, PathLoweringContext}; | |
| 43 | 44 | use rustc_ast_ir::Mutability; |
| 44 | 45 | use rustc_hash::FxHashSet; |
| 45 | 46 | use rustc_pattern_analysis::Captures; |
| ... | ... | @@ -50,16 +51,18 @@ use rustc_type_ir::{ |
| 50 | 51 | TypeVisitableExt, |
| 51 | 52 | inherent::{GenericArg as _, GenericArgs as _, IntoKind as _, Region as _, SliceLike, Ty as _}, |
| 52 | 53 | }; |
| 54 | use rustc_type_ir::{TypeFoldable, TypeFolder, Upcast}; | |
| 53 | 55 | use salsa::plumbing::AsId; |
| 54 | 56 | use smallvec::{SmallVec, smallvec}; |
| 55 | 57 | use stdx::never; |
| 56 | 58 | use triomphe::Arc; |
| 57 | 59 | |
| 58 | 60 | use crate::ValueTyDefId; |
| 61 | use crate::next_solver::ParamConst; | |
| 59 | 62 | use crate::{ |
| 60 | 63 | FnAbi, ImplTraitId, Interner, ParamKind, TraitEnvironment, TyDefId, TyLoweringDiagnostic, |
| 61 | 64 | TyLoweringDiagnosticKind, |
| 62 | consteval_nextsolver::{intern_const_ref, path_to_const, unknown_const_as_generic}, | |
| 65 | consteval::{intern_const_ref, path_to_const, unknown_const_as_generic}, | |
| 63 | 66 | db::HirDatabase, |
| 64 | 67 | generics::{Generics, generics, trait_self_param_idx}, |
| 65 | 68 | lower::{Diagnostics, PathDiagnosticCallbackData, create_diagnostics}, |
| ... | ... | @@ -79,11 +82,11 @@ pub struct ImplTraits<'db> { |
| 79 | 82 | } |
| 80 | 83 | |
| 81 | 84 | #[derive(PartialEq, Eq, Debug, Hash)] |
| 82 | pub(crate) struct ImplTrait<'db> { | |
| 85 | pub struct ImplTrait<'db> { | |
| 83 | 86 | pub(crate) predicates: Vec<Clause<'db>>, |
| 84 | 87 | } |
| 85 | 88 | |
| 86 | pub(crate) type ImplTraitIdx<'db> = Idx<ImplTrait<'db>>; | |
| 89 | pub type ImplTraitIdx<'db> = Idx<ImplTrait<'db>>; | |
| 87 | 90 | |
| 88 | 91 | #[derive(Debug, Default)] |
| 89 | 92 | struct ImplTraitLoweringState<'db> { |
| ... | ... | @@ -102,7 +105,7 @@ impl<'db> ImplTraitLoweringState<'db> { |
| 102 | 105 | } |
| 103 | 106 | |
| 104 | 107 | #[derive(Debug, Clone)] |
| 105 | pub(crate) enum LifetimeElisionKind<'db> { | |
| 108 | pub enum LifetimeElisionKind<'db> { | |
| 106 | 109 | /// Create a new anonymous lifetime parameter and reference it. |
| 107 | 110 | /// |
| 108 | 111 | /// If `report_in_path`, report an error when encountering lifetime elision in a path: |
| ... | ... | @@ -171,7 +174,7 @@ impl<'db> LifetimeElisionKind<'db> { |
| 171 | 174 | } |
| 172 | 175 | |
| 173 | 176 | #[derive(Debug)] |
| 174 | pub(crate) struct TyLoweringContext<'db, 'a> { | |
| 177 | pub struct TyLoweringContext<'db, 'a> { | |
| 175 | 178 | pub db: &'db dyn HirDatabase, |
| 176 | 179 | interner: DbInterner<'db>, |
| 177 | 180 | resolver: &'a Resolver<'db>, |
| ... | ... | @@ -184,10 +187,12 @@ pub(crate) struct TyLoweringContext<'db, 'a> { |
| 184 | 187 | pub(crate) unsized_types: FxHashSet<Ty<'db>>, |
| 185 | 188 | pub(crate) diagnostics: Vec<TyLoweringDiagnostic>, |
| 186 | 189 | lifetime_elision: LifetimeElisionKind<'db>, |
| 190 | /// We disallow referencing generic parameters that have an index greater than or equal to this number. | |
| 191 | disallow_params_after: u32, | |
| 187 | 192 | } |
| 188 | 193 | |
| 189 | 194 | impl<'db, 'a> TyLoweringContext<'db, 'a> { |
| 190 | pub(crate) fn new( | |
| 195 | pub fn new( | |
| 191 | 196 | db: &'db dyn HirDatabase, |
| 192 | 197 | resolver: &'a Resolver<'db>, |
| 193 | 198 | store: &'a ExpressionStore, |
| ... | ... | @@ -208,6 +213,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { |
| 208 | 213 | unsized_types: FxHashSet::default(), |
| 209 | 214 | diagnostics: Vec::new(), |
| 210 | 215 | lifetime_elision, |
| 216 | disallow_params_after: u32::MAX, | |
| 211 | 217 | } |
| 212 | 218 | } |
| 213 | 219 | |
| ... | ... | @@ -243,6 +249,10 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { |
| 243 | 249 | self |
| 244 | 250 | } |
| 245 | 251 | |
| 252 | pub(crate) fn disallow_params_after(&mut self, after: u32) { | |
| 253 | self.disallow_params_after = after; | |
| 254 | } | |
| 255 | ||
| 246 | 256 | pub(crate) fn push_diagnostic(&mut self, type_ref: TypeRefId, kind: TyLoweringDiagnosticKind) { |
| 247 | 257 | self.diagnostics.push(TyLoweringDiagnostic { source: type_ref, kind }); |
| 248 | 258 | } |
| ... | ... | @@ -261,11 +271,11 @@ pub(crate) enum ImplTraitLoweringMode { |
| 261 | 271 | } |
| 262 | 272 | |
| 263 | 273 | impl<'db, 'a> TyLoweringContext<'db, 'a> { |
| 264 | pub(crate) fn lower_ty(&mut self, type_ref: TypeRefId) -> Ty<'db> { | |
| 274 | pub fn lower_ty(&mut self, type_ref: TypeRefId) -> Ty<'db> { | |
| 265 | 275 | self.lower_ty_ext(type_ref).0 |
| 266 | 276 | } |
| 267 | 277 | |
| 268 | pub(crate) fn lower_const(&mut self, const_ref: &ConstRef, const_type: Ty<'db>) -> Const<'db> { | |
| 278 | pub(crate) fn lower_const(&mut self, const_ref: ConstRef, const_type: Ty<'db>) -> Const<'db> { | |
| 269 | 279 | let const_ref = &self.store[const_ref.expr]; |
| 270 | 280 | match const_ref { |
| 271 | 281 | hir_def::hir::Expr::Path(path) => { |
| ... | ... | @@ -323,8 +333,35 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { |
| 323 | 333 | self.generics.get_or_init(|| generics(self.db, self.def)) |
| 324 | 334 | } |
| 325 | 335 | |
| 336 | fn type_param(&mut self, id: TypeParamId, index: u32, name: Symbol) -> Ty<'db> { | |
| 337 | if index >= self.disallow_params_after { | |
| 338 | // FIXME: Report an error. | |
| 339 | Ty::new_error(self.interner, ErrorGuaranteed) | |
| 340 | } else { | |
| 341 | Ty::new_param(self.interner, id, index, name) | |
| 342 | } | |
| 343 | } | |
| 344 | ||
| 345 | fn const_param(&mut self, id: ConstParamId, index: u32) -> Const<'db> { | |
| 346 | if index >= self.disallow_params_after { | |
| 347 | // FIXME: Report an error. | |
| 348 | Const::error(self.interner) | |
| 349 | } else { | |
| 350 | Const::new_param(self.interner, ParamConst { id, index }) | |
| 351 | } | |
| 352 | } | |
| 353 | ||
| 354 | fn region_param(&mut self, id: LifetimeParamId, index: u32) -> Region<'db> { | |
| 355 | if index >= self.disallow_params_after { | |
| 356 | // FIXME: Report an error. | |
| 357 | Region::error(self.interner) | |
| 358 | } else { | |
| 359 | Region::new_early_param(self.interner, EarlyParamRegion { id, index }) | |
| 360 | } | |
| 361 | } | |
| 362 | ||
| 326 | 363 | #[tracing::instrument(skip(self), ret)] |
| 327 | pub(crate) fn lower_ty_ext(&mut self, type_ref_id: TypeRefId) -> (Ty<'db>, Option<TypeNs>) { | |
| 364 | pub fn lower_ty_ext(&mut self, type_ref_id: TypeRefId) -> (Ty<'db>, Option<TypeNs>) { | |
| 328 | 365 | let interner = self.interner; |
| 329 | 366 | let mut res = None; |
| 330 | 367 | let type_ref = &self.store[type_ref_id]; |
| ... | ... | @@ -351,8 +388,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { |
| 351 | 388 | TypeOrConstParamData::TypeParamData(ty) => ty, |
| 352 | 389 | _ => unreachable!(), |
| 353 | 390 | }; |
| 354 | Ty::new_param( | |
| 355 | self.interner, | |
| 391 | self.type_param( | |
| 356 | 392 | type_param_id, |
| 357 | 393 | idx as u32, |
| 358 | 394 | type_data |
| ... | ... | @@ -367,7 +403,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { |
| 367 | 403 | } |
| 368 | 404 | TypeRef::Array(array) => { |
| 369 | 405 | let inner_ty = self.lower_ty(array.ty); |
| 370 | let const_len = self.lower_const(&array.len, Ty::new_usize(interner)); | |
| 406 | let const_len = self.lower_const(array.len, Ty::new_usize(interner)); | |
| 371 | 407 | Ty::new_array_with_const_len(interner, inner_ty, const_len) |
| 372 | 408 | } |
| 373 | 409 | &TypeRef::Slice(inner) => { |
| ... | ... | @@ -491,7 +527,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { |
| 491 | 527 | } |
| 492 | 528 | |
| 493 | 529 | #[inline] |
| 494 | fn on_path_diagnostic_callback(type_ref: TypeRefId) -> PathDiagnosticCallback<'static, 'db> { | |
| 530 | fn on_path_diagnostic_callback<'b>(type_ref: TypeRefId) -> PathDiagnosticCallback<'b, 'db> { | |
| 495 | 531 | PathDiagnosticCallback { |
| 496 | 532 | data: Either::Left(PathDiagnosticCallbackData(type_ref)), |
| 497 | 533 | callback: |data, this, diag| { |
| ... | ... | @@ -515,7 +551,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { |
| 515 | 551 | if let Some(type_ref) = path.type_anchor() { |
| 516 | 552 | let (ty, res) = self.lower_ty_ext(type_ref); |
| 517 | 553 | let mut ctx = self.at_path(path_id); |
| 518 | return ctx.lower_ty_relative_path(ty, res); | |
| 554 | return ctx.lower_ty_relative_path(ty, res, false); | |
| 519 | 555 | } |
| 520 | 556 | |
| 521 | 557 | let mut ctx = self.at_path(path_id); |
| ... | ... | @@ -545,7 +581,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { |
| 545 | 581 | TypeNs::TraitId(tr) => tr, |
| 546 | 582 | _ => return None, |
| 547 | 583 | }; |
| 548 | Some((ctx.lower_trait_ref_from_resolved_path(resolved, explicit_self_ty), ctx)) | |
| 584 | Some((ctx.lower_trait_ref_from_resolved_path(resolved, explicit_self_ty, false), ctx)) | |
| 549 | 585 | } |
| 550 | 586 | |
| 551 | 587 | fn lower_trait_ref( |
| ... | ... | @@ -869,7 +905,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { |
| 869 | 905 | ImplTrait { predicates } |
| 870 | 906 | } |
| 871 | 907 | |
| 872 | pub(crate) fn lower_lifetime(&self, lifetime: LifetimeRefId) -> Region<'db> { | |
| 908 | pub(crate) fn lower_lifetime(&mut self, lifetime: LifetimeRefId) -> Region<'db> { | |
| 873 | 909 | match self.resolver.resolve_lifetime(&self.store[lifetime]) { |
| 874 | 910 | Some(resolution) => match resolution { |
| 875 | 911 | LifetimeNs::Static => Region::new_static(self.interner), |
| ... | ... | @@ -878,10 +914,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { |
| 878 | 914 | None => return Region::error(self.interner), |
| 879 | 915 | Some(idx) => idx, |
| 880 | 916 | }; |
| 881 | Region::new_early_param( | |
| 882 | self.interner, | |
| 883 | EarlyParamRegion { index: idx as u32, id }, | |
| 884 | ) | |
| 917 | self.region_param(id, idx as u32) | |
| 885 | 918 | } |
| 886 | 919 | }, |
| 887 | 920 | None => Region::error(self.interner), |
| ... | ... | @@ -980,10 +1013,10 @@ pub(crate) fn type_alias_impl_traits<'db>( |
| 980 | 1013 | pub(crate) fn ty_query<'db>(db: &'db dyn HirDatabase, def: TyDefId) -> EarlyBinder<'db, Ty<'db>> { |
| 981 | 1014 | let interner = DbInterner::new_with(db, None, None); |
| 982 | 1015 | match def { |
| 983 | TyDefId::BuiltinType(it) => EarlyBinder::bind(builtin(interner, it)), | |
| 1016 | TyDefId::BuiltinType(it) => EarlyBinder::bind(Ty::from_builtin_type(interner, it)), | |
| 984 | 1017 | TyDefId::AdtId(it) => EarlyBinder::bind(Ty::new_adt( |
| 985 | 1018 | interner, |
| 986 | AdtDef::new(it, interner), | |
| 1019 | it, | |
| 987 | 1020 | GenericArgs::identity_for_item(interner, it.into()), |
| 988 | 1021 | )), |
| 989 | 1022 | TyDefId::TypeAliasId(it) => db.type_for_type_alias_with_diagnostics(it).0, |
| ... | ... | @@ -1368,6 +1401,7 @@ pub(crate) fn generic_predicates_for_param_cycle_result( |
| 1368 | 1401 | pub struct GenericPredicates<'db>(Option<Arc<[Clause<'db>]>>); |
| 1369 | 1402 | |
| 1370 | 1403 | impl<'db> GenericPredicates<'db> { |
| 1404 | #[inline] | |
| 1371 | 1405 | pub fn instantiate( |
| 1372 | 1406 | &self, |
| 1373 | 1407 | interner: DbInterner<'db>, |
| ... | ... | @@ -1377,6 +1411,11 @@ impl<'db> GenericPredicates<'db> { |
| 1377 | 1411 | .as_ref() |
| 1378 | 1412 | .map(|it| EarlyBinder::bind(it.iter().copied()).iter_instantiated(interner, args)) |
| 1379 | 1413 | } |
| 1414 | ||
| 1415 | #[inline] | |
| 1416 | pub fn instantiate_identity(&self) -> Option<impl Iterator<Item = Clause<'db>>> { | |
| 1417 | self.0.as_ref().map(|it| it.iter().copied()) | |
| 1418 | } | |
| 1380 | 1419 | } |
| 1381 | 1420 | |
| 1382 | 1421 | impl<'db> ops::Deref for GenericPredicates<'db> { |
| ... | ... | @@ -1425,8 +1464,7 @@ pub(crate) fn trait_environment_query<'db>( |
| 1425 | 1464 | for pred in maybe_parent_generics.where_predicates() { |
| 1426 | 1465 | for pred in ctx.lower_where_predicate(pred, false, &generics, PredicateFilter::All) { |
| 1427 | 1466 | if let rustc_type_ir::ClauseKind::Trait(tr) = pred.kind().skip_binder() { |
| 1428 | traits_in_scope | |
| 1429 | .push((convert_ty_for_result(interner, tr.self_ty()), tr.def_id().0)); | |
| 1467 | traits_in_scope.push((tr.self_ty(), tr.def_id().0)); | |
| 1430 | 1468 | } |
| 1431 | 1469 | clauses.push(pred); |
| 1432 | 1470 | } |
| ... | ... | @@ -1748,6 +1786,113 @@ pub(crate) fn lower_generic_arg<'a, 'db, T>( |
| 1748 | 1786 | } |
| 1749 | 1787 | } |
| 1750 | 1788 | |
| 1789 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | |
| 1790 | pub struct GenericDefaults<'db>( | |
| 1791 | Option<Arc<[Option<EarlyBinder<'db, crate::next_solver::GenericArg<'db>>>]>>, | |
| 1792 | ); | |
| 1793 | ||
| 1794 | impl<'db> GenericDefaults<'db> { | |
| 1795 | #[inline] | |
| 1796 | pub fn get(&self, idx: usize) -> Option<EarlyBinder<'db, crate::next_solver::GenericArg<'db>>> { | |
| 1797 | self.0.as_ref()?[idx] | |
| 1798 | } | |
| 1799 | } | |
| 1800 | ||
| 1801 | pub(crate) fn generic_defaults_query( | |
| 1802 | db: &dyn HirDatabase, | |
| 1803 | def: GenericDefId, | |
| 1804 | ) -> GenericDefaults<'_> { | |
| 1805 | db.generic_defaults_ns_with_diagnostics(def).0 | |
| 1806 | } | |
| 1807 | ||
| 1808 | /// Resolve the default type params from generics. | |
| 1809 | /// | |
| 1810 | /// Diagnostics are only returned for this `GenericDefId` (returned defaults include parents). | |
| 1811 | pub(crate) fn generic_defaults_with_diagnostics_query( | |
| 1812 | db: &dyn HirDatabase, | |
| 1813 | def: GenericDefId, | |
| 1814 | ) -> (GenericDefaults<'_>, Diagnostics) { | |
| 1815 | let generic_params = generics(db, def); | |
| 1816 | if generic_params.is_empty() { | |
| 1817 | return (GenericDefaults(None), None); | |
| 1818 | } | |
| 1819 | let resolver = def.resolver(db); | |
| 1820 | ||
| 1821 | let mut ctx = TyLoweringContext::new( | |
| 1822 | db, | |
| 1823 | &resolver, | |
| 1824 | generic_params.store(), | |
| 1825 | def, | |
| 1826 | LifetimeElisionKind::AnonymousReportError, | |
| 1827 | ) | |
| 1828 | .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed); | |
| 1829 | let mut idx = 0; | |
| 1830 | let mut has_any_default = false; | |
| 1831 | let mut defaults = generic_params | |
| 1832 | .iter_parents_with_store() | |
| 1833 | .map(|((id, p), store)| { | |
| 1834 | ctx.store = store; | |
| 1835 | let (result, has_default) = handle_generic_param(&mut ctx, idx, id, p, &generic_params); | |
| 1836 | has_any_default |= has_default; | |
| 1837 | idx += 1; | |
| 1838 | result | |
| 1839 | }) | |
| 1840 | .collect::<Vec<_>>(); | |
| 1841 | ctx.diagnostics.clear(); // Don't include diagnostics from the parent. | |
| 1842 | defaults.extend(generic_params.iter_self().map(|(id, p)| { | |
| 1843 | let (result, has_default) = handle_generic_param(&mut ctx, idx, id, p, &generic_params); | |
| 1844 | has_any_default |= has_default; | |
| 1845 | idx += 1; | |
| 1846 | result | |
| 1847 | })); | |
| 1848 | let diagnostics = create_diagnostics(mem::take(&mut ctx.diagnostics)); | |
| 1849 | let defaults = if has_any_default { | |
| 1850 | GenericDefaults(Some(Arc::from_iter(defaults))) | |
| 1851 | } else { | |
| 1852 | GenericDefaults(None) | |
| 1853 | }; | |
| 1854 | return (defaults, diagnostics); | |
| 1855 | ||
| 1856 | fn handle_generic_param<'db>( | |
| 1857 | ctx: &mut TyLoweringContext<'db, '_>, | |
| 1858 | idx: usize, | |
| 1859 | id: GenericParamId, | |
| 1860 | p: GenericParamDataRef<'_>, | |
| 1861 | generic_params: &Generics, | |
| 1862 | ) -> (Option<EarlyBinder<'db, crate::next_solver::GenericArg<'db>>>, bool) { | |
| 1863 | // Each default can only refer to previous parameters. | |
| 1864 | // Type variable default referring to parameter coming | |
| 1865 | // after it is forbidden. | |
| 1866 | ctx.disallow_params_after(idx as u32); | |
| 1867 | match p { | |
| 1868 | GenericParamDataRef::TypeParamData(p) => { | |
| 1869 | let ty = p.default.map(|ty| ctx.lower_ty(ty)); | |
| 1870 | (ty.map(|ty| EarlyBinder::bind(ty.into())), p.default.is_some()) | |
| 1871 | } | |
| 1872 | GenericParamDataRef::ConstParamData(p) => { | |
| 1873 | let GenericParamId::ConstParamId(id) = id else { | |
| 1874 | unreachable!("Unexpected lifetime or type argument") | |
| 1875 | }; | |
| 1876 | ||
| 1877 | let mut val = p.default.map(|c| { | |
| 1878 | let param_ty = ctx.lower_ty(p.ty); | |
| 1879 | let c = ctx.lower_const(c, param_ty); | |
| 1880 | c.into() | |
| 1881 | }); | |
| 1882 | (val.map(EarlyBinder::bind), p.default.is_some()) | |
| 1883 | } | |
| 1884 | GenericParamDataRef::LifetimeParamData(_) => (None, false), | |
| 1885 | } | |
| 1886 | } | |
| 1887 | } | |
| 1888 | ||
| 1889 | pub(crate) fn generic_defaults_with_diagnostics_cycle_result( | |
| 1890 | _db: &dyn HirDatabase, | |
| 1891 | _def: GenericDefId, | |
| 1892 | ) -> (GenericDefaults<'_>, Diagnostics) { | |
| 1893 | (GenericDefaults(None), None) | |
| 1894 | } | |
| 1895 | ||
| 1751 | 1896 | /// Build the signature of a callable item (function, struct or enum variant). |
| 1752 | 1897 | pub(crate) fn callable_item_signature_query<'db>( |
| 1753 | 1898 | db: &'db dyn HirDatabase, |
| ... | ... | @@ -1804,7 +1949,7 @@ fn fn_sig_for_fn<'db>( |
| 1804 | 1949 | fn type_for_adt<'db>(db: &'db dyn HirDatabase, adt: AdtId) -> EarlyBinder<'db, Ty<'db>> { |
| 1805 | 1950 | let interner = DbInterner::new_with(db, None, None); |
| 1806 | 1951 | let args = GenericArgs::identity_for_item(interner, adt.into()); |
| 1807 | let ty = Ty::new_adt(interner, AdtDef::new(adt, interner), args); | |
| 1952 | let ty = Ty::new_adt(interner, adt, args); | |
| 1808 | 1953 | EarlyBinder::bind(ty) |
| 1809 | 1954 | } |
| 1810 | 1955 |
src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver/path.rs+40-62| ... | ... | @@ -30,7 +30,7 @@ use stdx::never; |
| 30 | 30 | use crate::{ |
| 31 | 31 | GenericArgsProhibitedReason, IncorrectGenericsLenKind, PathGenericsSource, |
| 32 | 32 | PathLoweringDiagnostic, TyDefId, ValueTyDefId, |
| 33 | consteval_nextsolver::{unknown_const, unknown_const_as_generic}, | |
| 33 | consteval::{unknown_const, unknown_const_as_generic}, | |
| 34 | 34 | db::HirDatabase, |
| 35 | 35 | generics::{Generics, generics}, |
| 36 | 36 | lower::PathDiagnosticCallbackData, |
| ... | ... | @@ -51,15 +51,17 @@ use super::{ |
| 51 | 51 | const_param_ty_query, ty_query, |
| 52 | 52 | }; |
| 53 | 53 | |
| 54 | type CallbackData<'a> = | |
| 55 | Either<PathDiagnosticCallbackData, crate::infer::diagnostics::PathDiagnosticCallbackData<'a>>; | |
| 54 | type CallbackData<'a, 'db> = Either< | |
| 55 | PathDiagnosticCallbackData, | |
| 56 | crate::infer::diagnostics::PathDiagnosticCallbackData<'a, 'db>, | |
| 57 | >; | |
| 56 | 58 | |
| 57 | 59 | // We cannot use `&mut dyn FnMut()` because of lifetime issues, and we don't want to use `Box<dyn FnMut()>` |
| 58 | 60 | // because of the allocation, so we create a lifetime-less callback, tailored for our needs. |
| 59 | 61 | pub(crate) struct PathDiagnosticCallback<'a, 'db> { |
| 60 | pub(crate) data: CallbackData<'a>, | |
| 62 | pub(crate) data: CallbackData<'a, 'db>, | |
| 61 | 63 | pub(crate) callback: |
| 62 | fn(&CallbackData<'_>, &mut TyLoweringContext<'db, '_>, PathLoweringDiagnostic), | |
| 64 | fn(&CallbackData<'_, 'db>, &mut TyLoweringContext<'db, '_>, PathLoweringDiagnostic), | |
| 63 | 65 | } |
| 64 | 66 | |
| 65 | 67 | pub(crate) struct PathLoweringContext<'a, 'b, 'db> { |
| ... | ... | @@ -155,13 +157,14 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { |
| 155 | 157 | ty: Ty<'db>, |
| 156 | 158 | // We need the original resolution to lower `Self::AssocTy` correctly |
| 157 | 159 | res: Option<TypeNs>, |
| 160 | infer_args: bool, | |
| 158 | 161 | ) -> (Ty<'db>, Option<TypeNs>) { |
| 159 | 162 | let remaining_segments = self.segments.len() - self.current_segment_idx; |
| 160 | 163 | match remaining_segments { |
| 161 | 164 | 0 => (ty, res), |
| 162 | 165 | 1 => { |
| 163 | 166 | // resolve unselected assoc types |
| 164 | (self.select_associated_type(res), None) | |
| 167 | (self.select_associated_type(res, infer_args), None) | |
| 165 | 168 | } |
| 166 | 169 | _ => { |
| 167 | 170 | // FIXME report error (ambiguous associated type) |
| ... | ... | @@ -204,6 +207,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { |
| 204 | 207 | let trait_ref = self.lower_trait_ref_from_resolved_path( |
| 205 | 208 | trait_, |
| 206 | 209 | Ty::new_error(self.ctx.interner, ErrorGuaranteed), |
| 210 | false, | |
| 207 | 211 | ); |
| 208 | 212 | tracing::debug!(?trait_ref); |
| 209 | 213 | self.skip_resolved_segment(); |
| ... | ... | @@ -276,8 +280,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { |
| 276 | 280 | GenericParamDataRef::TypeParamData(p) => p, |
| 277 | 281 | _ => unreachable!(), |
| 278 | 282 | }; |
| 279 | Ty::new_param( | |
| 280 | self.ctx.interner, | |
| 283 | self.ctx.type_param( | |
| 281 | 284 | param_id, |
| 282 | 285 | idx as u32, |
| 283 | 286 | p.name |
| ... | ... | @@ -293,7 +296,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { |
| 293 | 296 | self.ctx.interner, |
| 294 | 297 | adt.into(), |
| 295 | 298 | ); |
| 296 | Ty::new_adt(self.ctx.interner, AdtDef::new(adt, self.ctx.interner), args) | |
| 299 | Ty::new_adt(self.ctx.interner, adt, args) | |
| 297 | 300 | } |
| 298 | 301 | |
| 299 | 302 | TypeNs::AdtId(it) => self.lower_path_inner(it.into(), infer_args), |
| ... | ... | @@ -308,7 +311,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { |
| 308 | 311 | tracing::debug!(?ty); |
| 309 | 312 | |
| 310 | 313 | self.skip_resolved_segment(); |
| 311 | self.lower_ty_relative_path(ty, Some(resolution)) | |
| 314 | self.lower_ty_relative_path(ty, Some(resolution), infer_args) | |
| 312 | 315 | } |
| 313 | 316 | |
| 314 | 317 | fn handle_type_ns_resolution(&mut self, resolution: &TypeNs) { |
| ... | ... | @@ -480,14 +483,19 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { |
| 480 | 483 | // and statics can be generic, or just because it was easier for rustc implementors. |
| 481 | 484 | // That means we'll show the wrong error code. Because of us it's easier to do it |
| 482 | 485 | // this way :) |
| 483 | ValueNs::GenericParam(_) | ValueNs::ConstId(_) => { | |
| 486 | ValueNs::GenericParam(_) => { | |
| 484 | 487 | prohibit_generics_on_resolved(GenericArgsProhibitedReason::Const) |
| 485 | 488 | } |
| 486 | 489 | ValueNs::StaticId(_) => { |
| 487 | 490 | prohibit_generics_on_resolved(GenericArgsProhibitedReason::Static) |
| 488 | 491 | } |
| 489 | ValueNs::FunctionId(_) | ValueNs::StructId(_) | ValueNs::EnumVariantId(_) => {} | |
| 490 | ValueNs::LocalBinding(_) => {} | |
| 492 | ValueNs::LocalBinding(_) => { | |
| 493 | prohibit_generics_on_resolved(GenericArgsProhibitedReason::LocalVariable) | |
| 494 | } | |
| 495 | ValueNs::FunctionId(_) | |
| 496 | | ValueNs::StructId(_) | |
| 497 | | ValueNs::EnumVariantId(_) | |
| 498 | | ValueNs::ConstId(_) => {} | |
| 491 | 499 | } |
| 492 | 500 | } |
| 493 | 501 | ResolveValueResult::Partial(resolution, _, _) => { |
| ... | ... | @@ -498,7 +506,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { |
| 498 | 506 | } |
| 499 | 507 | |
| 500 | 508 | #[tracing::instrument(skip(self), ret)] |
| 501 | fn select_associated_type(&mut self, res: Option<TypeNs>) -> Ty<'db> { | |
| 509 | fn select_associated_type(&mut self, res: Option<TypeNs>, infer_args: bool) -> Ty<'db> { | |
| 502 | 510 | let interner = self.ctx.interner; |
| 503 | 511 | let Some(res) = res else { |
| 504 | 512 | return Ty::new_error(self.ctx.interner, ErrorGuaranteed); |
| ... | ... | @@ -516,7 +524,8 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { |
| 516 | 524 | // generic params. It's inefficient to splice the `Substitution`s, so we may want |
| 517 | 525 | // that method to optionally take parent `Substitution` as we already know them at |
| 518 | 526 | // this point (`t.substitution`). |
| 519 | let substs = self.substs_from_path_segment(associated_ty.into(), false, None, true); | |
| 527 | let substs = | |
| 528 | self.substs_from_path_segment(associated_ty.into(), infer_args, None, true); | |
| 520 | 529 | |
| 521 | 530 | let substs = crate::next_solver::GenericArgs::new_from_iter( |
| 522 | 531 | interner, |
| ... | ... | @@ -541,7 +550,9 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { |
| 541 | 550 | |
| 542 | 551 | fn lower_path_inner(&mut self, typeable: TyDefId, infer_args: bool) -> Ty<'db> { |
| 543 | 552 | let generic_def = match typeable { |
| 544 | TyDefId::BuiltinType(builtinty) => return builtin(self.ctx.interner, builtinty), | |
| 553 | TyDefId::BuiltinType(builtinty) => { | |
| 554 | return Ty::from_builtin_type(self.ctx.interner, builtinty); | |
| 555 | } | |
| 545 | 556 | TyDefId::AdtId(it) => it.into(), |
| 546 | 557 | TyDefId::TypeAliasId(it) => it.into(), |
| 547 | 558 | }; |
| ... | ... | @@ -715,12 +726,12 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { |
| 715 | 726 | param: GenericParamDataRef<'_>, |
| 716 | 727 | arg: &GenericArg, |
| 717 | 728 | ) -> crate::next_solver::GenericArg<'db> { |
| 718 | match (param, arg) { | |
| 729 | match (param, *arg) { | |
| 719 | 730 | (GenericParamDataRef::LifetimeParamData(_), GenericArg::Lifetime(lifetime)) => { |
| 720 | self.ctx.ctx.lower_lifetime(*lifetime).into() | |
| 731 | self.ctx.ctx.lower_lifetime(lifetime).into() | |
| 721 | 732 | } |
| 722 | 733 | (GenericParamDataRef::TypeParamData(_), GenericArg::Type(type_ref)) => { |
| 723 | self.ctx.ctx.lower_ty(*type_ref).into() | |
| 734 | self.ctx.ctx.lower_ty(type_ref).into() | |
| 724 | 735 | } |
| 725 | 736 | (GenericParamDataRef::ConstParamData(_), GenericArg::Const(konst)) => { |
| 726 | 737 | let GenericParamId::ConstParamId(const_id) = param_id else { |
| ... | ... | @@ -859,8 +870,9 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { |
| 859 | 870 | &mut self, |
| 860 | 871 | resolved: TraitId, |
| 861 | 872 | explicit_self_ty: Ty<'db>, |
| 873 | infer_args: bool, | |
| 862 | 874 | ) -> TraitRef<'db> { |
| 863 | let args = self.trait_ref_substs_from_path(resolved, explicit_self_ty); | |
| 875 | let args = self.trait_ref_substs_from_path(resolved, explicit_self_ty, infer_args); | |
| 864 | 876 | TraitRef::new_from_args(self.ctx.interner, resolved.into(), args) |
| 865 | 877 | } |
| 866 | 878 | |
| ... | ... | @@ -868,8 +880,9 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { |
| 868 | 880 | &mut self, |
| 869 | 881 | resolved: TraitId, |
| 870 | 882 | explicit_self_ty: Ty<'db>, |
| 883 | infer_args: bool, | |
| 871 | 884 | ) -> crate::next_solver::GenericArgs<'db> { |
| 872 | self.substs_from_path_segment(resolved.into(), false, Some(explicit_self_ty), false) | |
| 885 | self.substs_from_path_segment(resolved.into(), infer_args, Some(explicit_self_ty), false) | |
| 873 | 886 | } |
| 874 | 887 | |
| 875 | 888 | pub(super) fn assoc_type_bindings_from_type_bound<'c>( |
| ... | ... | @@ -1039,8 +1052,12 @@ fn check_generic_args_len<'db>( |
| 1039 | 1052 | } |
| 1040 | 1053 | |
| 1041 | 1054 | let lifetime_args_len = def_generics.len_lifetimes_self(); |
| 1042 | if provided_lifetimes_count == 0 && lifetime_args_len > 0 && !lowering_assoc_type_generics { | |
| 1043 | // In generic associated types, we never allow inferring the lifetimes. | |
| 1055 | if provided_lifetimes_count == 0 | |
| 1056 | && lifetime_args_len > 0 | |
| 1057 | && (!lowering_assoc_type_generics || infer_args) | |
| 1058 | { | |
| 1059 | // In generic associated types, we never allow inferring the lifetimes, but only in type context, that is | |
| 1060 | // when `infer_args == false`. In expression/pattern context we always allow inferring them, even for GATs. | |
| 1044 | 1061 | match lifetime_elision { |
| 1045 | 1062 | &LifetimeElisionKind::AnonymousCreateParameter { report_in_path } => { |
| 1046 | 1063 | ctx.report_elided_lifetimes_in_path(def, lifetime_args_len as u32, report_in_path); |
| ... | ... | @@ -1335,42 +1352,3 @@ fn unknown_subst<'db>( |
| 1335 | 1352 | }), |
| 1336 | 1353 | ) |
| 1337 | 1354 | } |
| 1338 | ||
| 1339 | pub(crate) fn builtin<'db>(interner: DbInterner<'db>, builtin: BuiltinType) -> Ty<'db> { | |
| 1340 | match builtin { | |
| 1341 | BuiltinType::Char => Ty::new(interner, rustc_type_ir::TyKind::Char), | |
| 1342 | BuiltinType::Bool => Ty::new_bool(interner), | |
| 1343 | BuiltinType::Str => Ty::new(interner, rustc_type_ir::TyKind::Str), | |
| 1344 | BuiltinType::Int(t) => { | |
| 1345 | let int_ty = match primitive::int_ty_from_builtin(t) { | |
| 1346 | chalk_ir::IntTy::Isize => rustc_type_ir::IntTy::Isize, | |
| 1347 | chalk_ir::IntTy::I8 => rustc_type_ir::IntTy::I8, | |
| 1348 | chalk_ir::IntTy::I16 => rustc_type_ir::IntTy::I16, | |
| 1349 | chalk_ir::IntTy::I32 => rustc_type_ir::IntTy::I32, | |
| 1350 | chalk_ir::IntTy::I64 => rustc_type_ir::IntTy::I64, | |
| 1351 | chalk_ir::IntTy::I128 => rustc_type_ir::IntTy::I128, | |
| 1352 | }; | |
| 1353 | Ty::new_int(interner, int_ty) | |
| 1354 | } | |
| 1355 | BuiltinType::Uint(t) => { | |
| 1356 | let uint_ty = match primitive::uint_ty_from_builtin(t) { | |
| 1357 | chalk_ir::UintTy::Usize => rustc_type_ir::UintTy::Usize, | |
| 1358 | chalk_ir::UintTy::U8 => rustc_type_ir::UintTy::U8, | |
| 1359 | chalk_ir::UintTy::U16 => rustc_type_ir::UintTy::U16, | |
| 1360 | chalk_ir::UintTy::U32 => rustc_type_ir::UintTy::U32, | |
| 1361 | chalk_ir::UintTy::U64 => rustc_type_ir::UintTy::U64, | |
| 1362 | chalk_ir::UintTy::U128 => rustc_type_ir::UintTy::U128, | |
| 1363 | }; | |
| 1364 | Ty::new_uint(interner, uint_ty) | |
| 1365 | } | |
| 1366 | BuiltinType::Float(t) => { | |
| 1367 | let float_ty = match primitive::float_ty_from_builtin(t) { | |
| 1368 | chalk_ir::FloatTy::F16 => rustc_type_ir::FloatTy::F16, | |
| 1369 | chalk_ir::FloatTy::F32 => rustc_type_ir::FloatTy::F32, | |
| 1370 | chalk_ir::FloatTy::F64 => rustc_type_ir::FloatTy::F64, | |
| 1371 | chalk_ir::FloatTy::F128 => rustc_type_ir::FloatTy::F128, | |
| 1372 | }; | |
| 1373 | Ty::new_float(interner, float_ty) | |
| 1374 | } | |
| 1375 | } | |
| 1376 | } |
src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs+342-514| ... | ... | @@ -4,43 +4,44 @@ |
| 4 | 4 | //! and the corresponding code mostly in rustc_hir_analysis/check/method/probe.rs. |
| 5 | 5 | use std::ops::ControlFlow; |
| 6 | 6 | |
| 7 | use arrayvec::ArrayVec; | |
| 8 | 7 | use base_db::Crate; |
| 9 | use chalk_ir::{UniverseIndex, WithKind, cast::Cast}; | |
| 10 | 8 | use hir_def::{ |
| 11 | AssocItemId, BlockId, ConstId, FunctionId, HasModule, ImplId, ItemContainerId, Lookup, | |
| 12 | ModuleId, TraitId, | |
| 13 | nameres::{DefMap, assoc::ImplItems, block_def_map, crate_def_map}, | |
| 9 | AdtId, AssocItemId, BlockId, ConstId, FunctionId, HasModule, ImplId, ItemContainerId, Lookup, | |
| 10 | ModuleId, TraitId, TypeAliasId, | |
| 11 | nameres::{DefMap, block_def_map, crate_def_map}, | |
| 14 | 12 | signatures::{ConstFlags, EnumFlags, FnFlags, StructFlags, TraitFlags, TypeAliasFlags}, |
| 15 | 13 | }; |
| 16 | 14 | use hir_expand::name::Name; |
| 17 | 15 | use intern::sym; |
| 16 | use rustc_ast_ir::Mutability; | |
| 18 | 17 | use rustc_hash::{FxHashMap, FxHashSet}; |
| 19 | use rustc_type_ir::inherent::{IntoKind, SliceLike, Ty as _}; | |
| 18 | use rustc_type_ir::{ | |
| 19 | FloatTy, IntTy, TypeVisitableExt, UintTy, | |
| 20 | inherent::{ | |
| 21 | AdtDef, BoundExistentialPredicates, GenericArgs as _, IntoKind, SliceLike, Ty as _, | |
| 22 | }, | |
| 23 | }; | |
| 20 | 24 | use smallvec::{SmallVec, smallvec}; |
| 21 | 25 | use stdx::never; |
| 22 | 26 | use triomphe::Arc; |
| 23 | 27 | |
| 28 | use crate::next_solver::infer::InferCtxt; | |
| 29 | use crate::next_solver::infer::select::ImplSource; | |
| 24 | 30 | use crate::{ |
| 25 | AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId, GenericArgData, | |
| 26 | Goal, InEnvironment, Interner, Mutability, Scalar, Substitution, TraitEnvironment, TraitRef, | |
| 27 | TraitRefExt, Ty, TyBuilder, TyExt, TyKind, VariableKind, WhereClause, | |
| 31 | TraitEnvironment, TyBuilder, | |
| 28 | 32 | autoderef::{self, AutoderefKind}, |
| 29 | 33 | db::HirDatabase, |
| 30 | from_chalk_trait_id, from_foreign_def_id, | |
| 31 | 34 | infer::{Adjust, Adjustment, OverloadedDeref, PointerCast, unify::InferenceTable}, |
| 32 | 35 | lang_items::is_box, |
| 33 | 36 | next_solver::{ |
| 34 | self, DbInterner, SolverDefId, | |
| 37 | Canonical, DbInterner, ErrorGuaranteed, GenericArgs, Goal, Predicate, Region, SolverDefId, | |
| 38 | TraitRef, Ty, TyKind, TypingMode, | |
| 35 | 39 | infer::{ |
| 36 | DefineOpaqueTypes, | |
| 37 | traits::{ObligationCause, PredicateObligation}, | |
| 40 | DbInternerInferExt, DefineOpaqueTypes, | |
| 41 | traits::{Obligation, ObligationCause, PredicateObligation}, | |
| 38 | 42 | }, |
| 39 | mapping::{ChalkToNextSolver, NextSolverToChalk}, | |
| 40 | 43 | obligation_ctxt::ObligationCtxt, |
| 41 | 44 | }, |
| 42 | primitive::{FloatTy, IntTy, UintTy}, | |
| 43 | to_chalk_trait_id, | |
| 44 | 45 | traits::next_trait_solve_canonical_in_ctxt, |
| 45 | 46 | utils::all_super_traits, |
| 46 | 47 | }; |
| ... | ... | @@ -55,11 +56,15 @@ pub enum TyFingerprint { |
| 55 | 56 | Never, |
| 56 | 57 | Ref(Mutability), |
| 57 | 58 | RawPtr(Mutability), |
| 58 | Scalar(Scalar), | |
| 59 | Bool, | |
| 60 | Char, | |
| 61 | Int(IntTy), | |
| 62 | Uint(UintTy), | |
| 63 | Float(FloatTy), | |
| 59 | 64 | // These can have user-defined impls: |
| 60 | 65 | Adt(hir_def::AdtId), |
| 61 | 66 | Dyn(TraitId), |
| 62 | ForeignType(ForeignDefId), | |
| 67 | ForeignType(TypeAliasId), | |
| 63 | 68 | // These only exist for trait impls |
| 64 | 69 | Unit, |
| 65 | 70 | Unnameable, |
| ... | ... | @@ -71,140 +76,73 @@ impl TyFingerprint { |
| 71 | 76 | /// types can have inherent impls: if we have some `struct S`, we can have |
| 72 | 77 | /// an `impl S`, but not `impl &S`. Hence, this will return `None` for |
| 73 | 78 | /// reference types and such. |
| 74 | pub fn for_inherent_impl(ty: &Ty) -> Option<TyFingerprint> { | |
| 75 | let fp = match ty.kind(Interner) { | |
| 79 | pub fn for_inherent_impl<'db>(ty: Ty<'db>) -> Option<TyFingerprint> { | |
| 80 | let fp = match ty.kind() { | |
| 76 | 81 | TyKind::Str => TyFingerprint::Str, |
| 77 | 82 | TyKind::Never => TyFingerprint::Never, |
| 78 | 83 | TyKind::Slice(..) => TyFingerprint::Slice, |
| 79 | 84 | TyKind::Array(..) => TyFingerprint::Array, |
| 80 | TyKind::Scalar(scalar) => TyFingerprint::Scalar(*scalar), | |
| 81 | TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(*adt), | |
| 82 | TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(*mutability), | |
| 83 | TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(*alias_id), | |
| 84 | TyKind::Dyn(_) => ty.dyn_trait().map(TyFingerprint::Dyn)?, | |
| 85 | TyKind::Bool => TyFingerprint::Bool, | |
| 86 | TyKind::Char => TyFingerprint::Char, | |
| 87 | TyKind::Int(int) => TyFingerprint::Int(int), | |
| 88 | TyKind::Uint(int) => TyFingerprint::Uint(int), | |
| 89 | TyKind::Float(float) => TyFingerprint::Float(float), | |
| 90 | TyKind::Adt(adt_def, _) => TyFingerprint::Adt(adt_def.def_id().0), | |
| 91 | TyKind::RawPtr(_, mutability) => TyFingerprint::RawPtr(mutability), | |
| 92 | TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(alias_id.0), | |
| 93 | TyKind::Dynamic(bounds, _) => { | |
| 94 | bounds.principal_def_id().map(|trait_| TyFingerprint::Dyn(trait_.0))? | |
| 95 | } | |
| 85 | 96 | _ => return None, |
| 86 | 97 | }; |
| 87 | 98 | Some(fp) |
| 88 | 99 | } |
| 89 | 100 | |
| 90 | 101 | /// Creates a TyFingerprint for looking up a trait impl. |
| 91 | pub fn for_trait_impl(ty: &Ty) -> Option<TyFingerprint> { | |
| 92 | let fp = match ty.kind(Interner) { | |
| 102 | pub fn for_trait_impl<'db>(ty: Ty<'db>) -> Option<TyFingerprint> { | |
| 103 | let fp = match ty.kind() { | |
| 93 | 104 | TyKind::Str => TyFingerprint::Str, |
| 94 | 105 | TyKind::Never => TyFingerprint::Never, |
| 95 | 106 | TyKind::Slice(..) => TyFingerprint::Slice, |
| 96 | 107 | TyKind::Array(..) => TyFingerprint::Array, |
| 97 | TyKind::Scalar(scalar) => TyFingerprint::Scalar(*scalar), | |
| 98 | TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(*adt), | |
| 99 | TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(*mutability), | |
| 100 | TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(*alias_id), | |
| 101 | TyKind::Dyn(_) => ty.dyn_trait().map(TyFingerprint::Dyn)?, | |
| 102 | TyKind::Ref(mutability, _, _) => TyFingerprint::Ref(*mutability), | |
| 103 | TyKind::Tuple(_, subst) => { | |
| 104 | let first_ty = subst.interned().first().map(|arg| arg.assert_ty_ref(Interner)); | |
| 108 | TyKind::Bool => TyFingerprint::Bool, | |
| 109 | TyKind::Char => TyFingerprint::Char, | |
| 110 | TyKind::Int(int) => TyFingerprint::Int(int), | |
| 111 | TyKind::Uint(int) => TyFingerprint::Uint(int), | |
| 112 | TyKind::Float(float) => TyFingerprint::Float(float), | |
| 113 | TyKind::Adt(adt_def, _) => TyFingerprint::Adt(adt_def.def_id().0), | |
| 114 | TyKind::RawPtr(_, mutability) => TyFingerprint::RawPtr(mutability), | |
| 115 | TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(alias_id.0), | |
| 116 | TyKind::Dynamic(bounds, _) => { | |
| 117 | bounds.principal_def_id().map(|trait_| TyFingerprint::Dyn(trait_.0))? | |
| 118 | } | |
| 119 | TyKind::Ref(_, _, mutability) => TyFingerprint::Ref(mutability), | |
| 120 | TyKind::Tuple(subst) => { | |
| 121 | let first_ty = subst.as_slice().first(); | |
| 105 | 122 | match first_ty { |
| 106 | Some(ty) => return TyFingerprint::for_trait_impl(ty), | |
| 123 | Some(ty) => return TyFingerprint::for_trait_impl(*ty), | |
| 107 | 124 | None => TyFingerprint::Unit, |
| 108 | 125 | } |
| 109 | 126 | } |
| 110 | TyKind::AssociatedType(_, _) | |
| 111 | 127 | // FIXME(next-solver): Putting `Alias` here is *probably* incorrect, AFAIK it should return `None`. But this breaks |
| 112 | 128 | // flyimport, which uses an incorrect but fast method resolution algorithm. Therefore we put it here, |
| 113 | 129 | // because this function is only called by flyimport, and anyway we should get rid of `TyFingerprint` |
| 114 | 130 | // and switch to `rustc_type_ir`'s `SimplifiedType`. |
| 115 | | TyKind::Alias(_) | |
| 116 | | TyKind::OpaqueType(_, _) | |
| 131 | TyKind::Alias(..) | |
| 117 | 132 | | TyKind::FnDef(_, _) |
| 118 | 133 | | TyKind::Closure(_, _) |
| 119 | 134 | | TyKind::Coroutine(..) |
| 135 | | TyKind::CoroutineClosure(..) | |
| 120 | 136 | | TyKind::CoroutineWitness(..) => TyFingerprint::Unnameable, |
| 121 | TyKind::Function(fn_ptr) => { | |
| 122 | TyFingerprint::Function(fn_ptr.substitution.0.len(Interner) as u32) | |
| 123 | } | |
| 124 | TyKind::Placeholder(_) | |
| 125 | | TyKind::BoundVar(_) | |
| 126 | | TyKind::InferenceVar(_, _) | |
| 127 | | TyKind::Error => return None, | |
| 128 | }; | |
| 129 | Some(fp) | |
| 130 | } | |
| 131 | ||
| 132 | /// Creates a TyFingerprint for looking up a trait impl. | |
| 133 | pub fn for_trait_impl_ns<'db>(ty: &next_solver::Ty<'db>) -> Option<TyFingerprint> { | |
| 134 | use rustc_type_ir::TyKind; | |
| 135 | let fp = match (*ty).kind() { | |
| 136 | TyKind::Str => TyFingerprint::Str, | |
| 137 | TyKind::Never => TyFingerprint::Never, | |
| 138 | TyKind::Slice(..) => TyFingerprint::Slice, | |
| 139 | TyKind::Array(..) => TyFingerprint::Array, | |
| 140 | TyKind::Int(int) => TyFingerprint::Scalar(Scalar::Int(match int { | |
| 141 | rustc_type_ir::IntTy::Isize => IntTy::Isize, | |
| 142 | rustc_type_ir::IntTy::I8 => IntTy::I8, | |
| 143 | rustc_type_ir::IntTy::I16 => IntTy::I16, | |
| 144 | rustc_type_ir::IntTy::I32 => IntTy::I32, | |
| 145 | rustc_type_ir::IntTy::I64 => IntTy::I64, | |
| 146 | rustc_type_ir::IntTy::I128 => IntTy::I128, | |
| 147 | })), | |
| 148 | TyKind::Uint(uint) => TyFingerprint::Scalar(Scalar::Uint(match uint { | |
| 149 | rustc_type_ir::UintTy::Usize => UintTy::Usize, | |
| 150 | rustc_type_ir::UintTy::U8 => UintTy::U8, | |
| 151 | rustc_type_ir::UintTy::U16 => UintTy::U16, | |
| 152 | rustc_type_ir::UintTy::U32 => UintTy::U32, | |
| 153 | rustc_type_ir::UintTy::U64 => UintTy::U64, | |
| 154 | rustc_type_ir::UintTy::U128 => UintTy::U128, | |
| 155 | })), | |
| 156 | TyKind::Float(float) => TyFingerprint::Scalar(Scalar::Float(match float { | |
| 157 | rustc_type_ir::FloatTy::F16 => FloatTy::F16, | |
| 158 | rustc_type_ir::FloatTy::F32 => FloatTy::F32, | |
| 159 | rustc_type_ir::FloatTy::F64 => FloatTy::F64, | |
| 160 | rustc_type_ir::FloatTy::F128 => FloatTy::F128, | |
| 161 | })), | |
| 162 | TyKind::Bool => TyFingerprint::Scalar(Scalar::Bool), | |
| 163 | TyKind::Char => TyFingerprint::Scalar(Scalar::Char), | |
| 164 | TyKind::Adt(def, _) => TyFingerprint::Adt(def.inner().id), | |
| 165 | TyKind::RawPtr(.., mutability) => match mutability { | |
| 166 | rustc_ast_ir::Mutability::Mut => TyFingerprint::RawPtr(Mutability::Mut), | |
| 167 | rustc_ast_ir::Mutability::Not => TyFingerprint::RawPtr(Mutability::Not), | |
| 168 | }, | |
| 169 | TyKind::Foreign(def) => TyFingerprint::ForeignType(crate::to_foreign_def_id(def.0)), | |
| 170 | TyKind::Dynamic(bounds, _) => { | |
| 171 | let trait_ref = bounds | |
| 172 | .as_slice() | |
| 173 | .iter() | |
| 174 | .map(|b| (*b).skip_binder()) | |
| 175 | .filter_map(|b| match b { | |
| 176 | rustc_type_ir::ExistentialPredicate::Trait(t) => Some(t.def_id), | |
| 177 | _ => None, | |
| 178 | }) | |
| 179 | .next()?; | |
| 180 | TyFingerprint::Dyn(trait_ref.0) | |
| 181 | } | |
| 182 | TyKind::Ref(_, _, mutability) => match mutability { | |
| 183 | rustc_ast_ir::Mutability::Mut => TyFingerprint::Ref(Mutability::Mut), | |
| 184 | rustc_ast_ir::Mutability::Not => TyFingerprint::Ref(Mutability::Not), | |
| 185 | }, | |
| 186 | TyKind::Tuple(tys) => { | |
| 187 | let first_ty = tys.as_slice().iter().next(); | |
| 188 | match first_ty { | |
| 189 | Some(ty) => return TyFingerprint::for_trait_impl_ns(ty), | |
| 190 | None => TyFingerprint::Unit, | |
| 191 | } | |
| 192 | } | |
| 193 | TyKind::FnDef(_, _) | |
| 194 | | TyKind::Closure(_, _) | |
| 195 | | TyKind::Coroutine(..) | |
| 196 | | TyKind::CoroutineWitness(..) | |
| 197 | | TyKind::Pat(..) | |
| 198 | | TyKind::CoroutineClosure(..) => TyFingerprint::Unnameable, | |
| 199 | 137 | TyKind::FnPtr(sig, _) => { |
| 200 | TyFingerprint::Function(sig.inputs().skip_binder().len() as u32) | |
| 138 | TyFingerprint::Function(sig.skip_binder().inputs_and_output.inner().len() as u32) | |
| 201 | 139 | } |
| 202 | TyKind::Alias(..) | |
| 203 | | TyKind::Placeholder(_) | |
| 140 | TyKind::Param(_) | |
| 204 | 141 | | TyKind::Bound(..) |
| 142 | | TyKind::Placeholder(..) | |
| 205 | 143 | | TyKind::Infer(_) |
| 206 | 144 | | TyKind::Error(_) |
| 207 | | TyKind::Param(..) | |
| 145 | | TyKind::Pat(..) | |
| 208 | 146 | | TyKind::UnsafeBinder(..) => return None, |
| 209 | 147 | }; |
| 210 | 148 | Some(fp) |
| ... | ... | @@ -212,25 +150,25 @@ impl TyFingerprint { |
| 212 | 150 | } |
| 213 | 151 | |
| 214 | 152 | pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [ |
| 215 | TyFingerprint::Scalar(Scalar::Int(IntTy::I8)), | |
| 216 | TyFingerprint::Scalar(Scalar::Int(IntTy::I16)), | |
| 217 | TyFingerprint::Scalar(Scalar::Int(IntTy::I32)), | |
| 218 | TyFingerprint::Scalar(Scalar::Int(IntTy::I64)), | |
| 219 | TyFingerprint::Scalar(Scalar::Int(IntTy::I128)), | |
| 220 | TyFingerprint::Scalar(Scalar::Int(IntTy::Isize)), | |
| 221 | TyFingerprint::Scalar(Scalar::Uint(UintTy::U8)), | |
| 222 | TyFingerprint::Scalar(Scalar::Uint(UintTy::U16)), | |
| 223 | TyFingerprint::Scalar(Scalar::Uint(UintTy::U32)), | |
| 224 | TyFingerprint::Scalar(Scalar::Uint(UintTy::U64)), | |
| 225 | TyFingerprint::Scalar(Scalar::Uint(UintTy::U128)), | |
| 226 | TyFingerprint::Scalar(Scalar::Uint(UintTy::Usize)), | |
| 153 | TyFingerprint::Int(IntTy::I8), | |
| 154 | TyFingerprint::Int(IntTy::I16), | |
| 155 | TyFingerprint::Int(IntTy::I32), | |
| 156 | TyFingerprint::Int(IntTy::I64), | |
| 157 | TyFingerprint::Int(IntTy::I128), | |
| 158 | TyFingerprint::Int(IntTy::Isize), | |
| 159 | TyFingerprint::Uint(UintTy::U8), | |
| 160 | TyFingerprint::Uint(UintTy::U16), | |
| 161 | TyFingerprint::Uint(UintTy::U32), | |
| 162 | TyFingerprint::Uint(UintTy::U64), | |
| 163 | TyFingerprint::Uint(UintTy::U128), | |
| 164 | TyFingerprint::Uint(UintTy::Usize), | |
| 227 | 165 | ]; |
| 228 | 166 | |
| 229 | 167 | pub(crate) const ALL_FLOAT_FPS: [TyFingerprint; 4] = [ |
| 230 | TyFingerprint::Scalar(Scalar::Float(FloatTy::F16)), | |
| 231 | TyFingerprint::Scalar(Scalar::Float(FloatTy::F32)), | |
| 232 | TyFingerprint::Scalar(Scalar::Float(FloatTy::F64)), | |
| 233 | TyFingerprint::Scalar(Scalar::Float(FloatTy::F128)), | |
| 168 | TyFingerprint::Float(FloatTy::F16), | |
| 169 | TyFingerprint::Float(FloatTy::F32), | |
| 170 | TyFingerprint::Float(FloatTy::F64), | |
| 171 | TyFingerprint::Float(FloatTy::F128), | |
| 234 | 172 | ]; |
| 235 | 173 | |
| 236 | 174 | type TraitFpMap = FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Box<[ImplId]>>>; |
| ... | ... | @@ -300,9 +238,8 @@ impl TraitImpls { |
| 300 | 238 | Some(tr) => tr.skip_binder().def_id.0, |
| 301 | 239 | None => continue, |
| 302 | 240 | }; |
| 303 | let interner = DbInterner::new_with(db, None, None); | |
| 304 | let self_ty = db.impl_self_ty(impl_id).instantiate_identity().to_chalk(interner); | |
| 305 | let self_ty_fp = TyFingerprint::for_trait_impl(&self_ty); | |
| 241 | let self_ty = db.impl_self_ty(impl_id); | |
| 242 | let self_ty_fp = TyFingerprint::for_trait_impl(self_ty.instantiate_identity()); | |
| 306 | 243 | map.entry(target_trait).or_default().entry(self_ty_fp).or_default().push(impl_id); |
| 307 | 244 | } |
| 308 | 245 | |
| ... | ... | @@ -415,8 +352,8 @@ impl InherentImpls { |
| 415 | 352 | continue; |
| 416 | 353 | } |
| 417 | 354 | |
| 418 | let interner = DbInterner::new_with(db, None, None); | |
| 419 | let self_ty = &db.impl_self_ty(impl_id).instantiate_identity().to_chalk(interner); | |
| 355 | let self_ty = db.impl_self_ty(impl_id); | |
| 356 | let self_ty = self_ty.instantiate_identity(); | |
| 420 | 357 | |
| 421 | 358 | match is_inherent_impl_coherent(db, def_map, impl_id, self_ty) { |
| 422 | 359 | true => { |
| ... | ... | @@ -440,7 +377,7 @@ impl InherentImpls { |
| 440 | 377 | } |
| 441 | 378 | } |
| 442 | 379 | |
| 443 | pub fn for_self_ty(&self, self_ty: &Ty) -> &[ImplId] { | |
| 380 | pub fn for_self_ty<'db>(&self, self_ty: Ty<'db>) -> &[ImplId] { | |
| 444 | 381 | match TyFingerprint::for_inherent_impl(self_ty) { |
| 445 | 382 | Some(fp) => self.map.get(&fp).map(|vec| vec.as_ref()).unwrap_or(&[]), |
| 446 | 383 | None => &[], |
| ... | ... | @@ -476,9 +413,14 @@ pub(crate) fn incoherent_inherent_impl_crates( |
| 476 | 413 | res |
| 477 | 414 | } |
| 478 | 415 | |
| 479 | pub fn def_crates(db: &dyn HirDatabase, ty: &Ty, cur_crate: Crate) -> Option<SmallVec<[Crate; 2]>> { | |
| 480 | match ty.kind(Interner) { | |
| 481 | &TyKind::Adt(AdtId(def_id), _) => { | |
| 416 | pub fn def_crates<'db>( | |
| 417 | db: &'db dyn HirDatabase, | |
| 418 | ty: Ty<'db>, | |
| 419 | cur_crate: Crate, | |
| 420 | ) -> Option<SmallVec<[Crate; 2]>> { | |
| 421 | match ty.kind() { | |
| 422 | TyKind::Adt(adt_def, _) => { | |
| 423 | let def_id = adt_def.def_id().0; | |
| 482 | 424 | let rustc_has_incoherent_inherent_impls = match def_id { |
| 483 | 425 | hir_def::AdtId::StructId(id) => db |
| 484 | 426 | .struct_signature(id) |
| ... | ... | @@ -499,22 +441,22 @@ pub fn def_crates(db: &dyn HirDatabase, ty: &Ty, cur_crate: Crate) -> Option<Sma |
| 499 | 441 | smallvec![def_id.module(db).krate()] |
| 500 | 442 | }) |
| 501 | 443 | } |
| 502 | &TyKind::Foreign(id) => { | |
| 503 | let alias = from_foreign_def_id(id); | |
| 444 | TyKind::Foreign(alias) => { | |
| 445 | let alias = alias.0; | |
| 504 | 446 | Some( |
| 505 | 447 | if db |
| 506 | 448 | .type_alias_signature(alias) |
| 507 | 449 | .flags |
| 508 | 450 | .contains(TypeAliasFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPL) |
| 509 | 451 | { |
| 510 | db.incoherent_inherent_impl_crates(cur_crate, TyFingerprint::ForeignType(id)) | |
| 452 | db.incoherent_inherent_impl_crates(cur_crate, TyFingerprint::ForeignType(alias)) | |
| 511 | 453 | } else { |
| 512 | 454 | smallvec![alias.module(db).krate()] |
| 513 | 455 | }, |
| 514 | 456 | ) |
| 515 | 457 | } |
| 516 | TyKind::Dyn(_) => { | |
| 517 | let trait_id = ty.dyn_trait()?; | |
| 458 | TyKind::Dynamic(bounds, _) => { | |
| 459 | let trait_id = bounds.principal_def_id()?.0; | |
| 518 | 460 | Some( |
| 519 | 461 | if db |
| 520 | 462 | .trait_signature(trait_id) |
| ... | ... | @@ -530,11 +472,15 @@ pub fn def_crates(db: &dyn HirDatabase, ty: &Ty, cur_crate: Crate) -> Option<Sma |
| 530 | 472 | // for primitives, there may be impls in various places (core and alloc |
| 531 | 473 | // mostly). We just check the whole crate graph for crates with impls |
| 532 | 474 | // (cached behind a query). |
| 533 | TyKind::Scalar(_) | |
| 475 | TyKind::Bool | |
| 476 | | TyKind::Char | |
| 477 | | TyKind::Int(_) | |
| 478 | | TyKind::Uint(_) | |
| 479 | | TyKind::Float(_) | |
| 534 | 480 | | TyKind::Str |
| 535 | 481 | | TyKind::Slice(_) |
| 536 | 482 | | TyKind::Array(..) |
| 537 | | TyKind::Raw(..) => Some(db.incoherent_inherent_impl_crates( | |
| 483 | | TyKind::RawPtr(..) => Some(db.incoherent_inherent_impl_crates( | |
| 538 | 484 | cur_crate, |
| 539 | 485 | TyFingerprint::for_inherent_impl(ty).expect("fingerprint for primitive"), |
| 540 | 486 | )), |
| ... | ... | @@ -545,7 +491,7 @@ pub fn def_crates(db: &dyn HirDatabase, ty: &Ty, cur_crate: Crate) -> Option<Sma |
| 545 | 491 | /// Look up the method with the given name. |
| 546 | 492 | pub(crate) fn lookup_method<'db>( |
| 547 | 493 | db: &'db dyn HirDatabase, |
| 548 | ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, | |
| 494 | ty: &Canonical<'db, Ty<'db>>, | |
| 549 | 495 | env: Arc<TraitEnvironment<'db>>, |
| 550 | 496 | traits_in_scope: &FxHashSet<TraitId>, |
| 551 | 497 | visible_from_module: VisibleFromModule, |
| ... | ... | @@ -626,23 +572,23 @@ pub struct ReceiverAdjustments { |
| 626 | 572 | } |
| 627 | 573 | |
| 628 | 574 | impl ReceiverAdjustments { |
| 629 | pub(crate) fn apply( | |
| 575 | pub(crate) fn apply<'db>( | |
| 630 | 576 | &self, |
| 631 | table: &mut InferenceTable<'_>, | |
| 632 | mut ty: Ty, | |
| 633 | ) -> (Ty, Vec<Adjustment>) { | |
| 577 | table: &mut InferenceTable<'db>, | |
| 578 | mut ty: Ty<'db>, | |
| 579 | ) -> (Ty<'db>, Vec<Adjustment<'db>>) { | |
| 634 | 580 | let mut adjust = Vec::new(); |
| 635 | let mut autoderef = table.autoderef(ty.to_nextsolver(table.interner)); | |
| 581 | let mut autoderef = table.autoderef(ty); | |
| 636 | 582 | autoderef.next(); |
| 637 | 583 | for _ in 0..self.autoderefs { |
| 638 | 584 | match autoderef.next() { |
| 639 | 585 | None => { |
| 640 | 586 | never!("autoderef not possible for {:?}", ty); |
| 641 | ty = TyKind::Error.intern(Interner); | |
| 587 | ty = Ty::new_error(table.interner(), ErrorGuaranteed); | |
| 642 | 588 | break; |
| 643 | 589 | } |
| 644 | 590 | Some((new_ty, _)) => { |
| 645 | ty = new_ty.to_chalk(autoderef.table.interner); | |
| 591 | ty = new_ty; | |
| 646 | 592 | let mutbl = match self.autoref { |
| 647 | 593 | Some(AutorefOrPtrAdjustment::Autoref(m)) => Some(m), |
| 648 | 594 | Some(AutorefOrPtrAdjustment::ToConstPtr) => Some(Mutability::Not), |
| ... | ... | @@ -654,26 +600,26 @@ impl ReceiverAdjustments { |
| 654 | 600 | AutoderefKind::Overloaded => Some(OverloadedDeref(mutbl)), |
| 655 | 601 | AutoderefKind::Builtin => None, |
| 656 | 602 | }), |
| 657 | target: ty.clone(), | |
| 603 | target: ty, | |
| 658 | 604 | }); |
| 659 | 605 | } |
| 660 | 606 | } |
| 661 | 607 | } |
| 662 | 608 | if let Some(autoref) = &self.autoref { |
| 663 | let lt = table.new_lifetime_var(); | |
| 609 | let lt = table.next_region_var(); | |
| 664 | 610 | match autoref { |
| 665 | 611 | AutorefOrPtrAdjustment::Autoref(m) => { |
| 666 | let a = Adjustment::borrow(*m, ty, lt); | |
| 667 | ty = a.target.clone(); | |
| 612 | let a = Adjustment::borrow(table.interner(), *m, ty, lt); | |
| 613 | ty = a.target; | |
| 668 | 614 | adjust.push(a); |
| 669 | 615 | } |
| 670 | 616 | AutorefOrPtrAdjustment::ToConstPtr => { |
| 671 | if let TyKind::Raw(Mutability::Mut, pointee) = ty.kind(Interner) { | |
| 617 | if let TyKind::RawPtr(pointee, Mutability::Mut) = ty.kind() { | |
| 672 | 618 | let a = Adjustment { |
| 673 | 619 | kind: Adjust::Pointer(PointerCast::MutToConstPointer), |
| 674 | target: TyKind::Raw(Mutability::Not, pointee.clone()).intern(Interner), | |
| 620 | target: Ty::new_ptr(table.interner(), pointee, Mutability::Not), | |
| 675 | 621 | }; |
| 676 | ty = a.target.clone(); | |
| 622 | ty = a.target; | |
| 677 | 623 | adjust.push(a); |
| 678 | 624 | } else { |
| 679 | 625 | never!("`ToConstPtr` target is not a raw mutable pointer"); |
| ... | ... | @@ -683,23 +629,20 @@ impl ReceiverAdjustments { |
| 683 | 629 | } |
| 684 | 630 | if self.unsize_array { |
| 685 | 631 | ty = 'it: { |
| 686 | if let TyKind::Ref(m, l, inner) = ty.kind(Interner) | |
| 687 | && let TyKind::Array(inner, _) = inner.kind(Interner) | |
| 632 | if let TyKind::Ref(l, inner, m) = ty.kind() | |
| 633 | && let TyKind::Array(inner, _) = inner.kind() | |
| 688 | 634 | { |
| 689 | break 'it TyKind::Ref( | |
| 690 | *m, | |
| 691 | l.clone(), | |
| 692 | TyKind::Slice(inner.clone()).intern(Interner), | |
| 693 | ) | |
| 694 | .intern(Interner); | |
| 635 | break 'it Ty::new_ref( | |
| 636 | table.interner(), | |
| 637 | l, | |
| 638 | Ty::new_slice(table.interner(), inner), | |
| 639 | m, | |
| 640 | ); | |
| 695 | 641 | } |
| 696 | 642 | // FIXME: report diagnostic if array unsizing happens without indirection. |
| 697 | 643 | ty |
| 698 | 644 | }; |
| 699 | adjust.push(Adjustment { | |
| 700 | kind: Adjust::Pointer(PointerCast::Unsize), | |
| 701 | target: ty.clone(), | |
| 702 | }); | |
| 645 | adjust.push(Adjustment { kind: Adjust::Pointer(PointerCast::Unsize), target: ty }); | |
| 703 | 646 | } |
| 704 | 647 | (ty, adjust) |
| 705 | 648 | } |
| ... | ... | @@ -713,7 +656,7 @@ impl ReceiverAdjustments { |
| 713 | 656 | // lifetime problems, because we need to borrow temp `CrateImplDefs`. |
| 714 | 657 | // FIXME add a context type here? |
| 715 | 658 | pub(crate) fn iterate_method_candidates<'db, T>( |
| 716 | ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, | |
| 659 | ty: &Canonical<'db, Ty<'db>>, | |
| 717 | 660 | db: &'db dyn HirDatabase, |
| 718 | 661 | env: Arc<TraitEnvironment<'db>>, |
| 719 | 662 | traits_in_scope: &FxHashSet<TraitId>, |
| ... | ... | @@ -744,17 +687,19 @@ pub(crate) fn iterate_method_candidates<'db, T>( |
| 744 | 687 | } |
| 745 | 688 | |
| 746 | 689 | pub fn lookup_impl_const<'db>( |
| 747 | db: &'db dyn HirDatabase, | |
| 690 | infcx: &InferCtxt<'db>, | |
| 748 | 691 | env: Arc<TraitEnvironment<'db>>, |
| 749 | 692 | const_id: ConstId, |
| 750 | subs: Substitution, | |
| 751 | ) -> (ConstId, Substitution) { | |
| 693 | subs: GenericArgs<'db>, | |
| 694 | ) -> (ConstId, GenericArgs<'db>) { | |
| 695 | let interner = infcx.interner; | |
| 696 | let db = interner.db; | |
| 697 | ||
| 752 | 698 | let trait_id = match const_id.lookup(db).container { |
| 753 | 699 | ItemContainerId::TraitId(id) => id, |
| 754 | 700 | _ => return (const_id, subs), |
| 755 | 701 | }; |
| 756 | let substitution = Substitution::from_iter(Interner, subs.iter(Interner)); | |
| 757 | let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution }; | |
| 702 | let trait_ref = TraitRef::new(interner, trait_id.into(), subs); | |
| 758 | 703 | |
| 759 | 704 | let const_signature = db.const_signature(const_id); |
| 760 | 705 | let name = match const_signature.name.as_ref() { |
| ... | ... | @@ -762,7 +707,7 @@ pub fn lookup_impl_const<'db>( |
| 762 | 707 | None => return (const_id, subs), |
| 763 | 708 | }; |
| 764 | 709 | |
| 765 | lookup_impl_assoc_item_for_trait_ref(trait_ref, db, env, name) | |
| 710 | lookup_impl_assoc_item_for_trait_ref(infcx, trait_ref, env, name) | |
| 766 | 711 | .and_then( |
| 767 | 712 | |assoc| if let (AssocItemId::ConstId(id), s) = assoc { Some((id, s)) } else { None }, |
| 768 | 713 | ) |
| ... | ... | @@ -772,37 +717,30 @@ pub fn lookup_impl_const<'db>( |
| 772 | 717 | /// Checks if the self parameter of `Trait` method is the `dyn Trait` and we should |
| 773 | 718 | /// call the method using the vtable. |
| 774 | 719 | pub fn is_dyn_method<'db>( |
| 775 | db: &'db dyn HirDatabase, | |
| 720 | interner: DbInterner<'db>, | |
| 776 | 721 | _env: Arc<TraitEnvironment<'db>>, |
| 777 | 722 | func: FunctionId, |
| 778 | fn_subst: Substitution, | |
| 723 | fn_subst: GenericArgs<'db>, | |
| 779 | 724 | ) -> Option<usize> { |
| 725 | let db = interner.db; | |
| 726 | ||
| 780 | 727 | let ItemContainerId::TraitId(trait_id) = func.lookup(db).container else { |
| 781 | 728 | return None; |
| 782 | 729 | }; |
| 783 | 730 | let trait_params = db.generic_params(trait_id.into()).len(); |
| 784 | let fn_params = fn_subst.len(Interner) - trait_params; | |
| 785 | let trait_ref = TraitRef { | |
| 786 | trait_id: to_chalk_trait_id(trait_id), | |
| 787 | substitution: Substitution::from_iter(Interner, fn_subst.iter(Interner).take(trait_params)), | |
| 788 | }; | |
| 789 | let self_ty = trait_ref.self_type_parameter(Interner); | |
| 790 | if let TyKind::Dyn(d) = self_ty.kind(Interner) { | |
| 731 | let fn_params = fn_subst.len() - trait_params; | |
| 732 | let trait_ref = TraitRef::new( | |
| 733 | interner, | |
| 734 | trait_id.into(), | |
| 735 | GenericArgs::new_from_iter(interner, fn_subst.iter().take(trait_params)), | |
| 736 | ); | |
| 737 | let self_ty = trait_ref.self_ty(); | |
| 738 | if let TyKind::Dynamic(d, _) = self_ty.kind() { | |
| 739 | // rustc doesn't accept `impl Foo<2> for dyn Foo<5>`, so if the trait id is equal, no matter | |
| 740 | // what the generics are, we are sure that the method is come from the vtable. | |
| 791 | 741 | let is_my_trait_in_bounds = d |
| 792 | .bounds | |
| 793 | .skip_binders() | |
| 794 | .as_slice(Interner) | |
| 795 | .iter() | |
| 796 | .map(|it| it.skip_binders()) | |
| 797 | .flat_map(|it| match it { | |
| 798 | WhereClause::Implemented(tr) => { | |
| 799 | all_super_traits(db, from_chalk_trait_id(tr.trait_id)) | |
| 800 | } | |
| 801 | _ => smallvec![], | |
| 802 | }) | |
| 803 | // rustc doesn't accept `impl Foo<2> for dyn Foo<5>`, so if the trait id is equal, no matter | |
| 804 | // what the generics are, we are sure that the method is come from the vtable. | |
| 805 | .any(|x| x == trait_id); | |
| 742 | .principal_def_id() | |
| 743 | .is_some_and(|trait_| all_super_traits(db, trait_.0).contains(&trait_id)); | |
| 806 | 744 | if is_my_trait_in_bounds { |
| 807 | 745 | return Some(fn_params); |
| 808 | 746 | } |
| ... | ... | @@ -817,20 +755,24 @@ pub(crate) fn lookup_impl_method_query<'db>( |
| 817 | 755 | db: &'db dyn HirDatabase, |
| 818 | 756 | env: Arc<TraitEnvironment<'db>>, |
| 819 | 757 | func: FunctionId, |
| 820 | fn_subst: Substitution, | |
| 821 | ) -> (FunctionId, Substitution) { | |
| 758 | fn_subst: GenericArgs<'db>, | |
| 759 | ) -> (FunctionId, GenericArgs<'db>) { | |
| 760 | let interner = DbInterner::new_with(db, Some(env.krate), env.block); | |
| 761 | let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); | |
| 762 | ||
| 822 | 763 | let ItemContainerId::TraitId(trait_id) = func.lookup(db).container else { |
| 823 | 764 | return (func, fn_subst); |
| 824 | 765 | }; |
| 825 | 766 | let trait_params = db.generic_params(trait_id.into()).len(); |
| 826 | let trait_ref = TraitRef { | |
| 827 | trait_id: to_chalk_trait_id(trait_id), | |
| 828 | substitution: Substitution::from_iter(Interner, fn_subst.iter(Interner).take(trait_params)), | |
| 829 | }; | |
| 767 | let trait_ref = TraitRef::new( | |
| 768 | interner, | |
| 769 | trait_id.into(), | |
| 770 | GenericArgs::new_from_iter(interner, fn_subst.iter().take(trait_params)), | |
| 771 | ); | |
| 830 | 772 | |
| 831 | 773 | let name = &db.function_signature(func).name; |
| 832 | 774 | let Some((impl_fn, impl_subst)) = |
| 833 | lookup_impl_assoc_item_for_trait_ref(trait_ref, db, env, name).and_then(|assoc| { | |
| 775 | lookup_impl_assoc_item_for_trait_ref(&infcx, trait_ref, env, name).and_then(|assoc| { | |
| 834 | 776 | if let (AssocItemId::FunctionId(id), subst) = assoc { Some((id, subst)) } else { None } |
| 835 | 777 | }) |
| 836 | 778 | else { |
| ... | ... | @@ -839,133 +781,109 @@ pub(crate) fn lookup_impl_method_query<'db>( |
| 839 | 781 | |
| 840 | 782 | ( |
| 841 | 783 | impl_fn, |
| 842 | Substitution::from_iter( | |
| 843 | Interner, | |
| 844 | impl_subst.iter(Interner).chain(fn_subst.iter(Interner).skip(trait_params)), | |
| 784 | GenericArgs::new_from_iter( | |
| 785 | interner, | |
| 786 | impl_subst.iter().chain(fn_subst.iter().skip(trait_params)), | |
| 845 | 787 | ), |
| 846 | 788 | ) |
| 847 | 789 | } |
| 848 | 790 | |
| 849 | 791 | fn lookup_impl_assoc_item_for_trait_ref<'db>( |
| 850 | trait_ref: TraitRef, | |
| 851 | db: &'db dyn HirDatabase, | |
| 792 | infcx: &InferCtxt<'db>, | |
| 793 | trait_ref: TraitRef<'db>, | |
| 852 | 794 | env: Arc<TraitEnvironment<'db>>, |
| 853 | 795 | name: &Name, |
| 854 | ) -> Option<(AssocItemId, Substitution)> { | |
| 855 | let hir_trait_id = trait_ref.hir_trait_id(); | |
| 856 | let self_ty = trait_ref.self_type_parameter(Interner); | |
| 857 | let self_ty_fp = TyFingerprint::for_trait_impl(&self_ty)?; | |
| 858 | let impls = db.trait_impls_in_deps(env.krate); | |
| 859 | ||
| 860 | let trait_module = hir_trait_id.module(db); | |
| 861 | let type_module = match self_ty_fp { | |
| 862 | TyFingerprint::Adt(adt_id) => Some(adt_id.module(db)), | |
| 863 | TyFingerprint::ForeignType(type_id) => Some(from_foreign_def_id(type_id).module(db)), | |
| 864 | TyFingerprint::Dyn(trait_id) => Some(trait_id.module(db)), | |
| 865 | _ => None, | |
| 866 | }; | |
| 867 | ||
| 868 | let def_blocks: ArrayVec<_, 2> = | |
| 869 | [trait_module.containing_block(), type_module.and_then(|it| it.containing_block())] | |
| 870 | .into_iter() | |
| 871 | .flatten() | |
| 872 | .filter_map(|block_id| db.trait_impls_in_block(block_id)) | |
| 873 | .collect(); | |
| 874 | ||
| 875 | let impls = impls | |
| 876 | .iter() | |
| 877 | .chain(&def_blocks) | |
| 878 | .flat_map(|impls| impls.for_trait_and_self_ty(hir_trait_id, self_ty_fp)); | |
| 879 | ||
| 880 | let table = InferenceTable::new(db, env); | |
| 881 | ||
| 882 | let (impl_data, impl_subst) = find_matching_impl(impls, table, trait_ref)?; | |
| 883 | let item = impl_data.items.iter().find_map(|(n, it)| match *it { | |
| 884 | AssocItemId::FunctionId(f) => (n == name).then_some(AssocItemId::FunctionId(f)), | |
| 885 | AssocItemId::ConstId(c) => (n == name).then_some(AssocItemId::ConstId(c)), | |
| 886 | AssocItemId::TypeAliasId(_) => None, | |
| 887 | })?; | |
| 796 | ) -> Option<(AssocItemId, GenericArgs<'db>)> { | |
| 797 | let (impl_id, impl_subst) = find_matching_impl(infcx, &env, trait_ref)?; | |
| 798 | let item = | |
| 799 | impl_id.impl_items(infcx.interner.db).items.iter().find_map(|(n, it)| match *it { | |
| 800 | AssocItemId::FunctionId(f) => (n == name).then_some(AssocItemId::FunctionId(f)), | |
| 801 | AssocItemId::ConstId(c) => (n == name).then_some(AssocItemId::ConstId(c)), | |
| 802 | AssocItemId::TypeAliasId(_) => None, | |
| 803 | })?; | |
| 888 | 804 | Some((item, impl_subst)) |
| 889 | 805 | } |
| 890 | 806 | |
| 891 | fn find_matching_impl( | |
| 892 | mut impls: impl Iterator<Item = ImplId>, | |
| 893 | mut table: InferenceTable<'_>, | |
| 894 | actual_trait_ref: TraitRef, | |
| 895 | ) -> Option<(&ImplItems, Substitution)> { | |
| 896 | let db = table.db; | |
| 897 | impls.find_map(|impl_| { | |
| 898 | table.run_in_snapshot(|table| { | |
| 899 | let impl_substs = | |
| 900 | TyBuilder::subst_for_def(db, impl_, None).fill_with_inference_vars(table).build(); | |
| 901 | let args: crate::next_solver::GenericArgs<'_> = | |
| 902 | impl_substs.to_nextsolver(table.interner); | |
| 903 | let trait_ref = db | |
| 904 | .impl_trait(impl_) | |
| 905 | .expect("non-trait method in find_matching_impl") | |
| 906 | .instantiate(table.interner, args) | |
| 907 | .to_chalk(table.interner); | |
| 908 | ||
| 909 | if !table.unify(&trait_ref, &actual_trait_ref) { | |
| 910 | return None; | |
| 911 | } | |
| 807 | pub(crate) fn find_matching_impl<'db>( | |
| 808 | infcx: &InferCtxt<'db>, | |
| 809 | env: &TraitEnvironment<'db>, | |
| 810 | trait_ref: TraitRef<'db>, | |
| 811 | ) -> Option<(ImplId, GenericArgs<'db>)> { | |
| 812 | let trait_ref = | |
| 813 | infcx.at(&ObligationCause::dummy(), env.env).deeply_normalize(trait_ref).ok()?; | |
| 912 | 814 | |
| 913 | let wcs = crate::chalk_db::convert_where_clauses(db, impl_.into(), &impl_substs) | |
| 914 | .into_iter() | |
| 915 | .map(|b| -> Goal { b.cast(Interner) }); | |
| 916 | for goal in wcs { | |
| 917 | let goal = goal.to_nextsolver(table.interner); | |
| 918 | if table.try_obligation(goal).no_solution() { | |
| 919 | return None; | |
| 920 | } | |
| 921 | table.register_obligation(goal); | |
| 922 | } | |
| 923 | Some(( | |
| 924 | impl_.impl_items(db), | |
| 925 | table.resolve_completely::<_, crate::next_solver::GenericArgs<'_>>(impl_substs), | |
| 926 | )) | |
| 927 | }) | |
| 928 | }) | |
| 815 | let obligation = Obligation::new(infcx.interner, ObligationCause::dummy(), env.env, trait_ref); | |
| 816 | ||
| 817 | let selection = infcx.select(&obligation).ok()??; | |
| 818 | ||
| 819 | // Currently, we use a fulfillment context to completely resolve | |
| 820 | // all nested obligations. This is because they can inform the | |
| 821 | // inference of the impl's type parameters. | |
| 822 | let mut ocx = ObligationCtxt::new(infcx); | |
| 823 | let impl_source = selection.map(|obligation| ocx.register_obligation(obligation)); | |
| 824 | ||
| 825 | let errors = ocx.evaluate_obligations_error_on_ambiguity(); | |
| 826 | if !errors.is_empty() { | |
| 827 | return None; | |
| 828 | } | |
| 829 | ||
| 830 | let impl_source = infcx.resolve_vars_if_possible(impl_source); | |
| 831 | if impl_source.has_non_region_infer() { | |
| 832 | return None; | |
| 833 | } | |
| 834 | ||
| 835 | match impl_source { | |
| 836 | ImplSource::UserDefined(impl_source) => Some((impl_source.impl_def_id, impl_source.args)), | |
| 837 | ImplSource::Param(_) | ImplSource::Builtin(..) => None, | |
| 838 | } | |
| 929 | 839 | } |
| 930 | 840 | |
| 931 | fn is_inherent_impl_coherent( | |
| 932 | db: &dyn HirDatabase, | |
| 841 | fn is_inherent_impl_coherent<'db>( | |
| 842 | db: &'db dyn HirDatabase, | |
| 933 | 843 | def_map: &DefMap, |
| 934 | 844 | impl_id: ImplId, |
| 935 | self_ty: &Ty, | |
| 845 | self_ty: Ty<'db>, | |
| 936 | 846 | ) -> bool { |
| 937 | let self_ty = self_ty.kind(Interner); | |
| 847 | let self_ty = self_ty.kind(); | |
| 938 | 848 | let impl_allowed = match self_ty { |
| 939 | TyKind::Tuple(_, _) | |
| 849 | TyKind::Tuple(_) | |
| 940 | 850 | | TyKind::FnDef(_, _) |
| 941 | 851 | | TyKind::Array(_, _) |
| 942 | 852 | | TyKind::Never |
| 943 | | TyKind::Raw(_, _) | |
| 853 | | TyKind::RawPtr(_, _) | |
| 944 | 854 | | TyKind::Ref(_, _, _) |
| 945 | 855 | | TyKind::Slice(_) |
| 946 | 856 | | TyKind::Str |
| 947 | | TyKind::Scalar(_) => def_map.is_rustc_coherence_is_core(), | |
| 857 | | TyKind::Bool | |
| 858 | | TyKind::Char | |
| 859 | | TyKind::Int(_) | |
| 860 | | TyKind::Uint(_) | |
| 861 | | TyKind::Float(_) => def_map.is_rustc_coherence_is_core(), | |
| 948 | 862 | |
| 949 | &TyKind::Adt(AdtId(adt), _) => adt.module(db).krate() == def_map.krate(), | |
| 950 | TyKind::Dyn(it) => it.principal_id().is_some_and(|trait_id| { | |
| 951 | from_chalk_trait_id(trait_id).module(db).krate() == def_map.krate() | |
| 952 | }), | |
| 863 | TyKind::Adt(adt_def, _) => adt_def.def_id().0.module(db).krate() == def_map.krate(), | |
| 864 | TyKind::Dynamic(it, _) => it | |
| 865 | .principal_def_id() | |
| 866 | .is_some_and(|trait_id| trait_id.0.module(db).krate() == def_map.krate()), | |
| 953 | 867 | |
| 954 | 868 | _ => true, |
| 955 | 869 | }; |
| 956 | 870 | impl_allowed || { |
| 957 | 871 | let rustc_has_incoherent_inherent_impls = match self_ty { |
| 958 | TyKind::Tuple(_, _) | |
| 872 | TyKind::Tuple(_) | |
| 959 | 873 | | TyKind::FnDef(_, _) |
| 960 | 874 | | TyKind::Array(_, _) |
| 961 | 875 | | TyKind::Never |
| 962 | | TyKind::Raw(_, _) | |
| 876 | | TyKind::RawPtr(_, _) | |
| 963 | 877 | | TyKind::Ref(_, _, _) |
| 964 | 878 | | TyKind::Slice(_) |
| 965 | 879 | | TyKind::Str |
| 966 | | TyKind::Scalar(_) => true, | |
| 880 | | TyKind::Bool | |
| 881 | | TyKind::Char | |
| 882 | | TyKind::Int(_) | |
| 883 | | TyKind::Uint(_) | |
| 884 | | TyKind::Float(_) => true, | |
| 967 | 885 | |
| 968 | &TyKind::Adt(AdtId(adt), _) => match adt { | |
| 886 | TyKind::Adt(adt_def, _) => match adt_def.def_id().0 { | |
| 969 | 887 | hir_def::AdtId::StructId(id) => db |
| 970 | 888 | .struct_signature(id) |
| 971 | 889 | .flags |
| ... | ... | @@ -979,8 +897,8 @@ fn is_inherent_impl_coherent( |
| 979 | 897 | .flags |
| 980 | 898 | .contains(EnumFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS), |
| 981 | 899 | }, |
| 982 | TyKind::Dyn(it) => it.principal_id().is_some_and(|trait_id| { | |
| 983 | db.trait_signature(from_chalk_trait_id(trait_id)) | |
| 900 | TyKind::Dynamic(it, _) => it.principal_def_id().is_some_and(|trait_id| { | |
| 901 | db.trait_signature(trait_id.0) | |
| 984 | 902 | .flags |
| 985 | 903 | .contains(TraitFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS) |
| 986 | 904 | }), |
| ... | ... | @@ -1012,8 +930,7 @@ fn is_inherent_impl_coherent( |
| 1012 | 930 | /// - All of |
| 1013 | 931 | /// - At least one of the types `T0..=Tn`` must be a local type. Let `Ti`` be the first such type. |
| 1014 | 932 | /// - No uncovered type parameters `P1..=Pn` may appear in `T0..Ti`` (excluding `Ti`) |
| 1015 | pub fn check_orphan_rules(db: &dyn HirDatabase, impl_: ImplId) -> bool { | |
| 1016 | let substs = TyBuilder::placeholder_subst(db, impl_); | |
| 933 | pub fn check_orphan_rules<'db>(db: &'db dyn HirDatabase, impl_: ImplId) -> bool { | |
| 1017 | 934 | let Some(impl_trait) = db.impl_trait(impl_) else { |
| 1018 | 935 | // not a trait impl |
| 1019 | 936 | return true; |
| ... | ... | @@ -1022,24 +939,25 @@ pub fn check_orphan_rules(db: &dyn HirDatabase, impl_: ImplId) -> bool { |
| 1022 | 939 | let local_crate = impl_.lookup(db).container.krate(); |
| 1023 | 940 | let is_local = |tgt_crate| tgt_crate == local_crate; |
| 1024 | 941 | |
| 1025 | let interner = DbInterner::new_with(db, None, None); | |
| 1026 | let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 1027 | let trait_ref = impl_trait.instantiate(interner, args).to_chalk(interner); | |
| 1028 | let trait_id = from_chalk_trait_id(trait_ref.trait_id); | |
| 942 | let trait_ref = impl_trait.instantiate_identity(); | |
| 943 | let trait_id = trait_ref.def_id.0; | |
| 1029 | 944 | if is_local(trait_id.module(db).krate()) { |
| 1030 | 945 | // trait to be implemented is local |
| 1031 | 946 | return true; |
| 1032 | 947 | } |
| 1033 | 948 | |
| 1034 | let unwrap_fundamental = |mut ty: Ty| { | |
| 949 | let unwrap_fundamental = |mut ty: Ty<'db>| { | |
| 1035 | 950 | // Unwrap all layers of fundamental types with a loop. |
| 1036 | 951 | loop { |
| 1037 | match ty.kind(Interner) { | |
| 1038 | TyKind::Ref(_, _, referenced) => ty = referenced.clone(), | |
| 1039 | &TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), ref subs) => { | |
| 952 | match ty.kind() { | |
| 953 | TyKind::Ref(_, referenced, _) => ty = referenced, | |
| 954 | TyKind::Adt(adt_def, subs) => { | |
| 955 | let AdtId::StructId(s) = adt_def.def_id().0 else { | |
| 956 | break ty; | |
| 957 | }; | |
| 1040 | 958 | let struct_signature = db.struct_signature(s); |
| 1041 | 959 | if struct_signature.flags.contains(StructFlags::FUNDAMENTAL) { |
| 1042 | let next = subs.type_parameters(Interner).next(); | |
| 960 | let next = subs.types().next(); | |
| 1043 | 961 | match next { |
| 1044 | 962 | Some(it) => ty = it, |
| 1045 | 963 | None => break ty, |
| ... | ... | @@ -1056,22 +974,20 @@ pub fn check_orphan_rules(db: &dyn HirDatabase, impl_: ImplId) -> bool { |
| 1056 | 974 | |
| 1057 | 975 | // FIXME: param coverage |
| 1058 | 976 | // - No uncovered type parameters `P1..=Pn` may appear in `T0..Ti`` (excluding `Ti`) |
| 1059 | let is_not_orphan = trait_ref.substitution.type_parameters(Interner).any(|ty| { | |
| 1060 | match unwrap_fundamental(ty).kind(Interner) { | |
| 1061 | &TyKind::Adt(AdtId(id), _) => is_local(id.module(db).krate()), | |
| 1062 | TyKind::Error => true, | |
| 1063 | TyKind::Dyn(it) => it | |
| 1064 | .principal_id() | |
| 1065 | .is_some_and(|trait_id| is_local(from_chalk_trait_id(trait_id).module(db).krate())), | |
| 1066 | _ => false, | |
| 977 | let is_not_orphan = trait_ref.args.types().any(|ty| match unwrap_fundamental(ty).kind() { | |
| 978 | TyKind::Adt(adt_def, _) => is_local(adt_def.def_id().0.module(db).krate()), | |
| 979 | TyKind::Error(_) => true, | |
| 980 | TyKind::Dynamic(it, _) => { | |
| 981 | it.principal_def_id().is_some_and(|trait_id| is_local(trait_id.0.module(db).krate())) | |
| 1067 | 982 | } |
| 983 | _ => false, | |
| 1068 | 984 | }); |
| 1069 | 985 | #[allow(clippy::let_and_return)] |
| 1070 | 986 | is_not_orphan |
| 1071 | 987 | } |
| 1072 | 988 | |
| 1073 | 989 | pub fn iterate_path_candidates<'db>( |
| 1074 | ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, | |
| 990 | ty: &Canonical<'db, Ty<'db>>, | |
| 1075 | 991 | db: &'db dyn HirDatabase, |
| 1076 | 992 | env: Arc<TraitEnvironment<'db>>, |
| 1077 | 993 | traits_in_scope: &FxHashSet<TraitId>, |
| ... | ... | @@ -1093,7 +1009,7 @@ pub fn iterate_path_candidates<'db>( |
| 1093 | 1009 | } |
| 1094 | 1010 | |
| 1095 | 1011 | pub fn iterate_method_candidates_dyn<'db>( |
| 1096 | ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, | |
| 1012 | ty: &Canonical<'db, Ty<'db>>, | |
| 1097 | 1013 | db: &'db dyn HirDatabase, |
| 1098 | 1014 | env: Arc<TraitEnvironment<'db>>, |
| 1099 | 1015 | traits_in_scope: &FxHashSet<TraitId>, |
| ... | ... | @@ -1132,7 +1048,7 @@ pub fn iterate_method_candidates_dyn<'db>( |
| 1132 | 1048 | // types*. |
| 1133 | 1049 | |
| 1134 | 1050 | let mut table = InferenceTable::new(db, env); |
| 1135 | let ty = table.instantiate_canonical_ns(*ty); | |
| 1051 | let ty = table.instantiate_canonical(*ty); | |
| 1136 | 1052 | let deref_chain = autoderef_method_receiver(&mut table, ty); |
| 1137 | 1053 | |
| 1138 | 1054 | deref_chain.into_iter().try_for_each(|(receiver_ty, adj)| { |
| ... | ... | @@ -1165,14 +1081,14 @@ pub fn iterate_method_candidates_dyn<'db>( |
| 1165 | 1081 | #[tracing::instrument(skip_all, fields(name = ?name))] |
| 1166 | 1082 | fn iterate_method_candidates_with_autoref<'db>( |
| 1167 | 1083 | table: &mut InferenceTable<'db>, |
| 1168 | receiver_ty: next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, | |
| 1084 | receiver_ty: Canonical<'db, Ty<'db>>, | |
| 1169 | 1085 | first_adjustment: ReceiverAdjustments, |
| 1170 | 1086 | traits_in_scope: &FxHashSet<TraitId>, |
| 1171 | 1087 | visible_from_module: VisibleFromModule, |
| 1172 | 1088 | name: Option<&Name>, |
| 1173 | 1089 | callback: &mut dyn MethodCandidateCallback, |
| 1174 | 1090 | ) -> ControlFlow<()> { |
| 1175 | let interner = table.interner; | |
| 1091 | let interner = table.interner(); | |
| 1176 | 1092 | |
| 1177 | 1093 | let mut iterate_method_candidates_by_receiver = move |receiver_ty, first_adjustment| { |
| 1178 | 1094 | iterate_method_candidates_by_receiver( |
| ... | ... | @@ -1187,11 +1103,7 @@ fn iterate_method_candidates_with_autoref<'db>( |
| 1187 | 1103 | }; |
| 1188 | 1104 | |
| 1189 | 1105 | let mut maybe_reborrowed = first_adjustment.clone(); |
| 1190 | if let rustc_type_ir::TyKind::Ref(_, _, m) = receiver_ty.value.kind() { | |
| 1191 | let m = match m { | |
| 1192 | rustc_ast_ir::Mutability::Mut => chalk_ir::Mutability::Mut, | |
| 1193 | rustc_ast_ir::Mutability::Not => chalk_ir::Mutability::Not, | |
| 1194 | }; | |
| 1106 | if let TyKind::Ref(_, _, m) = receiver_ty.value.kind() { | |
| 1195 | 1107 | // Prefer reborrow of references to move |
| 1196 | 1108 | maybe_reborrowed.autoref = Some(AutorefOrPtrAdjustment::Autoref(m)); |
| 1197 | 1109 | maybe_reborrowed.autoderefs += 1; |
| ... | ... | @@ -1199,15 +1111,10 @@ fn iterate_method_candidates_with_autoref<'db>( |
| 1199 | 1111 | |
| 1200 | 1112 | iterate_method_candidates_by_receiver(receiver_ty, maybe_reborrowed)?; |
| 1201 | 1113 | |
| 1202 | let refed = next_solver::Canonical { | |
| 1114 | let refed = Canonical { | |
| 1203 | 1115 | max_universe: receiver_ty.max_universe, |
| 1204 | 1116 | variables: receiver_ty.variables, |
| 1205 | value: next_solver::Ty::new_ref( | |
| 1206 | interner, | |
| 1207 | next_solver::Region::error(interner), | |
| 1208 | receiver_ty.value, | |
| 1209 | rustc_ast_ir::Mutability::Not, | |
| 1210 | ), | |
| 1117 | value: Ty::new_ref(interner, Region::error(interner), receiver_ty.value, Mutability::Not), | |
| 1211 | 1118 | }; |
| 1212 | 1119 | |
| 1213 | 1120 | iterate_method_candidates_by_receiver( |
| ... | ... | @@ -1215,15 +1122,10 @@ fn iterate_method_candidates_with_autoref<'db>( |
| 1215 | 1122 | first_adjustment.with_autoref(AutorefOrPtrAdjustment::Autoref(Mutability::Not)), |
| 1216 | 1123 | )?; |
| 1217 | 1124 | |
| 1218 | let ref_muted = next_solver::Canonical { | |
| 1125 | let ref_muted = Canonical { | |
| 1219 | 1126 | max_universe: receiver_ty.max_universe, |
| 1220 | 1127 | variables: receiver_ty.variables, |
| 1221 | value: next_solver::Ty::new_ref( | |
| 1222 | interner, | |
| 1223 | next_solver::Region::error(interner), | |
| 1224 | receiver_ty.value, | |
| 1225 | rustc_ast_ir::Mutability::Mut, | |
| 1226 | ), | |
| 1128 | value: Ty::new_ref(interner, Region::error(interner), receiver_ty.value, Mutability::Mut), | |
| 1227 | 1129 | }; |
| 1228 | 1130 | |
| 1229 | 1131 | iterate_method_candidates_by_receiver( |
| ... | ... | @@ -1231,12 +1133,10 @@ fn iterate_method_candidates_with_autoref<'db>( |
| 1231 | 1133 | first_adjustment.with_autoref(AutorefOrPtrAdjustment::Autoref(Mutability::Mut)), |
| 1232 | 1134 | )?; |
| 1233 | 1135 | |
| 1234 | if let rustc_type_ir::TyKind::RawPtr(ty, rustc_ast_ir::Mutability::Mut) = | |
| 1235 | receiver_ty.value.kind() | |
| 1236 | { | |
| 1136 | if let TyKind::RawPtr(ty, Mutability::Mut) = receiver_ty.value.kind() { | |
| 1237 | 1137 | let const_ptr_ty = rustc_type_ir::Canonical { |
| 1238 | 1138 | max_universe: rustc_type_ir::UniverseIndex::ZERO, |
| 1239 | value: next_solver::Ty::new_ptr(interner, ty, rustc_ast_ir::Mutability::Not), | |
| 1139 | value: Ty::new_ptr(interner, ty, Mutability::Not), | |
| 1240 | 1140 | variables: receiver_ty.variables, |
| 1241 | 1141 | }; |
| 1242 | 1142 | iterate_method_candidates_by_receiver( |
| ... | ... | @@ -1290,30 +1190,27 @@ where |
| 1290 | 1190 | #[tracing::instrument(skip_all, fields(name = ?name))] |
| 1291 | 1191 | fn iterate_method_candidates_by_receiver<'db>( |
| 1292 | 1192 | table: &mut InferenceTable<'db>, |
| 1293 | receiver_ty: next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, | |
| 1193 | receiver_ty: Canonical<'db, Ty<'db>>, | |
| 1294 | 1194 | receiver_adjustments: ReceiverAdjustments, |
| 1295 | 1195 | traits_in_scope: &FxHashSet<TraitId>, |
| 1296 | 1196 | visible_from_module: VisibleFromModule, |
| 1297 | 1197 | name: Option<&Name>, |
| 1298 | 1198 | callback: &mut dyn MethodCandidateCallback, |
| 1299 | 1199 | ) -> ControlFlow<()> { |
| 1300 | let interner = table.interner; | |
| 1301 | let receiver_ty = table.instantiate_canonical_ns(receiver_ty); | |
| 1302 | let receiver_ty: crate::Ty = receiver_ty.to_chalk(interner); | |
| 1200 | let receiver_ty = table.instantiate_canonical(receiver_ty); | |
| 1303 | 1201 | // We're looking for methods with *receiver* type receiver_ty. These could |
| 1304 | 1202 | // be found in any of the derefs of receiver_ty, so we have to go through |
| 1305 | 1203 | // that, including raw derefs. |
| 1306 | 1204 | table.run_in_snapshot(|table| { |
| 1307 | let mut autoderef = | |
| 1308 | autoderef::Autoderef::new_no_tracking(table, receiver_ty.to_nextsolver(interner)) | |
| 1309 | .include_raw_pointers() | |
| 1310 | .use_receiver_trait(); | |
| 1205 | let mut autoderef = autoderef::Autoderef::new_no_tracking(table, receiver_ty) | |
| 1206 | .include_raw_pointers() | |
| 1207 | .use_receiver_trait(); | |
| 1311 | 1208 | while let Some((self_ty, _)) = autoderef.next() { |
| 1312 | 1209 | iterate_inherent_methods( |
| 1313 | &self_ty.to_chalk(interner), | |
| 1210 | self_ty, | |
| 1314 | 1211 | autoderef.table, |
| 1315 | 1212 | name, |
| 1316 | Some(&receiver_ty), | |
| 1213 | Some(receiver_ty), | |
| 1317 | 1214 | Some(receiver_adjustments.clone()), |
| 1318 | 1215 | visible_from_module, |
| 1319 | 1216 | LookupMode::MethodCall, |
| ... | ... | @@ -1325,23 +1222,21 @@ fn iterate_method_candidates_by_receiver<'db>( |
| 1325 | 1222 | ControlFlow::Continue(()) |
| 1326 | 1223 | })?; |
| 1327 | 1224 | table.run_in_snapshot(|table| { |
| 1328 | let mut autoderef = | |
| 1329 | autoderef::Autoderef::new_no_tracking(table, receiver_ty.to_nextsolver(interner)) | |
| 1330 | .include_raw_pointers() | |
| 1331 | .use_receiver_trait(); | |
| 1225 | let mut autoderef = autoderef::Autoderef::new_no_tracking(table, receiver_ty) | |
| 1226 | .include_raw_pointers() | |
| 1227 | .use_receiver_trait(); | |
| 1332 | 1228 | while let Some((self_ty, _)) = autoderef.next() { |
| 1333 | if matches!(self_ty.kind(), crate::next_solver::TyKind::Infer(rustc_type_ir::TyVar(_))) | |
| 1334 | { | |
| 1229 | if matches!(self_ty.kind(), TyKind::Infer(rustc_type_ir::TyVar(_))) { | |
| 1335 | 1230 | // don't try to resolve methods on unknown types |
| 1336 | 1231 | return ControlFlow::Continue(()); |
| 1337 | 1232 | } |
| 1338 | 1233 | |
| 1339 | 1234 | iterate_trait_method_candidates( |
| 1340 | &self_ty.to_chalk(interner), | |
| 1235 | self_ty, | |
| 1341 | 1236 | autoderef.table, |
| 1342 | 1237 | traits_in_scope, |
| 1343 | 1238 | name, |
| 1344 | Some(&receiver_ty), | |
| 1239 | Some(receiver_ty), | |
| 1345 | 1240 | Some(receiver_adjustments.clone()), |
| 1346 | 1241 | LookupMode::MethodCall, |
| 1347 | 1242 | &mut |adjustments, item, is_visible| { |
| ... | ... | @@ -1355,7 +1250,7 @@ fn iterate_method_candidates_by_receiver<'db>( |
| 1355 | 1250 | |
| 1356 | 1251 | #[tracing::instrument(skip_all, fields(name = ?name))] |
| 1357 | 1252 | fn iterate_method_candidates_for_self_ty<'db>( |
| 1358 | self_ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, | |
| 1253 | self_ty: &Canonical<'db, Ty<'db>>, | |
| 1359 | 1254 | db: &'db dyn HirDatabase, |
| 1360 | 1255 | env: Arc<TraitEnvironment<'db>>, |
| 1361 | 1256 | traits_in_scope: &FxHashSet<TraitId>, |
| ... | ... | @@ -1364,9 +1259,9 @@ fn iterate_method_candidates_for_self_ty<'db>( |
| 1364 | 1259 | callback: &mut dyn MethodCandidateCallback, |
| 1365 | 1260 | ) -> ControlFlow<()> { |
| 1366 | 1261 | let mut table = InferenceTable::new(db, env); |
| 1367 | let self_ty = table.instantiate_canonical_ns(*self_ty).to_chalk(table.interner); | |
| 1262 | let self_ty = table.instantiate_canonical(*self_ty); | |
| 1368 | 1263 | iterate_inherent_methods( |
| 1369 | &self_ty, | |
| 1264 | self_ty, | |
| 1370 | 1265 | &mut table, |
| 1371 | 1266 | name, |
| 1372 | 1267 | None, |
| ... | ... | @@ -1378,7 +1273,7 @@ fn iterate_method_candidates_for_self_ty<'db>( |
| 1378 | 1273 | }, |
| 1379 | 1274 | )?; |
| 1380 | 1275 | iterate_trait_method_candidates( |
| 1381 | &self_ty, | |
| 1276 | self_ty, | |
| 1382 | 1277 | &mut table, |
| 1383 | 1278 | traits_in_scope, |
| 1384 | 1279 | name, |
| ... | ... | @@ -1392,19 +1287,19 @@ fn iterate_method_candidates_for_self_ty<'db>( |
| 1392 | 1287 | } |
| 1393 | 1288 | |
| 1394 | 1289 | #[tracing::instrument(skip_all, fields(name = ?name, visible_from_module, receiver_ty))] |
| 1395 | fn iterate_trait_method_candidates( | |
| 1396 | self_ty: &Ty, | |
| 1397 | table: &mut InferenceTable<'_>, | |
| 1290 | fn iterate_trait_method_candidates<'db>( | |
| 1291 | self_ty: Ty<'db>, | |
| 1292 | table: &mut InferenceTable<'db>, | |
| 1398 | 1293 | traits_in_scope: &FxHashSet<TraitId>, |
| 1399 | 1294 | name: Option<&Name>, |
| 1400 | receiver_ty: Option<&Ty>, | |
| 1295 | receiver_ty: Option<Ty<'db>>, | |
| 1401 | 1296 | receiver_adjustments: Option<ReceiverAdjustments>, |
| 1402 | 1297 | mode: LookupMode, |
| 1403 | 1298 | callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, |
| 1404 | 1299 | ) -> ControlFlow<()> { |
| 1405 | 1300 | let db = table.db; |
| 1406 | 1301 | |
| 1407 | let canonical_self_ty = table.canonicalize(self_ty.clone().to_nextsolver(table.interner)); | |
| 1302 | let canonical_self_ty = table.canonicalize(self_ty); | |
| 1408 | 1303 | let krate = table.trait_env.krate; |
| 1409 | 1304 | |
| 1410 | 1305 | 'traits: for &t in traits_in_scope { |
| ... | ... | @@ -1416,7 +1311,7 @@ fn iterate_trait_method_candidates( |
| 1416 | 1311 | // This is to make `[a].into_iter()` not break code with the new `IntoIterator` impl for |
| 1417 | 1312 | // arrays. |
| 1418 | 1313 | if data.flags.contains(TraitFlags::SKIP_ARRAY_DURING_METHOD_DISPATCH) |
| 1419 | && matches!(self_ty.kind(Interner), TyKind::Array(..)) | |
| 1314 | && matches!(self_ty.kind(), TyKind::Array(..)) | |
| 1420 | 1315 | { |
| 1421 | 1316 | // FIXME: this should really be using the edition of the method name's span, in case it |
| 1422 | 1317 | // comes from a macro |
| ... | ... | @@ -1426,9 +1321,9 @@ fn iterate_trait_method_candidates( |
| 1426 | 1321 | } |
| 1427 | 1322 | if data.flags.contains(TraitFlags::SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH) |
| 1428 | 1323 | && matches!( |
| 1429 | self_ty.kind(Interner), TyKind::Adt(AdtId(def), subst) | |
| 1430 | if is_box(table.db, *def) | |
| 1431 | && matches!(subst.at(Interner, 0).assert_ty_ref(Interner).kind(Interner), TyKind::Slice(..)) | |
| 1324 | self_ty.kind(), TyKind::Adt(adt_def, subst) | |
| 1325 | if is_box(table.db, adt_def.def_id().0) | |
| 1326 | && matches!(subst.type_at(0).kind(), TyKind::Slice(..)) | |
| 1432 | 1327 | ) |
| 1433 | 1328 | { |
| 1434 | 1329 | // FIXME: this should really be using the edition of the method name's span, in case it |
| ... | ... | @@ -1472,11 +1367,11 @@ fn iterate_trait_method_candidates( |
| 1472 | 1367 | } |
| 1473 | 1368 | |
| 1474 | 1369 | #[tracing::instrument(skip_all, fields(name = ?name, visible_from_module, receiver_ty))] |
| 1475 | fn iterate_inherent_methods( | |
| 1476 | self_ty: &Ty, | |
| 1477 | table: &mut InferenceTable<'_>, | |
| 1370 | fn iterate_inherent_methods<'db>( | |
| 1371 | self_ty: Ty<'db>, | |
| 1372 | table: &mut InferenceTable<'db>, | |
| 1478 | 1373 | name: Option<&Name>, |
| 1479 | receiver_ty: Option<&Ty>, | |
| 1374 | receiver_ty: Option<Ty<'db>>, | |
| 1480 | 1375 | receiver_adjustments: Option<ReceiverAdjustments>, |
| 1481 | 1376 | visible_from_module: VisibleFromModule, |
| 1482 | 1377 | mode: LookupMode, |
| ... | ... | @@ -1489,12 +1384,11 @@ fn iterate_inherent_methods( |
| 1489 | 1384 | // its super traits are considered inherent methods. This matters because these methods have |
| 1490 | 1385 | // higher priority than the other traits' methods, which would be considered in |
| 1491 | 1386 | // `iterate_trait_method_candidates()` only after this function. |
| 1492 | match self_ty.kind(Interner) { | |
| 1493 | TyKind::Placeholder(_) => { | |
| 1387 | match self_ty.kind() { | |
| 1388 | TyKind::Param(_) => { | |
| 1494 | 1389 | let env = table.trait_env.clone(); |
| 1495 | let traits = env | |
| 1496 | .traits_in_scope_from_clauses(self_ty.clone()) | |
| 1497 | .flat_map(|t| all_super_traits(db, t)); | |
| 1390 | let traits = | |
| 1391 | env.traits_in_scope_from_clauses(self_ty).flat_map(|t| all_super_traits(db, t)); | |
| 1498 | 1392 | iterate_inherent_trait_methods( |
| 1499 | 1393 | self_ty, |
| 1500 | 1394 | table, |
| ... | ... | @@ -1506,9 +1400,9 @@ fn iterate_inherent_methods( |
| 1506 | 1400 | mode, |
| 1507 | 1401 | )?; |
| 1508 | 1402 | } |
| 1509 | TyKind::Dyn(_) => { | |
| 1510 | if let Some(principal_trait) = self_ty.dyn_trait() { | |
| 1511 | let traits = all_super_traits(db, principal_trait); | |
| 1403 | TyKind::Dynamic(bounds, _) => { | |
| 1404 | if let Some(principal_trait) = bounds.principal_def_id() { | |
| 1405 | let traits = all_super_traits(db, principal_trait.0); | |
| 1512 | 1406 | iterate_inherent_trait_methods( |
| 1513 | 1407 | self_ty, |
| 1514 | 1408 | table, |
| ... | ... | @@ -1568,11 +1462,11 @@ fn iterate_inherent_methods( |
| 1568 | 1462 | return ControlFlow::Continue(()); |
| 1569 | 1463 | |
| 1570 | 1464 | #[tracing::instrument(skip_all, fields(name = ?name, visible_from_module, receiver_ty))] |
| 1571 | fn iterate_inherent_trait_methods( | |
| 1572 | self_ty: &Ty, | |
| 1573 | table: &mut InferenceTable<'_>, | |
| 1465 | fn iterate_inherent_trait_methods<'db>( | |
| 1466 | self_ty: Ty<'db>, | |
| 1467 | table: &mut InferenceTable<'db>, | |
| 1574 | 1468 | name: Option<&Name>, |
| 1575 | receiver_ty: Option<&Ty>, | |
| 1469 | receiver_ty: Option<Ty<'db>>, | |
| 1576 | 1470 | receiver_adjustments: Option<ReceiverAdjustments>, |
| 1577 | 1471 | callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, |
| 1578 | 1472 | traits: impl Iterator<Item = TraitId>, |
| ... | ... | @@ -1603,12 +1497,12 @@ fn iterate_inherent_methods( |
| 1603 | 1497 | } |
| 1604 | 1498 | |
| 1605 | 1499 | #[tracing::instrument(skip_all, fields(name = ?name, visible_from_module, receiver_ty))] |
| 1606 | fn impls_for_self_ty( | |
| 1500 | fn impls_for_self_ty<'db>( | |
| 1607 | 1501 | impls: &InherentImpls, |
| 1608 | self_ty: &Ty, | |
| 1609 | table: &mut InferenceTable<'_>, | |
| 1502 | self_ty: Ty<'db>, | |
| 1503 | table: &mut InferenceTable<'db>, | |
| 1610 | 1504 | name: Option<&Name>, |
| 1611 | receiver_ty: Option<&Ty>, | |
| 1505 | receiver_ty: Option<Ty<'db>>, | |
| 1612 | 1506 | receiver_adjustments: Option<ReceiverAdjustments>, |
| 1613 | 1507 | visible_from_module: Option<ModuleId>, |
| 1614 | 1508 | callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, |
| ... | ... | @@ -1639,10 +1533,10 @@ fn iterate_inherent_methods( |
| 1639 | 1533 | /// Returns the receiver type for the index trait call. |
| 1640 | 1534 | pub(crate) fn resolve_indexing_op<'db>( |
| 1641 | 1535 | table: &mut InferenceTable<'db>, |
| 1642 | ty: next_solver::Canonical<'db, next_solver::Ty<'db>>, | |
| 1536 | ty: Canonical<'db, Ty<'db>>, | |
| 1643 | 1537 | index_trait: TraitId, |
| 1644 | 1538 | ) -> Option<ReceiverAdjustments> { |
| 1645 | let ty = table.instantiate_canonical_ns(ty); | |
| 1539 | let ty = table.instantiate_canonical(ty); | |
| 1646 | 1540 | let deref_chain = autoderef_method_receiver(table, ty); |
| 1647 | 1541 | for (ty, adj) in deref_chain { |
| 1648 | 1542 | let goal = generic_implements_goal_ns(table, index_trait, ty); |
| ... | ... | @@ -1670,10 +1564,10 @@ enum IsValidCandidate { |
| 1670 | 1564 | } |
| 1671 | 1565 | |
| 1672 | 1566 | #[tracing::instrument(skip_all, fields(name))] |
| 1673 | fn is_valid_impl_method_candidate( | |
| 1674 | table: &mut InferenceTable<'_>, | |
| 1675 | self_ty: &Ty, | |
| 1676 | receiver_ty: Option<&Ty>, | |
| 1567 | fn is_valid_impl_method_candidate<'db>( | |
| 1568 | table: &mut InferenceTable<'db>, | |
| 1569 | self_ty: Ty<'db>, | |
| 1570 | receiver_ty: Option<Ty<'db>>, | |
| 1677 | 1571 | visible_from_module: Option<ModuleId>, |
| 1678 | 1572 | name: Option<&Name>, |
| 1679 | 1573 | impl_id: ImplId, |
| ... | ... | @@ -1705,9 +1599,8 @@ fn is_valid_impl_method_candidate( |
| 1705 | 1599 | let self_ty_matches = table.run_in_snapshot(|table| { |
| 1706 | 1600 | let expected_self_ty = TyBuilder::impl_self_ty(db, impl_id) |
| 1707 | 1601 | .fill_with_inference_vars(table) |
| 1708 | .build(DbInterner::conjure()) | |
| 1709 | .to_chalk(DbInterner::conjure()); | |
| 1710 | table.unify(&expected_self_ty, self_ty) | |
| 1602 | .build(table.interner()); | |
| 1603 | table.unify(expected_self_ty, self_ty) | |
| 1711 | 1604 | }); |
| 1712 | 1605 | if !self_ty_matches { |
| 1713 | 1606 | cov_mark::hit!(const_candidate_self_type_mismatch); |
| ... | ... | @@ -1721,13 +1614,13 @@ fn is_valid_impl_method_candidate( |
| 1721 | 1614 | |
| 1722 | 1615 | /// Checks whether a given `AssocItemId` is applicable for `receiver_ty`. |
| 1723 | 1616 | #[tracing::instrument(skip_all, fields(name))] |
| 1724 | fn is_valid_trait_method_candidate( | |
| 1725 | table: &mut InferenceTable<'_>, | |
| 1617 | fn is_valid_trait_method_candidate<'db>( | |
| 1618 | table: &mut InferenceTable<'db>, | |
| 1726 | 1619 | trait_id: TraitId, |
| 1727 | 1620 | name: Option<&Name>, |
| 1728 | receiver_ty: Option<&Ty>, | |
| 1621 | receiver_ty: Option<Ty<'db>>, | |
| 1729 | 1622 | item: AssocItemId, |
| 1730 | self_ty: &Ty, | |
| 1623 | self_ty: Ty<'db>, | |
| 1731 | 1624 | mode: LookupMode, |
| 1732 | 1625 | ) -> IsValidCandidate { |
| 1733 | 1626 | let db = table.db; |
| ... | ... | @@ -1738,27 +1631,20 @@ fn is_valid_trait_method_candidate( |
| 1738 | 1631 | check_that!(name.is_none_or(|n| n == &data.name)); |
| 1739 | 1632 | |
| 1740 | 1633 | table.run_in_snapshot(|table| { |
| 1741 | let impl_subst = TyBuilder::subst_for_def(db, trait_id, None) | |
| 1742 | .fill_with_inference_vars(table) | |
| 1743 | .build(); | |
| 1744 | let expect_self_ty = impl_subst.at(Interner, 0).assert_ty_ref(Interner).clone(); | |
| 1634 | let impl_subst = table.fresh_args_for_item(trait_id.into()); | |
| 1635 | let expect_self_ty = impl_subst.type_at(0); | |
| 1745 | 1636 | |
| 1746 | check_that!(table.unify(&expect_self_ty, self_ty)); | |
| 1637 | check_that!(table.unify(expect_self_ty, self_ty)); | |
| 1747 | 1638 | |
| 1748 | 1639 | if let Some(receiver_ty) = receiver_ty { |
| 1749 | 1640 | check_that!(data.has_self_param()); |
| 1750 | 1641 | |
| 1751 | let fn_subst = TyBuilder::subst_for_def(db, fn_id, Some(impl_subst)) | |
| 1752 | .fill_with_inference_vars(table) | |
| 1753 | .build(); | |
| 1642 | let args = table.fill_rest_fresh_args(fn_id.into(), impl_subst); | |
| 1754 | 1643 | |
| 1755 | let args: crate::next_solver::GenericArgs<'_> = | |
| 1756 | fn_subst.to_nextsolver(table.interner); | |
| 1757 | 1644 | let sig = db.callable_item_signature(fn_id.into()); |
| 1758 | 1645 | let expected_receiver = sig |
| 1759 | 1646 | .map_bound(|s| s.skip_binder().inputs_and_output.as_slice()[0]) |
| 1760 | .instantiate(table.interner, args) | |
| 1761 | .to_chalk(table.interner); | |
| 1647 | .instantiate(table.interner(), args); | |
| 1762 | 1648 | |
| 1763 | 1649 | // FIXME: Clean up this mess with some context struct like rustc's `ProbeContext` |
| 1764 | 1650 | let variance = match mode { |
| ... | ... | @@ -1767,16 +1653,8 @@ fn is_valid_trait_method_candidate( |
| 1767 | 1653 | }; |
| 1768 | 1654 | let res = table |
| 1769 | 1655 | .infer_ctxt |
| 1770 | .at( | |
| 1771 | &next_solver::infer::traits::ObligationCause::dummy(), | |
| 1772 | table.trait_env.env, | |
| 1773 | ) | |
| 1774 | .relate( | |
| 1775 | DefineOpaqueTypes::No, | |
| 1776 | expected_receiver.to_nextsolver(table.interner), | |
| 1777 | variance, | |
| 1778 | receiver_ty.to_nextsolver(table.interner), | |
| 1779 | ); | |
| 1656 | .at(&ObligationCause::dummy(), table.trait_env.env) | |
| 1657 | .relate(DefineOpaqueTypes::No, expected_receiver, variance, receiver_ty); | |
| 1780 | 1658 | let Ok(infer_ok) = res else { |
| 1781 | 1659 | return IsValidCandidate::No; |
| 1782 | 1660 | }; |
| ... | ... | @@ -1788,7 +1666,7 @@ fn is_valid_trait_method_candidate( |
| 1788 | 1666 | check_that!(ctxt.try_evaluate_obligations().is_empty()); |
| 1789 | 1667 | } |
| 1790 | 1668 | |
| 1791 | check_that!(table.unify(receiver_ty, &expected_receiver)); | |
| 1669 | check_that!(table.unify(receiver_ty, expected_receiver)); | |
| 1792 | 1670 | } |
| 1793 | 1671 | |
| 1794 | 1672 | IsValidCandidate::Yes |
| ... | ... | @@ -1805,13 +1683,13 @@ fn is_valid_trait_method_candidate( |
| 1805 | 1683 | } |
| 1806 | 1684 | |
| 1807 | 1685 | #[tracing::instrument(skip_all, fields(name))] |
| 1808 | fn is_valid_impl_fn_candidate( | |
| 1809 | table: &mut InferenceTable<'_>, | |
| 1686 | fn is_valid_impl_fn_candidate<'db>( | |
| 1687 | table: &mut InferenceTable<'db>, | |
| 1810 | 1688 | impl_id: ImplId, |
| 1811 | 1689 | fn_id: FunctionId, |
| 1812 | 1690 | name: Option<&Name>, |
| 1813 | receiver_ty: Option<&Ty>, | |
| 1814 | self_ty: &Ty, | |
| 1691 | receiver_ty: Option<Ty<'db>>, | |
| 1692 | self_ty: Ty<'db>, | |
| 1815 | 1693 | visible_from_module: Option<ModuleId>, |
| 1816 | 1694 | item_name: &Name, |
| 1817 | 1695 | ) -> IsValidCandidate { |
| ... | ... | @@ -1829,34 +1707,28 @@ fn is_valid_impl_fn_candidate( |
| 1829 | 1707 | table.run_in_snapshot(|table| { |
| 1830 | 1708 | let _p = tracing::info_span!("subst_for_def").entered(); |
| 1831 | 1709 | let impl_subst = table.infer_ctxt.fresh_args_for_item(impl_id.into()); |
| 1832 | let expect_self_ty = db | |
| 1833 | .impl_self_ty(impl_id) | |
| 1834 | .instantiate(table.interner, &impl_subst) | |
| 1835 | .to_chalk(table.interner); | |
| 1710 | let expect_self_ty = db.impl_self_ty(impl_id).instantiate(table.interner(), &impl_subst); | |
| 1836 | 1711 | |
| 1837 | check_that!(table.unify(&expect_self_ty, self_ty)); | |
| 1712 | check_that!(table.unify(expect_self_ty, self_ty)); | |
| 1838 | 1713 | |
| 1839 | 1714 | if let Some(receiver_ty) = receiver_ty { |
| 1840 | 1715 | let _p = tracing::info_span!("check_receiver_ty").entered(); |
| 1841 | 1716 | check_that!(data.has_self_param()); |
| 1842 | 1717 | |
| 1843 | let fn_subst: crate::Substitution = | |
| 1844 | table.infer_ctxt.fresh_args_for_item(fn_id.into()).to_chalk(table.interner); | |
| 1718 | let args = table.infer_ctxt.fresh_args_for_item(fn_id.into()); | |
| 1845 | 1719 | |
| 1846 | let args: crate::next_solver::GenericArgs<'_> = fn_subst.to_nextsolver(table.interner); | |
| 1847 | 1720 | let sig = db.callable_item_signature(fn_id.into()); |
| 1848 | 1721 | let expected_receiver = sig |
| 1849 | 1722 | .map_bound(|s| s.skip_binder().inputs_and_output.as_slice()[0]) |
| 1850 | .instantiate(table.interner, args) | |
| 1851 | .to_chalk(table.interner); | |
| 1723 | .instantiate(table.interner(), args); | |
| 1852 | 1724 | |
| 1853 | check_that!(table.unify(receiver_ty, &expected_receiver)); | |
| 1725 | check_that!(table.unify(receiver_ty, expected_receiver)); | |
| 1854 | 1726 | } |
| 1855 | 1727 | |
| 1856 | 1728 | // We need to consider the bounds on the impl to distinguish functions of the same name |
| 1857 | 1729 | // for a type. |
| 1858 | 1730 | let predicates = db.generic_predicates_ns(impl_id.into()); |
| 1859 | let Some(predicates) = predicates.instantiate(table.interner, impl_subst) else { | |
| 1731 | let Some(predicates) = predicates.instantiate(table.interner(), impl_subst) else { | |
| 1860 | 1732 | return IsValidCandidate::Yes; |
| 1861 | 1733 | }; |
| 1862 | 1734 | |
| ... | ... | @@ -1864,7 +1736,7 @@ fn is_valid_impl_fn_candidate( |
| 1864 | 1736 | |
| 1865 | 1737 | ctxt.register_obligations(predicates.into_iter().map(|p| { |
| 1866 | 1738 | PredicateObligation::new( |
| 1867 | table.interner, | |
| 1739 | table.interner(), | |
| 1868 | 1740 | ObligationCause::new(), |
| 1869 | 1741 | table.trait_env.env, |
| 1870 | 1742 | p.0, |
| ... | ... | @@ -1879,73 +1751,29 @@ fn is_valid_impl_fn_candidate( |
| 1879 | 1751 | }) |
| 1880 | 1752 | } |
| 1881 | 1753 | |
| 1882 | pub fn implements_trait_unique<'db>( | |
| 1883 | ty: &Canonical<Ty>, | |
| 1884 | db: &'db dyn HirDatabase, | |
| 1885 | env: &TraitEnvironment<'db>, | |
| 1886 | trait_: TraitId, | |
| 1887 | ) -> bool { | |
| 1888 | let goal = generic_implements_goal(db, env, trait_, ty); | |
| 1889 | db.trait_solve(env.krate, env.block, goal.cast(Interner)).certain() | |
| 1890 | } | |
| 1891 | ||
| 1892 | /// This creates Substs for a trait with the given Self type and type variables | |
| 1893 | /// for all other parameters, to query next solver with it. | |
| 1894 | #[tracing::instrument(skip_all)] | |
| 1895 | fn generic_implements_goal<'db>( | |
| 1896 | db: &'db dyn HirDatabase, | |
| 1897 | env: &TraitEnvironment<'db>, | |
| 1898 | trait_: TraitId, | |
| 1899 | self_ty: &Canonical<Ty>, | |
| 1900 | ) -> Canonical<InEnvironment<super::DomainGoal>> { | |
| 1901 | let binders = self_ty.binders.interned(); | |
| 1902 | let trait_ref = TyBuilder::trait_ref(db, trait_) | |
| 1903 | .push(self_ty.value.clone()) | |
| 1904 | .fill_with_bound_vars(DebruijnIndex::INNERMOST, binders.len()) | |
| 1905 | .build(); | |
| 1906 | ||
| 1907 | let kinds = | |
| 1908 | binders.iter().cloned().chain(trait_ref.substitution.iter(Interner).skip(1).map(|it| { | |
| 1909 | let vk = match it.data(Interner) { | |
| 1910 | GenericArgData::Ty(_) => VariableKind::Ty(chalk_ir::TyVariableKind::General), | |
| 1911 | GenericArgData::Lifetime(_) => VariableKind::Lifetime, | |
| 1912 | GenericArgData::Const(c) => VariableKind::Const(c.data(Interner).ty.clone()), | |
| 1913 | }; | |
| 1914 | WithKind::new(vk, UniverseIndex::ROOT) | |
| 1915 | })); | |
| 1916 | let binders = CanonicalVarKinds::from_iter(Interner, kinds); | |
| 1917 | ||
| 1918 | let obligation = trait_ref.cast(Interner); | |
| 1919 | let value = InEnvironment::new( | |
| 1920 | &env.env.to_chalk(DbInterner::new_with(db, Some(env.krate), env.block)), | |
| 1921 | obligation, | |
| 1922 | ); | |
| 1923 | Canonical { binders, value } | |
| 1924 | } | |
| 1925 | ||
| 1926 | 1754 | /// This creates Substs for a trait with the given Self type and type variables |
| 1927 | 1755 | /// for all other parameters, to query the trait solver with it. |
| 1928 | 1756 | #[tracing::instrument(skip_all)] |
| 1929 | 1757 | fn generic_implements_goal_ns<'db>( |
| 1930 | 1758 | table: &mut InferenceTable<'db>, |
| 1931 | 1759 | trait_: TraitId, |
| 1932 | self_ty: next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, | |
| 1933 | ) -> next_solver::Canonical<'db, next_solver::Goal<'db, crate::next_solver::Predicate<'db>>> { | |
| 1760 | self_ty: Canonical<'db, Ty<'db>>, | |
| 1761 | ) -> Canonical<'db, Goal<'db, Predicate<'db>>> { | |
| 1934 | 1762 | let args = table.infer_ctxt.fresh_args_for_item(SolverDefId::TraitId(trait_)); |
| 1935 | let self_ty = table.instantiate_canonical_ns(self_ty); | |
| 1763 | let self_ty = table.instantiate_canonical(self_ty); | |
| 1936 | 1764 | let trait_ref = |
| 1937 | 1765 | rustc_type_ir::TraitRef::new_from_args(table.infer_ctxt.interner, trait_.into(), args) |
| 1938 | 1766 | .with_replaced_self_ty(table.infer_ctxt.interner, self_ty); |
| 1939 | let goal = next_solver::Goal::new(table.infer_ctxt.interner, table.trait_env.env, trait_ref); | |
| 1767 | let goal = Goal::new(table.infer_ctxt.interner, table.trait_env.env, trait_ref); | |
| 1940 | 1768 | |
| 1941 | 1769 | table.canonicalize(goal) |
| 1942 | 1770 | } |
| 1943 | 1771 | |
| 1944 | 1772 | fn autoderef_method_receiver<'db>( |
| 1945 | 1773 | table: &mut InferenceTable<'db>, |
| 1946 | ty: next_solver::Ty<'db>, | |
| 1947 | ) -> Vec<(next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, ReceiverAdjustments)> { | |
| 1948 | let interner = table.interner; | |
| 1774 | ty: Ty<'db>, | |
| 1775 | ) -> Vec<(Canonical<'db, Ty<'db>>, ReceiverAdjustments)> { | |
| 1776 | let interner = table.interner(); | |
| 1949 | 1777 | let mut deref_chain = Vec::new(); |
| 1950 | 1778 | let mut autoderef = autoderef::Autoderef::new_no_tracking(table, ty).use_receiver_trait(); |
| 1951 | 1779 | while let Some((ty, derefs)) = autoderef.next() { |
| ... | ... | @@ -1958,9 +1786,9 @@ fn autoderef_method_receiver<'db>( |
| 1958 | 1786 | if let Some((rustc_type_ir::Array(parameters, _), variables, max_universe, adj)) = |
| 1959 | 1787 | deref_chain.last().map(|d| (d.0.value.kind(), d.0.variables, d.0.max_universe, d.1.clone())) |
| 1960 | 1788 | { |
| 1961 | let unsized_ty = next_solver::Ty::new_slice(interner, parameters); | |
| 1789 | let unsized_ty = Ty::new_slice(interner, parameters); | |
| 1962 | 1790 | deref_chain.push(( |
| 1963 | next_solver::Canonical { max_universe, value: unsized_ty, variables }, | |
| 1791 | Canonical { max_universe, value: unsized_ty, variables }, | |
| 1964 | 1792 | ReceiverAdjustments { unsize_array: true, ..adj.clone() }, |
| 1965 | 1793 | )); |
| 1966 | 1794 | } |
src/tools/rust-analyzer/crates/hir-ty/src/mir.rs+203-196| ... | ... | @@ -2,18 +2,7 @@ |
| 2 | 2 | |
| 3 | 3 | use std::{collections::hash_map::Entry, fmt::Display, iter}; |
| 4 | 4 | |
| 5 | use crate::{ | |
| 6 | CallableDefId, ClosureId, Const, ConstScalar, InferenceResult, Interner, MemoryMap, | |
| 7 | Substitution, TraitEnvironment, Ty, TyExt, TyKind, | |
| 8 | consteval::usize_const, | |
| 9 | db::HirDatabase, | |
| 10 | display::{DisplayTarget, HirDisplay}, | |
| 11 | infer::{PointerCast, normalize}, | |
| 12 | lang_items::is_box, | |
| 13 | mapping::ToChalk, | |
| 14 | }; | |
| 15 | 5 | use base_db::Crate; |
| 16 | use chalk_ir::Mutability; | |
| 17 | 6 | use either::Either; |
| 18 | 7 | use hir_def::{ |
| 19 | 8 | DefWithBodyId, FieldId, StaticId, TupleFieldId, UnionId, VariantId, |
| ... | ... | @@ -21,6 +10,25 @@ use hir_def::{ |
| 21 | 10 | hir::{BindingAnnotation, BindingId, Expr, ExprId, Ordering, PatId}, |
| 22 | 11 | }; |
| 23 | 12 | use la_arena::{Arena, ArenaMap, Idx, RawIdx}; |
| 13 | use rustc_ast_ir::Mutability; | |
| 14 | use rustc_hash::FxHashMap; | |
| 15 | use rustc_type_ir::inherent::{AdtDef, GenericArgs as _, IntoKind, SliceLike, Ty as _}; | |
| 16 | use smallvec::{SmallVec, smallvec}; | |
| 17 | use stdx::{impl_from, never}; | |
| 18 | ||
| 19 | use crate::{ | |
| 20 | CallableDefId, InferenceResult, MemoryMap, | |
| 21 | consteval::usize_const, | |
| 22 | db::{HirDatabase, InternedClosureId}, | |
| 23 | display::{DisplayTarget, HirDisplay}, | |
| 24 | infer::PointerCast, | |
| 25 | lang_items::is_box, | |
| 26 | next_solver::{ | |
| 27 | Const, DbInterner, ErrorGuaranteed, GenericArgs, ParamEnv, Ty, TyKind, | |
| 28 | infer::{InferCtxt, traits::ObligationCause}, | |
| 29 | obligation_ctxt::ObligationCtxt, | |
| 30 | }, | |
| 31 | }; | |
| 24 | 32 | |
| 25 | 33 | mod borrowck; |
| 26 | 34 | mod eval; |
| ... | ... | @@ -36,25 +44,22 @@ pub use lower::{MirLowerError, lower_to_mir, mir_body_for_closure_query, mir_bod |
| 36 | 44 | pub use monomorphization::{ |
| 37 | 45 | monomorphized_mir_body_for_closure_query, monomorphized_mir_body_query, |
| 38 | 46 | }; |
| 39 | use rustc_hash::FxHashMap; | |
| 40 | use smallvec::{SmallVec, smallvec}; | |
| 41 | use stdx::{impl_from, never}; | |
| 42 | 47 | |
| 43 | 48 | pub(crate) use lower::mir_body_cycle_result; |
| 44 | 49 | pub(crate) use monomorphization::monomorphized_mir_body_cycle_result; |
| 45 | 50 | |
| 46 | use super::consteval::{intern_const_scalar, try_const_usize}; | |
| 51 | use super::consteval::try_const_usize; | |
| 47 | 52 | |
| 48 | pub type BasicBlockId = Idx<BasicBlock>; | |
| 49 | pub type LocalId = Idx<Local>; | |
| 53 | pub type BasicBlockId<'db> = Idx<BasicBlock<'db>>; | |
| 54 | pub type LocalId<'db> = Idx<Local<'db>>; | |
| 50 | 55 | |
| 51 | fn return_slot() -> LocalId { | |
| 56 | fn return_slot<'db>() -> LocalId<'db> { | |
| 52 | 57 | LocalId::from_raw(RawIdx::from(0)) |
| 53 | 58 | } |
| 54 | 59 | |
| 55 | 60 | #[derive(Debug, Clone, PartialEq, Eq)] |
| 56 | pub struct Local { | |
| 57 | pub ty: Ty, | |
| 61 | pub struct Local<'db> { | |
| 62 | pub ty: Ty<'db>, | |
| 58 | 63 | } |
| 59 | 64 | |
| 60 | 65 | /// An operand in MIR represents a "value" in Rust, the definition of which is undecided and part of |
| ... | ... | @@ -76,19 +81,19 @@ pub struct Local { |
| 76 | 81 | /// currently implements it, but it seems like this may be something to check against in the |
| 77 | 82 | /// validator. |
| 78 | 83 | #[derive(Debug, PartialEq, Eq, Clone)] |
| 79 | pub struct Operand { | |
| 80 | kind: OperandKind, | |
| 84 | pub struct Operand<'db> { | |
| 85 | kind: OperandKind<'db>, | |
| 81 | 86 | // FIXME : This should actually just be of type `MirSpan`. |
| 82 | 87 | span: Option<MirSpan>, |
| 83 | 88 | } |
| 84 | 89 | |
| 85 | 90 | #[derive(Debug, PartialEq, Eq, Clone)] |
| 86 | pub enum OperandKind { | |
| 91 | pub enum OperandKind<'db> { | |
| 87 | 92 | /// Creates a value by loading the given place. |
| 88 | 93 | /// |
| 89 | 94 | /// Before drop elaboration, the type of the place must be `Copy`. After drop elaboration there |
| 90 | 95 | /// is no such requirement. |
| 91 | Copy(Place), | |
| 96 | Copy(Place<'db>), | |
| 92 | 97 | |
| 93 | 98 | /// Creates a value by performing loading the place, just like the `Copy` operand. |
| 94 | 99 | /// |
| ... | ... | @@ -97,41 +102,41 @@ pub enum OperandKind { |
| 97 | 102 | /// place without first re-initializing it. |
| 98 | 103 | /// |
| 99 | 104 | /// [UCG#188]: https://github.com/rust-lang/unsafe-code-guidelines/issues/188 |
| 100 | Move(Place), | |
| 105 | Move(Place<'db>), | |
| 101 | 106 | /// Constants are already semantically values, and remain unchanged. |
| 102 | Constant(Const), | |
| 107 | Constant { konst: Const<'db>, ty: Ty<'db> }, | |
| 103 | 108 | /// NON STANDARD: This kind of operand returns an immutable reference to that static memory. Rustc |
| 104 | 109 | /// handles it with the `Constant` variant somehow. |
| 105 | 110 | Static(StaticId), |
| 106 | 111 | } |
| 107 | 112 | |
| 108 | impl Operand { | |
| 109 | fn from_concrete_const(data: Box<[u8]>, memory_map: MemoryMap<'static>, ty: Ty) -> Self { | |
| 113 | impl<'db> Operand<'db> { | |
| 114 | fn from_concrete_const(data: Box<[u8]>, memory_map: MemoryMap<'db>, ty: Ty<'db>) -> Self { | |
| 115 | let interner = DbInterner::conjure(); | |
| 110 | 116 | Operand { |
| 111 | kind: OperandKind::Constant(intern_const_scalar( | |
| 112 | ConstScalar::Bytes(data, memory_map), | |
| 117 | kind: OperandKind::Constant { | |
| 118 | konst: Const::new_valtree(interner, ty, data, memory_map), | |
| 113 | 119 | ty, |
| 114 | )), | |
| 120 | }, | |
| 115 | 121 | span: None, |
| 116 | 122 | } |
| 117 | 123 | } |
| 118 | 124 | |
| 119 | fn from_bytes(data: Box<[u8]>, ty: Ty) -> Self { | |
| 125 | fn from_bytes(data: Box<[u8]>, ty: Ty<'db>) -> Self { | |
| 120 | 126 | Operand::from_concrete_const(data, MemoryMap::default(), ty) |
| 121 | 127 | } |
| 122 | 128 | |
| 123 | fn const_zst(ty: Ty) -> Operand { | |
| 129 | fn const_zst(ty: Ty<'db>) -> Operand<'db> { | |
| 124 | 130 | Self::from_bytes(Box::default(), ty) |
| 125 | 131 | } |
| 126 | 132 | |
| 127 | 133 | fn from_fn( |
| 128 | db: &dyn HirDatabase, | |
| 134 | db: &'db dyn HirDatabase, | |
| 129 | 135 | func_id: hir_def::FunctionId, |
| 130 | generic_args: Substitution, | |
| 131 | ) -> Operand { | |
| 132 | let ty = | |
| 133 | chalk_ir::TyKind::FnDef(CallableDefId::FunctionId(func_id).to_chalk(db), generic_args) | |
| 134 | .intern(Interner); | |
| 136 | generic_args: GenericArgs<'db>, | |
| 137 | ) -> Operand<'db> { | |
| 138 | let interner = DbInterner::new_with(db, None, None); | |
| 139 | let ty = Ty::new_fn_def(interner, CallableDefId::FunctionId(func_id).into(), generic_args); | |
| 135 | 140 | Operand::from_bytes(Box::default(), ty) |
| 136 | 141 | } |
| 137 | 142 | } |
| ... | ... | @@ -150,83 +155,81 @@ pub enum ProjectionElem<V, T> { |
| 150 | 155 | } |
| 151 | 156 | |
| 152 | 157 | impl<V, T> ProjectionElem<V, T> { |
| 153 | pub fn projected_ty( | |
| 158 | pub fn projected_ty<'db>( | |
| 154 | 159 | &self, |
| 155 | mut base: Ty, | |
| 156 | db: &dyn HirDatabase, | |
| 157 | closure_field: impl FnOnce(ClosureId, &Substitution, usize) -> Ty, | |
| 160 | infcx: &InferCtxt<'db>, | |
| 161 | mut base: Ty<'db>, | |
| 162 | closure_field: impl FnOnce(InternedClosureId, GenericArgs<'db>, usize) -> Ty<'db>, | |
| 158 | 163 | krate: Crate, |
| 159 | ) -> Ty { | |
| 164 | ) -> Ty<'db> { | |
| 165 | let interner = infcx.interner; | |
| 166 | let db = interner.db; | |
| 167 | ||
| 160 | 168 | // we only bail on mir building when there are type mismatches |
| 161 | 169 | // but error types may pop up resulting in us still attempting to build the mir |
| 162 | 170 | // so just propagate the error type |
| 163 | if base.is_unknown() { | |
| 164 | return TyKind::Error.intern(Interner); | |
| 171 | if base.is_ty_error() { | |
| 172 | return Ty::new_error(interner, ErrorGuaranteed); | |
| 165 | 173 | } |
| 166 | 174 | |
| 167 | if matches!(base.kind(Interner), TyKind::Alias(_) | TyKind::AssociatedType(..)) { | |
| 168 | base = normalize( | |
| 169 | db, | |
| 170 | // FIXME: we should get this from caller | |
| 171 | TraitEnvironment::empty(krate), | |
| 172 | base, | |
| 173 | ); | |
| 175 | if matches!(base.kind(), TyKind::Alias(..)) { | |
| 176 | let mut ocx = ObligationCtxt::new(infcx); | |
| 177 | // FIXME: we should get this from caller | |
| 178 | let env = ParamEnv::empty(); | |
| 179 | match ocx.structurally_normalize_ty(&ObligationCause::dummy(), env, base) { | |
| 180 | Ok(it) => base = it, | |
| 181 | Err(_) => return Ty::new_error(interner, ErrorGuaranteed), | |
| 182 | } | |
| 174 | 183 | } |
| 184 | ||
| 175 | 185 | match self { |
| 176 | ProjectionElem::Deref => match &base.kind(Interner) { | |
| 177 | TyKind::Raw(_, inner) | TyKind::Ref(_, _, inner) => inner.clone(), | |
| 178 | TyKind::Adt(adt, subst) if is_box(db, adt.0) => { | |
| 179 | subst.at(Interner, 0).assert_ty_ref(Interner).clone() | |
| 180 | } | |
| 186 | ProjectionElem::Deref => match base.kind() { | |
| 187 | TyKind::RawPtr(inner, _) | TyKind::Ref(_, inner, _) => inner, | |
| 188 | TyKind::Adt(adt_def, subst) if is_box(db, adt_def.def_id().0) => subst.type_at(0), | |
| 181 | 189 | _ => { |
| 182 | 190 | never!( |
| 183 | 191 | "Overloaded deref on type {} is not a projection", |
| 184 | 192 | base.display(db, DisplayTarget::from_crate(db, krate)) |
| 185 | 193 | ); |
| 186 | TyKind::Error.intern(Interner) | |
| 194 | Ty::new_error(interner, ErrorGuaranteed) | |
| 187 | 195 | } |
| 188 | 196 | }, |
| 189 | ProjectionElem::Field(Either::Left(f)) => match base.kind(Interner) { | |
| 197 | ProjectionElem::Field(Either::Left(f)) => match base.kind() { | |
| 190 | 198 | TyKind::Adt(_, subst) => { |
| 191 | db.field_types(f.parent)[f.local_id].clone().substitute(Interner, subst) | |
| 199 | db.field_types_ns(f.parent)[f.local_id].instantiate(interner, subst) | |
| 192 | 200 | } |
| 193 | 201 | ty => { |
| 194 | 202 | never!("Only adt has field, found {:?}", ty); |
| 195 | TyKind::Error.intern(Interner) | |
| 203 | Ty::new_error(interner, ErrorGuaranteed) | |
| 196 | 204 | } |
| 197 | 205 | }, |
| 198 | ProjectionElem::Field(Either::Right(f)) => match &base.kind(Interner) { | |
| 199 | TyKind::Tuple(_, subst) => subst | |
| 200 | .as_slice(Interner) | |
| 201 | .get(f.index as usize) | |
| 202 | .map(|x| x.assert_ty_ref(Interner)) | |
| 203 | .cloned() | |
| 204 | .unwrap_or_else(|| { | |
| 206 | ProjectionElem::Field(Either::Right(f)) => match base.kind() { | |
| 207 | TyKind::Tuple(subst) => { | |
| 208 | subst.as_slice().get(f.index as usize).copied().unwrap_or_else(|| { | |
| 205 | 209 | never!("Out of bound tuple field"); |
| 206 | TyKind::Error.intern(Interner) | |
| 207 | }), | |
| 210 | Ty::new_error(interner, ErrorGuaranteed) | |
| 211 | }) | |
| 212 | } | |
| 208 | 213 | ty => { |
| 209 | 214 | never!("Only tuple has tuple field: {:?}", ty); |
| 210 | TyKind::Error.intern(Interner) | |
| 215 | Ty::new_error(interner, ErrorGuaranteed) | |
| 211 | 216 | } |
| 212 | 217 | }, |
| 213 | ProjectionElem::ClosureField(f) => match &base.kind(Interner) { | |
| 214 | TyKind::Closure(id, subst) => closure_field(*id, subst, *f), | |
| 218 | ProjectionElem::ClosureField(f) => match base.kind() { | |
| 219 | TyKind::Closure(id, subst) => closure_field(id.0, subst, *f), | |
| 215 | 220 | _ => { |
| 216 | 221 | never!("Only closure has closure field"); |
| 217 | TyKind::Error.intern(Interner) | |
| 222 | Ty::new_error(interner, ErrorGuaranteed) | |
| 218 | 223 | } |
| 219 | 224 | }, |
| 220 | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Index(_) => { | |
| 221 | match &base.kind(Interner) { | |
| 222 | TyKind::Array(inner, _) | TyKind::Slice(inner) => inner.clone(), | |
| 223 | _ => { | |
| 224 | never!("Overloaded index is not a projection"); | |
| 225 | TyKind::Error.intern(Interner) | |
| 226 | } | |
| 225 | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Index(_) => match base.kind() { | |
| 226 | TyKind::Array(inner, _) | TyKind::Slice(inner) => inner, | |
| 227 | _ => { | |
| 228 | never!("Overloaded index is not a projection"); | |
| 229 | Ty::new_error(interner, ErrorGuaranteed) | |
| 227 | 230 | } |
| 228 | } | |
| 229 | &ProjectionElem::Subslice { from, to } => match &base.kind(Interner) { | |
| 231 | }, | |
| 232 | &ProjectionElem::Subslice { from, to } => match base.kind() { | |
| 230 | 233 | TyKind::Array(inner, c) => { |
| 231 | 234 | let next_c = usize_const( |
| 232 | 235 | db, |
| ... | ... | @@ -236,34 +239,34 @@ impl<V, T> ProjectionElem<V, T> { |
| 236 | 239 | }, |
| 237 | 240 | krate, |
| 238 | 241 | ); |
| 239 | TyKind::Array(inner.clone(), next_c).intern(Interner) | |
| 242 | Ty::new_array_with_const_len(interner, inner, next_c) | |
| 240 | 243 | } |
| 241 | TyKind::Slice(_) => base.clone(), | |
| 244 | TyKind::Slice(_) => base, | |
| 242 | 245 | _ => { |
| 243 | 246 | never!("Subslice projection should only happen on slice and array"); |
| 244 | TyKind::Error.intern(Interner) | |
| 247 | Ty::new_error(interner, ErrorGuaranteed) | |
| 245 | 248 | } |
| 246 | 249 | }, |
| 247 | 250 | ProjectionElem::OpaqueCast(_) => { |
| 248 | 251 | never!("We don't emit these yet"); |
| 249 | TyKind::Error.intern(Interner) | |
| 252 | Ty::new_error(interner, ErrorGuaranteed) | |
| 250 | 253 | } |
| 251 | 254 | } |
| 252 | 255 | } |
| 253 | 256 | } |
| 254 | 257 | |
| 255 | type PlaceElem = ProjectionElem<LocalId, Ty>; | |
| 258 | type PlaceElem<'db> = ProjectionElem<LocalId<'db>, Ty<'db>>; | |
| 256 | 259 | |
| 257 | 260 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
| 258 | 261 | pub struct ProjectionId(u32); |
| 259 | 262 | |
| 260 | 263 | #[derive(Debug, Clone, PartialEq, Eq)] |
| 261 | pub struct ProjectionStore { | |
| 262 | id_to_proj: FxHashMap<ProjectionId, Box<[PlaceElem]>>, | |
| 263 | proj_to_id: FxHashMap<Box<[PlaceElem]>, ProjectionId>, | |
| 264 | pub struct ProjectionStore<'db> { | |
| 265 | id_to_proj: FxHashMap<ProjectionId, Box<[PlaceElem<'db>]>>, | |
| 266 | proj_to_id: FxHashMap<Box<[PlaceElem<'db>]>, ProjectionId>, | |
| 264 | 267 | } |
| 265 | 268 | |
| 266 | impl Default for ProjectionStore { | |
| 269 | impl Default for ProjectionStore<'_> { | |
| 267 | 270 | fn default() -> Self { |
| 268 | 271 | let mut this = Self { id_to_proj: Default::default(), proj_to_id: Default::default() }; |
| 269 | 272 | // Ensure that [] will get the id 0 which is used in `ProjectionId::Empty` |
| ... | ... | @@ -272,17 +275,17 @@ impl Default for ProjectionStore { |
| 272 | 275 | } |
| 273 | 276 | } |
| 274 | 277 | |
| 275 | impl ProjectionStore { | |
| 278 | impl<'db> ProjectionStore<'db> { | |
| 276 | 279 | pub fn shrink_to_fit(&mut self) { |
| 277 | 280 | self.id_to_proj.shrink_to_fit(); |
| 278 | 281 | self.proj_to_id.shrink_to_fit(); |
| 279 | 282 | } |
| 280 | 283 | |
| 281 | pub fn intern_if_exist(&self, projection: &[PlaceElem]) -> Option<ProjectionId> { | |
| 284 | pub fn intern_if_exist(&self, projection: &[PlaceElem<'db>]) -> Option<ProjectionId> { | |
| 282 | 285 | self.proj_to_id.get(projection).copied() |
| 283 | 286 | } |
| 284 | 287 | |
| 285 | pub fn intern(&mut self, projection: Box<[PlaceElem]>) -> ProjectionId { | |
| 288 | pub fn intern(&mut self, projection: Box<[PlaceElem<'db>]>) -> ProjectionId { | |
| 286 | 289 | let new_id = ProjectionId(self.proj_to_id.len() as u32); |
| 287 | 290 | match self.proj_to_id.entry(projection) { |
| 288 | 291 | Entry::Occupied(id) => *id.get(), |
| ... | ... | @@ -303,11 +306,15 @@ impl ProjectionId { |
| 303 | 306 | self == ProjectionId::EMPTY |
| 304 | 307 | } |
| 305 | 308 | |
| 306 | pub fn lookup(self, store: &ProjectionStore) -> &[PlaceElem] { | |
| 309 | pub fn lookup<'a, 'db>(self, store: &'a ProjectionStore<'db>) -> &'a [PlaceElem<'db>] { | |
| 307 | 310 | store.id_to_proj.get(&self).unwrap() |
| 308 | 311 | } |
| 309 | 312 | |
| 310 | pub fn project(self, projection: PlaceElem, store: &mut ProjectionStore) -> ProjectionId { | |
| 313 | pub fn project<'db>( | |
| 314 | self, | |
| 315 | projection: PlaceElem<'db>, | |
| 316 | store: &mut ProjectionStore<'db>, | |
| 317 | ) -> ProjectionId { | |
| 311 | 318 | let mut current = self.lookup(store).to_vec(); |
| 312 | 319 | current.push(projection); |
| 313 | 320 | store.intern(current.into()) |
| ... | ... | @@ -315,13 +322,13 @@ impl ProjectionId { |
| 315 | 322 | } |
| 316 | 323 | |
| 317 | 324 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
| 318 | pub struct Place { | |
| 319 | pub local: LocalId, | |
| 325 | pub struct Place<'db> { | |
| 326 | pub local: LocalId<'db>, | |
| 320 | 327 | pub projection: ProjectionId, |
| 321 | 328 | } |
| 322 | 329 | |
| 323 | impl Place { | |
| 324 | fn is_parent(&self, child: &Place, store: &ProjectionStore) -> bool { | |
| 330 | impl<'db> Place<'db> { | |
| 331 | fn is_parent(&self, child: &Place<'db>, store: &ProjectionStore<'db>) -> bool { | |
| 325 | 332 | self.local == child.local |
| 326 | 333 | && child.projection.lookup(store).starts_with(self.projection.lookup(store)) |
| 327 | 334 | } |
| ... | ... | @@ -329,39 +336,39 @@ impl Place { |
| 329 | 336 | /// The place itself is not included |
| 330 | 337 | fn iterate_over_parents<'a>( |
| 331 | 338 | &'a self, |
| 332 | store: &'a ProjectionStore, | |
| 333 | ) -> impl Iterator<Item = Place> + 'a { | |
| 339 | store: &'a ProjectionStore<'db>, | |
| 340 | ) -> impl Iterator<Item = Place<'db>> + 'a { | |
| 334 | 341 | let projection = self.projection.lookup(store); |
| 335 | 342 | (0..projection.len()).map(|x| &projection[0..x]).filter_map(move |x| { |
| 336 | 343 | Some(Place { local: self.local, projection: store.intern_if_exist(x)? }) |
| 337 | 344 | }) |
| 338 | 345 | } |
| 339 | 346 | |
| 340 | fn project(&self, projection: PlaceElem, store: &mut ProjectionStore) -> Place { | |
| 347 | fn project(&self, projection: PlaceElem<'db>, store: &mut ProjectionStore<'db>) -> Place<'db> { | |
| 341 | 348 | Place { local: self.local, projection: self.projection.project(projection, store) } |
| 342 | 349 | } |
| 343 | 350 | } |
| 344 | 351 | |
| 345 | impl From<LocalId> for Place { | |
| 346 | fn from(local: LocalId) -> Self { | |
| 352 | impl<'db> From<LocalId<'db>> for Place<'db> { | |
| 353 | fn from(local: LocalId<'db>) -> Self { | |
| 347 | 354 | Self { local, projection: ProjectionId::EMPTY } |
| 348 | 355 | } |
| 349 | 356 | } |
| 350 | 357 | |
| 351 | 358 | #[derive(Debug, PartialEq, Eq, Clone)] |
| 352 | pub enum AggregateKind { | |
| 359 | pub enum AggregateKind<'db> { | |
| 353 | 360 | /// The type is of the element |
| 354 | Array(Ty), | |
| 361 | Array(Ty<'db>), | |
| 355 | 362 | /// The type is of the tuple |
| 356 | Tuple(Ty), | |
| 357 | Adt(VariantId, Substitution), | |
| 363 | Tuple(Ty<'db>), | |
| 364 | Adt(VariantId, GenericArgs<'db>), | |
| 358 | 365 | Union(UnionId, FieldId), |
| 359 | Closure(Ty), | |
| 366 | Closure(Ty<'db>), | |
| 360 | 367 | //Coroutine(LocalDefId, SubstsRef, Movability), |
| 361 | 368 | } |
| 362 | 369 | |
| 363 | 370 | #[derive(Debug, Clone, Hash, PartialEq, Eq)] |
| 364 | pub struct SwitchTargets { | |
| 371 | pub struct SwitchTargets<'db> { | |
| 365 | 372 | /// Possible values. The locations to branch to in each case |
| 366 | 373 | /// are found in the corresponding indices from the `targets` vector. |
| 367 | 374 | values: SmallVec<[u128; 1]>, |
| ... | ... | @@ -378,17 +385,17 @@ pub struct SwitchTargets { |
| 378 | 385 | // |
| 379 | 386 | // However we’ve decided to keep this as-is until we figure a case |
| 380 | 387 | // where some other approach seems to be strictly better than other. |
| 381 | targets: SmallVec<[BasicBlockId; 2]>, | |
| 388 | targets: SmallVec<[BasicBlockId<'db>; 2]>, | |
| 382 | 389 | } |
| 383 | 390 | |
| 384 | impl SwitchTargets { | |
| 391 | impl<'db> SwitchTargets<'db> { | |
| 385 | 392 | /// Creates switch targets from an iterator of values and target blocks. |
| 386 | 393 | /// |
| 387 | 394 | /// The iterator may be empty, in which case the `SwitchInt` instruction is equivalent to |
| 388 | 395 | /// `goto otherwise;`. |
| 389 | 396 | pub fn new( |
| 390 | targets: impl Iterator<Item = (u128, BasicBlockId)>, | |
| 391 | otherwise: BasicBlockId, | |
| 397 | targets: impl Iterator<Item = (u128, BasicBlockId<'db>)>, | |
| 398 | otherwise: BasicBlockId<'db>, | |
| 392 | 399 | ) -> Self { |
| 393 | 400 | let (values, mut targets): (SmallVec<_>, SmallVec<_>) = targets.unzip(); |
| 394 | 401 | targets.push(otherwise); |
| ... | ... | @@ -397,12 +404,12 @@ impl SwitchTargets { |
| 397 | 404 | |
| 398 | 405 | /// Builds a switch targets definition that jumps to `then` if the tested value equals `value`, |
| 399 | 406 | /// and to `else_` if not. |
| 400 | pub fn static_if(value: u128, then: BasicBlockId, else_: BasicBlockId) -> Self { | |
| 407 | pub fn static_if(value: u128, then: BasicBlockId<'db>, else_: BasicBlockId<'db>) -> Self { | |
| 401 | 408 | Self { values: smallvec![value], targets: smallvec![then, else_] } |
| 402 | 409 | } |
| 403 | 410 | |
| 404 | 411 | /// Returns the fallback target that is jumped to when none of the values match the operand. |
| 405 | pub fn otherwise(&self) -> BasicBlockId { | |
| 412 | pub fn otherwise(&self) -> BasicBlockId<'db> { | |
| 406 | 413 | *self.targets.last().unwrap() |
| 407 | 414 | } |
| 408 | 415 | |
| ... | ... | @@ -412,33 +419,33 @@ impl SwitchTargets { |
| 412 | 419 | /// including the `otherwise` fallback target. |
| 413 | 420 | /// |
| 414 | 421 | /// Note that this may yield 0 elements. Only the `otherwise` branch is mandatory. |
| 415 | pub fn iter(&self) -> impl Iterator<Item = (u128, BasicBlockId)> + '_ { | |
| 422 | pub fn iter(&self) -> impl Iterator<Item = (u128, BasicBlockId<'db>)> + '_ { | |
| 416 | 423 | iter::zip(&self.values, &self.targets).map(|(x, y)| (*x, *y)) |
| 417 | 424 | } |
| 418 | 425 | |
| 419 | 426 | /// Returns a slice with all possible jump targets (including the fallback target). |
| 420 | pub fn all_targets(&self) -> &[BasicBlockId] { | |
| 427 | pub fn all_targets(&self) -> &[BasicBlockId<'db>] { | |
| 421 | 428 | &self.targets |
| 422 | 429 | } |
| 423 | 430 | |
| 424 | 431 | /// Finds the `BasicBlock` to which this `SwitchInt` will branch given the |
| 425 | 432 | /// specific value. This cannot fail, as it'll return the `otherwise` |
| 426 | 433 | /// branch if there's not a specific match for the value. |
| 427 | pub fn target_for_value(&self, value: u128) -> BasicBlockId { | |
| 434 | pub fn target_for_value(&self, value: u128) -> BasicBlockId<'db> { | |
| 428 | 435 | self.iter().find_map(|(v, t)| (v == value).then_some(t)).unwrap_or_else(|| self.otherwise()) |
| 429 | 436 | } |
| 430 | 437 | } |
| 431 | 438 | |
| 432 | 439 | #[derive(Debug, PartialEq, Eq, Clone)] |
| 433 | pub struct Terminator { | |
| 440 | pub struct Terminator<'db> { | |
| 434 | 441 | pub span: MirSpan, |
| 435 | pub kind: TerminatorKind, | |
| 442 | pub kind: TerminatorKind<'db>, | |
| 436 | 443 | } |
| 437 | 444 | |
| 438 | 445 | #[derive(Debug, PartialEq, Eq, Clone)] |
| 439 | pub enum TerminatorKind { | |
| 446 | pub enum TerminatorKind<'db> { | |
| 440 | 447 | /// Block has one successor; we continue execution there. |
| 441 | Goto { target: BasicBlockId }, | |
| 448 | Goto { target: BasicBlockId<'db> }, | |
| 442 | 449 | |
| 443 | 450 | /// Switches based on the computed value. |
| 444 | 451 | /// |
| ... | ... | @@ -450,9 +457,9 @@ pub enum TerminatorKind { |
| 450 | 457 | /// Target values may not appear more than once. |
| 451 | 458 | SwitchInt { |
| 452 | 459 | /// The discriminant value being tested. |
| 453 | discr: Operand, | |
| 460 | discr: Operand<'db>, | |
| 454 | 461 | |
| 455 | targets: SwitchTargets, | |
| 462 | targets: SwitchTargets<'db>, | |
| 456 | 463 | }, |
| 457 | 464 | |
| 458 | 465 | /// Indicates that the landing pad is finished and that the process should continue unwinding. |
| ... | ... | @@ -503,7 +510,7 @@ pub enum TerminatorKind { |
| 503 | 510 | /// > The drop glue is executed if, among all statements executed within this `Body`, an assignment to |
| 504 | 511 | /// > the place or one of its "parents" occurred more recently than a move out of it. This does not |
| 505 | 512 | /// > consider indirect assignments. |
| 506 | Drop { place: Place, target: BasicBlockId, unwind: Option<BasicBlockId> }, | |
| 513 | Drop { place: Place<'db>, target: BasicBlockId<'db>, unwind: Option<BasicBlockId<'db>> }, | |
| 507 | 514 | |
| 508 | 515 | /// Drops the place and assigns a new value to it. |
| 509 | 516 | /// |
| ... | ... | @@ -536,10 +543,10 @@ pub enum TerminatorKind { |
| 536 | 543 | /// |
| 537 | 544 | /// Disallowed after drop elaboration. |
| 538 | 545 | DropAndReplace { |
| 539 | place: Place, | |
| 540 | value: Operand, | |
| 541 | target: BasicBlockId, | |
| 542 | unwind: Option<BasicBlockId>, | |
| 546 | place: Place<'db>, | |
| 547 | value: Operand<'db>, | |
| 548 | target: BasicBlockId<'db>, | |
| 549 | unwind: Option<BasicBlockId<'db>>, | |
| 543 | 550 | }, |
| 544 | 551 | |
| 545 | 552 | /// Roughly speaking, evaluates the `func` operand and the arguments, and starts execution of |
| ... | ... | @@ -554,18 +561,18 @@ pub enum TerminatorKind { |
| 554 | 561 | /// [#71117]: https://github.com/rust-lang/rust/issues/71117 |
| 555 | 562 | Call { |
| 556 | 563 | /// The function that’s being called. |
| 557 | func: Operand, | |
| 564 | func: Operand<'db>, | |
| 558 | 565 | /// Arguments the function is called with. |
| 559 | 566 | /// These are owned by the callee, which is free to modify them. |
| 560 | 567 | /// This allows the memory occupied by "by-value" arguments to be |
| 561 | 568 | /// reused across function calls without duplicating the contents. |
| 562 | args: Box<[Operand]>, | |
| 569 | args: Box<[Operand<'db>]>, | |
| 563 | 570 | /// Where the returned value will be written |
| 564 | destination: Place, | |
| 571 | destination: Place<'db>, | |
| 565 | 572 | /// Where to go after this call returns. If none, the call necessarily diverges. |
| 566 | target: Option<BasicBlockId>, | |
| 573 | target: Option<BasicBlockId<'db>>, | |
| 567 | 574 | /// Cleanups to be done if the call unwinds. |
| 568 | cleanup: Option<BasicBlockId>, | |
| 575 | cleanup: Option<BasicBlockId<'db>>, | |
| 569 | 576 | /// `true` if this is from a call in HIR rather than from an overloaded |
| 570 | 577 | /// operator. True for overloaded function call. |
| 571 | 578 | from_hir_call: bool, |
| ... | ... | @@ -581,11 +588,11 @@ pub enum TerminatorKind { |
| 581 | 588 | /// necessarily executed even in the case of a panic, for example in `-C panic=abort`. If the |
| 582 | 589 | /// assertion does not fail, execution continues at the specified basic block. |
| 583 | 590 | Assert { |
| 584 | cond: Operand, | |
| 591 | cond: Operand<'db>, | |
| 585 | 592 | expected: bool, |
| 586 | 593 | //msg: AssertMessage, |
| 587 | target: BasicBlockId, | |
| 588 | cleanup: Option<BasicBlockId>, | |
| 594 | target: BasicBlockId<'db>, | |
| 595 | cleanup: Option<BasicBlockId<'db>>, | |
| 589 | 596 | }, |
| 590 | 597 | |
| 591 | 598 | /// Marks a suspend point. |
| ... | ... | @@ -602,13 +609,13 @@ pub enum TerminatorKind { |
| 602 | 609 | /// **Needs clarification**: What about the evaluation order of the `resume_arg` and `value`? |
| 603 | 610 | Yield { |
| 604 | 611 | /// The value to return. |
| 605 | value: Operand, | |
| 612 | value: Operand<'db>, | |
| 606 | 613 | /// Where to resume to. |
| 607 | resume: BasicBlockId, | |
| 614 | resume: BasicBlockId<'db>, | |
| 608 | 615 | /// The place to store the resume argument in. |
| 609 | resume_arg: Place, | |
| 616 | resume_arg: Place<'db>, | |
| 610 | 617 | /// Cleanup to be done if the coroutine is dropped at this suspend point. |
| 611 | drop: Option<BasicBlockId>, | |
| 618 | drop: Option<BasicBlockId<'db>>, | |
| 612 | 619 | }, |
| 613 | 620 | |
| 614 | 621 | /// Indicates the end of dropping a coroutine. |
| ... | ... | @@ -631,10 +638,10 @@ pub enum TerminatorKind { |
| 631 | 638 | /// Disallowed after drop elaboration. |
| 632 | 639 | FalseEdge { |
| 633 | 640 | /// The target normal control flow will take. |
| 634 | real_target: BasicBlockId, | |
| 641 | real_target: BasicBlockId<'db>, | |
| 635 | 642 | /// A block control flow could conceptually jump to, but won't in |
| 636 | 643 | /// practice. |
| 637 | imaginary_target: BasicBlockId, | |
| 644 | imaginary_target: BasicBlockId<'db>, | |
| 638 | 645 | }, |
| 639 | 646 | |
| 640 | 647 | /// A terminator for blocks that only take one path in reality, but where we reserve the right |
| ... | ... | @@ -646,14 +653,14 @@ pub enum TerminatorKind { |
| 646 | 653 | /// Disallowed after drop elaboration. |
| 647 | 654 | FalseUnwind { |
| 648 | 655 | /// The target normal control flow will take. |
| 649 | real_target: BasicBlockId, | |
| 656 | real_target: BasicBlockId<'db>, | |
| 650 | 657 | /// The imaginary cleanup block link. This particular path will never be taken |
| 651 | 658 | /// in practice, but in order to avoid fragility we want to always |
| 652 | 659 | /// consider it in borrowck. We don't want to accept programs which |
| 653 | 660 | /// pass borrowck only when `panic=abort` or some assertions are disabled |
| 654 | 661 | /// due to release vs. debug mode builds. This needs to be an `Option` because |
| 655 | 662 | /// of the `remove_noop_landing_pads` and `abort_unwinding_calls` passes. |
| 656 | unwind: Option<BasicBlockId>, | |
| 663 | unwind: Option<BasicBlockId<'db>>, | |
| 657 | 664 | }, |
| 658 | 665 | } |
| 659 | 666 | |
| ... | ... | @@ -708,10 +715,10 @@ impl BorrowKind { |
| 708 | 715 | } |
| 709 | 716 | } |
| 710 | 717 | |
| 711 | fn from_chalk(m: Mutability) -> Self { | |
| 718 | fn from_rustc(m: rustc_ast_ir::Mutability) -> Self { | |
| 712 | 719 | match m { |
| 713 | Mutability::Not => BorrowKind::Shared, | |
| 714 | Mutability::Mut => BorrowKind::Mut { kind: MutBorrowKind::Default }, | |
| 720 | rustc_ast_ir::Mutability::Not => BorrowKind::Shared, | |
| 721 | rustc_ast_ir::Mutability::Mut => BorrowKind::Mut { kind: MutBorrowKind::Default }, | |
| 715 | 722 | } |
| 716 | 723 | } |
| 717 | 724 | } |
| ... | ... | @@ -840,8 +847,8 @@ impl From<hir_def::hir::CmpOp> for BinOp { |
| 840 | 847 | } |
| 841 | 848 | } |
| 842 | 849 | |
| 843 | impl From<Operand> for Rvalue { | |
| 844 | fn from(x: Operand) -> Self { | |
| 850 | impl<'db> From<Operand<'db>> for Rvalue<'db> { | |
| 851 | fn from(x: Operand<'db>) -> Self { | |
| 845 | 852 | Self::Use(x) |
| 846 | 853 | } |
| 847 | 854 | } |
| ... | ... | @@ -870,14 +877,14 @@ pub enum CastKind { |
| 870 | 877 | } |
| 871 | 878 | |
| 872 | 879 | #[derive(Debug, PartialEq, Eq, Clone)] |
| 873 | pub enum Rvalue { | |
| 880 | pub enum Rvalue<'db> { | |
| 874 | 881 | /// Yields the operand unchanged |
| 875 | Use(Operand), | |
| 882 | Use(Operand<'db>), | |
| 876 | 883 | |
| 877 | 884 | /// Creates an array where each element is the value of the operand. |
| 878 | 885 | /// |
| 879 | 886 | /// Corresponds to source code like `[x; 32]`. |
| 880 | Repeat(Operand, Const), | |
| 887 | Repeat(Operand<'db>, Const<'db>), | |
| 881 | 888 | |
| 882 | 889 | /// Creates a reference of the indicated kind to the place. |
| 883 | 890 | /// |
| ... | ... | @@ -886,7 +893,7 @@ pub enum Rvalue { |
| 886 | 893 | /// exactly what the behavior of this operation should be. |
| 887 | 894 | /// |
| 888 | 895 | /// `Shallow` borrows are disallowed after drop lowering. |
| 889 | Ref(BorrowKind, Place), | |
| 896 | Ref(BorrowKind, Place<'db>), | |
| 890 | 897 | |
| 891 | 898 | /// Creates a pointer/reference to the given thread local. |
| 892 | 899 | /// |
| ... | ... | @@ -917,7 +924,7 @@ pub enum Rvalue { |
| 917 | 924 | /// If the type of the place is an array, this is the array length. For slices (`[T]`, not |
| 918 | 925 | /// `&[T]`) this accesses the place's metadata to determine the length. This rvalue is |
| 919 | 926 | /// ill-formed for places of other types. |
| 920 | Len(Place), | |
| 927 | Len(Place<'db>), | |
| 921 | 928 | |
| 922 | 929 | /// Performs essentially all of the casts that can be performed via `as`. |
| 923 | 930 | /// |
| ... | ... | @@ -925,7 +932,7 @@ pub enum Rvalue { |
| 925 | 932 | /// |
| 926 | 933 | /// **FIXME**: Document exactly which `CastKind`s allow which types of casts. Figure out why |
| 927 | 934 | /// `ArrayToPointer` and `MutToConstPointer` are special. |
| 928 | Cast(CastKind, Operand, Ty), | |
| 935 | Cast(CastKind, Operand<'db>, Ty<'db>), | |
| 929 | 936 | |
| 930 | 937 | // FIXME link to `pointer::offset` when it hits stable. |
| 931 | 938 | /// * `Offset` has the same semantics as `pointer::offset`, except that the second |
| ... | ... | @@ -957,7 +964,7 @@ pub enum Rvalue { |
| 957 | 964 | /// when the value of right-hand side is negative. |
| 958 | 965 | /// |
| 959 | 966 | /// Other combinations of types and operators are unsupported. |
| 960 | CheckedBinaryOp(BinOp, Operand, Operand), | |
| 967 | CheckedBinaryOp(BinOp, Operand<'db>, Operand<'db>), | |
| 961 | 968 | |
| 962 | 969 | /// Computes a value as described by the operation. |
| 963 | 970 | //NullaryOp(NullOp, Ty), |
| ... | ... | @@ -968,7 +975,7 @@ pub enum Rvalue { |
| 968 | 975 | /// Also does two's-complement arithmetic. Negation requires a signed integer or a float; |
| 969 | 976 | /// bitwise not requires a signed integer, unsigned integer, or bool. Both operation kinds |
| 970 | 977 | /// return a value with the same type as their operand. |
| 971 | UnaryOp(UnOp, Operand), | |
| 978 | UnaryOp(UnOp, Operand<'db>), | |
| 972 | 979 | |
| 973 | 980 | /// Computes the discriminant of the place, returning it as an integer of type |
| 974 | 981 | /// [`discriminant_ty`]. Returns zero for types without discriminant. |
| ... | ... | @@ -980,7 +987,7 @@ pub enum Rvalue { |
| 980 | 987 | /// [`discriminant_ty`]: crate::ty::Ty::discriminant_ty |
| 981 | 988 | /// [#91095]: https://github.com/rust-lang/rust/issues/91095 |
| 982 | 989 | /// [`discriminant_for_variant`]: crate::ty::Ty::discriminant_for_variant |
| 983 | Discriminant(Place), | |
| 990 | Discriminant(Place<'db>), | |
| 984 | 991 | |
| 985 | 992 | /// Creates an aggregate value, like a tuple or struct. |
| 986 | 993 | /// |
| ... | ... | @@ -990,17 +997,17 @@ pub enum Rvalue { |
| 990 | 997 | /// |
| 991 | 998 | /// Disallowed after deaggregation for all aggregate kinds except `Array` and `Coroutine`. After |
| 992 | 999 | /// coroutine lowering, `Coroutine` aggregate kinds are disallowed too. |
| 993 | Aggregate(AggregateKind, Box<[Operand]>), | |
| 1000 | Aggregate(AggregateKind<'db>, Box<[Operand<'db>]>), | |
| 994 | 1001 | |
| 995 | 1002 | /// Transmutes a `*mut u8` into shallow-initialized `Box<T>`. |
| 996 | 1003 | /// |
| 997 | 1004 | /// This is different from a normal transmute because dataflow analysis will treat the box as |
| 998 | 1005 | /// initialized but its content as uninitialized. Like other pointer casts, this in general |
| 999 | 1006 | /// affects alias analysis. |
| 1000 | ShallowInitBox(Operand, Ty), | |
| 1007 | ShallowInitBox(Operand<'db>, Ty<'db>), | |
| 1001 | 1008 | |
| 1002 | 1009 | /// NON STANDARD: allocates memory with the type's layout, and shallow init the box with the resulting pointer. |
| 1003 | ShallowInitBoxWithAlloc(Ty), | |
| 1010 | ShallowInitBoxWithAlloc(Ty<'db>), | |
| 1004 | 1011 | |
| 1005 | 1012 | /// A CopyForDeref is equivalent to a read from a place at the |
| 1006 | 1013 | /// codegen level, but is treated specially by drop elaboration. When such a read happens, it |
| ... | ... | @@ -1010,41 +1017,41 @@ pub enum Rvalue { |
| 1010 | 1017 | /// read never happened and just projects further. This allows simplifying various MIR |
| 1011 | 1018 | /// optimizations and codegen backends that previously had to handle deref operations anywhere |
| 1012 | 1019 | /// in a place. |
| 1013 | CopyForDeref(Place), | |
| 1020 | CopyForDeref(Place<'db>), | |
| 1014 | 1021 | } |
| 1015 | 1022 | |
| 1016 | 1023 | #[derive(Debug, PartialEq, Eq, Clone)] |
| 1017 | pub enum StatementKind { | |
| 1018 | Assign(Place, Rvalue), | |
| 1019 | FakeRead(Place), | |
| 1024 | pub enum StatementKind<'db> { | |
| 1025 | Assign(Place<'db>, Rvalue<'db>), | |
| 1026 | FakeRead(Place<'db>), | |
| 1020 | 1027 | //SetDiscriminant { |
| 1021 | 1028 | // place: Box<Place>, |
| 1022 | 1029 | // variant_index: VariantIdx, |
| 1023 | 1030 | //}, |
| 1024 | Deinit(Place), | |
| 1025 | StorageLive(LocalId), | |
| 1026 | StorageDead(LocalId), | |
| 1031 | Deinit(Place<'db>), | |
| 1032 | StorageLive(LocalId<'db>), | |
| 1033 | StorageDead(LocalId<'db>), | |
| 1027 | 1034 | //Retag(RetagKind, Box<Place>), |
| 1028 | 1035 | //AscribeUserType(Place, UserTypeProjection, Variance), |
| 1029 | 1036 | //Intrinsic(Box<NonDivergingIntrinsic>), |
| 1030 | 1037 | Nop, |
| 1031 | 1038 | } |
| 1032 | impl StatementKind { | |
| 1033 | fn with_span(self, span: MirSpan) -> Statement { | |
| 1039 | impl<'db> StatementKind<'db> { | |
| 1040 | fn with_span(self, span: MirSpan) -> Statement<'db> { | |
| 1034 | 1041 | Statement { kind: self, span } |
| 1035 | 1042 | } |
| 1036 | 1043 | } |
| 1037 | 1044 | |
| 1038 | 1045 | #[derive(Debug, PartialEq, Eq, Clone)] |
| 1039 | pub struct Statement { | |
| 1040 | pub kind: StatementKind, | |
| 1046 | pub struct Statement<'db> { | |
| 1047 | pub kind: StatementKind<'db>, | |
| 1041 | 1048 | pub span: MirSpan, |
| 1042 | 1049 | } |
| 1043 | 1050 | |
| 1044 | 1051 | #[derive(Debug, Default, Clone, PartialEq, Eq)] |
| 1045 | pub struct BasicBlock { | |
| 1052 | pub struct BasicBlock<'db> { | |
| 1046 | 1053 | /// List of statements in this block. |
| 1047 | pub statements: Vec<Statement>, | |
| 1054 | pub statements: Vec<Statement<'db>>, | |
| 1048 | 1055 | |
| 1049 | 1056 | /// Terminator for this block. |
| 1050 | 1057 | /// |
| ... | ... | @@ -1054,7 +1061,7 @@ pub struct BasicBlock { |
| 1054 | 1061 | /// exception is that certain passes, such as `simplify_cfg`, swap |
| 1055 | 1062 | /// out the terminator temporarily with `None` while they continue |
| 1056 | 1063 | /// to recurse over the set of basic blocks. |
| 1057 | pub terminator: Option<Terminator>, | |
| 1064 | pub terminator: Option<Terminator<'db>>, | |
| 1058 | 1065 | |
| 1059 | 1066 | /// If true, this block lies on an unwind path. This is used |
| 1060 | 1067 | /// during codegen where distinct kinds of basic blocks may be |
| ... | ... | @@ -1064,35 +1071,35 @@ pub struct BasicBlock { |
| 1064 | 1071 | } |
| 1065 | 1072 | |
| 1066 | 1073 | #[derive(Debug, Clone, PartialEq, Eq)] |
| 1067 | pub struct MirBody { | |
| 1068 | pub projection_store: ProjectionStore, | |
| 1069 | pub basic_blocks: Arena<BasicBlock>, | |
| 1070 | pub locals: Arena<Local>, | |
| 1071 | pub start_block: BasicBlockId, | |
| 1074 | pub struct MirBody<'db> { | |
| 1075 | pub projection_store: ProjectionStore<'db>, | |
| 1076 | pub basic_blocks: Arena<BasicBlock<'db>>, | |
| 1077 | pub locals: Arena<Local<'db>>, | |
| 1078 | pub start_block: BasicBlockId<'db>, | |
| 1072 | 1079 | pub owner: DefWithBodyId, |
| 1073 | pub binding_locals: ArenaMap<BindingId, LocalId>, | |
| 1074 | pub param_locals: Vec<LocalId>, | |
| 1080 | pub binding_locals: ArenaMap<BindingId, LocalId<'db>>, | |
| 1081 | pub param_locals: Vec<LocalId<'db>>, | |
| 1075 | 1082 | /// This field stores the closures directly owned by this body. It is used |
| 1076 | 1083 | /// in traversing every mir body. |
| 1077 | pub closures: Vec<ClosureId>, | |
| 1084 | pub closures: Vec<InternedClosureId>, | |
| 1078 | 1085 | } |
| 1079 | 1086 | |
| 1080 | impl MirBody { | |
| 1081 | pub fn local_to_binding_map(&self) -> ArenaMap<LocalId, BindingId> { | |
| 1087 | impl<'db> MirBody<'db> { | |
| 1088 | pub fn local_to_binding_map(&self) -> ArenaMap<LocalId<'db>, BindingId> { | |
| 1082 | 1089 | self.binding_locals.iter().map(|(it, y)| (*y, it)).collect() |
| 1083 | 1090 | } |
| 1084 | 1091 | |
| 1085 | fn walk_places(&mut self, mut f: impl FnMut(&mut Place, &mut ProjectionStore)) { | |
| 1086 | fn for_operand( | |
| 1087 | op: &mut Operand, | |
| 1088 | f: &mut impl FnMut(&mut Place, &mut ProjectionStore), | |
| 1089 | store: &mut ProjectionStore, | |
| 1092 | fn walk_places(&mut self, mut f: impl FnMut(&mut Place<'db>, &mut ProjectionStore<'db>)) { | |
| 1093 | fn for_operand<'db>( | |
| 1094 | op: &mut Operand<'db>, | |
| 1095 | f: &mut impl FnMut(&mut Place<'db>, &mut ProjectionStore<'db>), | |
| 1096 | store: &mut ProjectionStore<'db>, | |
| 1090 | 1097 | ) { |
| 1091 | 1098 | match &mut op.kind { |
| 1092 | 1099 | OperandKind::Copy(p) | OperandKind::Move(p) => { |
| 1093 | 1100 | f(p, store); |
| 1094 | 1101 | } |
| 1095 | OperandKind::Constant(_) | OperandKind::Static(_) => (), | |
| 1102 | OperandKind::Constant { .. } | OperandKind::Static(_) => (), | |
| 1096 | 1103 | } |
| 1097 | 1104 | } |
| 1098 | 1105 | for (_, block) in self.basic_blocks.iter_mut() { |
src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs+118-86| ... | ... | @@ -12,11 +12,14 @@ use stdx::never; |
| 12 | 12 | use triomphe::Arc; |
| 13 | 13 | |
| 14 | 14 | use crate::{ |
| 15 | ClosureId, Interner, Substitution, Ty, TyExt, TypeFlags, | |
| 16 | db::{HirDatabase, InternedClosure}, | |
| 15 | TraitEnvironment, | |
| 16 | db::{HirDatabase, InternedClosure, InternedClosureId}, | |
| 17 | 17 | display::DisplayTarget, |
| 18 | 18 | mir::OperandKind, |
| 19 | utils::ClosureSubst, | |
| 19 | next_solver::{ | |
| 20 | DbInterner, GenericArgs, SolverDefIds, Ty, TypingMode, | |
| 21 | infer::{DbInternerInferExt, InferCtxt}, | |
| 22 | }, | |
| 20 | 23 | }; |
| 21 | 24 | |
| 22 | 25 | use super::{ |
| ... | ... | @@ -33,45 +36,45 @@ pub enum MutabilityReason { |
| 33 | 36 | } |
| 34 | 37 | |
| 35 | 38 | #[derive(Debug, Clone, PartialEq, Eq)] |
| 36 | pub struct MovedOutOfRef { | |
| 37 | pub ty: Ty, | |
| 39 | pub struct MovedOutOfRef<'db> { | |
| 40 | pub ty: Ty<'db>, | |
| 38 | 41 | pub span: MirSpan, |
| 39 | 42 | } |
| 40 | 43 | |
| 41 | 44 | #[derive(Debug, Clone, PartialEq, Eq)] |
| 42 | pub struct PartiallyMoved { | |
| 43 | pub ty: Ty, | |
| 45 | pub struct PartiallyMoved<'db> { | |
| 46 | pub ty: Ty<'db>, | |
| 44 | 47 | pub span: MirSpan, |
| 45 | pub local: LocalId, | |
| 48 | pub local: LocalId<'db>, | |
| 46 | 49 | } |
| 47 | 50 | |
| 48 | 51 | #[derive(Debug, Clone, PartialEq, Eq)] |
| 49 | pub struct BorrowRegion { | |
| 50 | pub local: LocalId, | |
| 52 | pub struct BorrowRegion<'db> { | |
| 53 | pub local: LocalId<'db>, | |
| 51 | 54 | pub kind: BorrowKind, |
| 52 | 55 | pub places: Vec<MirSpan>, |
| 53 | 56 | } |
| 54 | 57 | |
| 55 | 58 | #[derive(Debug, Clone, PartialEq, Eq)] |
| 56 | pub struct BorrowckResult { | |
| 57 | pub mir_body: Arc<MirBody>, | |
| 58 | pub mutability_of_locals: ArenaMap<LocalId, MutabilityReason>, | |
| 59 | pub moved_out_of_ref: Vec<MovedOutOfRef>, | |
| 60 | pub partially_moved: Vec<PartiallyMoved>, | |
| 61 | pub borrow_regions: Vec<BorrowRegion>, | |
| 59 | pub struct BorrowckResult<'db> { | |
| 60 | pub mir_body: Arc<MirBody<'db>>, | |
| 61 | pub mutability_of_locals: ArenaMap<LocalId<'db>, MutabilityReason>, | |
| 62 | pub moved_out_of_ref: Vec<MovedOutOfRef<'db>>, | |
| 63 | pub partially_moved: Vec<PartiallyMoved<'db>>, | |
| 64 | pub borrow_regions: Vec<BorrowRegion<'db>>, | |
| 62 | 65 | } |
| 63 | 66 | |
| 64 | fn all_mir_bodies( | |
| 65 | db: &dyn HirDatabase, | |
| 67 | fn all_mir_bodies<'db>( | |
| 68 | db: &'db dyn HirDatabase, | |
| 66 | 69 | def: DefWithBodyId, |
| 67 | mut cb: impl FnMut(Arc<MirBody>), | |
| 68 | ) -> Result<(), MirLowerError> { | |
| 69 | fn for_closure( | |
| 70 | db: &dyn HirDatabase, | |
| 71 | c: ClosureId, | |
| 72 | cb: &mut impl FnMut(Arc<MirBody>), | |
| 73 | ) -> Result<(), MirLowerError> { | |
| 74 | match db.mir_body_for_closure(c.into()) { | |
| 70 | mut cb: impl FnMut(Arc<MirBody<'db>>), | |
| 71 | ) -> Result<(), MirLowerError<'db>> { | |
| 72 | fn for_closure<'db>( | |
| 73 | db: &'db dyn HirDatabase, | |
| 74 | c: InternedClosureId, | |
| 75 | cb: &mut impl FnMut(Arc<MirBody<'db>>), | |
| 76 | ) -> Result<(), MirLowerError<'db>> { | |
| 77 | match db.mir_body_for_closure(c) { | |
| 75 | 78 | Ok(body) => { |
| 76 | 79 | cb(body.clone()); |
| 77 | 80 | body.closures.iter().try_for_each(|&it| for_closure(db, it, cb)) |
| ... | ... | @@ -88,17 +91,24 @@ fn all_mir_bodies( |
| 88 | 91 | } |
| 89 | 92 | } |
| 90 | 93 | |
| 91 | pub fn borrowck_query( | |
| 92 | db: &dyn HirDatabase, | |
| 94 | pub fn borrowck_query<'db>( | |
| 95 | db: &'db dyn HirDatabase, | |
| 93 | 96 | def: DefWithBodyId, |
| 94 | ) -> Result<Arc<[BorrowckResult]>, MirLowerError> { | |
| 97 | ) -> Result<Arc<[BorrowckResult<'db>]>, MirLowerError<'db>> { | |
| 95 | 98 | let _p = tracing::info_span!("borrowck_query").entered(); |
| 99 | let module = def.module(db); | |
| 100 | let interner = DbInterner::new_with(db, Some(module.krate()), module.containing_block()); | |
| 101 | let env = db.trait_environment_for_body(def); | |
| 96 | 102 | let mut res = vec![]; |
| 97 | 103 | all_mir_bodies(db, def, |body| { |
| 104 | // FIXME(next-solver): Opaques. | |
| 105 | let infcx = interner.infer_ctxt().build(TypingMode::Borrowck { | |
| 106 | defining_opaque_types: SolverDefIds::new_from_iter(interner, []), | |
| 107 | }); | |
| 98 | 108 | res.push(BorrowckResult { |
| 99 | mutability_of_locals: mutability_of_locals(db, &body), | |
| 100 | moved_out_of_ref: moved_out_of_ref(db, &body), | |
| 101 | partially_moved: partially_moved(db, &body), | |
| 109 | mutability_of_locals: mutability_of_locals(&infcx, &body), | |
| 110 | moved_out_of_ref: moved_out_of_ref(&infcx, &env, &body), | |
| 111 | partially_moved: partially_moved(&infcx, &env, &body), | |
| 102 | 112 | borrow_regions: borrow_regions(db, &body), |
| 103 | 113 | mir_body: body, |
| 104 | 114 | }); |
| ... | ... | @@ -106,48 +116,49 @@ pub fn borrowck_query( |
| 106 | 116 | Ok(res.into()) |
| 107 | 117 | } |
| 108 | 118 | |
| 109 | fn make_fetch_closure_field( | |
| 110 | db: &dyn HirDatabase, | |
| 111 | ) -> impl FnOnce(ClosureId, &Substitution, usize) -> Ty + '_ { | |
| 112 | |c: ClosureId, subst: &Substitution, f: usize| { | |
| 113 | let InternedClosure(def, _) = db.lookup_intern_closure(c.into()); | |
| 119 | fn make_fetch_closure_field<'db>( | |
| 120 | db: &'db dyn HirDatabase, | |
| 121 | ) -> impl FnOnce(InternedClosureId, GenericArgs<'db>, usize) -> Ty<'db> + use<'db> { | |
| 122 | |c: InternedClosureId, subst: GenericArgs<'db>, f: usize| { | |
| 123 | let InternedClosure(def, _) = db.lookup_intern_closure(c); | |
| 114 | 124 | let infer = db.infer(def); |
| 115 | let (captures, _) = infer.closure_info(&c); | |
| 116 | let parent_subst = ClosureSubst(subst).parent_subst(db); | |
| 117 | captures | |
| 118 | .get(f) | |
| 119 | .expect("broken closure field") | |
| 120 | .ty | |
| 121 | .clone() | |
| 122 | .substitute(Interner, &parent_subst) | |
| 125 | let (captures, _) = infer.closure_info(c); | |
| 126 | let parent_subst = subst.split_closure_args_untupled().parent_args; | |
| 127 | let interner = DbInterner::new_with(db, None, None); | |
| 128 | captures.get(f).expect("broken closure field").ty.instantiate(interner, parent_subst) | |
| 123 | 129 | } |
| 124 | 130 | } |
| 125 | 131 | |
| 126 | fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec<MovedOutOfRef> { | |
| 132 | fn moved_out_of_ref<'db>( | |
| 133 | infcx: &InferCtxt<'db>, | |
| 134 | env: &TraitEnvironment<'db>, | |
| 135 | body: &MirBody<'db>, | |
| 136 | ) -> Vec<MovedOutOfRef<'db>> { | |
| 137 | let db = infcx.interner.db; | |
| 127 | 138 | let mut result = vec![]; |
| 128 | let mut for_operand = |op: &Operand, span: MirSpan| match op.kind { | |
| 139 | let mut for_operand = |op: &Operand<'db>, span: MirSpan| match op.kind { | |
| 129 | 140 | OperandKind::Copy(p) | OperandKind::Move(p) => { |
| 130 | let mut ty: Ty = body.locals[p.local].ty.clone(); | |
| 141 | let mut ty: Ty<'db> = body.locals[p.local].ty; | |
| 131 | 142 | let mut is_dereference_of_ref = false; |
| 132 | 143 | for proj in p.projection.lookup(&body.projection_store) { |
| 133 | 144 | if *proj == ProjectionElem::Deref && ty.as_reference().is_some() { |
| 134 | 145 | is_dereference_of_ref = true; |
| 135 | 146 | } |
| 136 | 147 | ty = proj.projected_ty( |
| 148 | infcx, | |
| 137 | 149 | ty, |
| 138 | db, | |
| 139 | 150 | make_fetch_closure_field(db), |
| 140 | 151 | body.owner.module(db).krate(), |
| 141 | 152 | ); |
| 142 | 153 | } |
| 143 | 154 | if is_dereference_of_ref |
| 144 | && !ty.clone().is_copy(db, body.owner) | |
| 145 | && !ty.data(Interner).flags.intersects(TypeFlags::HAS_ERROR) | |
| 155 | && !infcx.type_is_copy_modulo_regions(env.env, ty) | |
| 156 | && !ty.references_non_lt_error() | |
| 146 | 157 | { |
| 147 | 158 | result.push(MovedOutOfRef { span: op.span.unwrap_or(span), ty }); |
| 148 | 159 | } |
| 149 | 160 | } |
| 150 | OperandKind::Constant(_) | OperandKind::Static(_) => (), | |
| 161 | OperandKind::Constant { .. } | OperandKind::Static(_) => (), | |
| 151 | 162 | }; |
| 152 | 163 | for (_, block) in body.basic_blocks.iter() { |
| 153 | 164 | db.unwind_if_revision_cancelled(); |
| ... | ... | @@ -218,26 +229,29 @@ fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec<MovedOutOfRef> |
| 218 | 229 | result |
| 219 | 230 | } |
| 220 | 231 | |
| 221 | fn partially_moved(db: &dyn HirDatabase, body: &MirBody) -> Vec<PartiallyMoved> { | |
| 232 | fn partially_moved<'db>( | |
| 233 | infcx: &InferCtxt<'db>, | |
| 234 | env: &TraitEnvironment<'db>, | |
| 235 | body: &MirBody<'db>, | |
| 236 | ) -> Vec<PartiallyMoved<'db>> { | |
| 237 | let db = infcx.interner.db; | |
| 222 | 238 | let mut result = vec![]; |
| 223 | let mut for_operand = |op: &Operand, span: MirSpan| match op.kind { | |
| 239 | let mut for_operand = |op: &Operand<'db>, span: MirSpan| match op.kind { | |
| 224 | 240 | OperandKind::Copy(p) | OperandKind::Move(p) => { |
| 225 | let mut ty: Ty = body.locals[p.local].ty.clone(); | |
| 241 | let mut ty: Ty<'db> = body.locals[p.local].ty; | |
| 226 | 242 | for proj in p.projection.lookup(&body.projection_store) { |
| 227 | 243 | ty = proj.projected_ty( |
| 244 | infcx, | |
| 228 | 245 | ty, |
| 229 | db, | |
| 230 | 246 | make_fetch_closure_field(db), |
| 231 | 247 | body.owner.module(db).krate(), |
| 232 | 248 | ); |
| 233 | 249 | } |
| 234 | if !ty.clone().is_copy(db, body.owner) | |
| 235 | && !ty.data(Interner).flags.intersects(TypeFlags::HAS_ERROR) | |
| 236 | { | |
| 250 | if !infcx.type_is_copy_modulo_regions(env.env, ty) && !ty.references_non_lt_error() { | |
| 237 | 251 | result.push(PartiallyMoved { span, ty, local: p.local }); |
| 238 | 252 | } |
| 239 | 253 | } |
| 240 | OperandKind::Constant(_) | OperandKind::Static(_) => (), | |
| 254 | OperandKind::Constant { .. } | OperandKind::Static(_) => (), | |
| 241 | 255 | }; |
| 242 | 256 | for (_, block) in body.basic_blocks.iter() { |
| 243 | 257 | db.unwind_if_revision_cancelled(); |
| ... | ... | @@ -308,7 +322,7 @@ fn partially_moved(db: &dyn HirDatabase, body: &MirBody) -> Vec<PartiallyMoved> |
| 308 | 322 | result |
| 309 | 323 | } |
| 310 | 324 | |
| 311 | fn borrow_regions(db: &dyn HirDatabase, body: &MirBody) -> Vec<BorrowRegion> { | |
| 325 | fn borrow_regions<'db>(db: &'db dyn HirDatabase, body: &MirBody<'db>) -> Vec<BorrowRegion<'db>> { | |
| 312 | 326 | let mut borrows = FxHashMap::default(); |
| 313 | 327 | for (_, block) in body.basic_blocks.iter() { |
| 314 | 328 | db.unwind_if_revision_cancelled(); |
| ... | ... | @@ -316,7 +330,7 @@ fn borrow_regions(db: &dyn HirDatabase, body: &MirBody) -> Vec<BorrowRegion> { |
| 316 | 330 | if let StatementKind::Assign(_, Rvalue::Ref(kind, p)) = &statement.kind { |
| 317 | 331 | borrows |
| 318 | 332 | .entry(p.local) |
| 319 | .and_modify(|it: &mut BorrowRegion| { | |
| 333 | .and_modify(|it: &mut BorrowRegion<'db>| { | |
| 320 | 334 | it.places.push(statement.span); |
| 321 | 335 | }) |
| 322 | 336 | .or_insert_with(|| BorrowRegion { |
| ... | ... | @@ -358,9 +372,14 @@ enum ProjectionCase { |
| 358 | 372 | Indirect, |
| 359 | 373 | } |
| 360 | 374 | |
| 361 | fn place_case(db: &dyn HirDatabase, body: &MirBody, lvalue: &Place) -> ProjectionCase { | |
| 375 | fn place_case<'db>( | |
| 376 | infcx: &InferCtxt<'db>, | |
| 377 | body: &MirBody<'db>, | |
| 378 | lvalue: &Place<'db>, | |
| 379 | ) -> ProjectionCase { | |
| 380 | let db = infcx.interner.db; | |
| 362 | 381 | let mut is_part_of = false; |
| 363 | let mut ty = body.locals[lvalue.local].ty.clone(); | |
| 382 | let mut ty = body.locals[lvalue.local].ty; | |
| 364 | 383 | for proj in lvalue.projection.lookup(&body.projection_store).iter() { |
| 365 | 384 | match proj { |
| 366 | 385 | ProjectionElem::Deref if ty.as_adt().is_none() => return ProjectionCase::Indirect, // It's indirect in case of reference and raw |
| ... | ... | @@ -374,7 +393,12 @@ fn place_case(db: &dyn HirDatabase, body: &MirBody, lvalue: &Place) -> Projectio |
| 374 | 393 | } |
| 375 | 394 | ProjectionElem::OpaqueCast(_) => (), |
| 376 | 395 | } |
| 377 | ty = proj.projected_ty(ty, db, make_fetch_closure_field(db), body.owner.module(db).krate()); | |
| 396 | ty = proj.projected_ty( | |
| 397 | infcx, | |
| 398 | ty, | |
| 399 | make_fetch_closure_field(db), | |
| 400 | body.owner.module(db).krate(), | |
| 401 | ); | |
| 378 | 402 | } |
| 379 | 403 | if is_part_of { ProjectionCase::DirectPart } else { ProjectionCase::Direct } |
| 380 | 404 | } |
| ... | ... | @@ -382,18 +406,18 @@ fn place_case(db: &dyn HirDatabase, body: &MirBody, lvalue: &Place) -> Projectio |
| 382 | 406 | /// Returns a map from basic blocks to the set of locals that might be ever initialized before |
| 383 | 407 | /// the start of the block. Only `StorageDead` can remove something from this map, and we ignore |
| 384 | 408 | /// `Uninit` and `drop` and similar after initialization. |
| 385 | fn ever_initialized_map( | |
| 386 | db: &dyn HirDatabase, | |
| 387 | body: &MirBody, | |
| 388 | ) -> ArenaMap<BasicBlockId, ArenaMap<LocalId, bool>> { | |
| 389 | let mut result: ArenaMap<BasicBlockId, ArenaMap<LocalId, bool>> = | |
| 409 | fn ever_initialized_map<'db>( | |
| 410 | db: &'db dyn HirDatabase, | |
| 411 | body: &MirBody<'db>, | |
| 412 | ) -> ArenaMap<BasicBlockId<'db>, ArenaMap<LocalId<'db>, bool>> { | |
| 413 | let mut result: ArenaMap<BasicBlockId<'db>, ArenaMap<LocalId<'db>, bool>> = | |
| 390 | 414 | body.basic_blocks.iter().map(|it| (it.0, ArenaMap::default())).collect(); |
| 391 | fn dfs( | |
| 392 | db: &dyn HirDatabase, | |
| 393 | body: &MirBody, | |
| 394 | l: LocalId, | |
| 395 | stack: &mut Vec<BasicBlockId>, | |
| 396 | result: &mut ArenaMap<BasicBlockId, ArenaMap<LocalId, bool>>, | |
| 415 | fn dfs<'db>( | |
| 416 | db: &'db dyn HirDatabase, | |
| 417 | body: &MirBody<'db>, | |
| 418 | l: LocalId<'db>, | |
| 419 | stack: &mut Vec<BasicBlockId<'db>>, | |
| 420 | result: &mut ArenaMap<BasicBlockId<'db>, ArenaMap<LocalId<'db>, bool>>, | |
| 397 | 421 | ) { |
| 398 | 422 | while let Some(b) = stack.pop() { |
| 399 | 423 | let mut is_ever_initialized = result[b][l]; // It must be filled, as we use it as mark for dfs |
| ... | ... | @@ -481,7 +505,11 @@ fn ever_initialized_map( |
| 481 | 505 | result |
| 482 | 506 | } |
| 483 | 507 | |
| 484 | fn push_mut_span(local: LocalId, span: MirSpan, result: &mut ArenaMap<LocalId, MutabilityReason>) { | |
| 508 | fn push_mut_span<'db>( | |
| 509 | local: LocalId<'db>, | |
| 510 | span: MirSpan, | |
| 511 | result: &mut ArenaMap<LocalId<'db>, MutabilityReason>, | |
| 512 | ) { | |
| 485 | 513 | match &mut result[local] { |
| 486 | 514 | MutabilityReason::Mut { spans } => spans.push(span), |
| 487 | 515 | it @ (MutabilityReason::Not | MutabilityReason::Unused) => { |
| ... | ... | @@ -490,23 +518,27 @@ fn push_mut_span(local: LocalId, span: MirSpan, result: &mut ArenaMap<LocalId, M |
| 490 | 518 | }; |
| 491 | 519 | } |
| 492 | 520 | |
| 493 | fn record_usage(local: LocalId, result: &mut ArenaMap<LocalId, MutabilityReason>) { | |
| 521 | fn record_usage<'db>(local: LocalId<'db>, result: &mut ArenaMap<LocalId<'db>, MutabilityReason>) { | |
| 494 | 522 | if let it @ MutabilityReason::Unused = &mut result[local] { |
| 495 | 523 | *it = MutabilityReason::Not; |
| 496 | 524 | }; |
| 497 | 525 | } |
| 498 | 526 | |
| 499 | fn record_usage_for_operand(arg: &Operand, result: &mut ArenaMap<LocalId, MutabilityReason>) { | |
| 527 | fn record_usage_for_operand<'db>( | |
| 528 | arg: &Operand<'db>, | |
| 529 | result: &mut ArenaMap<LocalId<'db>, MutabilityReason>, | |
| 530 | ) { | |
| 500 | 531 | if let OperandKind::Copy(p) | OperandKind::Move(p) = arg.kind { |
| 501 | 532 | record_usage(p.local, result); |
| 502 | 533 | } |
| 503 | 534 | } |
| 504 | 535 | |
| 505 | fn mutability_of_locals( | |
| 506 | db: &dyn HirDatabase, | |
| 507 | body: &MirBody, | |
| 508 | ) -> ArenaMap<LocalId, MutabilityReason> { | |
| 509 | let mut result: ArenaMap<LocalId, MutabilityReason> = | |
| 536 | fn mutability_of_locals<'db>( | |
| 537 | infcx: &InferCtxt<'db>, | |
| 538 | body: &MirBody<'db>, | |
| 539 | ) -> ArenaMap<LocalId<'db>, MutabilityReason> { | |
| 540 | let db = infcx.interner.db; | |
| 541 | let mut result: ArenaMap<LocalId<'db>, MutabilityReason> = | |
| 510 | 542 | body.locals.iter().map(|it| (it.0, MutabilityReason::Unused)).collect(); |
| 511 | 543 | |
| 512 | 544 | let ever_init_maps = ever_initialized_map(db, body); |
| ... | ... | @@ -515,7 +547,7 @@ fn mutability_of_locals( |
| 515 | 547 | for statement in &block.statements { |
| 516 | 548 | match &statement.kind { |
| 517 | 549 | StatementKind::Assign(place, value) => { |
| 518 | match place_case(db, body, place) { | |
| 550 | match place_case(infcx, body, place) { | |
| 519 | 551 | ProjectionCase::Direct => { |
| 520 | 552 | if ever_init_map.get(place.local).copied().unwrap_or_default() { |
| 521 | 553 | push_mut_span(place.local, statement.span, &mut result); |
| ... | ... | @@ -564,7 +596,7 @@ fn mutability_of_locals( |
| 564 | 596 | }, |
| 565 | 597 | p, |
| 566 | 598 | ) = value |
| 567 | && place_case(db, body, p) != ProjectionCase::Indirect | |
| 599 | && place_case(infcx, body, p) != ProjectionCase::Indirect | |
| 568 | 600 | { |
| 569 | 601 | push_mut_span(p.local, statement.span, &mut result); |
| 570 | 602 | } |
src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs+479-497| ... | ... | @@ -2,14 +2,11 @@ |
| 2 | 2 | |
| 3 | 3 | use std::{borrow::Cow, cell::RefCell, fmt::Write, iter, mem, ops::Range}; |
| 4 | 4 | |
| 5 | use base_db::Crate; | |
| 6 | use base_db::target::TargetLoadError; | |
| 7 | use chalk_ir::{Mutability, cast::Cast}; | |
| 5 | use base_db::{Crate, target::TargetLoadError}; | |
| 8 | 6 | use either::Either; |
| 9 | 7 | use hir_def::{ |
| 10 | AdtId, DefWithBodyId, EnumVariantId, FunctionId, HasModule, ItemContainerId, Lookup, StaticId, | |
| 11 | VariantId, | |
| 12 | builtin_type::BuiltinType, | |
| 8 | AdtId, DefWithBodyId, EnumVariantId, FunctionId, GeneralConstId, HasModule, ItemContainerId, | |
| 9 | Lookup, StaticId, VariantId, | |
| 13 | 10 | expr_store::HygieneId, |
| 14 | 11 | item_tree::FieldsShape, |
| 15 | 12 | lang_item::LangItem, |
| ... | ... | @@ -25,30 +22,33 @@ use rustc_apfloat::{ |
| 25 | 22 | Float, |
| 26 | 23 | ieee::{Half as f16, Quad as f128}, |
| 27 | 24 | }; |
| 25 | use rustc_ast_ir::Mutability; | |
| 28 | 26 | use rustc_hash::{FxHashMap, FxHashSet}; |
| 29 | use rustc_type_ir::inherent::{AdtDef, IntoKind, SliceLike}; | |
| 27 | use rustc_type_ir::{ | |
| 28 | AliasTyKind, | |
| 29 | inherent::{AdtDef, IntoKind, Region as _, SliceLike, Ty as _}, | |
| 30 | }; | |
| 30 | 31 | use span::FileId; |
| 31 | 32 | use stdx::never; |
| 32 | 33 | use syntax::{SyntaxNodePtr, TextRange}; |
| 33 | 34 | use triomphe::Arc; |
| 34 | 35 | |
| 35 | 36 | use crate::{ |
| 36 | AliasTy, CallableDefId, ClosureId, ComplexMemoryMap, Const, ConstData, ConstScalar, Interner, | |
| 37 | MemoryMap, Substitution, ToChalk, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, | |
| 38 | consteval::{ConstEvalError, intern_const_scalar, try_const_usize}, | |
| 39 | consteval_nextsolver, | |
| 40 | db::{HirDatabase, InternedClosure}, | |
| 37 | CallableDefId, ComplexMemoryMap, MemoryMap, TraitEnvironment, | |
| 38 | consteval::{self, ConstEvalError, try_const_usize}, | |
| 39 | db::{HirDatabase, InternedClosure, InternedClosureId}, | |
| 41 | 40 | display::{ClosureStyle, DisplayTarget, HirDisplay}, |
| 42 | 41 | infer::PointerCast, |
| 43 | 42 | layout::{Layout, LayoutError, RustcEnumVariantIdx}, |
| 44 | 43 | method_resolution::{is_dyn_method, lookup_impl_const}, |
| 45 | 44 | next_solver::{ |
| 46 | DbInterner, | |
| 47 | mapping::{ChalkToNextSolver, convert_args_for_result, convert_ty_for_result}, | |
| 45 | Const, ConstBytes, ConstKind, DbInterner, ErrorGuaranteed, GenericArgs, Region, | |
| 46 | SolverDefId, Ty, TyKind, TypingMode, UnevaluatedConst, ValueConst, | |
| 47 | infer::{DbInternerInferExt, InferCtxt, traits::ObligationCause}, | |
| 48 | obligation_ctxt::ObligationCtxt, | |
| 48 | 49 | }, |
| 49 | static_lifetime, | |
| 50 | 50 | traits::FnTrait, |
| 51 | utils::{ClosureSubst, detect_variant_from_bytes}, | |
| 51 | utils::detect_variant_from_bytes, | |
| 52 | 52 | }; |
| 53 | 53 | |
| 54 | 54 | use super::{ |
| ... | ... | @@ -85,14 +85,14 @@ macro_rules! not_supported { |
| 85 | 85 | |
| 86 | 86 | #[derive(Debug, Default, Clone, PartialEq, Eq)] |
| 87 | 87 | pub struct VTableMap<'db> { |
| 88 | ty_to_id: FxHashMap<crate::next_solver::Ty<'db>, usize>, | |
| 89 | id_to_ty: Vec<crate::next_solver::Ty<'db>>, | |
| 88 | ty_to_id: FxHashMap<Ty<'db>, usize>, | |
| 89 | id_to_ty: Vec<Ty<'db>>, | |
| 90 | 90 | } |
| 91 | 91 | |
| 92 | 92 | impl<'db> VTableMap<'db> { |
| 93 | 93 | const OFFSET: usize = 1000; // We should add some offset to ids to make 0 (null) an invalid id. |
| 94 | 94 | |
| 95 | fn id(&mut self, ty: crate::next_solver::Ty<'db>) -> usize { | |
| 95 | fn id(&mut self, ty: Ty<'db>) -> usize { | |
| 96 | 96 | if let Some(it) = self.ty_to_id.get(&ty) { |
| 97 | 97 | return *it; |
| 98 | 98 | } |
| ... | ... | @@ -102,13 +102,13 @@ impl<'db> VTableMap<'db> { |
| 102 | 102 | id |
| 103 | 103 | } |
| 104 | 104 | |
| 105 | pub(crate) fn ty(&self, id: usize) -> Result<crate::next_solver::Ty<'db>> { | |
| 105 | pub(crate) fn ty(&self, id: usize) -> Result<'db, Ty<'db>> { | |
| 106 | 106 | id.checked_sub(VTableMap::OFFSET) |
| 107 | 107 | .and_then(|id| self.id_to_ty.get(id).copied()) |
| 108 | 108 | .ok_or(MirEvalError::InvalidVTableId(id)) |
| 109 | 109 | } |
| 110 | 110 | |
| 111 | fn ty_of_bytes(&self, bytes: &[u8]) -> Result<crate::next_solver::Ty<'db>> { | |
| 111 | fn ty_of_bytes(&self, bytes: &[u8]) -> Result<'db, Ty<'db>> { | |
| 112 | 112 | let id = from_bytes!(usize, bytes); |
| 113 | 113 | self.ty(id) |
| 114 | 114 | } |
| ... | ... | @@ -134,14 +134,14 @@ impl TlsData { |
| 134 | 134 | self.keys.len() - 1 |
| 135 | 135 | } |
| 136 | 136 | |
| 137 | fn get_key(&mut self, key: usize) -> Result<u128> { | |
| 137 | fn get_key(&mut self, key: usize) -> Result<'static, u128> { | |
| 138 | 138 | let r = self.keys.get(key).ok_or_else(|| { |
| 139 | 139 | MirEvalError::UndefinedBehavior(format!("Getting invalid tls key {key}")) |
| 140 | 140 | })?; |
| 141 | 141 | Ok(*r) |
| 142 | 142 | } |
| 143 | 143 | |
| 144 | fn set_key(&mut self, key: usize, value: u128) -> Result<()> { | |
| 144 | fn set_key(&mut self, key: usize, value: u128) -> Result<'static, ()> { | |
| 145 | 145 | let r = self.keys.get_mut(key).ok_or_else(|| { |
| 146 | 146 | MirEvalError::UndefinedBehavior(format!("Setting invalid tls key {key}")) |
| 147 | 147 | })?; |
| ... | ... | @@ -150,45 +150,45 @@ impl TlsData { |
| 150 | 150 | } |
| 151 | 151 | } |
| 152 | 152 | |
| 153 | struct StackFrame { | |
| 154 | locals: Locals, | |
| 155 | destination: Option<BasicBlockId>, | |
| 153 | struct StackFrame<'db> { | |
| 154 | locals: Locals<'db>, | |
| 155 | destination: Option<BasicBlockId<'db>>, | |
| 156 | 156 | prev_stack_ptr: usize, |
| 157 | 157 | span: (MirSpan, DefWithBodyId), |
| 158 | 158 | } |
| 159 | 159 | |
| 160 | 160 | #[derive(Clone)] |
| 161 | enum MirOrDynIndex { | |
| 162 | Mir(Arc<MirBody>), | |
| 161 | enum MirOrDynIndex<'db> { | |
| 162 | Mir(Arc<MirBody<'db>>), | |
| 163 | 163 | Dyn(usize), |
| 164 | 164 | } |
| 165 | 165 | |
| 166 | pub struct Evaluator<'a> { | |
| 167 | db: &'a dyn HirDatabase, | |
| 168 | trait_env: Arc<TraitEnvironment<'a>>, | |
| 166 | pub struct Evaluator<'db> { | |
| 167 | db: &'db dyn HirDatabase, | |
| 168 | trait_env: Arc<TraitEnvironment<'db>>, | |
| 169 | 169 | target_data_layout: Arc<TargetDataLayout>, |
| 170 | 170 | stack: Vec<u8>, |
| 171 | 171 | heap: Vec<u8>, |
| 172 | code_stack: Vec<StackFrame>, | |
| 172 | code_stack: Vec<StackFrame<'db>>, | |
| 173 | 173 | /// Stores the global location of the statics. We const evaluate every static first time we need it |
| 174 | 174 | /// and see it's missing, then we add it to this to reuse. |
| 175 | 175 | static_locations: FxHashMap<StaticId, Address>, |
| 176 | 176 | /// We don't really have function pointers, i.e. pointers to some assembly instructions that we can run. Instead, we |
| 177 | 177 | /// store the type as an interned id in place of function and vtable pointers, and we recover back the type at the |
| 178 | 178 | /// time of use. |
| 179 | vtable_map: VTableMap<'a>, | |
| 179 | vtable_map: VTableMap<'db>, | |
| 180 | 180 | thread_local_storage: TlsData, |
| 181 | 181 | random_state: oorandom::Rand64, |
| 182 | 182 | stdout: Vec<u8>, |
| 183 | 183 | stderr: Vec<u8>, |
| 184 | layout_cache: RefCell<FxHashMap<crate::next_solver::Ty<'a>, Arc<Layout>>>, | |
| 185 | projected_ty_cache: RefCell<FxHashMap<(Ty, PlaceElem), Ty>>, | |
| 184 | layout_cache: RefCell<FxHashMap<Ty<'db>, Arc<Layout>>>, | |
| 185 | projected_ty_cache: RefCell<FxHashMap<(Ty<'db>, PlaceElem<'db>), Ty<'db>>>, | |
| 186 | 186 | not_special_fn_cache: RefCell<FxHashSet<FunctionId>>, |
| 187 | mir_or_dyn_index_cache: RefCell<FxHashMap<(FunctionId, Substitution), MirOrDynIndex>>, | |
| 188 | /// Constantly dropping and creating `Locals` is very costly. We store | |
| 187 | mir_or_dyn_index_cache: RefCell<FxHashMap<(FunctionId, GenericArgs<'db>), MirOrDynIndex<'db>>>, | |
| 188 | /// Constantly dropping and creating `Locals<'db>` is very costly. We store | |
| 189 | 189 | /// old locals that we normally want to drop here, to reuse their allocations |
| 190 | 190 | /// later. |
| 191 | unused_locals_store: RefCell<FxHashMap<DefWithBodyId, Vec<Locals>>>, | |
| 191 | unused_locals_store: RefCell<FxHashMap<DefWithBodyId, Vec<Locals<'db>>>>, | |
| 192 | 192 | cached_ptr_size: usize, |
| 193 | 193 | cached_fn_trait_func: Option<FunctionId>, |
| 194 | 194 | cached_fn_mut_trait_func: Option<FunctionId>, |
| ... | ... | @@ -202,6 +202,7 @@ pub struct Evaluator<'a> { |
| 202 | 202 | stack_depth_limit: usize, |
| 203 | 203 | /// Maximum count of bytes that heap and stack can grow |
| 204 | 204 | memory_limit: usize, |
| 205 | infcx: InferCtxt<'db>, | |
| 205 | 206 | } |
| 206 | 207 | |
| 207 | 208 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
| ... | ... | @@ -220,9 +221,9 @@ struct Interval { |
| 220 | 221 | } |
| 221 | 222 | |
| 222 | 223 | #[derive(Debug, Clone)] |
| 223 | struct IntervalAndTy { | |
| 224 | struct IntervalAndTy<'db> { | |
| 224 | 225 | interval: Interval, |
| 225 | ty: Ty, | |
| 226 | ty: Ty<'db>, | |
| 226 | 227 | } |
| 227 | 228 | |
| 228 | 229 | impl Interval { |
| ... | ... | @@ -230,15 +231,19 @@ impl Interval { |
| 230 | 231 | Self { addr, size } |
| 231 | 232 | } |
| 232 | 233 | |
| 233 | fn get<'a, 'db>(&self, memory: &'a Evaluator<'db>) -> Result<&'a [u8]> { | |
| 234 | fn get<'a, 'db>(&self, memory: &'a Evaluator<'db>) -> Result<'db, &'a [u8]> { | |
| 234 | 235 | memory.read_memory(self.addr, self.size) |
| 235 | 236 | } |
| 236 | 237 | |
| 237 | fn write_from_bytes(&self, memory: &mut Evaluator<'_>, bytes: &[u8]) -> Result<()> { | |
| 238 | fn write_from_bytes<'db>(&self, memory: &mut Evaluator<'db>, bytes: &[u8]) -> Result<'db, ()> { | |
| 238 | 239 | memory.write_memory(self.addr, bytes) |
| 239 | 240 | } |
| 240 | 241 | |
| 241 | fn write_from_interval(&self, memory: &mut Evaluator<'_>, interval: Interval) -> Result<()> { | |
| 242 | fn write_from_interval<'db>( | |
| 243 | &self, | |
| 244 | memory: &mut Evaluator<'db>, | |
| 245 | interval: Interval, | |
| 246 | ) -> Result<'db, ()> { | |
| 242 | 247 | memory.copy_from_interval(self.addr, interval) |
| 243 | 248 | } |
| 244 | 249 | |
| ... | ... | @@ -247,18 +252,18 @@ impl Interval { |
| 247 | 252 | } |
| 248 | 253 | } |
| 249 | 254 | |
| 250 | impl IntervalAndTy { | |
| 251 | fn get<'a, 'db>(&self, memory: &'a Evaluator<'db>) -> Result<&'a [u8]> { | |
| 255 | impl<'db> IntervalAndTy<'db> { | |
| 256 | fn get<'a>(&self, memory: &'a Evaluator<'db>) -> Result<'db, &'a [u8]> { | |
| 252 | 257 | memory.read_memory(self.interval.addr, self.interval.size) |
| 253 | 258 | } |
| 254 | 259 | |
| 255 | 260 | fn new( |
| 256 | 261 | addr: Address, |
| 257 | ty: Ty, | |
| 258 | evaluator: &Evaluator<'_>, | |
| 259 | locals: &Locals, | |
| 260 | ) -> Result<IntervalAndTy> { | |
| 261 | let size = evaluator.size_of_sized(&ty, locals, "type of interval")?; | |
| 262 | ty: Ty<'db>, | |
| 263 | evaluator: &Evaluator<'db>, | |
| 264 | locals: &Locals<'db>, | |
| 265 | ) -> Result<'db, IntervalAndTy<'db>> { | |
| 266 | let size = evaluator.size_of_sized(ty, locals, "type of interval")?; | |
| 262 | 267 | Ok(IntervalAndTy { interval: Interval { addr, size }, ty }) |
| 263 | 268 | } |
| 264 | 269 | } |
| ... | ... | @@ -275,7 +280,7 @@ impl From<Interval> for IntervalOrOwned { |
| 275 | 280 | } |
| 276 | 281 | |
| 277 | 282 | impl IntervalOrOwned { |
| 278 | fn get<'a, 'db>(&'a self, memory: &'a Evaluator<'db>) -> Result<&'a [u8]> { | |
| 283 | fn get<'a, 'db>(&'a self, memory: &'a Evaluator<'db>) -> Result<'db, &'a [u8]> { | |
| 279 | 284 | Ok(match self { |
| 280 | 285 | IntervalOrOwned::Owned(o) => o, |
| 281 | 286 | IntervalOrOwned::Borrowed(b) => b.get(memory)?, |
| ... | ... | @@ -295,7 +300,7 @@ const HEAP_OFFSET: usize = 1 << 29; |
| 295 | 300 | |
| 296 | 301 | impl Address { |
| 297 | 302 | #[allow(clippy::double_parens)] |
| 298 | fn from_bytes(it: &[u8]) -> Result<Self> { | |
| 303 | fn from_bytes<'db>(it: &[u8]) -> Result<'db, Self> { | |
| 299 | 304 | Ok(Address::from_usize(from_bytes!(usize, it))) |
| 300 | 305 | } |
| 301 | 306 | |
| ... | ... | @@ -335,32 +340,35 @@ impl Address { |
| 335 | 340 | } |
| 336 | 341 | |
| 337 | 342 | #[derive(Clone, PartialEq, Eq)] |
| 338 | pub enum MirEvalError { | |
| 339 | ConstEvalError(String, Box<ConstEvalError>), | |
| 340 | LayoutError(LayoutError, Ty), | |
| 343 | pub enum MirEvalError<'db> { | |
| 344 | ConstEvalError(String, Box<ConstEvalError<'db>>), | |
| 345 | LayoutError(LayoutError, Ty<'db>), | |
| 341 | 346 | TargetDataLayoutNotAvailable(TargetLoadError), |
| 342 | 347 | /// Means that code had undefined behavior. We don't try to actively detect UB, but if it was detected |
| 343 | 348 | /// then use this type of error. |
| 344 | 349 | UndefinedBehavior(String), |
| 345 | 350 | Panic(String), |
| 346 | 351 | // FIXME: This should be folded into ConstEvalError? |
| 347 | MirLowerError(FunctionId, MirLowerError), | |
| 348 | MirLowerErrorForClosure(ClosureId, MirLowerError), | |
| 349 | TypeIsUnsized(Ty, &'static str), | |
| 352 | MirLowerError(FunctionId, MirLowerError<'db>), | |
| 353 | MirLowerErrorForClosure(InternedClosureId, MirLowerError<'db>), | |
| 354 | TypeIsUnsized(Ty<'db>, &'static str), | |
| 350 | 355 | NotSupported(String), |
| 351 | InvalidConst(Const), | |
| 352 | InFunction(Box<MirEvalError>, Vec<(Either<FunctionId, ClosureId>, MirSpan, DefWithBodyId)>), | |
| 356 | InvalidConst(Const<'db>), | |
| 357 | InFunction( | |
| 358 | Box<MirEvalError<'db>>, | |
| 359 | Vec<(Either<FunctionId, InternedClosureId>, MirSpan, DefWithBodyId)>, | |
| 360 | ), | |
| 353 | 361 | ExecutionLimitExceeded, |
| 354 | 362 | StackOverflow, |
| 355 | 363 | /// FIXME: Fold this into InternalError |
| 356 | 364 | InvalidVTableId(usize), |
| 357 | 365 | /// ? |
| 358 | CoerceUnsizedError(Ty), | |
| 366 | CoerceUnsizedError(Ty<'db>), | |
| 359 | 367 | /// These should not occur, usually indicates a bug in mir lowering. |
| 360 | 368 | InternalError(Box<str>), |
| 361 | 369 | } |
| 362 | 370 | |
| 363 | impl MirEvalError { | |
| 371 | impl MirEvalError<'_> { | |
| 364 | 372 | pub fn pretty_print( |
| 365 | 373 | &self, |
| 366 | 374 | f: &mut String, |
| ... | ... | @@ -431,13 +439,8 @@ impl MirEvalError { |
| 431 | 439 | let function_name = db.function_signature(*func); |
| 432 | 440 | let self_ = match func.lookup(db).container { |
| 433 | 441 | ItemContainerId::ImplId(impl_id) => Some({ |
| 434 | let generics = crate::generics::generics(db, impl_id.into()); | |
| 435 | let interner = DbInterner::new_with(db, None, None); | |
| 436 | let substs = generics.placeholder_subst(db); | |
| 437 | let args: crate::next_solver::GenericArgs<'_> = | |
| 438 | substs.to_nextsolver(interner); | |
| 439 | 442 | db.impl_self_ty(impl_id) |
| 440 | .instantiate(interner, args) | |
| 443 | .instantiate_identity() | |
| 441 | 444 | .display(db, display_target) |
| 442 | 445 | .to_string() |
| 443 | 446 | }), |
| ... | ... | @@ -492,7 +495,7 @@ impl MirEvalError { |
| 492 | 495 | } |
| 493 | 496 | } |
| 494 | 497 | |
| 495 | impl std::fmt::Debug for MirEvalError { | |
| 498 | impl std::fmt::Debug for MirEvalError<'_> { | |
| 496 | 499 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 497 | 500 | match self { |
| 498 | 501 | Self::ConstEvalError(arg0, arg1) => { |
| ... | ... | @@ -523,10 +526,7 @@ impl std::fmt::Debug for MirEvalError { |
| 523 | 526 | Self::InternalError(arg0) => f.debug_tuple("InternalError").field(arg0).finish(), |
| 524 | 527 | Self::InvalidVTableId(arg0) => f.debug_tuple("InvalidVTableId").field(arg0).finish(), |
| 525 | 528 | Self::NotSupported(arg0) => f.debug_tuple("NotSupported").field(arg0).finish(), |
| 526 | Self::InvalidConst(arg0) => { | |
| 527 | let data = &arg0.data(Interner); | |
| 528 | f.debug_struct("InvalidConst").field("ty", &data.ty).field("value", &arg0).finish() | |
| 529 | } | |
| 529 | Self::InvalidConst(arg0) => f.debug_tuple("InvalidConst").field(&arg0).finish(), | |
| 530 | 530 | Self::InFunction(e, stack) => { |
| 531 | 531 | f.debug_struct("WithStack").field("error", e).field("stack", &stack).finish() |
| 532 | 532 | } |
| ... | ... | @@ -534,15 +534,15 @@ impl std::fmt::Debug for MirEvalError { |
| 534 | 534 | } |
| 535 | 535 | } |
| 536 | 536 | |
| 537 | type Result<T> = std::result::Result<T, MirEvalError>; | |
| 537 | type Result<'db, T> = std::result::Result<T, MirEvalError<'db>>; | |
| 538 | 538 | |
| 539 | 539 | #[derive(Debug, Default)] |
| 540 | struct DropFlags { | |
| 541 | need_drop: FxHashSet<Place>, | |
| 540 | struct DropFlags<'db> { | |
| 541 | need_drop: FxHashSet<Place<'db>>, | |
| 542 | 542 | } |
| 543 | 543 | |
| 544 | impl DropFlags { | |
| 545 | fn add_place(&mut self, p: Place, store: &ProjectionStore) { | |
| 544 | impl<'db> DropFlags<'db> { | |
| 545 | fn add_place(&mut self, p: Place<'db>, store: &ProjectionStore<'db>) { | |
| 546 | 546 | if p.iterate_over_parents(store).any(|it| self.need_drop.contains(&it)) { |
| 547 | 547 | return; |
| 548 | 548 | } |
| ... | ... | @@ -550,7 +550,7 @@ impl DropFlags { |
| 550 | 550 | self.need_drop.insert(p); |
| 551 | 551 | } |
| 552 | 552 | |
| 553 | fn remove_place(&mut self, p: &Place, store: &ProjectionStore) -> bool { | |
| 553 | fn remove_place(&mut self, p: &Place<'db>, store: &ProjectionStore<'db>) -> bool { | |
| 554 | 554 | // FIXME: replace parents with parts |
| 555 | 555 | if let Some(parent) = p.iterate_over_parents(store).find(|it| self.need_drop.contains(it)) { |
| 556 | 556 | self.need_drop.remove(&parent); |
| ... | ... | @@ -565,10 +565,10 @@ impl DropFlags { |
| 565 | 565 | } |
| 566 | 566 | |
| 567 | 567 | #[derive(Debug)] |
| 568 | struct Locals { | |
| 569 | ptr: ArenaMap<LocalId, Interval>, | |
| 570 | body: Arc<MirBody>, | |
| 571 | drop_flags: DropFlags, | |
| 568 | struct Locals<'db> { | |
| 569 | ptr: ArenaMap<LocalId<'db>, Interval>, | |
| 570 | body: Arc<MirBody<'db>>, | |
| 571 | drop_flags: DropFlags<'db>, | |
| 572 | 572 | } |
| 573 | 573 | |
| 574 | 574 | pub struct MirOutput { |
| ... | ... | @@ -587,7 +587,7 @@ impl MirOutput { |
| 587 | 587 | |
| 588 | 588 | pub fn interpret_mir<'db>( |
| 589 | 589 | db: &'db dyn HirDatabase, |
| 590 | body: Arc<MirBody>, | |
| 590 | body: Arc<MirBody<'db>>, | |
| 591 | 591 | // FIXME: This is workaround. Ideally, const generics should have a separate body (issue #7434), but now |
| 592 | 592 | // they share their body with their parent, so in MIR lowering we have locals of the parent body, which |
| 593 | 593 | // might have placeholders. With this argument, we (wrongly) assume that every placeholder type has |
| ... | ... | @@ -595,10 +595,10 @@ pub fn interpret_mir<'db>( |
| 595 | 595 | // (and probably should) do better here, for example by excluding bindings outside of the target expression. |
| 596 | 596 | assert_placeholder_ty_is_unused: bool, |
| 597 | 597 | trait_env: Option<Arc<TraitEnvironment<'db>>>, |
| 598 | ) -> Result<(Result<Const>, MirOutput)> { | |
| 599 | let ty = body.locals[return_slot()].ty.clone(); | |
| 598 | ) -> Result<'db, (Result<'db, Const<'db>>, MirOutput)> { | |
| 599 | let ty = body.locals[return_slot()].ty; | |
| 600 | 600 | let mut evaluator = Evaluator::new(db, body.owner, assert_placeholder_ty_is_unused, trait_env)?; |
| 601 | let it: Result<Const> = (|| { | |
| 601 | let it: Result<'db, Const<'db>> = (|| { | |
| 602 | 602 | if evaluator.ptr_size() != size_of::<usize>() { |
| 603 | 603 | not_supported!("targets with different pointer size from host"); |
| 604 | 604 | } |
| ... | ... | @@ -606,7 +606,7 @@ pub fn interpret_mir<'db>( |
| 606 | 606 | let bytes = interval.get(&evaluator)?; |
| 607 | 607 | let mut memory_map = evaluator.create_memory_map( |
| 608 | 608 | bytes, |
| 609 | &ty, | |
| 609 | ty, | |
| 610 | 610 | &Locals { ptr: ArenaMap::new(), body, drop_flags: DropFlags::default() }, |
| 611 | 611 | )?; |
| 612 | 612 | let bytes = bytes.into(); |
| ... | ... | @@ -617,13 +617,7 @@ pub fn interpret_mir<'db>( |
| 617 | 617 | memory_map.vtable.shrink_to_fit(); |
| 618 | 618 | MemoryMap::Complex(Box::new(memory_map)) |
| 619 | 619 | }; |
| 620 | // SAFETY: will never use this without a db | |
| 621 | Ok(intern_const_scalar( | |
| 622 | ConstScalar::Bytes(bytes, unsafe { | |
| 623 | std::mem::transmute::<MemoryMap<'_>, MemoryMap<'static>>(memory_map) | |
| 624 | }), | |
| 625 | ty, | |
| 626 | )) | |
| 620 | Ok(Const::new_valtree(evaluator.interner(), ty, bytes, memory_map)) | |
| 627 | 621 | })(); |
| 628 | 622 | Ok((it, MirOutput { stdout: evaluator.stdout, stderr: evaluator.stderr })) |
| 629 | 623 | } |
| ... | ... | @@ -639,13 +633,16 @@ impl<'db> Evaluator<'db> { |
| 639 | 633 | owner: DefWithBodyId, |
| 640 | 634 | assert_placeholder_ty_is_unused: bool, |
| 641 | 635 | trait_env: Option<Arc<TraitEnvironment<'db>>>, |
| 642 | ) -> Result<Evaluator<'db>> { | |
| 643 | let crate_id = owner.module(db).krate(); | |
| 636 | ) -> Result<'db, Evaluator<'db>> { | |
| 637 | let module = owner.module(db); | |
| 638 | let crate_id = module.krate(); | |
| 644 | 639 | let target_data_layout = match db.target_data_layout(crate_id) { |
| 645 | 640 | Ok(target_data_layout) => target_data_layout, |
| 646 | 641 | Err(e) => return Err(MirEvalError::TargetDataLayoutNotAvailable(e)), |
| 647 | 642 | }; |
| 648 | 643 | let cached_ptr_size = target_data_layout.pointer_size().bytes_usize(); |
| 644 | let interner = DbInterner::new_with(db, Some(crate_id), module.containing_block()); | |
| 645 | let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); | |
| 649 | 646 | Ok(Evaluator { |
| 650 | 647 | target_data_layout, |
| 651 | 648 | stack: vec![0], |
| ... | ... | @@ -679,19 +676,25 @@ impl<'db> Evaluator<'db> { |
| 679 | 676 | cached_fn_once_trait_func: LangItem::FnOnce.resolve_trait(db, crate_id).and_then(|x| { |
| 680 | 677 | x.trait_items(db).method_by_name(&Name::new_symbol_root(sym::call_once)) |
| 681 | 678 | }), |
| 679 | infcx, | |
| 682 | 680 | }) |
| 683 | 681 | } |
| 684 | 682 | |
| 685 | fn place_addr(&self, p: &Place, locals: &Locals) -> Result<Address> { | |
| 683 | #[inline] | |
| 684 | fn interner(&self) -> DbInterner<'db> { | |
| 685 | self.infcx.interner | |
| 686 | } | |
| 687 | ||
| 688 | fn place_addr(&self, p: &Place<'db>, locals: &Locals<'db>) -> Result<'db, Address> { | |
| 686 | 689 | Ok(self.place_addr_and_ty_and_metadata(p, locals)?.0) |
| 687 | 690 | } |
| 688 | 691 | |
| 689 | fn place_interval(&self, p: &Place, locals: &Locals) -> Result<Interval> { | |
| 692 | fn place_interval(&self, p: &Place<'db>, locals: &Locals<'db>) -> Result<'db, Interval> { | |
| 690 | 693 | let place_addr_and_ty = self.place_addr_and_ty_and_metadata(p, locals)?; |
| 691 | 694 | Ok(Interval { |
| 692 | 695 | addr: place_addr_and_ty.0, |
| 693 | 696 | size: self.size_of_sized( |
| 694 | &place_addr_and_ty.1, | |
| 697 | place_addr_and_ty.1, | |
| 695 | 698 | locals, |
| 696 | 699 | "Type of place that we need its interval", |
| 697 | 700 | )?, |
| ... | ... | @@ -702,48 +705,46 @@ impl<'db> Evaluator<'db> { |
| 702 | 705 | self.cached_ptr_size |
| 703 | 706 | } |
| 704 | 707 | |
| 705 | fn projected_ty(&self, ty: Ty, proj: PlaceElem) -> Ty { | |
| 708 | fn projected_ty(&self, ty: Ty<'db>, proj: PlaceElem<'db>) -> Ty<'db> { | |
| 706 | 709 | let pair = (ty, proj); |
| 707 | 710 | if let Some(r) = self.projected_ty_cache.borrow().get(&pair) { |
| 708 | return r.clone(); | |
| 711 | return *r; | |
| 709 | 712 | } |
| 710 | 713 | let (ty, proj) = pair; |
| 711 | 714 | let r = proj.projected_ty( |
| 712 | ty.clone(), | |
| 713 | self.db, | |
| 715 | &self.infcx, | |
| 716 | ty, | |
| 714 | 717 | |c, subst, f| { |
| 715 | let InternedClosure(def, _) = self.db.lookup_intern_closure(c.into()); | |
| 718 | let InternedClosure(def, _) = self.db.lookup_intern_closure(c); | |
| 716 | 719 | let infer = self.db.infer(def); |
| 717 | let (captures, _) = infer.closure_info(&c); | |
| 718 | let parent_subst = ClosureSubst(subst).parent_subst(self.db); | |
| 720 | let (captures, _) = infer.closure_info(c); | |
| 721 | let parent_subst = subst.split_closure_args_untupled().parent_args; | |
| 719 | 722 | captures |
| 720 | 723 | .get(f) |
| 721 | 724 | .expect("broken closure field") |
| 722 | 725 | .ty |
| 723 | .clone() | |
| 724 | .substitute(Interner, &parent_subst) | |
| 726 | .instantiate(self.interner(), parent_subst) | |
| 725 | 727 | }, |
| 726 | 728 | self.crate_id, |
| 727 | 729 | ); |
| 728 | self.projected_ty_cache.borrow_mut().insert((ty, proj), r.clone()); | |
| 730 | self.projected_ty_cache.borrow_mut().insert((ty, proj), r); | |
| 729 | 731 | r |
| 730 | 732 | } |
| 731 | 733 | |
| 732 | 734 | fn place_addr_and_ty_and_metadata<'a>( |
| 733 | 735 | &'a self, |
| 734 | p: &Place, | |
| 735 | locals: &'a Locals, | |
| 736 | ) -> Result<(Address, Ty, Option<IntervalOrOwned>)> { | |
| 737 | let interner = DbInterner::new_with(self.db, None, None); | |
| 736 | p: &Place<'db>, | |
| 737 | locals: &'a Locals<'db>, | |
| 738 | ) -> Result<'db, (Address, Ty<'db>, Option<IntervalOrOwned>)> { | |
| 738 | 739 | let mut addr = locals.ptr[p.local].addr; |
| 739 | let mut ty: Ty = locals.body.locals[p.local].ty.clone(); | |
| 740 | let mut ty: Ty<'db> = locals.body.locals[p.local].ty; | |
| 740 | 741 | let mut metadata: Option<IntervalOrOwned> = None; // locals are always sized |
| 741 | 742 | for proj in p.projection.lookup(&locals.body.projection_store) { |
| 742 | let prev_ty = ty.clone(); | |
| 743 | let prev_ty = ty; | |
| 743 | 744 | ty = self.projected_ty(ty, proj.clone()); |
| 744 | 745 | match proj { |
| 745 | 746 | ProjectionElem::Deref => { |
| 746 | metadata = if self.size_align_of(&ty, locals)?.is_none() { | |
| 747 | metadata = if self.size_align_of(ty, locals)?.is_none() { | |
| 747 | 748 | Some( |
| 748 | 749 | Interval { addr: addr.offset(self.ptr_size()), size: self.ptr_size() } |
| 749 | 750 | .into(), |
| ... | ... | @@ -761,12 +762,12 @@ impl<'db> Evaluator<'db> { |
| 761 | 762 | ); |
| 762 | 763 | metadata = None; // Result of index is always sized |
| 763 | 764 | let ty_size = |
| 764 | self.size_of_sized(&ty, locals, "array inner type should be sized")?; | |
| 765 | self.size_of_sized(ty, locals, "array inner type should be sized")?; | |
| 765 | 766 | addr = addr.offset(ty_size * offset); |
| 766 | 767 | } |
| 767 | 768 | &ProjectionElem::ConstantIndex { from_end, offset } => { |
| 768 | 769 | let offset = if from_end { |
| 769 | let len = match prev_ty.kind(Interner) { | |
| 770 | let len = match prev_ty.kind() { | |
| 770 | 771 | TyKind::Array(_, c) => match try_const_usize(self.db, c) { |
| 771 | 772 | Some(it) => it as u64, |
| 772 | 773 | None => { |
| ... | ... | @@ -785,13 +786,13 @@ impl<'db> Evaluator<'db> { |
| 785 | 786 | }; |
| 786 | 787 | metadata = None; // Result of index is always sized |
| 787 | 788 | let ty_size = |
| 788 | self.size_of_sized(&ty, locals, "array inner type should be sized")?; | |
| 789 | self.size_of_sized(ty, locals, "array inner type should be sized")?; | |
| 789 | 790 | addr = addr.offset(ty_size * offset); |
| 790 | 791 | } |
| 791 | 792 | &ProjectionElem::Subslice { from, to } => { |
| 792 | let inner_ty = match &ty.kind(Interner) { | |
| 793 | TyKind::Array(inner, _) | TyKind::Slice(inner) => inner.clone(), | |
| 794 | _ => TyKind::Error.intern(Interner), | |
| 793 | let inner_ty = match ty.kind() { | |
| 794 | TyKind::Array(inner, _) | TyKind::Slice(inner) => inner, | |
| 795 | _ => Ty::new_error(self.interner(), ErrorGuaranteed), | |
| 795 | 796 | }; |
| 796 | 797 | metadata = match metadata { |
| 797 | 798 | Some(it) => { |
| ... | ... | @@ -803,23 +804,23 @@ impl<'db> Evaluator<'db> { |
| 803 | 804 | None => None, |
| 804 | 805 | }; |
| 805 | 806 | let ty_size = |
| 806 | self.size_of_sized(&inner_ty, locals, "array inner type should be sized")?; | |
| 807 | self.size_of_sized(inner_ty, locals, "array inner type should be sized")?; | |
| 807 | 808 | addr = addr.offset(ty_size * (from as usize)); |
| 808 | 809 | } |
| 809 | 810 | &ProjectionElem::ClosureField(f) => { |
| 810 | let layout = self.layout(prev_ty.to_nextsolver(interner))?; | |
| 811 | let layout = self.layout(prev_ty)?; | |
| 811 | 812 | let offset = layout.fields.offset(f).bytes_usize(); |
| 812 | 813 | addr = addr.offset(offset); |
| 813 | 814 | metadata = None; |
| 814 | 815 | } |
| 815 | 816 | ProjectionElem::Field(Either::Right(f)) => { |
| 816 | let layout = self.layout(prev_ty.to_nextsolver(interner))?; | |
| 817 | let layout = self.layout(prev_ty)?; | |
| 817 | 818 | let offset = layout.fields.offset(f.index as usize).bytes_usize(); |
| 818 | 819 | addr = addr.offset(offset); |
| 819 | 820 | metadata = None; // tuple field is always sized FIXME: This is wrong, the tail can be unsized |
| 820 | 821 | } |
| 821 | 822 | ProjectionElem::Field(Either::Left(f)) => { |
| 822 | let layout = self.layout(prev_ty.to_nextsolver(interner))?; | |
| 823 | let layout = self.layout(prev_ty)?; | |
| 823 | 824 | let variant_layout = match &layout.variants { |
| 824 | 825 | Variants::Single { .. } | Variants::Empty => &layout, |
| 825 | 826 | Variants::Multiple { variants, .. } => { |
| ... | ... | @@ -841,7 +842,7 @@ impl<'db> Evaluator<'db> { |
| 841 | 842 | .bytes_usize(); |
| 842 | 843 | addr = addr.offset(offset); |
| 843 | 844 | // Unsized field metadata is equal to the metadata of the struct |
| 844 | if self.size_align_of(&ty, locals)?.is_some() { | |
| 845 | if self.size_align_of(ty, locals)?.is_some() { | |
| 845 | 846 | metadata = None; |
| 846 | 847 | } |
| 847 | 848 | } |
| ... | ... | @@ -851,46 +852,47 @@ impl<'db> Evaluator<'db> { |
| 851 | 852 | Ok((addr, ty, metadata)) |
| 852 | 853 | } |
| 853 | 854 | |
| 854 | fn layout(&self, ty: crate::next_solver::Ty<'db>) -> Result<Arc<Layout>> { | |
| 855 | fn layout(&self, ty: Ty<'db>) -> Result<'db, Arc<Layout>> { | |
| 855 | 856 | if let Some(x) = self.layout_cache.borrow().get(&ty) { |
| 856 | 857 | return Ok(x.clone()); |
| 857 | 858 | } |
| 858 | let interner = DbInterner::new_with(self.db, None, None); | |
| 859 | 859 | let r = self |
| 860 | 860 | .db |
| 861 | 861 | .layout_of_ty(ty, self.trait_env.clone()) |
| 862 | .map_err(|e| MirEvalError::LayoutError(e, convert_ty_for_result(interner, ty)))?; | |
| 862 | .map_err(|e| MirEvalError::LayoutError(e, ty))?; | |
| 863 | 863 | self.layout_cache.borrow_mut().insert(ty, r.clone()); |
| 864 | 864 | Ok(r) |
| 865 | 865 | } |
| 866 | 866 | |
| 867 | fn layout_adt(&self, adt: AdtId, subst: Substitution) -> Result<Arc<Layout>> { | |
| 868 | let interner = DbInterner::new_with(self.db, None, None); | |
| 869 | self.layout(crate::next_solver::Ty::new( | |
| 870 | interner, | |
| 871 | rustc_type_ir::TyKind::Adt( | |
| 872 | crate::next_solver::AdtDef::new(adt, interner), | |
| 873 | subst.to_nextsolver(interner), | |
| 874 | ), | |
| 875 | )) | |
| 867 | fn layout_adt(&self, adt: AdtId, subst: GenericArgs<'db>) -> Result<'db, Arc<Layout>> { | |
| 868 | self.layout(Ty::new_adt(self.interner(), adt, subst)) | |
| 876 | 869 | } |
| 877 | 870 | |
| 878 | fn place_ty<'a>(&'a self, p: &Place, locals: &'a Locals) -> Result<Ty> { | |
| 871 | fn place_ty<'a>(&'a self, p: &Place<'db>, locals: &'a Locals<'db>) -> Result<'db, Ty<'db>> { | |
| 879 | 872 | Ok(self.place_addr_and_ty_and_metadata(p, locals)?.1) |
| 880 | 873 | } |
| 881 | 874 | |
| 882 | fn operand_ty(&self, o: &Operand, locals: &Locals) -> Result<Ty> { | |
| 875 | fn operand_ty(&self, o: &Operand<'db>, locals: &Locals<'db>) -> Result<'db, Ty<'db>> { | |
| 883 | 876 | Ok(match &o.kind { |
| 884 | 877 | OperandKind::Copy(p) | OperandKind::Move(p) => self.place_ty(p, locals)?, |
| 885 | OperandKind::Constant(c) => c.data(Interner).ty.clone(), | |
| 878 | OperandKind::Constant { konst: _, ty } => *ty, | |
| 886 | 879 | &OperandKind::Static(s) => { |
| 887 | let ty = self.db.infer(s.into())[self.db.body(s.into()).body_expr].clone(); | |
| 888 | TyKind::Ref(Mutability::Not, static_lifetime(), ty).intern(Interner) | |
| 880 | let ty = self.db.infer(s.into())[self.db.body(s.into()).body_expr]; | |
| 881 | Ty::new_ref( | |
| 882 | self.interner(), | |
| 883 | Region::new_static(self.interner()), | |
| 884 | ty, | |
| 885 | Mutability::Not, | |
| 886 | ) | |
| 889 | 887 | } |
| 890 | 888 | }) |
| 891 | 889 | } |
| 892 | 890 | |
| 893 | fn operand_ty_and_eval(&mut self, o: &Operand, locals: &mut Locals) -> Result<IntervalAndTy> { | |
| 891 | fn operand_ty_and_eval( | |
| 892 | &mut self, | |
| 893 | o: &Operand<'db>, | |
| 894 | locals: &mut Locals<'db>, | |
| 895 | ) -> Result<'db, IntervalAndTy<'db>> { | |
| 894 | 896 | Ok(IntervalAndTy { |
| 895 | 897 | interval: self.eval_operand(o, locals)?, |
| 896 | 898 | ty: self.operand_ty(o, locals)?, |
| ... | ... | @@ -899,9 +901,9 @@ impl<'db> Evaluator<'db> { |
| 899 | 901 | |
| 900 | 902 | fn interpret_mir( |
| 901 | 903 | &mut self, |
| 902 | body: Arc<MirBody>, | |
| 904 | body: Arc<MirBody<'db>>, | |
| 903 | 905 | args: impl Iterator<Item = IntervalOrOwned>, |
| 904 | ) -> Result<Interval> { | |
| 906 | ) -> Result<'db, Interval> { | |
| 905 | 907 | if let Some(it) = self.stack_depth_limit.checked_sub(1) { |
| 906 | 908 | self.stack_depth_limit = it; |
| 907 | 909 | } else { |
| ... | ... | @@ -962,9 +964,9 @@ impl<'db> Evaluator<'db> { |
| 962 | 964 | let args = args |
| 963 | 965 | .iter() |
| 964 | 966 | .map(|it| self.operand_ty_and_eval(it, locals)) |
| 965 | .collect::<Result<Vec<_>>>()?; | |
| 966 | let stack_frame = match &fn_ty.kind(Interner) { | |
| 967 | TyKind::Function(_) => { | |
| 967 | .collect::<Result<'db, Vec<_>>>()?; | |
| 968 | let stack_frame = match fn_ty.kind() { | |
| 969 | TyKind::FnPtr(..) => { | |
| 968 | 970 | let bytes = self.eval_operand(func, locals)?; |
| 969 | 971 | self.exec_fn_pointer( |
| 970 | 972 | bytes, |
| ... | ... | @@ -976,7 +978,7 @@ impl<'db> Evaluator<'db> { |
| 976 | 978 | )? |
| 977 | 979 | } |
| 978 | 980 | TyKind::FnDef(def, generic_args) => self.exec_fn_def( |
| 979 | CallableDefId::from_chalk(self.db, *def), | |
| 981 | def.0, | |
| 980 | 982 | generic_args, |
| 981 | 983 | destination_interval, |
| 982 | 984 | &args, |
| ... | ... | @@ -1063,10 +1065,10 @@ impl<'db> Evaluator<'db> { |
| 1063 | 1065 | |
| 1064 | 1066 | fn fill_locals_for_body( |
| 1065 | 1067 | &mut self, |
| 1066 | body: &MirBody, | |
| 1067 | locals: &mut Locals, | |
| 1068 | body: &MirBody<'db>, | |
| 1069 | locals: &mut Locals<'db>, | |
| 1068 | 1070 | args: impl Iterator<Item = IntervalOrOwned>, |
| 1069 | ) -> Result<()> { | |
| 1071 | ) -> Result<'db, ()> { | |
| 1070 | 1072 | let mut remain_args = body.param_locals.len(); |
| 1071 | 1073 | for ((l, interval), value) in locals.ptr.iter().skip(1).zip(args) { |
| 1072 | 1074 | locals.drop_flags.add_place(l.into(), &locals.body.projection_store); |
| ... | ... | @@ -1087,9 +1089,9 @@ impl<'db> Evaluator<'db> { |
| 1087 | 1089 | |
| 1088 | 1090 | fn create_locals_for_body( |
| 1089 | 1091 | &mut self, |
| 1090 | body: &Arc<MirBody>, | |
| 1092 | body: &Arc<MirBody<'db>>, | |
| 1091 | 1093 | destination: Option<Interval>, |
| 1092 | ) -> Result<(Locals, usize)> { | |
| 1094 | ) -> Result<'db, (Locals<'db>, usize)> { | |
| 1093 | 1095 | let mut locals = |
| 1094 | 1096 | match self.unused_locals_store.borrow_mut().entry(body.owner).or_default().pop() { |
| 1095 | 1097 | None => Locals { |
| ... | ... | @@ -1113,7 +1115,7 @@ impl<'db> Evaluator<'db> { |
| 1113 | 1115 | continue; |
| 1114 | 1116 | } |
| 1115 | 1117 | let (size, align) = self.size_align_of_sized( |
| 1116 | &it.ty, | |
| 1118 | it.ty, | |
| 1117 | 1119 | &locals, |
| 1118 | 1120 | "no unsized local in extending stack", |
| 1119 | 1121 | )?; |
| ... | ... | @@ -1136,8 +1138,11 @@ impl<'db> Evaluator<'db> { |
| 1136 | 1138 | Ok((locals, prev_stack_pointer)) |
| 1137 | 1139 | } |
| 1138 | 1140 | |
| 1139 | fn eval_rvalue(&mut self, r: &Rvalue, locals: &mut Locals) -> Result<IntervalOrOwned> { | |
| 1140 | let interner = DbInterner::new_with(self.db, None, None); | |
| 1141 | fn eval_rvalue( | |
| 1142 | &mut self, | |
| 1143 | r: &Rvalue<'db>, | |
| 1144 | locals: &mut Locals<'db>, | |
| 1145 | ) -> Result<'db, IntervalOrOwned> { | |
| 1141 | 1146 | use IntervalOrOwned::*; |
| 1142 | 1147 | Ok(match r { |
| 1143 | 1148 | Rvalue::Use(it) => Borrowed(self.eval_operand(it, locals)?), |
| ... | ... | @@ -1163,33 +1168,33 @@ impl<'db> Evaluator<'db> { |
| 1163 | 1168 | Rvalue::UnaryOp(op, val) => { |
| 1164 | 1169 | let mut c = self.eval_operand(val, locals)?.get(self)?; |
| 1165 | 1170 | let mut ty = self.operand_ty(val, locals)?; |
| 1166 | while let TyKind::Ref(_, _, z) = ty.kind(Interner) { | |
| 1167 | ty = z.clone(); | |
| 1168 | let size = self.size_of_sized(&ty, locals, "operand of unary op")?; | |
| 1171 | while let TyKind::Ref(_, z, _) = ty.kind() { | |
| 1172 | ty = z; | |
| 1173 | let size = self.size_of_sized(ty, locals, "operand of unary op")?; | |
| 1169 | 1174 | c = self.read_memory(Address::from_bytes(c)?, size)?; |
| 1170 | 1175 | } |
| 1171 | if let TyKind::Scalar(chalk_ir::Scalar::Float(f)) = ty.kind(Interner) { | |
| 1176 | if let TyKind::Float(f) = ty.kind() { | |
| 1172 | 1177 | match f { |
| 1173 | chalk_ir::FloatTy::F16 => { | |
| 1178 | rustc_type_ir::FloatTy::F16 => { | |
| 1174 | 1179 | let c = -from_bytes!(f16, u16, c); |
| 1175 | 1180 | Owned(u16::try_from(c.to_bits()).unwrap().to_le_bytes().into()) |
| 1176 | 1181 | } |
| 1177 | chalk_ir::FloatTy::F32 => { | |
| 1182 | rustc_type_ir::FloatTy::F32 => { | |
| 1178 | 1183 | let c = -from_bytes!(f32, c); |
| 1179 | 1184 | Owned(c.to_le_bytes().into()) |
| 1180 | 1185 | } |
| 1181 | chalk_ir::FloatTy::F64 => { | |
| 1186 | rustc_type_ir::FloatTy::F64 => { | |
| 1182 | 1187 | let c = -from_bytes!(f64, c); |
| 1183 | 1188 | Owned(c.to_le_bytes().into()) |
| 1184 | 1189 | } |
| 1185 | chalk_ir::FloatTy::F128 => { | |
| 1190 | rustc_type_ir::FloatTy::F128 => { | |
| 1186 | 1191 | let c = -from_bytes!(f128, u128, c); |
| 1187 | 1192 | Owned(c.to_bits().to_le_bytes().into()) |
| 1188 | 1193 | } |
| 1189 | 1194 | } |
| 1190 | 1195 | } else { |
| 1191 | 1196 | let mut c = c.to_vec(); |
| 1192 | if ty.as_builtin() == Some(BuiltinType::Bool) { | |
| 1197 | if matches!(ty.kind(), TyKind::Bool) { | |
| 1193 | 1198 | c[0] = 1 - c[0]; |
| 1194 | 1199 | } else { |
| 1195 | 1200 | match op { |
| ... | ... | @@ -1215,8 +1220,8 @@ impl<'db> Evaluator<'db> { |
| 1215 | 1220 | let mut lc = lc.get(self)?; |
| 1216 | 1221 | let mut rc = rc.get(self)?; |
| 1217 | 1222 | let mut ty = self.operand_ty(lhs, locals)?; |
| 1218 | while let TyKind::Ref(_, _, z) = ty.kind(Interner) { | |
| 1219 | ty = z.clone(); | |
| 1223 | while let TyKind::Ref(_, z, _) = ty.kind() { | |
| 1224 | ty = z; | |
| 1220 | 1225 | let size = if ty.is_str() { |
| 1221 | 1226 | if *op != BinOp::Eq { |
| 1222 | 1227 | never!("Only eq is builtin for `str`"); |
| ... | ... | @@ -1232,14 +1237,14 @@ impl<'db> Evaluator<'db> { |
| 1232 | 1237 | rc = self.read_memory(Address::from_bytes(rc)?, ls)?; |
| 1233 | 1238 | break 'binary_op Owned(vec![u8::from(lc == rc)]); |
| 1234 | 1239 | } else { |
| 1235 | self.size_of_sized(&ty, locals, "operand of binary op")? | |
| 1240 | self.size_of_sized(ty, locals, "operand of binary op")? | |
| 1236 | 1241 | }; |
| 1237 | 1242 | lc = self.read_memory(Address::from_bytes(lc)?, size)?; |
| 1238 | 1243 | rc = self.read_memory(Address::from_bytes(rc)?, size)?; |
| 1239 | 1244 | } |
| 1240 | if let TyKind::Scalar(chalk_ir::Scalar::Float(f)) = ty.kind(Interner) { | |
| 1245 | if let TyKind::Float(f) = ty.kind() { | |
| 1241 | 1246 | match f { |
| 1242 | chalk_ir::FloatTy::F16 => { | |
| 1247 | rustc_type_ir::FloatTy::F16 => { | |
| 1243 | 1248 | let l = from_bytes!(f16, u16, lc); |
| 1244 | 1249 | let r = from_bytes!(f16, u16, rc); |
| 1245 | 1250 | match op { |
| ... | ... | @@ -1272,7 +1277,7 @@ impl<'db> Evaluator<'db> { |
| 1272 | 1277 | ), |
| 1273 | 1278 | } |
| 1274 | 1279 | } |
| 1275 | chalk_ir::FloatTy::F32 => { | |
| 1280 | rustc_type_ir::FloatTy::F32 => { | |
| 1276 | 1281 | let l = from_bytes!(f32, lc); |
| 1277 | 1282 | let r = from_bytes!(f32, rc); |
| 1278 | 1283 | match op { |
| ... | ... | @@ -1300,7 +1305,7 @@ impl<'db> Evaluator<'db> { |
| 1300 | 1305 | ), |
| 1301 | 1306 | } |
| 1302 | 1307 | } |
| 1303 | chalk_ir::FloatTy::F64 => { | |
| 1308 | rustc_type_ir::FloatTy::F64 => { | |
| 1304 | 1309 | let l = from_bytes!(f64, lc); |
| 1305 | 1310 | let r = from_bytes!(f64, rc); |
| 1306 | 1311 | match op { |
| ... | ... | @@ -1328,7 +1333,7 @@ impl<'db> Evaluator<'db> { |
| 1328 | 1333 | ), |
| 1329 | 1334 | } |
| 1330 | 1335 | } |
| 1331 | chalk_ir::FloatTy::F128 => { | |
| 1336 | rustc_type_ir::FloatTy::F128 => { | |
| 1332 | 1337 | let l = from_bytes!(f128, u128, lc); |
| 1333 | 1338 | let r = from_bytes!(f128, u128, rc); |
| 1334 | 1339 | match op { |
| ... | ... | @@ -1358,7 +1363,7 @@ impl<'db> Evaluator<'db> { |
| 1358 | 1363 | } |
| 1359 | 1364 | } |
| 1360 | 1365 | } else { |
| 1361 | let is_signed = matches!(ty.as_builtin(), Some(BuiltinType::Int(_))); | |
| 1366 | let is_signed = matches!(ty.kind(), TyKind::Int(_)); | |
| 1362 | 1367 | let l128 = IntValue::from_bytes(lc, is_signed); |
| 1363 | 1368 | let r128 = IntValue::from_bytes(rc, is_signed); |
| 1364 | 1369 | match op { |
| ... | ... | @@ -1429,7 +1434,7 @@ impl<'db> Evaluator<'db> { |
| 1429 | 1434 | Owned(result.to_le_bytes().to_vec()) |
| 1430 | 1435 | } |
| 1431 | 1436 | Rvalue::Repeat(it, len) => { |
| 1432 | let len = match try_const_usize(self.db, len) { | |
| 1437 | let len = match try_const_usize(self.db, *len) { | |
| 1433 | 1438 | Some(it) => it as usize, |
| 1434 | 1439 | None => not_supported!("non evaluatable array len in repeat Rvalue"), |
| 1435 | 1440 | }; |
| ... | ... | @@ -1439,7 +1444,7 @@ impl<'db> Evaluator<'db> { |
| 1439 | 1444 | } |
| 1440 | 1445 | Rvalue::ShallowInitBox(_, _) => not_supported!("shallow init box"), |
| 1441 | 1446 | Rvalue::ShallowInitBoxWithAlloc(ty) => { |
| 1442 | let Some((size, align)) = self.size_align_of(ty, locals)? else { | |
| 1447 | let Some((size, align)) = self.size_align_of(*ty, locals)? else { | |
| 1443 | 1448 | not_supported!("unsized box initialization"); |
| 1444 | 1449 | }; |
| 1445 | 1450 | let addr = self.heap_allocate(size, align)?; |
| ... | ... | @@ -1450,7 +1455,7 @@ impl<'db> Evaluator<'db> { |
| 1450 | 1455 | let values = values |
| 1451 | 1456 | .iter() |
| 1452 | 1457 | .map(|it| self.eval_operand(it, locals)) |
| 1453 | .collect::<Result<Vec<_>>>()?; | |
| 1458 | .collect::<Result<'db, Vec<_>>>()?; | |
| 1454 | 1459 | match kind { |
| 1455 | 1460 | AggregateKind::Array(_) => { |
| 1456 | 1461 | let mut r = vec![]; |
| ... | ... | @@ -1461,7 +1466,7 @@ impl<'db> Evaluator<'db> { |
| 1461 | 1466 | Owned(r) |
| 1462 | 1467 | } |
| 1463 | 1468 | AggregateKind::Tuple(ty) => { |
| 1464 | let layout = self.layout(ty.to_nextsolver(interner))?; | |
| 1469 | let layout = self.layout(*ty)?; | |
| 1465 | 1470 | Owned(self.construct_with_layout( |
| 1466 | 1471 | layout.size.bytes_usize(), |
| 1467 | 1472 | &layout, |
| ... | ... | @@ -1470,8 +1475,10 @@ impl<'db> Evaluator<'db> { |
| 1470 | 1475 | )?) |
| 1471 | 1476 | } |
| 1472 | 1477 | AggregateKind::Union(it, f) => { |
| 1473 | let layout = | |
| 1474 | self.layout_adt((*it).into(), Substitution::empty(Interner))?; | |
| 1478 | let layout = self.layout_adt( | |
| 1479 | (*it).into(), | |
| 1480 | GenericArgs::new_from_iter(self.interner(), []), | |
| 1481 | )?; | |
| 1475 | 1482 | let offset = layout |
| 1476 | 1483 | .fields |
| 1477 | 1484 | .offset(u32::from(f.local_id.into_raw()) as usize) |
| ... | ... | @@ -1483,7 +1490,7 @@ impl<'db> Evaluator<'db> { |
| 1483 | 1490 | } |
| 1484 | 1491 | AggregateKind::Adt(it, subst) => { |
| 1485 | 1492 | let (size, variant_layout, tag) = |
| 1486 | self.layout_of_variant(*it, subst.clone(), locals)?; | |
| 1493 | self.layout_of_variant(*it, *subst, locals)?; | |
| 1487 | 1494 | Owned(self.construct_with_layout( |
| 1488 | 1495 | size, |
| 1489 | 1496 | &variant_layout, |
| ... | ... | @@ -1492,7 +1499,7 @@ impl<'db> Evaluator<'db> { |
| 1492 | 1499 | )?) |
| 1493 | 1500 | } |
| 1494 | 1501 | AggregateKind::Closure(ty) => { |
| 1495 | let layout = self.layout(ty.to_nextsolver(interner))?; | |
| 1502 | let layout = self.layout(*ty)?; | |
| 1496 | 1503 | Owned(self.construct_with_layout( |
| 1497 | 1504 | layout.size.bytes_usize(), |
| 1498 | 1505 | &layout, |
| ... | ... | @@ -1506,11 +1513,7 @@ impl<'db> Evaluator<'db> { |
| 1506 | 1513 | CastKind::PointerCoercion(cast) => match cast { |
| 1507 | 1514 | PointerCast::ReifyFnPointer | PointerCast::ClosureFnPointer(_) => { |
| 1508 | 1515 | let current_ty = self.operand_ty(operand, locals)?; |
| 1509 | if let TyKind::FnDef(_, _) | TyKind::Closure(_, _) = | |
| 1510 | &current_ty.kind(Interner) | |
| 1511 | { | |
| 1512 | let interner = DbInterner::new_with(self.db, None, None); | |
| 1513 | let current_ty = current_ty.to_nextsolver(interner); | |
| 1516 | if let TyKind::FnDef(_, _) | TyKind::Closure(_, _) = current_ty.kind() { | |
| 1514 | 1517 | let id = self.vtable_map.id(current_ty); |
| 1515 | 1518 | let ptr_size = self.ptr_size(); |
| 1516 | 1519 | Owned(id.to_le_bytes()[0..ptr_size].to_vec()) |
| ... | ... | @@ -1523,7 +1526,7 @@ impl<'db> Evaluator<'db> { |
| 1523 | 1526 | PointerCast::Unsize => { |
| 1524 | 1527 | let current_ty = self.operand_ty(operand, locals)?; |
| 1525 | 1528 | let addr = self.eval_operand(operand, locals)?; |
| 1526 | self.coerce_unsized(addr, &current_ty, target_ty)? | |
| 1529 | self.coerce_unsized(addr, current_ty, *target_ty)? | |
| 1527 | 1530 | } |
| 1528 | 1531 | PointerCast::MutToConstPointer | PointerCast::UnsafeFnPointer => { |
| 1529 | 1532 | // This is no-op |
| ... | ... | @@ -1540,40 +1543,34 @@ impl<'db> Evaluator<'db> { |
| 1540 | 1543 | | CastKind::PointerExposeAddress |
| 1541 | 1544 | | CastKind::PointerFromExposedAddress => { |
| 1542 | 1545 | let current_ty = self.operand_ty(operand, locals)?; |
| 1543 | let is_signed = matches!( | |
| 1544 | current_ty.kind(Interner), | |
| 1545 | TyKind::Scalar(chalk_ir::Scalar::Int(_)) | |
| 1546 | ); | |
| 1546 | let is_signed = matches!(current_ty.kind(), TyKind::Int(_)); | |
| 1547 | 1547 | let current = pad16(self.eval_operand(operand, locals)?.get(self)?, is_signed); |
| 1548 | 1548 | let dest_size = |
| 1549 | self.size_of_sized(target_ty, locals, "destination of int to int cast")?; | |
| 1549 | self.size_of_sized(*target_ty, locals, "destination of int to int cast")?; | |
| 1550 | 1550 | Owned(current[0..dest_size].to_vec()) |
| 1551 | 1551 | } |
| 1552 | 1552 | CastKind::FloatToInt => { |
| 1553 | 1553 | let ty = self.operand_ty(operand, locals)?; |
| 1554 | let TyKind::Scalar(chalk_ir::Scalar::Float(ty)) = ty.kind(Interner) else { | |
| 1554 | let TyKind::Float(ty) = ty.kind() else { | |
| 1555 | 1555 | not_supported!("invalid float to int cast"); |
| 1556 | 1556 | }; |
| 1557 | 1557 | let value = self.eval_operand(operand, locals)?.get(self)?; |
| 1558 | 1558 | let value = match ty { |
| 1559 | chalk_ir::FloatTy::F32 => { | |
| 1559 | rustc_type_ir::FloatTy::F32 => { | |
| 1560 | 1560 | let value = value.try_into().unwrap(); |
| 1561 | 1561 | f32::from_le_bytes(value) as f64 |
| 1562 | 1562 | } |
| 1563 | chalk_ir::FloatTy::F64 => { | |
| 1563 | rustc_type_ir::FloatTy::F64 => { | |
| 1564 | 1564 | let value = value.try_into().unwrap(); |
| 1565 | 1565 | f64::from_le_bytes(value) |
| 1566 | 1566 | } |
| 1567 | chalk_ir::FloatTy::F16 | chalk_ir::FloatTy::F128 => { | |
| 1567 | rustc_type_ir::FloatTy::F16 | rustc_type_ir::FloatTy::F128 => { | |
| 1568 | 1568 | not_supported!("unstable floating point type f16 and f128"); |
| 1569 | 1569 | } |
| 1570 | 1570 | }; |
| 1571 | let is_signed = matches!( | |
| 1572 | target_ty.kind(Interner), | |
| 1573 | TyKind::Scalar(chalk_ir::Scalar::Int(_)) | |
| 1574 | ); | |
| 1571 | let is_signed = matches!(target_ty.kind(), TyKind::Int(_)); | |
| 1575 | 1572 | let dest_size = |
| 1576 | self.size_of_sized(target_ty, locals, "destination of float to int cast")?; | |
| 1573 | self.size_of_sized(*target_ty, locals, "destination of float to int cast")?; | |
| 1577 | 1574 | let dest_bits = dest_size * 8; |
| 1578 | 1575 | let (max, min) = if dest_bits == 128 { |
| 1579 | 1576 | (i128::MAX, i128::MIN) |
| ... | ... | @@ -1589,53 +1586,46 @@ impl<'db> Evaluator<'db> { |
| 1589 | 1586 | } |
| 1590 | 1587 | CastKind::FloatToFloat => { |
| 1591 | 1588 | let ty = self.operand_ty(operand, locals)?; |
| 1592 | let TyKind::Scalar(chalk_ir::Scalar::Float(ty)) = ty.kind(Interner) else { | |
| 1589 | let TyKind::Float(ty) = ty.kind() else { | |
| 1593 | 1590 | not_supported!("invalid float to int cast"); |
| 1594 | 1591 | }; |
| 1595 | 1592 | let value = self.eval_operand(operand, locals)?.get(self)?; |
| 1596 | 1593 | let value = match ty { |
| 1597 | chalk_ir::FloatTy::F32 => { | |
| 1594 | rustc_type_ir::FloatTy::F32 => { | |
| 1598 | 1595 | let value = value.try_into().unwrap(); |
| 1599 | 1596 | f32::from_le_bytes(value) as f64 |
| 1600 | 1597 | } |
| 1601 | chalk_ir::FloatTy::F64 => { | |
| 1598 | rustc_type_ir::FloatTy::F64 => { | |
| 1602 | 1599 | let value = value.try_into().unwrap(); |
| 1603 | 1600 | f64::from_le_bytes(value) |
| 1604 | 1601 | } |
| 1605 | chalk_ir::FloatTy::F16 | chalk_ir::FloatTy::F128 => { | |
| 1602 | rustc_type_ir::FloatTy::F16 | rustc_type_ir::FloatTy::F128 => { | |
| 1606 | 1603 | not_supported!("unstable floating point type f16 and f128"); |
| 1607 | 1604 | } |
| 1608 | 1605 | }; |
| 1609 | let TyKind::Scalar(chalk_ir::Scalar::Float(target_ty)) = | |
| 1610 | target_ty.kind(Interner) | |
| 1611 | else { | |
| 1606 | let TyKind::Float(target_ty) = target_ty.kind() else { | |
| 1612 | 1607 | not_supported!("invalid float to float cast"); |
| 1613 | 1608 | }; |
| 1614 | 1609 | match target_ty { |
| 1615 | chalk_ir::FloatTy::F32 => Owned((value as f32).to_le_bytes().to_vec()), | |
| 1616 | chalk_ir::FloatTy::F64 => Owned((value as f64).to_le_bytes().to_vec()), | |
| 1617 | chalk_ir::FloatTy::F16 | chalk_ir::FloatTy::F128 => { | |
| 1610 | rustc_type_ir::FloatTy::F32 => Owned((value as f32).to_le_bytes().to_vec()), | |
| 1611 | rustc_type_ir::FloatTy::F64 => Owned((value as f64).to_le_bytes().to_vec()), | |
| 1612 | rustc_type_ir::FloatTy::F16 | rustc_type_ir::FloatTy::F128 => { | |
| 1618 | 1613 | not_supported!("unstable floating point type f16 and f128"); |
| 1619 | 1614 | } |
| 1620 | 1615 | } |
| 1621 | 1616 | } |
| 1622 | 1617 | CastKind::IntToFloat => { |
| 1623 | 1618 | let current_ty = self.operand_ty(operand, locals)?; |
| 1624 | let is_signed = matches!( | |
| 1625 | current_ty.kind(Interner), | |
| 1626 | TyKind::Scalar(chalk_ir::Scalar::Int(_)) | |
| 1627 | ); | |
| 1619 | let is_signed = matches!(current_ty.kind(), TyKind::Int(_)); | |
| 1628 | 1620 | let value = pad16(self.eval_operand(operand, locals)?.get(self)?, is_signed); |
| 1629 | 1621 | let value = i128::from_le_bytes(value); |
| 1630 | let TyKind::Scalar(chalk_ir::Scalar::Float(target_ty)) = | |
| 1631 | target_ty.kind(Interner) | |
| 1632 | else { | |
| 1622 | let TyKind::Float(target_ty) = target_ty.kind() else { | |
| 1633 | 1623 | not_supported!("invalid int to float cast"); |
| 1634 | 1624 | }; |
| 1635 | 1625 | match target_ty { |
| 1636 | chalk_ir::FloatTy::F32 => Owned((value as f32).to_le_bytes().to_vec()), | |
| 1637 | chalk_ir::FloatTy::F64 => Owned((value as f64).to_le_bytes().to_vec()), | |
| 1638 | chalk_ir::FloatTy::F16 | chalk_ir::FloatTy::F128 => { | |
| 1626 | rustc_type_ir::FloatTy::F32 => Owned((value as f32).to_le_bytes().to_vec()), | |
| 1627 | rustc_type_ir::FloatTy::F64 => Owned((value as f64).to_le_bytes().to_vec()), | |
| 1628 | rustc_type_ir::FloatTy::F16 | rustc_type_ir::FloatTy::F128 => { | |
| 1639 | 1629 | not_supported!("unstable floating point type f16 and f128"); |
| 1640 | 1630 | } |
| 1641 | 1631 | } |
| ... | ... | @@ -1649,10 +1639,12 @@ impl<'db> Evaluator<'db> { |
| 1649 | 1639 | }) |
| 1650 | 1640 | } |
| 1651 | 1641 | |
| 1652 | fn compute_discriminant(&self, ty: Ty, bytes: &[u8]) -> Result<i128> { | |
| 1653 | let interner = DbInterner::new_with(self.db, None, None); | |
| 1654 | let layout = self.layout(ty.to_nextsolver(interner))?; | |
| 1655 | let &TyKind::Adt(chalk_ir::AdtId(AdtId::EnumId(e)), _) = ty.kind(Interner) else { | |
| 1642 | fn compute_discriminant(&self, ty: Ty<'db>, bytes: &[u8]) -> Result<'db, i128> { | |
| 1643 | let layout = self.layout(ty)?; | |
| 1644 | let TyKind::Adt(adt_def, _) = ty.kind() else { | |
| 1645 | return Ok(0); | |
| 1646 | }; | |
| 1647 | let AdtId::EnumId(e) = adt_def.def_id().0 else { | |
| 1656 | 1648 | return Ok(0); |
| 1657 | 1649 | }; |
| 1658 | 1650 | match &layout.variants { |
| ... | ... | @@ -1694,35 +1686,35 @@ impl<'db> Evaluator<'db> { |
| 1694 | 1686 | |
| 1695 | 1687 | fn coerce_unsized_look_through_fields<T>( |
| 1696 | 1688 | &self, |
| 1697 | ty: &Ty, | |
| 1698 | goal: impl Fn(&TyKind) -> Option<T>, | |
| 1699 | ) -> Result<T> { | |
| 1700 | let kind = ty.kind(Interner); | |
| 1689 | ty: Ty<'db>, | |
| 1690 | goal: impl Fn(TyKind<'db>) -> Option<T>, | |
| 1691 | ) -> Result<'db, T> { | |
| 1692 | let kind = ty.kind(); | |
| 1701 | 1693 | if let Some(it) = goal(kind) { |
| 1702 | 1694 | return Ok(it); |
| 1703 | 1695 | } |
| 1704 | if let TyKind::Adt(id, subst) = kind | |
| 1705 | && let AdtId::StructId(struct_id) = id.0 | |
| 1696 | if let TyKind::Adt(adt_ef, subst) = kind | |
| 1697 | && let AdtId::StructId(struct_id) = adt_ef.def_id().0 | |
| 1706 | 1698 | { |
| 1707 | let field_types = self.db.field_types(struct_id.into()); | |
| 1699 | let field_types = self.db.field_types_ns(struct_id.into()); | |
| 1708 | 1700 | if let Some(ty) = |
| 1709 | field_types.iter().last().map(|it| it.1.clone().substitute(Interner, subst)) | |
| 1701 | field_types.iter().last().map(|it| it.1.instantiate(self.interner(), subst)) | |
| 1710 | 1702 | { |
| 1711 | return self.coerce_unsized_look_through_fields(&ty, goal); | |
| 1703 | return self.coerce_unsized_look_through_fields(ty, goal); | |
| 1712 | 1704 | } |
| 1713 | 1705 | } |
| 1714 | Err(MirEvalError::CoerceUnsizedError(ty.clone())) | |
| 1706 | Err(MirEvalError::CoerceUnsizedError(ty)) | |
| 1715 | 1707 | } |
| 1716 | 1708 | |
| 1717 | 1709 | fn coerce_unsized( |
| 1718 | 1710 | &mut self, |
| 1719 | 1711 | addr: Interval, |
| 1720 | current_ty: &Ty, | |
| 1721 | target_ty: &Ty, | |
| 1722 | ) -> Result<IntervalOrOwned> { | |
| 1723 | fn for_ptr(it: &TyKind) -> Option<Ty> { | |
| 1712 | current_ty: Ty<'db>, | |
| 1713 | target_ty: Ty<'db>, | |
| 1714 | ) -> Result<'db, IntervalOrOwned> { | |
| 1715 | fn for_ptr<'db>(it: TyKind<'db>) -> Option<Ty<'db>> { | |
| 1724 | 1716 | match it { |
| 1725 | TyKind::Raw(_, ty) | TyKind::Ref(_, _, ty) => Some(ty.clone()), | |
| 1717 | TyKind::RawPtr(ty, _) | TyKind::Ref(_, ty, _) => Some(ty), | |
| 1726 | 1718 | _ => None, |
| 1727 | 1719 | } |
| 1728 | 1720 | } |
| ... | ... | @@ -1735,15 +1727,15 @@ impl<'db> Evaluator<'db> { |
| 1735 | 1727 | /// Adds metadata to the address and create the fat pointer result of the unsizing operation. |
| 1736 | 1728 | fn unsizing_ptr_from_addr( |
| 1737 | 1729 | &mut self, |
| 1738 | target_ty: Ty, | |
| 1739 | current_ty: Ty, | |
| 1730 | target_ty: Ty<'db>, | |
| 1731 | current_ty: Ty<'db>, | |
| 1740 | 1732 | addr: Interval, |
| 1741 | ) -> Result<IntervalOrOwned> { | |
| 1733 | ) -> Result<'db, IntervalOrOwned> { | |
| 1742 | 1734 | use IntervalOrOwned::*; |
| 1743 | Ok(match &target_ty.kind(Interner) { | |
| 1744 | TyKind::Slice(_) => match &current_ty.kind(Interner) { | |
| 1735 | Ok(match &target_ty.kind() { | |
| 1736 | TyKind::Slice(_) => match &current_ty.kind() { | |
| 1745 | 1737 | TyKind::Array(_, size) => { |
| 1746 | let len = match try_const_usize(self.db, size) { | |
| 1738 | let len = match try_const_usize(self.db, *size) { | |
| 1747 | 1739 | None => { |
| 1748 | 1740 | not_supported!("unevaluatble len of array in coerce unsized") |
| 1749 | 1741 | } |
| ... | ... | @@ -1759,9 +1751,7 @@ impl<'db> Evaluator<'db> { |
| 1759 | 1751 | not_supported!("slice unsizing from non array type {t:?}") |
| 1760 | 1752 | } |
| 1761 | 1753 | }, |
| 1762 | TyKind::Dyn(_) => { | |
| 1763 | let interner = DbInterner::new_with(self.db, None, None); | |
| 1764 | let current_ty = current_ty.to_nextsolver(interner); | |
| 1754 | TyKind::Dynamic(..) => { | |
| 1765 | 1755 | let vtable = self.vtable_map.id(current_ty); |
| 1766 | 1756 | let mut r = Vec::with_capacity(16); |
| 1767 | 1757 | let addr = addr.get(self)?; |
| ... | ... | @@ -1769,12 +1759,14 @@ impl<'db> Evaluator<'db> { |
| 1769 | 1759 | r.extend(vtable.to_le_bytes()); |
| 1770 | 1760 | Owned(r) |
| 1771 | 1761 | } |
| 1772 | TyKind::Adt(id, target_subst) => match &current_ty.kind(Interner) { | |
| 1773 | TyKind::Adt(current_id, current_subst) => { | |
| 1762 | TyKind::Adt(adt_def, target_subst) => match &current_ty.kind() { | |
| 1763 | TyKind::Adt(current_adt_def, current_subst) => { | |
| 1764 | let id = adt_def.def_id().0; | |
| 1765 | let current_id = current_adt_def.def_id().0; | |
| 1774 | 1766 | if id != current_id { |
| 1775 | 1767 | not_supported!("unsizing struct with different type"); |
| 1776 | 1768 | } |
| 1777 | let id = match id.0 { | |
| 1769 | let id = match id { | |
| 1778 | 1770 | AdtId::StructId(s) => s, |
| 1779 | 1771 | AdtId::UnionId(_) => not_supported!("unsizing unions"), |
| 1780 | 1772 | AdtId::EnumId(_) => not_supported!("unsizing enums"), |
| ... | ... | @@ -1783,12 +1775,10 @@ impl<'db> Evaluator<'db> { |
| 1783 | 1775 | else { |
| 1784 | 1776 | not_supported!("unsizing struct without field"); |
| 1785 | 1777 | }; |
| 1786 | let target_last_field = self.db.field_types(id.into())[last_field] | |
| 1787 | .clone() | |
| 1788 | .substitute(Interner, target_subst); | |
| 1789 | let current_last_field = self.db.field_types(id.into())[last_field] | |
| 1790 | .clone() | |
| 1791 | .substitute(Interner, current_subst); | |
| 1778 | let target_last_field = self.db.field_types_ns(id.into())[last_field] | |
| 1779 | .instantiate(self.interner(), target_subst); | |
| 1780 | let current_last_field = self.db.field_types_ns(id.into())[last_field] | |
| 1781 | .instantiate(self.interner(), current_subst); | |
| 1792 | 1782 | return self.unsizing_ptr_from_addr( |
| 1793 | 1783 | target_last_field, |
| 1794 | 1784 | current_last_field, |
| ... | ... | @@ -1804,10 +1794,9 @@ impl<'db> Evaluator<'db> { |
| 1804 | 1794 | fn layout_of_variant( |
| 1805 | 1795 | &mut self, |
| 1806 | 1796 | it: VariantId, |
| 1807 | subst: Substitution, | |
| 1808 | locals: &Locals, | |
| 1809 | ) -> Result<(usize, Arc<Layout>, Option<(usize, usize, i128)>)> { | |
| 1810 | let interner = DbInterner::new_with(self.db, None, None); | |
| 1797 | subst: GenericArgs<'db>, | |
| 1798 | locals: &Locals<'db>, | |
| 1799 | ) -> Result<'db, (usize, Arc<Layout>, Option<(usize, usize, i128)>)> { | |
| 1811 | 1800 | let adt = it.adt_id(self.db); |
| 1812 | 1801 | if let DefWithBodyId::VariantId(f) = locals.body.owner |
| 1813 | 1802 | && let VariantId::EnumVariantId(it) = it |
| ... | ... | @@ -1817,11 +1806,7 @@ impl<'db> Evaluator<'db> { |
| 1817 | 1806 | // Computing the exact size of enums require resolving the enum discriminants. In order to prevent loops (and |
| 1818 | 1807 | // infinite sized type errors) we use a dummy layout |
| 1819 | 1808 | let i = self.const_eval_discriminant(it)?; |
| 1820 | return Ok(( | |
| 1821 | 16, | |
| 1822 | self.layout(crate::next_solver::Ty::new_empty_tuple(interner))?, | |
| 1823 | Some((0, 16, i)), | |
| 1824 | )); | |
| 1809 | return Ok((16, self.layout(Ty::new_empty_tuple(self.interner()))?, Some((0, 16, i)))); | |
| 1825 | 1810 | } |
| 1826 | 1811 | let layout = self.layout_adt(adt, subst)?; |
| 1827 | 1812 | Ok(match &layout.variants { |
| ... | ... | @@ -1874,7 +1859,7 @@ impl<'db> Evaluator<'db> { |
| 1874 | 1859 | variant_layout: &Layout, |
| 1875 | 1860 | tag: Option<(usize, usize, i128)>, |
| 1876 | 1861 | values: impl Iterator<Item = IntervalOrOwned>, |
| 1877 | ) -> Result<Vec<u8>> { | |
| 1862 | ) -> Result<'db, Vec<u8>> { | |
| 1878 | 1863 | let mut result = vec![0; size]; |
| 1879 | 1864 | if let Some((offset, size, value)) = tag { |
| 1880 | 1865 | match result.get_mut(offset..offset + size) { |
| ... | ... | @@ -1904,7 +1889,11 @@ impl<'db> Evaluator<'db> { |
| 1904 | 1889 | Ok(result) |
| 1905 | 1890 | } |
| 1906 | 1891 | |
| 1907 | fn eval_operand(&mut self, it: &Operand, locals: &mut Locals) -> Result<Interval> { | |
| 1892 | fn eval_operand( | |
| 1893 | &mut self, | |
| 1894 | it: &Operand<'db>, | |
| 1895 | locals: &mut Locals<'db>, | |
| 1896 | ) -> Result<'db, Interval> { | |
| 1908 | 1897 | Ok(match &it.kind { |
| 1909 | 1898 | OperandKind::Copy(p) | OperandKind::Move(p) => { |
| 1910 | 1899 | locals.drop_flags.remove_place(p, &locals.body.projection_store); |
| ... | ... | @@ -1914,25 +1903,28 @@ impl<'db> Evaluator<'db> { |
| 1914 | 1903 | let addr = self.eval_static(*st, locals)?; |
| 1915 | 1904 | Interval::new(addr, self.ptr_size()) |
| 1916 | 1905 | } |
| 1917 | OperandKind::Constant(konst) => self.allocate_const_in_heap(locals, konst)?, | |
| 1906 | OperandKind::Constant { konst, .. } => self.allocate_const_in_heap(locals, *konst)?, | |
| 1918 | 1907 | }) |
| 1919 | 1908 | } |
| 1920 | 1909 | |
| 1921 | 1910 | #[allow(clippy::double_parens)] |
| 1922 | fn allocate_const_in_heap(&mut self, locals: &Locals, konst: &Const) -> Result<Interval> { | |
| 1923 | let interner = DbInterner::new_with(self.db, None, None); | |
| 1924 | let ConstData { ty, value: chalk_ir::ConstValue::Concrete(c) } = &konst.data(Interner) | |
| 1925 | else { | |
| 1926 | not_supported!("evaluating non concrete constant"); | |
| 1927 | }; | |
| 1911 | fn allocate_const_in_heap( | |
| 1912 | &mut self, | |
| 1913 | locals: &Locals<'db>, | |
| 1914 | konst: Const<'db>, | |
| 1915 | ) -> Result<'db, Interval> { | |
| 1928 | 1916 | let result_owner; |
| 1929 | let (v, memory_map) = match &c.interned { | |
| 1930 | ConstScalar::Bytes(v, mm) => (v, mm), | |
| 1931 | ConstScalar::UnevaluatedConst(const_id, subst) => 'b: { | |
| 1932 | let mut const_id = *const_id; | |
| 1933 | let mut subst = subst.clone(); | |
| 1917 | let value = match konst.kind() { | |
| 1918 | ConstKind::Value(value) => value, | |
| 1919 | ConstKind::Unevaluated(UnevaluatedConst { def: const_id, args: subst }) => 'b: { | |
| 1920 | let mut const_id = match const_id { | |
| 1921 | SolverDefId::ConstId(it) => GeneralConstId::from(it), | |
| 1922 | SolverDefId::StaticId(it) => it.into(), | |
| 1923 | _ => unreachable!("unevaluated consts should be consts or statics"), | |
| 1924 | }; | |
| 1925 | let mut subst = subst; | |
| 1934 | 1926 | if let hir_def::GeneralConstId::ConstId(c) = const_id { |
| 1935 | let (c, s) = lookup_impl_const(self.db, self.trait_env.clone(), c, subst); | |
| 1927 | let (c, s) = lookup_impl_const(&self.infcx, self.trait_env.clone(), c, subst); | |
| 1936 | 1928 | const_id = hir_def::GeneralConstId::ConstId(c); |
| 1937 | 1929 | subst = s; |
| 1938 | 1930 | } |
| ... | ... | @@ -1943,15 +1935,15 @@ impl<'db> Evaluator<'db> { |
| 1943 | 1935 | let name = const_id.name(self.db); |
| 1944 | 1936 | MirEvalError::ConstEvalError(name, Box::new(e)) |
| 1945 | 1937 | })?; |
| 1946 | if let chalk_ir::ConstValue::Concrete(c) = &result_owner.data(Interner).value | |
| 1947 | && let ConstScalar::Bytes(v, mm) = &c.interned | |
| 1948 | { | |
| 1949 | break 'b (v, mm); | |
| 1938 | if let ConstKind::Value(value) = result_owner.kind() { | |
| 1939 | break 'b value; | |
| 1950 | 1940 | } |
| 1951 | 1941 | not_supported!("unevaluatable constant"); |
| 1952 | 1942 | } |
| 1953 | ConstScalar::Unknown => not_supported!("evaluating unknown const"), | |
| 1943 | _ => not_supported!("evaluating unknown const"), | |
| 1954 | 1944 | }; |
| 1945 | let ValueConst { ty, value } = value; | |
| 1946 | let ConstBytes { memory: v, memory_map } = value.inner(); | |
| 1955 | 1947 | let patch_map = memory_map.transform_addresses(|b, align| { |
| 1956 | 1948 | let addr = self.heap_allocate(b.len(), align)?; |
| 1957 | 1949 | self.write_memory(addr, b)?; |
| ... | ... | @@ -1965,7 +1957,7 @@ impl<'db> Evaluator<'db> { |
| 1965 | 1957 | } else if size < 16 && v.len() == 16 { |
| 1966 | 1958 | Cow::Borrowed(&v[0..size]) |
| 1967 | 1959 | } else { |
| 1968 | return Err(MirEvalError::InvalidConst(konst.clone())); | |
| 1960 | return Err(MirEvalError::InvalidConst(konst)); | |
| 1969 | 1961 | } |
| 1970 | 1962 | } else { |
| 1971 | 1963 | Cow::Borrowed(v) |
| ... | ... | @@ -1981,21 +1973,21 @@ impl<'db> Evaluator<'db> { |
| 1981 | 1973 | MemoryMap::Complex(cm) => cm.vtable.ty_of_bytes(bytes), |
| 1982 | 1974 | }, |
| 1983 | 1975 | addr, |
| 1984 | ty.to_nextsolver(interner), | |
| 1976 | ty, | |
| 1985 | 1977 | locals, |
| 1986 | 1978 | )?; |
| 1987 | 1979 | Ok(Interval::new(addr, size)) |
| 1988 | 1980 | } |
| 1989 | 1981 | |
| 1990 | fn eval_place(&mut self, p: &Place, locals: &Locals) -> Result<Interval> { | |
| 1982 | fn eval_place(&mut self, p: &Place<'db>, locals: &Locals<'db>) -> Result<'db, Interval> { | |
| 1991 | 1983 | let addr = self.place_addr(p, locals)?; |
| 1992 | 1984 | Ok(Interval::new( |
| 1993 | 1985 | addr, |
| 1994 | self.size_of_sized(&self.place_ty(p, locals)?, locals, "type of this place")?, | |
| 1986 | self.size_of_sized(self.place_ty(p, locals)?, locals, "type of this place")?, | |
| 1995 | 1987 | )) |
| 1996 | 1988 | } |
| 1997 | 1989 | |
| 1998 | fn read_memory(&self, addr: Address, size: usize) -> Result<&[u8]> { | |
| 1990 | fn read_memory(&self, addr: Address, size: usize) -> Result<'db, &[u8]> { | |
| 1999 | 1991 | if size == 0 { |
| 2000 | 1992 | return Ok(&[]); |
| 2001 | 1993 | } |
| ... | ... | @@ -2012,7 +2004,7 @@ impl<'db> Evaluator<'db> { |
| 2012 | 2004 | .ok_or_else(|| MirEvalError::UndefinedBehavior("out of bound memory read".to_owned())) |
| 2013 | 2005 | } |
| 2014 | 2006 | |
| 2015 | fn write_memory_using_ref(&mut self, addr: Address, size: usize) -> Result<&mut [u8]> { | |
| 2007 | fn write_memory_using_ref(&mut self, addr: Address, size: usize) -> Result<'db, &mut [u8]> { | |
| 2016 | 2008 | let (mem, pos) = match addr { |
| 2017 | 2009 | Stack(it) => (&mut self.stack, it), |
| 2018 | 2010 | Heap(it) => (&mut self.heap, it), |
| ... | ... | @@ -2026,7 +2018,7 @@ impl<'db> Evaluator<'db> { |
| 2026 | 2018 | .ok_or_else(|| MirEvalError::UndefinedBehavior("out of bound memory write".to_owned())) |
| 2027 | 2019 | } |
| 2028 | 2020 | |
| 2029 | fn write_memory(&mut self, addr: Address, r: &[u8]) -> Result<()> { | |
| 2021 | fn write_memory(&mut self, addr: Address, r: &[u8]) -> Result<'db, ()> { | |
| 2030 | 2022 | if r.is_empty() { |
| 2031 | 2023 | return Ok(()); |
| 2032 | 2024 | } |
| ... | ... | @@ -2034,14 +2026,18 @@ impl<'db> Evaluator<'db> { |
| 2034 | 2026 | Ok(()) |
| 2035 | 2027 | } |
| 2036 | 2028 | |
| 2037 | fn copy_from_interval_or_owned(&mut self, addr: Address, r: IntervalOrOwned) -> Result<()> { | |
| 2029 | fn copy_from_interval_or_owned( | |
| 2030 | &mut self, | |
| 2031 | addr: Address, | |
| 2032 | r: IntervalOrOwned, | |
| 2033 | ) -> Result<'db, ()> { | |
| 2038 | 2034 | match r { |
| 2039 | 2035 | IntervalOrOwned::Borrowed(r) => self.copy_from_interval(addr, r), |
| 2040 | 2036 | IntervalOrOwned::Owned(r) => self.write_memory(addr, &r), |
| 2041 | 2037 | } |
| 2042 | 2038 | } |
| 2043 | 2039 | |
| 2044 | fn copy_from_interval(&mut self, addr: Address, r: Interval) -> Result<()> { | |
| 2040 | fn copy_from_interval(&mut self, addr: Address, r: Interval) -> Result<'db, ()> { | |
| 2045 | 2041 | if r.size == 0 { |
| 2046 | 2042 | return Ok(()); |
| 2047 | 2043 | } |
| ... | ... | @@ -2083,9 +2079,12 @@ impl<'db> Evaluator<'db> { |
| 2083 | 2079 | Ok(()) |
| 2084 | 2080 | } |
| 2085 | 2081 | |
| 2086 | fn size_align_of(&self, ty: &Ty, locals: &Locals) -> Result<Option<(usize, usize)>> { | |
| 2087 | let interner = DbInterner::new_with(self.db, None, None); | |
| 2088 | if let Some(layout) = self.layout_cache.borrow().get(&ty.to_nextsolver(interner)) { | |
| 2082 | fn size_align_of( | |
| 2083 | &self, | |
| 2084 | ty: Ty<'db>, | |
| 2085 | locals: &Locals<'db>, | |
| 2086 | ) -> Result<'db, Option<(usize, usize)>> { | |
| 2087 | if let Some(layout) = self.layout_cache.borrow().get(&ty) { | |
| 2089 | 2088 | return Ok(layout |
| 2090 | 2089 | .is_sized() |
| 2091 | 2090 | .then(|| (layout.size.bytes_usize(), layout.align.bytes() as usize))); |
| ... | ... | @@ -2098,24 +2097,27 @@ impl<'db> Evaluator<'db> { |
| 2098 | 2097 | // infinite sized type errors) we use a dummy size |
| 2099 | 2098 | return Ok(Some((16, 16))); |
| 2100 | 2099 | } |
| 2101 | let layout = self.layout(ty.to_nextsolver(interner)); | |
| 2100 | let layout = self.layout(ty); | |
| 2102 | 2101 | if self.assert_placeholder_ty_is_unused |
| 2103 | 2102 | && matches!(layout, Err(MirEvalError::LayoutError(LayoutError::HasPlaceholder, _))) |
| 2104 | 2103 | { |
| 2105 | 2104 | return Ok(Some((0, 1))); |
| 2106 | 2105 | } |
| 2107 | 2106 | let layout = layout?; |
| 2108 | Ok(layout | |
| 2109 | .is_sized() | |
| 2110 | .then(|| (layout.size.bytes_usize(), layout.align.bytes() as usize))) | |
| 2107 | Ok(layout.is_sized().then(|| (layout.size.bytes_usize(), layout.align.bytes() as usize))) | |
| 2111 | 2108 | } |
| 2112 | 2109 | |
| 2113 | 2110 | /// A version of `self.size_of` which returns error if the type is unsized. `what` argument should |
| 2114 | 2111 | /// be something that complete this: `error: type {ty} was unsized. {what} should be sized` |
| 2115 | fn size_of_sized(&self, ty: &Ty, locals: &Locals, what: &'static str) -> Result<usize> { | |
| 2112 | fn size_of_sized( | |
| 2113 | &self, | |
| 2114 | ty: Ty<'db>, | |
| 2115 | locals: &Locals<'db>, | |
| 2116 | what: &'static str, | |
| 2117 | ) -> Result<'db, usize> { | |
| 2116 | 2118 | match self.size_align_of(ty, locals)? { |
| 2117 | 2119 | Some(it) => Ok(it.0), |
| 2118 | None => Err(MirEvalError::TypeIsUnsized(ty.clone(), what)), | |
| 2120 | None => Err(MirEvalError::TypeIsUnsized(ty, what)), | |
| 2119 | 2121 | } |
| 2120 | 2122 | } |
| 2121 | 2123 | |
| ... | ... | @@ -2123,17 +2125,17 @@ impl<'db> Evaluator<'db> { |
| 2123 | 2125 | /// be something that complete this: `error: type {ty} was unsized. {what} should be sized` |
| 2124 | 2126 | fn size_align_of_sized( |
| 2125 | 2127 | &self, |
| 2126 | ty: &Ty, | |
| 2127 | locals: &Locals, | |
| 2128 | ty: Ty<'db>, | |
| 2129 | locals: &Locals<'db>, | |
| 2128 | 2130 | what: &'static str, |
| 2129 | ) -> Result<(usize, usize)> { | |
| 2131 | ) -> Result<'db, (usize, usize)> { | |
| 2130 | 2132 | match self.size_align_of(ty, locals)? { |
| 2131 | 2133 | Some(it) => Ok(it), |
| 2132 | None => Err(MirEvalError::TypeIsUnsized(ty.clone(), what)), | |
| 2134 | None => Err(MirEvalError::TypeIsUnsized(ty, what)), | |
| 2133 | 2135 | } |
| 2134 | 2136 | } |
| 2135 | 2137 | |
| 2136 | fn heap_allocate(&mut self, size: usize, align: usize) -> Result<Address> { | |
| 2138 | fn heap_allocate(&mut self, size: usize, align: usize) -> Result<'db, Address> { | |
| 2137 | 2139 | if !align.is_power_of_two() || align > 10000 { |
| 2138 | 2140 | return Err(MirEvalError::UndefinedBehavior(format!("Alignment {align} is invalid"))); |
| 2139 | 2141 | } |
| ... | ... | @@ -2164,23 +2166,22 @@ impl<'db> Evaluator<'db> { |
| 2164 | 2166 | fn create_memory_map( |
| 2165 | 2167 | &self, |
| 2166 | 2168 | bytes: &[u8], |
| 2167 | ty: &Ty, | |
| 2168 | locals: &Locals, | |
| 2169 | ) -> Result<ComplexMemoryMap<'db>> { | |
| 2169 | ty: Ty<'db>, | |
| 2170 | locals: &Locals<'db>, | |
| 2171 | ) -> Result<'db, ComplexMemoryMap<'db>> { | |
| 2170 | 2172 | fn rec<'db>( |
| 2171 | 2173 | this: &Evaluator<'db>, |
| 2172 | 2174 | bytes: &[u8], |
| 2173 | ty: &Ty, | |
| 2174 | locals: &Locals, | |
| 2175 | ty: Ty<'db>, | |
| 2176 | locals: &Locals<'db>, | |
| 2175 | 2177 | mm: &mut ComplexMemoryMap<'db>, |
| 2176 | 2178 | stack_depth_limit: usize, |
| 2177 | ) -> Result<()> { | |
| 2178 | let interner = DbInterner::new_with(this.db, None, None); | |
| 2179 | ) -> Result<'db, ()> { | |
| 2179 | 2180 | if stack_depth_limit.checked_sub(1).is_none() { |
| 2180 | 2181 | return Err(MirEvalError::StackOverflow); |
| 2181 | 2182 | } |
| 2182 | match ty.kind(Interner) { | |
| 2183 | TyKind::Ref(_, _, t) => { | |
| 2183 | match ty.kind() { | |
| 2184 | TyKind::Ref(_, t, _) => { | |
| 2184 | 2185 | let size = this.size_align_of(t, locals)?; |
| 2185 | 2186 | match size { |
| 2186 | 2187 | Some((size, _)) => { |
| ... | ... | @@ -2193,29 +2194,28 @@ impl<'db> Evaluator<'db> { |
| 2193 | 2194 | None => { |
| 2194 | 2195 | let mut check_inner = None; |
| 2195 | 2196 | let (addr, meta) = bytes.split_at(bytes.len() / 2); |
| 2196 | let element_size = match t.kind(Interner) { | |
| 2197 | let element_size = match t.kind() { | |
| 2197 | 2198 | TyKind::Str => 1, |
| 2198 | 2199 | TyKind::Slice(t) => { |
| 2199 | check_inner = Some(t.clone()); | |
| 2200 | check_inner = Some(t); | |
| 2200 | 2201 | this.size_of_sized(t, locals, "slice inner type")? |
| 2201 | 2202 | } |
| 2202 | TyKind::Dyn(_) => { | |
| 2203 | TyKind::Dynamic(..) => { | |
| 2203 | 2204 | let t = this.vtable_map.ty_of_bytes(meta)?; |
| 2204 | let t = convert_ty_for_result(interner, t); | |
| 2205 | check_inner = Some(t.clone()); | |
| 2206 | this.size_of_sized(&t, locals, "dyn concrete type")? | |
| 2205 | check_inner = Some(t); | |
| 2206 | this.size_of_sized(t, locals, "dyn concrete type")? | |
| 2207 | 2207 | } |
| 2208 | 2208 | _ => return Ok(()), |
| 2209 | 2209 | }; |
| 2210 | let count = match t.kind(Interner) { | |
| 2211 | TyKind::Dyn(_) => 1, | |
| 2210 | let count = match t.kind() { | |
| 2211 | TyKind::Dynamic(..) => 1, | |
| 2212 | 2212 | _ => from_bytes!(usize, meta), |
| 2213 | 2213 | }; |
| 2214 | 2214 | let size = element_size * count; |
| 2215 | 2215 | let addr = Address::from_bytes(addr)?; |
| 2216 | 2216 | let b = this.read_memory(addr, size)?; |
| 2217 | 2217 | mm.insert(addr.to_usize(), b.into()); |
| 2218 | if let Some(ty) = &check_inner { | |
| 2218 | if let Some(ty) = check_inner { | |
| 2219 | 2219 | for i in 0..count { |
| 2220 | 2220 | let offset = element_size * i; |
| 2221 | 2221 | rec( |
| ... | ... | @@ -2249,12 +2249,11 @@ impl<'db> Evaluator<'db> { |
| 2249 | 2249 | )?; |
| 2250 | 2250 | } |
| 2251 | 2251 | } |
| 2252 | TyKind::Tuple(_, subst) => { | |
| 2253 | let layout = this.layout(ty.to_nextsolver(interner))?; | |
| 2254 | for (id, ty) in subst.iter(Interner).enumerate() { | |
| 2255 | let ty = ty.assert_ty_ref(Interner); // Tuple only has type argument | |
| 2252 | TyKind::Tuple(subst) => { | |
| 2253 | let layout = this.layout(ty)?; | |
| 2254 | for (id, ty) in subst.iter().enumerate() { | |
| 2256 | 2255 | let offset = layout.fields.offset(id).bytes_usize(); |
| 2257 | let size = this.layout(ty.to_nextsolver(interner))?.size.bytes_usize(); | |
| 2256 | let size = this.layout(ty)?.size.bytes_usize(); | |
| 2258 | 2257 | rec( |
| 2259 | 2258 | this, |
| 2260 | 2259 | &bytes[offset..offset + size], |
| ... | ... | @@ -2265,18 +2264,18 @@ impl<'db> Evaluator<'db> { |
| 2265 | 2264 | )?; |
| 2266 | 2265 | } |
| 2267 | 2266 | } |
| 2268 | TyKind::Adt(adt, subst) => match adt.0 { | |
| 2267 | TyKind::Adt(adt, subst) => match adt.def_id().0 { | |
| 2269 | 2268 | AdtId::StructId(s) => { |
| 2270 | 2269 | let data = s.fields(this.db); |
| 2271 | let layout = this.layout(ty.to_nextsolver(interner))?; | |
| 2272 | let field_types = this.db.field_types(s.into()); | |
| 2270 | let layout = this.layout(ty)?; | |
| 2271 | let field_types = this.db.field_types_ns(s.into()); | |
| 2273 | 2272 | for (f, _) in data.fields().iter() { |
| 2274 | 2273 | let offset = layout |
| 2275 | 2274 | .fields |
| 2276 | 2275 | .offset(u32::from(f.into_raw()) as usize) |
| 2277 | 2276 | .bytes_usize(); |
| 2278 | let ty = &field_types[f].clone().substitute(Interner, subst); | |
| 2279 | let size = this.layout(ty.to_nextsolver(interner))?.size.bytes_usize(); | |
| 2277 | let ty = field_types[f].instantiate(this.interner(), subst); | |
| 2278 | let size = this.layout(ty)?.size.bytes_usize(); | |
| 2280 | 2279 | rec( |
| 2281 | 2280 | this, |
| 2282 | 2281 | &bytes[offset..offset + size], |
| ... | ... | @@ -2288,7 +2287,7 @@ impl<'db> Evaluator<'db> { |
| 2288 | 2287 | } |
| 2289 | 2288 | } |
| 2290 | 2289 | AdtId::EnumId(e) => { |
| 2291 | let layout = this.layout(ty.to_nextsolver(interner))?; | |
| 2290 | let layout = this.layout(ty)?; | |
| 2292 | 2291 | if let Some((v, l)) = detect_variant_from_bytes( |
| 2293 | 2292 | &layout, |
| 2294 | 2293 | this.db, |
| ... | ... | @@ -2297,13 +2296,12 @@ impl<'db> Evaluator<'db> { |
| 2297 | 2296 | e, |
| 2298 | 2297 | ) { |
| 2299 | 2298 | let data = v.fields(this.db); |
| 2300 | let field_types = this.db.field_types(v.into()); | |
| 2299 | let field_types = this.db.field_types_ns(v.into()); | |
| 2301 | 2300 | for (f, _) in data.fields().iter() { |
| 2302 | 2301 | let offset = |
| 2303 | 2302 | l.fields.offset(u32::from(f.into_raw()) as usize).bytes_usize(); |
| 2304 | let ty = &field_types[f].clone().substitute(Interner, subst); | |
| 2305 | let size = | |
| 2306 | this.layout(ty.to_nextsolver(interner))?.size.bytes_usize(); | |
| 2303 | let ty = field_types[f].instantiate(this.interner(), subst); | |
| 2304 | let size = this.layout(ty)?.size.bytes_usize(); | |
| 2307 | 2305 | rec( |
| 2308 | 2306 | this, |
| 2309 | 2307 | &bytes[offset..offset + size], |
| ... | ... | @@ -2317,9 +2315,17 @@ impl<'db> Evaluator<'db> { |
| 2317 | 2315 | } |
| 2318 | 2316 | AdtId::UnionId(_) => (), |
| 2319 | 2317 | }, |
| 2320 | TyKind::Alias(AliasTy::Projection(proj)) => { | |
| 2321 | let ty = this.db.normalize_projection(proj.clone(), this.trait_env.clone()); | |
| 2322 | rec(this, bytes, &ty, locals, mm, stack_depth_limit - 1)?; | |
| 2318 | TyKind::Alias(AliasTyKind::Projection, _) => { | |
| 2319 | let mut ocx = ObligationCtxt::new(&this.infcx); | |
| 2320 | let ty = ocx | |
| 2321 | .structurally_normalize_ty( | |
| 2322 | &ObligationCause::dummy(), | |
| 2323 | this.trait_env.env, | |
| 2324 | ty, | |
| 2325 | ) | |
| 2326 | .map_err(|_| MirEvalError::NotSupported("couldn't normalize".to_owned()))?; | |
| 2327 | ||
| 2328 | rec(this, bytes, ty, locals, mm, stack_depth_limit - 1)?; | |
| 2323 | 2329 | } |
| 2324 | 2330 | _ => (), |
| 2325 | 2331 | } |
| ... | ... | @@ -2333,23 +2339,18 @@ impl<'db> Evaluator<'db> { |
| 2333 | 2339 | fn patch_addresses( |
| 2334 | 2340 | &mut self, |
| 2335 | 2341 | patch_map: &FxHashMap<usize, usize>, |
| 2336 | ty_of_bytes: impl Fn(&[u8]) -> Result<crate::next_solver::Ty<'db>> + Copy, | |
| 2342 | ty_of_bytes: impl Fn(&[u8]) -> Result<'db, Ty<'db>> + Copy, | |
| 2337 | 2343 | addr: Address, |
| 2338 | ty: crate::next_solver::Ty<'db>, | |
| 2339 | locals: &Locals, | |
| 2340 | ) -> Result<()> { | |
| 2341 | let interner = DbInterner::new_with(self.db, None, None); | |
| 2344 | ty: Ty<'db>, | |
| 2345 | locals: &Locals<'db>, | |
| 2346 | ) -> Result<'db, ()> { | |
| 2342 | 2347 | // FIXME: support indirect references |
| 2343 | 2348 | let layout = self.layout(ty)?; |
| 2344 | let my_size = self.size_of_sized( | |
| 2345 | &convert_ty_for_result(interner, ty), | |
| 2346 | locals, | |
| 2347 | "value to patch address", | |
| 2348 | )?; | |
| 2349 | let my_size = self.size_of_sized(ty, locals, "value to patch address")?; | |
| 2349 | 2350 | use rustc_type_ir::TyKind; |
| 2350 | 2351 | match ty.kind() { |
| 2351 | 2352 | TyKind::Ref(_, t, _) => { |
| 2352 | let size = self.size_align_of(&convert_ty_for_result(interner, t), locals)?; | |
| 2353 | let size = self.size_align_of(t, locals)?; | |
| 2353 | 2354 | match size { |
| 2354 | 2355 | Some(_) => { |
| 2355 | 2356 | let current = from_bytes!(usize, self.read_memory(addr, my_size)?); |
| ... | ... | @@ -2374,7 +2375,7 @@ impl<'db> Evaluator<'db> { |
| 2374 | 2375 | AdtId::StructId(s) => { |
| 2375 | 2376 | for (i, (_, ty)) in self.db.field_types_ns(s.into()).iter().enumerate() { |
| 2376 | 2377 | let offset = layout.fields.offset(i).bytes_usize(); |
| 2377 | let ty = ty.instantiate(interner, args); | |
| 2378 | let ty = ty.instantiate(self.interner(), args); | |
| 2378 | 2379 | self.patch_addresses( |
| 2379 | 2380 | patch_map, |
| 2380 | 2381 | ty_of_bytes, |
| ... | ... | @@ -2395,7 +2396,7 @@ impl<'db> Evaluator<'db> { |
| 2395 | 2396 | ) { |
| 2396 | 2397 | for (i, (_, ty)) in self.db.field_types_ns(ev.into()).iter().enumerate() { |
| 2397 | 2398 | let offset = layout.fields.offset(i).bytes_usize(); |
| 2398 | let ty = ty.instantiate(interner, args); | |
| 2399 | let ty = ty.instantiate(self.interner(), args); | |
| 2399 | 2400 | self.patch_addresses( |
| 2400 | 2401 | patch_map, |
| 2401 | 2402 | ty_of_bytes, |
| ... | ... | @@ -2414,15 +2415,11 @@ impl<'db> Evaluator<'db> { |
| 2414 | 2415 | } |
| 2415 | 2416 | } |
| 2416 | 2417 | TyKind::Array(inner, len) => { |
| 2417 | let len = match consteval_nextsolver::try_const_usize(self.db, len) { | |
| 2418 | let len = match consteval::try_const_usize(self.db, len) { | |
| 2418 | 2419 | Some(it) => it as usize, |
| 2419 | 2420 | None => not_supported!("non evaluatable array len in patching addresses"), |
| 2420 | 2421 | }; |
| 2421 | let size = self.size_of_sized( | |
| 2422 | &convert_ty_for_result(interner, inner), | |
| 2423 | locals, | |
| 2424 | "inner of array", | |
| 2425 | )?; | |
| 2422 | let size = self.size_of_sized(inner, locals, "inner of array")?; | |
| 2426 | 2423 | for i in 0..len { |
| 2427 | 2424 | self.patch_addresses( |
| 2428 | 2425 | patch_map, |
| ... | ... | @@ -2465,29 +2462,22 @@ impl<'db> Evaluator<'db> { |
| 2465 | 2462 | &mut self, |
| 2466 | 2463 | bytes: Interval, |
| 2467 | 2464 | destination: Interval, |
| 2468 | args: &[IntervalAndTy], | |
| 2469 | locals: &Locals, | |
| 2470 | target_bb: Option<BasicBlockId>, | |
| 2465 | args: &[IntervalAndTy<'db>], | |
| 2466 | locals: &Locals<'db>, | |
| 2467 | target_bb: Option<BasicBlockId<'db>>, | |
| 2471 | 2468 | span: MirSpan, |
| 2472 | ) -> Result<Option<StackFrame>> { | |
| 2469 | ) -> Result<'db, Option<StackFrame<'db>>> { | |
| 2473 | 2470 | let id = from_bytes!(usize, bytes.get(self)?); |
| 2474 | 2471 | let next_ty = self.vtable_map.ty(id)?; |
| 2475 | let interner = DbInterner::new_with(self.db, None, None); | |
| 2476 | 2472 | use rustc_type_ir::TyKind; |
| 2477 | 2473 | match next_ty.kind() { |
| 2478 | TyKind::FnDef(def, generic_args) => self.exec_fn_def( | |
| 2479 | def.0, | |
| 2480 | &convert_args_for_result(interner, generic_args.as_slice()), | |
| 2481 | destination, | |
| 2482 | args, | |
| 2483 | locals, | |
| 2484 | target_bb, | |
| 2485 | span, | |
| 2486 | ), | |
| 2474 | TyKind::FnDef(def, generic_args) => { | |
| 2475 | self.exec_fn_def(def.0, generic_args, destination, args, locals, target_bb, span) | |
| 2476 | } | |
| 2487 | 2477 | TyKind::Closure(id, generic_args) => self.exec_closure( |
| 2488 | id.0.into(), | |
| 2478 | id.0, | |
| 2489 | 2479 | bytes.slice(0..0), |
| 2490 | &convert_args_for_result(interner, generic_args.as_slice()), | |
| 2480 | generic_args, | |
| 2491 | 2481 | destination, |
| 2492 | 2482 | args, |
| 2493 | 2483 | locals, |
| ... | ... | @@ -2499,21 +2489,17 @@ impl<'db> Evaluator<'db> { |
| 2499 | 2489 | |
| 2500 | 2490 | fn exec_closure( |
| 2501 | 2491 | &mut self, |
| 2502 | closure: ClosureId, | |
| 2492 | closure: InternedClosureId, | |
| 2503 | 2493 | closure_data: Interval, |
| 2504 | generic_args: &Substitution, | |
| 2494 | generic_args: GenericArgs<'db>, | |
| 2505 | 2495 | destination: Interval, |
| 2506 | args: &[IntervalAndTy], | |
| 2507 | locals: &Locals, | |
| 2496 | args: &[IntervalAndTy<'db>], | |
| 2497 | locals: &Locals<'db>, | |
| 2508 | 2498 | span: MirSpan, |
| 2509 | ) -> Result<Option<StackFrame>> { | |
| 2499 | ) -> Result<'db, Option<StackFrame<'db>>> { | |
| 2510 | 2500 | let mir_body = self |
| 2511 | 2501 | .db |
| 2512 | .monomorphized_mir_body_for_closure( | |
| 2513 | closure.into(), | |
| 2514 | generic_args.clone(), | |
| 2515 | self.trait_env.clone(), | |
| 2516 | ) | |
| 2502 | .monomorphized_mir_body_for_closure(closure, generic_args, self.trait_env.clone()) | |
| 2517 | 2503 | .map_err(|it| MirEvalError::MirLowerErrorForClosure(closure, it))?; |
| 2518 | 2504 | let closure_data = if mir_body.locals[mir_body.param_locals[0]].ty.as_reference().is_some() |
| 2519 | 2505 | { |
| ... | ... | @@ -2523,7 +2509,7 @@ impl<'db> Evaluator<'db> { |
| 2523 | 2509 | }; |
| 2524 | 2510 | let arg_bytes = iter::once(Ok(closure_data)) |
| 2525 | 2511 | .chain(args.iter().map(|it| Ok(it.get(self)?.to_owned()))) |
| 2526 | .collect::<Result<Vec<_>>>()?; | |
| 2512 | .collect::<Result<'db, Vec<_>>>()?; | |
| 2527 | 2513 | let interval = self |
| 2528 | 2514 | .interpret_mir(mir_body, arg_bytes.into_iter().map(IntervalOrOwned::Owned)) |
| 2529 | 2515 | .map_err(|e| { |
| ... | ... | @@ -2539,14 +2525,13 @@ impl<'db> Evaluator<'db> { |
| 2539 | 2525 | fn exec_fn_def( |
| 2540 | 2526 | &mut self, |
| 2541 | 2527 | def: CallableDefId, |
| 2542 | generic_args: &Substitution, | |
| 2528 | generic_args: GenericArgs<'db>, | |
| 2543 | 2529 | destination: Interval, |
| 2544 | args: &[IntervalAndTy], | |
| 2545 | locals: &Locals, | |
| 2546 | target_bb: Option<BasicBlockId>, | |
| 2530 | args: &[IntervalAndTy<'db>], | |
| 2531 | locals: &Locals<'db>, | |
| 2532 | target_bb: Option<BasicBlockId<'db>>, | |
| 2547 | 2533 | span: MirSpan, |
| 2548 | ) -> Result<Option<StackFrame>> { | |
| 2549 | let generic_args = generic_args.clone(); | |
| 2534 | ) -> Result<'db, Option<StackFrame<'db>>> { | |
| 2550 | 2535 | match def { |
| 2551 | 2536 | CallableDefId::FunctionId(def) => { |
| 2552 | 2537 | if self.detect_fn_trait(def).is_some() { |
| ... | ... | @@ -2600,22 +2585,22 @@ impl<'db> Evaluator<'db> { |
| 2600 | 2585 | fn get_mir_or_dyn_index( |
| 2601 | 2586 | &self, |
| 2602 | 2587 | def: FunctionId, |
| 2603 | generic_args: Substitution, | |
| 2604 | locals: &Locals, | |
| 2588 | generic_args: GenericArgs<'db>, | |
| 2589 | locals: &Locals<'db>, | |
| 2605 | 2590 | span: MirSpan, |
| 2606 | ) -> Result<MirOrDynIndex> { | |
| 2591 | ) -> Result<'db, MirOrDynIndex<'db>> { | |
| 2607 | 2592 | let pair = (def, generic_args); |
| 2608 | 2593 | if let Some(r) = self.mir_or_dyn_index_cache.borrow().get(&pair) { |
| 2609 | 2594 | return Ok(r.clone()); |
| 2610 | 2595 | } |
| 2611 | 2596 | let (def, generic_args) = pair; |
| 2612 | 2597 | let r = if let Some(self_ty_idx) = |
| 2613 | is_dyn_method(self.db, self.trait_env.clone(), def, generic_args.clone()) | |
| 2598 | is_dyn_method(self.interner(), self.trait_env.clone(), def, generic_args) | |
| 2614 | 2599 | { |
| 2615 | 2600 | MirOrDynIndex::Dyn(self_ty_idx) |
| 2616 | 2601 | } else { |
| 2617 | 2602 | let (imp, generic_args) = |
| 2618 | self.db.lookup_impl_method(self.trait_env.clone(), def, generic_args.clone()); | |
| 2603 | self.db.lookup_impl_method(self.trait_env.clone(), def, generic_args); | |
| 2619 | 2604 | |
| 2620 | 2605 | let mir_body = self |
| 2621 | 2606 | .db |
| ... | ... | @@ -2635,18 +2620,17 @@ impl<'db> Evaluator<'db> { |
| 2635 | 2620 | fn exec_fn_with_args( |
| 2636 | 2621 | &mut self, |
| 2637 | 2622 | mut def: FunctionId, |
| 2638 | args: &[IntervalAndTy], | |
| 2639 | generic_args: Substitution, | |
| 2640 | locals: &Locals, | |
| 2623 | args: &[IntervalAndTy<'db>], | |
| 2624 | generic_args: GenericArgs<'db>, | |
| 2625 | locals: &Locals<'db>, | |
| 2641 | 2626 | destination: Interval, |
| 2642 | target_bb: Option<BasicBlockId>, | |
| 2627 | target_bb: Option<BasicBlockId<'db>>, | |
| 2643 | 2628 | span: MirSpan, |
| 2644 | ) -> Result<Option<StackFrame>> { | |
| 2645 | let interner = DbInterner::new_with(self.db, None, None); | |
| 2629 | ) -> Result<'db, Option<StackFrame<'db>>> { | |
| 2646 | 2630 | if self.detect_and_exec_special_function( |
| 2647 | 2631 | def, |
| 2648 | 2632 | args, |
| 2649 | &generic_args, | |
| 2633 | generic_args, | |
| 2650 | 2634 | locals, |
| 2651 | 2635 | destination, |
| 2652 | 2636 | span, |
| ... | ... | @@ -2657,7 +2641,7 @@ impl<'db> Evaluator<'db> { |
| 2657 | 2641 | def = redirect_def; |
| 2658 | 2642 | } |
| 2659 | 2643 | let arg_bytes = args.iter().map(|it| IntervalOrOwned::Borrowed(it.interval)); |
| 2660 | match self.get_mir_or_dyn_index(def, generic_args.clone(), locals, span)? { | |
| 2644 | match self.get_mir_or_dyn_index(def, generic_args, locals, span)? { | |
| 2661 | 2645 | MirOrDynIndex::Dyn(self_ty_idx) => { |
| 2662 | 2646 | // In the layout of current possible receiver, which at the moment of writing this code is one of |
| 2663 | 2647 | // `&T`, `&mut T`, `Box<T>`, `Rc<T>`, `Arc<T>`, and `Pin<P>` where `P` is one of possible receivers, |
| ... | ... | @@ -2669,18 +2653,16 @@ impl<'db> Evaluator<'db> { |
| 2669 | 2653 | .vtable_map |
| 2670 | 2654 | .ty_of_bytes(&first_arg[self.ptr_size()..self.ptr_size() * 2])?; |
| 2671 | 2655 | let mut args_for_target = args.to_vec(); |
| 2672 | let ty = convert_ty_for_result(interner, ty); | |
| 2673 | 2656 | args_for_target[0] = IntervalAndTy { |
| 2674 | 2657 | interval: args_for_target[0].interval.slice(0..self.ptr_size()), |
| 2675 | ty: ty.clone(), | |
| 2658 | ty, | |
| 2676 | 2659 | }; |
| 2677 | let ty = ty.clone().cast(Interner); | |
| 2678 | let generics_for_target = Substitution::from_iter( | |
| 2679 | Interner, | |
| 2660 | let generics_for_target = GenericArgs::new_from_iter( | |
| 2661 | self.interner(), | |
| 2680 | 2662 | generic_args |
| 2681 | .iter(Interner) | |
| 2663 | .iter() | |
| 2682 | 2664 | .enumerate() |
| 2683 | .map(|(i, it)| if i == self_ty_idx { &ty } else { it }), | |
| 2665 | .map(|(i, it)| if i == self_ty_idx { ty.into() } else { it }), | |
| 2684 | 2666 | ); |
| 2685 | 2667 | self.exec_fn_with_args( |
| 2686 | 2668 | def, |
| ... | ... | @@ -2706,14 +2688,14 @@ impl<'db> Evaluator<'db> { |
| 2706 | 2688 | |
| 2707 | 2689 | fn exec_looked_up_function( |
| 2708 | 2690 | &mut self, |
| 2709 | mir_body: Arc<MirBody>, | |
| 2710 | locals: &Locals, | |
| 2691 | mir_body: Arc<MirBody<'db>>, | |
| 2692 | locals: &Locals<'db>, | |
| 2711 | 2693 | def: FunctionId, |
| 2712 | 2694 | arg_bytes: impl Iterator<Item = IntervalOrOwned>, |
| 2713 | 2695 | span: MirSpan, |
| 2714 | 2696 | destination: Interval, |
| 2715 | target_bb: Option<BasicBlockId>, | |
| 2716 | ) -> Result<Option<StackFrame>> { | |
| 2697 | target_bb: Option<BasicBlockId<'db>>, | |
| 2698 | ) -> Result<'db, Option<StackFrame<'db>>> { | |
| 2717 | 2699 | Ok(if let Some(target_bb) = target_bb { |
| 2718 | 2700 | let (mut locals, prev_stack_ptr) = |
| 2719 | 2701 | self.create_locals_for_body(&mir_body, Some(destination))?; |
| ... | ... | @@ -2735,47 +2717,40 @@ impl<'db> Evaluator<'db> { |
| 2735 | 2717 | fn exec_fn_trait( |
| 2736 | 2718 | &mut self, |
| 2737 | 2719 | def: FunctionId, |
| 2738 | args: &[IntervalAndTy], | |
| 2739 | generic_args: Substitution, | |
| 2740 | locals: &Locals, | |
| 2720 | args: &[IntervalAndTy<'db>], | |
| 2721 | generic_args: GenericArgs<'db>, | |
| 2722 | locals: &Locals<'db>, | |
| 2741 | 2723 | destination: Interval, |
| 2742 | target_bb: Option<BasicBlockId>, | |
| 2724 | target_bb: Option<BasicBlockId<'db>>, | |
| 2743 | 2725 | span: MirSpan, |
| 2744 | ) -> Result<Option<StackFrame>> { | |
| 2745 | let interner = DbInterner::new_with(self.db, None, None); | |
| 2726 | ) -> Result<'db, Option<StackFrame<'db>>> { | |
| 2746 | 2727 | let func = args |
| 2747 | 2728 | .first() |
| 2748 | 2729 | .ok_or_else(|| MirEvalError::InternalError("fn trait with no arg".into()))?; |
| 2749 | let mut func_ty = func.ty.clone(); | |
| 2730 | let mut func_ty = func.ty; | |
| 2750 | 2731 | let mut func_data = func.interval; |
| 2751 | while let TyKind::Ref(_, _, z) = func_ty.kind(Interner) { | |
| 2752 | func_ty = z.clone(); | |
| 2753 | if matches!(func_ty.kind(Interner), TyKind::Dyn(_)) { | |
| 2732 | while let TyKind::Ref(_, z, _) = func_ty.kind() { | |
| 2733 | func_ty = z; | |
| 2734 | if matches!(func_ty.kind(), TyKind::Dynamic(..)) { | |
| 2754 | 2735 | let id = |
| 2755 | 2736 | from_bytes!(usize, &func_data.get(self)?[self.ptr_size()..self.ptr_size() * 2]); |
| 2756 | 2737 | func_data = func_data.slice(0..self.ptr_size()); |
| 2757 | func_ty = convert_ty_for_result(interner, self.vtable_map.ty(id)?); | |
| 2738 | func_ty = self.vtable_map.ty(id)?; | |
| 2758 | 2739 | } |
| 2759 | let size = self.size_of_sized(&func_ty, locals, "self type of fn trait")?; | |
| 2740 | let size = self.size_of_sized(func_ty, locals, "self type of fn trait")?; | |
| 2760 | 2741 | func_data = Interval { addr: Address::from_bytes(func_data.get(self)?)?, size }; |
| 2761 | 2742 | } |
| 2762 | match &func_ty.kind(Interner) { | |
| 2763 | TyKind::FnDef(def, subst) => self.exec_fn_def( | |
| 2764 | CallableDefId::from_chalk(self.db, *def), | |
| 2765 | subst, | |
| 2766 | destination, | |
| 2767 | &args[1..], | |
| 2768 | locals, | |
| 2769 | target_bb, | |
| 2770 | span, | |
| 2771 | ), | |
| 2772 | TyKind::Function(_) => { | |
| 2743 | match func_ty.kind() { | |
| 2744 | TyKind::FnDef(def, subst) => { | |
| 2745 | self.exec_fn_def(def.0, subst, destination, &args[1..], locals, target_bb, span) | |
| 2746 | } | |
| 2747 | TyKind::FnPtr(..) => { | |
| 2773 | 2748 | self.exec_fn_pointer(func_data, destination, &args[1..], locals, target_bb, span) |
| 2774 | 2749 | } |
| 2775 | 2750 | TyKind::Closure(closure, subst) => self.exec_closure( |
| 2776 | *closure, | |
| 2751 | closure.0, | |
| 2777 | 2752 | func_data, |
| 2778 | &ClosureSubst(subst).parent_subst(self.db), | |
| 2753 | subst.split_closure_args_untupled().parent_args, | |
| 2779 | 2754 | destination, |
| 2780 | 2755 | &args[1..], |
| 2781 | 2756 | locals, |
| ... | ... | @@ -2786,12 +2761,8 @@ impl<'db> Evaluator<'db> { |
| 2786 | 2761 | let arg0 = func; |
| 2787 | 2762 | let args = &args[1..]; |
| 2788 | 2763 | let arg1 = { |
| 2789 | let ty = TyKind::Tuple( | |
| 2790 | args.len(), | |
| 2791 | Substitution::from_iter(Interner, args.iter().map(|it| it.ty.clone())), | |
| 2792 | ) | |
| 2793 | .intern(Interner); | |
| 2794 | let layout = self.layout(ty.to_nextsolver(interner))?; | |
| 2764 | let ty = Ty::new_tup_from_iter(self.interner(), args.iter().map(|it| it.ty)); | |
| 2765 | let layout = self.layout(ty)?; | |
| 2795 | 2766 | let result = self.construct_with_layout( |
| 2796 | 2767 | layout.size.bytes_usize(), |
| 2797 | 2768 | &layout, |
| ... | ... | @@ -2817,7 +2788,7 @@ impl<'db> Evaluator<'db> { |
| 2817 | 2788 | } |
| 2818 | 2789 | } |
| 2819 | 2790 | |
| 2820 | fn eval_static(&mut self, st: StaticId, locals: &Locals) -> Result<Address> { | |
| 2791 | fn eval_static(&mut self, st: StaticId, locals: &Locals<'db>) -> Result<'db, Address> { | |
| 2821 | 2792 | if let Some(o) = self.static_locations.get(&st) { |
| 2822 | 2793 | return Ok(*o); |
| 2823 | 2794 | }; |
| ... | ... | @@ -2826,9 +2797,9 @@ impl<'db> Evaluator<'db> { |
| 2826 | 2797 | let konst = self.db.const_eval_static(st).map_err(|e| { |
| 2827 | 2798 | MirEvalError::ConstEvalError(static_data.name.as_str().to_owned(), Box::new(e)) |
| 2828 | 2799 | })?; |
| 2829 | self.allocate_const_in_heap(locals, &konst)? | |
| 2800 | self.allocate_const_in_heap(locals, konst)? | |
| 2830 | 2801 | } else { |
| 2831 | let ty = &self.db.infer(st.into())[self.db.body(st.into()).body_expr]; | |
| 2802 | let ty = self.db.infer(st.into())[self.db.body(st.into()).body_expr]; | |
| 2832 | 2803 | let Some((size, align)) = self.size_align_of(ty, locals)? else { |
| 2833 | 2804 | not_supported!("unsized extern static"); |
| 2834 | 2805 | }; |
| ... | ... | @@ -2841,7 +2812,7 @@ impl<'db> Evaluator<'db> { |
| 2841 | 2812 | Ok(addr) |
| 2842 | 2813 | } |
| 2843 | 2814 | |
| 2844 | fn const_eval_discriminant(&self, variant: EnumVariantId) -> Result<i128> { | |
| 2815 | fn const_eval_discriminant(&self, variant: EnumVariantId) -> Result<'db, i128> { | |
| 2845 | 2816 | let r = self.db.const_eval_discriminant(variant); |
| 2846 | 2817 | match r { |
| 2847 | 2818 | Ok(r) => Ok(r), |
| ... | ... | @@ -2863,7 +2834,12 @@ impl<'db> Evaluator<'db> { |
| 2863 | 2834 | } |
| 2864 | 2835 | } |
| 2865 | 2836 | |
| 2866 | fn drop_place(&mut self, place: &Place, locals: &mut Locals, span: MirSpan) -> Result<()> { | |
| 2837 | fn drop_place( | |
| 2838 | &mut self, | |
| 2839 | place: &Place<'db>, | |
| 2840 | locals: &mut Locals<'db>, | |
| 2841 | span: MirSpan, | |
| 2842 | ) -> Result<'db, ()> { | |
| 2867 | 2843 | let (addr, ty, metadata) = self.place_addr_and_ty_and_metadata(place, locals)?; |
| 2868 | 2844 | if !locals.drop_flags.remove_place(place, &locals.body.projection_store) { |
| 2869 | 2845 | return Ok(()); |
| ... | ... | @@ -2877,12 +2853,12 @@ impl<'db> Evaluator<'db> { |
| 2877 | 2853 | |
| 2878 | 2854 | fn run_drop_glue_deep( |
| 2879 | 2855 | &mut self, |
| 2880 | ty: Ty, | |
| 2881 | locals: &Locals, | |
| 2856 | ty: Ty<'db>, | |
| 2857 | locals: &Locals<'db>, | |
| 2882 | 2858 | addr: Address, |
| 2883 | 2859 | _metadata: &[u8], |
| 2884 | 2860 | span: MirSpan, |
| 2885 | ) -> Result<()> { | |
| 2861 | ) -> Result<'db, ()> { | |
| 2886 | 2862 | let Some(drop_fn) = (|| { |
| 2887 | 2863 | let drop_trait = LangItem::Drop.resolve_trait(self.db, self.crate_id)?; |
| 2888 | 2864 | drop_trait.trait_items(self.db).method_by_name(&Name::new_symbol_root(sym::drop)) |
| ... | ... | @@ -2892,7 +2868,7 @@ impl<'db> Evaluator<'db> { |
| 2892 | 2868 | return Ok(()); |
| 2893 | 2869 | }; |
| 2894 | 2870 | |
| 2895 | let generic_args = Substitution::from1(Interner, ty.clone()); | |
| 2871 | let generic_args = GenericArgs::new_from_iter(self.interner(), [ty.into()]); | |
| 2896 | 2872 | if let Ok(MirOrDynIndex::Mir(body)) = |
| 2897 | 2873 | self.get_mir_or_dyn_index(drop_fn, generic_args, locals, span) |
| 2898 | 2874 | { |
| ... | ... | @@ -2906,26 +2882,27 @@ impl<'db> Evaluator<'db> { |
| 2906 | 2882 | None, |
| 2907 | 2883 | )?; |
| 2908 | 2884 | } |
| 2909 | match ty.kind(Interner) { | |
| 2910 | TyKind::Adt(id, subst) => { | |
| 2911 | match id.0 { | |
| 2885 | match ty.kind() { | |
| 2886 | TyKind::Adt(adt_def, subst) => { | |
| 2887 | let id = adt_def.def_id().0; | |
| 2888 | match id { | |
| 2912 | 2889 | AdtId::StructId(s) => { |
| 2913 | 2890 | let data = self.db.struct_signature(s); |
| 2914 | 2891 | if data.flags.contains(StructFlags::IS_MANUALLY_DROP) { |
| 2915 | 2892 | return Ok(()); |
| 2916 | 2893 | } |
| 2917 | let layout = self.layout_adt(id.0, subst.clone())?; | |
| 2894 | let layout = self.layout_adt(id, subst)?; | |
| 2918 | 2895 | let variant_fields = s.fields(self.db); |
| 2919 | 2896 | match variant_fields.shape { |
| 2920 | 2897 | FieldsShape::Record | FieldsShape::Tuple => { |
| 2921 | let field_types = self.db.field_types(s.into()); | |
| 2898 | let field_types = self.db.field_types_ns(s.into()); | |
| 2922 | 2899 | for (field, _) in variant_fields.fields().iter() { |
| 2923 | 2900 | let offset = layout |
| 2924 | 2901 | .fields |
| 2925 | 2902 | .offset(u32::from(field.into_raw()) as usize) |
| 2926 | 2903 | .bytes_usize(); |
| 2927 | 2904 | let addr = addr.offset(offset); |
| 2928 | let ty = field_types[field].clone().substitute(Interner, subst); | |
| 2905 | let ty = field_types[field].instantiate(self.interner(), subst); | |
| 2929 | 2906 | self.run_drop_glue_deep(ty, locals, addr, &[], span)?; |
| 2930 | 2907 | } |
| 2931 | 2908 | } |
| ... | ... | @@ -2936,49 +2913,55 @@ impl<'db> Evaluator<'db> { |
| 2936 | 2913 | AdtId::EnumId(_) => (), |
| 2937 | 2914 | } |
| 2938 | 2915 | } |
| 2939 | TyKind::AssociatedType(_, _) | |
| 2940 | | TyKind::Scalar(_) | |
| 2941 | | TyKind::Tuple(_, _) | |
| 2916 | TyKind::Bool | |
| 2917 | | TyKind::Char | |
| 2918 | | TyKind::Int(_) | |
| 2919 | | TyKind::Uint(_) | |
| 2920 | | TyKind::Float(_) | |
| 2921 | | TyKind::Tuple(_) | |
| 2942 | 2922 | | TyKind::Array(_, _) |
| 2943 | 2923 | | TyKind::Slice(_) |
| 2944 | | TyKind::Raw(_, _) | |
| 2924 | | TyKind::RawPtr(_, _) | |
| 2945 | 2925 | | TyKind::Ref(_, _, _) |
| 2946 | | TyKind::OpaqueType(_, _) | |
| 2926 | | TyKind::Alias(..) | |
| 2947 | 2927 | | TyKind::FnDef(_, _) |
| 2948 | 2928 | | TyKind::Str |
| 2949 | 2929 | | TyKind::Never |
| 2950 | 2930 | | TyKind::Closure(_, _) |
| 2951 | 2931 | | TyKind::Coroutine(_, _) |
| 2932 | | TyKind::CoroutineClosure(..) | |
| 2952 | 2933 | | TyKind::CoroutineWitness(_, _) |
| 2953 | 2934 | | TyKind::Foreign(_) |
| 2954 | | TyKind::Error | |
| 2935 | | TyKind::Error(_) | |
| 2936 | | TyKind::Param(_) | |
| 2955 | 2937 | | TyKind::Placeholder(_) |
| 2956 | | TyKind::Dyn(_) | |
| 2957 | | TyKind::Alias(_) | |
| 2958 | | TyKind::Function(_) | |
| 2959 | | TyKind::BoundVar(_) | |
| 2960 | | TyKind::InferenceVar(_, _) => (), | |
| 2938 | | TyKind::Dynamic(..) | |
| 2939 | | TyKind::FnPtr(..) | |
| 2940 | | TyKind::Bound(..) | |
| 2941 | | TyKind::Infer(..) | |
| 2942 | | TyKind::Pat(..) | |
| 2943 | | TyKind::UnsafeBinder(..) => (), | |
| 2961 | 2944 | }; |
| 2962 | 2945 | Ok(()) |
| 2963 | 2946 | } |
| 2964 | 2947 | |
| 2965 | fn write_to_stdout(&mut self, interval: Interval) -> Result<()> { | |
| 2948 | fn write_to_stdout(&mut self, interval: Interval) -> Result<'db, ()> { | |
| 2966 | 2949 | self.stdout.extend(interval.get(self)?.to_vec()); |
| 2967 | 2950 | Ok(()) |
| 2968 | 2951 | } |
| 2969 | 2952 | |
| 2970 | fn write_to_stderr(&mut self, interval: Interval) -> Result<()> { | |
| 2953 | fn write_to_stderr(&mut self, interval: Interval) -> Result<'db, ()> { | |
| 2971 | 2954 | self.stderr.extend(interval.get(self)?.to_vec()); |
| 2972 | 2955 | Ok(()) |
| 2973 | 2956 | } |
| 2974 | 2957 | } |
| 2975 | 2958 | |
| 2976 | pub fn render_const_using_debug_impl( | |
| 2977 | db: &dyn HirDatabase, | |
| 2959 | pub fn render_const_using_debug_impl<'db>( | |
| 2960 | db: &'db dyn HirDatabase, | |
| 2978 | 2961 | owner: DefWithBodyId, |
| 2979 | c: &Const, | |
| 2980 | ) -> Result<String> { | |
| 2981 | let interner = DbInterner::new_with(db, None, None); | |
| 2962 | c: Const<'db>, | |
| 2963 | ty: Ty<'db>, | |
| 2964 | ) -> Result<'db, String> { | |
| 2982 | 2965 | let mut evaluator = Evaluator::new(db, owner, false, None)?; |
| 2983 | 2966 | let locals = &Locals { |
| 2984 | 2967 | ptr: ArenaMap::new(), |
| ... | ... | @@ -3007,12 +2990,11 @@ pub fn render_const_using_debug_impl( |
| 3007 | 2990 | // and its ABI doesn't break yet, we put it in memory manually. |
| 3008 | 2991 | let a2 = evaluator.heap_allocate(evaluator.ptr_size() * 2, evaluator.ptr_size())?; |
| 3009 | 2992 | evaluator.write_memory(a2, &data.addr.to_bytes())?; |
| 3010 | let debug_fmt_fn_ptr = evaluator.vtable_map.id(TyKind::FnDef( | |
| 3011 | CallableDefId::FunctionId(debug_fmt_fn).to_chalk(db), | |
| 3012 | Substitution::from1(Interner, c.data(Interner).ty.clone()), | |
| 3013 | ) | |
| 3014 | .intern(Interner) | |
| 3015 | .to_nextsolver(interner)); | |
| 2993 | let debug_fmt_fn_ptr = evaluator.vtable_map.id(Ty::new_fn_def( | |
| 2994 | evaluator.interner(), | |
| 2995 | CallableDefId::FunctionId(debug_fmt_fn).into(), | |
| 2996 | GenericArgs::new_from_iter(evaluator.interner(), [ty.into()]), | |
| 2997 | )); | |
| 3016 | 2998 | evaluator.write_memory(a2.offset(evaluator.ptr_size()), &debug_fmt_fn_ptr.to_le_bytes())?; |
| 3017 | 2999 | // a3 = ::core::fmt::Arguments::new_v1(a1, a2) |
| 3018 | 3000 | // FIXME: similarly, we should call function here, not directly working with memory. |
src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs+138-184| ... | ... | @@ -3,32 +3,21 @@ |
| 3 | 3 | //! |
| 4 | 4 | use std::cmp::{self, Ordering}; |
| 5 | 5 | |
| 6 | use chalk_ir::TyKind; | |
| 7 | use hir_def::signatures::FunctionSignature; | |
| 8 | use hir_def::{ | |
| 9 | CrateRootModuleId, | |
| 10 | builtin_type::{BuiltinInt, BuiltinUint}, | |
| 11 | resolver::HasResolver, | |
| 12 | }; | |
| 6 | use hir_def::{CrateRootModuleId, resolver::HasResolver, signatures::FunctionSignature}; | |
| 13 | 7 | use hir_expand::name::Name; |
| 14 | 8 | use intern::{Symbol, sym}; |
| 9 | use rustc_type_ir::inherent::{AdtDef, IntoKind, SliceLike, Ty as _}; | |
| 15 | 10 | use stdx::never; |
| 16 | 11 | |
| 17 | use crate::next_solver::mapping::NextSolverToChalk; | |
| 18 | 12 | use crate::{ |
| 19 | DropGlue, | |
| 20 | 13 | display::DisplayTarget, |
| 21 | error_lifetime, | |
| 14 | drop::{DropGlue, has_drop_glue}, | |
| 22 | 15 | mir::eval::{ |
| 23 | Address, AdtId, Arc, BuiltinType, Evaluator, FunctionId, HasModule, HirDisplay, | |
| 24 | InternedClosure, Interner, Interval, IntervalAndTy, IntervalOrOwned, ItemContainerId, | |
| 25 | LangItem, Layout, Locals, Lookup, MirEvalError, MirSpan, Mutability, Result, Substitution, | |
| 26 | Ty, TyBuilder, TyExt, pad16, | |
| 27 | }, | |
| 28 | next_solver::{ | |
| 29 | DbInterner, | |
| 30 | mapping::{ChalkToNextSolver, convert_ty_for_result}, | |
| 16 | Address, AdtId, Arc, Evaluator, FunctionId, GenericArgs, HasModule, HirDisplay, | |
| 17 | InternedClosure, Interval, IntervalAndTy, IntervalOrOwned, ItemContainerId, LangItem, | |
| 18 | Layout, Locals, Lookup, MirEvalError, MirSpan, Mutability, Result, Ty, TyKind, pad16, | |
| 31 | 19 | }, |
| 20 | next_solver::Region, | |
| 32 | 21 | }; |
| 33 | 22 | |
| 34 | 23 | mod simd; |
| ... | ... | @@ -49,16 +38,16 @@ macro_rules! not_supported { |
| 49 | 38 | }; |
| 50 | 39 | } |
| 51 | 40 | |
| 52 | impl Evaluator<'_> { | |
| 41 | impl<'db> Evaluator<'db> { | |
| 53 | 42 | pub(super) fn detect_and_exec_special_function( |
| 54 | 43 | &mut self, |
| 55 | 44 | def: FunctionId, |
| 56 | args: &[IntervalAndTy], | |
| 57 | generic_args: &Substitution, | |
| 58 | locals: &Locals, | |
| 45 | args: &[IntervalAndTy<'db>], | |
| 46 | generic_args: GenericArgs<'db>, | |
| 47 | locals: &Locals<'db>, | |
| 59 | 48 | destination: Interval, |
| 60 | 49 | span: MirSpan, |
| 61 | ) -> Result<bool> { | |
| 50 | ) -> Result<'db, bool> { | |
| 62 | 51 | if self.not_special_fn_cache.borrow().contains(&def) { |
| 63 | 52 | return Ok(false); |
| 64 | 53 | } |
| ... | ... | @@ -118,18 +107,16 @@ impl Evaluator<'_> { |
| 118 | 107 | if let ItemContainerId::TraitId(t) = def.lookup(self.db).container |
| 119 | 108 | && self.db.lang_attr(t.into()) == Some(LangItem::Clone) |
| 120 | 109 | { |
| 121 | let [self_ty] = generic_args.as_slice(Interner) else { | |
| 110 | let [self_ty] = generic_args.as_slice() else { | |
| 122 | 111 | not_supported!("wrong generic arg count for clone"); |
| 123 | 112 | }; |
| 124 | let Some(self_ty) = self_ty.ty(Interner) else { | |
| 113 | let Some(self_ty) = self_ty.ty() else { | |
| 125 | 114 | not_supported!("wrong generic arg kind for clone"); |
| 126 | 115 | }; |
| 127 | 116 | // Clone has special impls for tuples and function pointers |
| 128 | if matches!( | |
| 129 | self_ty.kind(Interner), | |
| 130 | TyKind::Function(_) | TyKind::Tuple(..) | TyKind::Closure(..) | |
| 131 | ) { | |
| 132 | self.exec_clone(def, args, self_ty.clone(), locals, destination, span)?; | |
| 117 | if matches!(self_ty.kind(), TyKind::FnPtr(..) | TyKind::Tuple(..) | TyKind::Closure(..)) | |
| 118 | { | |
| 119 | self.exec_clone(def, args, self_ty, locals, destination, span)?; | |
| 133 | 120 | return Ok(true); |
| 134 | 121 | } |
| 135 | 122 | // Return early to prevent caching clone as non special fn. |
| ... | ... | @@ -142,7 +129,7 @@ impl Evaluator<'_> { |
| 142 | 129 | pub(super) fn detect_and_redirect_special_function( |
| 143 | 130 | &mut self, |
| 144 | 131 | def: FunctionId, |
| 145 | ) -> Result<Option<FunctionId>> { | |
| 132 | ) -> Result<'db, Option<FunctionId>> { | |
| 146 | 133 | // `PanicFmt` is redirected to `ConstPanicFmt` |
| 147 | 134 | if let Some(LangItem::PanicFmt) = self.db.lang_attr(def.into()) { |
| 148 | 135 | let resolver = CrateRootModuleId::from(self.crate_id).resolver(self.db); |
| ... | ... | @@ -161,15 +148,14 @@ impl Evaluator<'_> { |
| 161 | 148 | fn exec_clone( |
| 162 | 149 | &mut self, |
| 163 | 150 | def: FunctionId, |
| 164 | args: &[IntervalAndTy], | |
| 165 | self_ty: Ty, | |
| 166 | locals: &Locals, | |
| 151 | args: &[IntervalAndTy<'db>], | |
| 152 | self_ty: Ty<'db>, | |
| 153 | locals: &Locals<'db>, | |
| 167 | 154 | destination: Interval, |
| 168 | 155 | span: MirSpan, |
| 169 | ) -> Result<()> { | |
| 170 | let interner = DbInterner::new_with(self.db, None, None); | |
| 171 | match self_ty.kind(Interner) { | |
| 172 | TyKind::Function(_) => { | |
| 156 | ) -> Result<'db, ()> { | |
| 157 | match self_ty.kind() { | |
| 158 | TyKind::FnPtr(..) => { | |
| 173 | 159 | let [arg] = args else { |
| 174 | 160 | not_supported!("wrong arg count for clone"); |
| 175 | 161 | }; |
| ... | ... | @@ -182,27 +168,35 @@ impl Evaluator<'_> { |
| 182 | 168 | not_supported!("wrong arg count for clone"); |
| 183 | 169 | }; |
| 184 | 170 | let addr = Address::from_bytes(arg.get(self)?)?; |
| 185 | let InternedClosure(closure_owner, _) = self.db.lookup_intern_closure((*id).into()); | |
| 171 | let InternedClosure(closure_owner, _) = self.db.lookup_intern_closure(id.0); | |
| 186 | 172 | let infer = self.db.infer(closure_owner); |
| 187 | let (captures, _) = infer.closure_info(id); | |
| 188 | let layout = self.layout(self_ty.to_nextsolver(interner))?; | |
| 189 | let ty_iter = captures.iter().map(|c| c.ty(self.db, subst)); | |
| 173 | let (captures, _) = infer.closure_info(id.0); | |
| 174 | let layout = self.layout(self_ty)?; | |
| 175 | let db = self.db; | |
| 176 | let ty_iter = captures.iter().map(|c| c.ty(db, subst)); | |
| 190 | 177 | self.exec_clone_for_fields(ty_iter, layout, addr, def, locals, destination, span)?; |
| 191 | 178 | } |
| 192 | TyKind::Tuple(_, subst) => { | |
| 179 | TyKind::Tuple(subst) => { | |
| 193 | 180 | let [arg] = args else { |
| 194 | 181 | not_supported!("wrong arg count for clone"); |
| 195 | 182 | }; |
| 196 | 183 | let addr = Address::from_bytes(arg.get(self)?)?; |
| 197 | let layout = self.layout(self_ty.to_nextsolver(interner))?; | |
| 198 | let ty_iter = subst.iter(Interner).map(|ga| ga.assert_ty_ref(Interner).clone()); | |
| 199 | self.exec_clone_for_fields(ty_iter, layout, addr, def, locals, destination, span)?; | |
| 184 | let layout = self.layout(self_ty)?; | |
| 185 | self.exec_clone_for_fields( | |
| 186 | subst.iter(), | |
| 187 | layout, | |
| 188 | addr, | |
| 189 | def, | |
| 190 | locals, | |
| 191 | destination, | |
| 192 | span, | |
| 193 | )?; | |
| 200 | 194 | } |
| 201 | 195 | _ => { |
| 202 | 196 | self.exec_fn_with_args( |
| 203 | 197 | def, |
| 204 | 198 | args, |
| 205 | Substitution::from1(Interner, self_ty), | |
| 199 | GenericArgs::new_from_iter(self.interner(), [self_ty.into()]), | |
| 206 | 200 | locals, |
| 207 | 201 | destination, |
| 208 | 202 | None, |
| ... | ... | @@ -215,21 +209,25 @@ impl Evaluator<'_> { |
| 215 | 209 | |
| 216 | 210 | fn exec_clone_for_fields( |
| 217 | 211 | &mut self, |
| 218 | ty_iter: impl Iterator<Item = Ty>, | |
| 212 | ty_iter: impl Iterator<Item = Ty<'db>>, | |
| 219 | 213 | layout: Arc<Layout>, |
| 220 | 214 | addr: Address, |
| 221 | 215 | def: FunctionId, |
| 222 | locals: &Locals, | |
| 216 | locals: &Locals<'db>, | |
| 223 | 217 | destination: Interval, |
| 224 | 218 | span: MirSpan, |
| 225 | ) -> Result<()> { | |
| 226 | let interner = DbInterner::new_with(self.db, None, None); | |
| 219 | ) -> Result<'db, ()> { | |
| 227 | 220 | for (i, ty) in ty_iter.enumerate() { |
| 228 | let size = self.layout(ty.to_nextsolver(interner))?.size.bytes_usize(); | |
| 221 | let size = self.layout(ty)?.size.bytes_usize(); | |
| 229 | 222 | let tmp = self.heap_allocate(self.ptr_size(), self.ptr_size())?; |
| 230 | 223 | let arg = IntervalAndTy { |
| 231 | 224 | interval: Interval { addr: tmp, size: self.ptr_size() }, |
| 232 | ty: TyKind::Ref(Mutability::Not, error_lifetime(), ty.clone()).intern(Interner), | |
| 225 | ty: Ty::new_ref( | |
| 226 | self.interner(), | |
| 227 | Region::error(self.interner()), | |
| 228 | ty, | |
| 229 | Mutability::Not, | |
| 230 | ), | |
| 233 | 231 | }; |
| 234 | 232 | let offset = layout.fields.offset(i).bytes_usize(); |
| 235 | 233 | self.write_memory(tmp, &addr.offset(offset).to_bytes())?; |
| ... | ... | @@ -248,9 +246,9 @@ impl Evaluator<'_> { |
| 248 | 246 | fn exec_alloc_fn( |
| 249 | 247 | &mut self, |
| 250 | 248 | alloc_fn: &Symbol, |
| 251 | args: &[IntervalAndTy], | |
| 249 | args: &[IntervalAndTy<'db>], | |
| 252 | 250 | destination: Interval, |
| 253 | ) -> Result<()> { | |
| 251 | ) -> Result<'db, ()> { | |
| 254 | 252 | match alloc_fn { |
| 255 | 253 | _ if *alloc_fn == sym::rustc_allocator_zeroed || *alloc_fn == sym::rustc_allocator => { |
| 256 | 254 | let [size, align] = args else { |
| ... | ... | @@ -310,11 +308,11 @@ impl Evaluator<'_> { |
| 310 | 308 | fn exec_lang_item( |
| 311 | 309 | &mut self, |
| 312 | 310 | it: LangItem, |
| 313 | generic_args: &Substitution, | |
| 314 | args: &[IntervalAndTy], | |
| 315 | locals: &Locals, | |
| 311 | generic_args: GenericArgs<'db>, | |
| 312 | args: &[IntervalAndTy<'db>], | |
| 313 | locals: &Locals<'db>, | |
| 316 | 314 | span: MirSpan, |
| 317 | ) -> Result<Vec<u8>> { | |
| 315 | ) -> Result<'db, Vec<u8>> { | |
| 318 | 316 | use LangItem::*; |
| 319 | 317 | let mut args = args.iter(); |
| 320 | 318 | match it { |
| ... | ... | @@ -325,7 +323,7 @@ impl Evaluator<'_> { |
| 325 | 323 | "argument of BeginPanic is not provided".into(), |
| 326 | 324 | ))? |
| 327 | 325 | .clone(); |
| 328 | while let TyKind::Ref(_, _, ty) = arg.ty.kind(Interner) { | |
| 326 | while let TyKind::Ref(_, ty, _) = arg.ty.kind() { | |
| 329 | 327 | if ty.is_str() { |
| 330 | 328 | let (pointee, metadata) = arg.interval.get(self)?.split_at(self.ptr_size()); |
| 331 | 329 | let len = from_bytes!(usize, metadata); |
| ... | ... | @@ -344,13 +342,10 @@ impl Evaluator<'_> { |
| 344 | 342 | let pointee = arg.interval.get(self)?; |
| 345 | 343 | arg = IntervalAndTy { |
| 346 | 344 | interval: Interval::new(Address::from_bytes(pointee)?, size), |
| 347 | ty: ty.clone(), | |
| 345 | ty, | |
| 348 | 346 | }; |
| 349 | 347 | } |
| 350 | Err(MirEvalError::Panic(format!( | |
| 351 | "unknown-panic-payload: {:?}", | |
| 352 | arg.ty.kind(Interner) | |
| 353 | ))) | |
| 348 | Err(MirEvalError::Panic(format!("unknown-panic-payload: {:?}", arg.ty.kind()))) | |
| 354 | 349 | } |
| 355 | 350 | SliceLen => { |
| 356 | 351 | let arg = args.next().ok_or(MirEvalError::InternalError( |
| ... | ... | @@ -361,18 +356,17 @@ impl Evaluator<'_> { |
| 361 | 356 | Ok(arg[ptr_size..].into()) |
| 362 | 357 | } |
| 363 | 358 | DropInPlace => { |
| 364 | let ty = | |
| 365 | generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)).ok_or( | |
| 366 | MirEvalError::InternalError( | |
| 367 | "generic argument of drop_in_place is not provided".into(), | |
| 368 | ), | |
| 369 | )?; | |
| 359 | let ty = generic_args.as_slice().first().and_then(|it| it.ty()).ok_or( | |
| 360 | MirEvalError::InternalError( | |
| 361 | "generic argument of drop_in_place is not provided".into(), | |
| 362 | ), | |
| 363 | )?; | |
| 370 | 364 | let arg = args.next().ok_or(MirEvalError::InternalError( |
| 371 | 365 | "argument of drop_in_place is not provided".into(), |
| 372 | 366 | ))?; |
| 373 | 367 | let arg = arg.interval.get(self)?.to_owned(); |
| 374 | 368 | self.run_drop_glue_deep( |
| 375 | ty.clone(), | |
| 369 | ty, | |
| 376 | 370 | locals, |
| 377 | 371 | Address::from_bytes(&arg[0..self.ptr_size()])?, |
| 378 | 372 | &arg[self.ptr_size()..], |
| ... | ... | @@ -387,11 +381,11 @@ impl Evaluator<'_> { |
| 387 | 381 | fn exec_syscall( |
| 388 | 382 | &mut self, |
| 389 | 383 | id: i64, |
| 390 | args: &[IntervalAndTy], | |
| 384 | args: &[IntervalAndTy<'db>], | |
| 391 | 385 | destination: Interval, |
| 392 | _locals: &Locals, | |
| 386 | _locals: &Locals<'db>, | |
| 393 | 387 | _span: MirSpan, |
| 394 | ) -> Result<()> { | |
| 388 | ) -> Result<'db, ()> { | |
| 395 | 389 | match id { |
| 396 | 390 | 318 => { |
| 397 | 391 | // SYS_getrandom |
| ... | ... | @@ -417,12 +411,12 @@ impl Evaluator<'_> { |
| 417 | 411 | fn exec_extern_c( |
| 418 | 412 | &mut self, |
| 419 | 413 | as_str: &str, |
| 420 | args: &[IntervalAndTy], | |
| 421 | _generic_args: &Substitution, | |
| 414 | args: &[IntervalAndTy<'db>], | |
| 415 | _generic_args: GenericArgs<'db>, | |
| 422 | 416 | destination: Interval, |
| 423 | locals: &Locals, | |
| 417 | locals: &Locals<'db>, | |
| 424 | 418 | span: MirSpan, |
| 425 | ) -> Result<()> { | |
| 419 | ) -> Result<'db, ()> { | |
| 426 | 420 | match as_str { |
| 427 | 421 | "memcmp" => { |
| 428 | 422 | let [ptr1, ptr2, size] = args else { |
| ... | ... | @@ -583,14 +577,13 @@ impl Evaluator<'_> { |
| 583 | 577 | fn exec_intrinsic( |
| 584 | 578 | &mut self, |
| 585 | 579 | name: &str, |
| 586 | args: &[IntervalAndTy], | |
| 587 | generic_args: &Substitution, | |
| 580 | args: &[IntervalAndTy<'db>], | |
| 581 | generic_args: GenericArgs<'db>, | |
| 588 | 582 | destination: Interval, |
| 589 | locals: &Locals, | |
| 583 | locals: &Locals<'db>, | |
| 590 | 584 | span: MirSpan, |
| 591 | 585 | needs_override: bool, |
| 592 | ) -> Result<bool> { | |
| 593 | let interner = DbInterner::new_with(self.db, None, None); | |
| 586 | ) -> Result<'db, bool> { | |
| 594 | 587 | if let Some(name) = name.strip_prefix("atomic_") { |
| 595 | 588 | return self |
| 596 | 589 | .exec_atomic_intrinsic(name, args, generic_args, destination, locals, span) |
| ... | ... | @@ -748,9 +741,7 @@ impl Evaluator<'_> { |
| 748 | 741 | } |
| 749 | 742 | match name { |
| 750 | 743 | "size_of" => { |
| 751 | let Some(ty) = | |
| 752 | generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) | |
| 753 | else { | |
| 744 | let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else { | |
| 754 | 745 | return Err(MirEvalError::InternalError( |
| 755 | 746 | "size_of generic arg is not provided".into(), |
| 756 | 747 | )); |
| ... | ... | @@ -761,20 +752,16 @@ impl Evaluator<'_> { |
| 761 | 752 | // FIXME: `min_align_of` was renamed to `align_of` in Rust 1.89 |
| 762 | 753 | // (https://github.com/rust-lang/rust/pull/142410) |
| 763 | 754 | "min_align_of" | "align_of" => { |
| 764 | let Some(ty) = | |
| 765 | generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) | |
| 766 | else { | |
| 755 | let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else { | |
| 767 | 756 | return Err(MirEvalError::InternalError( |
| 768 | 757 | "align_of generic arg is not provided".into(), |
| 769 | 758 | )); |
| 770 | 759 | }; |
| 771 | let align = self.layout(ty.to_nextsolver(interner))?.align.bytes(); | |
| 760 | let align = self.layout(ty)?.align.bytes(); | |
| 772 | 761 | destination.write_from_bytes(self, &align.to_le_bytes()[0..destination.size]) |
| 773 | 762 | } |
| 774 | 763 | "size_of_val" => { |
| 775 | let Some(ty) = | |
| 776 | generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) | |
| 777 | else { | |
| 764 | let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else { | |
| 778 | 765 | return Err(MirEvalError::InternalError( |
| 779 | 766 | "size_of_val generic arg is not provided".into(), |
| 780 | 767 | )); |
| ... | ... | @@ -795,9 +782,7 @@ impl Evaluator<'_> { |
| 795 | 782 | // FIXME: `min_align_of_val` was renamed to `align_of_val` in Rust 1.89 |
| 796 | 783 | // (https://github.com/rust-lang/rust/pull/142410) |
| 797 | 784 | "min_align_of_val" | "align_of_val" => { |
| 798 | let Some(ty) = | |
| 799 | generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) | |
| 800 | else { | |
| 785 | let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else { | |
| 801 | 786 | return Err(MirEvalError::InternalError( |
| 802 | 787 | "align_of_val generic arg is not provided".into(), |
| 803 | 788 | )); |
| ... | ... | @@ -816,9 +801,7 @@ impl Evaluator<'_> { |
| 816 | 801 | } |
| 817 | 802 | } |
| 818 | 803 | "type_name" => { |
| 819 | let Some(ty) = | |
| 820 | generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) | |
| 821 | else { | |
| 804 | let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else { | |
| 822 | 805 | return Err(MirEvalError::InternalError( |
| 823 | 806 | "type_name generic arg is not provided".into(), |
| 824 | 807 | )); |
| ... | ... | @@ -845,14 +828,12 @@ impl Evaluator<'_> { |
| 845 | 828 | .write_from_bytes(self, &len.to_le_bytes()) |
| 846 | 829 | } |
| 847 | 830 | "needs_drop" => { |
| 848 | let Some(ty) = | |
| 849 | generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) | |
| 850 | else { | |
| 831 | let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else { | |
| 851 | 832 | return Err(MirEvalError::InternalError( |
| 852 | 833 | "size_of generic arg is not provided".into(), |
| 853 | 834 | )); |
| 854 | 835 | }; |
| 855 | let result = match self.db.has_drop_glue(ty.clone(), self.trait_env.clone()) { | |
| 836 | let result = match has_drop_glue(&self.infcx, ty, self.trait_env.clone()) { | |
| 856 | 837 | DropGlue::HasDropGlue => true, |
| 857 | 838 | DropGlue::None => false, |
| 858 | 839 | DropGlue::DependOnParams => { |
| ... | ... | @@ -915,9 +896,7 @@ impl Evaluator<'_> { |
| 915 | 896 | let lhs = i128::from_le_bytes(pad16(lhs.get(self)?, false)); |
| 916 | 897 | let rhs = i128::from_le_bytes(pad16(rhs.get(self)?, false)); |
| 917 | 898 | let ans = lhs.wrapping_sub(rhs); |
| 918 | let Some(ty) = | |
| 919 | generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) | |
| 920 | else { | |
| 899 | let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else { | |
| 921 | 900 | return Err(MirEvalError::InternalError( |
| 922 | 901 | "ptr_offset_from generic arg is not provided".into(), |
| 923 | 902 | )); |
| ... | ... | @@ -1006,13 +985,11 @@ impl Evaluator<'_> { |
| 1006 | 985 | "const_eval_select args are not provided".into(), |
| 1007 | 986 | )); |
| 1008 | 987 | }; |
| 1009 | let result_ty = TyKind::Tuple( | |
| 1010 | 2, | |
| 1011 | Substitution::from_iter(Interner, [lhs.ty.clone(), TyBuilder::bool()]), | |
| 1012 | ) | |
| 1013 | .intern(Interner); | |
| 1014 | let op_size = | |
| 1015 | self.size_of_sized(&lhs.ty, locals, "operand of add_with_overflow")?; | |
| 988 | let result_ty = Ty::new_tup_from_iter( | |
| 989 | self.interner(), | |
| 990 | [lhs.ty, Ty::new_bool(self.interner())].into_iter(), | |
| 991 | ); | |
| 992 | let op_size = self.size_of_sized(lhs.ty, locals, "operand of add_with_overflow")?; | |
| 1016 | 993 | let lhs = u128::from_le_bytes(pad16(lhs.get(self)?, false)); |
| 1017 | 994 | let rhs = u128::from_le_bytes(pad16(rhs.get(self)?, false)); |
| 1018 | 995 | let (ans, u128overflow) = match name { |
| ... | ... | @@ -1024,7 +1001,7 @@ impl Evaluator<'_> { |
| 1024 | 1001 | let is_overflow = u128overflow |
| 1025 | 1002 | || ans.to_le_bytes()[op_size..].iter().any(|&it| it != 0 && it != 255); |
| 1026 | 1003 | let is_overflow = vec![u8::from(is_overflow)]; |
| 1027 | let layout = self.layout(result_ty.to_nextsolver(interner))?; | |
| 1004 | let layout = self.layout(result_ty)?; | |
| 1028 | 1005 | let result = self.construct_with_layout( |
| 1029 | 1006 | layout.size.bytes_usize(), |
| 1030 | 1007 | &layout, |
| ... | ... | @@ -1041,9 +1018,7 @@ impl Evaluator<'_> { |
| 1041 | 1018 | "copy_nonoverlapping args are not provided".into(), |
| 1042 | 1019 | )); |
| 1043 | 1020 | }; |
| 1044 | let Some(ty) = | |
| 1045 | generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) | |
| 1046 | else { | |
| 1021 | let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else { | |
| 1047 | 1022 | return Err(MirEvalError::InternalError( |
| 1048 | 1023 | "copy_nonoverlapping generic arg is not provided".into(), |
| 1049 | 1024 | )); |
| ... | ... | @@ -1062,43 +1037,35 @@ impl Evaluator<'_> { |
| 1062 | 1037 | return Err(MirEvalError::InternalError("offset args are not provided".into())); |
| 1063 | 1038 | }; |
| 1064 | 1039 | let ty = if name == "offset" { |
| 1065 | let Some(ty0) = | |
| 1066 | generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) | |
| 1067 | else { | |
| 1040 | let Some(ty0) = generic_args.as_slice().first().and_then(|it| it.ty()) else { | |
| 1068 | 1041 | return Err(MirEvalError::InternalError( |
| 1069 | 1042 | "offset generic arg is not provided".into(), |
| 1070 | 1043 | )); |
| 1071 | 1044 | }; |
| 1072 | let Some(ty1) = | |
| 1073 | generic_args.as_slice(Interner).get(1).and_then(|it| it.ty(Interner)) | |
| 1074 | else { | |
| 1045 | let Some(ty1) = generic_args.as_slice().get(1).and_then(|it| it.ty()) else { | |
| 1075 | 1046 | return Err(MirEvalError::InternalError( |
| 1076 | 1047 | "offset generic arg is not provided".into(), |
| 1077 | 1048 | )); |
| 1078 | 1049 | }; |
| 1079 | 1050 | if !matches!( |
| 1080 | ty1.as_builtin(), | |
| 1081 | Some( | |
| 1082 | BuiltinType::Int(BuiltinInt::Isize) | |
| 1083 | | BuiltinType::Uint(BuiltinUint::Usize) | |
| 1084 | ) | |
| 1051 | ty1.kind(), | |
| 1052 | TyKind::Int(rustc_type_ir::IntTy::Isize) | |
| 1053 | | TyKind::Uint(rustc_type_ir::UintTy::Usize) | |
| 1085 | 1054 | ) { |
| 1086 | 1055 | return Err(MirEvalError::InternalError( |
| 1087 | 1056 | "offset generic arg is not usize or isize".into(), |
| 1088 | 1057 | )); |
| 1089 | 1058 | } |
| 1090 | match ty0.as_raw_ptr() { | |
| 1091 | Some((ty, _)) => ty, | |
| 1092 | None => { | |
| 1059 | match ty0.kind() { | |
| 1060 | TyKind::RawPtr(ty, _) => ty, | |
| 1061 | _ => { | |
| 1093 | 1062 | return Err(MirEvalError::InternalError( |
| 1094 | 1063 | "offset generic arg is not a raw pointer".into(), |
| 1095 | 1064 | )); |
| 1096 | 1065 | } |
| 1097 | 1066 | } |
| 1098 | 1067 | } else { |
| 1099 | let Some(ty) = | |
| 1100 | generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) | |
| 1101 | else { | |
| 1068 | let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else { | |
| 1102 | 1069 | return Err(MirEvalError::InternalError( |
| 1103 | 1070 | "arith_offset generic arg is not provided".into(), |
| 1104 | 1071 | )); |
| ... | ... | @@ -1223,9 +1190,7 @@ impl Evaluator<'_> { |
| 1223 | 1190 | "discriminant_value arg is not provided".into(), |
| 1224 | 1191 | )); |
| 1225 | 1192 | }; |
| 1226 | let Some(ty) = | |
| 1227 | generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) | |
| 1228 | else { | |
| 1193 | let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else { | |
| 1229 | 1194 | return Err(MirEvalError::InternalError( |
| 1230 | 1195 | "discriminant_value generic arg is not provided".into(), |
| 1231 | 1196 | )); |
| ... | ... | @@ -1233,7 +1198,7 @@ impl Evaluator<'_> { |
| 1233 | 1198 | let addr = Address::from_bytes(arg.get(self)?)?; |
| 1234 | 1199 | let size = self.size_of_sized(ty, locals, "discriminant_value ptr type")?; |
| 1235 | 1200 | let interval = Interval { addr, size }; |
| 1236 | let r = self.compute_discriminant(ty.clone(), interval.get(self)?)?; | |
| 1201 | let r = self.compute_discriminant(ty, interval.get(self)?)?; | |
| 1237 | 1202 | destination.write_from_bytes(self, &r.to_le_bytes()[0..destination.size]) |
| 1238 | 1203 | } |
| 1239 | 1204 | "const_eval_select" => { |
| ... | ... | @@ -1243,14 +1208,13 @@ impl Evaluator<'_> { |
| 1243 | 1208 | )); |
| 1244 | 1209 | }; |
| 1245 | 1210 | let mut args = vec![const_fn.clone()]; |
| 1246 | let TyKind::Tuple(_, fields) = tuple.ty.kind(Interner) else { | |
| 1211 | let TyKind::Tuple(fields) = tuple.ty.kind() else { | |
| 1247 | 1212 | return Err(MirEvalError::InternalError( |
| 1248 | 1213 | "const_eval_select arg[0] is not a tuple".into(), |
| 1249 | 1214 | )); |
| 1250 | 1215 | }; |
| 1251 | let layout = self.layout(tuple.ty.to_nextsolver(interner))?; | |
| 1252 | for (i, field) in fields.iter(Interner).enumerate() { | |
| 1253 | let field = field.assert_ty_ref(Interner).clone(); | |
| 1216 | let layout = self.layout(tuple.ty)?; | |
| 1217 | for (i, field) in fields.iter().enumerate() { | |
| 1254 | 1218 | let offset = layout.fields.offset(i).bytes_usize(); |
| 1255 | 1219 | let addr = tuple.interval.addr.offset(offset); |
| 1256 | 1220 | args.push(IntervalAndTy::new(addr, field, self, locals)?); |
| ... | ... | @@ -1264,7 +1228,7 @@ impl Evaluator<'_> { |
| 1264 | 1228 | def, |
| 1265 | 1229 | &args, |
| 1266 | 1230 | // FIXME: wrong for manual impls of `FnOnce` |
| 1267 | Substitution::empty(Interner), | |
| 1231 | GenericArgs::new_from_iter(self.interner(), []), | |
| 1268 | 1232 | locals, |
| 1269 | 1233 | destination, |
| 1270 | 1234 | None, |
| ... | ... | @@ -1290,9 +1254,7 @@ impl Evaluator<'_> { |
| 1290 | 1254 | )); |
| 1291 | 1255 | }; |
| 1292 | 1256 | let dst = Address::from_bytes(ptr.get(self)?)?; |
| 1293 | let Some(ty) = | |
| 1294 | generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) | |
| 1295 | else { | |
| 1257 | let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else { | |
| 1296 | 1258 | return Err(MirEvalError::InternalError( |
| 1297 | 1259 | "write_via_copy generic arg is not provided".into(), |
| 1298 | 1260 | )); |
| ... | ... | @@ -1309,9 +1271,7 @@ impl Evaluator<'_> { |
| 1309 | 1271 | }; |
| 1310 | 1272 | let count = from_bytes!(usize, count.get(self)?); |
| 1311 | 1273 | let val = from_bytes!(u8, val.get(self)?); |
| 1312 | let Some(ty) = | |
| 1313 | generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) | |
| 1314 | else { | |
| 1274 | let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else { | |
| 1315 | 1275 | return Err(MirEvalError::InternalError( |
| 1316 | 1276 | "write_bytes generic arg is not provided".into(), |
| 1317 | 1277 | )); |
| ... | ... | @@ -1339,16 +1299,14 @@ impl Evaluator<'_> { |
| 1339 | 1299 | "three_way_compare args are not provided".into(), |
| 1340 | 1300 | )); |
| 1341 | 1301 | }; |
| 1342 | let Some(ty) = | |
| 1343 | generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) | |
| 1344 | else { | |
| 1302 | let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else { | |
| 1345 | 1303 | return Err(MirEvalError::InternalError( |
| 1346 | 1304 | "three_way_compare generic arg is not provided".into(), |
| 1347 | 1305 | )); |
| 1348 | 1306 | }; |
| 1349 | let signed = match ty.as_builtin().unwrap() { | |
| 1350 | BuiltinType::Int(_) => true, | |
| 1351 | BuiltinType::Uint(_) => false, | |
| 1307 | let signed = match ty.kind() { | |
| 1308 | TyKind::Int(_) => true, | |
| 1309 | TyKind::Uint(_) => false, | |
| 1352 | 1310 | _ => { |
| 1353 | 1311 | return Err(MirEvalError::InternalError( |
| 1354 | 1312 | "three_way_compare expects an integral type".into(), |
| ... | ... | @@ -1372,8 +1330,8 @@ impl Evaluator<'_> { |
| 1372 | 1330 | result = (l as i8).cmp(&(r as i8)); |
| 1373 | 1331 | } |
| 1374 | 1332 | if let Some(e) = LangItem::Ordering.resolve_enum(self.db, self.crate_id) { |
| 1375 | let ty = self.db.ty(e.into()).skip_binder().to_chalk(interner); | |
| 1376 | let r = self.compute_discriminant(ty.clone(), &[result as i8 as u8])?; | |
| 1333 | let ty = self.db.ty(e.into()).skip_binder(); | |
| 1334 | let r = self.compute_discriminant(ty, &[result as i8 as u8])?; | |
| 1377 | 1335 | destination.write_from_bytes(self, &r.to_le_bytes()[0..destination.size])?; |
| 1378 | 1336 | Ok(()) |
| 1379 | 1337 | } else { |
| ... | ... | @@ -1402,38 +1360,37 @@ impl Evaluator<'_> { |
| 1402 | 1360 | |
| 1403 | 1361 | fn size_align_of_unsized( |
| 1404 | 1362 | &mut self, |
| 1405 | ty: &Ty, | |
| 1363 | ty: Ty<'db>, | |
| 1406 | 1364 | metadata: Interval, |
| 1407 | locals: &Locals, | |
| 1408 | ) -> Result<(usize, usize)> { | |
| 1409 | let interner = DbInterner::new_with(self.db, None, None); | |
| 1410 | Ok(match ty.kind(Interner) { | |
| 1365 | locals: &Locals<'db>, | |
| 1366 | ) -> Result<'db, (usize, usize)> { | |
| 1367 | Ok(match ty.kind() { | |
| 1411 | 1368 | TyKind::Str => (from_bytes!(usize, metadata.get(self)?), 1), |
| 1412 | 1369 | TyKind::Slice(inner) => { |
| 1413 | 1370 | let len = from_bytes!(usize, metadata.get(self)?); |
| 1414 | 1371 | let (size, align) = self.size_align_of_sized(inner, locals, "slice inner type")?; |
| 1415 | 1372 | (size * len, align) |
| 1416 | 1373 | } |
| 1417 | TyKind::Dyn(_) => self.size_align_of_sized( | |
| 1418 | &convert_ty_for_result(interner, self.vtable_map.ty_of_bytes(metadata.get(self)?)?), | |
| 1374 | TyKind::Dynamic(..) => self.size_align_of_sized( | |
| 1375 | self.vtable_map.ty_of_bytes(metadata.get(self)?)?, | |
| 1419 | 1376 | locals, |
| 1420 | 1377 | "dyn concrete type", |
| 1421 | 1378 | )?, |
| 1422 | TyKind::Adt(id, subst) => { | |
| 1423 | let id = id.0; | |
| 1424 | let layout = self.layout_adt(id, subst.clone())?; | |
| 1379 | TyKind::Adt(adt_def, subst) => { | |
| 1380 | let id = adt_def.def_id().0; | |
| 1381 | let layout = self.layout_adt(id, subst)?; | |
| 1425 | 1382 | let id = match id { |
| 1426 | 1383 | AdtId::StructId(s) => s, |
| 1427 | 1384 | _ => not_supported!("unsized enum or union"), |
| 1428 | 1385 | }; |
| 1429 | let field_types = &self.db.field_types(id.into()); | |
| 1386 | let field_types = self.db.field_types_ns(id.into()); | |
| 1430 | 1387 | let last_field_ty = |
| 1431 | field_types.iter().next_back().unwrap().1.clone().substitute(Interner, subst); | |
| 1388 | field_types.iter().next_back().unwrap().1.instantiate(self.interner(), subst); | |
| 1432 | 1389 | let sized_part_size = |
| 1433 | 1390 | layout.fields.offset(field_types.iter().count() - 1).bytes_usize(); |
| 1434 | 1391 | let sized_part_align = layout.align.bytes() as usize; |
| 1435 | 1392 | let (unsized_part_size, unsized_part_align) = |
| 1436 | self.size_align_of_unsized(&last_field_ty, metadata, locals)?; | |
| 1393 | self.size_align_of_unsized(last_field_ty, metadata, locals)?; | |
| 1437 | 1394 | let align = sized_part_align.max(unsized_part_align) as isize; |
| 1438 | 1395 | let size = (sized_part_size + unsized_part_size) as isize; |
| 1439 | 1396 | // Must add any necessary padding to `size` |
| ... | ... | @@ -1456,13 +1413,12 @@ impl Evaluator<'_> { |
| 1456 | 1413 | fn exec_atomic_intrinsic( |
| 1457 | 1414 | &mut self, |
| 1458 | 1415 | name: &str, |
| 1459 | args: &[IntervalAndTy], | |
| 1460 | generic_args: &Substitution, | |
| 1416 | args: &[IntervalAndTy<'db>], | |
| 1417 | generic_args: GenericArgs<'db>, | |
| 1461 | 1418 | destination: Interval, |
| 1462 | locals: &Locals, | |
| 1419 | locals: &Locals<'db>, | |
| 1463 | 1420 | _span: MirSpan, |
| 1464 | ) -> Result<()> { | |
| 1465 | let interner = DbInterner::new_with(self.db, None, None); | |
| 1421 | ) -> Result<'db, ()> { | |
| 1466 | 1422 | // We are a single threaded runtime with no UB checking and no optimization, so |
| 1467 | 1423 | // we can implement atomic intrinsics as normal functions. |
| 1468 | 1424 | |
| ... | ... | @@ -1472,8 +1428,7 @@ impl Evaluator<'_> { |
| 1472 | 1428 | |
| 1473 | 1429 | // The rest of atomic intrinsics have exactly one generic arg |
| 1474 | 1430 | |
| 1475 | let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) | |
| 1476 | else { | |
| 1431 | let Some(ty) = generic_args.as_slice().first().and_then(|it| it.ty()) else { | |
| 1477 | 1432 | return Err(MirEvalError::InternalError( |
| 1478 | 1433 | "atomic intrinsic generic arg is not provided".into(), |
| 1479 | 1434 | )); |
| ... | ... | @@ -1555,12 +1510,11 @@ impl Evaluator<'_> { |
| 1555 | 1510 | } else { |
| 1556 | 1511 | (arg0_interval, false) |
| 1557 | 1512 | }; |
| 1558 | let result_ty = TyKind::Tuple( | |
| 1559 | 2, | |
| 1560 | Substitution::from_iter(Interner, [ty.clone(), TyBuilder::bool()]), | |
| 1561 | ) | |
| 1562 | .intern(Interner); | |
| 1563 | let layout = self.layout(result_ty.to_nextsolver(interner))?; | |
| 1513 | let result_ty = Ty::new_tup_from_iter( | |
| 1514 | self.interner(), | |
| 1515 | [ty, Ty::new_bool(self.interner())].into_iter(), | |
| 1516 | ); | |
| 1517 | let layout = self.layout(result_ty)?; | |
| 1564 | 1518 | let result = self.construct_with_layout( |
| 1565 | 1519 | layout.size.bytes_usize(), |
| 1566 | 1520 | &layout, |
src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs+19-24| ... | ... | @@ -2,7 +2,6 @@ |
| 2 | 2 | |
| 3 | 3 | use std::cmp::Ordering; |
| 4 | 4 | |
| 5 | use crate::TyKind; | |
| 6 | 5 | use crate::consteval::try_const_usize; |
| 7 | 6 | |
| 8 | 7 | use super::*; |
| ... | ... | @@ -22,23 +21,21 @@ macro_rules! not_supported { |
| 22 | 21 | }; |
| 23 | 22 | } |
| 24 | 23 | |
| 25 | impl Evaluator<'_> { | |
| 26 | fn detect_simd_ty(&self, ty: &Ty) -> Result<(usize, Ty)> { | |
| 27 | match ty.kind(Interner) { | |
| 28 | TyKind::Adt(id, subst) => { | |
| 29 | let len = match subst.as_slice(Interner).get(1).and_then(|it| it.constant(Interner)) | |
| 30 | { | |
| 24 | impl<'db> Evaluator<'db> { | |
| 25 | fn detect_simd_ty(&self, ty: Ty<'db>) -> Result<'db, (usize, Ty<'db>)> { | |
| 26 | match ty.kind() { | |
| 27 | TyKind::Adt(adt_def, subst) => { | |
| 28 | let len = match subst.as_slice().get(1).and_then(|it| it.konst()) { | |
| 31 | 29 | Some(len) => len, |
| 32 | 30 | _ => { |
| 33 | if let AdtId::StructId(id) = id.0 { | |
| 31 | if let AdtId::StructId(id) = adt_def.def_id().0 { | |
| 34 | 32 | let struct_data = id.fields(self.db); |
| 35 | 33 | let fields = struct_data.fields(); |
| 36 | 34 | let Some((first_field, _)) = fields.iter().next() else { |
| 37 | 35 | not_supported!("simd type with no field"); |
| 38 | 36 | }; |
| 39 | let field_ty = self.db.field_types(id.into())[first_field] | |
| 40 | .clone() | |
| 41 | .substitute(Interner, subst); | |
| 37 | let field_ty = self.db.field_types_ns(id.into())[first_field] | |
| 38 | .instantiate(self.interner(), subst); | |
| 42 | 39 | return Ok((fields.len(), field_ty)); |
| 43 | 40 | } |
| 44 | 41 | return Err(MirEvalError::InternalError( |
| ... | ... | @@ -48,14 +45,12 @@ impl Evaluator<'_> { |
| 48 | 45 | }; |
| 49 | 46 | match try_const_usize(self.db, len) { |
| 50 | 47 | Some(len) => { |
| 51 | let Some(ty) = | |
| 52 | subst.as_slice(Interner).first().and_then(|it| it.ty(Interner)) | |
| 53 | else { | |
| 48 | let Some(ty) = subst.as_slice().first().and_then(|it| it.ty()) else { | |
| 54 | 49 | return Err(MirEvalError::InternalError( |
| 55 | 50 | "simd type with no ty param".into(), |
| 56 | 51 | )); |
| 57 | 52 | }; |
| 58 | Ok((len as usize, ty.clone())) | |
| 53 | Ok((len as usize, ty)) | |
| 59 | 54 | } |
| 60 | 55 | None => Err(MirEvalError::InternalError( |
| 61 | 56 | "simd type with unevaluatable len param".into(), |
| ... | ... | @@ -69,12 +64,12 @@ impl Evaluator<'_> { |
| 69 | 64 | pub(super) fn exec_simd_intrinsic( |
| 70 | 65 | &mut self, |
| 71 | 66 | name: &str, |
| 72 | args: &[IntervalAndTy], | |
| 73 | _generic_args: &Substitution, | |
| 67 | args: &[IntervalAndTy<'db>], | |
| 68 | _generic_args: GenericArgs<'db>, | |
| 74 | 69 | destination: Interval, |
| 75 | _locals: &Locals, | |
| 70 | _locals: &Locals<'db>, | |
| 76 | 71 | _span: MirSpan, |
| 77 | ) -> Result<()> { | |
| 72 | ) -> Result<'db, ()> { | |
| 78 | 73 | match name { |
| 79 | 74 | "and" | "or" | "xor" => { |
| 80 | 75 | let [left, right] = args else { |
| ... | ... | @@ -99,8 +94,8 @@ impl Evaluator<'_> { |
| 99 | 94 | let [left, right] = args else { |
| 100 | 95 | return Err(MirEvalError::InternalError("simd args are not provided".into())); |
| 101 | 96 | }; |
| 102 | let (len, ty) = self.detect_simd_ty(&left.ty)?; | |
| 103 | let is_signed = matches!(ty.as_builtin(), Some(BuiltinType::Int(_))); | |
| 97 | let (len, ty) = self.detect_simd_ty(left.ty)?; | |
| 98 | let is_signed = matches!(ty.kind(), TyKind::Int(_)); | |
| 104 | 99 | let size = left.interval.size / len; |
| 105 | 100 | let dest_size = destination.size / len; |
| 106 | 101 | let mut destination_bytes = vec![]; |
| ... | ... | @@ -137,7 +132,7 @@ impl Evaluator<'_> { |
| 137 | 132 | "simd_bitmask args are not provided".into(), |
| 138 | 133 | )); |
| 139 | 134 | }; |
| 140 | let (op_len, _) = self.detect_simd_ty(&op.ty)?; | |
| 135 | let (op_len, _) = self.detect_simd_ty(op.ty)?; | |
| 141 | 136 | let op_count = op.interval.size / op_len; |
| 142 | 137 | let mut result: u64 = 0; |
| 143 | 138 | for (i, val) in op.get(self)?.chunks(op_count).enumerate() { |
| ... | ... | @@ -153,7 +148,7 @@ impl Evaluator<'_> { |
| 153 | 148 | "simd_shuffle args are not provided".into(), |
| 154 | 149 | )); |
| 155 | 150 | }; |
| 156 | let TyKind::Array(_, index_len) = index.ty.kind(Interner) else { | |
| 151 | let TyKind::Array(_, index_len) = index.ty.kind() else { | |
| 157 | 152 | return Err(MirEvalError::InternalError( |
| 158 | 153 | "simd_shuffle index argument has non-array type".into(), |
| 159 | 154 | )); |
| ... | ... | @@ -166,7 +161,7 @@ impl Evaluator<'_> { |
| 166 | 161 | )); |
| 167 | 162 | } |
| 168 | 163 | }; |
| 169 | let (left_len, _) = self.detect_simd_ty(&left.ty)?; | |
| 164 | let (left_len, _) = self.detect_simd_ty(left.ty)?; | |
| 170 | 165 | let left_size = left.interval.size / left_len; |
| 171 | 166 | let vector = |
| 172 | 167 | left.get(self)?.chunks(left_size).chain(right.get(self)?.chunks(left_size)); |
src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs+21-12| ... | ... | @@ -4,15 +4,20 @@ use span::Edition; |
| 4 | 4 | use syntax::{TextRange, TextSize}; |
| 5 | 5 | use test_fixture::WithFixture; |
| 6 | 6 | |
| 7 | use crate::display::DisplayTarget; | |
| 8 | 7 | use crate::{ |
| 9 | Interner, Substitution, db::HirDatabase, mir::MirLowerError, setup_tracing, test_db::TestDB, | |
| 8 | db::HirDatabase, | |
| 9 | display::DisplayTarget, | |
| 10 | mir::MirLowerError, | |
| 11 | next_solver::{DbInterner, GenericArgs}, | |
| 12 | setup_tracing, | |
| 13 | test_db::TestDB, | |
| 10 | 14 | }; |
| 11 | 15 | |
| 12 | 16 | use super::{MirEvalError, interpret_mir}; |
| 13 | 17 | |
| 14 | fn eval_main(db: &TestDB, file_id: EditionedFileId) -> Result<(String, String), MirEvalError> { | |
| 15 | salsa::attach(db, || { | |
| 18 | fn eval_main(db: &TestDB, file_id: EditionedFileId) -> Result<(String, String), MirEvalError<'_>> { | |
| 19 | crate::attach_db(db, || { | |
| 20 | let interner = DbInterner::new_with(db, None, None); | |
| 16 | 21 | let module_id = db.module_for_file(file_id.file_id(db)); |
| 17 | 22 | let def_map = module_id.def_map(db); |
| 18 | 23 | let scope = &def_map[module_id.local_id].scope; |
| ... | ... | @@ -34,7 +39,7 @@ fn eval_main(db: &TestDB, file_id: EditionedFileId) -> Result<(String, String), |
| 34 | 39 | let body = db |
| 35 | 40 | .monomorphized_mir_body( |
| 36 | 41 | func_id.into(), |
| 37 | Substitution::empty(Interner), | |
| 42 | GenericArgs::new_from_iter(interner, []), | |
| 38 | 43 | db.trait_environment(func_id.into()), |
| 39 | 44 | ) |
| 40 | 45 | .map_err(|e| MirEvalError::MirLowerError(func_id, e))?; |
| ... | ... | @@ -56,7 +61,7 @@ fn check_pass_and_stdio( |
| 56 | 61 | ) { |
| 57 | 62 | let _tracing = setup_tracing(); |
| 58 | 63 | let (db, file_ids) = TestDB::with_many_files(ra_fixture); |
| 59 | salsa::attach(&db, || { | |
| 64 | crate::attach_db(&db, || { | |
| 60 | 65 | let file_id = *file_ids.last().unwrap(); |
| 61 | 66 | let x = eval_main(&db, file_id); |
| 62 | 67 | match x { |
| ... | ... | @@ -102,7 +107,7 @@ fn check_pass_and_stdio( |
| 102 | 107 | |
| 103 | 108 | fn check_panic(#[rust_analyzer::rust_fixture] ra_fixture: &str, expected_panic: &str) { |
| 104 | 109 | let (db, file_ids) = TestDB::with_many_files(ra_fixture); |
| 105 | salsa::attach(&db, || { | |
| 110 | crate::attach_db(&db, || { | |
| 106 | 111 | let file_id = *file_ids.last().unwrap(); |
| 107 | 112 | let e = eval_main(&db, file_id).unwrap_err(); |
| 108 | 113 | assert_eq!( |
| ... | ... | @@ -114,10 +119,10 @@ fn check_panic(#[rust_analyzer::rust_fixture] ra_fixture: &str, expected_panic: |
| 114 | 119 | |
| 115 | 120 | fn check_error_with( |
| 116 | 121 | #[rust_analyzer::rust_fixture] ra_fixture: &str, |
| 117 | expect_err: impl FnOnce(MirEvalError) -> bool, | |
| 122 | expect_err: impl FnOnce(MirEvalError<'_>) -> bool, | |
| 118 | 123 | ) { |
| 119 | 124 | let (db, file_ids) = TestDB::with_many_files(ra_fixture); |
| 120 | salsa::attach(&db, || { | |
| 125 | crate::attach_db(&db, || { | |
| 121 | 126 | let file_id = *file_ids.last().unwrap(); |
| 122 | 127 | let e = eval_main(&db, file_id).unwrap_err(); |
| 123 | 128 | assert!(expect_err(e)); |
| ... | ... | @@ -631,11 +636,16 @@ fn main() { |
| 631 | 636 | ); |
| 632 | 637 | } |
| 633 | 638 | |
| 639 | #[ignore = " | |
| 640 | FIXME(next-solver): | |
| 641 | This does not work currently because I replaced homemade selection with selection by the trait solver; | |
| 642 | This will work once we implement `Interner::impl_specializes()` properly. | |
| 643 | "] | |
| 634 | 644 | #[test] |
| 635 | 645 | fn specialization_array_clone() { |
| 636 | 646 | check_pass( |
| 637 | 647 | r#" |
| 638 | //- minicore: copy, derive, slice, index, coerce_unsized | |
| 648 | //- minicore: copy, derive, slice, index, coerce_unsized, panic | |
| 639 | 649 | impl<T: Clone, const N: usize> Clone for [T; N] { |
| 640 | 650 | #[inline] |
| 641 | 651 | fn clone(&self) -> Self { |
| ... | ... | @@ -650,8 +660,7 @@ trait SpecArrayClone: Clone { |
| 650 | 660 | impl<T: Clone> SpecArrayClone for T { |
| 651 | 661 | #[inline] |
| 652 | 662 | default fn clone<const N: usize>(array: &[T; N]) -> [T; N] { |
| 653 | // FIXME: panic here when we actually implement specialization. | |
| 654 | from_slice(array) | |
| 663 | panic!("should go to the specialized impl") | |
| 655 | 664 | } |
| 656 | 665 | } |
| 657 | 666 |
src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs+319-272| ... | ... | @@ -3,10 +3,9 @@ |
| 3 | 3 | use std::{fmt::Write, iter, mem}; |
| 4 | 4 | |
| 5 | 5 | use base_db::Crate; |
| 6 | use chalk_ir::{BoundVar, ConstData, DebruijnIndex, TyKind}; | |
| 7 | 6 | use hir_def::{ |
| 8 | AdtId, DefWithBodyId, EnumVariantId, GeneralConstId, HasModule, ItemContainerId, LocalFieldId, | |
| 9 | Lookup, TraitId, TupleId, TypeOrConstParamId, | |
| 7 | AdtId, DefWithBodyId, EnumVariantId, GeneralConstId, GenericParamId, HasModule, | |
| 8 | ItemContainerId, LocalFieldId, Lookup, TraitId, TupleId, | |
| 10 | 9 | expr_store::{Body, ExpressionStore, HygieneId, path::Path}, |
| 11 | 10 | hir::{ |
| 12 | 11 | ArithOp, Array, BinaryOp, BindingAnnotation, BindingId, ExprId, LabelId, Literal, MatchArm, |
| ... | ... | @@ -20,36 +19,33 @@ use hir_expand::name::Name; |
| 20 | 19 | use la_arena::ArenaMap; |
| 21 | 20 | use rustc_apfloat::Float; |
| 22 | 21 | use rustc_hash::FxHashMap; |
| 22 | use rustc_type_ir::inherent::{Const as _, IntoKind, SliceLike, Ty as _}; | |
| 23 | 23 | use span::{Edition, FileId}; |
| 24 | 24 | use syntax::TextRange; |
| 25 | 25 | use triomphe::Arc; |
| 26 | 26 | |
| 27 | 27 | use crate::{ |
| 28 | Adjust, Adjustment, AutoBorrow, CallableDefId, TraitEnvironment, TyBuilder, TyExt, | |
| 28 | Adjust, Adjustment, AutoBorrow, CallableDefId, TraitEnvironment, | |
| 29 | 29 | consteval::ConstEvalError, |
| 30 | 30 | db::{HirDatabase, InternedClosure, InternedClosureId}, |
| 31 | 31 | display::{DisplayTarget, HirDisplay, hir_display_with_store}, |
| 32 | error_lifetime, | |
| 33 | 32 | generics::generics, |
| 34 | 33 | infer::{CaptureKind, CapturedItem, TypeMismatch, cast::CastTy}, |
| 35 | 34 | inhabitedness::is_ty_uninhabited_from, |
| 36 | 35 | layout::LayoutError, |
| 37 | mapping::ToChalk, | |
| 38 | 36 | mir::{ |
| 39 | AggregateKind, Arena, BasicBlock, BasicBlockId, BinOp, BorrowKind, CastKind, ConstScalar, | |
| 40 | Either, Expr, FieldId, Idx, InferenceResult, Interner, Local, LocalId, MemoryMap, MirBody, | |
| 41 | MirSpan, Mutability, Operand, Place, PlaceElem, PointerCast, ProjectionElem, | |
| 42 | ProjectionStore, RawIdx, Rvalue, Statement, StatementKind, Substitution, SwitchTargets, | |
| 43 | Terminator, TerminatorKind, TupleFieldId, Ty, UnOp, VariantId, intern_const_scalar, | |
| 44 | return_slot, | |
| 37 | AggregateKind, Arena, BasicBlock, BasicBlockId, BinOp, BorrowKind, CastKind, Either, Expr, | |
| 38 | FieldId, GenericArgs, Idx, InferenceResult, Local, LocalId, MemoryMap, MirBody, MirSpan, | |
| 39 | Mutability, Operand, Place, PlaceElem, PointerCast, ProjectionElem, ProjectionStore, | |
| 40 | RawIdx, Rvalue, Statement, StatementKind, SwitchTargets, Terminator, TerminatorKind, | |
| 41 | TupleFieldId, Ty, UnOp, VariantId, return_slot, | |
| 45 | 42 | }, |
| 46 | 43 | next_solver::{ |
| 47 | DbInterner, | |
| 48 | mapping::{ChalkToNextSolver, NextSolverToChalk}, | |
| 44 | Const, DbInterner, ParamConst, Region, TyKind, TypingMode, UnevaluatedConst, | |
| 45 | infer::{DbInternerInferExt, InferCtxt}, | |
| 46 | mapping::NextSolverToChalk, | |
| 49 | 47 | }, |
| 50 | static_lifetime, | |
| 51 | 48 | traits::FnTrait, |
| 52 | utils::ClosureSubst, | |
| 53 | 49 | }; |
| 54 | 50 | |
| 55 | 51 | use super::OperandKind; |
| ... | ... | @@ -60,38 +56,39 @@ mod pattern_matching; |
| 60 | 56 | mod tests; |
| 61 | 57 | |
| 62 | 58 | #[derive(Debug, Clone)] |
| 63 | struct LoopBlocks { | |
| 64 | begin: BasicBlockId, | |
| 59 | struct LoopBlocks<'db> { | |
| 60 | begin: BasicBlockId<'db>, | |
| 65 | 61 | /// `None` for loops that are not terminating |
| 66 | end: Option<BasicBlockId>, | |
| 67 | place: Place, | |
| 62 | end: Option<BasicBlockId<'db>>, | |
| 63 | place: Place<'db>, | |
| 68 | 64 | drop_scope_index: usize, |
| 69 | 65 | } |
| 70 | 66 | |
| 71 | 67 | #[derive(Debug, Clone, Default)] |
| 72 | struct DropScope { | |
| 68 | struct DropScope<'db> { | |
| 73 | 69 | /// locals, in order of definition (so we should run drop glues in reverse order) |
| 74 | locals: Vec<LocalId>, | |
| 70 | locals: Vec<LocalId<'db>>, | |
| 75 | 71 | } |
| 76 | 72 | |
| 77 | struct MirLowerCtx<'db> { | |
| 78 | result: MirBody, | |
| 73 | struct MirLowerCtx<'a, 'db> { | |
| 74 | result: MirBody<'db>, | |
| 79 | 75 | owner: DefWithBodyId, |
| 80 | current_loop_blocks: Option<LoopBlocks>, | |
| 81 | labeled_loop_blocks: FxHashMap<LabelId, LoopBlocks>, | |
| 82 | discr_temp: Option<Place>, | |
| 76 | current_loop_blocks: Option<LoopBlocks<'db>>, | |
| 77 | labeled_loop_blocks: FxHashMap<LabelId, LoopBlocks<'db>>, | |
| 78 | discr_temp: Option<Place<'db>>, | |
| 83 | 79 | db: &'db dyn HirDatabase, |
| 84 | body: &'db Body, | |
| 85 | infer: &'db InferenceResult, | |
| 80 | body: &'a Body, | |
| 81 | infer: &'a InferenceResult<'db>, | |
| 86 | 82 | resolver: Resolver<'db>, |
| 87 | drop_scopes: Vec<DropScope>, | |
| 83 | drop_scopes: Vec<DropScope<'db>>, | |
| 88 | 84 | env: Arc<TraitEnvironment<'db>>, |
| 85 | infcx: InferCtxt<'db>, | |
| 89 | 86 | } |
| 90 | 87 | |
| 91 | 88 | // FIXME: Make this smaller, its stored in database queries |
| 92 | 89 | #[derive(Debug, Clone, PartialEq, Eq)] |
| 93 | pub enum MirLowerError { | |
| 94 | ConstEvalError(Box<str>, Box<ConstEvalError>), | |
| 90 | pub enum MirLowerError<'db> { | |
| 91 | ConstEvalError(Box<str>, Box<ConstEvalError<'db>>), | |
| 95 | 92 | LayoutError(LayoutError), |
| 96 | 93 | IncompleteExpr, |
| 97 | 94 | IncompletePattern, |
| ... | ... | @@ -101,9 +98,9 @@ pub enum MirLowerError { |
| 101 | 98 | RecordLiteralWithoutPath, |
| 102 | 99 | UnresolvedMethod(String), |
| 103 | 100 | UnresolvedField, |
| 104 | UnsizedTemporary(Ty), | |
| 101 | UnsizedTemporary(Ty<'db>), | |
| 105 | 102 | MissingFunctionDefinition(DefWithBodyId, ExprId), |
| 106 | TypeMismatch(TypeMismatch), | |
| 103 | TypeMismatch(TypeMismatch<'db>), | |
| 107 | 104 | HasErrors, |
| 108 | 105 | /// This should never happen. Type mismatch should catch everything. |
| 109 | 106 | TypeError(&'static str), |
| ... | ... | @@ -116,22 +113,22 @@ pub enum MirLowerError { |
| 116 | 113 | LangItemNotFound(LangItem), |
| 117 | 114 | MutatingRvalue, |
| 118 | 115 | UnresolvedLabel, |
| 119 | UnresolvedUpvar(Place), | |
| 116 | UnresolvedUpvar(Place<'db>), | |
| 120 | 117 | InaccessibleLocal, |
| 121 | 118 | |
| 122 | 119 | // monomorphization errors: |
| 123 | GenericArgNotProvided(TypeOrConstParamId, Substitution), | |
| 120 | GenericArgNotProvided(GenericParamId, GenericArgs<'db>), | |
| 124 | 121 | } |
| 125 | 122 | |
| 126 | 123 | /// A token to ensuring that each drop scope is popped at most once, thanks to the compiler that checks moves. |
| 127 | 124 | struct DropScopeToken; |
| 128 | 125 | impl DropScopeToken { |
| 129 | fn pop_and_drop( | |
| 126 | fn pop_and_drop<'db>( | |
| 130 | 127 | self, |
| 131 | ctx: &mut MirLowerCtx<'_>, | |
| 132 | current: BasicBlockId, | |
| 128 | ctx: &mut MirLowerCtx<'_, 'db>, | |
| 129 | current: BasicBlockId<'db>, | |
| 133 | 130 | span: MirSpan, |
| 134 | ) -> BasicBlockId { | |
| 131 | ) -> BasicBlockId<'db> { | |
| 135 | 132 | std::mem::forget(self); |
| 136 | 133 | ctx.pop_drop_scope_internal(current, span) |
| 137 | 134 | } |
| ... | ... | @@ -140,7 +137,7 @@ impl DropScopeToken { |
| 140 | 137 | /// code. Either when the control flow is diverging (so drop code doesn't reached) or when drop is handled |
| 141 | 138 | /// for us (for example a block that ended with a return statement. Return will drop everything, so the block shouldn't |
| 142 | 139 | /// do anything) |
| 143 | fn pop_assume_dropped(self, ctx: &mut MirLowerCtx<'_>) { | |
| 140 | fn pop_assume_dropped(self, ctx: &mut MirLowerCtx<'_, '_>) { | |
| 144 | 141 | std::mem::forget(self); |
| 145 | 142 | ctx.pop_drop_scope_assume_dropped_internal(); |
| 146 | 143 | } |
| ... | ... | @@ -161,7 +158,7 @@ impl Drop for DropScopeToken { |
| 161 | 158 | // } |
| 162 | 159 | // } |
| 163 | 160 | |
| 164 | impl MirLowerError { | |
| 161 | impl MirLowerError<'_> { | |
| 165 | 162 | pub fn pretty_print( |
| 166 | 163 | &self, |
| 167 | 164 | f: &mut String, |
| ... | ... | @@ -197,15 +194,24 @@ impl MirLowerError { |
| 197 | 194 | e.actual.display(db, display_target), |
| 198 | 195 | )?, |
| 199 | 196 | MirLowerError::GenericArgNotProvided(id, subst) => { |
| 200 | let parent = id.parent; | |
| 201 | let param = &db.generic_params(parent)[id.local_id]; | |
| 197 | let param_name = match *id { | |
| 198 | GenericParamId::TypeParamId(id) => { | |
| 199 | db.generic_params(id.parent())[id.local_id()].name().cloned() | |
| 200 | } | |
| 201 | GenericParamId::ConstParamId(id) => { | |
| 202 | db.generic_params(id.parent())[id.local_id()].name().cloned() | |
| 203 | } | |
| 204 | GenericParamId::LifetimeParamId(id) => { | |
| 205 | Some(db.generic_params(id.parent)[id.local_id].name.clone()) | |
| 206 | } | |
| 207 | }; | |
| 202 | 208 | writeln!( |
| 203 | 209 | f, |
| 204 | 210 | "Generic arg not provided for {}", |
| 205 | param.name().unwrap_or(&Name::missing()).display(db, display_target.edition) | |
| 211 | param_name.unwrap_or(Name::missing()).display(db, display_target.edition) | |
| 206 | 212 | )?; |
| 207 | 213 | writeln!(f, "Provided args: [")?; |
| 208 | for g in subst.iter(Interner) { | |
| 214 | for g in subst.iter() { | |
| 209 | 215 | write!(f, " {},", g.display(db, display_target))?; |
| 210 | 216 | } |
| 211 | 217 | writeln!(f, "]")?; |
| ... | ... | @@ -248,13 +254,13 @@ macro_rules! implementation_error { |
| 248 | 254 | }}; |
| 249 | 255 | } |
| 250 | 256 | |
| 251 | impl From<LayoutError> for MirLowerError { | |
| 257 | impl From<LayoutError> for MirLowerError<'_> { | |
| 252 | 258 | fn from(value: LayoutError) -> Self { |
| 253 | 259 | MirLowerError::LayoutError(value) |
| 254 | 260 | } |
| 255 | 261 | } |
| 256 | 262 | |
| 257 | impl MirLowerError { | |
| 263 | impl MirLowerError<'_> { | |
| 258 | 264 | fn unresolved_path( |
| 259 | 265 | db: &dyn HirDatabase, |
| 260 | 266 | p: &Path, |
| ... | ... | @@ -267,14 +273,14 @@ impl MirLowerError { |
| 267 | 273 | } |
| 268 | 274 | } |
| 269 | 275 | |
| 270 | type Result<T> = std::result::Result<T, MirLowerError>; | |
| 276 | type Result<'db, T> = std::result::Result<T, MirLowerError<'db>>; | |
| 271 | 277 | |
| 272 | impl<'ctx> MirLowerCtx<'ctx> { | |
| 278 | impl<'a, 'db> MirLowerCtx<'a, 'db> { | |
| 273 | 279 | fn new( |
| 274 | db: &'ctx dyn HirDatabase, | |
| 280 | db: &'db dyn HirDatabase, | |
| 275 | 281 | owner: DefWithBodyId, |
| 276 | body: &'ctx Body, | |
| 277 | infer: &'ctx InferenceResult, | |
| 282 | body: &'a Body, | |
| 283 | infer: &'a InferenceResult<'db>, | |
| 278 | 284 | ) -> Self { |
| 279 | 285 | let mut basic_blocks = Arena::new(); |
| 280 | 286 | let start_block = basic_blocks.alloc(BasicBlock { |
| ... | ... | @@ -283,7 +289,7 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 283 | 289 | is_cleanup: false, |
| 284 | 290 | }); |
| 285 | 291 | let locals = Arena::new(); |
| 286 | let binding_locals: ArenaMap<BindingId, LocalId> = ArenaMap::new(); | |
| 292 | let binding_locals: ArenaMap<BindingId, LocalId<'db>> = ArenaMap::new(); | |
| 287 | 293 | let mir = MirBody { |
| 288 | 294 | projection_store: ProjectionStore::default(), |
| 289 | 295 | basic_blocks, |
| ... | ... | @@ -296,6 +302,8 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 296 | 302 | }; |
| 297 | 303 | let resolver = owner.resolver(db); |
| 298 | 304 | let env = db.trait_environment_for_body(owner); |
| 305 | let interner = DbInterner::new_with(db, Some(env.krate), env.block); | |
| 306 | let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); | |
| 299 | 307 | |
| 300 | 308 | MirLowerCtx { |
| 301 | 309 | result: mir, |
| ... | ... | @@ -309,11 +317,22 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 309 | 317 | discr_temp: None, |
| 310 | 318 | drop_scopes: vec![DropScope::default()], |
| 311 | 319 | env, |
| 320 | infcx, | |
| 312 | 321 | } |
| 313 | 322 | } |
| 314 | 323 | |
| 315 | fn temp(&mut self, ty: Ty, current: BasicBlockId, span: MirSpan) -> Result<LocalId> { | |
| 316 | if matches!(ty.kind(Interner), TyKind::Slice(_) | TyKind::Dyn(_)) { | |
| 324 | #[inline] | |
| 325 | fn interner(&self) -> DbInterner<'db> { | |
| 326 | self.infcx.interner | |
| 327 | } | |
| 328 | ||
| 329 | fn temp( | |
| 330 | &mut self, | |
| 331 | ty: Ty<'db>, | |
| 332 | current: BasicBlockId<'db>, | |
| 333 | span: MirSpan, | |
| 334 | ) -> Result<'db, LocalId<'db>> { | |
| 335 | if matches!(ty.kind(), TyKind::Slice(_) | TyKind::Dynamic(..)) { | |
| 317 | 336 | return Err(MirLowerError::UnsizedTemporary(ty)); |
| 318 | 337 | } |
| 319 | 338 | let l = self.result.locals.alloc(Local { ty }); |
| ... | ... | @@ -324,8 +343,8 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 324 | 343 | fn lower_expr_to_some_operand( |
| 325 | 344 | &mut self, |
| 326 | 345 | expr_id: ExprId, |
| 327 | current: BasicBlockId, | |
| 328 | ) -> Result<Option<(Operand, BasicBlockId)>> { | |
| 346 | current: BasicBlockId<'db>, | |
| 347 | ) -> Result<'db, Option<(Operand<'db>, BasicBlockId<'db>)>> { | |
| 329 | 348 | if !self.has_adjustments(expr_id) |
| 330 | 349 | && let Expr::Literal(l) = &self.body[expr_id] |
| 331 | 350 | { |
| ... | ... | @@ -341,15 +360,18 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 341 | 360 | fn lower_expr_to_place_with_adjust( |
| 342 | 361 | &mut self, |
| 343 | 362 | expr_id: ExprId, |
| 344 | place: Place, | |
| 345 | current: BasicBlockId, | |
| 346 | adjustments: &[Adjustment], | |
| 347 | ) -> Result<Option<BasicBlockId>> { | |
| 363 | place: Place<'db>, | |
| 364 | current: BasicBlockId<'db>, | |
| 365 | adjustments: &[Adjustment<'db>], | |
| 366 | ) -> Result<'db, Option<BasicBlockId<'db>>> { | |
| 348 | 367 | match adjustments.split_last() { |
| 349 | 368 | Some((last, rest)) => match &last.kind { |
| 350 | 369 | Adjust::NeverToAny => { |
| 351 | let temp = | |
| 352 | self.temp(TyKind::Never.intern(Interner), current, MirSpan::Unknown)?; | |
| 370 | let temp = self.temp( | |
| 371 | Ty::new(self.interner(), TyKind::Never), | |
| 372 | current, | |
| 373 | MirSpan::Unknown, | |
| 374 | )?; | |
| 353 | 375 | self.lower_expr_to_place_with_adjust(expr_id, temp.into(), current, rest) |
| 354 | 376 | } |
| 355 | 377 | Adjust::Deref(_) => { |
| ... | ... | @@ -372,7 +394,7 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 372 | 394 | else { |
| 373 | 395 | return Ok(None); |
| 374 | 396 | }; |
| 375 | let bk = BorrowKind::from_chalk(*m); | |
| 397 | let bk = BorrowKind::from_rustc(*m); | |
| 376 | 398 | self.push_assignment(current, place, Rvalue::Ref(bk, p), expr_id.into()); |
| 377 | 399 | Ok(Some(current)) |
| 378 | 400 | } |
| ... | ... | @@ -388,7 +410,7 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 388 | 410 | Rvalue::Cast( |
| 389 | 411 | CastKind::PointerCoercion(*cast), |
| 390 | 412 | Operand { kind: OperandKind::Copy(p), span: None }, |
| 391 | last.target.clone(), | |
| 413 | last.target, | |
| 392 | 414 | ), |
| 393 | 415 | expr_id.into(), |
| 394 | 416 | ); |
| ... | ... | @@ -402,9 +424,9 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 402 | 424 | fn lower_expr_to_place( |
| 403 | 425 | &mut self, |
| 404 | 426 | expr_id: ExprId, |
| 405 | place: Place, | |
| 406 | prev_block: BasicBlockId, | |
| 407 | ) -> Result<Option<BasicBlockId>> { | |
| 427 | place: Place<'db>, | |
| 428 | prev_block: BasicBlockId<'db>, | |
| 429 | ) -> Result<'db, Option<BasicBlockId<'db>>> { | |
| 408 | 430 | if let Some(adjustments) = self.infer.expr_adjustments.get(&expr_id) { |
| 409 | 431 | return self.lower_expr_to_place_with_adjust(expr_id, place, prev_block, adjustments); |
| 410 | 432 | } |
| ... | ... | @@ -414,9 +436,9 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 414 | 436 | fn lower_expr_to_place_without_adjust( |
| 415 | 437 | &mut self, |
| 416 | 438 | expr_id: ExprId, |
| 417 | place: Place, | |
| 418 | mut current: BasicBlockId, | |
| 419 | ) -> Result<Option<BasicBlockId>> { | |
| 439 | place: Place<'db>, | |
| 440 | mut current: BasicBlockId<'db>, | |
| 441 | ) -> Result<'db, Option<BasicBlockId<'db>>> { | |
| 420 | 442 | match &self.body[expr_id] { |
| 421 | 443 | Expr::OffsetOf(_) => { |
| 422 | 444 | not_supported!("builtin#offset_of") |
| ... | ... | @@ -439,14 +461,7 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 439 | 461 | if let Some((assoc, subst)) = self.infer.assoc_resolutions_for_expr(expr_id) { |
| 440 | 462 | match assoc { |
| 441 | 463 | hir_def::AssocItemId::ConstId(c) => { |
| 442 | self.lower_const( | |
| 443 | c.into(), | |
| 444 | current, | |
| 445 | place, | |
| 446 | subst, | |
| 447 | expr_id.into(), | |
| 448 | self.expr_ty_without_adjust(expr_id), | |
| 449 | )?; | |
| 464 | self.lower_const(c.into(), current, place, subst, expr_id.into())?; | |
| 450 | 465 | return Ok(Some(current)); |
| 451 | 466 | } |
| 452 | 467 | hir_def::AssocItemId::FunctionId(_) => { |
| ... | ... | @@ -502,16 +517,15 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 502 | 517 | const_id.into(), |
| 503 | 518 | current, |
| 504 | 519 | place, |
| 505 | Substitution::empty(Interner), | |
| 520 | GenericArgs::new_from_iter(self.interner(), []), | |
| 506 | 521 | expr_id.into(), |
| 507 | self.expr_ty_without_adjust(expr_id), | |
| 508 | 522 | )?; |
| 509 | 523 | Ok(Some(current)) |
| 510 | 524 | } |
| 511 | 525 | ValueNs::EnumVariantId(variant_id) => { |
| 512 | 526 | let variant_fields = variant_id.fields(self.db); |
| 513 | 527 | if variant_fields.shape == FieldsShape::Unit { |
| 514 | let ty = self.infer.type_of_expr[expr_id].clone(); | |
| 528 | let ty = self.infer.type_of_expr[expr_id]; | |
| 515 | 529 | current = self.lower_enum_variant( |
| 516 | 530 | variant_id, |
| 517 | 531 | current, |
| ... | ... | @@ -529,25 +543,21 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 529 | 543 | not_supported!("owner without generic def id"); |
| 530 | 544 | }; |
| 531 | 545 | let generics = generics(self.db, def); |
| 532 | let ty = self.expr_ty_without_adjust(expr_id); | |
| 546 | let index = generics | |
| 547 | .type_or_const_param_idx(p.into()) | |
| 548 | .ok_or(MirLowerError::TypeError("fail to lower const generic param"))? | |
| 549 | as u32; | |
| 533 | 550 | self.push_assignment( |
| 534 | 551 | current, |
| 535 | 552 | place, |
| 536 | 553 | Rvalue::from(Operand { |
| 537 | kind: OperandKind::Constant( | |
| 538 | ConstData { | |
| 539 | ty, | |
| 540 | value: chalk_ir::ConstValue::BoundVar(BoundVar::new( | |
| 541 | DebruijnIndex::INNERMOST, | |
| 542 | generics.type_or_const_param_idx(p.into()).ok_or( | |
| 543 | MirLowerError::TypeError( | |
| 544 | "fail to lower const generic param", | |
| 545 | ), | |
| 546 | )?, | |
| 547 | )), | |
| 548 | } | |
| 549 | .intern(Interner), | |
| 550 | ), | |
| 554 | kind: OperandKind::Constant { | |
| 555 | konst: Const::new_param( | |
| 556 | self.interner(), | |
| 557 | ParamConst { id: p, index }, | |
| 558 | ), | |
| 559 | ty: self.db.const_param_ty_ns(p), | |
| 560 | }, | |
| 551 | 561 | span: None, |
| 552 | 562 | }), |
| 553 | 563 | expr_id.into(), |
| ... | ... | @@ -599,7 +609,7 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 599 | 609 | then_target, |
| 600 | 610 | place, |
| 601 | 611 | Box::new([1]), |
| 602 | TyBuilder::bool(), | |
| 612 | Ty::new_bool(self.interner()), | |
| 603 | 613 | MirSpan::Unknown, |
| 604 | 614 | )?; |
| 605 | 615 | if let Some(else_target) = else_target { |
| ... | ... | @@ -607,7 +617,7 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 607 | 617 | else_target, |
| 608 | 618 | place, |
| 609 | 619 | Box::new([0]), |
| 610 | TyBuilder::bool(), | |
| 620 | Ty::new_bool(self.interner()), | |
| 611 | 621 | MirSpan::Unknown, |
| 612 | 622 | )?; |
| 613 | 623 | } |
| ... | ... | @@ -649,11 +659,11 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 649 | 659 | } |
| 650 | 660 | Expr::Call { callee, args, .. } => { |
| 651 | 661 | if let Some((func_id, generic_args)) = self.infer.method_resolution(expr_id) { |
| 652 | let ty = chalk_ir::TyKind::FnDef( | |
| 653 | CallableDefId::FunctionId(func_id).to_chalk(self.db), | |
| 662 | let ty = Ty::new_fn_def( | |
| 663 | self.interner(), | |
| 664 | CallableDefId::FunctionId(func_id).into(), | |
| 654 | 665 | generic_args, |
| 655 | ) | |
| 656 | .intern(Interner); | |
| 666 | ); | |
| 657 | 667 | let func = Operand::from_bytes(Box::default(), ty); |
| 658 | 668 | return self.lower_call_and_args( |
| 659 | 669 | func, |
| ... | ... | @@ -665,9 +675,9 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 665 | 675 | ); |
| 666 | 676 | } |
| 667 | 677 | let callee_ty = self.expr_ty_after_adjustments(*callee); |
| 668 | match &callee_ty.kind(Interner) { | |
| 669 | chalk_ir::TyKind::FnDef(..) => { | |
| 670 | let func = Operand::from_bytes(Box::default(), callee_ty.clone()); | |
| 678 | match callee_ty.kind() { | |
| 679 | TyKind::FnDef(..) => { | |
| 680 | let func = Operand::from_bytes(Box::default(), callee_ty); | |
| 671 | 681 | self.lower_call_and_args( |
| 672 | 682 | func, |
| 673 | 683 | args.iter().copied(), |
| ... | ... | @@ -677,7 +687,7 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 677 | 687 | expr_id.into(), |
| 678 | 688 | ) |
| 679 | 689 | } |
| 680 | chalk_ir::TyKind::Function(_) => { | |
| 690 | TyKind::FnPtr(..) => { | |
| 681 | 691 | let Some((func, current)) = |
| 682 | 692 | self.lower_expr_to_some_operand(*callee, current)? |
| 683 | 693 | else { |
| ... | ... | @@ -697,7 +707,7 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 697 | 707 | "method resolution not emitted for closure (Are Fn traits available?)" |
| 698 | 708 | ); |
| 699 | 709 | } |
| 700 | TyKind::Error => { | |
| 710 | TyKind::Error(_) => { | |
| 701 | 711 | Err(MirLowerError::MissingFunctionDefinition(self.owner, expr_id)) |
| 702 | 712 | } |
| 703 | 713 | _ => Err(MirLowerError::TypeError("function call on bad type")), |
| ... | ... | @@ -858,8 +868,8 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 858 | 868 | ), |
| 859 | 869 | None => MirLowerError::RecordLiteralWithoutPath, |
| 860 | 870 | })?; |
| 861 | let subst = match self.expr_ty_without_adjust(expr_id).kind(Interner) { | |
| 862 | TyKind::Adt(_, s) => s.clone(), | |
| 871 | let subst = match self.expr_ty_without_adjust(expr_id).kind() { | |
| 872 | TyKind::Adt(_, s) => s, | |
| 863 | 873 | _ => not_supported!("Non ADT record literal"), |
| 864 | 874 | }; |
| 865 | 875 | let variant_fields = variant_id.fields(self.db); |
| ... | ... | @@ -948,12 +958,12 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 948 | 958 | let rvalue = if self.infer.coercion_casts.contains(expr) { |
| 949 | 959 | Rvalue::Use(it) |
| 950 | 960 | } else { |
| 951 | let source_ty = self.infer[*expr].clone(); | |
| 952 | let target_ty = self.infer[expr_id].clone(); | |
| 961 | let source_ty = self.infer[*expr]; | |
| 962 | let target_ty = self.infer[expr_id]; | |
| 953 | 963 | let cast_kind = if source_ty.as_reference().is_some() { |
| 954 | 964 | CastKind::PointerCoercion(PointerCast::ArrayToPointer) |
| 955 | 965 | } else { |
| 956 | cast_kind(self.db, &source_ty, &target_ty)? | |
| 966 | cast_kind(self.db, source_ty, target_ty)? | |
| 957 | 967 | }; |
| 958 | 968 | |
| 959 | 969 | Rvalue::Cast(cast_kind, it, target_ty) |
| ... | ... | @@ -1030,8 +1040,8 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1030 | 1040 | let lhs_ty = self.expr_ty_without_adjust(*lhs); |
| 1031 | 1041 | let rhs_ty = self.expr_ty_without_adjust(*rhs); |
| 1032 | 1042 | if matches!(op, BinaryOp::CmpOp(syntax::ast::CmpOp::Eq { .. })) |
| 1033 | && lhs_ty.as_raw_ptr().is_some() | |
| 1034 | && rhs_ty.as_raw_ptr().is_some() | |
| 1043 | && matches!(lhs_ty.kind(), TyKind::RawPtr(..)) | |
| 1044 | && matches!(rhs_ty.kind(), TyKind::RawPtr(..)) | |
| 1035 | 1045 | { |
| 1036 | 1046 | break 'b true; |
| 1037 | 1047 | } |
| ... | ... | @@ -1040,9 +1050,21 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1040 | 1050 | BinaryOp::ArithOp(ArithOp::Shl | ArithOp::Shr) |
| 1041 | 1051 | | BinaryOp::Assignment { op: Some(ArithOp::Shl | ArithOp::Shr) } |
| 1042 | 1052 | ); |
| 1043 | lhs_ty.is_scalar() | |
| 1044 | && rhs_ty.is_scalar() | |
| 1045 | && (lhs_ty == rhs_ty || builtin_inequal_impls) | |
| 1053 | matches!( | |
| 1054 | lhs_ty.kind(), | |
| 1055 | TyKind::Bool | |
| 1056 | | TyKind::Char | |
| 1057 | | TyKind::Int(_) | |
| 1058 | | TyKind::Uint(_) | |
| 1059 | | TyKind::Float(_) | |
| 1060 | ) && matches!( | |
| 1061 | rhs_ty.kind(), | |
| 1062 | TyKind::Bool | |
| 1063 | | TyKind::Char | |
| 1064 | | TyKind::Int(_) | |
| 1065 | | TyKind::Uint(_) | |
| 1066 | | TyKind::Float(_) | |
| 1067 | ) && (lhs_ty == rhs_ty || builtin_inequal_impls) | |
| 1046 | 1068 | }; |
| 1047 | 1069 | if !is_builtin |
| 1048 | 1070 | && let Some((func_id, generic_args)) = self.infer.method_resolution(expr_id) |
| ... | ... | @@ -1180,7 +1202,7 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1180 | 1202 | current, |
| 1181 | 1203 | place, |
| 1182 | 1204 | Rvalue::Aggregate( |
| 1183 | AggregateKind::Adt(st.into(), subst.clone()), | |
| 1205 | AggregateKind::Adt(st.into(), subst), | |
| 1184 | 1206 | st.fields(self.db) |
| 1185 | 1207 | .fields() |
| 1186 | 1208 | .iter() |
| ... | ... | @@ -1188,14 +1210,15 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1188 | 1210 | let o = match it.1.name.as_str() { |
| 1189 | 1211 | "start" => lp.take(), |
| 1190 | 1212 | "end" => rp.take(), |
| 1191 | "exhausted" => { | |
| 1192 | Some(Operand::from_bytes(Box::new([0]), TyBuilder::bool())) | |
| 1193 | } | |
| 1213 | "exhausted" => Some(Operand::from_bytes( | |
| 1214 | Box::new([0]), | |
| 1215 | Ty::new_bool(self.interner()), | |
| 1216 | )), | |
| 1194 | 1217 | _ => None, |
| 1195 | 1218 | }; |
| 1196 | 1219 | o.ok_or(MirLowerError::UnresolvedField) |
| 1197 | 1220 | }) |
| 1198 | .collect::<Result<_>>()?, | |
| 1221 | .collect::<Result<'_, _>>()?, | |
| 1199 | 1222 | ), |
| 1200 | 1223 | expr_id.into(), |
| 1201 | 1224 | ); |
| ... | ... | @@ -1203,11 +1226,11 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1203 | 1226 | } |
| 1204 | 1227 | Expr::Closure { .. } => { |
| 1205 | 1228 | let ty = self.expr_ty_without_adjust(expr_id); |
| 1206 | let TyKind::Closure(id, _) = ty.kind(Interner) else { | |
| 1229 | let TyKind::Closure(id, _) = ty.kind() else { | |
| 1207 | 1230 | not_supported!("closure with non closure type"); |
| 1208 | 1231 | }; |
| 1209 | self.result.closures.push(*id); | |
| 1210 | let (captures, _) = self.infer.closure_info(id); | |
| 1232 | self.result.closures.push(id.0); | |
| 1233 | let (captures, _) = self.infer.closure_info(id.0); | |
| 1211 | 1234 | let mut operands = vec![]; |
| 1212 | 1235 | for capture in captures.iter() { |
| 1213 | 1236 | let p = Place { |
| ... | ... | @@ -1241,12 +1264,11 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1241 | 1264 | }; |
| 1242 | 1265 | match &capture.kind { |
| 1243 | 1266 | CaptureKind::ByRef(bk) => { |
| 1244 | let placeholder_subst = self.placeholder_subst(); | |
| 1245 | let tmp_ty = | |
| 1246 | capture.ty.clone().substitute(Interner, &placeholder_subst); | |
| 1267 | let tmp_ty = capture.ty.instantiate_identity(); | |
| 1247 | 1268 | // FIXME: Handle more than one span. |
| 1248 | 1269 | let capture_spans = capture.spans(); |
| 1249 | let tmp: Place = self.temp(tmp_ty, current, capture_spans[0])?.into(); | |
| 1270 | let tmp: Place<'db> = | |
| 1271 | self.temp(tmp_ty, current, capture_spans[0])?.into(); | |
| 1250 | 1272 | self.push_assignment( |
| 1251 | 1273 | current, |
| 1252 | 1274 | tmp, |
| ... | ... | @@ -1278,7 +1300,7 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1278 | 1300 | current = c; |
| 1279 | 1301 | Ok(Some(o)) |
| 1280 | 1302 | }) |
| 1281 | .collect::<Result<Option<_>>>()? | |
| 1303 | .collect::<Result<'_, Option<_>>>()? | |
| 1282 | 1304 | else { |
| 1283 | 1305 | return Ok(None); |
| 1284 | 1306 | }; |
| ... | ... | @@ -1291,8 +1313,8 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1291 | 1313 | } |
| 1292 | 1314 | Expr::Array(l) => match l { |
| 1293 | 1315 | Array::ElementList { elements, .. } => { |
| 1294 | let elem_ty = match &self.expr_ty_without_adjust(expr_id).kind(Interner) { | |
| 1295 | TyKind::Array(ty, _) => ty.clone(), | |
| 1316 | let elem_ty = match self.expr_ty_without_adjust(expr_id).kind() { | |
| 1317 | TyKind::Array(ty, _) => ty, | |
| 1296 | 1318 | _ => { |
| 1297 | 1319 | return Err(MirLowerError::TypeError( |
| 1298 | 1320 | "Array expression with non array type", |
| ... | ... | @@ -1309,7 +1331,7 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1309 | 1331 | current = c; |
| 1310 | 1332 | Ok(Some(o)) |
| 1311 | 1333 | }) |
| 1312 | .collect::<Result<Option<_>>>()? | |
| 1334 | .collect::<Result<'_, Option<_>>>()? | |
| 1313 | 1335 | else { |
| 1314 | 1336 | return Ok(None); |
| 1315 | 1337 | }; |
| ... | ... | @@ -1323,8 +1345,8 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1323 | 1345 | else { |
| 1324 | 1346 | return Ok(None); |
| 1325 | 1347 | }; |
| 1326 | let len = match &self.expr_ty_without_adjust(expr_id).kind(Interner) { | |
| 1327 | TyKind::Array(_, len) => len.clone(), | |
| 1348 | let len = match self.expr_ty_without_adjust(expr_id).kind() { | |
| 1349 | TyKind::Array(_, len) => len, | |
| 1328 | 1350 | _ => { |
| 1329 | 1351 | return Err(MirLowerError::TypeError( |
| 1330 | 1352 | "Array repeat expression with non array type", |
| ... | ... | @@ -1346,16 +1368,13 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1346 | 1368 | } |
| 1347 | 1369 | } |
| 1348 | 1370 | |
| 1349 | fn placeholder_subst(&mut self) -> Substitution { | |
| 1350 | match self.owner.as_generic_def_id(self.db) { | |
| 1351 | Some(it) => TyBuilder::placeholder_subst(self.db, it), | |
| 1352 | None => Substitution::empty(Interner), | |
| 1353 | } | |
| 1354 | } | |
| 1355 | ||
| 1356 | fn push_field_projection(&mut self, place: &mut Place, expr_id: ExprId) -> Result<()> { | |
| 1371 | fn push_field_projection( | |
| 1372 | &mut self, | |
| 1373 | place: &mut Place<'db>, | |
| 1374 | expr_id: ExprId, | |
| 1375 | ) -> Result<'db, ()> { | |
| 1357 | 1376 | if let Expr::Field { expr, name } = &self.body[expr_id] { |
| 1358 | if let TyKind::Tuple(..) = self.expr_ty_after_adjustments(*expr).kind(Interner) { | |
| 1377 | if let TyKind::Tuple(..) = self.expr_ty_after_adjustments(*expr).kind() { | |
| 1359 | 1378 | let index = |
| 1360 | 1379 | name.as_tuple_index().ok_or(MirLowerError::TypeError("named field on tuple"))? |
| 1361 | 1380 | as u32; |
| ... | ... | @@ -1378,7 +1397,11 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1378 | 1397 | Ok(()) |
| 1379 | 1398 | } |
| 1380 | 1399 | |
| 1381 | fn lower_literal_or_const_to_operand(&mut self, ty: Ty, loc: &ExprId) -> Result<Operand> { | |
| 1400 | fn lower_literal_or_const_to_operand( | |
| 1401 | &mut self, | |
| 1402 | ty: Ty<'db>, | |
| 1403 | loc: &ExprId, | |
| 1404 | ) -> Result<'db, Operand<'db>> { | |
| 1382 | 1405 | match &self.body[*loc] { |
| 1383 | 1406 | Expr::Literal(l) => self.lower_literal_to_operand(ty, l), |
| 1384 | 1407 | Expr::Path(c) => { |
| ... | ... | @@ -1399,7 +1422,10 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1399 | 1422 | match pr { |
| 1400 | 1423 | ResolveValueResult::ValueNs(v, _) => { |
| 1401 | 1424 | if let ValueNs::ConstId(c) = v { |
| 1402 | self.lower_const_to_operand(Substitution::empty(Interner), c.into(), ty) | |
| 1425 | self.lower_const_to_operand( | |
| 1426 | GenericArgs::new_from_iter(self.interner(), []), | |
| 1427 | c.into(), | |
| 1428 | ) | |
| 1403 | 1429 | } else { |
| 1404 | 1430 | not_supported!("bad path in range pattern"); |
| 1405 | 1431 | } |
| ... | ... | @@ -1415,13 +1441,8 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1415 | 1441 | } |
| 1416 | 1442 | } |
| 1417 | 1443 | |
| 1418 | fn lower_literal_to_operand(&mut self, ty: Ty, l: &Literal) -> Result<Operand> { | |
| 1419 | let interner = DbInterner::new_with(self.db, None, None); | |
| 1420 | let size = || { | |
| 1421 | self.db | |
| 1422 | .layout_of_ty(ty.to_nextsolver(interner), self.env.clone()) | |
| 1423 | .map(|it| it.size.bytes_usize()) | |
| 1424 | }; | |
| 1444 | fn lower_literal_to_operand(&mut self, ty: Ty<'db>, l: &Literal) -> Result<'db, Operand<'db>> { | |
| 1445 | let size = || self.db.layout_of_ty(ty, self.env.clone()).map(|it| it.size.bytes_usize()); | |
| 1425 | 1446 | const USIZE_SIZE: usize = size_of::<usize>(); |
| 1426 | 1447 | let bytes: Box<[_]> = match l { |
| 1427 | 1448 | hir_def::hir::Literal::String(b) => { |
| ... | ... | @@ -1467,50 +1488,59 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1467 | 1488 | Ok(Operand::from_concrete_const(bytes, MemoryMap::default(), ty)) |
| 1468 | 1489 | } |
| 1469 | 1490 | |
| 1470 | fn new_basic_block(&mut self) -> BasicBlockId { | |
| 1491 | fn new_basic_block(&mut self) -> BasicBlockId<'db> { | |
| 1471 | 1492 | self.result.basic_blocks.alloc(BasicBlock::default()) |
| 1472 | 1493 | } |
| 1473 | 1494 | |
| 1474 | 1495 | fn lower_const( |
| 1475 | 1496 | &mut self, |
| 1476 | 1497 | const_id: GeneralConstId, |
| 1477 | prev_block: BasicBlockId, | |
| 1478 | place: Place, | |
| 1479 | subst: Substitution, | |
| 1498 | prev_block: BasicBlockId<'db>, | |
| 1499 | place: Place<'db>, | |
| 1500 | subst: GenericArgs<'db>, | |
| 1480 | 1501 | span: MirSpan, |
| 1481 | ty: Ty, | |
| 1482 | ) -> Result<()> { | |
| 1483 | let c = self.lower_const_to_operand(subst, const_id, ty)?; | |
| 1502 | ) -> Result<'db, ()> { | |
| 1503 | let c = self.lower_const_to_operand(subst, const_id)?; | |
| 1484 | 1504 | self.push_assignment(prev_block, place, c.into(), span); |
| 1485 | 1505 | Ok(()) |
| 1486 | 1506 | } |
| 1487 | 1507 | |
| 1488 | 1508 | fn lower_const_to_operand( |
| 1489 | 1509 | &mut self, |
| 1490 | subst: Substitution, | |
| 1510 | subst: GenericArgs<'db>, | |
| 1491 | 1511 | const_id: GeneralConstId, |
| 1492 | ty: Ty, | |
| 1493 | ) -> Result<Operand> { | |
| 1494 | let c = if subst.len(Interner) != 0 { | |
| 1512 | ) -> Result<'db, Operand<'db>> { | |
| 1513 | let konst = if subst.len() != 0 { | |
| 1495 | 1514 | // We can't evaluate constant with substitution now, as generics are not monomorphized in lowering. |
| 1496 | intern_const_scalar(ConstScalar::UnevaluatedConst(const_id, subst), ty) | |
| 1515 | Const::new_unevaluated( | |
| 1516 | self.interner(), | |
| 1517 | UnevaluatedConst { def: const_id.into(), args: subst }, | |
| 1518 | ) | |
| 1497 | 1519 | } else { |
| 1498 | 1520 | let name = const_id.name(self.db); |
| 1499 | 1521 | self.db |
| 1500 | 1522 | .const_eval(const_id, subst, None) |
| 1501 | 1523 | .map_err(|e| MirLowerError::ConstEvalError(name.into(), Box::new(e)))? |
| 1502 | 1524 | }; |
| 1503 | Ok(Operand { kind: OperandKind::Constant(c), span: None }) | |
| 1525 | let ty = self | |
| 1526 | .db | |
| 1527 | .value_ty(match const_id { | |
| 1528 | GeneralConstId::ConstId(id) => id.into(), | |
| 1529 | GeneralConstId::StaticId(id) => id.into(), | |
| 1530 | }) | |
| 1531 | .unwrap() | |
| 1532 | .instantiate(self.interner(), subst); | |
| 1533 | Ok(Operand { kind: OperandKind::Constant { konst, ty }, span: None }) | |
| 1504 | 1534 | } |
| 1505 | 1535 | |
| 1506 | 1536 | fn write_bytes_to_place( |
| 1507 | 1537 | &mut self, |
| 1508 | prev_block: BasicBlockId, | |
| 1509 | place: Place, | |
| 1538 | prev_block: BasicBlockId<'db>, | |
| 1539 | place: Place<'db>, | |
| 1510 | 1540 | cv: Box<[u8]>, |
| 1511 | ty: Ty, | |
| 1541 | ty: Ty<'db>, | |
| 1512 | 1542 | span: MirSpan, |
| 1513 | ) -> Result<()> { | |
| 1543 | ) -> Result<'db, ()> { | |
| 1514 | 1544 | self.push_assignment(prev_block, place, Operand::from_bytes(cv, ty).into(), span); |
| 1515 | 1545 | Ok(()) |
| 1516 | 1546 | } |
| ... | ... | @@ -1518,14 +1548,14 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1518 | 1548 | fn lower_enum_variant( |
| 1519 | 1549 | &mut self, |
| 1520 | 1550 | variant_id: EnumVariantId, |
| 1521 | prev_block: BasicBlockId, | |
| 1522 | place: Place, | |
| 1523 | ty: Ty, | |
| 1524 | fields: Box<[Operand]>, | |
| 1551 | prev_block: BasicBlockId<'db>, | |
| 1552 | place: Place<'db>, | |
| 1553 | ty: Ty<'db>, | |
| 1554 | fields: Box<[Operand<'db>]>, | |
| 1525 | 1555 | span: MirSpan, |
| 1526 | ) -> Result<BasicBlockId> { | |
| 1527 | let subst = match ty.kind(Interner) { | |
| 1528 | TyKind::Adt(_, subst) => subst.clone(), | |
| 1556 | ) -> Result<'db, BasicBlockId<'db>> { | |
| 1557 | let subst = match ty.kind() { | |
| 1558 | TyKind::Adt(_, subst) => subst, | |
| 1529 | 1559 | _ => implementation_error!("Non ADT enum"), |
| 1530 | 1560 | }; |
| 1531 | 1561 | self.push_assignment( |
| ... | ... | @@ -1539,13 +1569,13 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1539 | 1569 | |
| 1540 | 1570 | fn lower_call_and_args( |
| 1541 | 1571 | &mut self, |
| 1542 | func: Operand, | |
| 1572 | func: Operand<'db>, | |
| 1543 | 1573 | args: impl Iterator<Item = ExprId>, |
| 1544 | place: Place, | |
| 1545 | mut current: BasicBlockId, | |
| 1574 | place: Place<'db>, | |
| 1575 | mut current: BasicBlockId<'db>, | |
| 1546 | 1576 | is_uninhabited: bool, |
| 1547 | 1577 | span: MirSpan, |
| 1548 | ) -> Result<Option<BasicBlockId>> { | |
| 1578 | ) -> Result<'db, Option<BasicBlockId<'db>>> { | |
| 1549 | 1579 | let Some(args) = args |
| 1550 | 1580 | .map(|arg| { |
| 1551 | 1581 | if let Some((temp, c)) = self.lower_expr_to_some_operand(arg, current)? { |
| ... | ... | @@ -1555,7 +1585,7 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1555 | 1585 | Ok(None) |
| 1556 | 1586 | } |
| 1557 | 1587 | }) |
| 1558 | .collect::<Result<Option<Vec<_>>>>()? | |
| 1588 | .collect::<Result<'_, Option<Vec<_>>>>()? | |
| 1559 | 1589 | else { |
| 1560 | 1590 | return Ok(None); |
| 1561 | 1591 | }; |
| ... | ... | @@ -1564,13 +1594,13 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1564 | 1594 | |
| 1565 | 1595 | fn lower_call( |
| 1566 | 1596 | &mut self, |
| 1567 | func: Operand, | |
| 1568 | args: Box<[Operand]>, | |
| 1569 | place: Place, | |
| 1570 | current: BasicBlockId, | |
| 1597 | func: Operand<'db>, | |
| 1598 | args: Box<[Operand<'db>]>, | |
| 1599 | place: Place<'db>, | |
| 1600 | current: BasicBlockId<'db>, | |
| 1571 | 1601 | is_uninhabited: bool, |
| 1572 | 1602 | span: MirSpan, |
| 1573 | ) -> Result<Option<BasicBlockId>> { | |
| 1603 | ) -> Result<'db, Option<BasicBlockId<'db>>> { | |
| 1574 | 1604 | let b = if is_uninhabited { None } else { Some(self.new_basic_block()) }; |
| 1575 | 1605 | self.set_terminator( |
| 1576 | 1606 | current, |
| ... | ... | @@ -1587,56 +1617,63 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1587 | 1617 | Ok(b) |
| 1588 | 1618 | } |
| 1589 | 1619 | |
| 1590 | fn is_unterminated(&mut self, source: BasicBlockId) -> bool { | |
| 1620 | fn is_unterminated(&mut self, source: BasicBlockId<'db>) -> bool { | |
| 1591 | 1621 | self.result.basic_blocks[source].terminator.is_none() |
| 1592 | 1622 | } |
| 1593 | 1623 | |
| 1594 | fn set_terminator(&mut self, source: BasicBlockId, terminator: TerminatorKind, span: MirSpan) { | |
| 1624 | fn set_terminator( | |
| 1625 | &mut self, | |
| 1626 | source: BasicBlockId<'db>, | |
| 1627 | terminator: TerminatorKind<'db>, | |
| 1628 | span: MirSpan, | |
| 1629 | ) { | |
| 1595 | 1630 | self.result.basic_blocks[source].terminator = Some(Terminator { span, kind: terminator }); |
| 1596 | 1631 | } |
| 1597 | 1632 | |
| 1598 | fn set_goto(&mut self, source: BasicBlockId, target: BasicBlockId, span: MirSpan) { | |
| 1633 | fn set_goto(&mut self, source: BasicBlockId<'db>, target: BasicBlockId<'db>, span: MirSpan) { | |
| 1599 | 1634 | self.set_terminator(source, TerminatorKind::Goto { target }, span); |
| 1600 | 1635 | } |
| 1601 | 1636 | |
| 1602 | fn expr_ty_without_adjust(&self, e: ExprId) -> Ty { | |
| 1603 | self.infer[e].clone() | |
| 1637 | fn expr_ty_without_adjust(&self, e: ExprId) -> Ty<'db> { | |
| 1638 | self.infer[e] | |
| 1604 | 1639 | } |
| 1605 | 1640 | |
| 1606 | fn expr_ty_after_adjustments(&self, e: ExprId) -> Ty { | |
| 1641 | fn expr_ty_after_adjustments(&self, e: ExprId) -> Ty<'db> { | |
| 1607 | 1642 | let mut ty = None; |
| 1608 | 1643 | if let Some(it) = self.infer.expr_adjustments.get(&e) |
| 1609 | 1644 | && let Some(it) = it.last() |
| 1610 | 1645 | { |
| 1611 | ty = Some(it.target.clone()); | |
| 1646 | ty = Some(it.target); | |
| 1612 | 1647 | } |
| 1613 | 1648 | ty.unwrap_or_else(|| self.expr_ty_without_adjust(e)) |
| 1614 | 1649 | } |
| 1615 | 1650 | |
| 1616 | fn push_statement(&mut self, block: BasicBlockId, statement: Statement) { | |
| 1651 | fn push_statement(&mut self, block: BasicBlockId<'db>, statement: Statement<'db>) { | |
| 1617 | 1652 | self.result.basic_blocks[block].statements.push(statement); |
| 1618 | 1653 | } |
| 1619 | 1654 | |
| 1620 | fn push_fake_read(&mut self, block: BasicBlockId, p: Place, span: MirSpan) { | |
| 1655 | fn push_fake_read(&mut self, block: BasicBlockId<'db>, p: Place<'db>, span: MirSpan) { | |
| 1621 | 1656 | self.push_statement(block, StatementKind::FakeRead(p).with_span(span)); |
| 1622 | 1657 | } |
| 1623 | 1658 | |
| 1624 | 1659 | fn push_assignment( |
| 1625 | 1660 | &mut self, |
| 1626 | block: BasicBlockId, | |
| 1627 | place: Place, | |
| 1628 | rvalue: Rvalue, | |
| 1661 | block: BasicBlockId<'db>, | |
| 1662 | place: Place<'db>, | |
| 1663 | rvalue: Rvalue<'db>, | |
| 1629 | 1664 | span: MirSpan, |
| 1630 | 1665 | ) { |
| 1631 | 1666 | self.push_statement(block, StatementKind::Assign(place, rvalue).with_span(span)); |
| 1632 | 1667 | } |
| 1633 | 1668 | |
| 1634 | fn discr_temp_place(&mut self, current: BasicBlockId) -> Place { | |
| 1669 | fn discr_temp_place(&mut self, current: BasicBlockId<'db>) -> Place<'db> { | |
| 1635 | 1670 | match &self.discr_temp { |
| 1636 | 1671 | Some(it) => *it, |
| 1637 | 1672 | None => { |
| 1638 | let tmp: Place = self | |
| 1639 | .temp(TyBuilder::discr_ty(), current, MirSpan::Unknown) | |
| 1673 | // FIXME: rustc's ty is dependent on the adt type, maybe we need to do that as well | |
| 1674 | let discr_ty = Ty::new_int(self.interner(), rustc_type_ir::IntTy::I128); | |
| 1675 | let tmp: Place<'db> = self | |
| 1676 | .temp(discr_ty, current, MirSpan::Unknown) | |
| 1640 | 1677 | .expect("discr_ty is never unsized") |
| 1641 | 1678 | .into(); |
| 1642 | 1679 | self.discr_temp = Some(tmp); |
| ... | ... | @@ -1647,12 +1684,12 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1647 | 1684 | |
| 1648 | 1685 | fn lower_loop( |
| 1649 | 1686 | &mut self, |
| 1650 | prev_block: BasicBlockId, | |
| 1651 | place: Place, | |
| 1687 | prev_block: BasicBlockId<'db>, | |
| 1688 | place: Place<'db>, | |
| 1652 | 1689 | label: Option<LabelId>, |
| 1653 | 1690 | span: MirSpan, |
| 1654 | f: impl FnOnce(&mut MirLowerCtx<'_>, BasicBlockId) -> Result<()>, | |
| 1655 | ) -> Result<Option<BasicBlockId>> { | |
| 1691 | f: impl FnOnce(&mut MirLowerCtx<'_, 'db>, BasicBlockId<'db>) -> Result<'db, ()>, | |
| 1692 | ) -> Result<'db, Option<BasicBlockId<'db>>> { | |
| 1656 | 1693 | let begin = self.new_basic_block(); |
| 1657 | 1694 | let prev = self.current_loop_blocks.replace(LoopBlocks { |
| 1658 | 1695 | begin, |
| ... | ... | @@ -1687,10 +1724,10 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1687 | 1724 | |
| 1688 | 1725 | fn merge_blocks( |
| 1689 | 1726 | &mut self, |
| 1690 | b1: Option<BasicBlockId>, | |
| 1691 | b2: Option<BasicBlockId>, | |
| 1727 | b1: Option<BasicBlockId<'db>>, | |
| 1728 | b2: Option<BasicBlockId<'db>>, | |
| 1692 | 1729 | span: MirSpan, |
| 1693 | ) -> Option<BasicBlockId> { | |
| 1730 | ) -> Option<BasicBlockId<'db>> { | |
| 1694 | 1731 | match (b1, b2) { |
| 1695 | 1732 | (None, None) => None, |
| 1696 | 1733 | (None, Some(b)) | (Some(b), None) => Some(b), |
| ... | ... | @@ -1703,7 +1740,7 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1703 | 1740 | } |
| 1704 | 1741 | } |
| 1705 | 1742 | |
| 1706 | fn current_loop_end(&mut self) -> Result<BasicBlockId> { | |
| 1743 | fn current_loop_end(&mut self) -> Result<'db, BasicBlockId<'db>> { | |
| 1707 | 1744 | let r = match self |
| 1708 | 1745 | .current_loop_blocks |
| 1709 | 1746 | .as_mut() |
| ... | ... | @@ -1730,7 +1767,7 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1730 | 1767 | fn is_uninhabited(&self, expr_id: ExprId) -> bool { |
| 1731 | 1768 | is_ty_uninhabited_from( |
| 1732 | 1769 | self.db, |
| 1733 | &self.infer[expr_id], | |
| 1770 | &self.infer[expr_id].to_chalk(self.interner()), | |
| 1734 | 1771 | self.owner.module(self.db), |
| 1735 | 1772 | self.env.clone(), |
| 1736 | 1773 | ) |
| ... | ... | @@ -1738,23 +1775,23 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1738 | 1775 | |
| 1739 | 1776 | /// This function push `StorageLive` statement for the binding, and applies changes to add `StorageDead` and |
| 1740 | 1777 | /// `Drop` in the appropriated places. |
| 1741 | fn push_storage_live(&mut self, b: BindingId, current: BasicBlockId) -> Result<()> { | |
| 1778 | fn push_storage_live(&mut self, b: BindingId, current: BasicBlockId<'db>) -> Result<'db, ()> { | |
| 1742 | 1779 | let l = self.binding_local(b)?; |
| 1743 | 1780 | self.push_storage_live_for_local(l, current, MirSpan::BindingId(b)) |
| 1744 | 1781 | } |
| 1745 | 1782 | |
| 1746 | 1783 | fn push_storage_live_for_local( |
| 1747 | 1784 | &mut self, |
| 1748 | l: LocalId, | |
| 1749 | current: BasicBlockId, | |
| 1785 | l: LocalId<'db>, | |
| 1786 | current: BasicBlockId<'db>, | |
| 1750 | 1787 | span: MirSpan, |
| 1751 | ) -> Result<()> { | |
| 1788 | ) -> Result<'db, ()> { | |
| 1752 | 1789 | self.drop_scopes.last_mut().unwrap().locals.push(l); |
| 1753 | 1790 | self.push_statement(current, StatementKind::StorageLive(l).with_span(span)); |
| 1754 | 1791 | Ok(()) |
| 1755 | 1792 | } |
| 1756 | 1793 | |
| 1757 | fn resolve_lang_item(&self, item: LangItem) -> Result<LangItemTarget> { | |
| 1794 | fn resolve_lang_item(&self, item: LangItem) -> Result<'db, LangItemTarget> { | |
| 1758 | 1795 | let crate_id = self.owner.module(self.db).krate(); |
| 1759 | 1796 | lang_item(self.db, crate_id, item).ok_or(MirLowerError::LangItemNotFound(item)) |
| 1760 | 1797 | } |
| ... | ... | @@ -1762,11 +1799,11 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1762 | 1799 | fn lower_block_to_place( |
| 1763 | 1800 | &mut self, |
| 1764 | 1801 | statements: &[hir_def::hir::Statement], |
| 1765 | mut current: BasicBlockId, | |
| 1802 | mut current: BasicBlockId<'db>, | |
| 1766 | 1803 | tail: Option<ExprId>, |
| 1767 | place: Place, | |
| 1804 | place: Place<'db>, | |
| 1768 | 1805 | span: MirSpan, |
| 1769 | ) -> Result<Option<Idx<BasicBlock>>> { | |
| 1806 | ) -> Result<'db, Option<Idx<BasicBlock<'db>>>> { | |
| 1770 | 1807 | let scope = self.push_drop_scope(); |
| 1771 | 1808 | for statement in statements.iter() { |
| 1772 | 1809 | match statement { |
| ... | ... | @@ -1839,10 +1876,10 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1839 | 1876 | |
| 1840 | 1877 | fn lower_params_and_bindings( |
| 1841 | 1878 | &mut self, |
| 1842 | params: impl Iterator<Item = (PatId, Ty)> + Clone, | |
| 1843 | self_binding: Option<(BindingId, Ty)>, | |
| 1879 | params: impl Iterator<Item = (PatId, Ty<'db>)> + Clone, | |
| 1880 | self_binding: Option<(BindingId, Ty<'db>)>, | |
| 1844 | 1881 | pick_binding: impl Fn(BindingId) -> bool, |
| 1845 | ) -> Result<BasicBlockId> { | |
| 1882 | ) -> Result<'db, BasicBlockId<'db>> { | |
| 1846 | 1883 | let base_param_count = self.result.param_locals.len(); |
| 1847 | 1884 | let self_binding = match self_binding { |
| 1848 | 1885 | Some((self_binding, ty)) => { |
| ... | ... | @@ -1875,7 +1912,7 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1875 | 1912 | if !self.result.binding_locals.contains_idx(id) { |
| 1876 | 1913 | self.result |
| 1877 | 1914 | .binding_locals |
| 1878 | .insert(id, self.result.locals.alloc(Local { ty: self.infer[id].clone() })); | |
| 1915 | .insert(id, self.result.locals.alloc(Local { ty: self.infer[id] })); | |
| 1879 | 1916 | } |
| 1880 | 1917 | } |
| 1881 | 1918 | let mut current = self.result.start_block; |
| ... | ... | @@ -1910,7 +1947,7 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1910 | 1947 | Ok(current) |
| 1911 | 1948 | } |
| 1912 | 1949 | |
| 1913 | fn binding_local(&self, b: BindingId) -> Result<LocalId> { | |
| 1950 | fn binding_local(&self, b: BindingId) -> Result<'db, LocalId<'db>> { | |
| 1914 | 1951 | match self.result.binding_locals.get(b) { |
| 1915 | 1952 | Some(it) => Ok(*it), |
| 1916 | 1953 | None => { |
| ... | ... | @@ -1922,7 +1959,7 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1922 | 1959 | } |
| 1923 | 1960 | } |
| 1924 | 1961 | |
| 1925 | fn const_eval_discriminant(&self, variant: EnumVariantId) -> Result<i128> { | |
| 1962 | fn const_eval_discriminant(&self, variant: EnumVariantId) -> Result<'db, i128> { | |
| 1926 | 1963 | let r = self.db.const_eval_discriminant(variant); |
| 1927 | 1964 | match r { |
| 1928 | 1965 | Ok(r) => Ok(r), |
| ... | ... | @@ -1959,9 +1996,9 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1959 | 1996 | fn drop_until_scope( |
| 1960 | 1997 | &mut self, |
| 1961 | 1998 | scope_index: usize, |
| 1962 | mut current: BasicBlockId, | |
| 1999 | mut current: BasicBlockId<'db>, | |
| 1963 | 2000 | span: MirSpan, |
| 1964 | ) -> BasicBlockId { | |
| 2001 | ) -> BasicBlockId<'db> { | |
| 1965 | 2002 | for scope in self.drop_scopes[scope_index..].to_vec().iter().rev() { |
| 1966 | 2003 | self.emit_drop_and_storage_dead_for_scope(scope, &mut current, span); |
| 1967 | 2004 | } |
| ... | ... | @@ -1981,9 +2018,9 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1981 | 2018 | /// Don't call directly |
| 1982 | 2019 | fn pop_drop_scope_internal( |
| 1983 | 2020 | &mut self, |
| 1984 | mut current: BasicBlockId, | |
| 2021 | mut current: BasicBlockId<'db>, | |
| 1985 | 2022 | span: MirSpan, |
| 1986 | ) -> BasicBlockId { | |
| 2023 | ) -> BasicBlockId<'db> { | |
| 1987 | 2024 | let scope = self.drop_scopes.pop().unwrap(); |
| 1988 | 2025 | self.emit_drop_and_storage_dead_for_scope(&scope, &mut current, span); |
| 1989 | 2026 | current |
| ... | ... | @@ -1991,9 +2028,9 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 1991 | 2028 | |
| 1992 | 2029 | fn pop_drop_scope_assert_finished( |
| 1993 | 2030 | &mut self, |
| 1994 | mut current: BasicBlockId, | |
| 2031 | mut current: BasicBlockId<'db>, | |
| 1995 | 2032 | span: MirSpan, |
| 1996 | ) -> Result<BasicBlockId> { | |
| 2033 | ) -> Result<'db, BasicBlockId<'db>> { | |
| 1997 | 2034 | current = self.pop_drop_scope_internal(current, span); |
| 1998 | 2035 | if !self.drop_scopes.is_empty() { |
| 1999 | 2036 | implementation_error!("Mismatched count between drop scope push and pops"); |
| ... | ... | @@ -2003,12 +2040,12 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 2003 | 2040 | |
| 2004 | 2041 | fn emit_drop_and_storage_dead_for_scope( |
| 2005 | 2042 | &mut self, |
| 2006 | scope: &DropScope, | |
| 2007 | current: &mut Idx<BasicBlock>, | |
| 2043 | scope: &DropScope<'db>, | |
| 2044 | current: &mut Idx<BasicBlock<'db>>, | |
| 2008 | 2045 | span: MirSpan, |
| 2009 | 2046 | ) { |
| 2010 | 2047 | for &l in scope.locals.iter().rev() { |
| 2011 | if !self.result.locals[l].ty.clone().is_copy(self.db, self.owner) { | |
| 2048 | if !self.infcx.type_is_copy_modulo_regions(self.env.env, self.result.locals[l].ty) { | |
| 2012 | 2049 | let prev = std::mem::replace(current, self.new_basic_block()); |
| 2013 | 2050 | self.set_terminator( |
| 2014 | 2051 | prev, |
| ... | ... | @@ -2021,7 +2058,11 @@ impl<'ctx> MirLowerCtx<'ctx> { |
| 2021 | 2058 | } |
| 2022 | 2059 | } |
| 2023 | 2060 | |
| 2024 | fn cast_kind(db: &dyn HirDatabase, source_ty: &Ty, target_ty: &Ty) -> Result<CastKind> { | |
| 2061 | fn cast_kind<'db>( | |
| 2062 | db: &'db dyn HirDatabase, | |
| 2063 | source_ty: Ty<'db>, | |
| 2064 | target_ty: Ty<'db>, | |
| 2065 | ) -> Result<'db, CastKind> { | |
| 2025 | 2066 | let from = CastTy::from_ty(db, source_ty); |
| 2026 | 2067 | let cast = CastTy::from_ty(db, target_ty); |
| 2027 | 2068 | Ok(match (from, cast) { |
| ... | ... | @@ -2039,41 +2080,49 @@ fn cast_kind(db: &dyn HirDatabase, source_ty: &Ty, target_ty: &Ty) -> Result<Cas |
| 2039 | 2080 | }) |
| 2040 | 2081 | } |
| 2041 | 2082 | |
| 2042 | pub fn mir_body_for_closure_query( | |
| 2043 | db: &dyn HirDatabase, | |
| 2083 | pub fn mir_body_for_closure_query<'db>( | |
| 2084 | db: &'db dyn HirDatabase, | |
| 2044 | 2085 | closure: InternedClosureId, |
| 2045 | ) -> Result<Arc<MirBody>> { | |
| 2086 | ) -> Result<'db, Arc<MirBody<'db>>> { | |
| 2046 | 2087 | let InternedClosure(owner, expr) = db.lookup_intern_closure(closure); |
| 2047 | 2088 | let body = db.body(owner); |
| 2048 | 2089 | let infer = db.infer(owner); |
| 2049 | 2090 | let Expr::Closure { args, body: root, .. } = &body[expr] else { |
| 2050 | 2091 | implementation_error!("closure expression is not closure"); |
| 2051 | 2092 | }; |
| 2052 | let TyKind::Closure(_, substs) = &infer[expr].kind(Interner) else { | |
| 2093 | let crate::next_solver::TyKind::Closure(_, substs) = infer[expr].kind() else { | |
| 2053 | 2094 | implementation_error!("closure expression is not closure"); |
| 2054 | 2095 | }; |
| 2055 | let (captures, kind) = infer.closure_info(&closure.into()); | |
| 2096 | let (captures, kind) = infer.closure_info(closure); | |
| 2056 | 2097 | let mut ctx = MirLowerCtx::new(db, owner, &body, &infer); |
| 2057 | 2098 | // 0 is return local |
| 2058 | ctx.result.locals.alloc(Local { ty: infer[*root].clone() }); | |
| 2099 | ctx.result.locals.alloc(Local { ty: infer[*root] }); | |
| 2059 | 2100 | let closure_local = ctx.result.locals.alloc(Local { |
| 2060 | 2101 | ty: match kind { |
| 2061 | FnTrait::FnOnce | FnTrait::AsyncFnOnce => infer[expr].clone(), | |
| 2062 | FnTrait::FnMut | FnTrait::AsyncFnMut => { | |
| 2063 | TyKind::Ref(Mutability::Mut, error_lifetime(), infer[expr].clone()).intern(Interner) | |
| 2064 | } | |
| 2065 | FnTrait::Fn | FnTrait::AsyncFn => { | |
| 2066 | TyKind::Ref(Mutability::Not, error_lifetime(), infer[expr].clone()).intern(Interner) | |
| 2067 | } | |
| 2102 | FnTrait::FnOnce | FnTrait::AsyncFnOnce => infer[expr], | |
| 2103 | FnTrait::FnMut | FnTrait::AsyncFnMut => Ty::new_ref( | |
| 2104 | ctx.interner(), | |
| 2105 | Region::error(ctx.interner()), | |
| 2106 | infer[expr], | |
| 2107 | Mutability::Mut, | |
| 2108 | ), | |
| 2109 | FnTrait::Fn | FnTrait::AsyncFn => Ty::new_ref( | |
| 2110 | ctx.interner(), | |
| 2111 | Region::error(ctx.interner()), | |
| 2112 | infer[expr], | |
| 2113 | Mutability::Not, | |
| 2114 | ), | |
| 2068 | 2115 | }, |
| 2069 | 2116 | }); |
| 2070 | 2117 | ctx.result.param_locals.push(closure_local); |
| 2071 | let Some(sig) = ClosureSubst(substs).sig_ty(db).callable_sig(db) else { | |
| 2118 | let Some(sig) = | |
| 2119 | substs.split_closure_args_untupled().closure_sig_as_fn_ptr_ty.callable_sig(ctx.interner()) | |
| 2120 | else { | |
| 2072 | 2121 | implementation_error!("closure has not callable sig"); |
| 2073 | 2122 | }; |
| 2074 | 2123 | let resolver_guard = ctx.resolver.update_to_inner_scope(db, owner, expr); |
| 2075 | 2124 | let current = ctx.lower_params_and_bindings( |
| 2076 | args.iter().zip(sig.params().iter()).map(|(it, y)| (*it, y.clone())), | |
| 2125 | args.iter().zip(sig.skip_binder().inputs().iter()).map(|(it, y)| (*it, y)), | |
| 2077 | 2126 | None, |
| 2078 | 2127 | |_| true, |
| 2079 | 2128 | )?; |
| ... | ... | @@ -2082,7 +2131,8 @@ pub fn mir_body_for_closure_query( |
| 2082 | 2131 | let current = ctx.pop_drop_scope_assert_finished(current, root.into())?; |
| 2083 | 2132 | ctx.set_terminator(current, TerminatorKind::Return, (*root).into()); |
| 2084 | 2133 | } |
| 2085 | let mut upvar_map: FxHashMap<LocalId, Vec<(&CapturedItem, usize)>> = FxHashMap::default(); | |
| 2134 | let mut upvar_map: FxHashMap<LocalId<'db>, Vec<(&CapturedItem<'_>, usize)>> = | |
| 2135 | FxHashMap::default(); | |
| 2086 | 2136 | for (i, capture) in captures.iter().enumerate() { |
| 2087 | 2137 | let local = ctx.binding_local(capture.place.local)?; |
| 2088 | 2138 | upvar_map.entry(local).or_default().push((capture, i)); |
| ... | ... | @@ -2144,7 +2194,10 @@ pub fn mir_body_for_closure_query( |
| 2144 | 2194 | Ok(Arc::new(ctx.result)) |
| 2145 | 2195 | } |
| 2146 | 2196 | |
| 2147 | pub fn mir_body_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Result<Arc<MirBody>> { | |
| 2197 | pub fn mir_body_query<'db>( | |
| 2198 | db: &'db dyn HirDatabase, | |
| 2199 | def: DefWithBodyId, | |
| 2200 | ) -> Result<'db, Arc<MirBody<'db>>> { | |
| 2148 | 2201 | let krate = def.krate(db); |
| 2149 | 2202 | let edition = krate.data(db).edition; |
| 2150 | 2203 | let detail = match def { |
| ... | ... | @@ -2177,22 +2230,22 @@ pub fn mir_body_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Result<Arc<Mi |
| 2177 | 2230 | Ok(Arc::new(result)) |
| 2178 | 2231 | } |
| 2179 | 2232 | |
| 2180 | pub(crate) fn mir_body_cycle_result( | |
| 2181 | _db: &dyn HirDatabase, | |
| 2233 | pub(crate) fn mir_body_cycle_result<'db>( | |
| 2234 | _db: &'db dyn HirDatabase, | |
| 2182 | 2235 | _def: DefWithBodyId, |
| 2183 | ) -> Result<Arc<MirBody>> { | |
| 2236 | ) -> Result<'db, Arc<MirBody<'db>>> { | |
| 2184 | 2237 | Err(MirLowerError::Loop) |
| 2185 | 2238 | } |
| 2186 | 2239 | |
| 2187 | pub fn lower_to_mir( | |
| 2188 | db: &dyn HirDatabase, | |
| 2240 | pub fn lower_to_mir<'db>( | |
| 2241 | db: &'db dyn HirDatabase, | |
| 2189 | 2242 | owner: DefWithBodyId, |
| 2190 | 2243 | body: &Body, |
| 2191 | infer: &InferenceResult, | |
| 2244 | infer: &InferenceResult<'db>, | |
| 2192 | 2245 | // FIXME: root_expr should always be the body.body_expr, but since `X` in `[(); X]` doesn't have its own specific body yet, we |
| 2193 | 2246 | // need to take this input explicitly. |
| 2194 | 2247 | root_expr: ExprId, |
| 2195 | ) -> Result<MirBody> { | |
| 2248 | ) -> Result<'db, MirBody<'db>> { | |
| 2196 | 2249 | if infer.type_mismatches().next().is_some() || infer.is_erroneous() { |
| 2197 | 2250 | return Err(MirLowerError::HasErrors); |
| 2198 | 2251 | } |
| ... | ... | @@ -2209,18 +2262,12 @@ pub fn lower_to_mir( |
| 2209 | 2262 | if body.body_expr == root_expr { |
| 2210 | 2263 | // otherwise it's an inline const, and has no parameter |
| 2211 | 2264 | if let DefWithBodyId::FunctionId(fid) = owner { |
| 2212 | let substs = TyBuilder::placeholder_subst(db, fid); | |
| 2213 | let interner = DbInterner::new_with(db, None, None); | |
| 2214 | let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 2215 | let callable_sig = db | |
| 2216 | .callable_item_signature(fid.into()) | |
| 2217 | .instantiate(interner, args) | |
| 2218 | .skip_binder() | |
| 2219 | .to_chalk(interner); | |
| 2220 | let mut params = callable_sig.params().iter(); | |
| 2221 | let self_param = body.self_param.and_then(|id| Some((id, params.next()?.clone()))); | |
| 2265 | let callable_sig = | |
| 2266 | db.callable_item_signature(fid.into()).instantiate_identity().skip_binder(); | |
| 2267 | let mut params = callable_sig.inputs().iter(); | |
| 2268 | let self_param = body.self_param.and_then(|id| Some((id, params.next()?))); | |
| 2222 | 2269 | break 'b ctx.lower_params_and_bindings( |
| 2223 | body.params.iter().zip(params).map(|(it, y)| (*it, y.clone())), | |
| 2270 | body.params.iter().zip(params).map(|(it, y)| (*it, y)), | |
| 2224 | 2271 | self_param, |
| 2225 | 2272 | binding_picker, |
| 2226 | 2273 | )?; |
src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs+68-59| ... | ... | @@ -1,10 +1,14 @@ |
| 1 | 1 | //! MIR lowering for places |
| 2 | 2 | |
| 3 | use crate::mir::{MutBorrowKind, Operand, OperandKind}; | |
| 4 | ||
| 5 | use super::*; | |
| 6 | 3 | use hir_def::FunctionId; |
| 7 | 4 | use intern::sym; |
| 5 | use rustc_type_ir::inherent::{AdtDef, Region as _, Ty as _}; | |
| 6 | ||
| 7 | use super::*; | |
| 8 | use crate::{ | |
| 9 | mir::{MutBorrowKind, Operand, OperandKind}, | |
| 10 | next_solver::Region, | |
| 11 | }; | |
| 8 | 12 | |
| 9 | 13 | macro_rules! not_supported { |
| 10 | 14 | ($it: expr) => { |
| ... | ... | @@ -12,12 +16,12 @@ macro_rules! not_supported { |
| 12 | 16 | }; |
| 13 | 17 | } |
| 14 | 18 | |
| 15 | impl MirLowerCtx<'_> { | |
| 19 | impl<'db> MirLowerCtx<'_, 'db> { | |
| 16 | 20 | fn lower_expr_to_some_place_without_adjust( |
| 17 | 21 | &mut self, |
| 18 | 22 | expr_id: ExprId, |
| 19 | prev_block: BasicBlockId, | |
| 20 | ) -> Result<Option<(Place, BasicBlockId)>> { | |
| 23 | prev_block: BasicBlockId<'db>, | |
| 24 | ) -> Result<'db, Option<(Place<'db>, BasicBlockId<'db>)>> { | |
| 21 | 25 | let ty = self.expr_ty_without_adjust(expr_id); |
| 22 | 26 | let place = self.temp(ty, prev_block, expr_id.into())?; |
| 23 | 27 | let Some(current) = |
| ... | ... | @@ -31,12 +35,12 @@ impl MirLowerCtx<'_> { |
| 31 | 35 | fn lower_expr_to_some_place_with_adjust( |
| 32 | 36 | &mut self, |
| 33 | 37 | expr_id: ExprId, |
| 34 | prev_block: BasicBlockId, | |
| 35 | adjustments: &[Adjustment], | |
| 36 | ) -> Result<Option<(Place, BasicBlockId)>> { | |
| 38 | prev_block: BasicBlockId<'db>, | |
| 39 | adjustments: &[Adjustment<'db>], | |
| 40 | ) -> Result<'db, Option<(Place<'db>, BasicBlockId<'db>)>> { | |
| 37 | 41 | let ty = adjustments |
| 38 | 42 | .last() |
| 39 | .map(|it| it.target.clone()) | |
| 43 | .map(|it| it.target) | |
| 40 | 44 | .unwrap_or_else(|| self.expr_ty_without_adjust(expr_id)); |
| 41 | 45 | let place = self.temp(ty, prev_block, expr_id.into())?; |
| 42 | 46 | let Some(current) = |
| ... | ... | @@ -49,12 +53,12 @@ impl MirLowerCtx<'_> { |
| 49 | 53 | |
| 50 | 54 | pub(super) fn lower_expr_as_place_with_adjust( |
| 51 | 55 | &mut self, |
| 52 | current: BasicBlockId, | |
| 56 | current: BasicBlockId<'db>, | |
| 53 | 57 | expr_id: ExprId, |
| 54 | 58 | upgrade_rvalue: bool, |
| 55 | adjustments: &[Adjustment], | |
| 56 | ) -> Result<Option<(Place, BasicBlockId)>> { | |
| 57 | let try_rvalue = |this: &mut MirLowerCtx<'_>| { | |
| 59 | adjustments: &[Adjustment<'db>], | |
| 60 | ) -> Result<'db, Option<(Place<'db>, BasicBlockId<'db>)>> { | |
| 61 | let try_rvalue = |this: &mut MirLowerCtx<'_, 'db>| { | |
| 58 | 62 | if !upgrade_rvalue { |
| 59 | 63 | return Err(MirLowerError::MutatingRvalue); |
| 60 | 64 | } |
| ... | ... | @@ -89,9 +93,9 @@ impl MirLowerCtx<'_> { |
| 89 | 93 | current, |
| 90 | 94 | r, |
| 91 | 95 | rest.last() |
| 92 | .map(|it| it.target.clone()) | |
| 96 | .map(|it| it.target) | |
| 93 | 97 | .unwrap_or_else(|| self.expr_ty_without_adjust(expr_id)), |
| 94 | last.target.clone(), | |
| 98 | last.target, | |
| 95 | 99 | expr_id.into(), |
| 96 | 100 | match od.0 { |
| 97 | 101 | Some(Mutability::Mut) => true, |
| ... | ... | @@ -111,10 +115,10 @@ impl MirLowerCtx<'_> { |
| 111 | 115 | |
| 112 | 116 | pub(super) fn lower_expr_as_place( |
| 113 | 117 | &mut self, |
| 114 | current: BasicBlockId, | |
| 118 | current: BasicBlockId<'db>, | |
| 115 | 119 | expr_id: ExprId, |
| 116 | 120 | upgrade_rvalue: bool, |
| 117 | ) -> Result<Option<(Place, BasicBlockId)>> { | |
| 121 | ) -> Result<'db, Option<(Place<'db>, BasicBlockId<'db>)>> { | |
| 118 | 122 | match self.infer.expr_adjustments.get(&expr_id) { |
| 119 | 123 | Some(a) => self.lower_expr_as_place_with_adjust(current, expr_id, upgrade_rvalue, a), |
| 120 | 124 | None => self.lower_expr_as_place_without_adjust(current, expr_id, upgrade_rvalue), |
| ... | ... | @@ -123,11 +127,11 @@ impl MirLowerCtx<'_> { |
| 123 | 127 | |
| 124 | 128 | pub(super) fn lower_expr_as_place_without_adjust( |
| 125 | 129 | &mut self, |
| 126 | current: BasicBlockId, | |
| 130 | current: BasicBlockId<'db>, | |
| 127 | 131 | expr_id: ExprId, |
| 128 | 132 | upgrade_rvalue: bool, |
| 129 | ) -> Result<Option<(Place, BasicBlockId)>> { | |
| 130 | let try_rvalue = |this: &mut MirLowerCtx<'_>| { | |
| 133 | ) -> Result<'db, Option<(Place<'db>, BasicBlockId<'db>)>> { | |
| 134 | let try_rvalue = |this: &mut MirLowerCtx<'_, 'db>| { | |
| 131 | 135 | if !upgrade_rvalue { |
| 132 | 136 | return Err(MirLowerError::MutatingRvalue); |
| 133 | 137 | } |
| ... | ... | @@ -149,9 +153,13 @@ impl MirLowerCtx<'_> { |
| 149 | 153 | } |
| 150 | 154 | ValueNs::StaticId(s) => { |
| 151 | 155 | let ty = self.expr_ty_without_adjust(expr_id); |
| 152 | let ref_ty = | |
| 153 | TyKind::Ref(Mutability::Not, static_lifetime(), ty).intern(Interner); | |
| 154 | let temp: Place = self.temp(ref_ty, current, expr_id.into())?.into(); | |
| 156 | let ref_ty = Ty::new_ref( | |
| 157 | self.interner(), | |
| 158 | Region::new_static(self.interner()), | |
| 159 | ty, | |
| 160 | Mutability::Not, | |
| 161 | ); | |
| 162 | let temp: Place<'db> = self.temp(ref_ty, current, expr_id.into())?.into(); | |
| 155 | 163 | self.push_assignment( |
| 156 | 164 | current, |
| 157 | 165 | temp, |
| ... | ... | @@ -167,10 +175,10 @@ impl MirLowerCtx<'_> { |
| 167 | 175 | } |
| 168 | 176 | } |
| 169 | 177 | Expr::UnaryOp { expr, op: hir_def::hir::UnaryOp::Deref } => { |
| 170 | let is_builtin = match self.expr_ty_without_adjust(*expr).kind(Interner) { | |
| 171 | TyKind::Ref(..) | TyKind::Raw(..) => true, | |
| 178 | let is_builtin = match self.expr_ty_without_adjust(*expr).kind() { | |
| 179 | TyKind::Ref(..) | TyKind::RawPtr(..) => true, | |
| 172 | 180 | TyKind::Adt(id, _) => { |
| 173 | if let Some(lang_item) = self.db.lang_attr(id.0.into()) { | |
| 181 | if let Some(lang_item) = self.db.lang_attr(id.def_id().0.into()) { | |
| 174 | 182 | lang_item == LangItem::OwnedBox |
| 175 | 183 | } else { |
| 176 | 184 | false |
| ... | ... | @@ -219,9 +227,9 @@ impl MirLowerCtx<'_> { |
| 219 | 227 | Expr::Index { base, index } => { |
| 220 | 228 | let base_ty = self.expr_ty_after_adjustments(*base); |
| 221 | 229 | let index_ty = self.expr_ty_after_adjustments(*index); |
| 222 | if index_ty != TyBuilder::usize() | |
| 230 | if !matches!(index_ty.kind(), TyKind::Uint(rustc_ast_ir::UintTy::Usize)) | |
| 223 | 231 | || !matches!( |
| 224 | base_ty.strip_reference().kind(Interner), | |
| 232 | base_ty.strip_reference().kind(), | |
| 225 | 233 | TyKind::Array(..) | TyKind::Slice(..) |
| 226 | 234 | ) |
| 227 | 235 | { |
| ... | ... | @@ -278,24 +286,26 @@ impl MirLowerCtx<'_> { |
| 278 | 286 | |
| 279 | 287 | fn lower_overloaded_index( |
| 280 | 288 | &mut self, |
| 281 | current: BasicBlockId, | |
| 282 | place: Place, | |
| 283 | base_ty: Ty, | |
| 284 | result_ty: Ty, | |
| 285 | index_operand: Operand, | |
| 289 | current: BasicBlockId<'db>, | |
| 290 | place: Place<'db>, | |
| 291 | base_ty: Ty<'db>, | |
| 292 | result_ty: Ty<'db>, | |
| 293 | index_operand: Operand<'db>, | |
| 286 | 294 | span: MirSpan, |
| 287 | index_fn: (FunctionId, Substitution), | |
| 288 | ) -> Result<Option<(Place, BasicBlockId)>> { | |
| 295 | index_fn: (FunctionId, GenericArgs<'db>), | |
| 296 | ) -> Result<'db, Option<(Place<'db>, BasicBlockId<'db>)>> { | |
| 289 | 297 | let mutability = match base_ty.as_reference() { |
| 290 | 298 | Some((_, _, mutability)) => mutability, |
| 291 | 299 | None => Mutability::Not, |
| 292 | 300 | }; |
| 293 | let result_ref = TyKind::Ref(mutability, error_lifetime(), result_ty).intern(Interner); | |
| 294 | let mut result: Place = self.temp(result_ref, current, span)?.into(); | |
| 295 | let index_fn_op = Operand::const_zst( | |
| 296 | TyKind::FnDef(CallableDefId::FunctionId(index_fn.0).to_chalk(self.db), index_fn.1) | |
| 297 | .intern(Interner), | |
| 298 | ); | |
| 301 | let result_ref = | |
| 302 | Ty::new_ref(self.interner(), Region::error(self.interner()), result_ty, mutability); | |
| 303 | let mut result: Place<'db> = self.temp(result_ref, current, span)?.into(); | |
| 304 | let index_fn_op = Operand::const_zst(Ty::new_fn_def( | |
| 305 | self.interner(), | |
| 306 | CallableDefId::FunctionId(index_fn.0).into(), | |
| 307 | index_fn.1, | |
| 308 | )); | |
| 299 | 309 | let Some(current) = self.lower_call( |
| 300 | 310 | index_fn_op, |
| 301 | 311 | Box::new([Operand { kind: OperandKind::Copy(place), span: None }, index_operand]), |
| ... | ... | @@ -313,14 +323,14 @@ impl MirLowerCtx<'_> { |
| 313 | 323 | |
| 314 | 324 | fn lower_overloaded_deref( |
| 315 | 325 | &mut self, |
| 316 | current: BasicBlockId, | |
| 317 | place: Place, | |
| 318 | source_ty: Ty, | |
| 319 | target_ty: Ty, | |
| 326 | current: BasicBlockId<'db>, | |
| 327 | place: Place<'db>, | |
| 328 | source_ty: Ty<'db>, | |
| 329 | target_ty: Ty<'db>, | |
| 320 | 330 | span: MirSpan, |
| 321 | 331 | mutability: bool, |
| 322 | ) -> Result<Option<(Place, BasicBlockId)>> { | |
| 323 | let (chalk_mut, trait_lang_item, trait_method_name, borrow_kind) = if !mutability { | |
| 332 | ) -> Result<'db, Option<(Place<'db>, BasicBlockId<'db>)>> { | |
| 333 | let (mutability, trait_lang_item, trait_method_name, borrow_kind) = if !mutability { | |
| 324 | 334 | ( |
| 325 | 335 | Mutability::Not, |
| 326 | 336 | LangItem::Deref, |
| ... | ... | @@ -335,9 +345,10 @@ impl MirLowerCtx<'_> { |
| 335 | 345 | BorrowKind::Mut { kind: MutBorrowKind::Default }, |
| 336 | 346 | ) |
| 337 | 347 | }; |
| 338 | let ty_ref = TyKind::Ref(chalk_mut, error_lifetime(), source_ty.clone()).intern(Interner); | |
| 339 | let target_ty_ref = TyKind::Ref(chalk_mut, error_lifetime(), target_ty).intern(Interner); | |
| 340 | let ref_place: Place = self.temp(ty_ref, current, span)?.into(); | |
| 348 | let error_region = Region::error(self.interner()); | |
| 349 | let ty_ref = Ty::new_ref(self.interner(), error_region, source_ty, mutability); | |
| 350 | let target_ty_ref = Ty::new_ref(self.interner(), error_region, target_ty, mutability); | |
| 351 | let ref_place: Place<'db> = self.temp(ty_ref, current, span)?.into(); | |
| 341 | 352 | self.push_assignment(current, ref_place, Rvalue::Ref(borrow_kind, place), span); |
| 342 | 353 | let deref_trait = self |
| 343 | 354 | .resolve_lang_item(trait_lang_item)? |
| ... | ... | @@ -347,14 +358,12 @@ impl MirLowerCtx<'_> { |
| 347 | 358 | .trait_items(self.db) |
| 348 | 359 | .method_by_name(&trait_method_name) |
| 349 | 360 | .ok_or(MirLowerError::LangItemNotFound(trait_lang_item))?; |
| 350 | let deref_fn_op = Operand::const_zst( | |
| 351 | TyKind::FnDef( | |
| 352 | CallableDefId::FunctionId(deref_fn).to_chalk(self.db), | |
| 353 | Substitution::from1(Interner, source_ty), | |
| 354 | ) | |
| 355 | .intern(Interner), | |
| 356 | ); | |
| 357 | let mut result: Place = self.temp(target_ty_ref, current, span)?.into(); | |
| 361 | let deref_fn_op = Operand::const_zst(Ty::new_fn_def( | |
| 362 | self.interner(), | |
| 363 | CallableDefId::FunctionId(deref_fn).into(), | |
| 364 | GenericArgs::new_from_iter(self.interner(), [source_ty.into()]), | |
| 365 | )); | |
| 366 | let mut result: Place<'db> = self.temp(target_ty_ref, current, span)?.into(); | |
| 358 | 367 | let Some(current) = self.lower_call( |
| 359 | 368 | deref_fn_op, |
| 360 | 369 | Box::new([Operand { kind: OperandKind::Copy(ref_place), span: None }]), |
src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs+80-81| ... | ... | @@ -1,17 +1,18 @@ |
| 1 | 1 | //! MIR lowering for patterns |
| 2 | 2 | |
| 3 | 3 | use hir_def::{AssocItemId, hir::ExprId, signatures::VariantFields}; |
| 4 | use rustc_type_ir::inherent::{IntoKind, SliceLike, Ty as _}; | |
| 4 | 5 | |
| 6 | use crate::next_solver::GenericArgs; | |
| 5 | 7 | use crate::{ |
| 6 | 8 | BindingMode, |
| 7 | 9 | mir::{ |
| 8 | 10 | LocalId, MutBorrowKind, Operand, OperandKind, |
| 9 | 11 | lower::{ |
| 10 | BasicBlockId, BinOp, BindingId, BorrowKind, Either, Expr, FieldId, Idx, Interner, | |
| 11 | MemoryMap, MirLowerCtx, MirLowerError, MirSpan, Mutability, Pat, PatId, Place, | |
| 12 | PlaceElem, ProjectionElem, RecordFieldPat, ResolveValueResult, Result, Rvalue, | |
| 13 | Substitution, SwitchTargets, TerminatorKind, TupleFieldId, TupleId, TyBuilder, TyKind, | |
| 14 | ValueNs, VariantId, | |
| 12 | BasicBlockId, BinOp, BindingId, BorrowKind, Either, Expr, FieldId, Idx, MemoryMap, | |
| 13 | MirLowerCtx, MirLowerError, MirSpan, Pat, PatId, Place, PlaceElem, ProjectionElem, | |
| 14 | RecordFieldPat, ResolveValueResult, Result, Rvalue, SwitchTargets, TerminatorKind, | |
| 15 | TupleFieldId, TupleId, Ty, TyKind, ValueNs, VariantId, | |
| 15 | 16 | }, |
| 16 | 17 | }, |
| 17 | 18 | }; |
| ... | ... | @@ -50,7 +51,7 @@ enum MatchingMode { |
| 50 | 51 | Assign, |
| 51 | 52 | } |
| 52 | 53 | |
| 53 | impl MirLowerCtx<'_> { | |
| 54 | impl<'db> MirLowerCtx<'_, 'db> { | |
| 54 | 55 | /// It gets a `current` unterminated block, appends some statements and possibly a terminator to it to check if |
| 55 | 56 | /// the pattern matches and write bindings, and returns two unterminated blocks, one for the matched path (which |
| 56 | 57 | /// can be the `current` block) and one for the mismatched path. If the input pattern is irrefutable, the |
| ... | ... | @@ -62,11 +63,11 @@ impl MirLowerCtx<'_> { |
| 62 | 63 | /// so it should be an empty block. |
| 63 | 64 | pub(super) fn pattern_match( |
| 64 | 65 | &mut self, |
| 65 | current: BasicBlockId, | |
| 66 | current_else: Option<BasicBlockId>, | |
| 67 | cond_place: Place, | |
| 66 | current: BasicBlockId<'db>, | |
| 67 | current_else: Option<BasicBlockId<'db>>, | |
| 68 | cond_place: Place<'db>, | |
| 68 | 69 | pattern: PatId, |
| 69 | ) -> Result<(BasicBlockId, Option<BasicBlockId>)> { | |
| 70 | ) -> Result<'db, (BasicBlockId<'db>, Option<BasicBlockId<'db>>)> { | |
| 70 | 71 | let (current, current_else) = self.pattern_match_inner( |
| 71 | 72 | current, |
| 72 | 73 | current_else, |
| ... | ... | @@ -86,10 +87,10 @@ impl MirLowerCtx<'_> { |
| 86 | 87 | |
| 87 | 88 | pub(super) fn pattern_match_assignment( |
| 88 | 89 | &mut self, |
| 89 | current: BasicBlockId, | |
| 90 | value: Place, | |
| 90 | current: BasicBlockId<'db>, | |
| 91 | value: Place<'db>, | |
| 91 | 92 | pattern: PatId, |
| 92 | ) -> Result<BasicBlockId> { | |
| 93 | ) -> Result<'db, BasicBlockId<'db>> { | |
| 93 | 94 | let (current, _) = |
| 94 | 95 | self.pattern_match_inner(current, None, value, pattern, MatchingMode::Assign)?; |
| 95 | 96 | Ok(current) |
| ... | ... | @@ -98,9 +99,9 @@ impl MirLowerCtx<'_> { |
| 98 | 99 | pub(super) fn match_self_param( |
| 99 | 100 | &mut self, |
| 100 | 101 | id: BindingId, |
| 101 | current: BasicBlockId, | |
| 102 | local: LocalId, | |
| 103 | ) -> Result<(BasicBlockId, Option<BasicBlockId>)> { | |
| 102 | current: BasicBlockId<'db>, | |
| 103 | local: LocalId<'db>, | |
| 104 | ) -> Result<'db, (BasicBlockId<'db>, Option<BasicBlockId<'db>>)> { | |
| 104 | 105 | self.pattern_match_binding( |
| 105 | 106 | id, |
| 106 | 107 | BindingMode::Move, |
| ... | ... | @@ -113,12 +114,12 @@ impl MirLowerCtx<'_> { |
| 113 | 114 | |
| 114 | 115 | fn pattern_match_inner( |
| 115 | 116 | &mut self, |
| 116 | mut current: BasicBlockId, | |
| 117 | mut current_else: Option<BasicBlockId>, | |
| 118 | mut cond_place: Place, | |
| 117 | mut current: BasicBlockId<'db>, | |
| 118 | mut current_else: Option<BasicBlockId<'db>>, | |
| 119 | mut cond_place: Place<'db>, | |
| 119 | 120 | pattern: PatId, |
| 120 | 121 | mode: MatchingMode, |
| 121 | ) -> Result<(BasicBlockId, Option<BasicBlockId>)> { | |
| 122 | ) -> Result<'db, (BasicBlockId<'db>, Option<BasicBlockId<'db>>)> { | |
| 122 | 123 | let cnt = self.infer.pat_adjustments.get(&pattern).map(|x| x.len()).unwrap_or_default(); |
| 123 | 124 | cond_place.projection = self.result.projection_store.intern( |
| 124 | 125 | cond_place |
| ... | ... | @@ -134,8 +135,8 @@ impl MirLowerCtx<'_> { |
| 134 | 135 | Pat::Missing => return Err(MirLowerError::IncompletePattern), |
| 135 | 136 | Pat::Wild => (current, current_else), |
| 136 | 137 | Pat::Tuple { args, ellipsis } => { |
| 137 | let subst = match self.infer[pattern].kind(Interner) { | |
| 138 | TyKind::Tuple(_, s) => s, | |
| 138 | let subst = match self.infer[pattern].kind() { | |
| 139 | TyKind::Tuple(s) => s, | |
| 139 | 140 | _ => { |
| 140 | 141 | return Err(MirLowerError::TypeError( |
| 141 | 142 | "non tuple type matched with tuple pattern", |
| ... | ... | @@ -147,7 +148,7 @@ impl MirLowerCtx<'_> { |
| 147 | 148 | current_else, |
| 148 | 149 | args, |
| 149 | 150 | *ellipsis, |
| 150 | (0..subst.len(Interner)).map(|i| { | |
| 151 | (0..subst.len()).map(|i| { | |
| 151 | 152 | PlaceElem::Field(Either::Right(TupleFieldId { |
| 152 | 153 | tuple: TupleId(!0), // Dummy as it is unused |
| 153 | 154 | index: i as u32, |
| ... | ... | @@ -207,13 +208,12 @@ impl MirLowerCtx<'_> { |
| 207 | 208 | )? |
| 208 | 209 | } |
| 209 | 210 | Pat::Range { start, end } => { |
| 210 | let mut add_check = |l: &ExprId, binop| -> Result<()> { | |
| 211 | let lv = | |
| 212 | self.lower_literal_or_const_to_operand(self.infer[pattern].clone(), l)?; | |
| 211 | let mut add_check = |l: &ExprId, binop| -> Result<'db, ()> { | |
| 212 | let lv = self.lower_literal_or_const_to_operand(self.infer[pattern], l)?; | |
| 213 | 213 | let else_target = *current_else.get_or_insert_with(|| self.new_basic_block()); |
| 214 | 214 | let next = self.new_basic_block(); |
| 215 | let discr: Place = | |
| 216 | self.temp(TyBuilder::bool(), current, pattern.into())?.into(); | |
| 215 | let discr: Place<'db> = | |
| 216 | self.temp(Ty::new_bool(self.interner()), current, pattern.into())?.into(); | |
| 217 | 217 | self.push_assignment( |
| 218 | 218 | current, |
| 219 | 219 | discr, |
| ... | ... | @@ -249,10 +249,11 @@ impl MirLowerCtx<'_> { |
| 249 | 249 | Pat::Slice { prefix, slice, suffix } => { |
| 250 | 250 | if mode == MatchingMode::Check { |
| 251 | 251 | // emit runtime length check for slice |
| 252 | if let TyKind::Slice(_) = self.infer[pattern].kind(Interner) { | |
| 252 | if let TyKind::Slice(_) = self.infer[pattern].kind() { | |
| 253 | 253 | let pattern_len = prefix.len() + suffix.len(); |
| 254 | let place_len: Place = | |
| 255 | self.temp(TyBuilder::usize(), current, pattern.into())?.into(); | |
| 254 | let place_len: Place<'db> = self | |
| 255 | .temp(Ty::new_usize(self.interner()), current, pattern.into())? | |
| 256 | .into(); | |
| 256 | 257 | self.push_assignment( |
| 257 | 258 | current, |
| 258 | 259 | place_len, |
| ... | ... | @@ -282,10 +283,11 @@ impl MirLowerCtx<'_> { |
| 282 | 283 | let c = Operand::from_concrete_const( |
| 283 | 284 | pattern_len.to_le_bytes().into(), |
| 284 | 285 | MemoryMap::default(), |
| 285 | TyBuilder::usize(), | |
| 286 | Ty::new_usize(self.interner()), | |
| 286 | 287 | ); |
| 287 | let discr: Place = | |
| 288 | self.temp(TyBuilder::bool(), current, pattern.into())?.into(); | |
| 288 | let discr: Place<'db> = self | |
| 289 | .temp(Ty::new_bool(self.interner()), current, pattern.into())? | |
| 290 | .into(); | |
| 289 | 291 | self.push_assignment( |
| 290 | 292 | current, |
| 291 | 293 | discr, |
| ... | ... | @@ -396,22 +398,16 @@ impl MirLowerCtx<'_> { |
| 396 | 398 | break 'b (c, x.1); |
| 397 | 399 | } |
| 398 | 400 | if let ResolveValueResult::ValueNs(ValueNs::ConstId(c), _) = pr { |
| 399 | break 'b (c, Substitution::empty(Interner)); | |
| 401 | break 'b (c, GenericArgs::new_from_iter(self.interner(), [])); | |
| 400 | 402 | } |
| 401 | 403 | not_supported!("path in pattern position that is not const or variant") |
| 402 | 404 | }; |
| 403 | let tmp: Place = | |
| 404 | self.temp(self.infer[pattern].clone(), current, pattern.into())?.into(); | |
| 405 | let tmp: Place<'db> = | |
| 406 | self.temp(self.infer[pattern], current, pattern.into())?.into(); | |
| 405 | 407 | let span = pattern.into(); |
| 406 | self.lower_const( | |
| 407 | c.into(), | |
| 408 | current, | |
| 409 | tmp, | |
| 410 | subst, | |
| 411 | span, | |
| 412 | self.infer[pattern].clone(), | |
| 413 | )?; | |
| 414 | let tmp2: Place = self.temp(TyBuilder::bool(), current, pattern.into())?.into(); | |
| 408 | self.lower_const(c.into(), current, tmp, subst, span)?; | |
| 409 | let tmp2: Place<'db> = | |
| 410 | self.temp(Ty::new_bool(self.interner()), current, pattern.into())?.into(); | |
| 415 | 411 | self.push_assignment( |
| 416 | 412 | current, |
| 417 | 413 | tmp2, |
| ... | ... | @@ -438,7 +434,7 @@ impl MirLowerCtx<'_> { |
| 438 | 434 | Pat::Lit(l) => match &self.body[*l] { |
| 439 | 435 | Expr::Literal(l) => { |
| 440 | 436 | if mode == MatchingMode::Check { |
| 441 | let c = self.lower_literal_to_operand(self.infer[pattern].clone(), l)?; | |
| 437 | let c = self.lower_literal_to_operand(self.infer[pattern], l)?; | |
| 442 | 438 | self.pattern_match_const(current_else, current, c, cond_place, pattern)? |
| 443 | 439 | } else { |
| 444 | 440 | (current, current_else) |
| ... | ... | @@ -510,11 +506,11 @@ impl MirLowerCtx<'_> { |
| 510 | 506 | &mut self, |
| 511 | 507 | id: BindingId, |
| 512 | 508 | mode: BindingMode, |
| 513 | cond_place: Place, | |
| 509 | cond_place: Place<'db>, | |
| 514 | 510 | span: MirSpan, |
| 515 | current: BasicBlockId, | |
| 516 | current_else: Option<BasicBlockId>, | |
| 517 | ) -> Result<(BasicBlockId, Option<BasicBlockId>)> { | |
| 511 | current: BasicBlockId<'db>, | |
| 512 | current_else: Option<BasicBlockId<'db>>, | |
| 513 | ) -> Result<'db, (BasicBlockId<'db>, Option<BasicBlockId<'db>>)> { | |
| 518 | 514 | let target_place = self.binding_local(id)?; |
| 519 | 515 | self.push_storage_live(id, current)?; |
| 520 | 516 | self.push_match_assignment(current, target_place, mode, cond_place, span); |
| ... | ... | @@ -523,10 +519,10 @@ impl MirLowerCtx<'_> { |
| 523 | 519 | |
| 524 | 520 | fn push_match_assignment( |
| 525 | 521 | &mut self, |
| 526 | current: BasicBlockId, | |
| 527 | target_place: LocalId, | |
| 522 | current: BasicBlockId<'db>, | |
| 523 | target_place: LocalId<'db>, | |
| 528 | 524 | mode: BindingMode, |
| 529 | cond_place: Place, | |
| 525 | cond_place: Place<'db>, | |
| 530 | 526 | span: MirSpan, |
| 531 | 527 | ) { |
| 532 | 528 | self.push_assignment( |
| ... | ... | @@ -536,8 +532,10 @@ impl MirLowerCtx<'_> { |
| 536 | 532 | BindingMode::Move => { |
| 537 | 533 | Operand { kind: OperandKind::Copy(cond_place), span: None }.into() |
| 538 | 534 | } |
| 539 | BindingMode::Ref(Mutability::Not) => Rvalue::Ref(BorrowKind::Shared, cond_place), | |
| 540 | BindingMode::Ref(Mutability::Mut) => { | |
| 535 | BindingMode::Ref(rustc_ast_ir::Mutability::Not) => { | |
| 536 | Rvalue::Ref(BorrowKind::Shared, cond_place) | |
| 537 | } | |
| 538 | BindingMode::Ref(rustc_ast_ir::Mutability::Mut) => { | |
| 541 | 539 | Rvalue::Ref(BorrowKind::Mut { kind: MutBorrowKind::Default }, cond_place) |
| 542 | 540 | } |
| 543 | 541 | }, |
| ... | ... | @@ -547,15 +545,16 @@ impl MirLowerCtx<'_> { |
| 547 | 545 | |
| 548 | 546 | fn pattern_match_const( |
| 549 | 547 | &mut self, |
| 550 | current_else: Option<BasicBlockId>, | |
| 551 | current: BasicBlockId, | |
| 552 | c: Operand, | |
| 553 | cond_place: Place, | |
| 548 | current_else: Option<BasicBlockId<'db>>, | |
| 549 | current: BasicBlockId<'db>, | |
| 550 | c: Operand<'db>, | |
| 551 | cond_place: Place<'db>, | |
| 554 | 552 | pattern: Idx<Pat>, |
| 555 | ) -> Result<(BasicBlockId, Option<BasicBlockId>)> { | |
| 553 | ) -> Result<'db, (BasicBlockId<'db>, Option<BasicBlockId<'db>>)> { | |
| 556 | 554 | let then_target = self.new_basic_block(); |
| 557 | 555 | let else_target = current_else.unwrap_or_else(|| self.new_basic_block()); |
| 558 | let discr: Place = self.temp(TyBuilder::bool(), current, pattern.into())?.into(); | |
| 556 | let discr: Place<'db> = | |
| 557 | self.temp(Ty::new_bool(self.interner()), current, pattern.into())?.into(); | |
| 559 | 558 | self.push_assignment( |
| 560 | 559 | current, |
| 561 | 560 | discr, |
| ... | ... | @@ -580,14 +579,14 @@ impl MirLowerCtx<'_> { |
| 580 | 579 | |
| 581 | 580 | fn pattern_matching_variant( |
| 582 | 581 | &mut self, |
| 583 | cond_place: Place, | |
| 582 | cond_place: Place<'db>, | |
| 584 | 583 | variant: VariantId, |
| 585 | mut current: BasicBlockId, | |
| 584 | mut current: BasicBlockId<'db>, | |
| 586 | 585 | span: MirSpan, |
| 587 | mut current_else: Option<BasicBlockId>, | |
| 586 | mut current_else: Option<BasicBlockId<'db>>, | |
| 588 | 587 | shape: AdtPatternShape<'_>, |
| 589 | 588 | mode: MatchingMode, |
| 590 | ) -> Result<(BasicBlockId, Option<BasicBlockId>)> { | |
| 589 | ) -> Result<'db, (BasicBlockId<'db>, Option<BasicBlockId<'db>>)> { | |
| 591 | 590 | Ok(match variant { |
| 592 | 591 | VariantId::EnumVariantId(v) => { |
| 593 | 592 | if mode == MatchingMode::Check { |
| ... | ... | @@ -636,11 +635,11 @@ impl MirLowerCtx<'_> { |
| 636 | 635 | shape: AdtPatternShape<'_>, |
| 637 | 636 | variant_data: &VariantFields, |
| 638 | 637 | v: VariantId, |
| 639 | current: BasicBlockId, | |
| 640 | current_else: Option<BasicBlockId>, | |
| 641 | cond_place: &Place, | |
| 638 | current: BasicBlockId<'db>, | |
| 639 | current_else: Option<BasicBlockId<'db>>, | |
| 640 | cond_place: &Place<'db>, | |
| 642 | 641 | mode: MatchingMode, |
| 643 | ) -> Result<(BasicBlockId, Option<BasicBlockId>)> { | |
| 642 | ) -> Result<'db, (BasicBlockId<'db>, Option<BasicBlockId<'db>>)> { | |
| 644 | 643 | Ok(match shape { |
| 645 | 644 | AdtPatternShape::Record { args } => { |
| 646 | 645 | let it = args |
| ... | ... | @@ -656,7 +655,7 @@ impl MirLowerCtx<'_> { |
| 656 | 655 | x.pat, |
| 657 | 656 | )) |
| 658 | 657 | }) |
| 659 | .collect::<Result<Vec<_>>>()?; | |
| 658 | .collect::<Result<'db, Vec<_>>>()?; | |
| 660 | 659 | self.pattern_match_adt(current, current_else, it.into_iter(), cond_place, mode)? |
| 661 | 660 | } |
| 662 | 661 | AdtPatternShape::Tuple { args, ellipsis } => { |
| ... | ... | @@ -679,12 +678,12 @@ impl MirLowerCtx<'_> { |
| 679 | 678 | |
| 680 | 679 | fn pattern_match_adt( |
| 681 | 680 | &mut self, |
| 682 | mut current: BasicBlockId, | |
| 683 | mut current_else: Option<BasicBlockId>, | |
| 684 | args: impl Iterator<Item = (PlaceElem, PatId)>, | |
| 685 | cond_place: &Place, | |
| 681 | mut current: BasicBlockId<'db>, | |
| 682 | mut current_else: Option<BasicBlockId<'db>>, | |
| 683 | args: impl Iterator<Item = (PlaceElem<'db>, PatId)>, | |
| 684 | cond_place: &Place<'db>, | |
| 686 | 685 | mode: MatchingMode, |
| 687 | ) -> Result<(BasicBlockId, Option<BasicBlockId>)> { | |
| 686 | ) -> Result<'db, (BasicBlockId<'db>, Option<BasicBlockId<'db>>)> { | |
| 688 | 687 | for (proj, arg) in args { |
| 689 | 688 | let cond_place = cond_place.project(proj, &mut self.result.projection_store); |
| 690 | 689 | (current, current_else) = |
| ... | ... | @@ -695,14 +694,14 @@ impl MirLowerCtx<'_> { |
| 695 | 694 | |
| 696 | 695 | fn pattern_match_tuple_like( |
| 697 | 696 | &mut self, |
| 698 | current: BasicBlockId, | |
| 699 | current_else: Option<BasicBlockId>, | |
| 697 | current: BasicBlockId<'db>, | |
| 698 | current_else: Option<BasicBlockId<'db>>, | |
| 700 | 699 | args: &[PatId], |
| 701 | 700 | ellipsis: Option<u32>, |
| 702 | fields: impl DoubleEndedIterator<Item = PlaceElem> + Clone, | |
| 703 | cond_place: &Place, | |
| 701 | fields: impl DoubleEndedIterator<Item = PlaceElem<'db>> + Clone, | |
| 702 | cond_place: &Place<'db>, | |
| 704 | 703 | mode: MatchingMode, |
| 705 | ) -> Result<(BasicBlockId, Option<BasicBlockId>)> { | |
| 704 | ) -> Result<'db, (BasicBlockId<'db>, Option<BasicBlockId<'db>>)> { | |
| 706 | 705 | let (al, ar) = args.split_at(ellipsis.map_or(args.len(), |it| it as usize)); |
| 707 | 706 | let it = al |
| 708 | 707 | .iter() |
src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/tests.rs+15-28| ... | ... | @@ -1,36 +1,23 @@ |
| 1 | use hir_def::db::DefDatabase; | |
| 2 | use rustc_hash::FxHashMap; | |
| 3 | use span::Edition; | |
| 4 | 1 | use test_fixture::WithFixture; |
| 5 | use triomphe::Arc; | |
| 6 | 2 | |
| 7 | use crate::{ | |
| 8 | db::HirDatabase, | |
| 9 | mir::{MirBody, MirLowerError}, | |
| 10 | setup_tracing, | |
| 11 | test_db::TestDB, | |
| 12 | }; | |
| 3 | use crate::{db::HirDatabase, setup_tracing, test_db::TestDB}; | |
| 13 | 4 | |
| 14 | fn lower_mir( | |
| 15 | #[rust_analyzer::rust_fixture] ra_fixture: &str, | |
| 16 | ) -> FxHashMap<String, Result<Arc<MirBody>, MirLowerError>> { | |
| 5 | fn lower_mir(#[rust_analyzer::rust_fixture] ra_fixture: &str) { | |
| 17 | 6 | let _tracing = setup_tracing(); |
| 18 | 7 | let (db, file_ids) = TestDB::with_many_files(ra_fixture); |
| 19 | let file_id = *file_ids.last().unwrap(); | |
| 20 | let module_id = db.module_for_file(file_id.file_id(&db)); | |
| 21 | let def_map = module_id.def_map(&db); | |
| 22 | let scope = &def_map[module_id.local_id].scope; | |
| 23 | let funcs = scope.declarations().filter_map(|x| match x { | |
| 24 | hir_def::ModuleDefId::FunctionId(it) => Some(it), | |
| 25 | _ => None, | |
| 26 | }); | |
| 27 | funcs | |
| 28 | .map(|func| { | |
| 29 | let name = db.function_signature(func).name.display(&db, Edition::CURRENT).to_string(); | |
| 30 | let mir = db.mir_body(func.into()); | |
| 31 | (name, mir) | |
| 32 | }) | |
| 33 | .collect() | |
| 8 | crate::attach_db(&db, || { | |
| 9 | let file_id = *file_ids.last().unwrap(); | |
| 10 | let module_id = db.module_for_file(file_id.file_id(&db)); | |
| 11 | let def_map = module_id.def_map(&db); | |
| 12 | let scope = &def_map[module_id.local_id].scope; | |
| 13 | let funcs = scope.declarations().filter_map(|x| match x { | |
| 14 | hir_def::ModuleDefId::FunctionId(it) => Some(it), | |
| 15 | _ => None, | |
| 16 | }); | |
| 17 | for func in funcs { | |
| 18 | _ = db.mir_body(func.into()); | |
| 19 | } | |
| 20 | }) | |
| 34 | 21 | } |
| 35 | 22 | |
| 36 | 23 | #[test] |
src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs+98-196| ... | ... | @@ -7,224 +7,129 @@ |
| 7 | 7 | //! |
| 8 | 8 | //! So the monomorphization should be called even if the substitution is empty. |
| 9 | 9 | |
| 10 | use std::mem; | |
| 11 | ||
| 12 | use chalk_ir::{ | |
| 13 | ConstData, DebruijnIndex, | |
| 14 | fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}, | |
| 15 | }; | |
| 16 | 10 | use hir_def::DefWithBodyId; |
| 11 | use rustc_type_ir::inherent::{IntoKind, SliceLike}; | |
| 12 | use rustc_type_ir::{ | |
| 13 | FallibleTypeFolder, TypeFlags, TypeFoldable, TypeSuperFoldable, TypeVisitableExt, | |
| 14 | }; | |
| 17 | 15 | use triomphe::Arc; |
| 18 | 16 | |
| 17 | use crate::next_solver::{Const, ConstKind, Region, RegionKind}; | |
| 19 | 18 | use crate::{ |
| 20 | Const, Interner, ProjectionTy, Substitution, TraitEnvironment, Ty, TyKind, | |
| 21 | consteval::{intern_const_scalar, unknown_const}, | |
| 22 | db::{HirDatabase, InternedClosure, InternedClosureId}, | |
| 23 | from_placeholder_idx, | |
| 24 | generics::{Generics, generics}, | |
| 25 | infer::normalize, | |
| 19 | TraitEnvironment, | |
| 20 | db::{HirDatabase, InternedClosureId}, | |
| 21 | next_solver::{ | |
| 22 | DbInterner, GenericArgs, Ty, TyKind, TypingMode, | |
| 23 | infer::{DbInternerInferExt, InferCtxt, traits::ObligationCause}, | |
| 24 | obligation_ctxt::ObligationCtxt, | |
| 25 | references_non_lt_error, | |
| 26 | }, | |
| 26 | 27 | }; |
| 27 | 28 | |
| 28 | 29 | use super::{MirBody, MirLowerError, Operand, OperandKind, Rvalue, StatementKind, TerminatorKind}; |
| 29 | 30 | |
| 30 | macro_rules! not_supported { | |
| 31 | ($it: expr) => { | |
| 32 | return Err(MirLowerError::NotSupported(format!($it))) | |
| 33 | }; | |
| 31 | struct Filler<'db> { | |
| 32 | infcx: InferCtxt<'db>, | |
| 33 | trait_env: Arc<TraitEnvironment<'db>>, | |
| 34 | subst: GenericArgs<'db>, | |
| 34 | 35 | } |
| 35 | 36 | |
| 36 | struct Filler<'a> { | |
| 37 | db: &'a dyn HirDatabase, | |
| 38 | trait_env: Arc<TraitEnvironment<'a>>, | |
| 39 | subst: &'a Substitution, | |
| 40 | generics: Option<Generics>, | |
| 41 | } | |
| 42 | impl FallibleTypeFolder<Interner> for Filler<'_> { | |
| 43 | type Error = MirLowerError; | |
| 37 | impl<'db> FallibleTypeFolder<DbInterner<'db>> for Filler<'db> { | |
| 38 | type Error = MirLowerError<'db>; | |
| 44 | 39 | |
| 45 | fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder<Interner, Error = Self::Error> { | |
| 46 | self | |
| 40 | fn cx(&self) -> DbInterner<'db> { | |
| 41 | self.infcx.interner | |
| 47 | 42 | } |
| 48 | 43 | |
| 49 | fn interner(&self) -> Interner { | |
| 50 | Interner | |
| 51 | } | |
| 44 | fn try_fold_ty(&mut self, ty: Ty<'db>) -> Result<Ty<'db>, Self::Error> { | |
| 45 | if !ty.has_type_flags(TypeFlags::HAS_ALIAS | TypeFlags::HAS_PARAM) { | |
| 46 | return Ok(ty); | |
| 47 | } | |
| 52 | 48 | |
| 53 | fn try_fold_ty( | |
| 54 | &mut self, | |
| 55 | ty: Ty, | |
| 56 | outer_binder: DebruijnIndex, | |
| 57 | ) -> std::result::Result<Ty, Self::Error> { | |
| 58 | match ty.kind(Interner) { | |
| 59 | TyKind::AssociatedType(id, subst) => { | |
| 60 | // I don't know exactly if and why this is needed, but it looks like `normalize_ty` likes | |
| 61 | // this kind of associated types. | |
| 62 | Ok(TyKind::Alias(chalk_ir::AliasTy::Projection(ProjectionTy { | |
| 63 | associated_ty_id: *id, | |
| 64 | substitution: subst.clone().try_fold_with(self, outer_binder)?, | |
| 65 | })) | |
| 66 | .intern(Interner)) | |
| 67 | } | |
| 68 | TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { | |
| 69 | opaque_ty_id: id, | |
| 70 | substitution: subst, | |
| 71 | })) | |
| 72 | | TyKind::OpaqueType(id, subst) => { | |
| 73 | let impl_trait_id = self.db.lookup_intern_impl_trait_id((*id).into()); | |
| 74 | let subst = subst.clone().try_fold_with(self.as_dyn(), outer_binder)?; | |
| 75 | match impl_trait_id { | |
| 76 | crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => { | |
| 77 | let infer = self.db.infer(func.into()); | |
| 78 | let filler = &mut Filler { | |
| 79 | db: self.db, | |
| 80 | trait_env: self.trait_env.clone(), | |
| 81 | subst: &subst, | |
| 82 | generics: Some(generics(self.db, func.into())), | |
| 83 | }; | |
| 84 | filler.try_fold_ty(infer.type_of_rpit[idx].clone(), outer_binder) | |
| 85 | } | |
| 86 | crate::ImplTraitId::TypeAliasImplTrait(..) => { | |
| 87 | not_supported!("type alias impl trait"); | |
| 88 | } | |
| 89 | crate::ImplTraitId::AsyncBlockTypeImplTrait(_, _) => { | |
| 90 | not_supported!("async block impl trait"); | |
| 91 | } | |
| 92 | } | |
| 49 | match ty.kind() { | |
| 50 | TyKind::Alias(..) => { | |
| 51 | // First instantiate params. | |
| 52 | let ty = ty.try_super_fold_with(self)?; | |
| 53 | ||
| 54 | let mut ocx = ObligationCtxt::new(&self.infcx); | |
| 55 | let ty = ocx | |
| 56 | .structurally_normalize_ty(&ObligationCause::dummy(), self.trait_env.env, ty) | |
| 57 | .map_err(|_| MirLowerError::NotSupported("can't normalize alias".to_owned()))?; | |
| 58 | ty.try_super_fold_with(self) | |
| 93 | 59 | } |
| 94 | _ => ty.try_super_fold_with(self.as_dyn(), outer_binder), | |
| 60 | TyKind::Param(param) => Ok(self | |
| 61 | .subst | |
| 62 | .as_slice() | |
| 63 | .get(param.index as usize) | |
| 64 | .and_then(|arg| arg.ty()) | |
| 65 | .ok_or_else(|| { | |
| 66 | MirLowerError::GenericArgNotProvided(param.id.into(), self.subst) | |
| 67 | })?), | |
| 68 | _ => ty.try_super_fold_with(self), | |
| 95 | 69 | } |
| 96 | 70 | } |
| 97 | 71 | |
| 98 | fn try_fold_free_placeholder_const( | |
| 99 | &mut self, | |
| 100 | _ty: chalk_ir::Ty<Interner>, | |
| 101 | idx: chalk_ir::PlaceholderIndex, | |
| 102 | _outer_binder: DebruijnIndex, | |
| 103 | ) -> std::result::Result<chalk_ir::Const<Interner>, Self::Error> { | |
| 104 | let it = from_placeholder_idx(self.db, idx).0; | |
| 105 | let Some(idx) = self.generics.as_ref().and_then(|g| g.type_or_const_param_idx(it)) else { | |
| 106 | not_supported!("missing idx in generics"); | |
| 72 | fn try_fold_const(&mut self, ct: Const<'db>) -> Result<Const<'db>, Self::Error> { | |
| 73 | let ConstKind::Param(param) = ct.kind() else { | |
| 74 | return ct.try_super_fold_with(self); | |
| 107 | 75 | }; |
| 108 | Ok(self | |
| 109 | .subst | |
| 110 | .as_slice(Interner) | |
| 111 | .get(idx) | |
| 112 | .and_then(|it| it.constant(Interner)) | |
| 113 | .ok_or_else(|| MirLowerError::GenericArgNotProvided(it, self.subst.clone()))? | |
| 114 | .clone()) | |
| 76 | self.subst | |
| 77 | .as_slice() | |
| 78 | .get(param.index as usize) | |
| 79 | .and_then(|arg| arg.konst()) | |
| 80 | .ok_or_else(|| MirLowerError::GenericArgNotProvided(param.id.into(), self.subst)) | |
| 115 | 81 | } |
| 116 | 82 | |
| 117 | fn try_fold_free_placeholder_ty( | |
| 118 | &mut self, | |
| 119 | idx: chalk_ir::PlaceholderIndex, | |
| 120 | _outer_binder: DebruijnIndex, | |
| 121 | ) -> std::result::Result<Ty, Self::Error> { | |
| 122 | let it = from_placeholder_idx(self.db, idx).0; | |
| 123 | let Some(idx) = self.generics.as_ref().and_then(|g| g.type_or_const_param_idx(it)) else { | |
| 124 | not_supported!("missing idx in generics"); | |
| 83 | fn try_fold_region(&mut self, region: Region<'db>) -> Result<Region<'db>, Self::Error> { | |
| 84 | let RegionKind::ReEarlyParam(param) = region.kind() else { | |
| 85 | return Ok(region); | |
| 125 | 86 | }; |
| 126 | Ok(self | |
| 127 | .subst | |
| 128 | .as_slice(Interner) | |
| 129 | .get(idx) | |
| 130 | .and_then(|it| it.ty(Interner)) | |
| 131 | .ok_or_else(|| MirLowerError::GenericArgNotProvided(it, self.subst.clone()))? | |
| 132 | .clone()) | |
| 133 | } | |
| 134 | ||
| 135 | fn try_fold_const( | |
| 136 | &mut self, | |
| 137 | constant: chalk_ir::Const<Interner>, | |
| 138 | outer_binder: DebruijnIndex, | |
| 139 | ) -> Result<chalk_ir::Const<Interner>, Self::Error> { | |
| 140 | let next_ty = normalize( | |
| 141 | self.db, | |
| 142 | self.trait_env.clone(), | |
| 143 | constant.data(Interner).ty.clone().try_fold_with(self, outer_binder)?, | |
| 144 | ); | |
| 145 | ConstData { ty: next_ty, value: constant.data(Interner).value.clone() } | |
| 146 | .intern(Interner) | |
| 147 | .try_super_fold_with(self, outer_binder) | |
| 87 | self.subst | |
| 88 | .as_slice() | |
| 89 | .get(param.index as usize) | |
| 90 | .and_then(|arg| arg.region()) | |
| 91 | .ok_or_else(|| MirLowerError::GenericArgNotProvided(param.id.into(), self.subst)) | |
| 148 | 92 | } |
| 149 | 93 | } |
| 150 | 94 | |
| 151 | impl Filler<'_> { | |
| 152 | fn fill_ty(&mut self, ty: &mut Ty) -> Result<(), MirLowerError> { | |
| 153 | let tmp = mem::replace(ty, TyKind::Error.intern(Interner)); | |
| 154 | *ty = normalize( | |
| 155 | self.db, | |
| 156 | self.trait_env.clone(), | |
| 157 | tmp.try_fold_with(self, DebruijnIndex::INNERMOST)?, | |
| 158 | ); | |
| 159 | Ok(()) | |
| 160 | } | |
| 161 | ||
| 162 | fn fill_const(&mut self, c: &mut Const) -> Result<(), MirLowerError> { | |
| 163 | let tmp = mem::replace(c, unknown_const(c.data(Interner).ty.clone())); | |
| 164 | *c = tmp.try_fold_with(self, DebruijnIndex::INNERMOST)?; | |
| 165 | Ok(()) | |
| 95 | impl<'db> Filler<'db> { | |
| 96 | fn new( | |
| 97 | db: &'db dyn HirDatabase, | |
| 98 | env: Arc<TraitEnvironment<'db>>, | |
| 99 | subst: GenericArgs<'db>, | |
| 100 | ) -> Self { | |
| 101 | let interner = DbInterner::new_with(db, Some(env.krate), env.block); | |
| 102 | let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); | |
| 103 | Self { infcx, trait_env: env, subst } | |
| 166 | 104 | } |
| 167 | 105 | |
| 168 | fn fill_subst(&mut self, ty: &mut Substitution) -> Result<(), MirLowerError> { | |
| 169 | let tmp = mem::replace(ty, Substitution::empty(Interner)); | |
| 170 | *ty = tmp.try_fold_with(self, DebruijnIndex::INNERMOST)?; | |
| 171 | Ok(()) | |
| 106 | fn fill<T: TypeFoldable<DbInterner<'db>> + Copy>( | |
| 107 | &mut self, | |
| 108 | t: &mut T, | |
| 109 | ) -> Result<(), MirLowerError<'db>> { | |
| 110 | // Can't deep normalized as that'll try to normalize consts and fail. | |
| 111 | *t = t.try_fold_with(self)?; | |
| 112 | if references_non_lt_error(t) { | |
| 113 | Err(MirLowerError::NotSupported("monomorphization resulted in errors".to_owned())) | |
| 114 | } else { | |
| 115 | Ok(()) | |
| 116 | } | |
| 172 | 117 | } |
| 173 | 118 | |
| 174 | fn fill_operand(&mut self, op: &mut Operand) -> Result<(), MirLowerError> { | |
| 119 | fn fill_operand(&mut self, op: &mut Operand<'db>) -> Result<(), MirLowerError<'db>> { | |
| 175 | 120 | match &mut op.kind { |
| 176 | OperandKind::Constant(c) => { | |
| 177 | match &c.data(Interner).value { | |
| 178 | chalk_ir::ConstValue::BoundVar(b) => { | |
| 179 | let resolved = self | |
| 180 | .subst | |
| 181 | .as_slice(Interner) | |
| 182 | .get(b.index) | |
| 183 | .ok_or_else(|| { | |
| 184 | MirLowerError::GenericArgNotProvided( | |
| 185 | self.generics | |
| 186 | .as_ref() | |
| 187 | .and_then(|it| it.iter().nth(b.index)) | |
| 188 | .and_then(|(id, _)| match id { | |
| 189 | hir_def::GenericParamId::ConstParamId(id) => { | |
| 190 | Some(hir_def::TypeOrConstParamId::from(id)) | |
| 191 | } | |
| 192 | hir_def::GenericParamId::TypeParamId(id) => { | |
| 193 | Some(hir_def::TypeOrConstParamId::from(id)) | |
| 194 | } | |
| 195 | _ => None, | |
| 196 | }) | |
| 197 | .unwrap(), | |
| 198 | self.subst.clone(), | |
| 199 | ) | |
| 200 | })? | |
| 201 | .assert_const_ref(Interner); | |
| 202 | *c = resolved.clone(); | |
| 203 | } | |
| 204 | chalk_ir::ConstValue::InferenceVar(_) | |
| 205 | | chalk_ir::ConstValue::Placeholder(_) => {} | |
| 206 | chalk_ir::ConstValue::Concrete(cc) => match &cc.interned { | |
| 207 | crate::ConstScalar::UnevaluatedConst(const_id, subst) => { | |
| 208 | let mut subst = subst.clone(); | |
| 209 | self.fill_subst(&mut subst)?; | |
| 210 | *c = intern_const_scalar( | |
| 211 | crate::ConstScalar::UnevaluatedConst(*const_id, subst), | |
| 212 | c.data(Interner).ty.clone(), | |
| 213 | ); | |
| 214 | } | |
| 215 | crate::ConstScalar::Bytes(_, _) | crate::ConstScalar::Unknown => (), | |
| 216 | }, | |
| 217 | } | |
| 218 | self.fill_const(c)?; | |
| 121 | OperandKind::Constant { konst, ty } => { | |
| 122 | self.fill(konst)?; | |
| 123 | self.fill(ty)?; | |
| 219 | 124 | } |
| 220 | 125 | OperandKind::Copy(_) | OperandKind::Move(_) | OperandKind::Static(_) => (), |
| 221 | 126 | } |
| 222 | 127 | Ok(()) |
| 223 | 128 | } |
| 224 | 129 | |
| 225 | fn fill_body(&mut self, body: &mut MirBody) -> Result<(), MirLowerError> { | |
| 130 | fn fill_body(&mut self, body: &mut MirBody<'db>) -> Result<(), MirLowerError<'db>> { | |
| 226 | 131 | for (_, l) in body.locals.iter_mut() { |
| 227 | self.fill_ty(&mut l.ty)?; | |
| 132 | self.fill(&mut l.ty)?; | |
| 228 | 133 | } |
| 229 | 134 | for (_, bb) in body.basic_blocks.iter_mut() { |
| 230 | 135 | for statement in &mut bb.statements { |
| ... | ... | @@ -237,20 +142,20 @@ impl Filler<'_> { |
| 237 | 142 | match ak { |
| 238 | 143 | super::AggregateKind::Array(ty) |
| 239 | 144 | | super::AggregateKind::Tuple(ty) |
| 240 | | super::AggregateKind::Closure(ty) => self.fill_ty(ty)?, | |
| 241 | super::AggregateKind::Adt(_, subst) => self.fill_subst(subst)?, | |
| 145 | | super::AggregateKind::Closure(ty) => self.fill(ty)?, | |
| 146 | super::AggregateKind::Adt(_, subst) => self.fill(subst)?, | |
| 242 | 147 | super::AggregateKind::Union(_, _) => (), |
| 243 | 148 | } |
| 244 | 149 | } |
| 245 | 150 | Rvalue::ShallowInitBox(_, ty) | Rvalue::ShallowInitBoxWithAlloc(ty) => { |
| 246 | self.fill_ty(ty)?; | |
| 151 | self.fill(ty)?; | |
| 247 | 152 | } |
| 248 | 153 | Rvalue::Use(op) => { |
| 249 | 154 | self.fill_operand(op)?; |
| 250 | 155 | } |
| 251 | 156 | Rvalue::Repeat(op, len) => { |
| 252 | 157 | self.fill_operand(op)?; |
| 253 | self.fill_const(len)?; | |
| 158 | self.fill(len)?; | |
| 254 | 159 | } |
| 255 | 160 | Rvalue::Ref(_, _) |
| 256 | 161 | | Rvalue::Len(_) |
| ... | ... | @@ -304,11 +209,10 @@ impl Filler<'_> { |
| 304 | 209 | pub fn monomorphized_mir_body_query<'db>( |
| 305 | 210 | db: &'db dyn HirDatabase, |
| 306 | 211 | owner: DefWithBodyId, |
| 307 | subst: Substitution, | |
| 212 | subst: GenericArgs<'db>, | |
| 308 | 213 | trait_env: Arc<crate::TraitEnvironment<'db>>, |
| 309 | ) -> Result<Arc<MirBody>, MirLowerError> { | |
| 310 | let generics = owner.as_generic_def_id(db).map(|g_def| generics(db, g_def)); | |
| 311 | let filler = &mut Filler { db, subst: &subst, trait_env, generics }; | |
| 214 | ) -> Result<Arc<MirBody<'db>>, MirLowerError<'db>> { | |
| 215 | let mut filler = Filler::new(db, trait_env, subst); | |
| 312 | 216 | let body = db.mir_body(owner)?; |
| 313 | 217 | let mut body = (*body).clone(); |
| 314 | 218 | filler.fill_body(&mut body)?; |
| ... | ... | @@ -318,21 +222,19 @@ pub fn monomorphized_mir_body_query<'db>( |
| 318 | 222 | pub(crate) fn monomorphized_mir_body_cycle_result<'db>( |
| 319 | 223 | _db: &'db dyn HirDatabase, |
| 320 | 224 | _: DefWithBodyId, |
| 321 | _: Substitution, | |
| 225 | _: GenericArgs<'db>, | |
| 322 | 226 | _: Arc<crate::TraitEnvironment<'db>>, |
| 323 | ) -> Result<Arc<MirBody>, MirLowerError> { | |
| 227 | ) -> Result<Arc<MirBody<'db>>, MirLowerError<'db>> { | |
| 324 | 228 | Err(MirLowerError::Loop) |
| 325 | 229 | } |
| 326 | 230 | |
| 327 | 231 | pub fn monomorphized_mir_body_for_closure_query<'db>( |
| 328 | 232 | db: &'db dyn HirDatabase, |
| 329 | 233 | closure: InternedClosureId, |
| 330 | subst: Substitution, | |
| 234 | subst: GenericArgs<'db>, | |
| 331 | 235 | trait_env: Arc<crate::TraitEnvironment<'db>>, |
| 332 | ) -> Result<Arc<MirBody>, MirLowerError> { | |
| 333 | let InternedClosure(owner, _) = db.lookup_intern_closure(closure); | |
| 334 | let generics = owner.as_generic_def_id(db).map(|g_def| generics(db, g_def)); | |
| 335 | let filler = &mut Filler { db, subst: &subst, trait_env, generics }; | |
| 236 | ) -> Result<Arc<MirBody<'db>>, MirLowerError<'db>> { | |
| 237 | let mut filler = Filler::new(db, trait_env, subst); | |
| 336 | 238 | let body = db.mir_body_for_closure(closure)?; |
| 337 | 239 | let mut body = (*body).clone(); |
| 338 | 240 | filler.fill_body(&mut body)?; |
src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs+36-30| ... | ... | @@ -11,8 +11,7 @@ use hir_expand::{Lookup, name::Name}; |
| 11 | 11 | use la_arena::ArenaMap; |
| 12 | 12 | |
| 13 | 13 | use crate::{ |
| 14 | ClosureId, | |
| 15 | db::HirDatabase, | |
| 14 | db::{HirDatabase, InternedClosureId}, | |
| 16 | 15 | display::{ClosureStyle, DisplayTarget, HirDisplay}, |
| 17 | 16 | mir::{PlaceElem, ProjectionElem, StatementKind, TerminatorKind}, |
| 18 | 17 | }; |
| ... | ... | @@ -37,8 +36,8 @@ macro_rules! wln { |
| 37 | 36 | }; |
| 38 | 37 | } |
| 39 | 38 | |
| 40 | impl MirBody { | |
| 41 | pub fn pretty_print(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String { | |
| 39 | impl<'db> MirBody<'db> { | |
| 40 | pub fn pretty_print(&self, db: &'db dyn HirDatabase, display_target: DisplayTarget) -> String { | |
| 42 | 41 | let hir_body = db.body(self.owner); |
| 43 | 42 | let mut ctx = MirPrettyCtx::new(self, &hir_body, db, display_target); |
| 44 | 43 | ctx.for_body(|this| match ctx.body.owner { |
| ... | ... | @@ -81,7 +80,7 @@ impl MirBody { |
| 81 | 80 | |
| 82 | 81 | // String with lines is rendered poorly in `dbg` macros, which I use very much, so this |
| 83 | 82 | // function exists to solve that. |
| 84 | pub fn dbg(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> impl Debug { | |
| 83 | pub fn dbg(&self, db: &'db dyn HirDatabase, display_target: DisplayTarget) -> impl Debug { | |
| 85 | 84 | struct StringDbg(String); |
| 86 | 85 | impl Debug for StringDbg { |
| 87 | 86 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| ... | ... | @@ -92,17 +91,17 @@ impl MirBody { |
| 92 | 91 | } |
| 93 | 92 | } |
| 94 | 93 | |
| 95 | struct MirPrettyCtx<'a> { | |
| 96 | body: &'a MirBody, | |
| 94 | struct MirPrettyCtx<'a, 'db> { | |
| 95 | body: &'a MirBody<'db>, | |
| 97 | 96 | hir_body: &'a Body, |
| 98 | db: &'a dyn HirDatabase, | |
| 97 | db: &'db dyn HirDatabase, | |
| 99 | 98 | result: String, |
| 100 | 99 | indent: String, |
| 101 | local_to_binding: ArenaMap<LocalId, BindingId>, | |
| 100 | local_to_binding: ArenaMap<LocalId<'db>, BindingId>, | |
| 102 | 101 | display_target: DisplayTarget, |
| 103 | 102 | } |
| 104 | 103 | |
| 105 | impl Write for MirPrettyCtx<'_> { | |
| 104 | impl Write for MirPrettyCtx<'_, '_> { | |
| 106 | 105 | fn write_str(&mut self, s: &str) -> std::fmt::Result { |
| 107 | 106 | let mut it = s.split('\n'); // note: `.lines()` is wrong here |
| 108 | 107 | self.write(it.next().unwrap_or_default()); |
| ... | ... | @@ -114,12 +113,12 @@ impl Write for MirPrettyCtx<'_> { |
| 114 | 113 | } |
| 115 | 114 | } |
| 116 | 115 | |
| 117 | enum LocalName { | |
| 118 | Unknown(LocalId), | |
| 119 | Binding(Name, LocalId), | |
| 116 | enum LocalName<'db> { | |
| 117 | Unknown(LocalId<'db>), | |
| 118 | Binding(Name, LocalId<'db>), | |
| 120 | 119 | } |
| 121 | 120 | |
| 122 | impl HirDisplay for LocalName { | |
| 121 | impl<'db> HirDisplay for LocalName<'db> { | |
| 123 | 122 | fn hir_fmt( |
| 124 | 123 | &self, |
| 125 | 124 | f: &mut crate::display::HirFormatter<'_>, |
| ... | ... | @@ -133,8 +132,8 @@ impl HirDisplay for LocalName { |
| 133 | 132 | } |
| 134 | 133 | } |
| 135 | 134 | |
| 136 | impl<'a> MirPrettyCtx<'a> { | |
| 137 | fn for_body(&mut self, name: impl FnOnce(&mut MirPrettyCtx<'_>)) { | |
| 135 | impl<'a, 'db> MirPrettyCtx<'a, 'db> { | |
| 136 | fn for_body(&mut self, name: impl FnOnce(&mut MirPrettyCtx<'_, 'db>)) { | |
| 138 | 137 | name(self); |
| 139 | 138 | self.with_block(|this| { |
| 140 | 139 | this.locals(); |
| ... | ... | @@ -146,8 +145,8 @@ impl<'a> MirPrettyCtx<'a> { |
| 146 | 145 | } |
| 147 | 146 | } |
| 148 | 147 | |
| 149 | fn for_closure(&mut self, closure: ClosureId) { | |
| 150 | let body = match self.db.mir_body_for_closure(closure.into()) { | |
| 148 | fn for_closure(&mut self, closure: InternedClosureId) { | |
| 149 | let body = match self.db.mir_body_for_closure(closure) { | |
| 151 | 150 | Ok(it) => it, |
| 152 | 151 | Err(e) => { |
| 153 | 152 | wln!(self, "// error in {closure:?}: {e:?}"); |
| ... | ... | @@ -168,7 +167,7 @@ impl<'a> MirPrettyCtx<'a> { |
| 168 | 167 | self.indent = ctx.indent; |
| 169 | 168 | } |
| 170 | 169 | |
| 171 | fn with_block(&mut self, f: impl FnOnce(&mut MirPrettyCtx<'_>)) { | |
| 170 | fn with_block(&mut self, f: impl FnOnce(&mut MirPrettyCtx<'_, 'db>)) { | |
| 172 | 171 | self.indent += " "; |
| 173 | 172 | wln!(self, "{{"); |
| 174 | 173 | f(self); |
| ... | ... | @@ -180,9 +179,9 @@ impl<'a> MirPrettyCtx<'a> { |
| 180 | 179 | } |
| 181 | 180 | |
| 182 | 181 | fn new( |
| 183 | body: &'a MirBody, | |
| 182 | body: &'a MirBody<'db>, | |
| 184 | 183 | hir_body: &'a Body, |
| 185 | db: &'a dyn HirDatabase, | |
| 184 | db: &'db dyn HirDatabase, | |
| 186 | 185 | display_target: DisplayTarget, |
| 187 | 186 | ) -> Self { |
| 188 | 187 | let local_to_binding = body.local_to_binding_map(); |
| ... | ... | @@ -217,14 +216,14 @@ impl<'a> MirPrettyCtx<'a> { |
| 217 | 216 | } |
| 218 | 217 | } |
| 219 | 218 | |
| 220 | fn local_name(&self, local: LocalId) -> LocalName { | |
| 219 | fn local_name(&self, local: LocalId<'db>) -> LocalName<'db> { | |
| 221 | 220 | match self.local_to_binding.get(local) { |
| 222 | 221 | Some(b) => LocalName::Binding(self.hir_body[*b].name.clone(), local), |
| 223 | 222 | None => LocalName::Unknown(local), |
| 224 | 223 | } |
| 225 | 224 | } |
| 226 | 225 | |
| 227 | fn basic_block_id(&self, basic_block_id: BasicBlockId) -> String { | |
| 226 | fn basic_block_id(&self, basic_block_id: BasicBlockId<'db>) -> String { | |
| 228 | 227 | format!("'bb{}", u32::from(basic_block_id.into_raw())) |
| 229 | 228 | } |
| 230 | 229 | |
| ... | ... | @@ -312,8 +311,12 @@ impl<'a> MirPrettyCtx<'a> { |
| 312 | 311 | } |
| 313 | 312 | } |
| 314 | 313 | |
| 315 | fn place(&mut self, p: &Place) { | |
| 316 | fn f(this: &mut MirPrettyCtx<'_>, local: LocalId, projections: &[PlaceElem]) { | |
| 314 | fn place(&mut self, p: &Place<'db>) { | |
| 315 | fn f<'db>( | |
| 316 | this: &mut MirPrettyCtx<'_, 'db>, | |
| 317 | local: LocalId<'db>, | |
| 318 | projections: &[PlaceElem<'db>], | |
| 319 | ) { | |
| 317 | 320 | let Some((last, head)) = projections.split_last() else { |
| 318 | 321 | // no projection |
| 319 | 322 | w!(this, "{}", this.local_name(local).display_test(this.db, this.display_target)); |
| ... | ... | @@ -373,19 +376,19 @@ impl<'a> MirPrettyCtx<'a> { |
| 373 | 376 | f(self, p.local, p.projection.lookup(&self.body.projection_store)); |
| 374 | 377 | } |
| 375 | 378 | |
| 376 | fn operand(&mut self, r: &Operand) { | |
| 379 | fn operand(&mut self, r: &Operand<'db>) { | |
| 377 | 380 | match &r.kind { |
| 378 | 381 | OperandKind::Copy(p) | OperandKind::Move(p) => { |
| 379 | 382 | // MIR at the time of writing doesn't have difference between move and copy, so we show them |
| 380 | 383 | // equally. Feel free to change it. |
| 381 | 384 | self.place(p); |
| 382 | 385 | } |
| 383 | OperandKind::Constant(c) => w!(self, "Const({})", self.hir_display(c)), | |
| 386 | OperandKind::Constant { konst, .. } => w!(self, "Const({})", self.hir_display(konst)), | |
| 384 | 387 | OperandKind::Static(s) => w!(self, "Static({:?})", s), |
| 385 | 388 | } |
| 386 | 389 | } |
| 387 | 390 | |
| 388 | fn rvalue(&mut self, r: &Rvalue) { | |
| 391 | fn rvalue(&mut self, r: &Rvalue<'db>) { | |
| 389 | 392 | match r { |
| 390 | 393 | Rvalue::Use(op) => self.operand(op), |
| 391 | 394 | Rvalue::Ref(r, p) => { |
| ... | ... | @@ -475,7 +478,7 @@ impl<'a> MirPrettyCtx<'a> { |
| 475 | 478 | } |
| 476 | 479 | } |
| 477 | 480 | |
| 478 | fn operand_list(&mut self, it: &[Operand]) { | |
| 481 | fn operand_list(&mut self, it: &[Operand<'db>]) { | |
| 479 | 482 | let mut it = it.iter(); |
| 480 | 483 | if let Some(first) = it.next() { |
| 481 | 484 | self.operand(first); |
| ... | ... | @@ -486,7 +489,10 @@ impl<'a> MirPrettyCtx<'a> { |
| 486 | 489 | } |
| 487 | 490 | } |
| 488 | 491 | |
| 489 | fn hir_display<T: HirDisplay>(&self, ty: &'a T) -> impl Display + 'a { | |
| 492 | fn hir_display<'b, T: HirDisplay>(&self, ty: &'b T) -> impl Display + use<'a, 'b, 'db, T> | |
| 493 | where | |
| 494 | 'db: 'b, | |
| 495 | { | |
| 490 | 496 | ty.display_test(self.db, self.display_target) |
| 491 | 497 | .with_closure_style(ClosureStyle::ClosureWithSubst) |
| 492 | 498 | } |
src/tools/rust-analyzer/crates/hir-ty/src/next_solver.rs+3| ... | ... | @@ -33,6 +33,9 @@ pub use region::*; |
| 33 | 33 | pub use solver::*; |
| 34 | 34 | pub use ty::*; |
| 35 | 35 | |
| 36 | pub use crate::lower_nextsolver::ImplTraitIdx; | |
| 37 | pub use rustc_ast_ir::Mutability; | |
| 38 | ||
| 36 | 39 | pub type Binder<'db, T> = rustc_type_ir::Binder<DbInterner<'db>, T>; |
| 37 | 40 | pub type EarlyBinder<'db, T> = rustc_type_ir::EarlyBinder<DbInterner<'db>, T>; |
| 38 | 41 | pub type Canonical<'db, T> = rustc_type_ir::Canonical<DbInterner<'db>, T>; |
src/tools/rust-analyzer/crates/hir-ty/src/next_solver/consts.rs+44-59| ... | ... | @@ -4,10 +4,11 @@ use std::hash::Hash; |
| 4 | 4 | |
| 5 | 5 | use hir_def::{ConstParamId, TypeOrConstParamId}; |
| 6 | 6 | use intern::{Interned, Symbol}; |
| 7 | use macros::{TypeFoldable, TypeVisitable}; | |
| 7 | 8 | use rustc_ast_ir::{try_visit, visit::VisitorResult}; |
| 8 | 9 | use rustc_type_ir::{ |
| 9 | BoundVar, FlagComputation, Flags, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, | |
| 10 | TypeVisitable, TypeVisitableExt, WithCachedTypeInfo, | |
| 10 | BoundVar, DebruijnIndex, FlagComputation, Flags, TypeFoldable, TypeSuperFoldable, | |
| 11 | TypeSuperVisitable, TypeVisitable, TypeVisitableExt, WithCachedTypeInfo, | |
| 11 | 12 | inherent::{IntoKind, ParamEnv as _, PlaceholderLike, SliceLike}, |
| 12 | 13 | relate::Relate, |
| 13 | 14 | }; |
| ... | ... | @@ -23,7 +24,7 @@ use super::{BoundVarKind, DbInterner, ErrorGuaranteed, GenericArgs, Placeholder, |
| 23 | 24 | pub type ConstKind<'db> = rustc_type_ir::ConstKind<DbInterner<'db>>; |
| 24 | 25 | pub type UnevaluatedConst<'db> = rustc_type_ir::UnevaluatedConst<DbInterner<'db>>; |
| 25 | 26 | |
| 26 | #[salsa::interned(constructor = new_, debug)] | |
| 27 | #[salsa::interned(constructor = new_)] | |
| 27 | 28 | pub struct Const<'db> { |
| 28 | 29 | #[returns(ref)] |
| 29 | 30 | kind_: InternedWrapperNoDebug<WithCachedTypeInfo<ConstKind<'db>>>, |
| ... | ... | @@ -41,13 +42,12 @@ impl<'db> Const<'db> { |
| 41 | 42 | } |
| 42 | 43 | |
| 43 | 44 | pub fn inner(&self) -> &WithCachedTypeInfo<ConstKind<'db>> { |
| 44 | salsa::with_attached_database(|db| { | |
| 45 | crate::with_attached_db(|db| { | |
| 45 | 46 | let inner = &self.kind_(db).0; |
| 46 | 47 | // SAFETY: The caller already has access to a `Const<'db>`, so borrowchecking will |
| 47 | 48 | // make sure that our returned value is valid for the lifetime `'db`. |
| 48 | 49 | unsafe { std::mem::transmute(inner) } |
| 49 | 50 | }) |
| 50 | .unwrap() | |
| 51 | 51 | } |
| 52 | 52 | |
| 53 | 53 | pub fn error(interner: DbInterner<'db>) -> Self { |
| ... | ... | @@ -62,6 +62,25 @@ impl<'db> Const<'db> { |
| 62 | 62 | Const::new(interner, ConstKind::Placeholder(placeholder)) |
| 63 | 63 | } |
| 64 | 64 | |
| 65 | pub fn new_bound(interner: DbInterner<'db>, index: DebruijnIndex, bound: BoundConst) -> Self { | |
| 66 | Const::new(interner, ConstKind::Bound(index, bound)) | |
| 67 | } | |
| 68 | ||
| 69 | pub fn new_valtree( | |
| 70 | interner: DbInterner<'db>, | |
| 71 | ty: Ty<'db>, | |
| 72 | memory: Box<[u8]>, | |
| 73 | memory_map: MemoryMap<'db>, | |
| 74 | ) -> Self { | |
| 75 | Const::new( | |
| 76 | interner, | |
| 77 | ConstKind::Value(ValueConst { | |
| 78 | ty, | |
| 79 | value: Valtree::new(ConstBytes { memory, memory_map }), | |
| 80 | }), | |
| 81 | ) | |
| 82 | } | |
| 83 | ||
| 65 | 84 | pub fn is_ct_infer(&self) -> bool { |
| 66 | 85 | matches!(&self.inner().internee, ConstKind::Infer(_)) |
| 67 | 86 | } |
| ... | ... | @@ -78,6 +97,12 @@ impl<'db> Const<'db> { |
| 78 | 97 | } |
| 79 | 98 | } |
| 80 | 99 | |
| 100 | impl<'db> std::fmt::Debug for Const<'db> { | |
| 101 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
| 102 | self.inner().internee.fmt(f) | |
| 103 | } | |
| 104 | } | |
| 105 | ||
| 81 | 106 | impl<'db> std::fmt::Debug for InternedWrapperNoDebug<WithCachedTypeInfo<ConstKind<'db>>> { |
| 82 | 107 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 83 | 108 | self.0.internee.fmt(f) |
| ... | ... | @@ -136,10 +161,13 @@ impl ParamConst { |
| 136 | 161 | /// A type-level constant value. |
| 137 | 162 | /// |
| 138 | 163 | /// Represents a typed, fully evaluated constant. |
| 139 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] | |
| 164 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, TypeFoldable, TypeVisitable)] | |
| 140 | 165 | pub struct ValueConst<'db> { |
| 141 | pub(crate) ty: Ty<'db>, | |
| 142 | pub(crate) value: Valtree<'db>, | |
| 166 | pub ty: Ty<'db>, | |
| 167 | // FIXME: Should we ignore this for TypeVisitable, TypeFoldable? | |
| 168 | #[type_visitable(ignore)] | |
| 169 | #[type_foldable(identity)] | |
| 170 | pub value: Valtree<'db>, | |
| 143 | 171 | } |
| 144 | 172 | |
| 145 | 173 | impl<'db> ValueConst<'db> { |
| ... | ... | @@ -159,33 +187,15 @@ impl<'db> rustc_type_ir::inherent::ValueConst<DbInterner<'db>> for ValueConst<'d |
| 159 | 187 | } |
| 160 | 188 | } |
| 161 | 189 | |
| 162 | impl<'db> rustc_type_ir::TypeVisitable<DbInterner<'db>> for ValueConst<'db> { | |
| 163 | fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>( | |
| 164 | &self, | |
| 165 | visitor: &mut V, | |
| 166 | ) -> V::Result { | |
| 167 | self.ty.visit_with(visitor) | |
| 168 | } | |
| 169 | } | |
| 170 | ||
| 171 | impl<'db> rustc_type_ir::TypeFoldable<DbInterner<'db>> for ValueConst<'db> { | |
| 172 | fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self { | |
| 173 | ValueConst { ty: self.ty.fold_with(folder), value: self.value } | |
| 174 | } | |
| 175 | fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>( | |
| 176 | self, | |
| 177 | folder: &mut F, | |
| 178 | ) -> Result<Self, F::Error> { | |
| 179 | Ok(ValueConst { ty: self.ty.try_fold_with(folder)?, value: self.value }) | |
| 180 | } | |
| 181 | } | |
| 182 | ||
| 183 | 190 | #[derive(Debug, Clone, PartialEq, Eq)] |
| 184 | pub struct ConstBytes<'db>(pub Box<[u8]>, pub MemoryMap<'db>); | |
| 191 | pub struct ConstBytes<'db> { | |
| 192 | pub memory: Box<[u8]>, | |
| 193 | pub memory_map: MemoryMap<'db>, | |
| 194 | } | |
| 185 | 195 | |
| 186 | 196 | impl Hash for ConstBytes<'_> { |
| 187 | 197 | fn hash<H: std::hash::Hasher>(&self, state: &mut H) { |
| 188 | self.0.hash(state) | |
| 198 | self.memory.hash(state) | |
| 189 | 199 | } |
| 190 | 200 | } |
| 191 | 201 | |
| ... | ... | @@ -197,25 +207,23 @@ pub struct Valtree<'db> { |
| 197 | 207 | |
| 198 | 208 | impl<'db> Valtree<'db> { |
| 199 | 209 | pub fn new(bytes: ConstBytes<'db>) -> Self { |
| 200 | salsa::with_attached_database(|db| unsafe { | |
| 210 | crate::with_attached_db(|db| unsafe { | |
| 201 | 211 | // SAFETY: ¯\_(ツ)_/¯ |
| 202 | 212 | std::mem::transmute(Valtree::new_(db, bytes)) |
| 203 | 213 | }) |
| 204 | .unwrap() | |
| 205 | 214 | } |
| 206 | 215 | |
| 207 | 216 | pub fn inner(&self) -> &ConstBytes<'db> { |
| 208 | salsa::with_attached_database(|db| { | |
| 217 | crate::with_attached_db(|db| { | |
| 209 | 218 | let inner = self.bytes_(db); |
| 210 | 219 | // SAFETY: The caller already has access to a `Valtree<'db>`, so borrowchecking will |
| 211 | 220 | // make sure that our returned value is valid for the lifetime `'db`. |
| 212 | 221 | unsafe { std::mem::transmute(inner) } |
| 213 | 222 | }) |
| 214 | .unwrap() | |
| 215 | 223 | } |
| 216 | 224 | } |
| 217 | 225 | |
| 218 | #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] | |
| 226 | #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, TypeVisitable, TypeFoldable)] | |
| 219 | 227 | pub struct ExprConst; |
| 220 | 228 | |
| 221 | 229 | impl rustc_type_ir::inherent::ParamLike for ParamConst { |
| ... | ... | @@ -415,29 +423,6 @@ impl<'db> PlaceholderLike<DbInterner<'db>> for PlaceholderConst { |
| 415 | 423 | } |
| 416 | 424 | } |
| 417 | 425 | |
| 418 | impl<'db> TypeVisitable<DbInterner<'db>> for ExprConst { | |
| 419 | fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>( | |
| 420 | &self, | |
| 421 | visitor: &mut V, | |
| 422 | ) -> V::Result { | |
| 423 | // Ensure we get back to this when we fill in the fields | |
| 424 | let ExprConst = &self; | |
| 425 | V::Result::output() | |
| 426 | } | |
| 427 | } | |
| 428 | ||
| 429 | impl<'db> TypeFoldable<DbInterner<'db>> for ExprConst { | |
| 430 | fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>( | |
| 431 | self, | |
| 432 | folder: &mut F, | |
| 433 | ) -> Result<Self, F::Error> { | |
| 434 | Ok(ExprConst) | |
| 435 | } | |
| 436 | fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self { | |
| 437 | ExprConst | |
| 438 | } | |
| 439 | } | |
| 440 | ||
| 441 | 426 | impl<'db> Relate<DbInterner<'db>> for ExprConst { |
| 442 | 427 | fn relate<R: rustc_type_ir::relate::TypeRelation<DbInterner<'db>>>( |
| 443 | 428 | relation: &mut R, |
src/tools/rust-analyzer/crates/hir-ty/src/next_solver/def_id.rs+32-2| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | 1 | //! Definition of `SolverDefId` |
| 2 | 2 | |
| 3 | 3 | use hir_def::{ |
| 4 | AdtId, CallableDefId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, | |
| 5 | StaticId, StructId, TraitId, TypeAliasId, UnionId, | |
| 4 | AdtId, CallableDefId, ConstId, EnumId, EnumVariantId, FunctionId, GeneralConstId, GenericDefId, | |
| 5 | ImplId, StaticId, StructId, TraitId, TypeAliasId, UnionId, | |
| 6 | 6 | }; |
| 7 | 7 | use rustc_type_ir::inherent; |
| 8 | 8 | use stdx::impl_from; |
| ... | ... | @@ -119,6 +119,16 @@ impl From<GenericDefId> for SolverDefId { |
| 119 | 119 | } |
| 120 | 120 | } |
| 121 | 121 | |
| 122 | impl From<GeneralConstId> for SolverDefId { | |
| 123 | #[inline] | |
| 124 | fn from(value: GeneralConstId) -> Self { | |
| 125 | match value { | |
| 126 | GeneralConstId::ConstId(const_id) => SolverDefId::ConstId(const_id), | |
| 127 | GeneralConstId::StaticId(static_id) => SolverDefId::StaticId(static_id), | |
| 128 | } | |
| 129 | } | |
| 130 | } | |
| 131 | ||
| 122 | 132 | impl TryFrom<SolverDefId> for GenericDefId { |
| 123 | 133 | type Error = SolverDefId; |
| 124 | 134 | |
| ... | ... | @@ -139,6 +149,26 @@ impl TryFrom<SolverDefId> for GenericDefId { |
| 139 | 149 | } |
| 140 | 150 | } |
| 141 | 151 | |
| 152 | impl SolverDefId { | |
| 153 | #[inline] | |
| 154 | #[track_caller] | |
| 155 | pub fn expect_opaque_ty(self) -> InternedOpaqueTyId { | |
| 156 | match self { | |
| 157 | SolverDefId::InternedOpaqueTyId(it) => it, | |
| 158 | _ => panic!("expected opaque type, found {self:?}"), | |
| 159 | } | |
| 160 | } | |
| 161 | ||
| 162 | #[inline] | |
| 163 | #[track_caller] | |
| 164 | pub fn expect_type_alias(self) -> TypeAliasId { | |
| 165 | match self { | |
| 166 | SolverDefId::TypeAliasId(it) => it, | |
| 167 | _ => panic!("expected type alias, found {self:?}"), | |
| 168 | } | |
| 169 | } | |
| 170 | } | |
| 171 | ||
| 142 | 172 | impl<'db> inherent::DefId<DbInterner<'db>> for SolverDefId { |
| 143 | 173 | fn as_local(self) -> Option<SolverDefId> { |
| 144 | 174 | Some(self) |
src/tools/rust-analyzer/crates/hir-ty/src/next_solver/fold.rs+23| ... | ... | @@ -129,3 +129,26 @@ where |
| 129 | 129 | if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p } |
| 130 | 130 | } |
| 131 | 131 | } |
| 132 | ||
| 133 | pub fn fold_tys<'db, T: TypeFoldable<DbInterner<'db>>>( | |
| 134 | interner: DbInterner<'db>, | |
| 135 | t: T, | |
| 136 | callback: impl FnMut(Ty<'db>) -> Ty<'db>, | |
| 137 | ) -> T { | |
| 138 | struct Folder<'db, F> { | |
| 139 | interner: DbInterner<'db>, | |
| 140 | callback: F, | |
| 141 | } | |
| 142 | impl<'db, F: FnMut(Ty<'db>) -> Ty<'db>> TypeFolder<DbInterner<'db>> for Folder<'db, F> { | |
| 143 | fn cx(&self) -> DbInterner<'db> { | |
| 144 | self.interner | |
| 145 | } | |
| 146 | ||
| 147 | fn fold_ty(&mut self, t: Ty<'db>) -> Ty<'db> { | |
| 148 | let t = t.super_fold_with(self); | |
| 149 | (self.callback)(t) | |
| 150 | } | |
| 151 | } | |
| 152 | ||
| 153 | t.fold_with(&mut Folder { interner, callback }) | |
| 154 | } |
src/tools/rust-analyzer/crates/hir-ty/src/next_solver/generic_arg.rs+92-66| ... | ... | @@ -1,7 +1,9 @@ |
| 1 | 1 | //! Things related to generic args in the next-trait-solver. |
| 2 | 2 | |
| 3 | use hir_def::GenericParamId; | |
| 3 | use hir_def::{GenericDefId, GenericParamId}; | |
| 4 | 4 | use intern::{Interned, Symbol}; |
| 5 | use macros::{TypeFoldable, TypeVisitable}; | |
| 6 | use rustc_type_ir::inherent::Const as _; | |
| 5 | 7 | use rustc_type_ir::{ |
| 6 | 8 | ClosureArgs, CollectAndApply, ConstVid, CoroutineArgs, CoroutineClosureArgs, FnSig, FnSigTys, |
| 7 | 9 | GenericArgKind, IntTy, Interner, TermKind, TyKind, TyVid, TypeFoldable, TypeVisitable, |
| ... | ... | @@ -22,7 +24,7 @@ use super::{ |
| 22 | 24 | interned_vec_db, |
| 23 | 25 | }; |
| 24 | 26 | |
| 25 | #[derive(Copy, Clone, PartialEq, Eq, Hash)] | |
| 27 | #[derive(Copy, Clone, PartialEq, Eq, Hash, TypeVisitable, TypeFoldable)] | |
| 26 | 28 | pub enum GenericArg<'db> { |
| 27 | 29 | Ty(Ty<'db>), |
| 28 | 30 | Lifetime(Region<'db>), |
| ... | ... | @@ -54,12 +56,27 @@ impl<'db> GenericArg<'db> { |
| 54 | 56 | } |
| 55 | 57 | } |
| 56 | 58 | |
| 59 | pub fn konst(self) -> Option<Const<'db>> { | |
| 60 | match self.kind() { | |
| 61 | GenericArgKind::Const(konst) => Some(konst), | |
| 62 | _ => None, | |
| 63 | } | |
| 64 | } | |
| 65 | ||
| 57 | 66 | pub fn region(self) -> Option<Region<'db>> { |
| 58 | 67 | match self.kind() { |
| 59 | 68 | GenericArgKind::Lifetime(r) => Some(r), |
| 60 | 69 | _ => None, |
| 61 | 70 | } |
| 62 | 71 | } |
| 72 | ||
| 73 | pub fn error_from_id(interner: DbInterner<'db>, id: GenericParamId) -> GenericArg<'db> { | |
| 74 | match id { | |
| 75 | GenericParamId::TypeParamId(_) => Ty::new_error(interner, ErrorGuaranteed).into(), | |
| 76 | GenericParamId::ConstParamId(_) => Const::error(interner).into(), | |
| 77 | GenericParamId::LifetimeParamId(_) => Region::error(interner).into(), | |
| 78 | } | |
| 79 | } | |
| 63 | 80 | } |
| 64 | 81 | |
| 65 | 82 | impl<'db> From<Term<'db>> for GenericArg<'db> { |
| ... | ... | @@ -71,7 +88,7 @@ impl<'db> From<Term<'db>> for GenericArg<'db> { |
| 71 | 88 | } |
| 72 | 89 | } |
| 73 | 90 | |
| 74 | #[derive(Copy, Clone, PartialEq, Eq, Hash)] | |
| 91 | #[derive(Copy, Clone, PartialEq, Eq, Hash, TypeVisitable, TypeFoldable)] | |
| 75 | 92 | pub enum Term<'db> { |
| 76 | 93 | Ty(Ty<'db>), |
| 77 | 94 | Const(Const<'db>), |
| ... | ... | @@ -129,39 +146,6 @@ impl<'db> IntoKind for GenericArg<'db> { |
| 129 | 146 | } |
| 130 | 147 | } |
| 131 | 148 | |
| 132 | impl<'db> TypeVisitable<DbInterner<'db>> for GenericArg<'db> { | |
| 133 | fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>( | |
| 134 | &self, | |
| 135 | visitor: &mut V, | |
| 136 | ) -> V::Result { | |
| 137 | match self { | |
| 138 | GenericArg::Lifetime(lt) => lt.visit_with(visitor), | |
| 139 | GenericArg::Ty(ty) => ty.visit_with(visitor), | |
| 140 | GenericArg::Const(ct) => ct.visit_with(visitor), | |
| 141 | } | |
| 142 | } | |
| 143 | } | |
| 144 | ||
| 145 | impl<'db> TypeFoldable<DbInterner<'db>> for GenericArg<'db> { | |
| 146 | fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>( | |
| 147 | self, | |
| 148 | folder: &mut F, | |
| 149 | ) -> Result<Self, F::Error> { | |
| 150 | match self.kind() { | |
| 151 | GenericArgKind::Lifetime(lt) => lt.try_fold_with(folder).map(Into::into), | |
| 152 | GenericArgKind::Type(ty) => ty.try_fold_with(folder).map(Into::into), | |
| 153 | GenericArgKind::Const(ct) => ct.try_fold_with(folder).map(Into::into), | |
| 154 | } | |
| 155 | } | |
| 156 | fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self { | |
| 157 | match self.kind() { | |
| 158 | GenericArgKind::Lifetime(lt) => lt.fold_with(folder).into(), | |
| 159 | GenericArgKind::Type(ty) => ty.fold_with(folder).into(), | |
| 160 | GenericArgKind::Const(ct) => ct.fold_with(folder).into(), | |
| 161 | } | |
| 162 | } | |
| 163 | } | |
| 164 | ||
| 165 | 149 | impl<'db> Relate<DbInterner<'db>> for GenericArg<'db> { |
| 166 | 150 | fn relate<R: rustc_type_ir::relate::TypeRelation<DbInterner<'db>>>( |
| 167 | 151 | relation: &mut R, |
| ... | ... | @@ -216,6 +200,66 @@ impl<'db> GenericArgs<'db> { |
| 216 | 200 | interner.mk_args(&args) |
| 217 | 201 | } |
| 218 | 202 | |
| 203 | /// Creates an all-error `GenericArgs`. | |
| 204 | pub fn error_for_item(interner: DbInterner<'db>, def_id: SolverDefId) -> GenericArgs<'db> { | |
| 205 | GenericArgs::for_item(interner, def_id, |_, _, id, _| { | |
| 206 | GenericArg::error_from_id(interner, id) | |
| 207 | }) | |
| 208 | } | |
| 209 | ||
| 210 | /// Like `for_item`, but prefers the default of a parameter if it has any. | |
| 211 | pub fn for_item_with_defaults<F>( | |
| 212 | interner: DbInterner<'db>, | |
| 213 | def_id: GenericDefId, | |
| 214 | mut fallback: F, | |
| 215 | ) -> GenericArgs<'db> | |
| 216 | where | |
| 217 | F: FnMut(&Symbol, u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>, | |
| 218 | { | |
| 219 | let defaults = interner.db.generic_defaults_ns(def_id); | |
| 220 | Self::for_item(interner, def_id.into(), |name, idx, id, prev| { | |
| 221 | match defaults.get(idx as usize) { | |
| 222 | Some(default) => default.instantiate(interner, prev), | |
| 223 | None => fallback(name, idx, id, prev), | |
| 224 | } | |
| 225 | }) | |
| 226 | } | |
| 227 | ||
| 228 | /// Like `for_item()`, but calls first uses the args from `first`. | |
| 229 | pub fn fill_rest<F>( | |
| 230 | interner: DbInterner<'db>, | |
| 231 | def_id: SolverDefId, | |
| 232 | first: impl IntoIterator<Item = GenericArg<'db>>, | |
| 233 | mut fallback: F, | |
| 234 | ) -> GenericArgs<'db> | |
| 235 | where | |
| 236 | F: FnMut(&Symbol, u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>, | |
| 237 | { | |
| 238 | let mut iter = first.into_iter(); | |
| 239 | Self::for_item(interner, def_id, |name, idx, id, prev| { | |
| 240 | iter.next().unwrap_or_else(|| fallback(name, idx, id, prev)) | |
| 241 | }) | |
| 242 | } | |
| 243 | ||
| 244 | /// Appends default param values to `first` if needed. Params without default will call `fallback()`. | |
| 245 | pub fn fill_with_defaults<F>( | |
| 246 | interner: DbInterner<'db>, | |
| 247 | def_id: GenericDefId, | |
| 248 | first: impl IntoIterator<Item = GenericArg<'db>>, | |
| 249 | mut fallback: F, | |
| 250 | ) -> GenericArgs<'db> | |
| 251 | where | |
| 252 | F: FnMut(&Symbol, u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>, | |
| 253 | { | |
| 254 | let defaults = interner.db.generic_defaults_ns(def_id); | |
| 255 | Self::fill_rest(interner, def_id.into(), first, |name, idx, id, prev| { | |
| 256 | defaults | |
| 257 | .get(idx as usize) | |
| 258 | .map(|default| default.instantiate(interner, prev)) | |
| 259 | .unwrap_or_else(|| fallback(name, idx, id, prev)) | |
| 260 | }) | |
| 261 | } | |
| 262 | ||
| 219 | 263 | fn fill_item<F>( |
| 220 | 264 | args: &mut SmallVec<[GenericArg<'db>; 8]>, |
| 221 | 265 | interner: DbInterner<'_>, |
| ... | ... | @@ -271,6 +315,18 @@ impl<'db> GenericArgs<'db> { |
| 271 | 315 | } |
| 272 | 316 | } |
| 273 | 317 | } |
| 318 | ||
| 319 | pub fn types(self) -> impl Iterator<Item = Ty<'db>> { | |
| 320 | self.iter().filter_map(|it| it.as_type()) | |
| 321 | } | |
| 322 | ||
| 323 | pub fn consts(self) -> impl Iterator<Item = Const<'db>> { | |
| 324 | self.iter().filter_map(|it| it.as_const()) | |
| 325 | } | |
| 326 | ||
| 327 | pub fn regions(self) -> impl Iterator<Item = Region<'db>> { | |
| 328 | self.iter().filter_map(|it| it.as_region()) | |
| 329 | } | |
| 274 | 330 | } |
| 275 | 331 | |
| 276 | 332 | impl<'db> rustc_type_ir::relate::Relate<DbInterner<'db>> for GenericArgs<'db> { |
| ... | ... | @@ -487,36 +543,6 @@ impl<'db> From<Const<'db>> for Term<'db> { |
| 487 | 543 | } |
| 488 | 544 | } |
| 489 | 545 | |
| 490 | impl<'db> TypeVisitable<DbInterner<'db>> for Term<'db> { | |
| 491 | fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>( | |
| 492 | &self, | |
| 493 | visitor: &mut V, | |
| 494 | ) -> V::Result { | |
| 495 | match self { | |
| 496 | Term::Ty(ty) => ty.visit_with(visitor), | |
| 497 | Term::Const(ct) => ct.visit_with(visitor), | |
| 498 | } | |
| 499 | } | |
| 500 | } | |
| 501 | ||
| 502 | impl<'db> TypeFoldable<DbInterner<'db>> for Term<'db> { | |
| 503 | fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>( | |
| 504 | self, | |
| 505 | folder: &mut F, | |
| 506 | ) -> Result<Self, F::Error> { | |
| 507 | match self.kind() { | |
| 508 | TermKind::Ty(ty) => ty.try_fold_with(folder).map(Into::into), | |
| 509 | TermKind::Const(ct) => ct.try_fold_with(folder).map(Into::into), | |
| 510 | } | |
| 511 | } | |
| 512 | fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self { | |
| 513 | match self.kind() { | |
| 514 | TermKind::Ty(ty) => ty.fold_with(folder).into(), | |
| 515 | TermKind::Const(ct) => ct.fold_with(folder).into(), | |
| 516 | } | |
| 517 | } | |
| 518 | } | |
| 519 | ||
| 520 | 546 | impl<'db> Relate<DbInterner<'db>> for Term<'db> { |
| 521 | 547 | fn relate<R: rustc_type_ir::relate::TypeRelation<DbInterner<'db>>>( |
| 522 | 548 | relation: &mut R, |
src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/mod.rs+114-2| ... | ... | @@ -10,6 +10,7 @@ pub use at::DefineOpaqueTypes; |
| 10 | 10 | use ena::undo_log::UndoLogs; |
| 11 | 11 | use ena::unify as ut; |
| 12 | 12 | use hir_def::GenericParamId; |
| 13 | use hir_def::lang_item::LangItem; | |
| 13 | 14 | use intern::Symbol; |
| 14 | 15 | use opaque_types::{OpaqueHiddenType, OpaqueTypeStorage}; |
| 15 | 16 | use region_constraints::{ |
| ... | ... | @@ -18,6 +19,7 @@ use region_constraints::{ |
| 18 | 19 | pub use relate::StructurallyRelateAliases; |
| 19 | 20 | pub use relate::combine::PredicateEmittingRelation; |
| 20 | 21 | use rustc_hash::{FxHashMap, FxHashSet}; |
| 22 | use rustc_next_trait_solver::solve::SolverDelegateEvalExt; | |
| 21 | 23 | use rustc_pattern_analysis::Captures; |
| 22 | 24 | use rustc_type_ir::error::{ExpectedFound, TypeError}; |
| 23 | 25 | use rustc_type_ir::inherent::{ |
| ... | ... | @@ -38,7 +40,10 @@ use unify_key::{ConstVariableOrigin, ConstVariableValue, ConstVidKey}; |
| 38 | 40 | |
| 39 | 41 | use crate::next_solver::fold::BoundVarReplacerDelegate; |
| 40 | 42 | use crate::next_solver::infer::opaque_types::table::OpaqueTypeStorageEntries; |
| 41 | use crate::next_solver::{BoundConst, BoundRegion, BoundTy, BoundVarKind}; | |
| 43 | use crate::next_solver::infer::select::EvaluationResult; | |
| 44 | use crate::next_solver::infer::traits::PredicateObligation; | |
| 45 | use crate::next_solver::obligation_ctxt::ObligationCtxt; | |
| 46 | use crate::next_solver::{BoundConst, BoundRegion, BoundTy, BoundVarKind, Goal, SolverContext}; | |
| 42 | 47 | |
| 43 | 48 | use super::generics::GenericParamDef; |
| 44 | 49 | use super::{ |
| ... | ... | @@ -62,7 +67,7 @@ pub(crate) mod traits; |
| 62 | 67 | mod type_variable; |
| 63 | 68 | mod unify_key; |
| 64 | 69 | |
| 65 | /// `InferOk<'tcx, ()>` is used a lot. It may seem like a useless wrapper | |
| 70 | /// `InferOk<'db, ()>` is used a lot. It may seem like a useless wrapper | |
| 66 | 71 | /// around `PredicateObligations`, but it has one important property: |
| 67 | 72 | /// because `InferOk` is marked with `#[must_use]`, if you have a method |
| 68 | 73 | /// `InferCtxt::f` that returns `InferResult<()>` and you call it with |
| ... | ... | @@ -395,6 +400,102 @@ impl<'db> InferCtxt<'db> { |
| 395 | 400 | self.typing_mode |
| 396 | 401 | } |
| 397 | 402 | |
| 403 | /// See the comment on [OpaqueTypesJank](crate::solve::OpaqueTypesJank) | |
| 404 | /// for more details. | |
| 405 | pub fn predicate_may_hold_opaque_types_jank( | |
| 406 | &self, | |
| 407 | obligation: &PredicateObligation<'db>, | |
| 408 | ) -> bool { | |
| 409 | <&SolverContext<'db>>::from(self).root_goal_may_hold_opaque_types_jank(Goal::new( | |
| 410 | self.interner, | |
| 411 | obligation.param_env, | |
| 412 | obligation.predicate, | |
| 413 | )) | |
| 414 | } | |
| 415 | ||
| 416 | /// Evaluates whether the predicate can be satisfied in the given | |
| 417 | /// `ParamEnv`, and returns `false` if not certain. However, this is | |
| 418 | /// not entirely accurate if inference variables are involved. | |
| 419 | /// | |
| 420 | /// This version may conservatively fail when outlives obligations | |
| 421 | /// are required. Therefore, this version should only be used for | |
| 422 | /// optimizations or diagnostics and be treated as if it can always | |
| 423 | /// return `false`. | |
| 424 | /// | |
| 425 | /// # Example | |
| 426 | /// | |
| 427 | /// ``` | |
| 428 | /// # #![allow(dead_code)] | |
| 429 | /// trait Trait {} | |
| 430 | /// | |
| 431 | /// fn check<T: Trait>() {} | |
| 432 | /// | |
| 433 | /// fn foo<T: 'static>() | |
| 434 | /// where | |
| 435 | /// &'static T: Trait, | |
| 436 | /// { | |
| 437 | /// // Evaluating `&'?0 T: Trait` adds a `'?0: 'static` outlives obligation, | |
| 438 | /// // which means that `predicate_must_hold_considering_regions` will return | |
| 439 | /// // `false`. | |
| 440 | /// check::<&'_ T>(); | |
| 441 | /// } | |
| 442 | /// ``` | |
| 443 | fn predicate_must_hold_considering_regions( | |
| 444 | &self, | |
| 445 | obligation: &PredicateObligation<'db>, | |
| 446 | ) -> bool { | |
| 447 | self.evaluate_obligation(obligation).must_apply_considering_regions() | |
| 448 | } | |
| 449 | ||
| 450 | /// Evaluates whether the predicate can be satisfied in the given | |
| 451 | /// `ParamEnv`, and returns `false` if not certain. However, this is | |
| 452 | /// not entirely accurate if inference variables are involved. | |
| 453 | /// | |
| 454 | /// This version ignores all outlives constraints. | |
| 455 | fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'db>) -> bool { | |
| 456 | self.evaluate_obligation(obligation).must_apply_modulo_regions() | |
| 457 | } | |
| 458 | ||
| 459 | /// Evaluate a given predicate, capturing overflow and propagating it back. | |
| 460 | fn evaluate_obligation(&self, obligation: &PredicateObligation<'db>) -> EvaluationResult { | |
| 461 | let param_env = obligation.param_env; | |
| 462 | ||
| 463 | self.probe(|snapshot| { | |
| 464 | let mut ocx = ObligationCtxt::new(self); | |
| 465 | ocx.register_obligation(obligation.clone()); | |
| 466 | let mut result = EvaluationResult::EvaluatedToOk; | |
| 467 | for error in ocx.evaluate_obligations_error_on_ambiguity() { | |
| 468 | if error.is_true_error() { | |
| 469 | return EvaluationResult::EvaluatedToErr; | |
| 470 | } else { | |
| 471 | result = result.max(EvaluationResult::EvaluatedToAmbig); | |
| 472 | } | |
| 473 | } | |
| 474 | if self.opaque_types_added_in_snapshot(snapshot) { | |
| 475 | result = result.max(EvaluationResult::EvaluatedToOkModuloOpaqueTypes); | |
| 476 | } else if self.region_constraints_added_in_snapshot(snapshot) { | |
| 477 | result = result.max(EvaluationResult::EvaluatedToOkModuloRegions); | |
| 478 | } | |
| 479 | result | |
| 480 | }) | |
| 481 | } | |
| 482 | ||
| 483 | pub fn type_is_copy_modulo_regions(&self, param_env: ParamEnv<'db>, ty: Ty<'db>) -> bool { | |
| 484 | let ty = self.resolve_vars_if_possible(ty); | |
| 485 | ||
| 486 | let Some(copy_def_id) = | |
| 487 | LangItem::Copy.resolve_trait(self.interner.db, self.interner.krate.unwrap()) | |
| 488 | else { | |
| 489 | return false; | |
| 490 | }; | |
| 491 | ||
| 492 | // This can get called from typeck (by euv), and `moves_by_default` | |
| 493 | // rightly refuses to work with inference variables, but | |
| 494 | // moves_by_default has a cache, which we want to use in other | |
| 495 | // cases. | |
| 496 | traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id) | |
| 497 | } | |
| 498 | ||
| 398 | 499 | pub fn unresolved_variables(&self) -> Vec<Ty<'db>> { |
| 399 | 500 | let mut inner = self.inner.borrow_mut(); |
| 400 | 501 | let mut vars: Vec<Ty<'db>> = inner |
| ... | ... | @@ -682,6 +783,17 @@ impl<'db> InferCtxt<'db> { |
| 682 | 783 | }) |
| 683 | 784 | } |
| 684 | 785 | |
| 786 | /// Like `fresh_args_for_item()`, but first uses the args from `first`. | |
| 787 | pub fn fill_rest_fresh_args( | |
| 788 | &self, | |
| 789 | def_id: SolverDefId, | |
| 790 | first: impl IntoIterator<Item = GenericArg<'db>>, | |
| 791 | ) -> GenericArgs<'db> { | |
| 792 | GenericArgs::fill_rest(self.interner, def_id, first, |name, index, kind, _| { | |
| 793 | self.var_for_def(kind, name) | |
| 794 | }) | |
| 795 | } | |
| 796 | ||
| 685 | 797 | /// Returns `true` if errors have been reported since this infcx was |
| 686 | 798 | /// created. This is sometimes used as a heuristic to skip |
| 687 | 799 | /// reporting errors that often occur as a result of earlier |
src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/resolve.rs+49-3| ... | ... | @@ -2,11 +2,12 @@ |
| 2 | 2 | |
| 3 | 3 | use rustc_type_ir::{ |
| 4 | 4 | ConstKind, FallibleTypeFolder, InferConst, InferTy, RegionKind, TyKind, TypeFoldable, |
| 5 | TypeFolder, TypeSuperFoldable, TypeVisitableExt, data_structures::DelayedMap, | |
| 6 | inherent::IntoKind, | |
| 5 | TypeFolder, TypeSuperFoldable, TypeVisitableExt, | |
| 6 | data_structures::DelayedMap, | |
| 7 | inherent::{Const as _, IntoKind, Ty as _}, | |
| 7 | 8 | }; |
| 8 | 9 | |
| 9 | use crate::next_solver::{Const, DbInterner, Region, Ty}; | |
| 10 | use crate::next_solver::{Const, DbInterner, ErrorGuaranteed, Region, Ty}; | |
| 10 | 11 | |
| 11 | 12 | use super::{FixupError, FixupResult, InferCtxt}; |
| 12 | 13 | |
| ... | ... | @@ -60,3 +61,48 @@ impl<'a, 'db> TypeFolder<DbInterner<'db>> for OpportunisticVarResolver<'a, 'db> |
| 60 | 61 | } |
| 61 | 62 | } |
| 62 | 63 | } |
| 64 | ||
| 65 | pub struct ReplaceInferWithError<'db> { | |
| 66 | interner: DbInterner<'db>, | |
| 67 | } | |
| 68 | ||
| 69 | impl<'db> ReplaceInferWithError<'db> { | |
| 70 | #[inline] | |
| 71 | pub fn new(interner: DbInterner<'db>) -> Self { | |
| 72 | Self { interner } | |
| 73 | } | |
| 74 | } | |
| 75 | ||
| 76 | impl<'db> TypeFolder<DbInterner<'db>> for ReplaceInferWithError<'db> { | |
| 77 | fn cx(&self) -> DbInterner<'db> { | |
| 78 | self.interner | |
| 79 | } | |
| 80 | ||
| 81 | fn fold_ty(&mut self, t: Ty<'db>) -> Ty<'db> { | |
| 82 | if !t.has_infer() { | |
| 83 | return t; | |
| 84 | } | |
| 85 | ||
| 86 | if t.is_infer() { | |
| 87 | Ty::new_error(self.interner, ErrorGuaranteed) | |
| 88 | } else { | |
| 89 | t.super_fold_with(self) | |
| 90 | } | |
| 91 | } | |
| 92 | ||
| 93 | fn fold_const(&mut self, c: Const<'db>) -> Const<'db> { | |
| 94 | if !c.has_infer() { | |
| 95 | return c; | |
| 96 | } | |
| 97 | ||
| 98 | if c.is_ct_infer() { | |
| 99 | Const::new_error(self.interner, ErrorGuaranteed) | |
| 100 | } else { | |
| 101 | c.super_fold_with(self) | |
| 102 | } | |
| 103 | } | |
| 104 | ||
| 105 | fn fold_region(&mut self, r: Region<'db>) -> Region<'db> { | |
| 106 | if r.is_var() { Region::error(self.interner) } else { r } | |
| 107 | } | |
| 108 | } |
src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/select.rs+83-2| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | use std::ops::ControlFlow; |
| 2 | 2 | |
| 3 | 3 | use hir_def::{ImplId, TraitId}; |
| 4 | use macros::{TypeFoldable, TypeVisitable}; | |
| 4 | 5 | use rustc_type_ir::{ |
| 5 | 6 | Interner, |
| 6 | 7 | solve::{BuiltinImplSource, CandidateSource, Certainty, inspect::ProbeKind}, |
| ... | ... | @@ -12,6 +13,7 @@ use crate::{ |
| 12 | 13 | Const, ErrorGuaranteed, GenericArgs, Goal, TraitRef, Ty, TypeError, |
| 13 | 14 | infer::{ |
| 14 | 15 | InferCtxt, |
| 16 | select::EvaluationResult::*, | |
| 15 | 17 | traits::{Obligation, ObligationCause, PredicateObligation, TraitObligation}, |
| 16 | 18 | }, |
| 17 | 19 | inspect::{InspectCandidate, InspectGoal, ProofTreeVisitor}, |
| ... | ... | @@ -47,6 +49,83 @@ pub enum NotConstEvaluatable { |
| 47 | 49 | MentionsParam, |
| 48 | 50 | } |
| 49 | 51 | |
| 52 | /// The result of trait evaluation. The order is important | |
| 53 | /// here as the evaluation of a list is the maximum of the | |
| 54 | /// evaluations. | |
| 55 | /// | |
| 56 | /// The evaluation results are ordered: | |
| 57 | /// - `EvaluatedToOk` implies `EvaluatedToOkModuloRegions` | |
| 58 | /// implies `EvaluatedToAmbig` implies `EvaluatedToAmbigStackDependent` | |
| 59 | /// - the "union" of evaluation results is equal to their maximum - | |
| 60 | /// all the "potential success" candidates can potentially succeed, | |
| 61 | /// so they are noops when unioned with a definite error, and within | |
| 62 | /// the categories it's easy to see that the unions are correct. | |
| 63 | #[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)] | |
| 64 | pub enum EvaluationResult { | |
| 65 | /// Evaluation successful. | |
| 66 | EvaluatedToOk, | |
| 67 | /// Evaluation successful, but there were unevaluated region obligations. | |
| 68 | EvaluatedToOkModuloRegions, | |
| 69 | /// Evaluation successful, but need to rerun because opaque types got | |
| 70 | /// hidden types assigned without it being known whether the opaque types | |
| 71 | /// are within their defining scope | |
| 72 | EvaluatedToOkModuloOpaqueTypes, | |
| 73 | /// Evaluation is known to be ambiguous -- it *might* hold for some | |
| 74 | /// assignment of inference variables, but it might not. | |
| 75 | /// | |
| 76 | /// While this has the same meaning as `EvaluatedToAmbigStackDependent` -- we can't | |
| 77 | /// know whether this obligation holds or not -- it is the result we | |
| 78 | /// would get with an empty stack, and therefore is cacheable. | |
| 79 | EvaluatedToAmbig, | |
| 80 | /// Evaluation failed because of recursion involving inference | |
| 81 | /// variables. We are somewhat imprecise there, so we don't actually | |
| 82 | /// know the real result. | |
| 83 | /// | |
| 84 | /// This can't be trivially cached because the result depends on the | |
| 85 | /// stack results. | |
| 86 | EvaluatedToAmbigStackDependent, | |
| 87 | /// Evaluation failed. | |
| 88 | EvaluatedToErr, | |
| 89 | } | |
| 90 | ||
| 91 | impl EvaluationResult { | |
| 92 | /// Returns `true` if this evaluation result is known to apply, even | |
| 93 | /// considering outlives constraints. | |
| 94 | pub fn must_apply_considering_regions(self) -> bool { | |
| 95 | self == EvaluatedToOk | |
| 96 | } | |
| 97 | ||
| 98 | /// Returns `true` if this evaluation result is known to apply, ignoring | |
| 99 | /// outlives constraints. | |
| 100 | pub fn must_apply_modulo_regions(self) -> bool { | |
| 101 | self <= EvaluatedToOkModuloRegions | |
| 102 | } | |
| 103 | ||
| 104 | pub fn may_apply(self) -> bool { | |
| 105 | match self { | |
| 106 | EvaluatedToOkModuloOpaqueTypes | |
| 107 | | EvaluatedToOk | |
| 108 | | EvaluatedToOkModuloRegions | |
| 109 | | EvaluatedToAmbig | |
| 110 | | EvaluatedToAmbigStackDependent => true, | |
| 111 | ||
| 112 | EvaluatedToErr => false, | |
| 113 | } | |
| 114 | } | |
| 115 | ||
| 116 | pub fn is_stack_dependent(self) -> bool { | |
| 117 | match self { | |
| 118 | EvaluatedToAmbigStackDependent => true, | |
| 119 | ||
| 120 | EvaluatedToOkModuloOpaqueTypes | |
| 121 | | EvaluatedToOk | |
| 122 | | EvaluatedToOkModuloRegions | |
| 123 | | EvaluatedToAmbig | |
| 124 | | EvaluatedToErr => false, | |
| 125 | } | |
| 126 | } | |
| 127 | } | |
| 128 | ||
| 50 | 129 | /// Indicates that trait evaluation caused overflow and in which pass. |
| 51 | 130 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] |
| 52 | 131 | pub enum OverflowError { |
| ... | ... | @@ -99,7 +178,7 @@ pub type SelectionResult<'db, T> = Result<Option<T>, SelectionError<'db>>; |
| 99 | 178 | /// ### The type parameter `N` |
| 100 | 179 | /// |
| 101 | 180 | /// See explanation on `ImplSourceUserDefinedData`. |
| 102 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | |
| 181 | #[derive(Debug, Clone, PartialEq, Eq, Hash, TypeVisitable, TypeFoldable)] | |
| 103 | 182 | pub enum ImplSource<'db, N> { |
| 104 | 183 | /// ImplSource identifying a particular impl. |
| 105 | 184 | UserDefined(ImplSourceUserDefinedData<'db, N>), |
| ... | ... | @@ -164,8 +243,10 @@ impl<'db, N> ImplSource<'db, N> { |
| 164 | 243 | /// is `Obligation`, as one might expect. During codegen, however, this |
| 165 | 244 | /// is `()`, because codegen only requires a shallow resolution of an |
| 166 | 245 | /// impl, and nested obligations are satisfied later. |
| 167 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | |
| 246 | #[derive(Debug, Clone, PartialEq, Eq, Hash, TypeVisitable, TypeFoldable)] | |
| 168 | 247 | pub struct ImplSourceUserDefinedData<'db, N> { |
| 248 | #[type_visitable(ignore)] | |
| 249 | #[type_foldable(identity)] | |
| 169 | 250 | pub impl_def_id: ImplId, |
| 170 | 251 | pub args: GenericArgs<'db>, |
| 171 | 252 | pub nested: Vec<N>, |
src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/snapshot/mod.rs+13| ... | ... | @@ -109,4 +109,17 @@ impl<'db> InferCtxt<'db> { |
| 109 | 109 | self.rollback_to(snapshot); |
| 110 | 110 | r |
| 111 | 111 | } |
| 112 | ||
| 113 | /// Scan the constraints produced since `snapshot` and check whether | |
| 114 | /// we added any region constraints. | |
| 115 | pub fn region_constraints_added_in_snapshot(&self, snapshot: &CombinedSnapshot) -> bool { | |
| 116 | self.inner | |
| 117 | .borrow_mut() | |
| 118 | .unwrap_region_constraints() | |
| 119 | .region_constraints_added_in_snapshot(&snapshot.undo_snapshot) | |
| 120 | } | |
| 121 | ||
| 122 | pub fn opaque_types_added_in_snapshot(&self, snapshot: &CombinedSnapshot) -> bool { | |
| 123 | self.inner.borrow().undo_log.opaque_types_in_snapshot(&snapshot.undo_snapshot) | |
| 124 | } | |
| 112 | 125 | } |
src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/traits.rs+39-35| ... | ... | @@ -7,16 +7,19 @@ use std::{ |
| 7 | 7 | hash::{Hash, Hasher}, |
| 8 | 8 | }; |
| 9 | 9 | |
| 10 | use hir_def::TraitId; | |
| 11 | use macros::{TypeFoldable, TypeVisitable}; | |
| 10 | 12 | use rustc_type_ir::elaborate::Elaboratable; |
| 11 | 13 | use rustc_type_ir::{ |
| 12 | 14 | PredicatePolarity, Upcast, |
| 13 | 15 | solve::{Certainty, NoSolution}, |
| 14 | 16 | }; |
| 15 | 17 | use rustc_type_ir::{TypeFoldable, TypeVisitable}; |
| 18 | use tracing::debug; | |
| 16 | 19 | |
| 17 | 20 | use crate::next_solver::{ |
| 18 | 21 | Binder, Clause, DbInterner, Goal, ParamEnv, PolyTraitPredicate, Predicate, SolverDefId, Span, |
| 19 | TraitPredicate, Ty, | |
| 22 | TraitPredicate, TraitRef, Ty, | |
| 20 | 23 | }; |
| 21 | 24 | |
| 22 | 25 | use super::InferCtxt; |
| ... | ... | @@ -63,8 +66,10 @@ impl ObligationCause { |
| 63 | 66 | /// either identifying an `impl` (e.g., `impl Eq for i32`) that |
| 64 | 67 | /// satisfies the obligation, or else finding a bound that is in |
| 65 | 68 | /// scope. The eventual result is usually a `Selection` (defined below). |
| 66 | #[derive(Clone, Debug)] | |
| 69 | #[derive(Clone, Debug, TypeVisitable, TypeFoldable)] | |
| 67 | 70 | pub struct Obligation<'db, T> { |
| 71 | #[type_foldable(identity)] | |
| 72 | #[type_visitable(ignore)] | |
| 68 | 73 | /// The reason we have to prove this thing. |
| 69 | 74 | pub cause: ObligationCause, |
| 70 | 75 | |
| ... | ... | @@ -115,39 +120,6 @@ impl<'db> Elaboratable<DbInterner<'db>> for PredicateObligation<'db> { |
| 115 | 120 | } |
| 116 | 121 | } |
| 117 | 122 | |
| 118 | impl<'db, T: TypeVisitable<DbInterner<'db>>> TypeVisitable<DbInterner<'db>> for Obligation<'db, T> { | |
| 119 | fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>( | |
| 120 | &self, | |
| 121 | visitor: &mut V, | |
| 122 | ) -> V::Result { | |
| 123 | rustc_ast_ir::try_visit!(self.param_env.visit_with(visitor)); | |
| 124 | self.predicate.visit_with(visitor) | |
| 125 | } | |
| 126 | } | |
| 127 | ||
| 128 | impl<'db, T: TypeFoldable<DbInterner<'db>>> TypeFoldable<DbInterner<'db>> for Obligation<'db, T> { | |
| 129 | fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>( | |
| 130 | self, | |
| 131 | folder: &mut F, | |
| 132 | ) -> Result<Self, F::Error> { | |
| 133 | Ok(Obligation { | |
| 134 | cause: self.cause.clone(), | |
| 135 | param_env: self.param_env.try_fold_with(folder)?, | |
| 136 | predicate: self.predicate.try_fold_with(folder)?, | |
| 137 | recursion_depth: self.recursion_depth, | |
| 138 | }) | |
| 139 | } | |
| 140 | ||
| 141 | fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self { | |
| 142 | Obligation { | |
| 143 | cause: self.cause.clone(), | |
| 144 | param_env: self.param_env.fold_with(folder), | |
| 145 | predicate: self.predicate.fold_with(folder), | |
| 146 | recursion_depth: self.recursion_depth, | |
| 147 | } | |
| 148 | } | |
| 149 | } | |
| 150 | ||
| 151 | 123 | impl<'db, T: Copy> Obligation<'db, T> { |
| 152 | 124 | pub fn as_goal(&self) -> Goal<'db, T> { |
| 153 | 125 | Goal { param_env: self.param_env, predicate: self.predicate } |
| ... | ... | @@ -237,3 +209,35 @@ impl<'db, O> Obligation<'db, O> { |
| 237 | 209 | Obligation::with_depth(tcx, self.cause.clone(), self.recursion_depth, self.param_env, value) |
| 238 | 210 | } |
| 239 | 211 | } |
| 212 | ||
| 213 | /// Determines whether the type `ty` is known to meet `bound` and | |
| 214 | /// returns true if so. Returns false if `ty` either does not meet | |
| 215 | /// `bound` or is not known to meet bound (note that this is | |
| 216 | /// conservative towards *no impl*, which is the opposite of the | |
| 217 | /// `evaluate` methods). | |
| 218 | pub fn type_known_to_meet_bound_modulo_regions<'tcx>( | |
| 219 | infcx: &InferCtxt<'tcx>, | |
| 220 | param_env: ParamEnv<'tcx>, | |
| 221 | ty: Ty<'tcx>, | |
| 222 | def_id: TraitId, | |
| 223 | ) -> bool { | |
| 224 | let trait_ref = TraitRef::new(infcx.interner, def_id.into(), [ty]); | |
| 225 | pred_known_to_hold_modulo_regions(infcx, param_env, trait_ref) | |
| 226 | } | |
| 227 | ||
| 228 | /// FIXME(@lcnr): this function doesn't seem right and shouldn't exist? | |
| 229 | /// | |
| 230 | /// Ping me on zulip if you want to use this method and need help with finding | |
| 231 | /// an appropriate replacement. | |
| 232 | fn pred_known_to_hold_modulo_regions<'db>( | |
| 233 | infcx: &InferCtxt<'db>, | |
| 234 | param_env: ParamEnv<'db>, | |
| 235 | pred: impl Upcast<DbInterner<'db>, Predicate<'db>>, | |
| 236 | ) -> bool { | |
| 237 | let obligation = Obligation::new(infcx.interner, ObligationCause::dummy(), param_env, pred); | |
| 238 | ||
| 239 | let result = infcx.evaluate_obligation(&obligation); | |
| 240 | debug!(?result); | |
| 241 | ||
| 242 | result.must_apply_modulo_regions() | |
| 243 | } |
src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs+203-80| ... | ... | @@ -1,75 +1,81 @@ |
| 1 | 1 | //! Things related to the Interner in the next-trait-solver. |
| 2 | #![allow(unused)] | |
| 2 | #![allow(unused)] // FIXME(next-solver): Remove this. | |
| 3 | ||
| 4 | use std::{fmt, ops::ControlFlow}; | |
| 5 | ||
| 6 | pub use tls_db::{attach_db, attach_db_allow_change, with_attached_db}; | |
| 3 | 7 | |
| 4 | 8 | use base_db::Crate; |
| 5 | 9 | use chalk_ir::{ProgramClauseImplication, SeparatorTraitRef, Variances}; |
| 6 | use hir_def::lang_item::LangItem; | |
| 7 | use hir_def::signatures::{FieldData, FnFlags, ImplFlags, StructFlags, TraitFlags}; | |
| 8 | use hir_def::{AdtId, BlockId, GenericDefId, TypeAliasId, VariantId}; | |
| 9 | use hir_def::{AttrDefId, Lookup}; | |
| 10 | use hir_def::{CallableDefId, EnumVariantId, ItemContainerId, StructId, UnionId}; | |
| 10 | use hir_def::{ | |
| 11 | AdtId, AttrDefId, BlockId, CallableDefId, EnumVariantId, GenericDefId, ItemContainerId, Lookup, | |
| 12 | StructId, TypeAliasId, UnionId, VariantId, | |
| 13 | lang_item::LangItem, | |
| 14 | signatures::{FieldData, FnFlags, ImplFlags, StructFlags, TraitFlags}, | |
| 15 | }; | |
| 11 | 16 | use intern::sym::non_exhaustive; |
| 12 | 17 | use intern::{Interned, impl_internable, sym}; |
| 13 | 18 | use la_arena::Idx; |
| 14 | 19 | use rustc_abi::{Align, ReprFlags, ReprOptions}; |
| 20 | use rustc_ast_ir::visit::VisitorResult; | |
| 15 | 21 | use rustc_hash::FxHashSet; |
| 16 | use rustc_index::bit_set::DenseBitSet; | |
| 17 | use rustc_type_ir::elaborate::elaborate; | |
| 18 | use rustc_type_ir::error::TypeError; | |
| 19 | use rustc_type_ir::inherent::{ | |
| 20 | AdtDef as _, GenericArgs as _, GenericsOf, IntoKind, SliceLike as _, Span as _, | |
| 21 | }; | |
| 22 | use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem}; | |
| 23 | use rustc_type_ir::solve::SizedTraitKind; | |
| 22 | use rustc_index::{IndexVec, bit_set::DenseBitSet}; | |
| 24 | 23 | use rustc_type_ir::{ |
| 25 | AliasTerm, AliasTermKind, AliasTy, AliasTyKind, EarlyBinder, FlagComputation, Flags, | |
| 26 | ImplPolarity, InferTy, ProjectionPredicate, TraitPredicate, TraitRef, Upcast, | |
| 24 | AliasTerm, AliasTermKind, AliasTy, AliasTyKind, BoundVar, CollectAndApply, DebruijnIndex, | |
| 25 | EarlyBinder, FlagComputation, Flags, GenericArgKind, ImplPolarity, InferTy, | |
| 26 | ProjectionPredicate, RegionKind, TermKind, TraitPredicate, TraitRef, TypeVisitableExt, | |
| 27 | UniverseIndex, Upcast, Variance, WithCachedTypeInfo, | |
| 28 | elaborate::{self, elaborate}, | |
| 29 | error::TypeError, | |
| 30 | inherent::{ | |
| 31 | self, AdtDef as _, Const as _, GenericArgs as _, GenericsOf, IntoKind, ParamEnv as _, | |
| 32 | Region as _, SliceLike as _, Span as _, Ty as _, | |
| 33 | }, | |
| 34 | ir_print, | |
| 35 | lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem}, | |
| 36 | relate, | |
| 37 | solve::SizedTraitKind, | |
| 27 | 38 | }; |
| 28 | 39 | use salsa::plumbing::AsId; |
| 29 | 40 | use smallvec::{SmallVec, smallvec}; |
| 30 | use std::fmt; | |
| 31 | use std::ops::ControlFlow; | |
| 32 | 41 | use syntax::ast::SelfParamKind; |
| 42 | use tracing::debug; | |
| 33 | 43 | use triomphe::Arc; |
| 34 | 44 | |
| 35 | use rustc_ast_ir::visit::VisitorResult; | |
| 36 | use rustc_index::IndexVec; | |
| 37 | use rustc_type_ir::TypeVisitableExt; | |
| 38 | use rustc_type_ir::{ | |
| 39 | BoundVar, CollectAndApply, DebruijnIndex, GenericArgKind, RegionKind, TermKind, UniverseIndex, | |
| 40 | Variance, WithCachedTypeInfo, elaborate, | |
| 41 | inherent::{self, Const as _, Region as _, Ty as _}, | |
| 42 | ir_print, relate, | |
| 43 | }; | |
| 44 | ||
| 45 | use crate::lower_nextsolver::{self, TyLoweringContext}; | |
| 46 | use crate::method_resolution::{ALL_FLOAT_FPS, ALL_INT_FPS, TyFingerprint}; | |
| 47 | use crate::next_solver::infer::InferCtxt; | |
| 48 | use crate::next_solver::util::{ContainsTypeErrors, explicit_item_bounds, for_trait_impls}; | |
| 49 | use crate::next_solver::{ | |
| 50 | AdtIdWrapper, BoundConst, CallableIdWrapper, CanonicalVarKind, ClosureIdWrapper, | |
| 51 | CoroutineIdWrapper, Ctor, FnSig, FxIndexMap, ImplIdWrapper, InternedWrapperNoDebug, | |
| 52 | RegionAssumptions, SolverContext, SolverDefIds, TraitIdWrapper, TypeAliasIdWrapper, | |
| 45 | use crate::{ | |
| 46 | ConstScalar, FnAbi, Interner, | |
| 47 | db::HirDatabase, | |
| 48 | lower_nextsolver::{self, TyLoweringContext}, | |
| 49 | method_resolution::{ALL_FLOAT_FPS, ALL_INT_FPS, TyFingerprint}, | |
| 50 | next_solver::{ | |
| 51 | AdtIdWrapper, BoundConst, CallableIdWrapper, CanonicalVarKind, ClosureIdWrapper, | |
| 52 | CoroutineIdWrapper, Ctor, FnSig, FxIndexMap, ImplIdWrapper, InternedWrapperNoDebug, | |
| 53 | RegionAssumptions, SolverContext, SolverDefIds, TraitIdWrapper, TypeAliasIdWrapper, | |
| 54 | TypingMode, | |
| 55 | infer::{ | |
| 56 | DbInternerInferExt, InferCtxt, | |
| 57 | traits::{Obligation, ObligationCause}, | |
| 58 | }, | |
| 59 | obligation_ctxt::ObligationCtxt, | |
| 60 | util::{ContainsTypeErrors, explicit_item_bounds, for_trait_impls}, | |
| 61 | }, | |
| 53 | 62 | }; |
| 54 | use crate::{ConstScalar, FnAbi, Interner, db::HirDatabase}; | |
| 55 | 63 | |
| 56 | use super::generics::generics; | |
| 57 | use super::util::sizedness_constraint_for_ty; | |
| 58 | 64 | use super::{ |
| 59 | 65 | Binder, BoundExistentialPredicate, BoundExistentialPredicates, BoundTy, BoundTyKind, Clause, |
| 60 | Clauses, Const, ConstKind, ErrorGuaranteed, ExprConst, ExternalConstraints, | |
| 66 | ClauseKind, Clauses, Const, ConstKind, ErrorGuaranteed, ExprConst, ExternalConstraints, | |
| 61 | 67 | ExternalConstraintsData, GenericArg, GenericArgs, InternedClausesWrapper, ParamConst, ParamEnv, |
| 62 | 68 | ParamTy, PlaceholderConst, PlaceholderTy, PredefinedOpaques, PredefinedOpaquesData, Predicate, |
| 63 | PredicateKind, Term, Ty, TyKind, Tys, ValueConst, | |
| 69 | PredicateKind, SolverDefId, Term, Ty, TyKind, Tys, Valtree, ValueConst, | |
| 64 | 70 | abi::Safety, |
| 65 | 71 | fold::{BoundVarReplacer, BoundVarReplacerDelegate, FnMutDelegate}, |
| 66 | generics::Generics, | |
| 72 | generics::{Generics, generics}, | |
| 67 | 73 | mapping::ChalkToNextSolver, |
| 68 | 74 | region::{ |
| 69 | 75 | BoundRegion, BoundRegionKind, EarlyParamRegion, LateParamRegion, PlaceholderRegion, Region, |
| 70 | 76 | }, |
| 77 | util::sizedness_constraint_for_ty, | |
| 71 | 78 | }; |
| 72 | use super::{ClauseKind, SolverDefId, Valtree}; | |
| 73 | 79 | |
| 74 | 80 | #[macro_export] |
| 75 | 81 | #[doc(hidden)] |
| ... | ... | @@ -127,11 +133,10 @@ macro_rules! _interned_vec_nolifetime_salsa { |
| 127 | 133 | |
| 128 | 134 | pub fn inner(&self) -> &smallvec::SmallVec<[$ty; 2]> { |
| 129 | 135 | // SAFETY: ¯\_(ツ)_/¯ |
| 130 | salsa::with_attached_database(|db| { | |
| 136 | $crate::with_attached_db(|db| { | |
| 131 | 137 | let inner = self.inner_(db); |
| 132 | 138 | unsafe { std::mem::transmute(inner) } |
| 133 | 139 | }) |
| 134 | .unwrap() | |
| 135 | 140 | } |
| 136 | 141 | } |
| 137 | 142 | |
| ... | ... | @@ -230,11 +235,10 @@ macro_rules! _interned_vec_db { |
| 230 | 235 | |
| 231 | 236 | pub fn inner(&self) -> &smallvec::SmallVec<[$ty<'db>; 2]> { |
| 232 | 237 | // SAFETY: ¯\_(ツ)_/¯ |
| 233 | salsa::with_attached_database(|db| { | |
| 238 | $crate::with_attached_db(|db| { | |
| 234 | 239 | let inner = self.inner_(db); |
| 235 | 240 | unsafe { std::mem::transmute(inner) } |
| 236 | 241 | }) |
| 237 | .unwrap() | |
| 238 | 242 | } |
| 239 | 243 | } |
| 240 | 244 | |
| ... | ... | @@ -285,14 +289,11 @@ unsafe impl Sync for DbInterner<'_> {} |
| 285 | 289 | impl<'db> DbInterner<'db> { |
| 286 | 290 | // FIXME(next-solver): remove this method |
| 287 | 291 | pub fn conjure() -> DbInterner<'db> { |
| 288 | salsa::with_attached_database(|db| DbInterner { | |
| 289 | db: unsafe { | |
| 290 | std::mem::transmute::<&dyn HirDatabase, &'db dyn HirDatabase>(db.as_view()) | |
| 291 | }, | |
| 292 | crate::with_attached_db(|db| DbInterner { | |
| 293 | db: unsafe { std::mem::transmute::<&dyn HirDatabase, &'db dyn HirDatabase>(db) }, | |
| 292 | 294 | krate: None, |
| 293 | 295 | block: None, |
| 294 | 296 | }) |
| 295 | .expect("db is expected to be attached") | |
| 296 | 297 | } |
| 297 | 298 | |
| 298 | 299 | pub fn new_with( |
| ... | ... | @@ -303,6 +304,7 @@ impl<'db> DbInterner<'db> { |
| 303 | 304 | DbInterner { db, krate, block } |
| 304 | 305 | } |
| 305 | 306 | |
| 307 | #[inline] | |
| 306 | 308 | pub fn db(&self) -> &'db dyn HirDatabase { |
| 307 | 309 | self.db |
| 308 | 310 | } |
| ... | ... | @@ -585,12 +587,11 @@ impl AdtDef { |
| 585 | 587 | } |
| 586 | 588 | |
| 587 | 589 | pub fn inner(&self) -> &AdtDefInner { |
| 588 | salsa::with_attached_database(|db| { | |
| 590 | crate::with_attached_db(|db| { | |
| 589 | 591 | let inner = self.data_(db); |
| 590 | 592 | // SAFETY: ¯\_(ツ)_/¯ |
| 591 | 593 | unsafe { std::mem::transmute(inner) } |
| 592 | 594 | }) |
| 593 | .unwrap() | |
| 594 | 595 | } |
| 595 | 596 | |
| 596 | 597 | pub fn is_enum(&self) -> bool { |
| ... | ... | @@ -708,21 +709,20 @@ impl<'db> inherent::AdtDef<DbInterner<'db>> for AdtDef { |
| 708 | 709 | |
| 709 | 710 | impl fmt::Debug for AdtDef { |
| 710 | 711 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 711 | salsa::with_attached_database(|db| match self.inner().id { | |
| 712 | crate::with_attached_db(|db| match self.inner().id { | |
| 712 | 713 | AdtId::StructId(struct_id) => { |
| 713 | let data = db.as_view::<dyn HirDatabase>().struct_signature(struct_id); | |
| 714 | let data = db.struct_signature(struct_id); | |
| 714 | 715 | f.write_str(data.name.as_str()) |
| 715 | 716 | } |
| 716 | 717 | AdtId::UnionId(union_id) => { |
| 717 | let data = db.as_view::<dyn HirDatabase>().union_signature(union_id); | |
| 718 | let data = db.union_signature(union_id); | |
| 718 | 719 | f.write_str(data.name.as_str()) |
| 719 | 720 | } |
| 720 | 721 | AdtId::EnumId(enum_id) => { |
| 721 | let data = db.as_view::<dyn HirDatabase>().enum_signature(enum_id); | |
| 722 | let data = db.enum_signature(enum_id); | |
| 722 | 723 | f.write_str(data.name.as_str()) |
| 723 | 724 | } |
| 724 | 725 | }) |
| 725 | .unwrap_or_else(|| f.write_str(&format!("AdtDef({:?})", self.inner().id))) | |
| 726 | 726 | } |
| 727 | 727 | } |
| 728 | 728 | |
| ... | ... | @@ -778,13 +778,12 @@ impl<'db> Pattern<'db> { |
| 778 | 778 | } |
| 779 | 779 | |
| 780 | 780 | pub fn inner(&self) -> &PatternKind<'db> { |
| 781 | salsa::with_attached_database(|db| { | |
| 781 | crate::with_attached_db(|db| { | |
| 782 | 782 | let inner = &self.kind_(db).0; |
| 783 | 783 | // SAFETY: The caller already has access to a `Ty<'db>`, so borrowchecking will |
| 784 | 784 | // make sure that our returned value is valid for the lifetime `'db`. |
| 785 | 785 | unsafe { std::mem::transmute(inner) } |
| 786 | 786 | }) |
| 787 | .unwrap() | |
| 788 | 787 | } |
| 789 | 788 | } |
| 790 | 789 | |
| ... | ... | @@ -1020,17 +1019,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> { |
| 1020 | 1019 | self, |
| 1021 | 1020 | f: impl FnOnce(&mut rustc_type_ir::search_graph::GlobalCache<Self>) -> R, |
| 1022 | 1021 | ) -> R { |
| 1023 | salsa::with_attached_database(|db| { | |
| 1024 | tls_cache::with_cache( | |
| 1025 | unsafe { | |
| 1026 | std::mem::transmute::<&dyn HirDatabase, &'db dyn HirDatabase>( | |
| 1027 | db.as_view::<dyn HirDatabase>(), | |
| 1028 | ) | |
| 1029 | }, | |
| 1030 | f, | |
| 1031 | ) | |
| 1032 | }) | |
| 1033 | .unwrap() | |
| 1022 | tls_cache::with_cache(self.db, f) | |
| 1034 | 1023 | } |
| 1035 | 1024 | |
| 1036 | 1025 | fn canonical_param_env_cache_get_or_insert<R>( |
| ... | ... | @@ -1118,7 +1107,15 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> { |
| 1118 | 1107 | fn alias_ty_kind(self, alias: rustc_type_ir::AliasTy<Self>) -> AliasTyKind { |
| 1119 | 1108 | match alias.def_id { |
| 1120 | 1109 | SolverDefId::InternedOpaqueTyId(_) => AliasTyKind::Opaque, |
| 1121 | SolverDefId::TypeAliasId(_) => AliasTyKind::Projection, | |
| 1110 | SolverDefId::TypeAliasId(type_alias) => match type_alias.loc(self.db).container { | |
| 1111 | ItemContainerId::ImplId(impl_) | |
| 1112 | if self.db.impl_signature(impl_).target_trait.is_none() => | |
| 1113 | { | |
| 1114 | AliasTyKind::Inherent | |
| 1115 | } | |
| 1116 | ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => AliasTyKind::Projection, | |
| 1117 | _ => AliasTyKind::Free, | |
| 1118 | }, | |
| 1122 | 1119 | _ => unimplemented!("Unexpected alias: {:?}", alias.def_id), |
| 1123 | 1120 | } |
| 1124 | 1121 | } |
| ... | ... | @@ -1129,7 +1126,19 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> { |
| 1129 | 1126 | ) -> rustc_type_ir::AliasTermKind { |
| 1130 | 1127 | match alias.def_id { |
| 1131 | 1128 | SolverDefId::InternedOpaqueTyId(_) => AliasTermKind::OpaqueTy, |
| 1132 | SolverDefId::TypeAliasId(_) => AliasTermKind::ProjectionTy, | |
| 1129 | SolverDefId::TypeAliasId(type_alias) => match type_alias.loc(self.db).container { | |
| 1130 | ItemContainerId::ImplId(impl_) | |
| 1131 | if self.db.impl_signature(impl_).target_trait.is_none() => | |
| 1132 | { | |
| 1133 | AliasTermKind::InherentTy | |
| 1134 | } | |
| 1135 | ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => { | |
| 1136 | AliasTermKind::ProjectionTy | |
| 1137 | } | |
| 1138 | _ => AliasTermKind::FreeTy, | |
| 1139 | }, | |
| 1140 | // rustc creates an `AnonConst` for consts, and evaluates them with CTFE (normalizing projections | |
| 1141 | // via selection, similar to ours `find_matching_impl()`, and not with the trait solver), so mimic it. | |
| 1133 | 1142 | SolverDefId::ConstId(_) => AliasTermKind::UnevaluatedConst, |
| 1134 | 1143 | _ => unimplemented!("Unexpected alias: {:?}", alias.def_id), |
| 1135 | 1144 | } |
| ... | ... | @@ -1616,7 +1625,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> { |
| 1616 | 1625 | mut f: impl FnMut(Self::ImplId), |
| 1617 | 1626 | ) { |
| 1618 | 1627 | let trait_ = trait_.0; |
| 1619 | let self_ty_fp = TyFingerprint::for_trait_impl_ns(&self_ty); | |
| 1628 | let self_ty_fp = TyFingerprint::for_trait_impl(self_ty); | |
| 1620 | 1629 | let fps: &[TyFingerprint] = match self_ty.kind() { |
| 1621 | 1630 | TyKind::Infer(InferTy::IntVar(..)) => &ALL_INT_FPS, |
| 1622 | 1631 | TyKind::Infer(InferTy::FloatVar(..)) => &ALL_FLOAT_FPS, |
| ... | ... | @@ -1692,8 +1701,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> { |
| 1692 | 1701 | } |
| 1693 | 1702 | |
| 1694 | 1703 | fn impl_is_default(self, impl_def_id: Self::ImplId) -> bool { |
| 1695 | // FIXME | |
| 1696 | false | |
| 1704 | self.db.impl_signature(impl_def_id.0).is_default() | |
| 1697 | 1705 | } |
| 1698 | 1706 | |
| 1699 | 1707 | #[tracing::instrument(skip(self), ret)] |
| ... | ... | @@ -1747,7 +1755,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> { |
| 1747 | 1755 | } |
| 1748 | 1756 | |
| 1749 | 1757 | fn delay_bug(self, msg: impl ToString) -> Self::ErrorGuaranteed { |
| 1750 | panic!("Bug encountered in next-trait-solver.") | |
| 1758 | panic!("Bug encountered in next-trait-solver: {}", msg.to_string()) | |
| 1751 | 1759 | } |
| 1752 | 1760 | |
| 1753 | 1761 | fn is_general_coroutine(self, coroutine_def_id: Self::CoroutineId) -> bool { |
| ... | ... | @@ -1907,7 +1915,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> { |
| 1907 | 1915 | match impl_trait_id { |
| 1908 | 1916 | crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => { |
| 1909 | 1917 | let infer = self.db().infer(func.into()); |
| 1910 | EarlyBinder::bind(infer.type_of_rpit[idx].to_nextsolver(self)) | |
| 1918 | EarlyBinder::bind(infer.type_of_rpit[idx.to_nextsolver(self)]) | |
| 1911 | 1919 | } |
| 1912 | 1920 | crate::ImplTraitId::TypeAliasImplTrait(..) |
| 1913 | 1921 | | crate::ImplTraitId::AsyncBlockTypeImplTrait(_, _) => { |
| ... | ... | @@ -1945,7 +1953,11 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> { |
| 1945 | 1953 | false |
| 1946 | 1954 | } |
| 1947 | 1955 | |
| 1948 | fn impl_specializes(self, impl_def_id: Self::ImplId, victim_def_id: Self::ImplId) -> bool { | |
| 1956 | fn impl_specializes( | |
| 1957 | self, | |
| 1958 | specializing_impl_def_id: Self::ImplId, | |
| 1959 | parent_impl_def_id: Self::ImplId, | |
| 1960 | ) -> bool { | |
| 1949 | 1961 | false |
| 1950 | 1962 | } |
| 1951 | 1963 | |
| ... | ... | @@ -2106,6 +2118,117 @@ TrivialTypeTraversalImpls! { |
| 2106 | 2118 | Placeholder<BoundVar>, |
| 2107 | 2119 | } |
| 2108 | 2120 | |
| 2121 | mod tls_db { | |
| 2122 | use std::{cell::Cell, ptr::NonNull}; | |
| 2123 | ||
| 2124 | use crate::db::HirDatabase; | |
| 2125 | ||
| 2126 | struct Attached { | |
| 2127 | database: Cell<Option<NonNull<dyn HirDatabase>>>, | |
| 2128 | } | |
| 2129 | ||
| 2130 | impl Attached { | |
| 2131 | #[inline] | |
| 2132 | fn attach<R>(&self, db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R { | |
| 2133 | struct DbGuard<'s> { | |
| 2134 | state: Option<&'s Attached>, | |
| 2135 | } | |
| 2136 | ||
| 2137 | impl<'s> DbGuard<'s> { | |
| 2138 | #[inline] | |
| 2139 | fn new(attached: &'s Attached, db: &dyn HirDatabase) -> Self { | |
| 2140 | match attached.database.get() { | |
| 2141 | Some(current_db) => { | |
| 2142 | let new_db = NonNull::from(db); | |
| 2143 | if !std::ptr::addr_eq(current_db.as_ptr(), new_db.as_ptr()) { | |
| 2144 | panic!( | |
| 2145 | "Cannot change attached database. This is likely a bug.\n\ | |
| 2146 | If this is not a bug, you can use `attach_db_allow_change()`." | |
| 2147 | ); | |
| 2148 | } | |
| 2149 | Self { state: None } | |
| 2150 | } | |
| 2151 | None => { | |
| 2152 | // Otherwise, set the database. | |
| 2153 | attached.database.set(Some(NonNull::from(db))); | |
| 2154 | Self { state: Some(attached) } | |
| 2155 | } | |
| 2156 | } | |
| 2157 | } | |
| 2158 | } | |
| 2159 | ||
| 2160 | impl Drop for DbGuard<'_> { | |
| 2161 | #[inline] | |
| 2162 | fn drop(&mut self) { | |
| 2163 | // Reset database to null if we did anything in `DbGuard::new`. | |
| 2164 | if let Some(attached) = self.state { | |
| 2165 | attached.database.set(None); | |
| 2166 | } | |
| 2167 | } | |
| 2168 | } | |
| 2169 | ||
| 2170 | let _guard = DbGuard::new(self, db); | |
| 2171 | op() | |
| 2172 | } | |
| 2173 | ||
| 2174 | #[inline] | |
| 2175 | fn attach_allow_change<R>(&self, db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R { | |
| 2176 | struct DbGuard<'s> { | |
| 2177 | state: &'s Attached, | |
| 2178 | prev: Option<NonNull<dyn HirDatabase>>, | |
| 2179 | } | |
| 2180 | ||
| 2181 | impl<'s> DbGuard<'s> { | |
| 2182 | #[inline] | |
| 2183 | fn new(attached: &'s Attached, db: &dyn HirDatabase) -> Self { | |
| 2184 | let prev = attached.database.replace(Some(NonNull::from(db))); | |
| 2185 | Self { state: attached, prev } | |
| 2186 | } | |
| 2187 | } | |
| 2188 | ||
| 2189 | impl Drop for DbGuard<'_> { | |
| 2190 | #[inline] | |
| 2191 | fn drop(&mut self) { | |
| 2192 | self.state.database.set(self.prev); | |
| 2193 | } | |
| 2194 | } | |
| 2195 | ||
| 2196 | let _guard = DbGuard::new(self, db); | |
| 2197 | op() | |
| 2198 | } | |
| 2199 | ||
| 2200 | #[inline] | |
| 2201 | fn with<R>(&self, op: impl FnOnce(&dyn HirDatabase) -> R) -> R { | |
| 2202 | let db = self.database.get().expect("Try to use attached db, but not db is attached"); | |
| 2203 | ||
| 2204 | // SAFETY: The db is attached, so it must be valid. | |
| 2205 | op(unsafe { db.as_ref() }) | |
| 2206 | } | |
| 2207 | } | |
| 2208 | ||
| 2209 | thread_local! { | |
| 2210 | static GLOBAL_DB: Attached = const { Attached { database: Cell::new(None) } }; | |
| 2211 | } | |
| 2212 | ||
| 2213 | #[inline] | |
| 2214 | pub fn attach_db<R>(db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R { | |
| 2215 | GLOBAL_DB.with(|global_db| global_db.attach(db, op)) | |
| 2216 | } | |
| 2217 | ||
| 2218 | #[inline] | |
| 2219 | pub fn attach_db_allow_change<R>(db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R { | |
| 2220 | GLOBAL_DB.with(|global_db| global_db.attach_allow_change(db, op)) | |
| 2221 | } | |
| 2222 | ||
| 2223 | #[inline] | |
| 2224 | pub fn with_attached_db<R>(op: impl FnOnce(&dyn HirDatabase) -> R) -> R { | |
| 2225 | GLOBAL_DB.with( | |
| 2226 | #[inline] | |
| 2227 | |a| a.with(op), | |
| 2228 | ) | |
| 2229 | } | |
| 2230 | } | |
| 2231 | ||
| 2109 | 2232 | mod tls_cache { |
| 2110 | 2233 | use crate::db::HirDatabase; |
| 2111 | 2234 |
src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ir_print.rs+13-31| ... | ... | @@ -16,10 +16,10 @@ impl<'db> IrPrint<ty::AliasTy<Self>> for DbInterner<'db> { |
| 16 | 16 | } |
| 17 | 17 | |
| 18 | 18 | fn print_debug(t: &ty::AliasTy<Self>, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 19 | salsa::with_attached_database(|db| match t.def_id { | |
| 19 | crate::with_attached_db(|db| match t.def_id { | |
| 20 | 20 | SolverDefId::TypeAliasId(id) => fmt.write_str(&format!( |
| 21 | 21 | "AliasTy({:?}[{:?}])", |
| 22 | db.as_view::<dyn HirDatabase>().type_alias_signature(id).name.as_str(), | |
| 22 | db.type_alias_signature(id).name.as_str(), | |
| 23 | 23 | t.args |
| 24 | 24 | )), |
| 25 | 25 | SolverDefId::InternedOpaqueTyId(id) => { |
| ... | ... | @@ -27,7 +27,6 @@ impl<'db> IrPrint<ty::AliasTy<Self>> for DbInterner<'db> { |
| 27 | 27 | } |
| 28 | 28 | _ => panic!("Expected TypeAlias or OpaqueTy."), |
| 29 | 29 | }) |
| 30 | .unwrap_or_else(|| fmt.write_str(&format!("AliasTy({:?}[{:?}])", t.def_id, t.args))) | |
| 31 | 30 | } |
| 32 | 31 | } |
| 33 | 32 | |
| ... | ... | @@ -37,10 +36,10 @@ impl<'db> IrPrint<ty::AliasTerm<Self>> for DbInterner<'db> { |
| 37 | 36 | } |
| 38 | 37 | |
| 39 | 38 | fn print_debug(t: &ty::AliasTerm<Self>, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 40 | salsa::with_attached_database(|db| match t.def_id { | |
| 39 | crate::with_attached_db(|db| match t.def_id { | |
| 41 | 40 | SolverDefId::TypeAliasId(id) => fmt.write_str(&format!( |
| 42 | 41 | "AliasTerm({:?}[{:?}])", |
| 43 | db.as_view::<dyn HirDatabase>().type_alias_signature(id).name.as_str(), | |
| 42 | db.type_alias_signature(id).name.as_str(), | |
| 44 | 43 | t.args |
| 45 | 44 | )), |
| 46 | 45 | SolverDefId::InternedOpaqueTyId(id) => { |
| ... | ... | @@ -48,7 +47,6 @@ impl<'db> IrPrint<ty::AliasTerm<Self>> for DbInterner<'db> { |
| 48 | 47 | } |
| 49 | 48 | _ => panic!("Expected TypeAlias or OpaqueTy."), |
| 50 | 49 | }) |
| 51 | .unwrap_or_else(|| fmt.write_str(&format!("AliasTerm({:?}[{:?}])", t.def_id, t.args))) | |
| 52 | 50 | } |
| 53 | 51 | } |
| 54 | 52 | impl<'db> IrPrint<ty::TraitRef<Self>> for DbInterner<'db> { |
| ... | ... | @@ -57,7 +55,7 @@ impl<'db> IrPrint<ty::TraitRef<Self>> for DbInterner<'db> { |
| 57 | 55 | } |
| 58 | 56 | |
| 59 | 57 | fn print_debug(t: &ty::TraitRef<Self>, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 60 | salsa::with_attached_database(|db| { | |
| 58 | crate::with_attached_db(|db| { | |
| 61 | 59 | let trait_ = t.def_id.0; |
| 62 | 60 | let self_ty = &t.args.as_slice()[0]; |
| 63 | 61 | let trait_args = &t.args.as_slice()[1..]; |
| ... | ... | @@ -65,18 +63,17 @@ impl<'db> IrPrint<ty::TraitRef<Self>> for DbInterner<'db> { |
| 65 | 63 | fmt.write_str(&format!( |
| 66 | 64 | "{:?}: {}", |
| 67 | 65 | self_ty, |
| 68 | db.as_view::<dyn HirDatabase>().trait_signature(trait_).name.as_str() | |
| 66 | db.trait_signature(trait_).name.as_str() | |
| 69 | 67 | )) |
| 70 | 68 | } else { |
| 71 | 69 | fmt.write_str(&format!( |
| 72 | 70 | "{:?}: {}<{:?}>", |
| 73 | 71 | self_ty, |
| 74 | db.as_view::<dyn HirDatabase>().trait_signature(trait_).name.as_str(), | |
| 72 | db.trait_signature(trait_).name.as_str(), | |
| 75 | 73 | trait_args |
| 76 | 74 | )) |
| 77 | 75 | } |
| 78 | 76 | }) |
| 79 | .unwrap_or_else(|| fmt.write_str(&format!("TraitRef({:?}[{:?}])", t.def_id, t.args))) | |
| 80 | 77 | } |
| 81 | 78 | } |
| 82 | 79 | impl<'db> IrPrint<ty::TraitPredicate<Self>> for DbInterner<'db> { |
| ... | ... | @@ -118,17 +115,14 @@ impl<'db> IrPrint<ty::ExistentialTraitRef<Self>> for DbInterner<'db> { |
| 118 | 115 | t: &ty::ExistentialTraitRef<Self>, |
| 119 | 116 | fmt: &mut std::fmt::Formatter<'_>, |
| 120 | 117 | ) -> std::fmt::Result { |
| 121 | salsa::with_attached_database(|db| { | |
| 118 | crate::with_attached_db(|db| { | |
| 122 | 119 | let trait_ = t.def_id.0; |
| 123 | 120 | fmt.write_str(&format!( |
| 124 | 121 | "ExistentialTraitRef({:?}[{:?}])", |
| 125 | db.as_view::<dyn HirDatabase>().trait_signature(trait_).name.as_str(), | |
| 122 | db.trait_signature(trait_).name.as_str(), | |
| 126 | 123 | t.args |
| 127 | 124 | )) |
| 128 | 125 | }) |
| 129 | .unwrap_or_else(|| { | |
| 130 | fmt.write_str(&format!("ExistentialTraitRef({:?}[{:?}])", t.def_id, t.args)) | |
| 131 | }) | |
| 132 | 126 | } |
| 133 | 127 | } |
| 134 | 128 | impl<'db> IrPrint<ty::ExistentialProjection<Self>> for DbInterner<'db> { |
| ... | ... | @@ -143,24 +137,18 @@ impl<'db> IrPrint<ty::ExistentialProjection<Self>> for DbInterner<'db> { |
| 143 | 137 | t: &ty::ExistentialProjection<Self>, |
| 144 | 138 | fmt: &mut std::fmt::Formatter<'_>, |
| 145 | 139 | ) -> std::fmt::Result { |
| 146 | salsa::with_attached_database(|db| { | |
| 140 | crate::with_attached_db(|db| { | |
| 147 | 141 | let id = match t.def_id { |
| 148 | 142 | SolverDefId::TypeAliasId(id) => id, |
| 149 | 143 | _ => panic!("Expected trait."), |
| 150 | 144 | }; |
| 151 | 145 | fmt.write_str(&format!( |
| 152 | 146 | "ExistentialProjection(({:?}[{:?}]) -> {:?})", |
| 153 | db.as_view::<dyn HirDatabase>().type_alias_signature(id).name.as_str(), | |
| 147 | db.type_alias_signature(id).name.as_str(), | |
| 154 | 148 | t.args, |
| 155 | 149 | t.term |
| 156 | 150 | )) |
| 157 | 151 | }) |
| 158 | .unwrap_or_else(|| { | |
| 159 | fmt.write_str(&format!( | |
| 160 | "ExistentialProjection(({:?}[{:?}]) -> {:?})", | |
| 161 | t.def_id, t.args, t.term | |
| 162 | )) | |
| 163 | }) | |
| 164 | 152 | } |
| 165 | 153 | } |
| 166 | 154 | impl<'db> IrPrint<ty::ProjectionPredicate<Self>> for DbInterner<'db> { |
| ... | ... | @@ -175,24 +163,18 @@ impl<'db> IrPrint<ty::ProjectionPredicate<Self>> for DbInterner<'db> { |
| 175 | 163 | t: &ty::ProjectionPredicate<Self>, |
| 176 | 164 | fmt: &mut std::fmt::Formatter<'_>, |
| 177 | 165 | ) -> std::fmt::Result { |
| 178 | salsa::with_attached_database(|db| { | |
| 166 | crate::with_attached_db(|db| { | |
| 179 | 167 | let id = match t.projection_term.def_id { |
| 180 | 168 | SolverDefId::TypeAliasId(id) => id, |
| 181 | 169 | _ => panic!("Expected trait."), |
| 182 | 170 | }; |
| 183 | 171 | fmt.write_str(&format!( |
| 184 | 172 | "ProjectionPredicate(({:?}[{:?}]) -> {:?})", |
| 185 | db.as_view::<dyn HirDatabase>().type_alias_signature(id).name.as_str(), | |
| 173 | db.type_alias_signature(id).name.as_str(), | |
| 186 | 174 | t.projection_term.args, |
| 187 | 175 | t.term |
| 188 | 176 | )) |
| 189 | 177 | }) |
| 190 | .unwrap_or_else(|| { | |
| 191 | fmt.write_str(&format!( | |
| 192 | "ProjectionPredicate(({:?}[{:?}]) -> {:?})", | |
| 193 | t.projection_term.def_id, t.projection_term.args, t.term | |
| 194 | )) | |
| 195 | }) | |
| 196 | 178 | } |
| 197 | 179 | } |
| 198 | 180 | impl<'db> IrPrint<ty::NormalizesTo<Self>> for DbInterner<'db> { |
src/tools/rust-analyzer/crates/hir-ty/src/next_solver/mapping.rs+45-3| ... | ... | @@ -143,10 +143,29 @@ pub trait ChalkToNextSolver<'db, Out> { |
| 143 | 143 | fn to_nextsolver(&self, interner: DbInterner<'db>) -> Out; |
| 144 | 144 | } |
| 145 | 145 | |
| 146 | impl<'db, A, OutA, B, OutB> ChalkToNextSolver<'db, (OutA, OutB)> for (A, B) | |
| 147 | where | |
| 148 | A: ChalkToNextSolver<'db, OutA>, | |
| 149 | B: ChalkToNextSolver<'db, OutB>, | |
| 150 | { | |
| 151 | fn to_nextsolver(&self, interner: DbInterner<'db>) -> (OutA, OutB) { | |
| 152 | (self.0.to_nextsolver(interner), self.1.to_nextsolver(interner)) | |
| 153 | } | |
| 154 | } | |
| 155 | ||
| 146 | 156 | pub trait NextSolverToChalk<'db, Out> { |
| 147 | 157 | fn to_chalk(self, interner: DbInterner<'db>) -> Out; |
| 148 | 158 | } |
| 149 | 159 | |
| 160 | impl<'db, T, Out> NextSolverToChalk<'db, Option<Out>> for Option<T> | |
| 161 | where | |
| 162 | T: NextSolverToChalk<'db, Out>, | |
| 163 | { | |
| 164 | fn to_chalk(self, interner: DbInterner<'db>) -> Option<Out> { | |
| 165 | self.map(|it| it.to_chalk(interner)) | |
| 166 | } | |
| 167 | } | |
| 168 | ||
| 150 | 169 | impl NextSolverToChalk<'_, chalk_ir::Mutability> for rustc_ast_ir::Mutability { |
| 151 | 170 | fn to_chalk(self, interner: DbInterner<'_>) -> chalk_ir::Mutability { |
| 152 | 171 | match self { |
| ... | ... | @@ -520,7 +539,7 @@ impl<'db> ChalkToNextSolver<'db, Const<'db>> for chalk_ir::Const<Interner> { |
| 520 | 539 | ConstScalar::Bytes(bytes, memory) => { |
| 521 | 540 | rustc_type_ir::ConstKind::Value(ValueConst::new( |
| 522 | 541 | data.ty.to_nextsolver(interner), |
| 523 | ConstBytes(bytes.clone(), memory.clone()), | |
| 542 | ConstBytes { memory: bytes.clone(), memory_map: memory.clone() }, | |
| 524 | 543 | )) |
| 525 | 544 | } |
| 526 | 545 | ConstScalar::UnevaluatedConst(c, subst) => { |
| ... | ... | @@ -633,6 +652,16 @@ impl<'db> ChalkToNextSolver<'db, GenericArg<'db>> for chalk_ir::GenericArg<Inter |
| 633 | 652 | } |
| 634 | 653 | } |
| 635 | 654 | |
| 655 | impl<'db> NextSolverToChalk<'db, crate::GenericArg> for GenericArg<'db> { | |
| 656 | fn to_chalk(self, interner: DbInterner<'db>) -> crate::GenericArg { | |
| 657 | match self { | |
| 658 | GenericArg::Ty(ty) => ty.to_chalk(interner).cast(Interner), | |
| 659 | GenericArg::Lifetime(region) => region.to_chalk(interner).cast(Interner), | |
| 660 | GenericArg::Const(konst) => konst.to_chalk(interner).cast(Interner), | |
| 661 | } | |
| 662 | } | |
| 663 | } | |
| 664 | ||
| 636 | 665 | impl<'db> ChalkToNextSolver<'db, GenericArgs<'db>> for chalk_ir::Substitution<Interner> { |
| 637 | 666 | fn to_nextsolver(&self, interner: DbInterner<'db>) -> GenericArgs<'db> { |
| 638 | 667 | GenericArgs::new_from_iter( |
| ... | ... | @@ -642,6 +671,17 @@ impl<'db> ChalkToNextSolver<'db, GenericArgs<'db>> for chalk_ir::Substitution<In |
| 642 | 671 | } |
| 643 | 672 | } |
| 644 | 673 | |
| 674 | impl<'db> ChalkToNextSolver<'db, crate::lower_nextsolver::ImplTraitIdx<'db>> | |
| 675 | for crate::ImplTraitIdx | |
| 676 | { | |
| 677 | fn to_nextsolver( | |
| 678 | &self, | |
| 679 | interner: DbInterner<'db>, | |
| 680 | ) -> crate::lower_nextsolver::ImplTraitIdx<'db> { | |
| 681 | crate::lower_nextsolver::ImplTraitIdx::from_raw(self.into_raw()) | |
| 682 | } | |
| 683 | } | |
| 684 | ||
| 645 | 685 | impl<'db> NextSolverToChalk<'db, chalk_ir::Substitution<Interner>> for GenericArgs<'db> { |
| 646 | 686 | fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Substitution<Interner> { |
| 647 | 687 | convert_args_for_result(interner, self.as_slice()) |
| ... | ... | @@ -1670,8 +1710,10 @@ pub fn convert_const_for_result<'db>( |
| 1670 | 1710 | let bytes = value_const.value.inner(); |
| 1671 | 1711 | let value = chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { |
| 1672 | 1712 | // SAFETY: we will never actually use this without a database |
| 1673 | interned: ConstScalar::Bytes(bytes.0.clone(), unsafe { | |
| 1674 | std::mem::transmute::<MemoryMap<'db>, MemoryMap<'static>>(bytes.1.clone()) | |
| 1713 | interned: ConstScalar::Bytes(bytes.memory.clone(), unsafe { | |
| 1714 | std::mem::transmute::<MemoryMap<'db>, MemoryMap<'static>>( | |
| 1715 | bytes.memory_map.clone(), | |
| 1716 | ) | |
| 1675 | 1717 | }), |
| 1676 | 1718 | }); |
| 1677 | 1719 | return chalk_ir::ConstData { |
src/tools/rust-analyzer/crates/hir-ty/src/next_solver/opaques.rs+2-4| ... | ... | @@ -24,12 +24,11 @@ impl<'db> PredefinedOpaques<'db> { |
| 24 | 24 | } |
| 25 | 25 | |
| 26 | 26 | pub fn inner(&self) -> &PredefinedOpaquesData<'db> { |
| 27 | salsa::with_attached_database(|db| { | |
| 27 | crate::with_attached_db(|db| { | |
| 28 | 28 | let inner = self.kind_(db); |
| 29 | 29 | // SAFETY: ¯\_(ツ)_/¯ |
| 30 | 30 | unsafe { std::mem::transmute(inner) } |
| 31 | 31 | }) |
| 32 | .unwrap() | |
| 33 | 32 | } |
| 34 | 33 | } |
| 35 | 34 | |
| ... | ... | @@ -96,12 +95,11 @@ impl<'db> ExternalConstraints<'db> { |
| 96 | 95 | } |
| 97 | 96 | |
| 98 | 97 | pub fn inner(&self) -> &ExternalConstraintsData<'db> { |
| 99 | salsa::with_attached_database(|db| { | |
| 98 | crate::with_attached_db(|db| { | |
| 100 | 99 | let inner = self.kind_(db); |
| 101 | 100 | // SAFETY: ¯\_(ツ)_/¯ |
| 102 | 101 | unsafe { std::mem::transmute(inner) } |
| 103 | 102 | }) |
| 104 | .unwrap() | |
| 105 | 103 | } |
| 106 | 104 | } |
| 107 | 105 |
src/tools/rust-analyzer/crates/hir-ty/src/next_solver/predicate.rs+4-27| ... | ... | @@ -3,6 +3,7 @@ |
| 3 | 3 | use std::cmp::Ordering; |
| 4 | 4 | |
| 5 | 5 | use intern::Interned; |
| 6 | use macros::{TypeFoldable, TypeVisitable}; | |
| 6 | 7 | use rustc_ast_ir::try_visit; |
| 7 | 8 | use rustc_type_ir::{ |
| 8 | 9 | self as ty, CollectAndApply, DebruijnIndex, EarlyBinder, FlagComputation, Flags, |
| ... | ... | @@ -232,13 +233,12 @@ impl<'db> Predicate<'db> { |
| 232 | 233 | } |
| 233 | 234 | |
| 234 | 235 | pub fn inner(&self) -> &WithCachedTypeInfo<Binder<'db, PredicateKind<'db>>> { |
| 235 | salsa::with_attached_database(|db| { | |
| 236 | crate::with_attached_db(|db| { | |
| 236 | 237 | let inner = &self.kind_(db).0; |
| 237 | 238 | // SAFETY: The caller already has access to a `Predicate<'db>`, so borrowchecking will |
| 238 | 239 | // make sure that our returned value is valid for the lifetime `'db`. |
| 239 | 240 | unsafe { std::mem::transmute(inner) } |
| 240 | 241 | }) |
| 241 | .unwrap() | |
| 242 | 242 | } |
| 243 | 243 | |
| 244 | 244 | /// Flips the polarity of a Predicate. |
| ... | ... | @@ -303,13 +303,12 @@ impl<'db> Clauses<'db> { |
| 303 | 303 | } |
| 304 | 304 | |
| 305 | 305 | pub fn inner(&self) -> &InternedClausesWrapper<'db> { |
| 306 | salsa::with_attached_database(|db| { | |
| 306 | crate::with_attached_db(|db| { | |
| 307 | 307 | let inner = self.inner_(db); |
| 308 | 308 | // SAFETY: The caller already has access to a `Clauses<'db>`, so borrowchecking will |
| 309 | 309 | // make sure that our returned value is valid for the lifetime `'db`. |
| 310 | 310 | unsafe { std::mem::transmute(inner) } |
| 311 | 311 | }) |
| 312 | .unwrap() | |
| 313 | 312 | } |
| 314 | 313 | } |
| 315 | 314 | |
| ... | ... | @@ -426,7 +425,7 @@ impl<'db> rustc_type_ir::TypeSuperVisitable<DbInterner<'db>> for Clauses<'db> { |
| 426 | 425 | pub struct Clause<'db>(pub(crate) Predicate<'db>); |
| 427 | 426 | |
| 428 | 427 | // We could cram the reveal into the clauses like rustc does, probably |
| 429 | #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] | |
| 428 | #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, TypeVisitable, TypeFoldable)] | |
| 430 | 429 | pub struct ParamEnv<'db> { |
| 431 | 430 | pub(crate) clauses: Clauses<'db>, |
| 432 | 431 | } |
| ... | ... | @@ -437,28 +436,6 @@ impl<'db> ParamEnv<'db> { |
| 437 | 436 | } |
| 438 | 437 | } |
| 439 | 438 | |
| 440 | impl<'db> TypeVisitable<DbInterner<'db>> for ParamEnv<'db> { | |
| 441 | fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>( | |
| 442 | &self, | |
| 443 | visitor: &mut V, | |
| 444 | ) -> V::Result { | |
| 445 | try_visit!(self.clauses.visit_with(visitor)); | |
| 446 | V::Result::output() | |
| 447 | } | |
| 448 | } | |
| 449 | ||
| 450 | impl<'db> TypeFoldable<DbInterner<'db>> for ParamEnv<'db> { | |
| 451 | fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>( | |
| 452 | self, | |
| 453 | folder: &mut F, | |
| 454 | ) -> Result<Self, F::Error> { | |
| 455 | Ok(ParamEnv { clauses: self.clauses.try_fold_with(folder)? }) | |
| 456 | } | |
| 457 | fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self { | |
| 458 | ParamEnv { clauses: self.clauses.fold_with(folder) } | |
| 459 | } | |
| 460 | } | |
| 461 | ||
| 462 | 439 | impl<'db> rustc_type_ir::inherent::ParamEnv<DbInterner<'db>> for ParamEnv<'db> { |
| 463 | 440 | fn caller_bounds(self) -> impl rustc_type_ir::inherent::SliceLike<Item = Clause<'db>> { |
| 464 | 441 | self.clauses |
src/tools/rust-analyzer/crates/hir-ty/src/next_solver/region.rs+22-4| ... | ... | @@ -3,7 +3,8 @@ |
| 3 | 3 | use hir_def::LifetimeParamId; |
| 4 | 4 | use intern::{Interned, Symbol}; |
| 5 | 5 | use rustc_type_ir::{ |
| 6 | BoundVar, Flags, INNERMOST, RegionVid, TypeFlags, TypeFoldable, TypeVisitable, VisitorResult, | |
| 6 | BoundVar, DebruijnIndex, Flags, INNERMOST, RegionVid, TypeFlags, TypeFoldable, TypeVisitable, | |
| 7 | VisitorResult, | |
| 7 | 8 | inherent::{IntoKind, PlaceholderLike, SliceLike}, |
| 8 | 9 | relate::Relate, |
| 9 | 10 | }; |
| ... | ... | @@ -17,25 +18,30 @@ use super::{ |
| 17 | 18 | |
| 18 | 19 | pub type RegionKind<'db> = rustc_type_ir::RegionKind<DbInterner<'db>>; |
| 19 | 20 | |
| 20 | #[salsa::interned(constructor = new_, debug)] | |
| 21 | #[salsa::interned(constructor = new_)] | |
| 21 | 22 | pub struct Region<'db> { |
| 22 | 23 | #[returns(ref)] |
| 23 | 24 | kind_: RegionKind<'db>, |
| 24 | 25 | } |
| 25 | 26 | |
| 27 | impl std::fmt::Debug for Region<'_> { | |
| 28 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
| 29 | self.kind().fmt(f) | |
| 30 | } | |
| 31 | } | |
| 32 | ||
| 26 | 33 | impl<'db> Region<'db> { |
| 27 | 34 | pub fn new(interner: DbInterner<'db>, kind: RegionKind<'db>) -> Self { |
| 28 | 35 | Region::new_(interner.db(), kind) |
| 29 | 36 | } |
| 30 | 37 | |
| 31 | 38 | pub fn inner(&self) -> &RegionKind<'db> { |
| 32 | salsa::with_attached_database(|db| { | |
| 39 | crate::with_attached_db(|db| { | |
| 33 | 40 | let inner = self.kind_(db); |
| 34 | 41 | // SAFETY: The caller already has access to a `Region<'db>`, so borrowchecking will |
| 35 | 42 | // make sure that our returned value is valid for the lifetime `'db`. |
| 36 | 43 | unsafe { std::mem::transmute::<&RegionKind<'_>, &RegionKind<'db>>(inner) } |
| 37 | 44 | }) |
| 38 | .unwrap() | |
| 39 | 45 | } |
| 40 | 46 | |
| 41 | 47 | pub fn new_early_param( |
| ... | ... | @@ -57,6 +63,14 @@ impl<'db> Region<'db> { |
| 57 | 63 | Region::new(interner, RegionKind::ReErased) |
| 58 | 64 | } |
| 59 | 65 | |
| 66 | pub fn new_bound( | |
| 67 | interner: DbInterner<'db>, | |
| 68 | index: DebruijnIndex, | |
| 69 | bound: BoundRegion, | |
| 70 | ) -> Region<'db> { | |
| 71 | Region::new(interner, RegionKind::ReBound(index, bound)) | |
| 72 | } | |
| 73 | ||
| 60 | 74 | pub fn is_placeholder(&self) -> bool { |
| 61 | 75 | matches!(self.inner(), RegionKind::RePlaceholder(..)) |
| 62 | 76 | } |
| ... | ... | @@ -69,6 +83,10 @@ impl<'db> Region<'db> { |
| 69 | 83 | matches!(self.inner(), RegionKind::ReVar(_)) |
| 70 | 84 | } |
| 71 | 85 | |
| 86 | pub fn is_error(&self) -> bool { | |
| 87 | matches!(self.inner(), RegionKind::ReError(_)) | |
| 88 | } | |
| 89 | ||
| 72 | 90 | pub fn error(interner: DbInterner<'db>) -> Self { |
| 73 | 91 | Region::new(interner, RegionKind::ReError(ErrorGuaranteed)) |
| 74 | 92 | } |
src/tools/rust-analyzer/crates/hir-ty/src/next_solver/solver.rs+45-20| ... | ... | @@ -149,13 +149,9 @@ impl<'db> SolverDelegate for SolverContext<'db> { |
| 149 | 149 | fn fetch_eligible_assoc_item( |
| 150 | 150 | &self, |
| 151 | 151 | goal_trait_ref: rustc_type_ir::TraitRef<Self::Interner>, |
| 152 | trait_assoc_def_id: <Self::Interner as rustc_type_ir::Interner>::DefId, | |
| 152 | trait_assoc_def_id: SolverDefId, | |
| 153 | 153 | impl_id: ImplIdWrapper, |
| 154 | ) -> Result<Option<<Self::Interner as rustc_type_ir::Interner>::DefId>, ErrorGuaranteed> { | |
| 155 | let trait_assoc_id = match trait_assoc_def_id { | |
| 156 | SolverDefId::TypeAliasId(id) => id, | |
| 157 | _ => panic!("Unexpected SolverDefId"), | |
| 158 | }; | |
| 154 | ) -> Result<Option<SolverDefId>, ErrorGuaranteed> { | |
| 159 | 155 | let trait_ = self |
| 160 | 156 | .0 |
| 161 | 157 | .interner |
| ... | ... | @@ -167,18 +163,47 @@ impl<'db> SolverDelegate for SolverContext<'db> { |
| 167 | 163 | .def_id |
| 168 | 164 | .0; |
| 169 | 165 | let trait_data = trait_.trait_items(self.0.interner.db()); |
| 170 | let id = | |
| 171 | impl_id.0.impl_items(self.0.interner.db()).items.iter().find_map(|item| -> Option<_> { | |
| 172 | match item { | |
| 173 | (_, AssocItemId::TypeAliasId(type_alias)) => { | |
| 174 | let name = &self.0.interner.db().type_alias_signature(*type_alias).name; | |
| 175 | let found_trait_assoc_id = trait_data.associated_type_by_name(name)?; | |
| 176 | (found_trait_assoc_id == trait_assoc_id).then_some(*type_alias) | |
| 177 | } | |
| 178 | _ => None, | |
| 179 | } | |
| 180 | }); | |
| 181 | Ok(id.map(SolverDefId::TypeAliasId)) | |
| 166 | let impl_items = impl_id.0.impl_items(self.0.interner.db()); | |
| 167 | let id = match trait_assoc_def_id { | |
| 168 | SolverDefId::TypeAliasId(trait_assoc_id) => { | |
| 169 | let trait_assoc_data = self.0.interner.db.type_alias_signature(trait_assoc_id); | |
| 170 | impl_items | |
| 171 | .items | |
| 172 | .iter() | |
| 173 | .find_map(|(impl_assoc_name, impl_assoc_id)| { | |
| 174 | if let AssocItemId::TypeAliasId(impl_assoc_id) = *impl_assoc_id | |
| 175 | && *impl_assoc_name == trait_assoc_data.name | |
| 176 | { | |
| 177 | Some(impl_assoc_id) | |
| 178 | } else { | |
| 179 | None | |
| 180 | } | |
| 181 | }) | |
| 182 | .map(SolverDefId::TypeAliasId) | |
| 183 | } | |
| 184 | SolverDefId::ConstId(trait_assoc_id) => { | |
| 185 | let trait_assoc_data = self.0.interner.db.const_signature(trait_assoc_id); | |
| 186 | let trait_assoc_name = trait_assoc_data | |
| 187 | .name | |
| 188 | .as_ref() | |
| 189 | .expect("unnamed consts should not get passed to the solver"); | |
| 190 | impl_items | |
| 191 | .items | |
| 192 | .iter() | |
| 193 | .find_map(|(impl_assoc_name, impl_assoc_id)| { | |
| 194 | if let AssocItemId::ConstId(impl_assoc_id) = *impl_assoc_id | |
| 195 | && impl_assoc_name == trait_assoc_name | |
| 196 | { | |
| 197 | Some(impl_assoc_id) | |
| 198 | } else { | |
| 199 | None | |
| 200 | } | |
| 201 | }) | |
| 202 | .map(SolverDefId::ConstId) | |
| 203 | } | |
| 204 | _ => panic!("Unexpected SolverDefId"), | |
| 205 | }; | |
| 206 | Ok(id) | |
| 182 | 207 | } |
| 183 | 208 | |
| 184 | 209 | fn is_transmutable( |
| ... | ... | @@ -200,9 +225,9 @@ impl<'db> SolverDelegate for SolverContext<'db> { |
| 200 | 225 | SolverDefId::StaticId(c) => GeneralConstId::StaticId(c), |
| 201 | 226 | _ => unreachable!(), |
| 202 | 227 | }; |
| 203 | let subst = uv.args.to_chalk(self.interner); | |
| 228 | let subst = uv.args; | |
| 204 | 229 | let ec = self.cx().db.const_eval(c, subst, None).ok()?; |
| 205 | Some(ec.to_nextsolver(self.interner)) | |
| 230 | Some(ec) | |
| 206 | 231 | } |
| 207 | 232 | |
| 208 | 233 | fn compute_goal_fast_path( |
src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs+282-14| ... | ... | @@ -3,18 +3,22 @@ |
| 3 | 3 | use std::iter; |
| 4 | 4 | use std::ops::ControlFlow; |
| 5 | 5 | |
| 6 | use hir_def::{GenericDefId, TypeOrConstParamId, TypeParamId}; | |
| 6 | use hir_def::{ | |
| 7 | AdtId, DefWithBodyId, GenericDefId, HasModule, TypeOrConstParamId, TypeParamId, | |
| 8 | hir::generics::{TypeOrConstParamData, TypeParamProvenance}, | |
| 9 | lang_item::LangItem, | |
| 10 | }; | |
| 11 | use hir_def::{TraitId, type_ref::Rawness}; | |
| 7 | 12 | use intern::{Interned, Symbol, sym}; |
| 8 | 13 | use rustc_abi::{Float, Integer, Size}; |
| 9 | 14 | use rustc_ast_ir::{Mutability, try_visit, visit::VisitorResult}; |
| 10 | use rustc_type_ir::TyVid; | |
| 11 | 15 | use rustc_type_ir::{ |
| 12 | BoundVar, ClosureKind, CollectAndApply, FlagComputation, Flags, FloatTy, FloatVid, InferTy, | |
| 13 | IntTy, IntVid, Interner, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, | |
| 14 | TypeVisitableExt, TypeVisitor, UintTy, WithCachedTypeInfo, | |
| 16 | AliasTyKind, BoundVar, ClosureKind, CollectAndApply, FlagComputation, Flags, FloatTy, FloatVid, | |
| 17 | InferTy, IntTy, IntVid, Interner, TyVid, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, | |
| 18 | TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, Upcast, WithCachedTypeInfo, | |
| 15 | 19 | inherent::{ |
| 16 | Abi, AdtDef, BoundVarLike, Const as _, GenericArgs as _, IntoKind, ParamLike, | |
| 17 | PlaceholderLike, Safety as _, SliceLike, Ty as _, | |
| 20 | Abi, AdtDef as _, BoundExistentialPredicates, BoundVarLike, Const as _, GenericArgs as _, | |
| 21 | IntoKind, ParamLike, PlaceholderLike, Safety as _, SliceLike, Ty as _, | |
| 18 | 22 | }, |
| 19 | 23 | relate::Relate, |
| 20 | 24 | solve::SizedTraitKind, |
| ... | ... | @@ -24,13 +28,14 @@ use salsa::plumbing::{AsId, FromId}; |
| 24 | 28 | use smallvec::SmallVec; |
| 25 | 29 | |
| 26 | 30 | use crate::{ |
| 27 | FnAbi, | |
| 31 | FnAbi, ImplTraitId, | |
| 28 | 32 | db::HirDatabase, |
| 29 | 33 | interner::InternedWrapperNoDebug, |
| 30 | 34 | next_solver::{ |
| 31 | CallableIdWrapper, ClosureIdWrapper, Const, CoroutineIdWrapper, FnSig, GenericArg, | |
| 32 | PolyFnSig, TypeAliasIdWrapper, | |
| 35 | AdtDef, Binder, CallableIdWrapper, Clause, ClauseKind, ClosureIdWrapper, Const, | |
| 36 | CoroutineIdWrapper, FnSig, GenericArg, PolyFnSig, Region, TraitRef, TypeAliasIdWrapper, | |
| 33 | 37 | abi::Safety, |
| 38 | mapping::ChalkToNextSolver, | |
| 34 | 39 | util::{CoroutineArgsExt, IntegerTypeExt}, |
| 35 | 40 | }, |
| 36 | 41 | }; |
| ... | ... | @@ -66,13 +71,16 @@ impl<'db> Ty<'db> { |
| 66 | 71 | } |
| 67 | 72 | |
| 68 | 73 | pub fn inner(&self) -> &WithCachedTypeInfo<TyKind<'db>> { |
| 69 | salsa::with_attached_database(|db| { | |
| 74 | crate::with_attached_db(|db| { | |
| 70 | 75 | let inner = &self.kind_(db).0; |
| 71 | 76 | // SAFETY: The caller already has access to a `Ty<'db>`, so borrowchecking will |
| 72 | 77 | // make sure that our returned value is valid for the lifetime `'db`. |
| 73 | 78 | unsafe { std::mem::transmute(inner) } |
| 74 | 79 | }) |
| 75 | .unwrap() | |
| 80 | } | |
| 81 | ||
| 82 | pub fn new_adt(interner: DbInterner<'db>, adt_id: AdtId, args: GenericArgs<'db>) -> Self { | |
| 83 | Ty::new(interner, TyKind::Adt(AdtDef::new(adt_id, interner), args)) | |
| 76 | 84 | } |
| 77 | 85 | |
| 78 | 86 | pub fn new_param(interner: DbInterner<'db>, id: TypeParamId, index: u32, name: Symbol) -> Self { |
| ... | ... | @@ -337,6 +345,23 @@ impl<'db> Ty<'db> { |
| 337 | 345 | matches!(self.kind(), TyKind::Tuple(tys) if tys.inner().is_empty()) |
| 338 | 346 | } |
| 339 | 347 | |
| 348 | #[inline] | |
| 349 | pub fn is_raw_ptr(self) -> bool { | |
| 350 | matches!(self.kind(), TyKind::RawPtr(..)) | |
| 351 | } | |
| 352 | ||
| 353 | pub fn is_union(self) -> bool { | |
| 354 | self.as_adt().is_some_and(|(adt, _)| matches!(adt, AdtId::UnionId(_))) | |
| 355 | } | |
| 356 | ||
| 357 | #[inline] | |
| 358 | pub fn as_adt(self) -> Option<(AdtId, GenericArgs<'db>)> { | |
| 359 | match self.kind() { | |
| 360 | TyKind::Adt(adt_def, args) => Some((adt_def.def_id().0, args)), | |
| 361 | _ => None, | |
| 362 | } | |
| 363 | } | |
| 364 | ||
| 340 | 365 | #[inline] |
| 341 | 366 | pub fn ty_vid(self) -> Option<TyVid> { |
| 342 | 367 | match self.kind() { |
| ... | ... | @@ -370,8 +395,245 @@ impl<'db> Ty<'db> { |
| 370 | 395 | |
| 371 | 396 | /// Whether the type contains some non-lifetime, aka. type or const, error type. |
| 372 | 397 | pub fn references_non_lt_error(self) -> bool { |
| 373 | self.references_error() && self.visit_with(&mut ReferencesNonLifetimeError).is_break() | |
| 398 | references_non_lt_error(&self) | |
| 399 | } | |
| 400 | ||
| 401 | pub fn callable_sig(self, interner: DbInterner<'db>) -> Option<Binder<'db, FnSig<'db>>> { | |
| 402 | match self.kind() { | |
| 403 | TyKind::FnDef(callable, args) => { | |
| 404 | Some(interner.fn_sig(callable).instantiate(interner, args)) | |
| 405 | } | |
| 406 | TyKind::FnPtr(sig, hdr) => Some(sig.with(hdr)), | |
| 407 | TyKind::Closure(closure_id, closure_args) => closure_args | |
| 408 | .split_closure_args_untupled() | |
| 409 | .closure_sig_as_fn_ptr_ty | |
| 410 | .callable_sig(interner), | |
| 411 | _ => None, | |
| 412 | } | |
| 413 | } | |
| 414 | ||
| 415 | pub fn as_reference(self) -> Option<(Ty<'db>, Region<'db>, Mutability)> { | |
| 416 | match self.kind() { | |
| 417 | TyKind::Ref(region, ty, mutability) => Some((ty, region, mutability)), | |
| 418 | _ => None, | |
| 419 | } | |
| 420 | } | |
| 421 | ||
| 422 | pub fn as_reference_or_ptr(self) -> Option<(Ty<'db>, Rawness, Mutability)> { | |
| 423 | match self.kind() { | |
| 424 | TyKind::Ref(_, ty, mutability) => Some((ty, Rawness::Ref, mutability)), | |
| 425 | TyKind::RawPtr(ty, mutability) => Some((ty, Rawness::RawPtr, mutability)), | |
| 426 | _ => None, | |
| 427 | } | |
| 374 | 428 | } |
| 429 | ||
| 430 | pub fn as_tuple(self) -> Option<Tys<'db>> { | |
| 431 | match self.kind() { | |
| 432 | TyKind::Tuple(tys) => Some(tys), | |
| 433 | _ => None, | |
| 434 | } | |
| 435 | } | |
| 436 | ||
| 437 | pub fn dyn_trait(self) -> Option<TraitId> { | |
| 438 | let TyKind::Dynamic(bounds, _) = self.kind() else { return None }; | |
| 439 | Some(bounds.principal_def_id()?.0) | |
| 440 | } | |
| 441 | ||
| 442 | pub fn strip_references(self) -> Ty<'db> { | |
| 443 | let mut t = self; | |
| 444 | while let TyKind::Ref(_lifetime, ty, _mutability) = t.kind() { | |
| 445 | t = ty; | |
| 446 | } | |
| 447 | t | |
| 448 | } | |
| 449 | ||
| 450 | pub fn strip_reference(self) -> Ty<'db> { | |
| 451 | self.as_reference().map_or(self, |(ty, _, _)| ty) | |
| 452 | } | |
| 453 | ||
| 454 | /// Replace infer vars with errors. | |
| 455 | /// | |
| 456 | /// This needs to be called for every type that may contain infer vars and is yielded to outside inference, | |
| 457 | /// as things other than inference do not expect to see infer vars. | |
| 458 | pub fn replace_infer_with_error(self, interner: DbInterner<'db>) -> Ty<'db> { | |
| 459 | self.fold_with(&mut crate::next_solver::infer::resolve::ReplaceInferWithError::new( | |
| 460 | interner, | |
| 461 | )) | |
| 462 | } | |
| 463 | ||
| 464 | pub fn from_builtin_type( | |
| 465 | interner: DbInterner<'db>, | |
| 466 | ty: hir_def::builtin_type::BuiltinType, | |
| 467 | ) -> Ty<'db> { | |
| 468 | let kind = match ty { | |
| 469 | hir_def::builtin_type::BuiltinType::Char => TyKind::Char, | |
| 470 | hir_def::builtin_type::BuiltinType::Bool => TyKind::Bool, | |
| 471 | hir_def::builtin_type::BuiltinType::Str => TyKind::Str, | |
| 472 | hir_def::builtin_type::BuiltinType::Int(int) => TyKind::Int(match int { | |
| 473 | hir_def::builtin_type::BuiltinInt::Isize => rustc_type_ir::IntTy::Isize, | |
| 474 | hir_def::builtin_type::BuiltinInt::I8 => rustc_type_ir::IntTy::I8, | |
| 475 | hir_def::builtin_type::BuiltinInt::I16 => rustc_type_ir::IntTy::I16, | |
| 476 | hir_def::builtin_type::BuiltinInt::I32 => rustc_type_ir::IntTy::I32, | |
| 477 | hir_def::builtin_type::BuiltinInt::I64 => rustc_type_ir::IntTy::I64, | |
| 478 | hir_def::builtin_type::BuiltinInt::I128 => rustc_type_ir::IntTy::I128, | |
| 479 | }), | |
| 480 | hir_def::builtin_type::BuiltinType::Uint(uint) => TyKind::Uint(match uint { | |
| 481 | hir_def::builtin_type::BuiltinUint::Usize => rustc_type_ir::UintTy::Usize, | |
| 482 | hir_def::builtin_type::BuiltinUint::U8 => rustc_type_ir::UintTy::U8, | |
| 483 | hir_def::builtin_type::BuiltinUint::U16 => rustc_type_ir::UintTy::U16, | |
| 484 | hir_def::builtin_type::BuiltinUint::U32 => rustc_type_ir::UintTy::U32, | |
| 485 | hir_def::builtin_type::BuiltinUint::U64 => rustc_type_ir::UintTy::U64, | |
| 486 | hir_def::builtin_type::BuiltinUint::U128 => rustc_type_ir::UintTy::U128, | |
| 487 | }), | |
| 488 | hir_def::builtin_type::BuiltinType::Float(float) => TyKind::Float(match float { | |
| 489 | hir_def::builtin_type::BuiltinFloat::F16 => rustc_type_ir::FloatTy::F16, | |
| 490 | hir_def::builtin_type::BuiltinFloat::F32 => rustc_type_ir::FloatTy::F32, | |
| 491 | hir_def::builtin_type::BuiltinFloat::F64 => rustc_type_ir::FloatTy::F64, | |
| 492 | hir_def::builtin_type::BuiltinFloat::F128 => rustc_type_ir::FloatTy::F128, | |
| 493 | }), | |
| 494 | }; | |
| 495 | Ty::new(interner, kind) | |
| 496 | } | |
| 497 | ||
| 498 | pub fn as_builtin(self) -> Option<hir_def::builtin_type::BuiltinType> { | |
| 499 | let builtin = match self.kind() { | |
| 500 | TyKind::Char => hir_def::builtin_type::BuiltinType::Char, | |
| 501 | TyKind::Bool => hir_def::builtin_type::BuiltinType::Bool, | |
| 502 | TyKind::Str => hir_def::builtin_type::BuiltinType::Str, | |
| 503 | TyKind::Int(int) => hir_def::builtin_type::BuiltinType::Int(match int { | |
| 504 | rustc_type_ir::IntTy::Isize => hir_def::builtin_type::BuiltinInt::Isize, | |
| 505 | rustc_type_ir::IntTy::I8 => hir_def::builtin_type::BuiltinInt::I8, | |
| 506 | rustc_type_ir::IntTy::I16 => hir_def::builtin_type::BuiltinInt::I16, | |
| 507 | rustc_type_ir::IntTy::I32 => hir_def::builtin_type::BuiltinInt::I32, | |
| 508 | rustc_type_ir::IntTy::I64 => hir_def::builtin_type::BuiltinInt::I64, | |
| 509 | rustc_type_ir::IntTy::I128 => hir_def::builtin_type::BuiltinInt::I128, | |
| 510 | }), | |
| 511 | TyKind::Uint(uint) => hir_def::builtin_type::BuiltinType::Uint(match uint { | |
| 512 | rustc_type_ir::UintTy::Usize => hir_def::builtin_type::BuiltinUint::Usize, | |
| 513 | rustc_type_ir::UintTy::U8 => hir_def::builtin_type::BuiltinUint::U8, | |
| 514 | rustc_type_ir::UintTy::U16 => hir_def::builtin_type::BuiltinUint::U16, | |
| 515 | rustc_type_ir::UintTy::U32 => hir_def::builtin_type::BuiltinUint::U32, | |
| 516 | rustc_type_ir::UintTy::U64 => hir_def::builtin_type::BuiltinUint::U64, | |
| 517 | rustc_type_ir::UintTy::U128 => hir_def::builtin_type::BuiltinUint::U128, | |
| 518 | }), | |
| 519 | TyKind::Float(float) => hir_def::builtin_type::BuiltinType::Float(match float { | |
| 520 | rustc_type_ir::FloatTy::F16 => hir_def::builtin_type::BuiltinFloat::F16, | |
| 521 | rustc_type_ir::FloatTy::F32 => hir_def::builtin_type::BuiltinFloat::F32, | |
| 522 | rustc_type_ir::FloatTy::F64 => hir_def::builtin_type::BuiltinFloat::F64, | |
| 523 | rustc_type_ir::FloatTy::F128 => hir_def::builtin_type::BuiltinFloat::F128, | |
| 524 | }), | |
| 525 | _ => return None, | |
| 526 | }; | |
| 527 | Some(builtin) | |
| 528 | } | |
| 529 | ||
| 530 | // FIXME: Should this be here? | |
| 531 | pub fn impl_trait_bounds(self, db: &'db dyn HirDatabase) -> Option<Vec<Clause<'db>>> { | |
| 532 | let interner = DbInterner::new_with(db, None, None); | |
| 533 | ||
| 534 | match self.kind() { | |
| 535 | TyKind::Alias(AliasTyKind::Opaque, opaque_ty) => { | |
| 536 | match db.lookup_intern_impl_trait_id(opaque_ty.def_id.expect_opaque_ty()) { | |
| 537 | ImplTraitId::ReturnTypeImplTrait(func, idx) => { | |
| 538 | db.return_type_impl_traits_ns(func).map(|it| { | |
| 539 | let data = (*it).as_ref().map_bound(|rpit| { | |
| 540 | &rpit.impl_traits[idx.to_nextsolver(interner)].predicates | |
| 541 | }); | |
| 542 | data.iter_instantiated_copied(interner, opaque_ty.args.as_slice()) | |
| 543 | .collect() | |
| 544 | }) | |
| 545 | } | |
| 546 | ImplTraitId::TypeAliasImplTrait(alias, idx) => { | |
| 547 | db.type_alias_impl_traits_ns(alias).map(|it| { | |
| 548 | let data = (*it).as_ref().map_bound(|rpit| { | |
| 549 | &rpit.impl_traits[idx.to_nextsolver(interner)].predicates | |
| 550 | }); | |
| 551 | data.iter_instantiated_copied(interner, opaque_ty.args.as_slice()) | |
| 552 | .collect() | |
| 553 | }) | |
| 554 | } | |
| 555 | ImplTraitId::AsyncBlockTypeImplTrait(def, _) => { | |
| 556 | let krate = def.module(db).krate(); | |
| 557 | if let Some(future_trait) = LangItem::Future.resolve_trait(db, krate) { | |
| 558 | // This is only used by type walking. | |
| 559 | // Parameters will be walked outside, and projection predicate is not used. | |
| 560 | // So just provide the Future trait. | |
| 561 | let impl_bound = TraitRef::new( | |
| 562 | interner, | |
| 563 | future_trait.into(), | |
| 564 | GenericArgs::new_from_iter(interner, []), | |
| 565 | ) | |
| 566 | .upcast(interner); | |
| 567 | Some(vec![impl_bound]) | |
| 568 | } else { | |
| 569 | None | |
| 570 | } | |
| 571 | } | |
| 572 | } | |
| 573 | } | |
| 574 | TyKind::Param(param) => { | |
| 575 | // FIXME: We shouldn't use `param.id` here. | |
| 576 | let generic_params = db.generic_params(param.id.parent()); | |
| 577 | let param_data = &generic_params[param.id.local_id()]; | |
| 578 | match param_data { | |
| 579 | TypeOrConstParamData::TypeParamData(p) => match p.provenance { | |
| 580 | TypeParamProvenance::ArgumentImplTrait => { | |
| 581 | let predicates = db | |
| 582 | .generic_predicates_ns(param.id.parent()) | |
| 583 | .instantiate_identity() | |
| 584 | .into_iter() | |
| 585 | .flatten() | |
| 586 | .filter(|wc| match wc.kind().skip_binder() { | |
| 587 | ClauseKind::Trait(tr) => tr.self_ty() == self, | |
| 588 | ClauseKind::Projection(pred) => pred.self_ty() == self, | |
| 589 | ClauseKind::TypeOutlives(pred) => pred.0 == self, | |
| 590 | _ => false, | |
| 591 | }) | |
| 592 | .collect::<Vec<_>>(); | |
| 593 | ||
| 594 | Some(predicates) | |
| 595 | } | |
| 596 | _ => None, | |
| 597 | }, | |
| 598 | _ => None, | |
| 599 | } | |
| 600 | } | |
| 601 | _ => None, | |
| 602 | } | |
| 603 | } | |
| 604 | ||
| 605 | /// FIXME: Get rid of this, it's not a good abstraction | |
| 606 | pub fn equals_ctor(self, other: Ty<'db>) -> bool { | |
| 607 | match (self.kind(), other.kind()) { | |
| 608 | (TyKind::Adt(adt, ..), TyKind::Adt(adt2, ..)) => adt.def_id() == adt2.def_id(), | |
| 609 | (TyKind::Slice(_), TyKind::Slice(_)) | (TyKind::Array(_, _), TyKind::Array(_, _)) => { | |
| 610 | true | |
| 611 | } | |
| 612 | (TyKind::FnDef(def_id, ..), TyKind::FnDef(def_id2, ..)) => def_id == def_id2, | |
| 613 | (TyKind::Alias(_, alias, ..), TyKind::Alias(_, alias2)) => { | |
| 614 | alias.def_id == alias2.def_id | |
| 615 | } | |
| 616 | (TyKind::Foreign(ty_id, ..), TyKind::Foreign(ty_id2, ..)) => ty_id == ty_id2, | |
| 617 | (TyKind::Closure(id1, _), TyKind::Closure(id2, _)) => id1 == id2, | |
| 618 | (TyKind::Ref(.., mutability), TyKind::Ref(.., mutability2)) | |
| 619 | | (TyKind::RawPtr(.., mutability), TyKind::RawPtr(.., mutability2)) => { | |
| 620 | mutability == mutability2 | |
| 621 | } | |
| 622 | (TyKind::FnPtr(sig, hdr), TyKind::FnPtr(sig2, hdr2)) => sig == sig2 && hdr == hdr2, | |
| 623 | (TyKind::Tuple(tys), TyKind::Tuple(tys2)) => tys.len() == tys2.len(), | |
| 624 | (TyKind::Str, TyKind::Str) | |
| 625 | | (TyKind::Never, TyKind::Never) | |
| 626 | | (TyKind::Char, TyKind::Char) | |
| 627 | | (TyKind::Bool, TyKind::Bool) => true, | |
| 628 | (TyKind::Int(int), TyKind::Int(int2)) => int == int2, | |
| 629 | (TyKind::Float(float), TyKind::Float(float2)) => float == float2, | |
| 630 | _ => false, | |
| 631 | } | |
| 632 | } | |
| 633 | } | |
| 634 | ||
| 635 | pub fn references_non_lt_error<'db, T: TypeVisitableExt<DbInterner<'db>>>(t: &T) -> bool { | |
| 636 | t.references_error() && t.visit_with(&mut ReferencesNonLifetimeError).is_break() | |
| 375 | 637 | } |
| 376 | 638 | |
| 377 | 639 | struct ReferencesNonLifetimeError; |
| ... | ... | @@ -928,11 +1190,17 @@ impl<'db> rustc_type_ir::inherent::Ty<DbInterner<'db>> for Ty<'db> { |
| 928 | 1190 | |
| 929 | 1191 | interned_vec_db!(Tys, Ty); |
| 930 | 1192 | |
| 1193 | impl<'db> Tys<'db> { | |
| 1194 | pub fn inputs(&self) -> &[Ty<'db>] { | |
| 1195 | self.as_slice().split_last().unwrap().1 | |
| 1196 | } | |
| 1197 | } | |
| 1198 | ||
| 931 | 1199 | impl<'db> rustc_type_ir::inherent::Tys<DbInterner<'db>> for Tys<'db> { |
| 932 | 1200 | fn inputs(self) -> <DbInterner<'db> as rustc_type_ir::Interner>::FnInputTys { |
| 933 | 1201 | Tys::new_from_iter( |
| 934 | 1202 | DbInterner::conjure(), |
| 935 | self.as_slice().split_last().unwrap().1.iter().cloned(), | |
| 1203 | self.as_slice().split_last().unwrap().1.iter().copied(), | |
| 936 | 1204 | ) |
| 937 | 1205 | } |
| 938 | 1206 |
src/tools/rust-analyzer/crates/hir-ty/src/next_solver/util.rs+2-2| ... | ... | @@ -413,7 +413,7 @@ pub(crate) fn for_trait_impls( |
| 413 | 413 | let trait_module = trait_id.module(db); |
| 414 | 414 | let type_module = match self_ty_fp { |
| 415 | 415 | Some(TyFingerprint::Adt(adt_id)) => Some(adt_id.module(db)), |
| 416 | Some(TyFingerprint::ForeignType(type_id)) => Some(from_foreign_def_id(type_id).module(db)), | |
| 416 | Some(TyFingerprint::ForeignType(type_id)) => Some(type_id.module(db)), | |
| 417 | 417 | Some(TyFingerprint::Dyn(trait_id)) => Some(trait_id.module(db)), |
| 418 | 418 | _ => None, |
| 419 | 419 | }; |
| ... | ... | @@ -486,7 +486,7 @@ pub fn sizedness_constraint_for_ty<'db>( |
| 486 | 486 | |
| 487 | 487 | Tuple(tys) => tys |
| 488 | 488 | .into_iter() |
| 489 | .last() | |
| 489 | .next_back() | |
| 490 | 490 | .and_then(|ty| sizedness_constraint_for_ty(interner, sizedness, ty)), |
| 491 | 491 | |
| 492 | 492 | Adt(adt, args) => { |
src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs+2-3| ... | ... | @@ -10,7 +10,7 @@ use base_db::{ |
| 10 | 10 | use hir_def::{ModuleId, db::DefDatabase, nameres::crate_def_map}; |
| 11 | 11 | use hir_expand::EditionedFileId; |
| 12 | 12 | use rustc_hash::FxHashMap; |
| 13 | use salsa::{AsDynDatabase, Durability}; | |
| 13 | use salsa::Durability; | |
| 14 | 14 | use span::FileId; |
| 15 | 15 | use syntax::TextRange; |
| 16 | 16 | use test_utils::extract_annotations; |
| ... | ... | @@ -191,8 +191,7 @@ impl TestDB { |
| 191 | 191 | // This is pretty horrible, but `Debug` is the only way to inspect |
| 192 | 192 | // QueryDescriptor at the moment. |
| 193 | 193 | salsa::EventKind::WillExecute { database_key } => { |
| 194 | let ingredient = self | |
| 195 | .as_dyn_database() | |
| 194 | let ingredient = (self as &dyn salsa::Database) | |
| 196 | 195 | .ingredient_debug_name(database_key.ingredient_index()); |
| 197 | 196 | Some(ingredient.to_string()) |
| 198 | 197 | } |
src/tools/rust-analyzer/crates/hir-ty/src/tests.rs+281-275| ... | ... | @@ -36,10 +36,11 @@ use test_fixture::WithFixture; |
| 36 | 36 | use triomphe::Arc; |
| 37 | 37 | |
| 38 | 38 | use crate::{ |
| 39 | InferenceResult, Ty, | |
| 39 | InferenceResult, | |
| 40 | 40 | db::HirDatabase, |
| 41 | 41 | display::{DisplayTarget, HirDisplay}, |
| 42 | 42 | infer::{Adjustment, TypeMismatch}, |
| 43 | next_solver::Ty, | |
| 43 | 44 | setup_tracing, |
| 44 | 45 | test_db::TestDB, |
| 45 | 46 | }; |
| ... | ... | @@ -78,172 +79,172 @@ fn check_impl( |
| 78 | 79 | let _tracing = setup_tracing(); |
| 79 | 80 | let (db, files) = TestDB::with_many_files(ra_fixture); |
| 80 | 81 | |
| 81 | let mut had_annotations = false; | |
| 82 | let mut mismatches = FxHashMap::default(); | |
| 83 | let mut types = FxHashMap::default(); | |
| 84 | let mut adjustments = FxHashMap::default(); | |
| 85 | for (file_id, annotations) in db.extract_annotations() { | |
| 86 | for (range, expected) in annotations { | |
| 87 | let file_range = FileRange { file_id, range }; | |
| 88 | if only_types { | |
| 89 | types.insert(file_range, expected); | |
| 90 | } else if expected.starts_with("type: ") { | |
| 91 | types.insert(file_range, expected.trim_start_matches("type: ").to_owned()); | |
| 92 | } else if expected.starts_with("expected") { | |
| 93 | mismatches.insert(file_range, expected); | |
| 94 | } else if expected.starts_with("adjustments:") { | |
| 95 | adjustments.insert( | |
| 96 | file_range, | |
| 97 | expected.trim_start_matches("adjustments:").trim().to_owned(), | |
| 98 | ); | |
| 99 | } else { | |
| 100 | panic!("unexpected annotation: {expected} @ {range:?}"); | |
| 82 | crate::attach_db(&db, || { | |
| 83 | let mut had_annotations = false; | |
| 84 | let mut mismatches = FxHashMap::default(); | |
| 85 | let mut types = FxHashMap::default(); | |
| 86 | let mut adjustments = FxHashMap::default(); | |
| 87 | for (file_id, annotations) in db.extract_annotations() { | |
| 88 | for (range, expected) in annotations { | |
| 89 | let file_range = FileRange { file_id, range }; | |
| 90 | if only_types { | |
| 91 | types.insert(file_range, expected); | |
| 92 | } else if expected.starts_with("type: ") { | |
| 93 | types.insert(file_range, expected.trim_start_matches("type: ").to_owned()); | |
| 94 | } else if expected.starts_with("expected") { | |
| 95 | mismatches.insert(file_range, expected); | |
| 96 | } else if expected.starts_with("adjustments:") { | |
| 97 | adjustments.insert( | |
| 98 | file_range, | |
| 99 | expected.trim_start_matches("adjustments:").trim().to_owned(), | |
| 100 | ); | |
| 101 | } else { | |
| 102 | panic!("unexpected annotation: {expected} @ {range:?}"); | |
| 103 | } | |
| 104 | had_annotations = true; | |
| 101 | 105 | } |
| 102 | had_annotations = true; | |
| 103 | 106 | } |
| 104 | } | |
| 105 | assert!(had_annotations || allow_none, "no `//^` annotations found"); | |
| 106 | ||
| 107 | let mut defs: Vec<(DefWithBodyId, Crate)> = Vec::new(); | |
| 108 | for file_id in files { | |
| 109 | let module = db.module_for_file_opt(file_id.file_id(&db)); | |
| 110 | let module = match module { | |
| 111 | Some(m) => m, | |
| 112 | None => continue, | |
| 113 | }; | |
| 114 | let def_map = module.def_map(&db); | |
| 115 | visit_module(&db, def_map, module.local_id, &mut |it| { | |
| 116 | let def = match it { | |
| 117 | ModuleDefId::FunctionId(it) => it.into(), | |
| 118 | ModuleDefId::EnumVariantId(it) => it.into(), | |
| 119 | ModuleDefId::ConstId(it) => it.into(), | |
| 120 | ModuleDefId::StaticId(it) => it.into(), | |
| 121 | _ => return, | |
| 107 | assert!(had_annotations || allow_none, "no `//^` annotations found"); | |
| 108 | ||
| 109 | let mut defs: Vec<(DefWithBodyId, Crate)> = Vec::new(); | |
| 110 | for file_id in files { | |
| 111 | let module = db.module_for_file_opt(file_id.file_id(&db)); | |
| 112 | let module = match module { | |
| 113 | Some(m) => m, | |
| 114 | None => continue, | |
| 122 | 115 | }; |
| 123 | defs.push((def, module.krate())) | |
| 124 | }); | |
| 125 | } | |
| 126 | defs.sort_by_key(|(def, _)| match def { | |
| 127 | DefWithBodyId::FunctionId(it) => { | |
| 128 | let loc = it.lookup(&db); | |
| 129 | loc.source(&db).value.syntax().text_range().start() | |
| 130 | } | |
| 131 | DefWithBodyId::ConstId(it) => { | |
| 132 | let loc = it.lookup(&db); | |
| 133 | loc.source(&db).value.syntax().text_range().start() | |
| 134 | } | |
| 135 | DefWithBodyId::StaticId(it) => { | |
| 136 | let loc = it.lookup(&db); | |
| 137 | loc.source(&db).value.syntax().text_range().start() | |
| 138 | } | |
| 139 | DefWithBodyId::VariantId(it) => { | |
| 140 | let loc = it.lookup(&db); | |
| 141 | loc.source(&db).value.syntax().text_range().start() | |
| 116 | let def_map = module.def_map(&db); | |
| 117 | visit_module(&db, def_map, module.local_id, &mut |it| { | |
| 118 | let def = match it { | |
| 119 | ModuleDefId::FunctionId(it) => it.into(), | |
| 120 | ModuleDefId::EnumVariantId(it) => it.into(), | |
| 121 | ModuleDefId::ConstId(it) => it.into(), | |
| 122 | ModuleDefId::StaticId(it) => it.into(), | |
| 123 | _ => return, | |
| 124 | }; | |
| 125 | defs.push((def, module.krate())) | |
| 126 | }); | |
| 142 | 127 | } |
| 143 | }); | |
| 144 | let mut unexpected_type_mismatches = String::new(); | |
| 145 | for (def, krate) in defs { | |
| 146 | let display_target = DisplayTarget::from_crate(&db, krate); | |
| 147 | let (body, body_source_map) = db.body_with_source_map(def); | |
| 148 | let inference_result = db.infer(def); | |
| 149 | ||
| 150 | for (pat, mut ty) in inference_result.type_of_pat.iter() { | |
| 151 | if let Pat::Bind { id, .. } = body[pat] { | |
| 152 | ty = &inference_result.type_of_binding[id]; | |
| 128 | defs.sort_by_key(|(def, _)| match def { | |
| 129 | DefWithBodyId::FunctionId(it) => { | |
| 130 | let loc = it.lookup(&db); | |
| 131 | loc.source(&db).value.syntax().text_range().start() | |
| 153 | 132 | } |
| 154 | let node = match pat_node(&body_source_map, pat, &db) { | |
| 155 | Some(value) => value, | |
| 156 | None => continue, | |
| 157 | }; | |
| 158 | let range = node.as_ref().original_file_range_rooted(&db); | |
| 159 | if let Some(expected) = types.remove(&range) { | |
| 160 | let actual = salsa::attach(&db, || { | |
| 161 | if display_source { | |
| 133 | DefWithBodyId::ConstId(it) => { | |
| 134 | let loc = it.lookup(&db); | |
| 135 | loc.source(&db).value.syntax().text_range().start() | |
| 136 | } | |
| 137 | DefWithBodyId::StaticId(it) => { | |
| 138 | let loc = it.lookup(&db); | |
| 139 | loc.source(&db).value.syntax().text_range().start() | |
| 140 | } | |
| 141 | DefWithBodyId::VariantId(it) => { | |
| 142 | let loc = it.lookup(&db); | |
| 143 | loc.source(&db).value.syntax().text_range().start() | |
| 144 | } | |
| 145 | }); | |
| 146 | let mut unexpected_type_mismatches = String::new(); | |
| 147 | for (def, krate) in defs { | |
| 148 | let display_target = DisplayTarget::from_crate(&db, krate); | |
| 149 | let (body, body_source_map) = db.body_with_source_map(def); | |
| 150 | let inference_result = db.infer(def); | |
| 151 | ||
| 152 | for (pat, mut ty) in inference_result.type_of_pat.iter() { | |
| 153 | if let Pat::Bind { id, .. } = body[pat] { | |
| 154 | ty = &inference_result.type_of_binding[id]; | |
| 155 | } | |
| 156 | let node = match pat_node(&body_source_map, pat, &db) { | |
| 157 | Some(value) => value, | |
| 158 | None => continue, | |
| 159 | }; | |
| 160 | let range = node.as_ref().original_file_range_rooted(&db); | |
| 161 | if let Some(expected) = types.remove(&range) { | |
| 162 | let actual = if display_source { | |
| 162 | 163 | ty.display_source_code(&db, def.module(&db), true).unwrap() |
| 163 | 164 | } else { |
| 164 | 165 | ty.display_test(&db, display_target).to_string() |
| 165 | } | |
| 166 | }); | |
| 167 | assert_eq!(actual, expected, "type annotation differs at {:#?}", range.range); | |
| 166 | }; | |
| 167 | assert_eq!(actual, expected, "type annotation differs at {:#?}", range.range); | |
| 168 | } | |
| 168 | 169 | } |
| 169 | } | |
| 170 | 170 | |
| 171 | for (expr, ty) in inference_result.type_of_expr.iter() { | |
| 172 | let node = match expr_node(&body_source_map, expr, &db) { | |
| 173 | Some(value) => value, | |
| 174 | None => continue, | |
| 175 | }; | |
| 176 | let range = node.as_ref().original_file_range_rooted(&db); | |
| 177 | if let Some(expected) = types.remove(&range) { | |
| 178 | let actual = salsa::attach(&db, || { | |
| 179 | if display_source { | |
| 171 | for (expr, ty) in inference_result.type_of_expr.iter() { | |
| 172 | let node = match expr_node(&body_source_map, expr, &db) { | |
| 173 | Some(value) => value, | |
| 174 | None => continue, | |
| 175 | }; | |
| 176 | let range = node.as_ref().original_file_range_rooted(&db); | |
| 177 | if let Some(expected) = types.remove(&range) { | |
| 178 | let actual = if display_source { | |
| 180 | 179 | ty.display_source_code(&db, def.module(&db), true).unwrap() |
| 181 | 180 | } else { |
| 182 | 181 | ty.display_test(&db, display_target).to_string() |
| 183 | } | |
| 184 | }); | |
| 185 | assert_eq!(actual, expected, "type annotation differs at {:#?}", range.range); | |
| 186 | } | |
| 187 | if let Some(expected) = adjustments.remove(&range) { | |
| 188 | let adjustments = inference_result | |
| 189 | .expr_adjustments | |
| 190 | .get(&expr) | |
| 191 | .map_or_else(Default::default, |it| &**it); | |
| 192 | assert_eq!( | |
| 193 | expected, | |
| 194 | adjustments | |
| 195 | .iter() | |
| 196 | .map(|Adjustment { kind, .. }| format!("{kind:?}")) | |
| 197 | .join(", ") | |
| 198 | ); | |
| 182 | }; | |
| 183 | assert_eq!(actual, expected, "type annotation differs at {:#?}", range.range); | |
| 184 | } | |
| 185 | if let Some(expected) = adjustments.remove(&range) { | |
| 186 | let adjustments = inference_result | |
| 187 | .expr_adjustments | |
| 188 | .get(&expr) | |
| 189 | .map_or_else(Default::default, |it| &**it); | |
| 190 | assert_eq!( | |
| 191 | expected, | |
| 192 | adjustments | |
| 193 | .iter() | |
| 194 | .map(|Adjustment { kind, .. }| format!("{kind:?}")) | |
| 195 | .join(", ") | |
| 196 | ); | |
| 197 | } | |
| 199 | 198 | } |
| 200 | } | |
| 201 | 199 | |
| 202 | for (expr_or_pat, mismatch) in inference_result.type_mismatches() { | |
| 203 | let Some(node) = (match expr_or_pat { | |
| 204 | hir_def::hir::ExprOrPatId::ExprId(expr) => expr_node(&body_source_map, expr, &db), | |
| 205 | hir_def::hir::ExprOrPatId::PatId(pat) => pat_node(&body_source_map, pat, &db), | |
| 206 | }) else { | |
| 207 | continue; | |
| 208 | }; | |
| 209 | let range = node.as_ref().original_file_range_rooted(&db); | |
| 210 | let actual = salsa::attach(&db, || { | |
| 211 | format!( | |
| 200 | for (expr_or_pat, mismatch) in inference_result.type_mismatches() { | |
| 201 | let Some(node) = (match expr_or_pat { | |
| 202 | hir_def::hir::ExprOrPatId::ExprId(expr) => { | |
| 203 | expr_node(&body_source_map, expr, &db) | |
| 204 | } | |
| 205 | hir_def::hir::ExprOrPatId::PatId(pat) => pat_node(&body_source_map, pat, &db), | |
| 206 | }) else { | |
| 207 | continue; | |
| 208 | }; | |
| 209 | let range = node.as_ref().original_file_range_rooted(&db); | |
| 210 | let actual = format!( | |
| 212 | 211 | "expected {}, got {}", |
| 213 | 212 | mismatch.expected.display_test(&db, display_target), |
| 214 | 213 | mismatch.actual.display_test(&db, display_target) |
| 215 | ) | |
| 216 | }); | |
| 217 | match mismatches.remove(&range) { | |
| 218 | Some(annotation) => assert_eq!(actual, annotation), | |
| 219 | None => format_to!(unexpected_type_mismatches, "{:?}: {}\n", range.range, actual), | |
| 214 | ); | |
| 215 | match mismatches.remove(&range) { | |
| 216 | Some(annotation) => assert_eq!(actual, annotation), | |
| 217 | None => { | |
| 218 | format_to!(unexpected_type_mismatches, "{:?}: {}\n", range.range, actual) | |
| 219 | } | |
| 220 | } | |
| 220 | 221 | } |
| 221 | 222 | } |
| 222 | } | |
| 223 | 223 | |
| 224 | let mut buf = String::new(); | |
| 225 | if !unexpected_type_mismatches.is_empty() { | |
| 226 | format_to!(buf, "Unexpected type mismatches:\n{}", unexpected_type_mismatches); | |
| 227 | } | |
| 228 | if !mismatches.is_empty() { | |
| 229 | format_to!(buf, "Unchecked mismatch annotations:\n"); | |
| 230 | for m in mismatches { | |
| 231 | format_to!(buf, "{:?}: {}\n", m.0.range, m.1); | |
| 224 | let mut buf = String::new(); | |
| 225 | if !unexpected_type_mismatches.is_empty() { | |
| 226 | format_to!(buf, "Unexpected type mismatches:\n{}", unexpected_type_mismatches); | |
| 232 | 227 | } |
| 233 | } | |
| 234 | if !types.is_empty() { | |
| 235 | format_to!(buf, "Unchecked type annotations:\n"); | |
| 236 | for t in types { | |
| 237 | format_to!(buf, "{:?}: type {}\n", t.0.range, t.1); | |
| 228 | if !mismatches.is_empty() { | |
| 229 | format_to!(buf, "Unchecked mismatch annotations:\n"); | |
| 230 | for m in mismatches { | |
| 231 | format_to!(buf, "{:?}: {}\n", m.0.range, m.1); | |
| 232 | } | |
| 238 | 233 | } |
| 239 | } | |
| 240 | if !adjustments.is_empty() { | |
| 241 | format_to!(buf, "Unchecked adjustments annotations:\n"); | |
| 242 | for t in adjustments { | |
| 243 | format_to!(buf, "{:?}: type {:?}\n", t.0.range, t.1); | |
| 234 | if !types.is_empty() { | |
| 235 | format_to!(buf, "Unchecked type annotations:\n"); | |
| 236 | for t in types { | |
| 237 | format_to!(buf, "{:?}: type {}\n", t.0.range, t.1); | |
| 238 | } | |
| 244 | 239 | } |
| 245 | } | |
| 246 | assert!(buf.is_empty(), "{}", buf); | |
| 240 | if !adjustments.is_empty() { | |
| 241 | format_to!(buf, "Unchecked adjustments annotations:\n"); | |
| 242 | for t in adjustments { | |
| 243 | format_to!(buf, "{:?}: type {:?}\n", t.0.range, t.1); | |
| 244 | } | |
| 245 | } | |
| 246 | assert!(buf.is_empty(), "{}", buf); | |
| 247 | }); | |
| 247 | 248 | } |
| 248 | 249 | |
| 249 | 250 | fn expr_node( |
| ... | ... | @@ -282,139 +283,140 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { |
| 282 | 283 | let _tracing = setup_tracing(); |
| 283 | 284 | let (db, file_id) = TestDB::with_single_file(content); |
| 284 | 285 | |
| 285 | let mut buf = String::new(); | |
| 286 | ||
| 287 | let mut infer_def = |inference_result: Arc<InferenceResult>, | |
| 288 | body: Arc<Body>, | |
| 289 | body_source_map: Arc<BodySourceMap>, | |
| 290 | krate: Crate| { | |
| 291 | let display_target = DisplayTarget::from_crate(&db, krate); | |
| 292 | let mut types: Vec<(InFile<SyntaxNode>, &Ty)> = Vec::new(); | |
| 293 | let mut mismatches: Vec<(InFile<SyntaxNode>, &TypeMismatch)> = Vec::new(); | |
| 294 | ||
| 295 | if let Some(self_param) = body.self_param { | |
| 296 | let ty = &inference_result.type_of_binding[self_param]; | |
| 297 | if let Some(syntax_ptr) = body_source_map.self_param_syntax() { | |
| 298 | let root = db.parse_or_expand(syntax_ptr.file_id); | |
| 299 | let node = syntax_ptr.map(|ptr| ptr.to_node(&root).syntax().clone()); | |
| 300 | types.push((node, ty)); | |
| 286 | crate::attach_db(&db, || { | |
| 287 | let mut buf = String::new(); | |
| 288 | ||
| 289 | let mut infer_def = |inference_result: Arc<InferenceResult<'_>>, | |
| 290 | body: Arc<Body>, | |
| 291 | body_source_map: Arc<BodySourceMap>, | |
| 292 | krate: Crate| { | |
| 293 | let display_target = DisplayTarget::from_crate(&db, krate); | |
| 294 | let mut types: Vec<(InFile<SyntaxNode>, &Ty<'_>)> = Vec::new(); | |
| 295 | let mut mismatches: Vec<(InFile<SyntaxNode>, &TypeMismatch<'_>)> = Vec::new(); | |
| 296 | ||
| 297 | if let Some(self_param) = body.self_param { | |
| 298 | let ty = &inference_result.type_of_binding[self_param]; | |
| 299 | if let Some(syntax_ptr) = body_source_map.self_param_syntax() { | |
| 300 | let root = db.parse_or_expand(syntax_ptr.file_id); | |
| 301 | let node = syntax_ptr.map(|ptr| ptr.to_node(&root).syntax().clone()); | |
| 302 | types.push((node, ty)); | |
| 303 | } | |
| 301 | 304 | } |
| 302 | } | |
| 303 | 305 | |
| 304 | for (pat, mut ty) in inference_result.type_of_pat.iter() { | |
| 305 | if let Pat::Bind { id, .. } = body[pat] { | |
| 306 | ty = &inference_result.type_of_binding[id]; | |
| 307 | } | |
| 308 | let node = match body_source_map.pat_syntax(pat) { | |
| 309 | Ok(sp) => { | |
| 310 | let root = db.parse_or_expand(sp.file_id); | |
| 311 | sp.map(|ptr| ptr.to_node(&root).syntax().clone()) | |
| 306 | for (pat, mut ty) in inference_result.type_of_pat.iter() { | |
| 307 | if let Pat::Bind { id, .. } = body[pat] { | |
| 308 | ty = &inference_result.type_of_binding[id]; | |
| 309 | } | |
| 310 | let node = match body_source_map.pat_syntax(pat) { | |
| 311 | Ok(sp) => { | |
| 312 | let root = db.parse_or_expand(sp.file_id); | |
| 313 | sp.map(|ptr| ptr.to_node(&root).syntax().clone()) | |
| 314 | } | |
| 315 | Err(SyntheticSyntax) => continue, | |
| 316 | }; | |
| 317 | types.push((node.clone(), ty)); | |
| 318 | if let Some(mismatch) = inference_result.type_mismatch_for_pat(pat) { | |
| 319 | mismatches.push((node, mismatch)); | |
| 312 | 320 | } |
| 313 | Err(SyntheticSyntax) => continue, | |
| 314 | }; | |
| 315 | types.push((node.clone(), ty)); | |
| 316 | if let Some(mismatch) = inference_result.type_mismatch_for_pat(pat) { | |
| 317 | mismatches.push((node, mismatch)); | |
| 318 | 321 | } |
| 319 | } | |
| 320 | 322 | |
| 321 | for (expr, ty) in inference_result.type_of_expr.iter() { | |
| 322 | let node = match body_source_map.expr_syntax(expr) { | |
| 323 | Ok(sp) => { | |
| 324 | let root = db.parse_or_expand(sp.file_id); | |
| 325 | sp.map(|ptr| ptr.to_node(&root).syntax().clone()) | |
| 323 | for (expr, ty) in inference_result.type_of_expr.iter() { | |
| 324 | let node = match body_source_map.expr_syntax(expr) { | |
| 325 | Ok(sp) => { | |
| 326 | let root = db.parse_or_expand(sp.file_id); | |
| 327 | sp.map(|ptr| ptr.to_node(&root).syntax().clone()) | |
| 328 | } | |
| 329 | Err(SyntheticSyntax) => continue, | |
| 330 | }; | |
| 331 | types.push((node.clone(), ty)); | |
| 332 | if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr) { | |
| 333 | mismatches.push((node, mismatch)); | |
| 326 | 334 | } |
| 327 | Err(SyntheticSyntax) => continue, | |
| 328 | }; | |
| 329 | types.push((node.clone(), ty)); | |
| 330 | if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr) { | |
| 331 | mismatches.push((node, mismatch)); | |
| 332 | 335 | } |
| 333 | } | |
| 334 | 336 | |
| 335 | // sort ranges for consistency | |
| 336 | types.sort_by_key(|(node, _)| { | |
| 337 | let range = node.value.text_range(); | |
| 338 | (range.start(), range.end()) | |
| 339 | }); | |
| 340 | for (node, ty) in &types { | |
| 341 | let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.value.clone()) { | |
| 342 | (self_param.name().unwrap().syntax().text_range(), "self".to_owned()) | |
| 343 | } else { | |
| 344 | (node.value.text_range(), node.value.text().to_string().replace('\n', " ")) | |
| 345 | }; | |
| 346 | let macro_prefix = if node.file_id != file_id { "!" } else { "" }; | |
| 347 | format_to!( | |
| 348 | buf, | |
| 349 | "{}{:?} '{}': {}\n", | |
| 350 | macro_prefix, | |
| 351 | range, | |
| 352 | ellipsize(text, 15), | |
| 353 | ty.display_test(&db, display_target) | |
| 354 | ); | |
| 355 | } | |
| 356 | if include_mismatches { | |
| 357 | mismatches.sort_by_key(|(node, _)| { | |
| 337 | // sort ranges for consistency | |
| 338 | types.sort_by_key(|(node, _)| { | |
| 358 | 339 | let range = node.value.text_range(); |
| 359 | 340 | (range.start(), range.end()) |
| 360 | 341 | }); |
| 361 | for (src_ptr, mismatch) in &mismatches { | |
| 362 | let range = src_ptr.value.text_range(); | |
| 363 | let macro_prefix = if src_ptr.file_id != file_id { "!" } else { "" }; | |
| 342 | for (node, ty) in &types { | |
| 343 | let (range, text) = | |
| 344 | if let Some(self_param) = ast::SelfParam::cast(node.value.clone()) { | |
| 345 | (self_param.name().unwrap().syntax().text_range(), "self".to_owned()) | |
| 346 | } else { | |
| 347 | (node.value.text_range(), node.value.text().to_string().replace('\n', " ")) | |
| 348 | }; | |
| 349 | let macro_prefix = if node.file_id != file_id { "!" } else { "" }; | |
| 364 | 350 | format_to!( |
| 365 | 351 | buf, |
| 366 | "{}{:?}: expected {}, got {}\n", | |
| 352 | "{}{:?} '{}': {}\n", | |
| 367 | 353 | macro_prefix, |
| 368 | 354 | range, |
| 369 | mismatch.expected.display_test(&db, display_target), | |
| 370 | mismatch.actual.display_test(&db, display_target), | |
| 355 | ellipsize(text, 15), | |
| 356 | ty.display_test(&db, display_target) | |
| 371 | 357 | ); |
| 372 | 358 | } |
| 373 | } | |
| 374 | }; | |
| 375 | ||
| 376 | let module = db.module_for_file(file_id.file_id(&db)); | |
| 377 | let def_map = module.def_map(&db); | |
| 378 | ||
| 379 | let mut defs: Vec<(DefWithBodyId, Crate)> = Vec::new(); | |
| 380 | visit_module(&db, def_map, module.local_id, &mut |it| { | |
| 381 | let def = match it { | |
| 382 | ModuleDefId::FunctionId(it) => it.into(), | |
| 383 | ModuleDefId::EnumVariantId(it) => it.into(), | |
| 384 | ModuleDefId::ConstId(it) => it.into(), | |
| 385 | ModuleDefId::StaticId(it) => it.into(), | |
| 386 | _ => return, | |
| 359 | if include_mismatches { | |
| 360 | mismatches.sort_by_key(|(node, _)| { | |
| 361 | let range = node.value.text_range(); | |
| 362 | (range.start(), range.end()) | |
| 363 | }); | |
| 364 | for (src_ptr, mismatch) in &mismatches { | |
| 365 | let range = src_ptr.value.text_range(); | |
| 366 | let macro_prefix = if src_ptr.file_id != file_id { "!" } else { "" }; | |
| 367 | format_to!( | |
| 368 | buf, | |
| 369 | "{}{:?}: expected {}, got {}\n", | |
| 370 | macro_prefix, | |
| 371 | range, | |
| 372 | mismatch.expected.display_test(&db, display_target), | |
| 373 | mismatch.actual.display_test(&db, display_target), | |
| 374 | ); | |
| 375 | } | |
| 376 | } | |
| 387 | 377 | }; |
| 388 | defs.push((def, module.krate())) | |
| 389 | }); | |
| 390 | defs.sort_by_key(|(def, _)| match def { | |
| 391 | DefWithBodyId::FunctionId(it) => { | |
| 392 | let loc = it.lookup(&db); | |
| 393 | loc.source(&db).value.syntax().text_range().start() | |
| 394 | } | |
| 395 | DefWithBodyId::ConstId(it) => { | |
| 396 | let loc = it.lookup(&db); | |
| 397 | loc.source(&db).value.syntax().text_range().start() | |
| 398 | } | |
| 399 | DefWithBodyId::StaticId(it) => { | |
| 400 | let loc = it.lookup(&db); | |
| 401 | loc.source(&db).value.syntax().text_range().start() | |
| 402 | } | |
| 403 | DefWithBodyId::VariantId(it) => { | |
| 404 | let loc = it.lookup(&db); | |
| 405 | loc.source(&db).value.syntax().text_range().start() | |
| 406 | } | |
| 407 | }); | |
| 408 | for (def, krate) in defs { | |
| 409 | let (body, source_map) = db.body_with_source_map(def); | |
| 410 | let infer = db.infer(def); | |
| 411 | salsa::attach(&db, || { | |
| 378 | ||
| 379 | let module = db.module_for_file(file_id.file_id(&db)); | |
| 380 | let def_map = module.def_map(&db); | |
| 381 | ||
| 382 | let mut defs: Vec<(DefWithBodyId, Crate)> = Vec::new(); | |
| 383 | visit_module(&db, def_map, module.local_id, &mut |it| { | |
| 384 | let def = match it { | |
| 385 | ModuleDefId::FunctionId(it) => it.into(), | |
| 386 | ModuleDefId::EnumVariantId(it) => it.into(), | |
| 387 | ModuleDefId::ConstId(it) => it.into(), | |
| 388 | ModuleDefId::StaticId(it) => it.into(), | |
| 389 | _ => return, | |
| 390 | }; | |
| 391 | defs.push((def, module.krate())) | |
| 392 | }); | |
| 393 | defs.sort_by_key(|(def, _)| match def { | |
| 394 | DefWithBodyId::FunctionId(it) => { | |
| 395 | let loc = it.lookup(&db); | |
| 396 | loc.source(&db).value.syntax().text_range().start() | |
| 397 | } | |
| 398 | DefWithBodyId::ConstId(it) => { | |
| 399 | let loc = it.lookup(&db); | |
| 400 | loc.source(&db).value.syntax().text_range().start() | |
| 401 | } | |
| 402 | DefWithBodyId::StaticId(it) => { | |
| 403 | let loc = it.lookup(&db); | |
| 404 | loc.source(&db).value.syntax().text_range().start() | |
| 405 | } | |
| 406 | DefWithBodyId::VariantId(it) => { | |
| 407 | let loc = it.lookup(&db); | |
| 408 | loc.source(&db).value.syntax().text_range().start() | |
| 409 | } | |
| 410 | }); | |
| 411 | for (def, krate) in defs { | |
| 412 | let (body, source_map) = db.body_with_source_map(def); | |
| 413 | let infer = db.infer(def); | |
| 412 | 414 | infer_def(infer, body, source_map, krate); |
| 413 | }) | |
| 414 | } | |
| 415 | } | |
| 415 | 416 | |
| 416 | buf.truncate(buf.trim_end().len()); | |
| 417 | buf | |
| 417 | buf.truncate(buf.trim_end().len()); | |
| 418 | buf | |
| 419 | }) | |
| 418 | 420 | } |
| 419 | 421 | |
| 420 | 422 | pub(crate) fn visit_module( |
| ... | ... | @@ -556,15 +558,17 @@ fn salsa_bug() { |
| 556 | 558 | ", |
| 557 | 559 | ); |
| 558 | 560 | |
| 559 | let module = db.module_for_file(pos.file_id.file_id(&db)); | |
| 560 | let crate_def_map = module.def_map(&db); | |
| 561 | visit_module(&db, crate_def_map, module.local_id, &mut |def| { | |
| 562 | db.infer(match def { | |
| 563 | ModuleDefId::FunctionId(it) => it.into(), | |
| 564 | ModuleDefId::EnumVariantId(it) => it.into(), | |
| 565 | ModuleDefId::ConstId(it) => it.into(), | |
| 566 | ModuleDefId::StaticId(it) => it.into(), | |
| 567 | _ => return, | |
| 561 | crate::attach_db(&db, || { | |
| 562 | let module = db.module_for_file(pos.file_id.file_id(&db)); | |
| 563 | let crate_def_map = module.def_map(&db); | |
| 564 | visit_module(&db, crate_def_map, module.local_id, &mut |def| { | |
| 565 | db.infer(match def { | |
| 566 | ModuleDefId::FunctionId(it) => it.into(), | |
| 567 | ModuleDefId::EnumVariantId(it) => it.into(), | |
| 568 | ModuleDefId::ConstId(it) => it.into(), | |
| 569 | ModuleDefId::StaticId(it) => it.into(), | |
| 570 | _ => return, | |
| 571 | }); | |
| 568 | 572 | }); |
| 569 | 573 | }); |
| 570 | 574 | |
| ... | ... | @@ -595,15 +599,17 @@ fn salsa_bug() { |
| 595 | 599 | |
| 596 | 600 | db.set_file_text(pos.file_id.file_id(&db), new_text); |
| 597 | 601 | |
| 598 | let module = db.module_for_file(pos.file_id.file_id(&db)); | |
| 599 | let crate_def_map = module.def_map(&db); | |
| 600 | visit_module(&db, crate_def_map, module.local_id, &mut |def| { | |
| 601 | db.infer(match def { | |
| 602 | ModuleDefId::FunctionId(it) => it.into(), | |
| 603 | ModuleDefId::EnumVariantId(it) => it.into(), | |
| 604 | ModuleDefId::ConstId(it) => it.into(), | |
| 605 | ModuleDefId::StaticId(it) => it.into(), | |
| 606 | _ => return, | |
| 602 | crate::attach_db(&db, || { | |
| 603 | let module = db.module_for_file(pos.file_id.file_id(&db)); | |
| 604 | let crate_def_map = module.def_map(&db); | |
| 605 | visit_module(&db, crate_def_map, module.local_id, &mut |def| { | |
| 606 | db.infer(match def { | |
| 607 | ModuleDefId::FunctionId(it) => it.into(), | |
| 608 | ModuleDefId::EnumVariantId(it) => it.into(), | |
| 609 | ModuleDefId::ConstId(it) => it.into(), | |
| 610 | ModuleDefId::StaticId(it) => it.into(), | |
| 611 | _ => return, | |
| 612 | }); | |
| 607 | 613 | }); |
| 608 | }); | |
| 614 | }) | |
| 609 | 615 | } |
src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs+101-90| ... | ... | @@ -2,111 +2,121 @@ use expect_test::{Expect, expect}; |
| 2 | 2 | use hir_def::db::DefDatabase; |
| 3 | 3 | use hir_expand::{HirFileId, files::InFileWrapper}; |
| 4 | 4 | use itertools::Itertools; |
| 5 | use salsa::plumbing::FromId; | |
| 6 | 5 | use span::TextRange; |
| 7 | 6 | use syntax::{AstNode, AstPtr}; |
| 8 | 7 | use test_fixture::WithFixture; |
| 9 | 8 | |
| 10 | use crate::db::{HirDatabase, InternedClosureId}; | |
| 11 | use crate::display::{DisplayTarget, HirDisplay}; | |
| 12 | use crate::mir::MirSpan; | |
| 13 | use crate::test_db::TestDB; | |
| 9 | use crate::{ | |
| 10 | db::HirDatabase, | |
| 11 | display::{DisplayTarget, HirDisplay}, | |
| 12 | mir::MirSpan, | |
| 13 | test_db::TestDB, | |
| 14 | }; | |
| 14 | 15 | |
| 15 | 16 | use super::{setup_tracing, visit_module}; |
| 16 | 17 | |
| 17 | 18 | fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { |
| 18 | 19 | let _tracing = setup_tracing(); |
| 19 | 20 | let (db, file_id) = TestDB::with_single_file(ra_fixture); |
| 20 | let module = db.module_for_file(file_id.file_id(&db)); | |
| 21 | let def_map = module.def_map(&db); | |
| 21 | crate::attach_db(&db, || { | |
| 22 | let module = db.module_for_file(file_id.file_id(&db)); | |
| 23 | let def_map = module.def_map(&db); | |
| 22 | 24 | |
| 23 | let mut defs = Vec::new(); | |
| 24 | visit_module(&db, def_map, module.local_id, &mut |it| defs.push(it)); | |
| 25 | let mut defs = Vec::new(); | |
| 26 | visit_module(&db, def_map, module.local_id, &mut |it| defs.push(it)); | |
| 25 | 27 | |
| 26 | let mut captures_info = Vec::new(); | |
| 27 | for def in defs { | |
| 28 | let def = match def { | |
| 29 | hir_def::ModuleDefId::FunctionId(it) => it.into(), | |
| 30 | hir_def::ModuleDefId::EnumVariantId(it) => it.into(), | |
| 31 | hir_def::ModuleDefId::ConstId(it) => it.into(), | |
| 32 | hir_def::ModuleDefId::StaticId(it) => it.into(), | |
| 33 | _ => continue, | |
| 34 | }; | |
| 35 | let infer = db.infer(def); | |
| 36 | let db = &db; | |
| 37 | captures_info.extend(infer.closure_info.iter().flat_map(|(closure_id, (captures, _))| { | |
| 38 | let closure = db.lookup_intern_closure(InternedClosureId::from_id(closure_id.0)); | |
| 39 | let source_map = db.body_with_source_map(closure.0).1; | |
| 40 | let closure_text_range = source_map | |
| 41 | .expr_syntax(closure.1) | |
| 42 | .expect("failed to map closure to SyntaxNode") | |
| 43 | .value | |
| 44 | .text_range(); | |
| 45 | captures.iter().map(move |capture| { | |
| 46 | fn text_range<N: AstNode>( | |
| 47 | db: &TestDB, | |
| 48 | syntax: InFileWrapper<HirFileId, AstPtr<N>>, | |
| 49 | ) -> TextRange { | |
| 50 | let root = syntax.file_syntax(db); | |
| 51 | syntax.value.to_node(&root).syntax().text_range() | |
| 52 | } | |
| 53 | ||
| 54 | // FIXME: Deduplicate this with hir::Local::sources(). | |
| 55 | let (body, source_map) = db.body_with_source_map(closure.0); | |
| 56 | let local_text_range = match body.self_param.zip(source_map.self_param_syntax()) { | |
| 57 | Some((param, source)) if param == capture.local() => { | |
| 58 | format!("{:?}", text_range(db, source)) | |
| 59 | } | |
| 60 | _ => source_map | |
| 61 | .patterns_for_binding(capture.local()) | |
| 62 | .iter() | |
| 63 | .map(|&definition| { | |
| 64 | text_range(db, source_map.pat_syntax(definition).unwrap()) | |
| 65 | }) | |
| 66 | .map(|it| format!("{it:?}")) | |
| 67 | .join(", "), | |
| 68 | }; | |
| 69 | let place = capture.display_place(closure.0, db); | |
| 70 | let capture_ty = salsa::attach(db, || { | |
| 71 | capture | |
| 72 | .ty | |
| 73 | .skip_binders() | |
| 74 | .display_test(db, DisplayTarget::from_crate(db, module.krate())) | |
| 75 | .to_string() | |
| 76 | }); | |
| 77 | let spans = capture | |
| 78 | .spans() | |
| 79 | .iter() | |
| 80 | .flat_map(|span| match *span { | |
| 81 | MirSpan::ExprId(expr) => { | |
| 82 | vec![text_range(db, source_map.expr_syntax(expr).unwrap())] | |
| 83 | } | |
| 84 | MirSpan::PatId(pat) => { | |
| 85 | vec![text_range(db, source_map.pat_syntax(pat).unwrap())] | |
| 28 | let mut captures_info = Vec::new(); | |
| 29 | for def in defs { | |
| 30 | let def = match def { | |
| 31 | hir_def::ModuleDefId::FunctionId(it) => it.into(), | |
| 32 | hir_def::ModuleDefId::EnumVariantId(it) => it.into(), | |
| 33 | hir_def::ModuleDefId::ConstId(it) => it.into(), | |
| 34 | hir_def::ModuleDefId::StaticId(it) => it.into(), | |
| 35 | _ => continue, | |
| 36 | }; | |
| 37 | let infer = db.infer(def); | |
| 38 | let db = &db; | |
| 39 | captures_info.extend(infer.closure_info.iter().flat_map( | |
| 40 | |(closure_id, (captures, _))| { | |
| 41 | let closure = db.lookup_intern_closure(*closure_id); | |
| 42 | let source_map = db.body_with_source_map(closure.0).1; | |
| 43 | let closure_text_range = source_map | |
| 44 | .expr_syntax(closure.1) | |
| 45 | .expect("failed to map closure to SyntaxNode") | |
| 46 | .value | |
| 47 | .text_range(); | |
| 48 | captures.iter().map(move |capture| { | |
| 49 | fn text_range<N: AstNode>( | |
| 50 | db: &TestDB, | |
| 51 | syntax: InFileWrapper<HirFileId, AstPtr<N>>, | |
| 52 | ) -> TextRange { | |
| 53 | let root = syntax.file_syntax(db); | |
| 54 | syntax.value.to_node(&root).syntax().text_range() | |
| 86 | 55 | } |
| 87 | MirSpan::BindingId(binding) => source_map | |
| 88 | .patterns_for_binding(binding) | |
| 56 | ||
| 57 | // FIXME: Deduplicate this with hir::Local::sources(). | |
| 58 | let (body, source_map) = db.body_with_source_map(closure.0); | |
| 59 | let local_text_range = | |
| 60 | match body.self_param.zip(source_map.self_param_syntax()) { | |
| 61 | Some((param, source)) if param == capture.local() => { | |
| 62 | format!("{:?}", text_range(db, source)) | |
| 63 | } | |
| 64 | _ => source_map | |
| 65 | .patterns_for_binding(capture.local()) | |
| 66 | .iter() | |
| 67 | .map(|&definition| { | |
| 68 | text_range(db, source_map.pat_syntax(definition).unwrap()) | |
| 69 | }) | |
| 70 | .map(|it| format!("{it:?}")) | |
| 71 | .join(", "), | |
| 72 | }; | |
| 73 | let place = capture.display_place(closure.0, db); | |
| 74 | let capture_ty = capture | |
| 75 | .ty | |
| 76 | .skip_binder() | |
| 77 | .display_test(db, DisplayTarget::from_crate(db, module.krate())) | |
| 78 | .to_string(); | |
| 79 | let spans = capture | |
| 80 | .spans() | |
| 89 | 81 | .iter() |
| 90 | .map(|pat| text_range(db, source_map.pat_syntax(*pat).unwrap())) | |
| 91 | .collect(), | |
| 92 | MirSpan::SelfParam => { | |
| 93 | vec![text_range(db, source_map.self_param_syntax().unwrap())] | |
| 94 | } | |
| 95 | MirSpan::Unknown => Vec::new(), | |
| 96 | }) | |
| 97 | .sorted_by_key(|it| it.start()) | |
| 98 | .map(|it| format!("{it:?}")) | |
| 99 | .join(","); | |
| 82 | .flat_map(|span| match *span { | |
| 83 | MirSpan::ExprId(expr) => { | |
| 84 | vec![text_range(db, source_map.expr_syntax(expr).unwrap())] | |
| 85 | } | |
| 86 | MirSpan::PatId(pat) => { | |
| 87 | vec![text_range(db, source_map.pat_syntax(pat).unwrap())] | |
| 88 | } | |
| 89 | MirSpan::BindingId(binding) => source_map | |
| 90 | .patterns_for_binding(binding) | |
| 91 | .iter() | |
| 92 | .map(|pat| text_range(db, source_map.pat_syntax(*pat).unwrap())) | |
| 93 | .collect(), | |
| 94 | MirSpan::SelfParam => { | |
| 95 | vec![text_range(db, source_map.self_param_syntax().unwrap())] | |
| 96 | } | |
| 97 | MirSpan::Unknown => Vec::new(), | |
| 98 | }) | |
| 99 | .sorted_by_key(|it| it.start()) | |
| 100 | .map(|it| format!("{it:?}")) | |
| 101 | .join(","); | |
| 100 | 102 | |
| 101 | (closure_text_range, local_text_range, spans, place, capture_ty, capture.kind()) | |
| 102 | }) | |
| 103 | })); | |
| 104 | } | |
| 105 | captures_info.sort_unstable_by_key(|(closure_text_range, local_text_range, ..)| { | |
| 106 | (closure_text_range.start(), local_text_range.clone()) | |
| 107 | }); | |
| 103 | ( | |
| 104 | closure_text_range, | |
| 105 | local_text_range, | |
| 106 | spans, | |
| 107 | place, | |
| 108 | capture_ty, | |
| 109 | capture.kind(), | |
| 110 | ) | |
| 111 | }) | |
| 112 | }, | |
| 113 | )); | |
| 114 | } | |
| 115 | captures_info.sort_unstable_by_key(|(closure_text_range, local_text_range, ..)| { | |
| 116 | (closure_text_range.start(), local_text_range.clone()) | |
| 117 | }); | |
| 108 | 118 | |
| 109 | let rendered = captures_info | |
| 119 | let rendered = captures_info | |
| 110 | 120 | .iter() |
| 111 | 121 | .map(|(closure_text_range, local_text_range, spans, place, capture_ty, capture_kind)| { |
| 112 | 122 | format!( |
| ... | ... | @@ -115,7 +125,8 @@ fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expec |
| 115 | 125 | }) |
| 116 | 126 | .join("\n"); |
| 117 | 127 | |
| 118 | expect.assert_eq(&rendered); | |
| 128 | expect.assert_eq(&rendered); | |
| 129 | }) | |
| 119 | 130 | } |
| 120 | 131 | |
| 121 | 132 | #[test] |
src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs+8-8| ... | ... | @@ -49,7 +49,7 @@ fn let_stmt_coerce() { |
| 49 | 49 | //- minicore: coerce_unsized |
| 50 | 50 | fn test() { |
| 51 | 51 | let x: &[isize] = &[1]; |
| 52 | // ^^^^ adjustments: Deref(None), Borrow(Ref('?1, Not)), Pointer(Unsize) | |
| 52 | // ^^^^ adjustments: Deref(None), Borrow(Ref('?2, Not)), Pointer(Unsize) | |
| 53 | 53 | let x: *const [isize] = &[1]; |
| 54 | 54 | // ^^^^ adjustments: Deref(None), Borrow(RawPtr(Not)), Pointer(Unsize) |
| 55 | 55 | } |
| ... | ... | @@ -268,7 +268,7 @@ fn takes_ref_str(x: &str) {} |
| 268 | 268 | fn returns_string() -> String { loop {} } |
| 269 | 269 | fn test() { |
| 270 | 270 | takes_ref_str(&{ returns_string() }); |
| 271 | // ^^^^^^^^^^^^^^^^^^^^^ adjustments: Deref(None), Deref(Some(OverloadedDeref(Some(Not)))), Borrow(Ref('{error}, Not)) | |
| 271 | // ^^^^^^^^^^^^^^^^^^^^^ adjustments: Deref(None), Deref(Some(OverloadedDeref(Some(Not)))), Borrow(Ref('{region error}, Not)) | |
| 272 | 272 | } |
| 273 | 273 | "#, |
| 274 | 274 | ); |
| ... | ... | @@ -567,7 +567,7 @@ trait Foo {} |
| 567 | 567 | fn test(f: impl Foo, g: &(impl Foo + ?Sized)) { |
| 568 | 568 | let _: &dyn Foo = &f; |
| 569 | 569 | let _: &dyn Foo = g; |
| 570 | //^ expected &'? (dyn Foo + '?), got &'? impl Foo + ?Sized | |
| 570 | //^ expected &'? (dyn Foo + 'static), got &'? impl Foo + ?Sized | |
| 571 | 571 | } |
| 572 | 572 | "#, |
| 573 | 573 | ); |
| ... | ... | @@ -833,11 +833,11 @@ struct V<T> { t: T } |
| 833 | 833 | fn main() { |
| 834 | 834 | let a: V<&dyn Tr>; |
| 835 | 835 | (a,) = V { t: &S }; |
| 836 | //^^^^expected V<&'? S>, got (V<&'? (dyn Tr + '?)>,) | |
| 836 | //^^^^expected V<&'? S>, got (V<&'? (dyn Tr + 'static)>,) | |
| 837 | 837 | |
| 838 | 838 | let mut a: V<&dyn Tr> = V { t: &S }; |
| 839 | 839 | (a,) = V { t: &S }; |
| 840 | //^^^^expected V<&'? S>, got (V<&'? (dyn Tr + '?)>,) | |
| 840 | //^^^^expected V<&'? S>, got (V<&'? (dyn Tr + 'static)>,) | |
| 841 | 841 | } |
| 842 | 842 | "#, |
| 843 | 843 | ); |
| ... | ... | @@ -854,8 +854,8 @@ impl core::cmp::PartialEq for Struct { |
| 854 | 854 | } |
| 855 | 855 | fn test() { |
| 856 | 856 | Struct == Struct; |
| 857 | // ^^^^^^ adjustments: Borrow(Ref('{error}, Not)) | |
| 858 | // ^^^^^^ adjustments: Borrow(Ref('{error}, Not)) | |
| 857 | // ^^^^^^ adjustments: Borrow(Ref('{region error}, Not)) | |
| 858 | // ^^^^^^ adjustments: Borrow(Ref('{region error}, Not)) | |
| 859 | 859 | }", |
| 860 | 860 | ); |
| 861 | 861 | } |
| ... | ... | @@ -871,7 +871,7 @@ impl core::ops::AddAssign for Struct { |
| 871 | 871 | } |
| 872 | 872 | fn test() { |
| 873 | 873 | Struct += Struct; |
| 874 | // ^^^^^^ adjustments: Borrow(Ref('{error}, Mut)) | |
| 874 | // ^^^^^^ adjustments: Borrow(Ref('{region error}, Mut)) | |
| 875 | 875 | // ^^^^^^ adjustments: |
| 876 | 876 | }", |
| 877 | 877 | ); |
src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs+4-4| ... | ... | @@ -67,11 +67,11 @@ trait B: A {} |
| 67 | 67 | |
| 68 | 68 | fn test<'a>( |
| 69 | 69 | _: &(dyn A<Assoc = ()> + Send), |
| 70 | //^ &(dyn A<Assoc = ()> + Send) | |
| 70 | //^ &(dyn A<Assoc = ()> + Send + 'static) | |
| 71 | 71 | _: &'a (dyn Send + A<Assoc = ()>), |
| 72 | //^ &'a (dyn A<Assoc = ()> + Send) | |
| 72 | //^ &'a (dyn A<Assoc = ()> + Send + 'static) | |
| 73 | 73 | _: &dyn B<Assoc = ()>, |
| 74 | //^ &(dyn B<Assoc = ()>) | |
| 74 | //^ &(dyn B<Assoc = ()> + 'static) | |
| 75 | 75 | ) {} |
| 76 | 76 | "#, |
| 77 | 77 | ); |
| ... | ... | @@ -85,7 +85,7 @@ fn render_dyn_for_ty() { |
| 85 | 85 | trait Foo<'a> {} |
| 86 | 86 | |
| 87 | 87 | fn foo(foo: &dyn for<'a> Foo<'a>) {} |
| 88 | // ^^^ &dyn Foo<'?> | |
| 88 | // ^^^ &(dyn Foo<'?> + 'static) | |
| 89 | 89 | "#, |
| 90 | 90 | ); |
| 91 | 91 | } |
src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs+12-11| ... | ... | @@ -44,7 +44,7 @@ fn foo() -> i32 { |
| 44 | 44 | "body_shim", |
| 45 | 45 | "body_with_source_map_shim", |
| 46 | 46 | "trait_environment_shim", |
| 47 | "return_type_impl_traits_shim", | |
| 47 | "return_type_impl_traits_ns_shim", | |
| 48 | 48 | "expr_scopes_shim", |
| 49 | 49 | "lang_item", |
| 50 | 50 | "crate_lang_items", |
| ... | ... | @@ -131,7 +131,7 @@ fn baz() -> i32 { |
| 131 | 131 | "body_shim", |
| 132 | 132 | "body_with_source_map_shim", |
| 133 | 133 | "trait_environment_shim", |
| 134 | "return_type_impl_traits_shim", | |
| 134 | "return_type_impl_traits_ns_shim", | |
| 135 | 135 | "expr_scopes_shim", |
| 136 | 136 | "lang_item", |
| 137 | 137 | "crate_lang_items", |
| ... | ... | @@ -143,7 +143,7 @@ fn baz() -> i32 { |
| 143 | 143 | "body_shim", |
| 144 | 144 | "body_with_source_map_shim", |
| 145 | 145 | "trait_environment_shim", |
| 146 | "return_type_impl_traits_shim", | |
| 146 | "return_type_impl_traits_ns_shim", | |
| 147 | 147 | "expr_scopes_shim", |
| 148 | 148 | "infer_shim", |
| 149 | 149 | "function_signature_shim", |
| ... | ... | @@ -151,7 +151,7 @@ fn baz() -> i32 { |
| 151 | 151 | "body_shim", |
| 152 | 152 | "body_with_source_map_shim", |
| 153 | 153 | "trait_environment_shim", |
| 154 | "return_type_impl_traits_shim", | |
| 154 | "return_type_impl_traits_ns_shim", | |
| 155 | 155 | "expr_scopes_shim", |
| 156 | 156 | ] |
| 157 | 157 | "#]], |
| ... | ... | @@ -586,7 +586,7 @@ fn main() { |
| 586 | 586 | "attrs_shim", |
| 587 | 587 | "attrs_shim", |
| 588 | 588 | "generic_predicates_ns_shim", |
| 589 | "return_type_impl_traits_shim", | |
| 589 | "return_type_impl_traits_ns_shim", | |
| 590 | 590 | "infer_shim", |
| 591 | 591 | "function_signature_shim", |
| 592 | 592 | "function_signature_with_source_map_shim", |
| ... | ... | @@ -594,7 +594,7 @@ fn main() { |
| 594 | 594 | "expr_scopes_shim", |
| 595 | 595 | "struct_signature_shim", |
| 596 | 596 | "struct_signature_with_source_map_shim", |
| 597 | "generic_predicates_shim", | |
| 597 | "generic_predicates_ns_shim", | |
| 598 | 598 | "value_ty_shim", |
| 599 | 599 | "VariantFields::firewall_", |
| 600 | 600 | "VariantFields::query_", |
| ... | ... | @@ -610,7 +610,7 @@ fn main() { |
| 610 | 610 | "impl_self_ty_with_diagnostics_shim", |
| 611 | 611 | "generic_predicates_ns_shim", |
| 612 | 612 | "value_ty_shim", |
| 613 | "generic_predicates_shim", | |
| 613 | "generic_predicates_ns_shim", | |
| 614 | 614 | ] |
| 615 | 615 | "#]], |
| 616 | 616 | ); |
| ... | ... | @@ -683,11 +683,12 @@ fn main() { |
| 683 | 683 | "attrs_shim", |
| 684 | 684 | "attrs_shim", |
| 685 | 685 | "generic_predicates_ns_shim", |
| 686 | "return_type_impl_traits_shim", | |
| 686 | "return_type_impl_traits_ns_shim", | |
| 687 | 687 | "infer_shim", |
| 688 | 688 | "function_signature_with_source_map_shim", |
| 689 | 689 | "expr_scopes_shim", |
| 690 | 690 | "struct_signature_with_source_map_shim", |
| 691 | "generic_predicates_ns_shim", | |
| 691 | 692 | "VariantFields::query_", |
| 692 | 693 | "inherent_impls_in_crate_shim", |
| 693 | 694 | "impl_signature_with_source_map_shim", |
| ... | ... | @@ -697,7 +698,7 @@ fn main() { |
| 697 | 698 | "impl_trait_with_diagnostics_shim", |
| 698 | 699 | "impl_self_ty_with_diagnostics_shim", |
| 699 | 700 | "generic_predicates_ns_shim", |
| 700 | "generic_predicates_shim", | |
| 701 | "generic_predicates_ns_shim", | |
| 701 | 702 | ] |
| 702 | 703 | "#]], |
| 703 | 704 | ); |
| ... | ... | @@ -709,8 +710,8 @@ fn execute_assert_events( |
| 709 | 710 | required: &[(&str, usize)], |
| 710 | 711 | expect: Expect, |
| 711 | 712 | ) { |
| 712 | let (executed, events) = db.log_executed(f); | |
| 713 | salsa::attach(db, || { | |
| 713 | crate::attach_db(db, || { | |
| 714 | let (executed, events) = db.log_executed(f); | |
| 714 | 715 | for (event, count) in required { |
| 715 | 716 | let n = executed.iter().filter(|it| it.contains(event)).count(); |
| 716 | 717 | assert_eq!( |
src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs+4-4| ... | ... | @@ -199,8 +199,8 @@ fn expr_macro_def_expanded_in_various_places() { |
| 199 | 199 | 100..119 'for _ ...!() {}': fn into_iter<isize>(isize) -> <isize as IntoIterator>::IntoIter |
| 200 | 200 | 100..119 'for _ ...!() {}': <isize as IntoIterator>::IntoIter |
| 201 | 201 | 100..119 'for _ ...!() {}': ! |
| 202 | 100..119 'for _ ...!() {}': <isize as IntoIterator>::IntoIter | |
| 203 | 100..119 'for _ ...!() {}': &'? mut <isize as IntoIterator>::IntoIter | |
| 202 | 100..119 'for _ ...!() {}': {unknown} | |
| 203 | 100..119 'for _ ...!() {}': &'? mut {unknown} | |
| 204 | 204 | 100..119 'for _ ...!() {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> |
| 205 | 205 | 100..119 'for _ ...!() {}': Option<<{unknown} as Iterator>::Item> |
| 206 | 206 | 100..119 'for _ ...!() {}': () |
| ... | ... | @@ -293,8 +293,8 @@ fn expr_macro_rules_expanded_in_various_places() { |
| 293 | 293 | 114..133 'for _ ...!() {}': fn into_iter<isize>(isize) -> <isize as IntoIterator>::IntoIter |
| 294 | 294 | 114..133 'for _ ...!() {}': <isize as IntoIterator>::IntoIter |
| 295 | 295 | 114..133 'for _ ...!() {}': ! |
| 296 | 114..133 'for _ ...!() {}': <isize as IntoIterator>::IntoIter | |
| 297 | 114..133 'for _ ...!() {}': &'? mut <isize as IntoIterator>::IntoIter | |
| 296 | 114..133 'for _ ...!() {}': {unknown} | |
| 297 | 114..133 'for _ ...!() {}': &'? mut {unknown} | |
| 298 | 298 | 114..133 'for _ ...!() {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> |
| 299 | 299 | 114..133 'for _ ...!() {}': Option<<{unknown} as Iterator>::Item> |
| 300 | 300 | 114..133 'for _ ...!() {}': () |
src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs+3-3| ... | ... | @@ -1157,9 +1157,9 @@ fn dyn_trait_super_trait_not_in_scope() { |
| 1157 | 1157 | 51..55 'self': &'? Self |
| 1158 | 1158 | 64..69 '{ 0 }': u32 |
| 1159 | 1159 | 66..67 '0': u32 |
| 1160 | 176..177 'd': &'? (dyn Trait + '?) | |
| 1160 | 176..177 'd': &'? (dyn Trait + 'static) | |
| 1161 | 1161 | 191..207 '{ ...o(); }': () |
| 1162 | 197..198 'd': &'? (dyn Trait + '?) | |
| 1162 | 197..198 'd': &'? (dyn Trait + 'static) | |
| 1163 | 1163 | 197..204 'd.foo()': u32 |
| 1164 | 1164 | "#]], |
| 1165 | 1165 | ); |
| ... | ... | @@ -2050,7 +2050,7 @@ impl dyn Error + Send { |
| 2050 | 2050 | /// Attempts to downcast the box to a concrete type. |
| 2051 | 2051 | pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error + Send>> { |
| 2052 | 2052 | let err: Box<dyn Error> = self; |
| 2053 | // ^^^^ expected Box<dyn Error + '?>, got Box<dyn Error + Send + 'static> | |
| 2053 | // ^^^^ expected Box<dyn Error + 'static>, got Box<dyn Error + Send + 'static> | |
| 2054 | 2054 | // FIXME, type mismatch should not occur |
| 2055 | 2055 | <dyn Error>::downcast(err).map_err(|_| loop {}) |
| 2056 | 2056 | //^^^^^^^^^^^^^^^^^^^^^ type: fn downcast<{unknown}>(Box<dyn Error + 'static>) -> Result<Box<{unknown}>, Box<dyn Error + 'static>> |
src/tools/rust-analyzer/crates/hir-ty/src/tests/opaque_types.rs+1| ... | ... | @@ -31,6 +31,7 @@ fn test() { |
| 31 | 31 | } |
| 32 | 32 | |
| 33 | 33 | #[test] |
| 34 | #[ignore = "FIXME(next-solver): This currently generates a type mismatch, need to switch opaque type handling to the solver"] | |
| 34 | 35 | fn associated_type_impl_traits_complex() { |
| 35 | 36 | check_types( |
| 36 | 37 | r#" |
src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs+4-4| ... | ... | @@ -1257,8 +1257,8 @@ fn test() { |
| 1257 | 1257 | 16..66 'for _ ... }': fn into_iter<()>(()) -> <() as IntoIterator>::IntoIter |
| 1258 | 1258 | 16..66 'for _ ... }': <() as IntoIterator>::IntoIter |
| 1259 | 1259 | 16..66 'for _ ... }': ! |
| 1260 | 16..66 'for _ ... }': <() as IntoIterator>::IntoIter | |
| 1261 | 16..66 'for _ ... }': &'? mut <() as IntoIterator>::IntoIter | |
| 1260 | 16..66 'for _ ... }': {unknown} | |
| 1261 | 16..66 'for _ ... }': &'? mut {unknown} | |
| 1262 | 1262 | 16..66 'for _ ... }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> |
| 1263 | 1263 | 16..66 'for _ ... }': Option<<{unknown} as Iterator>::Item> |
| 1264 | 1264 | 16..66 'for _ ... }': () |
| ... | ... | @@ -2363,8 +2363,8 @@ fn test() { |
| 2363 | 2363 | 108..125 '{ ... }': usize |
| 2364 | 2364 | 118..119 'N': usize |
| 2365 | 2365 | 139..157 '{ ...= N; }': () |
| 2366 | 149..150 '_': Foo<_> | |
| 2367 | 153..154 'N': Foo<_> | |
| 2366 | 149..150 '_': Foo<N> | |
| 2367 | 153..154 'N': Foo<N> | |
| 2368 | 2368 | "#]], |
| 2369 | 2369 | ); |
| 2370 | 2370 | } |
src/tools/rust-analyzer/crates/hir-ty/src/tests/regression/new_solver.rs+1-1| ... | ... | @@ -84,7 +84,7 @@ fn test() -> i32 { |
| 84 | 84 | 307..359 'core::...n Foo)': DynMetadata<dyn Foo + '?> |
| 85 | 85 | 327..328 '0': usize |
| 86 | 86 | 327..340 '0 as *const F': *const F |
| 87 | 327..358 '0 as *...yn Foo': *const (dyn Foo + '?) | |
| 87 | 327..358 '0 as *...yn Foo': *const (dyn Foo + 'static) | |
| 88 | 88 | 370..371 'f': F |
| 89 | 89 | 374..378 'F {}': F |
| 90 | 90 | 388..395 'fat_ptr': *const (dyn Foo + '?) |
src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs+1-34| ... | ... | @@ -2743,7 +2743,7 @@ impl B for Astruct {} |
| 2743 | 2743 | 725..754 '#[rust...1i32])': Box<[i32; 1], Global> |
| 2744 | 2744 | 747..753 '[1i32]': [i32; 1] |
| 2745 | 2745 | 748..752 '1i32': i32 |
| 2746 | 765..766 'v': Vec<Box<dyn B + '?, Global>, Global> | |
| 2746 | 765..766 'v': Vec<Box<dyn B + 'static, Global>, Global> | |
| 2747 | 2747 | 786..803 '<[_]> ...to_vec': fn into_vec<Box<dyn B + '?, Global>, Global>(Box<[Box<dyn B + '?, Global>], Global>) -> Vec<Box<dyn B + '?, Global>, Global> |
| 2748 | 2748 | 786..860 '<[_]> ...ct)]))': Vec<Box<dyn B + '?, Global>, Global> |
| 2749 | 2749 | 804..859 '#[rust...uct)])': Box<[Box<dyn B + '?, Global>; 1], Global> |
| ... | ... | @@ -3692,39 +3692,6 @@ fn main() { |
| 3692 | 3692 | ); |
| 3693 | 3693 | } |
| 3694 | 3694 | |
| 3695 | #[test] | |
| 3696 | fn infer_bad_lang_item() { | |
| 3697 | check_infer( | |
| 3698 | r#" | |
| 3699 | #[lang="eq"] | |
| 3700 | pub trait Eq { | |
| 3701 | fn eq(&self, ) -> bool; | |
| 3702 | ||
| 3703 | } | |
| 3704 | ||
| 3705 | #[lang="shr"] | |
| 3706 | pub trait Shr<RHS,Result> { | |
| 3707 | fn shr(&self, rhs: &RHS) -> Result; | |
| 3708 | } | |
| 3709 | ||
| 3710 | fn test() -> bool { | |
| 3711 | 1 >> 1; | |
| 3712 | 1 == 1; | |
| 3713 | } | |
| 3714 | "#, | |
| 3715 | expect![[r#" | |
| 3716 | 39..43 'self': &'? Self | |
| 3717 | 114..118 'self': &'? Self | |
| 3718 | 120..123 'rhs': &'? RHS | |
| 3719 | 163..190 '{ ...= 1; }': bool | |
| 3720 | 169..170 '1': i32 | |
| 3721 | 169..175 '1 >> 1': {unknown} | |
| 3722 | 181..182 '1': i32 | |
| 3723 | 181..187 '1 == 1': {unknown} | |
| 3724 | "#]], | |
| 3725 | ); | |
| 3726 | } | |
| 3727 | ||
| 3728 | 3695 | #[test] |
| 3729 | 3696 | fn macro_semitransparent_hygiene() { |
| 3730 | 3697 | check_types( |
src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs+27-27| ... | ... | @@ -1480,24 +1480,24 @@ fn test(x: Box<dyn Trait<u64>>, y: &dyn Trait<u64>) { |
| 1480 | 1480 | expect![[r#" |
| 1481 | 1481 | 29..33 'self': &'? Self |
| 1482 | 1482 | 54..58 'self': &'? Self |
| 1483 | 206..208 '{}': Box<dyn Trait<u64> + '?> | |
| 1484 | 218..219 'x': Box<dyn Trait<u64> + '?> | |
| 1485 | 242..243 'y': &'? (dyn Trait<u64> + '?) | |
| 1483 | 206..208 '{}': Box<dyn Trait<u64> + 'static> | |
| 1484 | 218..219 'x': Box<dyn Trait<u64> + 'static> | |
| 1485 | 242..243 'y': &'? (dyn Trait<u64> + 'static) | |
| 1486 | 1486 | 262..379 '{ ...2(); }': () |
| 1487 | 268..269 'x': Box<dyn Trait<u64> + '?> | |
| 1488 | 275..276 'y': &'? (dyn Trait<u64> + '?) | |
| 1487 | 268..269 'x': Box<dyn Trait<u64> + 'static> | |
| 1488 | 275..276 'y': &'? (dyn Trait<u64> + 'static) | |
| 1489 | 1489 | 286..287 'z': Box<dyn Trait<u64> + '?> |
| 1490 | 1490 | 290..293 'bar': fn bar() -> Box<dyn Trait<u64> + 'static> |
| 1491 | 1491 | 290..295 'bar()': Box<dyn Trait<u64> + 'static> |
| 1492 | 301..302 'x': Box<dyn Trait<u64> + '?> | |
| 1492 | 301..302 'x': Box<dyn Trait<u64> + 'static> | |
| 1493 | 1493 | 301..308 'x.foo()': u64 |
| 1494 | 314..315 'y': &'? (dyn Trait<u64> + '?) | |
| 1494 | 314..315 'y': &'? (dyn Trait<u64> + 'static) | |
| 1495 | 1495 | 314..321 'y.foo()': u64 |
| 1496 | 1496 | 327..328 'z': Box<dyn Trait<u64> + '?> |
| 1497 | 1497 | 327..334 'z.foo()': u64 |
| 1498 | 340..341 'x': Box<dyn Trait<u64> + '?> | |
| 1498 | 340..341 'x': Box<dyn Trait<u64> + 'static> | |
| 1499 | 1499 | 340..348 'x.foo2()': i64 |
| 1500 | 354..355 'y': &'? (dyn Trait<u64> + '?) | |
| 1500 | 354..355 'y': &'? (dyn Trait<u64> + 'static) | |
| 1501 | 1501 | 354..362 'y.foo2()': i64 |
| 1502 | 1502 | 368..369 'z': Box<dyn Trait<u64> + '?> |
| 1503 | 1503 | 368..376 'z.foo2()': i64 |
| ... | ... | @@ -1528,7 +1528,7 @@ fn test(s: S<u32, i32>) { |
| 1528 | 1528 | expect![[r#" |
| 1529 | 1529 | 32..36 'self': &'? Self |
| 1530 | 1530 | 102..106 'self': &'? S<T, U> |
| 1531 | 128..139 '{ loop {} }': &'? (dyn Trait<T, U> + '?) | |
| 1531 | 128..139 '{ loop {} }': &'? (dyn Trait<T, U> + 'static) | |
| 1532 | 1532 | 130..137 'loop {}': ! |
| 1533 | 1533 | 135..137 '{}': () |
| 1534 | 1534 | 175..179 'self': &'? Self |
| ... | ... | @@ -1561,18 +1561,18 @@ fn test(x: Trait, y: &Trait) -> u64 { |
| 1561 | 1561 | }"#, |
| 1562 | 1562 | expect![[r#" |
| 1563 | 1563 | 26..30 'self': &'? Self |
| 1564 | 60..62 '{}': dyn Trait + '? | |
| 1565 | 72..73 'x': dyn Trait + '? | |
| 1566 | 82..83 'y': &'? (dyn Trait + '?) | |
| 1564 | 60..62 '{}': dyn Trait + 'static | |
| 1565 | 72..73 'x': dyn Trait + 'static | |
| 1566 | 82..83 'y': &'? (dyn Trait + 'static) | |
| 1567 | 1567 | 100..175 '{ ...o(); }': u64 |
| 1568 | 106..107 'x': dyn Trait + '? | |
| 1569 | 113..114 'y': &'? (dyn Trait + '?) | |
| 1568 | 106..107 'x': dyn Trait + 'static | |
| 1569 | 113..114 'y': &'? (dyn Trait + 'static) | |
| 1570 | 1570 | 124..125 'z': dyn Trait + '? |
| 1571 | 1571 | 128..131 'bar': fn bar() -> dyn Trait + 'static |
| 1572 | 1572 | 128..133 'bar()': dyn Trait + 'static |
| 1573 | 139..140 'x': dyn Trait + '? | |
| 1573 | 139..140 'x': dyn Trait + 'static | |
| 1574 | 1574 | 139..146 'x.foo()': u64 |
| 1575 | 152..153 'y': &'? (dyn Trait + '?) | |
| 1575 | 152..153 'y': &'? (dyn Trait + 'static) | |
| 1576 | 1576 | 152..159 'y.foo()': u64 |
| 1577 | 1577 | 165..166 'z': dyn Trait + '? |
| 1578 | 1578 | 165..172 'z.foo()': u64 |
| ... | ... | @@ -1594,7 +1594,7 @@ fn main() { |
| 1594 | 1594 | expect![[r#" |
| 1595 | 1595 | 31..35 'self': &'? S |
| 1596 | 1596 | 37..39 '{}': () |
| 1597 | 47..48 '_': &'? (dyn Fn(S) + '?) | |
| 1597 | 47..48 '_': &'? (dyn Fn(S) + 'static) | |
| 1598 | 1598 | 58..60 '{}': () |
| 1599 | 1599 | 71..105 '{ ...()); }': () |
| 1600 | 1600 | 77..78 'f': fn f(&'? (dyn Fn(S) + 'static)) |
| ... | ... | @@ -2948,13 +2948,13 @@ fn test(x: &dyn Foo) { |
| 2948 | 2948 | foo(x); |
| 2949 | 2949 | }"#, |
| 2950 | 2950 | expect![[r#" |
| 2951 | 21..22 'x': &'? (dyn Foo + '?) | |
| 2951 | 21..22 'x': &'? (dyn Foo + 'static) | |
| 2952 | 2952 | 34..36 '{}': () |
| 2953 | 46..47 'x': &'? (dyn Foo + '?) | |
| 2953 | 46..47 'x': &'? (dyn Foo + 'static) | |
| 2954 | 2954 | 59..74 '{ foo(x); }': () |
| 2955 | 2955 | 65..68 'foo': fn foo(&'? (dyn Foo + 'static)) |
| 2956 | 2956 | 65..71 'foo(x)': () |
| 2957 | 69..70 'x': &'? (dyn Foo + '?) | |
| 2957 | 69..70 'x': &'? (dyn Foo + 'static) | |
| 2958 | 2958 | "#]], |
| 2959 | 2959 | ); |
| 2960 | 2960 | } |
| ... | ... | @@ -3230,13 +3230,13 @@ fn foo() { |
| 3230 | 3230 | 218..324 '{ ...&s); }': () |
| 3231 | 3231 | 228..229 's': Option<i32> |
| 3232 | 3232 | 232..236 'None': Option<i32> |
| 3233 | 246..247 'f': Box<dyn FnOnce(&'? Option<i32>) + '?> | |
| 3234 | 281..310 'Box { ... {}) }': Box<dyn FnOnce(&'? Option<i32>) + '?> | |
| 3233 | 246..247 'f': Box<dyn FnOnce(&'? Option<i32>) + 'static> | |
| 3234 | 281..310 'Box { ... {}) }': Box<dyn FnOnce(&'? Option<i32>) + 'static> | |
| 3235 | 3235 | 294..308 '&mut (|ps| {})': &'? mut impl FnOnce(&'? Option<i32>) |
| 3236 | 3236 | 300..307 '|ps| {}': impl FnOnce(&'? Option<i32>) |
| 3237 | 3237 | 301..303 'ps': &'? Option<i32> |
| 3238 | 3238 | 305..307 '{}': () |
| 3239 | 316..317 'f': Box<dyn FnOnce(&'? Option<i32>) + '?> | |
| 3239 | 316..317 'f': Box<dyn FnOnce(&'? Option<i32>) + 'static> | |
| 3240 | 3240 | 316..321 'f(&s)': () |
| 3241 | 3241 | 318..320 '&s': &'? Option<i32> |
| 3242 | 3242 | 319..320 's': Option<i32> |
| ... | ... | @@ -4272,10 +4272,10 @@ fn f<'a>(v: &dyn Trait<Assoc<i32> = &'a i32>) { |
| 4272 | 4272 | "#, |
| 4273 | 4273 | expect![[r#" |
| 4274 | 4274 | 90..94 'self': &'? Self |
| 4275 | 127..128 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + '?) | |
| 4275 | 127..128 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + 'static) | |
| 4276 | 4276 | 164..195 '{ ...f(); }': () |
| 4277 | 170..171 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + '?) | |
| 4278 | 170..184 'v.get::<i32>()': <dyn Trait<Assoc<i32> = &'a i32> + '? as Trait>::Assoc<i32> | |
| 4277 | 170..171 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + 'static) | |
| 4278 | 170..184 'v.get::<i32>()': <dyn Trait<Assoc<i32> = &'a i32> + 'static as Trait>::Assoc<i32> | |
| 4279 | 4279 | 170..192 'v.get:...eref()': {unknown} |
| 4280 | 4280 | "#]], |
| 4281 | 4281 | ); |
src/tools/rust-analyzer/crates/hir-ty/src/traits.rs+87-10| ... | ... | @@ -12,7 +12,7 @@ use intern::sym; |
| 12 | 12 | use rustc_next_trait_solver::solve::{HasChanged, SolverDelegateEvalExt}; |
| 13 | 13 | use rustc_type_ir::{ |
| 14 | 14 | InferCtxtLike, TypingMode, |
| 15 | inherent::{SliceLike, Span as _}, | |
| 15 | inherent::{IntoKind, SliceLike, Span as _, Ty as _}, | |
| 16 | 16 | solve::Certainty, |
| 17 | 17 | }; |
| 18 | 18 | use span::Edition; |
| ... | ... | @@ -23,11 +23,12 @@ use crate::{ |
| 23 | 23 | AliasEq, AliasTy, Canonical, DomainGoal, Goal, InEnvironment, Interner, ProjectionTy, |
| 24 | 24 | ProjectionTyExt, TraitRefExt, Ty, TyKind, TypeFlags, WhereClause, |
| 25 | 25 | db::HirDatabase, |
| 26 | infer::unify::InferenceTable, | |
| 26 | from_assoc_type_id, | |
| 27 | 27 | next_solver::{ |
| 28 | 28 | DbInterner, GenericArg, ParamEnv, Predicate, SolverContext, Span, |
| 29 | infer::{DbInternerInferExt, InferCtxt}, | |
| 30 | mapping::{ChalkToNextSolver, convert_canonical_args_for_result}, | |
| 29 | infer::{DbInternerInferExt, InferCtxt, traits::ObligationCause}, | |
| 30 | mapping::{ChalkToNextSolver, NextSolverToChalk, convert_canonical_args_for_result}, | |
| 31 | obligation_ctxt::ObligationCtxt, | |
| 31 | 32 | util::mini_canonicalize, |
| 32 | 33 | }, |
| 33 | 34 | utils::UnevaluatedConstEvaluatorFolder, |
| ... | ... | @@ -43,7 +44,7 @@ pub struct TraitEnvironment<'db> { |
| 43 | 44 | pub krate: Crate, |
| 44 | 45 | pub block: Option<BlockId>, |
| 45 | 46 | // FIXME make this a BTreeMap |
| 46 | traits_from_clauses: Box<[(Ty, TraitId)]>, | |
| 47 | traits_from_clauses: Box<[(crate::next_solver::Ty<'db>, TraitId)]>, | |
| 47 | 48 | pub env: ParamEnv<'db>, |
| 48 | 49 | } |
| 49 | 50 | |
| ... | ... | @@ -60,7 +61,7 @@ impl<'db> TraitEnvironment<'db> { |
| 60 | 61 | pub fn new( |
| 61 | 62 | krate: Crate, |
| 62 | 63 | block: Option<BlockId>, |
| 63 | traits_from_clauses: Box<[(Ty, TraitId)]>, | |
| 64 | traits_from_clauses: Box<[(crate::next_solver::Ty<'db>, TraitId)]>, | |
| 64 | 65 | env: ParamEnv<'db>, |
| 65 | 66 | ) -> Arc<Self> { |
| 66 | 67 | Arc::new(TraitEnvironment { krate, block, traits_from_clauses, env }) |
| ... | ... | @@ -71,13 +72,28 @@ impl<'db> TraitEnvironment<'db> { |
| 71 | 72 | Arc::make_mut(this).block = Some(block); |
| 72 | 73 | } |
| 73 | 74 | |
| 74 | pub fn traits_in_scope_from_clauses(&self, ty: Ty) -> impl Iterator<Item = TraitId> + '_ { | |
| 75 | pub fn traits_in_scope_from_clauses( | |
| 76 | &self, | |
| 77 | ty: crate::next_solver::Ty<'db>, | |
| 78 | ) -> impl Iterator<Item = TraitId> + '_ { | |
| 75 | 79 | self.traits_from_clauses |
| 76 | 80 | .iter() |
| 77 | 81 | .filter_map(move |(self_ty, trait_id)| (*self_ty == ty).then_some(*trait_id)) |
| 78 | 82 | } |
| 79 | 83 | } |
| 80 | 84 | |
| 85 | /// This should be used in `hir` only. | |
| 86 | pub fn structurally_normalize_ty<'db>( | |
| 87 | infcx: &InferCtxt<'db>, | |
| 88 | ty: crate::next_solver::Ty<'db>, | |
| 89 | env: Arc<TraitEnvironment<'db>>, | |
| 90 | ) -> crate::next_solver::Ty<'db> { | |
| 91 | let crate::next_solver::TyKind::Alias(..) = ty.kind() else { return ty }; | |
| 92 | let mut ocx = ObligationCtxt::new(infcx); | |
| 93 | let ty = ocx.structurally_normalize_ty(&ObligationCause::dummy(), env.env, ty).unwrap_or(ty); | |
| 94 | ty.replace_infer_with_error(infcx.interner) | |
| 95 | } | |
| 96 | ||
| 81 | 97 | pub(crate) fn normalize_projection_query<'db>( |
| 82 | 98 | db: &'db dyn HirDatabase, |
| 83 | 99 | projection: ProjectionTy, |
| ... | ... | @@ -93,9 +109,30 @@ pub(crate) fn normalize_projection_query<'db>( |
| 93 | 109 | return TyKind::Error.intern(Interner); |
| 94 | 110 | } |
| 95 | 111 | |
| 96 | let mut table = InferenceTable::new(db, env); | |
| 97 | let ty = table.normalize_projection_ty(projection); | |
| 98 | table.resolve_completely(ty) | |
| 112 | let interner = DbInterner::new_with(db, Some(env.krate), env.block); | |
| 113 | // FIXME(next-solver): I believe this should use `PostAnalysis` (this is only used for IDE things), | |
| 114 | // but this causes some bug because of our incorrect impl of `type_of_opaque_hir_typeck()` for TAIT | |
| 115 | // and async blocks. | |
| 116 | let infcx = interner.infer_ctxt().build(TypingMode::Analysis { | |
| 117 | defining_opaque_types_and_generators: crate::next_solver::SolverDefIds::new_from_iter( | |
| 118 | interner, | |
| 119 | [], | |
| 120 | ), | |
| 121 | }); | |
| 122 | let alias_ty = crate::next_solver::Ty::new_alias( | |
| 123 | interner, | |
| 124 | rustc_type_ir::AliasTyKind::Projection, | |
| 125 | crate::next_solver::AliasTy::new( | |
| 126 | interner, | |
| 127 | from_assoc_type_id(projection.associated_ty_id).into(), | |
| 128 | <crate::Substitution as ChalkToNextSolver<crate::next_solver::GenericArgs<'_>>>::to_nextsolver(&projection.substitution, interner), | |
| 129 | ), | |
| 130 | ); | |
| 131 | let mut ctxt = crate::next_solver::obligation_ctxt::ObligationCtxt::new(&infcx); | |
| 132 | let normalized = ctxt | |
| 133 | .structurally_normalize_ty(&ObligationCause::dummy(), env.env, alias_ty) | |
| 134 | .unwrap_or(alias_ty); | |
| 135 | normalized.replace_infer_with_error(interner).to_chalk(interner) | |
| 99 | 136 | } |
| 100 | 137 | |
| 101 | 138 | fn identity_subst( |
| ... | ... | @@ -419,3 +456,43 @@ impl FnTrait { |
| 419 | 456 | self.lang_item().resolve_trait(db, krate) |
| 420 | 457 | } |
| 421 | 458 | } |
| 459 | ||
| 460 | /// This should not be used in `hir-ty`, only in `hir`. | |
| 461 | pub fn implements_trait_unique<'db>( | |
| 462 | ty: crate::next_solver::Ty<'db>, | |
| 463 | db: &'db dyn HirDatabase, | |
| 464 | env: Arc<TraitEnvironment<'db>>, | |
| 465 | trait_: TraitId, | |
| 466 | ) -> bool { | |
| 467 | implements_trait_unique_impl(db, env, trait_, &mut |infcx| { | |
| 468 | infcx.fill_rest_fresh_args(trait_.into(), [ty.into()]) | |
| 469 | }) | |
| 470 | } | |
| 471 | ||
| 472 | /// This should not be used in `hir-ty`, only in `hir`. | |
| 473 | pub fn implements_trait_unique_with_args<'db>( | |
| 474 | db: &'db dyn HirDatabase, | |
| 475 | env: Arc<TraitEnvironment<'db>>, | |
| 476 | trait_: TraitId, | |
| 477 | args: crate::next_solver::GenericArgs<'db>, | |
| 478 | ) -> bool { | |
| 479 | implements_trait_unique_impl(db, env, trait_, &mut |_| args) | |
| 480 | } | |
| 481 | ||
| 482 | fn implements_trait_unique_impl<'db>( | |
| 483 | db: &'db dyn HirDatabase, | |
| 484 | env: Arc<TraitEnvironment<'db>>, | |
| 485 | trait_: TraitId, | |
| 486 | create_args: &mut dyn FnMut(&InferCtxt<'db>) -> crate::next_solver::GenericArgs<'db>, | |
| 487 | ) -> bool { | |
| 488 | let interner = DbInterner::new_with(db, Some(env.krate), env.block); | |
| 489 | // FIXME(next-solver): I believe this should be `PostAnalysis`. | |
| 490 | let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); | |
| 491 | ||
| 492 | let args = create_args(&infcx); | |
| 493 | let trait_ref = rustc_type_ir::TraitRef::new_from_args(interner, trait_.into(), args); | |
| 494 | let goal = crate::next_solver::Goal::new(interner, env.env, trait_ref); | |
| 495 | ||
| 496 | let result = crate::traits::next_trait_solve_in_ctxt(&infcx, goal); | |
| 497 | matches!(result, Ok((_, Certainty::Yes))) | |
| 498 | } |
src/tools/rust-analyzer/crates/hir-ty/src/utils.rs+7-15| ... | ... | @@ -20,11 +20,10 @@ use hir_expand::name::Name; |
| 20 | 20 | use intern::sym; |
| 21 | 21 | use rustc_abi::TargetDataLayout; |
| 22 | 22 | use rustc_hash::FxHashSet; |
| 23 | use rustc_type_ir::inherent::{GenericArgs, IntoKind, SliceLike}; | |
| 23 | use rustc_type_ir::inherent::{IntoKind, SliceLike}; | |
| 24 | 24 | use smallvec::{SmallVec, smallvec}; |
| 25 | 25 | use span::Edition; |
| 26 | 26 | |
| 27 | use crate::next_solver::mapping::NextSolverToChalk; | |
| 28 | 27 | use crate::{ |
| 29 | 28 | ChalkTraitId, Const, ConstScalar, Interner, Substitution, TargetFeatures, TraitRef, |
| 30 | 29 | TraitRefExt, Ty, |
| ... | ... | @@ -34,7 +33,7 @@ use crate::{ |
| 34 | 33 | mir::pad16, |
| 35 | 34 | next_solver::{ |
| 36 | 35 | DbInterner, |
| 37 | mapping::{ChalkToNextSolver, convert_args_for_result}, | |
| 36 | mapping::{ChalkToNextSolver, NextSolverToChalk, convert_args_for_result}, | |
| 38 | 37 | }, |
| 39 | 38 | to_chalk_trait_id, |
| 40 | 39 | }; |
| ... | ... | @@ -196,15 +195,6 @@ pub(super) fn associated_type_by_name_including_super_traits( |
| 196 | 195 | pub(crate) struct ClosureSubst<'a>(pub(crate) &'a Substitution); |
| 197 | 196 | |
| 198 | 197 | impl<'a> ClosureSubst<'a> { |
| 199 | pub(crate) fn parent_subst(&self, db: &dyn HirDatabase) -> Substitution { | |
| 200 | let interner = DbInterner::new_with(db, None, None); | |
| 201 | let subst = | |
| 202 | <Substitution as ChalkToNextSolver<crate::next_solver::GenericArgs<'_>>>::to_nextsolver( | |
| 203 | self.0, interner, | |
| 204 | ); | |
| 205 | subst.split_closure_args().parent_args.to_chalk(interner) | |
| 206 | } | |
| 207 | ||
| 208 | 198 | pub(crate) fn sig_ty(&self, db: &dyn HirDatabase) -> Ty { |
| 209 | 199 | let interner = DbInterner::new_with(db, None, None); |
| 210 | 200 | let subst = |
| ... | ... | @@ -310,10 +300,12 @@ impl FallibleTypeFolder<Interner> for UnevaluatedConstEvaluatorFolder<'_> { |
| 310 | 300 | if let chalk_ir::ConstValue::Concrete(c) = &constant.data(Interner).value |
| 311 | 301 | && let ConstScalar::UnevaluatedConst(id, subst) = &c.interned |
| 312 | 302 | { |
| 313 | if let Ok(eval) = self.db.const_eval(*id, subst.clone(), None) { | |
| 314 | return Ok(eval); | |
| 303 | let interner = DbInterner::conjure(); | |
| 304 | if let Ok(eval) = self.db.const_eval(*id, subst.to_nextsolver(interner), None) { | |
| 305 | return Ok(eval.to_chalk(interner)); | |
| 315 | 306 | } else { |
| 316 | return Ok(unknown_const(constant.data(Interner).ty.clone())); | |
| 307 | return Ok(unknown_const(constant.data(Interner).ty.to_nextsolver(interner)) | |
| 308 | .to_chalk(interner)); | |
| 317 | 309 | } |
| 318 | 310 | } |
| 319 | 311 | Ok(constant) |
src/tools/rust-analyzer/crates/hir-ty/src/variance.rs+80-78| ... | ... | @@ -1001,84 +1001,86 @@ struct FixedPoint<T, U, V>(&'static FixedPoint<(), T, U>, V); |
| 1001 | 1001 | // )); |
| 1002 | 1002 | let (db, file_id) = TestDB::with_single_file(ra_fixture); |
| 1003 | 1003 | |
| 1004 | let mut defs: Vec<GenericDefId> = Vec::new(); | |
| 1005 | let module = db.module_for_file_opt(file_id.file_id(&db)).unwrap(); | |
| 1006 | let def_map = module.def_map(&db); | |
| 1007 | crate::tests::visit_module(&db, def_map, module.local_id, &mut |it| { | |
| 1008 | defs.push(match it { | |
| 1009 | ModuleDefId::FunctionId(it) => it.into(), | |
| 1010 | ModuleDefId::AdtId(it) => it.into(), | |
| 1011 | ModuleDefId::ConstId(it) => it.into(), | |
| 1012 | ModuleDefId::TraitId(it) => it.into(), | |
| 1013 | ModuleDefId::TypeAliasId(it) => it.into(), | |
| 1014 | _ => return, | |
| 1015 | }) | |
| 1016 | }); | |
| 1017 | let defs = defs | |
| 1018 | .into_iter() | |
| 1019 | .filter_map(|def| { | |
| 1020 | Some(( | |
| 1021 | def, | |
| 1022 | match def { | |
| 1023 | GenericDefId::FunctionId(it) => { | |
| 1024 | let loc = it.lookup(&db); | |
| 1025 | loc.source(&db).value.name().unwrap() | |
| 1026 | } | |
| 1027 | GenericDefId::AdtId(AdtId::EnumId(it)) => { | |
| 1028 | let loc = it.lookup(&db); | |
| 1029 | loc.source(&db).value.name().unwrap() | |
| 1030 | } | |
| 1031 | GenericDefId::AdtId(AdtId::StructId(it)) => { | |
| 1032 | let loc = it.lookup(&db); | |
| 1033 | loc.source(&db).value.name().unwrap() | |
| 1034 | } | |
| 1035 | GenericDefId::AdtId(AdtId::UnionId(it)) => { | |
| 1036 | let loc = it.lookup(&db); | |
| 1037 | loc.source(&db).value.name().unwrap() | |
| 1038 | } | |
| 1039 | GenericDefId::TraitId(it) => { | |
| 1040 | let loc = it.lookup(&db); | |
| 1041 | loc.source(&db).value.name().unwrap() | |
| 1042 | } | |
| 1043 | GenericDefId::TypeAliasId(it) => { | |
| 1044 | let loc = it.lookup(&db); | |
| 1045 | loc.source(&db).value.name().unwrap() | |
| 1046 | } | |
| 1047 | GenericDefId::ImplId(_) => return None, | |
| 1048 | GenericDefId::ConstId(_) => return None, | |
| 1049 | GenericDefId::StaticId(_) => return None, | |
| 1050 | }, | |
| 1051 | )) | |
| 1052 | }) | |
| 1053 | .sorted_by_key(|(_, n)| n.syntax().text_range().start()); | |
| 1054 | let mut res = String::new(); | |
| 1055 | for (def, name) in defs { | |
| 1056 | let Some(variances) = db.variances_of(def) else { | |
| 1057 | continue; | |
| 1058 | }; | |
| 1059 | format_to!( | |
| 1060 | res, | |
| 1061 | "{name}[{}]\n", | |
| 1062 | generics(&db, def) | |
| 1063 | .iter() | |
| 1064 | .map(|(_, param)| match param { | |
| 1065 | GenericParamDataRef::TypeParamData(type_param_data) => { | |
| 1066 | type_param_data.name.as_ref().unwrap() | |
| 1067 | } | |
| 1068 | GenericParamDataRef::ConstParamData(const_param_data) => | |
| 1069 | &const_param_data.name, | |
| 1070 | GenericParamDataRef::LifetimeParamData(lifetime_param_data) => { | |
| 1071 | &lifetime_param_data.name | |
| 1072 | } | |
| 1073 | }) | |
| 1074 | .zip_eq(&*variances) | |
| 1075 | .format_with(", ", |(name, var), f| f(&format_args!( | |
| 1076 | "{}: {var}", | |
| 1077 | name.as_str() | |
| 1078 | ))) | |
| 1079 | ); | |
| 1080 | } | |
| 1004 | crate::attach_db(&db, || { | |
| 1005 | let mut defs: Vec<GenericDefId> = Vec::new(); | |
| 1006 | let module = db.module_for_file_opt(file_id.file_id(&db)).unwrap(); | |
| 1007 | let def_map = module.def_map(&db); | |
| 1008 | crate::tests::visit_module(&db, def_map, module.local_id, &mut |it| { | |
| 1009 | defs.push(match it { | |
| 1010 | ModuleDefId::FunctionId(it) => it.into(), | |
| 1011 | ModuleDefId::AdtId(it) => it.into(), | |
| 1012 | ModuleDefId::ConstId(it) => it.into(), | |
| 1013 | ModuleDefId::TraitId(it) => it.into(), | |
| 1014 | ModuleDefId::TypeAliasId(it) => it.into(), | |
| 1015 | _ => return, | |
| 1016 | }) | |
| 1017 | }); | |
| 1018 | let defs = defs | |
| 1019 | .into_iter() | |
| 1020 | .filter_map(|def| { | |
| 1021 | Some(( | |
| 1022 | def, | |
| 1023 | match def { | |
| 1024 | GenericDefId::FunctionId(it) => { | |
| 1025 | let loc = it.lookup(&db); | |
| 1026 | loc.source(&db).value.name().unwrap() | |
| 1027 | } | |
| 1028 | GenericDefId::AdtId(AdtId::EnumId(it)) => { | |
| 1029 | let loc = it.lookup(&db); | |
| 1030 | loc.source(&db).value.name().unwrap() | |
| 1031 | } | |
| 1032 | GenericDefId::AdtId(AdtId::StructId(it)) => { | |
| 1033 | let loc = it.lookup(&db); | |
| 1034 | loc.source(&db).value.name().unwrap() | |
| 1035 | } | |
| 1036 | GenericDefId::AdtId(AdtId::UnionId(it)) => { | |
| 1037 | let loc = it.lookup(&db); | |
| 1038 | loc.source(&db).value.name().unwrap() | |
| 1039 | } | |
| 1040 | GenericDefId::TraitId(it) => { | |
| 1041 | let loc = it.lookup(&db); | |
| 1042 | loc.source(&db).value.name().unwrap() | |
| 1043 | } | |
| 1044 | GenericDefId::TypeAliasId(it) => { | |
| 1045 | let loc = it.lookup(&db); | |
| 1046 | loc.source(&db).value.name().unwrap() | |
| 1047 | } | |
| 1048 | GenericDefId::ImplId(_) => return None, | |
| 1049 | GenericDefId::ConstId(_) => return None, | |
| 1050 | GenericDefId::StaticId(_) => return None, | |
| 1051 | }, | |
| 1052 | )) | |
| 1053 | }) | |
| 1054 | .sorted_by_key(|(_, n)| n.syntax().text_range().start()); | |
| 1055 | let mut res = String::new(); | |
| 1056 | for (def, name) in defs { | |
| 1057 | let Some(variances) = db.variances_of(def) else { | |
| 1058 | continue; | |
| 1059 | }; | |
| 1060 | format_to!( | |
| 1061 | res, | |
| 1062 | "{name}[{}]\n", | |
| 1063 | generics(&db, def) | |
| 1064 | .iter() | |
| 1065 | .map(|(_, param)| match param { | |
| 1066 | GenericParamDataRef::TypeParamData(type_param_data) => { | |
| 1067 | type_param_data.name.as_ref().unwrap() | |
| 1068 | } | |
| 1069 | GenericParamDataRef::ConstParamData(const_param_data) => | |
| 1070 | &const_param_data.name, | |
| 1071 | GenericParamDataRef::LifetimeParamData(lifetime_param_data) => { | |
| 1072 | &lifetime_param_data.name | |
| 1073 | } | |
| 1074 | }) | |
| 1075 | .zip_eq(&*variances) | |
| 1076 | .format_with(", ", |(name, var), f| f(&format_args!( | |
| 1077 | "{}: {var}", | |
| 1078 | name.as_str() | |
| 1079 | ))) | |
| 1080 | ); | |
| 1081 | } | |
| 1081 | 1082 | |
| 1082 | expected.assert_eq(&res); | |
| 1083 | expected.assert_eq(&res); | |
| 1084 | }) | |
| 1083 | 1085 | } |
| 1084 | 1086 | } |
src/tools/rust-analyzer/crates/hir/src/attrs.rs+3-11| ... | ... | @@ -14,11 +14,7 @@ use hir_expand::{ |
| 14 | 14 | mod_path::{ModPath, PathKind}, |
| 15 | 15 | name::Name, |
| 16 | 16 | }; |
| 17 | use hir_ty::{ | |
| 18 | db::HirDatabase, | |
| 19 | method_resolution, | |
| 20 | next_solver::{DbInterner, mapping::ChalkToNextSolver}, | |
| 21 | }; | |
| 17 | use hir_ty::{db::HirDatabase, method_resolution}; | |
| 22 | 18 | |
| 23 | 19 | use crate::{ |
| 24 | 20 | Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, DocLinkDef, Enum, ExternCrateDecl, |
| ... | ... | @@ -261,7 +257,7 @@ fn resolve_impl_trait_item<'db>( |
| 261 | 257 | name: &Name, |
| 262 | 258 | ns: Option<Namespace>, |
| 263 | 259 | ) -> Option<DocLinkDef> { |
| 264 | let canonical = ty.canonical(); | |
| 260 | let canonical = ty.canonical(db); | |
| 265 | 261 | let krate = ty.krate(db); |
| 266 | 262 | let environment = resolver |
| 267 | 263 | .generic_def() |
| ... | ... | @@ -275,11 +271,7 @@ fn resolve_impl_trait_item<'db>( |
| 275 | 271 | // |
| 276 | 272 | // FIXME: resolve type aliases (which are not yielded by iterate_path_candidates) |
| 277 | 273 | _ = method_resolution::iterate_path_candidates( |
| 278 | &canonical.to_nextsolver(DbInterner::new_with( | |
| 279 | db, | |
| 280 | Some(environment.krate), | |
| 281 | environment.block, | |
| 282 | )), | |
| 274 | &canonical, | |
| 283 | 275 | db, |
| 284 | 276 | environment, |
| 285 | 277 | &traits_in_scope, |
src/tools/rust-analyzer/crates/hir/src/diagnostics.rs+9-12| ... | ... | @@ -620,7 +620,7 @@ impl<'db> AnyDiagnostic<'db> { |
| 620 | 620 | pub(crate) fn inference_diagnostic( |
| 621 | 621 | db: &'db dyn HirDatabase, |
| 622 | 622 | def: DefWithBodyId, |
| 623 | d: &InferenceDiagnostic, | |
| 623 | d: &InferenceDiagnostic<'db>, | |
| 624 | 624 | source_map: &hir_def::expr_store::BodySourceMap, |
| 625 | 625 | sig_map: &hir_def::expr_store::ExpressionStoreSourceMap, |
| 626 | 626 | ) -> Option<AnyDiagnostic<'db>> { |
| ... | ... | @@ -666,8 +666,7 @@ impl<'db> AnyDiagnostic<'db> { |
| 666 | 666 | } |
| 667 | 667 | InferenceDiagnostic::ExpectedFunction { call_expr, found } => { |
| 668 | 668 | let call_expr = expr_syntax(*call_expr)?; |
| 669 | ExpectedFunction { call: call_expr, found: Type::new(db, def, found.clone()) } | |
| 670 | .into() | |
| 669 | ExpectedFunction { call: call_expr, found: Type::new(db, def, *found) }.into() | |
| 671 | 670 | } |
| 672 | 671 | InferenceDiagnostic::UnresolvedField { |
| 673 | 672 | expr, |
| ... | ... | @@ -679,7 +678,7 @@ impl<'db> AnyDiagnostic<'db> { |
| 679 | 678 | UnresolvedField { |
| 680 | 679 | expr, |
| 681 | 680 | name: name.clone(), |
| 682 | receiver: Type::new(db, def, receiver.clone()), | |
| 681 | receiver: Type::new(db, def, *receiver), | |
| 683 | 682 | method_with_same_name_exists: *method_with_same_name_exists, |
| 684 | 683 | } |
| 685 | 684 | .into() |
| ... | ... | @@ -695,10 +694,8 @@ impl<'db> AnyDiagnostic<'db> { |
| 695 | 694 | UnresolvedMethodCall { |
| 696 | 695 | expr, |
| 697 | 696 | name: name.clone(), |
| 698 | receiver: Type::new(db, def, receiver.clone()), | |
| 699 | field_with_same_name: field_with_same_name | |
| 700 | .clone() | |
| 701 | .map(|ty| Type::new(db, def, ty)), | |
| 697 | receiver: Type::new(db, def, *receiver), | |
| 698 | field_with_same_name: (*field_with_same_name).map(|ty| Type::new(db, def, ty)), | |
| 702 | 699 | assoc_func_with_same_name: assoc_func_with_same_name.map(Into::into), |
| 703 | 700 | } |
| 704 | 701 | .into() |
| ... | ... | @@ -725,7 +722,7 @@ impl<'db> AnyDiagnostic<'db> { |
| 725 | 722 | } |
| 726 | 723 | InferenceDiagnostic::TypedHole { expr, expected } => { |
| 727 | 724 | let expr = expr_syntax(*expr)?; |
| 728 | TypedHole { expr, expected: Type::new(db, def, expected.clone()) }.into() | |
| 725 | TypedHole { expr, expected: Type::new(db, def, *expected) }.into() | |
| 729 | 726 | } |
| 730 | 727 | &InferenceDiagnostic::MismatchedTupleStructPatArgCount { pat, expected, found } => { |
| 731 | 728 | let expr_or_pat = match pat { |
| ... | ... | @@ -742,12 +739,12 @@ impl<'db> AnyDiagnostic<'db> { |
| 742 | 739 | } |
| 743 | 740 | InferenceDiagnostic::CastToUnsized { expr, cast_ty } => { |
| 744 | 741 | let expr = expr_syntax(*expr)?; |
| 745 | CastToUnsized { expr, cast_ty: Type::new(db, def, cast_ty.clone()) }.into() | |
| 742 | CastToUnsized { expr, cast_ty: Type::new(db, def, *cast_ty) }.into() | |
| 746 | 743 | } |
| 747 | 744 | InferenceDiagnostic::InvalidCast { expr, error, expr_ty, cast_ty } => { |
| 748 | 745 | let expr = expr_syntax(*expr)?; |
| 749 | let expr_ty = Type::new(db, def, expr_ty.clone()); | |
| 750 | let cast_ty = Type::new(db, def, cast_ty.clone()); | |
| 746 | let expr_ty = Type::new(db, def, *expr_ty); | |
| 747 | let cast_ty = Type::new(db, def, *cast_ty); | |
| 751 | 748 | InvalidCast { expr, error: *error, expr_ty, cast_ty }.into() |
| 752 | 749 | } |
| 753 | 750 | InferenceDiagnostic::TyDiagnostic { source, diag } => { |
src/tools/rust-analyzer/crates/hir/src/display.rs+3-3| ... | ... | @@ -11,7 +11,7 @@ use hir_def::{ |
| 11 | 11 | type_ref::{TypeBound, TypeRef, TypeRefId}, |
| 12 | 12 | }; |
| 13 | 13 | use hir_ty::{ |
| 14 | AliasEq, AliasTy, Interner, ProjectionTyExt, TraitRefExt, TyKind, WhereClause, | |
| 14 | AliasEq, AliasTy, Interner, ProjectionTyExt, TraitRefExt, TyBuilder, TyKind, WhereClause, | |
| 15 | 15 | db::HirDatabase, |
| 16 | 16 | display::{ |
| 17 | 17 | HirDisplay, HirDisplayError, HirDisplayWithExpressionStore, HirFormatter, SizedByDefault, |
| ... | ... | @@ -23,8 +23,8 @@ use itertools::Itertools; |
| 23 | 23 | use crate::{ |
| 24 | 24 | Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Crate, Enum, |
| 25 | 25 | ExternCrateDecl, Field, Function, GenericParam, HasCrate, HasVisibility, Impl, LifetimeParam, |
| 26 | Macro, Module, SelfParam, Static, Struct, StructKind, Trait, TraitRef, TupleField, TyBuilder, | |
| 27 | Type, TypeAlias, TypeNs, TypeOrConstParam, TypeParam, Union, Variant, | |
| 26 | Macro, Module, SelfParam, Static, Struct, StructKind, Trait, TraitRef, TupleField, Type, | |
| 27 | TypeAlias, TypeNs, TypeOrConstParam, TypeParam, Union, Variant, | |
| 28 | 28 | }; |
| 29 | 29 | |
| 30 | 30 | impl HirDisplay for Function { |
src/tools/rust-analyzer/crates/hir/src/has_source.rs+1-1| ... | ... | @@ -238,7 +238,7 @@ impl HasSource for Param<'_> { |
| 238 | 238 | .map(|value| InFile { file_id, value }) |
| 239 | 239 | } |
| 240 | 240 | Callee::Closure(closure, _) => { |
| 241 | let InternedClosure(owner, expr_id) = db.lookup_intern_closure(closure.into()); | |
| 241 | let InternedClosure(owner, expr_id) = db.lookup_intern_closure(closure); | |
| 242 | 242 | let (_, source_map) = db.body_with_source_map(owner); |
| 243 | 243 | let ast @ InFile { file_id, value } = source_map.expr_syntax(expr_id).ok()?; |
| 244 | 244 | let root = db.parse_or_expand(file_id); |
src/tools/rust-analyzer/crates/hir/src/lib.rs+572-849| ... | ... | @@ -71,29 +71,31 @@ use hir_expand::{ |
| 71 | 71 | proc_macro::ProcMacroKind, |
| 72 | 72 | }; |
| 73 | 73 | use hir_ty::{ |
| 74 | AliasTy, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg, | |
| 75 | GenericArgData, Interner, ParamKind, ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, | |
| 76 | TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, TyLoweringDiagnostic, | |
| 77 | ValueTyDefId, WhereClause, all_super_traits, autoderef, check_orphan_rules, | |
| 78 | consteval::{ConstExt, try_const_usize, unknown_const_as_generic}, | |
| 74 | TraitEnvironment, TyDefId, TyLoweringDiagnostic, ValueTyDefId, all_super_traits, autoderef, | |
| 75 | check_orphan_rules, | |
| 76 | consteval::try_const_usize, | |
| 77 | db::InternedClosureId, | |
| 79 | 78 | diagnostics::BodyValidationDiagnostic, |
| 80 | direct_super_traits, error_lifetime, known_const_to_ast, | |
| 79 | direct_super_traits, known_const_to_ast, | |
| 81 | 80 | layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding}, |
| 82 | 81 | method_resolution, |
| 83 | 82 | mir::{MutBorrowKind, interpret_mir}, |
| 84 | 83 | next_solver::{ |
| 85 | ClauseKind, DbInterner, GenericArgs, | |
| 86 | infer::InferCtxt, | |
| 87 | mapping::{ChalkToNextSolver, NextSolverToChalk, convert_ty_for_result}, | |
| 84 | AliasTy, Canonical, ClauseKind, ConstKind, DbInterner, ErrorGuaranteed, GenericArg, | |
| 85 | GenericArgs, PolyFnSig, Region, SolverDefId, Ty, TyKind, TypingMode, | |
| 86 | infer::{DbInternerInferExt, InferCtxt}, | |
| 88 | 87 | }, |
| 89 | primitive::UintTy, | |
| 90 | traits::FnTrait, | |
| 88 | traits::{self, FnTrait, structurally_normalize_ty}, | |
| 91 | 89 | }; |
| 92 | 90 | use itertools::Itertools; |
| 93 | 91 | use rustc_hash::FxHashSet; |
| 92 | use rustc_type_ir::{ | |
| 93 | AliasTyKind, TypeSuperVisitable, TypeVisitable, TypeVisitor, | |
| 94 | inherent::{AdtDef, IntoKind, SliceLike, Term as _, Ty as _}, | |
| 95 | }; | |
| 94 | 96 | use smallvec::SmallVec; |
| 95 | 97 | use span::{AstIdNode, Edition, FileId}; |
| 96 | use stdx::{format_to, impl_from, never, variance::PhantomCovariantLifetime}; | |
| 98 | use stdx::{format_to, impl_from, never}; | |
| 97 | 99 | use syntax::{ |
| 98 | 100 | AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, T, TextRange, ToSmolStr, |
| 99 | 101 | ast::{self, HasAttrs as _, HasName, HasVisibility as _}, |
| ... | ... | @@ -112,7 +114,6 @@ pub use crate::{ |
| 112 | 114 | VisibleTraits, |
| 113 | 115 | }, |
| 114 | 116 | }; |
| 115 | use rustc_type_ir::inherent::{IntoKind, SliceLike}; | |
| 116 | 117 | |
| 117 | 118 | // Be careful with these re-exports. |
| 118 | 119 | // |
| ... | ... | @@ -156,18 +157,20 @@ pub use { |
| 156 | 157 | proc_macro::{ProcMacros, ProcMacrosBuilder}, |
| 157 | 158 | tt, |
| 158 | 159 | }, |
| 160 | // FIXME: Properly encapsulate mir | |
| 161 | hir_ty::mir, | |
| 159 | 162 | hir_ty::{ |
| 160 | CastError, DropGlue, FnAbi, PointerCast, Safety, Variance, | |
| 163 | CastError, FnAbi, PointerCast, Variance, attach_db, attach_db_allow_change, | |
| 161 | 164 | consteval::ConstEvalError, |
| 162 | 165 | diagnostics::UnsafetyReason, |
| 163 | 166 | display::{ClosureStyle, DisplayTarget, HirDisplay, HirDisplayError, HirWrite}, |
| 167 | drop::DropGlue, | |
| 164 | 168 | dyn_compatibility::{DynCompatibilityViolation, MethodViolationCode}, |
| 165 | 169 | layout::LayoutError, |
| 166 | 170 | method_resolution::TyFingerprint, |
| 167 | 171 | mir::{MirEvalError, MirLowerError}, |
| 172 | next_solver::abi::Safety, | |
| 168 | 173 | }, |
| 169 | // FIXME: Properly encapsulate mir | |
| 170 | hir_ty::{Interner as ChalkTyInterner, mir}, | |
| 171 | 174 | intern::{Symbol, sym}, |
| 172 | 175 | }; |
| 173 | 176 | |
| ... | ... | @@ -748,12 +751,15 @@ impl Module { |
| 748 | 751 | |
| 749 | 752 | let inherent_impls = db.inherent_impls_in_crate(self.id.krate()); |
| 750 | 753 | |
| 754 | let interner = DbInterner::new_with(db, Some(self.id.krate()), self.id.containing_block()); | |
| 755 | let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); | |
| 756 | ||
| 751 | 757 | let mut impl_assoc_items_scratch = vec![]; |
| 752 | 758 | for impl_def in self.impl_defs(db) { |
| 753 | 759 | GenericDef::Impl(impl_def).diagnostics(db, acc); |
| 754 | 760 | |
| 755 | 761 | let loc = impl_def.id.lookup(db); |
| 756 | let source_map = db.impl_signature_with_source_map(impl_def.id).1; | |
| 762 | let (impl_signature, source_map) = db.impl_signature_with_source_map(impl_def.id); | |
| 757 | 763 | expr_store_diagnostics(db, acc, &source_map); |
| 758 | 764 | |
| 759 | 765 | let file_id = loc.id.file_id; |
| ... | ... | @@ -782,10 +788,17 @@ impl Module { |
| 782 | 788 | } |
| 783 | 789 | |
| 784 | 790 | let trait_ = impl_def.trait_(db); |
| 785 | let trait_is_unsafe = trait_.is_some_and(|t| t.is_unsafe(db)); | |
| 791 | let mut trait_is_unsafe = trait_.is_some_and(|t| t.is_unsafe(db)); | |
| 786 | 792 | let impl_is_negative = impl_def.is_negative(db); |
| 787 | 793 | let impl_is_unsafe = impl_def.is_unsafe(db); |
| 788 | 794 | |
| 795 | let trait_is_unresolved = trait_.is_none() && impl_signature.target_trait.is_some(); | |
| 796 | if trait_is_unresolved { | |
| 797 | // Ignore trait safety errors when the trait is unresolved, as otherwise we'll treat it as safe, | |
| 798 | // which may not be correct. | |
| 799 | trait_is_unsafe = impl_is_unsafe; | |
| 800 | } | |
| 801 | ||
| 789 | 802 | let drop_maybe_dangle = (|| { |
| 790 | 803 | // FIXME: This can be simplified a lot by exposing hir-ty's utils.rs::Generics helper |
| 791 | 804 | let trait_ = trait_?; |
| ... | ... | @@ -865,26 +878,15 @@ impl Module { |
| 865 | 878 | .collect(); |
| 866 | 879 | |
| 867 | 880 | if !missing.is_empty() { |
| 868 | let interner = DbInterner::new_with(db, None, None); | |
| 869 | let args: crate::next_solver::GenericArgs<'_> = | |
| 870 | hir_ty::generics::generics(db, impl_def.id.into()) | |
| 871 | .placeholder_subst(db) | |
| 872 | .to_nextsolver(interner); | |
| 873 | let self_ty = | |
| 874 | db.impl_self_ty(impl_def.id).instantiate(interner, args).to_chalk(interner); | |
| 875 | let self_ty = if let TyKind::Alias(AliasTy::Projection(projection)) = | |
| 876 | self_ty.kind(Interner) | |
| 877 | { | |
| 878 | db.normalize_projection( | |
| 879 | projection.clone(), | |
| 880 | db.trait_environment(impl_def.id.into()), | |
| 881 | ) | |
| 882 | } else { | |
| 883 | self_ty | |
| 884 | }; | |
| 881 | let self_ty = db.impl_self_ty(impl_def.id).instantiate_identity(); | |
| 882 | let self_ty = structurally_normalize_ty( | |
| 883 | &infcx, | |
| 884 | self_ty, | |
| 885 | db.trait_environment(impl_def.id.into()), | |
| 886 | ); | |
| 885 | 887 | let self_ty_is_guaranteed_unsized = matches!( |
| 886 | self_ty.kind(Interner), | |
| 887 | TyKind::Dyn(..) | TyKind::Slice(..) | TyKind::Str | |
| 888 | self_ty.kind(), | |
| 889 | TyKind::Dynamic(..) | TyKind::Slice(..) | TyKind::Str | |
| 888 | 890 | ); |
| 889 | 891 | if self_ty_is_guaranteed_unsized { |
| 890 | 892 | missing.retain(|(_, assoc_item)| { |
| ... | ... | @@ -1287,19 +1289,15 @@ impl TupleField { |
| 1287 | 1289 | } |
| 1288 | 1290 | |
| 1289 | 1291 | pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> Type<'db> { |
| 1292 | let interner = DbInterner::new_with(db, None, None); | |
| 1290 | 1293 | let ty = db |
| 1291 | 1294 | .infer(self.owner) |
| 1292 | 1295 | .tuple_field_access_type(self.tuple) |
| 1293 | .as_slice(Interner) | |
| 1296 | .as_slice() | |
| 1294 | 1297 | .get(self.index as usize) |
| 1295 | .and_then(|arg| arg.ty(Interner)) | |
| 1296 | .cloned() | |
| 1297 | .unwrap_or_else(|| TyKind::Error.intern(Interner)); | |
| 1298 | Type { | |
| 1299 | env: db.trait_environment_for_body(self.owner), | |
| 1300 | ty, | |
| 1301 | _pd: PhantomCovariantLifetime::new(), | |
| 1302 | } | |
| 1298 | .copied() | |
| 1299 | .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed)); | |
| 1300 | Type { env: db.trait_environment_for_body(self.owner), ty } | |
| 1303 | 1301 | } |
| 1304 | 1302 | } |
| 1305 | 1303 | |
| ... | ... | @@ -1367,17 +1365,9 @@ impl Field { |
| 1367 | 1365 | VariantDef::Union(it) => it.id.into(), |
| 1368 | 1366 | VariantDef::Variant(it) => it.parent_enum(db).id.into(), |
| 1369 | 1367 | }; |
| 1370 | let mut generics = generics.map(|it| it.ty); | |
| 1371 | let substs = TyBuilder::subst_for_def(db, def_id, None) | |
| 1372 | .fill(|x| match x { | |
| 1373 | ParamKind::Type => { | |
| 1374 | generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner) | |
| 1375 | } | |
| 1376 | ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()), | |
| 1377 | ParamKind::Lifetime => error_lifetime().cast(Interner), | |
| 1378 | }) | |
| 1379 | .build(); | |
| 1380 | let ty = db.field_types(var_id)[self.id].clone().substitute(Interner, &substs); | |
| 1368 | let interner = DbInterner::new_with(db, None, None); | |
| 1369 | let args = generic_args_from_tys(interner, def_id.into(), generics.map(|ty| ty.ty)); | |
| 1370 | let ty = db.field_types_ns(var_id)[self.id].instantiate(interner, args); | |
| 1381 | 1371 | Type::new(db, var_id, ty) |
| 1382 | 1372 | } |
| 1383 | 1373 | |
| ... | ... | @@ -1437,8 +1427,8 @@ impl Struct { |
| 1437 | 1427 | Type::from_def(db, self.id) |
| 1438 | 1428 | } |
| 1439 | 1429 | |
| 1440 | pub fn ty_placeholders(self, db: &dyn HirDatabase) -> Type<'_> { | |
| 1441 | Type::from_def_placeholders(db, self.id) | |
| 1430 | pub fn ty_params(self, db: &dyn HirDatabase) -> Type<'_> { | |
| 1431 | Type::from_def_params(db, self.id) | |
| 1442 | 1432 | } |
| 1443 | 1433 | |
| 1444 | 1434 | pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type<'_> { |
| ... | ... | @@ -1526,8 +1516,8 @@ impl Union { |
| 1526 | 1516 | Type::from_def(db, self.id) |
| 1527 | 1517 | } |
| 1528 | 1518 | |
| 1529 | pub fn ty_placeholders(self, db: &dyn HirDatabase) -> Type<'_> { | |
| 1530 | Type::from_def_placeholders(db, self.id) | |
| 1519 | pub fn ty_params(self, db: &dyn HirDatabase) -> Type<'_> { | |
| 1520 | Type::from_def_params(db, self.id) | |
| 1531 | 1521 | } |
| 1532 | 1522 | |
| 1533 | 1523 | pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type<'_> { |
| ... | ... | @@ -1593,40 +1583,43 @@ impl Enum { |
| 1593 | 1583 | Type::from_def(db, self.id) |
| 1594 | 1584 | } |
| 1595 | 1585 | |
| 1596 | pub fn ty_placeholders<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> { | |
| 1597 | Type::from_def_placeholders(db, self.id) | |
| 1586 | pub fn ty_params<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> { | |
| 1587 | Type::from_def_params(db, self.id) | |
| 1598 | 1588 | } |
| 1599 | 1589 | |
| 1600 | 1590 | /// The type of the enum variant bodies. |
| 1601 | 1591 | pub fn variant_body_ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> { |
| 1592 | let interner = DbInterner::new_with(db, None, None); | |
| 1602 | 1593 | Type::new_for_crate( |
| 1603 | 1594 | self.id.lookup(db).container.krate(), |
| 1604 | TyBuilder::builtin(match db.enum_signature(self.id).variant_body_type() { | |
| 1595 | match db.enum_signature(self.id).variant_body_type() { | |
| 1605 | 1596 | layout::IntegerType::Pointer(sign) => match sign { |
| 1606 | true => hir_def::builtin_type::BuiltinType::Int( | |
| 1607 | hir_def::builtin_type::BuiltinInt::Isize, | |
| 1608 | ), | |
| 1609 | false => hir_def::builtin_type::BuiltinType::Uint( | |
| 1610 | hir_def::builtin_type::BuiltinUint::Usize, | |
| 1611 | ), | |
| 1597 | true => Ty::new_int(interner, rustc_type_ir::IntTy::Isize), | |
| 1598 | false => Ty::new_uint(interner, rustc_type_ir::UintTy::Usize), | |
| 1612 | 1599 | }, |
| 1613 | 1600 | layout::IntegerType::Fixed(i, sign) => match sign { |
| 1614 | true => hir_def::builtin_type::BuiltinType::Int(match i { | |
| 1615 | layout::Integer::I8 => hir_def::builtin_type::BuiltinInt::I8, | |
| 1616 | layout::Integer::I16 => hir_def::builtin_type::BuiltinInt::I16, | |
| 1617 | layout::Integer::I32 => hir_def::builtin_type::BuiltinInt::I32, | |
| 1618 | layout::Integer::I64 => hir_def::builtin_type::BuiltinInt::I64, | |
| 1619 | layout::Integer::I128 => hir_def::builtin_type::BuiltinInt::I128, | |
| 1620 | }), | |
| 1621 | false => hir_def::builtin_type::BuiltinType::Uint(match i { | |
| 1622 | layout::Integer::I8 => hir_def::builtin_type::BuiltinUint::U8, | |
| 1623 | layout::Integer::I16 => hir_def::builtin_type::BuiltinUint::U16, | |
| 1624 | layout::Integer::I32 => hir_def::builtin_type::BuiltinUint::U32, | |
| 1625 | layout::Integer::I64 => hir_def::builtin_type::BuiltinUint::U64, | |
| 1626 | layout::Integer::I128 => hir_def::builtin_type::BuiltinUint::U128, | |
| 1627 | }), | |
| 1601 | true => Ty::new_int( | |
| 1602 | interner, | |
| 1603 | match i { | |
| 1604 | layout::Integer::I8 => rustc_type_ir::IntTy::I8, | |
| 1605 | layout::Integer::I16 => rustc_type_ir::IntTy::I16, | |
| 1606 | layout::Integer::I32 => rustc_type_ir::IntTy::I32, | |
| 1607 | layout::Integer::I64 => rustc_type_ir::IntTy::I64, | |
| 1608 | layout::Integer::I128 => rustc_type_ir::IntTy::I128, | |
| 1609 | }, | |
| 1610 | ), | |
| 1611 | false => Ty::new_uint( | |
| 1612 | interner, | |
| 1613 | match i { | |
| 1614 | layout::Integer::I8 => rustc_type_ir::UintTy::U8, | |
| 1615 | layout::Integer::I16 => rustc_type_ir::UintTy::U16, | |
| 1616 | layout::Integer::I32 => rustc_type_ir::UintTy::U32, | |
| 1617 | layout::Integer::I64 => rustc_type_ir::UintTy::U64, | |
| 1618 | layout::Integer::I128 => rustc_type_ir::UintTy::U128, | |
| 1619 | }, | |
| 1620 | ), | |
| 1628 | 1621 | }, |
| 1629 | }), | |
| 1622 | }, | |
| 1630 | 1623 | ) |
| 1631 | 1624 | } |
| 1632 | 1625 | |
| ... | ... | @@ -1720,7 +1713,7 @@ impl Variant { |
| 1720 | 1713 | self.source(db)?.value.expr() |
| 1721 | 1714 | } |
| 1722 | 1715 | |
| 1723 | pub fn eval(self, db: &dyn HirDatabase) -> Result<i128, ConstEvalError> { | |
| 1716 | pub fn eval(self, db: &dyn HirDatabase) -> Result<i128, ConstEvalError<'_>> { | |
| 1724 | 1717 | db.const_eval_discriminant(self.into()) |
| 1725 | 1718 | } |
| 1726 | 1719 | |
| ... | ... | @@ -1802,26 +1795,18 @@ impl_from!(Struct, Union, Enum for Adt); |
| 1802 | 1795 | |
| 1803 | 1796 | impl Adt { |
| 1804 | 1797 | pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { |
| 1805 | let subst = db.generic_defaults(self.into()); | |
| 1806 | (subst.is_empty() && db.generic_params(self.into()).len_type_or_consts() != 0) | |
| 1807 | || subst.iter().any(|ty| match ty.skip_binders().data(Interner) { | |
| 1808 | GenericArgData::Ty(it) => it.is_unknown(), | |
| 1809 | _ => false, | |
| 1810 | }) | |
| 1798 | has_non_default_type_params(db, self.into()) | |
| 1811 | 1799 | } |
| 1812 | 1800 | |
| 1813 | 1801 | pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> { |
| 1814 | 1802 | let env = db.trait_environment(self.into()); |
| 1815 | 1803 | let interner = DbInterner::new_with(db, Some(env.krate), env.block); |
| 1816 | db.layout_of_adt( | |
| 1817 | self.into(), | |
| 1818 | TyBuilder::adt(db, self.into()) | |
| 1819 | .fill_with_defaults(db, || TyKind::Error.intern(Interner)) | |
| 1820 | .build_into_subst() | |
| 1821 | .to_nextsolver(interner), | |
| 1822 | env, | |
| 1823 | ) | |
| 1824 | .map(|layout| Layout(layout, db.target_data_layout(self.krate(db).id).unwrap())) | |
| 1804 | let adt_id = AdtId::from(self); | |
| 1805 | let args = GenericArgs::for_item_with_defaults(interner, adt_id.into(), |_, _, id, _| { | |
| 1806 | GenericArg::error_from_id(interner, id) | |
| 1807 | }); | |
| 1808 | db.layout_of_adt(adt_id, args, env) | |
| 1809 | .map(|layout| Layout(layout, db.target_data_layout(self.krate(db).id).unwrap())) | |
| 1825 | 1810 | } |
| 1826 | 1811 | |
| 1827 | 1812 | /// Turns this ADT into a type. Any type parameters of the ADT will be |
| ... | ... | @@ -1840,18 +1825,12 @@ impl Adt { |
| 1840 | 1825 | args: impl IntoIterator<Item = Type<'db>>, |
| 1841 | 1826 | ) -> Type<'db> { |
| 1842 | 1827 | let id = AdtId::from(self); |
| 1843 | let mut it = args.into_iter().map(|t| t.ty); | |
| 1844 | let ty = TyBuilder::def_ty(db, id.into(), None) | |
| 1845 | .fill(|x| { | |
| 1846 | let r = it.next().unwrap_or_else(|| TyKind::Error.intern(Interner)); | |
| 1847 | match x { | |
| 1848 | ParamKind::Type => r.cast(Interner), | |
| 1849 | ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()), | |
| 1850 | ParamKind::Lifetime => error_lifetime().cast(Interner), | |
| 1851 | } | |
| 1852 | }) | |
| 1853 | .build(DbInterner::conjure()) | |
| 1854 | .to_chalk(DbInterner::conjure()); | |
| 1828 | let interner = DbInterner::new_with(db, None, None); | |
| 1829 | let ty = Ty::new_adt( | |
| 1830 | interner, | |
| 1831 | id, | |
| 1832 | generic_args_from_tys(interner, id.into(), args.into_iter().map(|ty| ty.ty)), | |
| 1833 | ); | |
| 1855 | 1834 | Type::new(db, id, ty) |
| 1856 | 1835 | } |
| 1857 | 1836 | |
| ... | ... | @@ -2061,8 +2040,8 @@ impl DefWithBody { |
| 2061 | 2040 | acc.push( |
| 2062 | 2041 | TypeMismatch { |
| 2063 | 2042 | expr_or_pat, |
| 2064 | expected: Type::new(db, DefWithBodyId::from(self), mismatch.expected.clone()), | |
| 2065 | actual: Type::new(db, DefWithBodyId::from(self), mismatch.actual.clone()), | |
| 2043 | expected: Type::new(db, DefWithBodyId::from(self), mismatch.expected), | |
| 2044 | actual: Type::new(db, DefWithBodyId::from(self), mismatch.actual), | |
| 2066 | 2045 | } |
| 2067 | 2046 | .into(), |
| 2068 | 2047 | ); |
| ... | ... | @@ -2132,10 +2111,7 @@ impl DefWithBody { |
| 2132 | 2111 | } |
| 2133 | 2112 | mir::MirSpan::Unknown => continue, |
| 2134 | 2113 | }; |
| 2135 | acc.push( | |
| 2136 | MovedOutOfRef { ty: Type::new_for_crate(krate, moof.ty.clone()), span } | |
| 2137 | .into(), | |
| 2138 | ) | |
| 2114 | acc.push(MovedOutOfRef { ty: Type::new_for_crate(krate, moof.ty), span }.into()) | |
| 2139 | 2115 | } |
| 2140 | 2116 | let mol = &borrowck_result.mutability_of_locals; |
| 2141 | 2117 | for (binding_id, binding_data) in body.bindings() { |
| ... | ... | @@ -2285,30 +2261,24 @@ impl Function { |
| 2285 | 2261 | |
| 2286 | 2262 | pub fn fn_ptr_type(self, db: &dyn HirDatabase) -> Type<'_> { |
| 2287 | 2263 | let resolver = self.id.resolver(db); |
| 2288 | let substs = TyBuilder::placeholder_subst(db, self.id); | |
| 2289 | 2264 | let interner = DbInterner::new_with(db, None, None); |
| 2290 | let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 2291 | let callable_sig = db | |
| 2292 | .callable_item_signature(self.id.into()) | |
| 2293 | .instantiate(interner, args) | |
| 2294 | .skip_binder() | |
| 2295 | .to_chalk(interner); | |
| 2296 | let ty = TyKind::Function(callable_sig.to_fn_ptr()).intern(Interner); | |
| 2265 | // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. | |
| 2266 | let callable_sig = db.callable_item_signature(self.id.into()).instantiate_identity(); | |
| 2267 | let ty = Ty::new_fn_ptr(interner, callable_sig); | |
| 2297 | 2268 | Type::new_with_resolver_inner(db, &resolver, ty) |
| 2298 | 2269 | } |
| 2299 | 2270 | |
| 2271 | // FIXME: Find a better API to express all combinations here, perhaps we should have `PreInstantiationType`? | |
| 2272 | ||
| 2300 | 2273 | /// Get this function's return type |
| 2301 | 2274 | pub fn ret_type(self, db: &dyn HirDatabase) -> Type<'_> { |
| 2302 | 2275 | let resolver = self.id.resolver(db); |
| 2303 | let substs = TyBuilder::placeholder_subst(db, self.id); | |
| 2304 | let interner = DbInterner::new_with(db, None, None); | |
| 2305 | let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 2276 | // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. | |
| 2306 | 2277 | let ty = db |
| 2307 | 2278 | .callable_item_signature(self.id.into()) |
| 2308 | .instantiate(interner, args) | |
| 2279 | .instantiate_identity() | |
| 2309 | 2280 | .skip_binder() |
| 2310 | .output() | |
| 2311 | .to_chalk(interner); | |
| 2281 | .output(); | |
| 2312 | 2282 | Type::new_with_resolver_inner(db, &resolver, ty) |
| 2313 | 2283 | } |
| 2314 | 2284 | |
| ... | ... | @@ -2319,32 +2289,15 @@ impl Function { |
| 2319 | 2289 | generics: impl Iterator<Item = Type<'db>>, |
| 2320 | 2290 | ) -> Type<'db> { |
| 2321 | 2291 | let resolver = self.id.resolver(db); |
| 2322 | let parent_id: Option<GenericDefId> = match self.id.lookup(db).container { | |
| 2323 | ItemContainerId::ImplId(it) => Some(it.into()), | |
| 2324 | ItemContainerId::TraitId(it) => Some(it.into()), | |
| 2325 | ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None, | |
| 2326 | }; | |
| 2327 | let mut generics = generics.map(|it| it.ty); | |
| 2328 | let mut filler = |x: &_| match x { | |
| 2329 | ParamKind::Type => { | |
| 2330 | generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner) | |
| 2331 | } | |
| 2332 | ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()), | |
| 2333 | ParamKind::Lifetime => error_lifetime().cast(Interner), | |
| 2334 | }; | |
| 2335 | ||
| 2336 | let parent_substs = | |
| 2337 | parent_id.map(|id| TyBuilder::subst_for_def(db, id, None).fill(&mut filler).build()); | |
| 2338 | let substs = TyBuilder::subst_for_def(db, self.id, parent_substs).fill(&mut filler).build(); | |
| 2292 | let interner = DbInterner::new_with(db, None, None); | |
| 2293 | let args = generic_args_from_tys(interner, self.id.into(), generics.map(|ty| ty.ty)); | |
| 2339 | 2294 | |
| 2340 | 2295 | let interner = DbInterner::new_with(db, None, None); |
| 2341 | let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 2342 | 2296 | let ty = db |
| 2343 | 2297 | .callable_item_signature(self.id.into()) |
| 2344 | 2298 | .instantiate(interner, args) |
| 2345 | 2299 | .skip_binder() |
| 2346 | .output() | |
| 2347 | .to_chalk(interner); | |
| 2300 | .output(); | |
| 2348 | 2301 | Type::new_with_resolver_inner(db, &resolver, ty) |
| 2349 | 2302 | } |
| 2350 | 2303 | |
| ... | ... | @@ -2353,18 +2306,17 @@ impl Function { |
| 2353 | 2306 | return None; |
| 2354 | 2307 | } |
| 2355 | 2308 | let resolver = self.id.resolver(db); |
| 2356 | let substs = TyBuilder::placeholder_subst(db, self.id); | |
| 2357 | let interner = DbInterner::new_with(db, None, None); | |
| 2358 | let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 2309 | // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. | |
| 2359 | 2310 | let ret_ty = db |
| 2360 | 2311 | .callable_item_signature(self.id.into()) |
| 2361 | .instantiate(interner, args) | |
| 2312 | .instantiate_identity() | |
| 2362 | 2313 | .skip_binder() |
| 2363 | .output() | |
| 2364 | .to_chalk(interner); | |
| 2314 | .output(); | |
| 2365 | 2315 | for pred in ret_ty.impl_trait_bounds(db).into_iter().flatten() { |
| 2366 | if let WhereClause::AliasEq(output_eq) = pred.into_value_and_skipped_binders().0 { | |
| 2367 | return Type::new_with_resolver_inner(db, &resolver, output_eq.ty).into(); | |
| 2316 | if let ClauseKind::Projection(projection) = pred.kind().skip_binder() | |
| 2317 | && let Some(output_ty) = projection.term.as_type() | |
| 2318 | { | |
| 2319 | return Type::new_with_resolver_inner(db, &resolver, output_ty).into(); | |
| 2368 | 2320 | } |
| 2369 | 2321 | } |
| 2370 | 2322 | None |
| ... | ... | @@ -2380,24 +2332,15 @@ impl Function { |
| 2380 | 2332 | |
| 2381 | 2333 | pub fn assoc_fn_params(self, db: &dyn HirDatabase) -> Vec<Param<'_>> { |
| 2382 | 2334 | let environment = db.trait_environment(self.id.into()); |
| 2383 | let substs = TyBuilder::placeholder_subst(db, self.id); | |
| 2384 | let interner = DbInterner::new_with(db, None, None); | |
| 2385 | let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 2386 | let callable_sig = db | |
| 2387 | .callable_item_signature(self.id.into()) | |
| 2388 | .instantiate(interner, args) | |
| 2389 | .skip_binder() | |
| 2390 | .to_chalk(interner); | |
| 2335 | // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. | |
| 2336 | let callable_sig = | |
| 2337 | db.callable_item_signature(self.id.into()).instantiate_identity().skip_binder(); | |
| 2391 | 2338 | callable_sig |
| 2392 | .params() | |
| 2339 | .inputs() | |
| 2393 | 2340 | .iter() |
| 2394 | 2341 | .enumerate() |
| 2395 | 2342 | .map(|(idx, ty)| { |
| 2396 | let ty = Type { | |
| 2397 | env: environment.clone(), | |
| 2398 | ty: ty.clone(), | |
| 2399 | _pd: PhantomCovariantLifetime::new(), | |
| 2400 | }; | |
| 2343 | let ty = Type { env: environment.clone(), ty }; | |
| 2401 | 2344 | Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx } |
| 2402 | 2345 | }) |
| 2403 | 2346 | .collect() |
| ... | ... | @@ -2414,26 +2357,17 @@ impl Function { |
| 2414 | 2357 | |
| 2415 | 2358 | pub fn params_without_self(self, db: &dyn HirDatabase) -> Vec<Param<'_>> { |
| 2416 | 2359 | let environment = db.trait_environment(self.id.into()); |
| 2417 | let substs = TyBuilder::placeholder_subst(db, self.id); | |
| 2418 | let interner = DbInterner::new_with(db, None, None); | |
| 2419 | let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 2420 | let callable_sig = db | |
| 2421 | .callable_item_signature(self.id.into()) | |
| 2422 | .instantiate(interner, args) | |
| 2423 | .skip_binder() | |
| 2424 | .to_chalk(interner); | |
| 2360 | // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. | |
| 2361 | let callable_sig = | |
| 2362 | db.callable_item_signature(self.id.into()).instantiate_identity().skip_binder(); | |
| 2425 | 2363 | let skip = if db.function_signature(self.id).has_self_param() { 1 } else { 0 }; |
| 2426 | 2364 | callable_sig |
| 2427 | .params() | |
| 2365 | .inputs() | |
| 2428 | 2366 | .iter() |
| 2429 | 2367 | .enumerate() |
| 2430 | 2368 | .skip(skip) |
| 2431 | 2369 | .map(|(idx, ty)| { |
| 2432 | let ty = Type { | |
| 2433 | env: environment.clone(), | |
| 2434 | ty: ty.clone(), | |
| 2435 | _pd: PhantomCovariantLifetime::new(), | |
| 2436 | }; | |
| 2370 | let ty = Type { env: environment.clone(), ty }; | |
| 2437 | 2371 | Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx } |
| 2438 | 2372 | }) |
| 2439 | 2373 | .collect() |
| ... | ... | @@ -2446,50 +2380,18 @@ impl Function { |
| 2446 | 2380 | generics: impl Iterator<Item = Type<'db>>, |
| 2447 | 2381 | ) -> Vec<Param<'db>> { |
| 2448 | 2382 | let environment = db.trait_environment(self.id.into()); |
| 2449 | let parent_id: Option<GenericDefId> = match self.id.lookup(db).container { | |
| 2450 | ItemContainerId::ImplId(it) => Some(it.into()), | |
| 2451 | ItemContainerId::TraitId(it) => Some(it.into()), | |
| 2452 | ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None, | |
| 2453 | }; | |
| 2454 | let mut generics = generics.map(|it| it.ty); | |
| 2455 | let parent_substs = parent_id.map(|id| { | |
| 2456 | TyBuilder::subst_for_def(db, id, None) | |
| 2457 | .fill(|x| match x { | |
| 2458 | ParamKind::Type => generics | |
| 2459 | .next() | |
| 2460 | .unwrap_or_else(|| TyKind::Error.intern(Interner)) | |
| 2461 | .cast(Interner), | |
| 2462 | ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()), | |
| 2463 | ParamKind::Lifetime => error_lifetime().cast(Interner), | |
| 2464 | }) | |
| 2465 | .build() | |
| 2466 | }); | |
| 2467 | ||
| 2468 | let substs = TyBuilder::subst_for_def(db, self.id, parent_substs) | |
| 2469 | .fill(|_| { | |
| 2470 | let ty = generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)); | |
| 2471 | GenericArg::new(Interner, GenericArgData::Ty(ty)) | |
| 2472 | }) | |
| 2473 | .build(); | |
| 2474 | 2383 | let interner = DbInterner::new_with(db, None, None); |
| 2475 | let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 2476 | let callable_sig = db | |
| 2477 | .callable_item_signature(self.id.into()) | |
| 2478 | .instantiate(interner, args) | |
| 2479 | .skip_binder() | |
| 2480 | .to_chalk(interner); | |
| 2384 | let args = generic_args_from_tys(interner, self.id.into(), generics.map(|ty| ty.ty)); | |
| 2385 | let callable_sig = | |
| 2386 | db.callable_item_signature(self.id.into()).instantiate(interner, args).skip_binder(); | |
| 2481 | 2387 | let skip = if db.function_signature(self.id).has_self_param() { 1 } else { 0 }; |
| 2482 | 2388 | callable_sig |
| 2483 | .params() | |
| 2389 | .inputs() | |
| 2484 | 2390 | .iter() |
| 2485 | 2391 | .enumerate() |
| 2486 | 2392 | .skip(skip) |
| 2487 | 2393 | .map(|(idx, ty)| { |
| 2488 | let ty = Type { | |
| 2489 | env: environment.clone(), | |
| 2490 | ty: ty.clone(), | |
| 2491 | _pd: PhantomCovariantLifetime::new(), | |
| 2492 | }; | |
| 2394 | let ty = Type { env: environment.clone(), ty }; | |
| 2493 | 2395 | Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx } |
| 2494 | 2396 | }) |
| 2495 | 2397 | .collect() |
| ... | ... | @@ -2628,10 +2530,11 @@ impl Function { |
| 2628 | 2530 | self, |
| 2629 | 2531 | db: &dyn HirDatabase, |
| 2630 | 2532 | span_formatter: impl Fn(FileId, TextRange) -> String, |
| 2631 | ) -> Result<String, ConstEvalError> { | |
| 2533 | ) -> Result<String, ConstEvalError<'_>> { | |
| 2534 | let interner = DbInterner::new_with(db, None, None); | |
| 2632 | 2535 | let body = db.monomorphized_mir_body( |
| 2633 | 2536 | self.id.into(), |
| 2634 | Substitution::empty(Interner), | |
| 2537 | GenericArgs::new_from_iter(interner, []), | |
| 2635 | 2538 | db.trait_environment(self.id.into()), |
| 2636 | 2539 | )?; |
| 2637 | 2540 | let (result, output) = interpret_mir(db, body, false, None)?; |
| ... | ... | @@ -2670,18 +2573,18 @@ pub enum Access { |
| 2670 | 2573 | Owned, |
| 2671 | 2574 | } |
| 2672 | 2575 | |
| 2673 | impl From<hir_ty::Mutability> for Access { | |
| 2674 | fn from(mutability: hir_ty::Mutability) -> Access { | |
| 2576 | impl From<hir_ty::next_solver::Mutability> for Access { | |
| 2577 | fn from(mutability: hir_ty::next_solver::Mutability) -> Access { | |
| 2675 | 2578 | match mutability { |
| 2676 | hir_ty::Mutability::Not => Access::Shared, | |
| 2677 | hir_ty::Mutability::Mut => Access::Exclusive, | |
| 2579 | hir_ty::next_solver::Mutability::Not => Access::Shared, | |
| 2580 | hir_ty::next_solver::Mutability::Mut => Access::Exclusive, | |
| 2678 | 2581 | } |
| 2679 | 2582 | } |
| 2680 | 2583 | } |
| 2681 | 2584 | |
| 2682 | 2585 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
| 2683 | 2586 | pub struct Param<'db> { |
| 2684 | func: Callee, | |
| 2587 | func: Callee<'db>, | |
| 2685 | 2588 | /// The index in parameter list, including self parameter. |
| 2686 | 2589 | idx: usize, |
| 2687 | 2590 | ty: Type<'db>, |
| ... | ... | @@ -2727,7 +2630,7 @@ impl<'db> Param<'db> { |
| 2727 | 2630 | } |
| 2728 | 2631 | } |
| 2729 | 2632 | Callee::Closure(closure, _) => { |
| 2730 | let c = db.lookup_intern_closure(closure.into()); | |
| 2633 | let c = db.lookup_intern_closure(closure); | |
| 2731 | 2634 | let body = db.body(c.0); |
| 2732 | 2635 | if let Expr::Closure { args, .. } = &body[c.1] |
| 2733 | 2636 | && let Pat::Bind { id, .. } = &body[args[self.idx]] |
| ... | ... | @@ -2771,17 +2674,12 @@ impl SelfParam { |
| 2771 | 2674 | } |
| 2772 | 2675 | |
| 2773 | 2676 | pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> Type<'db> { |
| 2774 | let substs = TyBuilder::placeholder_subst(db, self.func); | |
| 2775 | let interner = DbInterner::new_with(db, None, None); | |
| 2776 | let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 2777 | let callable_sig = db | |
| 2778 | .callable_item_signature(self.func.into()) | |
| 2779 | .instantiate(interner, args) | |
| 2780 | .skip_binder() | |
| 2781 | .to_chalk(interner); | |
| 2677 | // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. | |
| 2678 | let callable_sig = | |
| 2679 | db.callable_item_signature(self.func.into()).instantiate_identity().skip_binder(); | |
| 2782 | 2680 | let environment = db.trait_environment(self.func.into()); |
| 2783 | let ty = callable_sig.params()[0].clone(); | |
| 2784 | Type { env: environment, ty, _pd: PhantomCovariantLifetime::new() } | |
| 2681 | let ty = callable_sig.inputs().as_slice()[0]; | |
| 2682 | Type { env: environment, ty } | |
| 2785 | 2683 | } |
| 2786 | 2684 | |
| 2787 | 2685 | // FIXME: Find better API to also handle const generics |
| ... | ... | @@ -2790,36 +2688,13 @@ impl SelfParam { |
| 2790 | 2688 | db: &'db dyn HirDatabase, |
| 2791 | 2689 | generics: impl Iterator<Item = Type<'db>>, |
| 2792 | 2690 | ) -> Type<'db> { |
| 2793 | let parent_id: GenericDefId = match self.func.lookup(db).container { | |
| 2794 | ItemContainerId::ImplId(it) => it.into(), | |
| 2795 | ItemContainerId::TraitId(it) => it.into(), | |
| 2796 | ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => { | |
| 2797 | panic!("Never get here") | |
| 2798 | } | |
| 2799 | }; | |
| 2800 | ||
| 2801 | let mut generics = generics.map(|it| it.ty); | |
| 2802 | let mut filler = |x: &_| match x { | |
| 2803 | ParamKind::Type => { | |
| 2804 | generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner) | |
| 2805 | } | |
| 2806 | ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()), | |
| 2807 | ParamKind::Lifetime => error_lifetime().cast(Interner), | |
| 2808 | }; | |
| 2809 | ||
| 2810 | let parent_substs = TyBuilder::subst_for_def(db, parent_id, None).fill(&mut filler).build(); | |
| 2811 | let substs = | |
| 2812 | TyBuilder::subst_for_def(db, self.func, Some(parent_substs)).fill(&mut filler).build(); | |
| 2813 | 2691 | let interner = DbInterner::new_with(db, None, None); |
| 2814 | let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 2815 | let callable_sig = db | |
| 2816 | .callable_item_signature(self.func.into()) | |
| 2817 | .instantiate(interner, args) | |
| 2818 | .skip_binder() | |
| 2819 | .to_chalk(interner); | |
| 2692 | let args = generic_args_from_tys(interner, self.func.into(), generics.map(|ty| ty.ty)); | |
| 2693 | let callable_sig = | |
| 2694 | db.callable_item_signature(self.func.into()).instantiate(interner, args).skip_binder(); | |
| 2820 | 2695 | let environment = db.trait_environment(self.func.into()); |
| 2821 | let ty = callable_sig.params()[0].clone(); | |
| 2822 | Type { env: environment, ty, _pd: PhantomCovariantLifetime::new() } | |
| 2696 | let ty = callable_sig.inputs().as_slice()[0]; | |
| 2697 | Type { env: environment, ty } | |
| 2823 | 2698 | } |
| 2824 | 2699 | } |
| 2825 | 2700 | |
| ... | ... | @@ -2912,9 +2787,11 @@ impl Const { |
| 2912 | 2787 | } |
| 2913 | 2788 | |
| 2914 | 2789 | /// Evaluate the constant. |
| 2915 | pub fn eval(self, db: &dyn HirDatabase) -> Result<EvaluatedConst, ConstEvalError> { | |
| 2916 | db.const_eval(self.id.into(), Substitution::empty(Interner), None) | |
| 2917 | .map(|it| EvaluatedConst { const_: it, def: self.id.into() }) | |
| 2790 | pub fn eval(self, db: &dyn HirDatabase) -> Result<EvaluatedConst<'_>, ConstEvalError<'_>> { | |
| 2791 | let interner = DbInterner::new_with(db, None, None); | |
| 2792 | let ty = db.value_ty(self.id.into()).unwrap().instantiate_identity(); | |
| 2793 | db.const_eval(self.id.into(), GenericArgs::new_from_iter(interner, []), None) | |
| 2794 | .map(|it| EvaluatedConst { const_: it, def: self.id.into(), ty }) | |
| 2918 | 2795 | } |
| 2919 | 2796 | } |
| 2920 | 2797 | |
| ... | ... | @@ -2924,27 +2801,28 @@ impl HasVisibility for Const { |
| 2924 | 2801 | } |
| 2925 | 2802 | } |
| 2926 | 2803 | |
| 2927 | pub struct EvaluatedConst { | |
| 2804 | pub struct EvaluatedConst<'db> { | |
| 2928 | 2805 | def: DefWithBodyId, |
| 2929 | const_: hir_ty::Const, | |
| 2806 | const_: hir_ty::next_solver::Const<'db>, | |
| 2807 | ty: Ty<'db>, | |
| 2930 | 2808 | } |
| 2931 | 2809 | |
| 2932 | impl EvaluatedConst { | |
| 2810 | impl<'db> EvaluatedConst<'db> { | |
| 2933 | 2811 | pub fn render(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String { |
| 2934 | 2812 | format!("{}", self.const_.display(db, display_target)) |
| 2935 | 2813 | } |
| 2936 | 2814 | |
| 2937 | pub fn render_debug(&self, db: &dyn HirDatabase) -> Result<String, MirEvalError> { | |
| 2938 | let data = self.const_.data(Interner); | |
| 2939 | if let TyKind::Scalar(s) = data.ty.kind(Interner) | |
| 2940 | && matches!(s, Scalar::Int(_) | Scalar::Uint(_)) | |
| 2941 | && let hir_ty::ConstValue::Concrete(c) = &data.value | |
| 2942 | && let hir_ty::ConstScalar::Bytes(b, _) = &c.interned | |
| 2815 | pub fn render_debug(&self, db: &'db dyn HirDatabase) -> Result<String, MirEvalError<'db>> { | |
| 2816 | let kind = self.const_.kind(); | |
| 2817 | if let ConstKind::Value(c) = kind | |
| 2818 | && let ty = c.ty.kind() | |
| 2819 | && let TyKind::Int(_) | TyKind::Uint(_) = ty | |
| 2943 | 2820 | { |
| 2821 | let b = &c.value.inner().memory; | |
| 2944 | 2822 | let value = u128::from_le_bytes(mir::pad16(b, false)); |
| 2945 | let value_signed = i128::from_le_bytes(mir::pad16(b, matches!(s, Scalar::Int(_)))); | |
| 2823 | let value_signed = i128::from_le_bytes(mir::pad16(b, matches!(ty, TyKind::Int(_)))); | |
| 2946 | 2824 | let mut result = |
| 2947 | if let Scalar::Int(_) = s { value_signed.to_string() } else { value.to_string() }; | |
| 2825 | if let TyKind::Int(_) = ty { value_signed.to_string() } else { value.to_string() }; | |
| 2948 | 2826 | if value >= 10 { |
| 2949 | 2827 | format_to!(result, " ({value:#X})"); |
| 2950 | 2828 | return Ok(result); |
| ... | ... | @@ -2952,7 +2830,7 @@ impl EvaluatedConst { |
| 2952 | 2830 | return Ok(result); |
| 2953 | 2831 | } |
| 2954 | 2832 | } |
| 2955 | mir::render_const_using_debug_impl(db, self.def, &self.const_) | |
| 2833 | mir::render_const_using_debug_impl(db, self.def, self.const_, self.ty) | |
| 2956 | 2834 | } |
| 2957 | 2835 | } |
| 2958 | 2836 | |
| ... | ... | @@ -2990,9 +2868,11 @@ impl Static { |
| 2990 | 2868 | } |
| 2991 | 2869 | |
| 2992 | 2870 | /// Evaluate the static initializer. |
| 2993 | pub fn eval(self, db: &dyn HirDatabase) -> Result<EvaluatedConst, ConstEvalError> { | |
| 2994 | db.const_eval(self.id.into(), Substitution::empty(Interner), None) | |
| 2995 | .map(|it| EvaluatedConst { const_: it, def: self.id.into() }) | |
| 2871 | pub fn eval(self, db: &dyn HirDatabase) -> Result<EvaluatedConst<'_>, ConstEvalError<'_>> { | |
| 2872 | let interner = DbInterner::new_with(db, None, None); | |
| 2873 | let ty = db.value_ty(self.id.into()).unwrap().instantiate_identity(); | |
| 2874 | db.const_eval(self.id.into(), GenericArgs::new_from_iter(interner, []), None) | |
| 2875 | .map(|it| EvaluatedConst { const_: it, def: self.id.into(), ty }) | |
| 2996 | 2876 | } |
| 2997 | 2877 | } |
| 2998 | 2878 | |
| ... | ... | @@ -3113,12 +2993,7 @@ pub struct TypeAlias { |
| 3113 | 2993 | |
| 3114 | 2994 | impl TypeAlias { |
| 3115 | 2995 | pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { |
| 3116 | let subst = db.generic_defaults(self.id.into()); | |
| 3117 | (subst.is_empty() && db.generic_params(self.id.into()).len_type_or_consts() != 0) | |
| 3118 | || subst.iter().any(|ty| match ty.skip_binders().data(Interner) { | |
| 3119 | GenericArgData::Ty(it) => it.is_unknown(), | |
| 3120 | _ => false, | |
| 3121 | }) | |
| 2996 | has_non_default_type_params(db, self.id.into()) | |
| 3122 | 2997 | } |
| 3123 | 2998 | |
| 3124 | 2999 | pub fn module(self, db: &dyn HirDatabase) -> Module { |
| ... | ... | @@ -3129,8 +3004,8 @@ impl TypeAlias { |
| 3129 | 3004 | Type::from_def(db, self.id) |
| 3130 | 3005 | } |
| 3131 | 3006 | |
| 3132 | pub fn ty_placeholders(self, db: &dyn HirDatabase) -> Type<'_> { | |
| 3133 | Type::from_def_placeholders(db, self.id) | |
| 3007 | pub fn ty_params(self, db: &dyn HirDatabase) -> Type<'_> { | |
| 3008 | Type::from_def_params(db, self.id) | |
| 3134 | 3009 | } |
| 3135 | 3010 | |
| 3136 | 3011 | pub fn name(self, db: &dyn HirDatabase) -> Name { |
| ... | ... | @@ -3183,7 +3058,8 @@ impl BuiltinType { |
| 3183 | 3058 | |
| 3184 | 3059 | pub fn ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> { |
| 3185 | 3060 | let core = Crate::core(db).map(|core| core.id).unwrap_or_else(|| db.all_crates()[0]); |
| 3186 | Type::new_for_crate(core, TyBuilder::builtin(self.inner)) | |
| 3061 | let interner = DbInterner::new_with(db, None, None); | |
| 3062 | Type::new_for_crate(core, Ty::from_builtin_type(interner, self.inner)) | |
| 3187 | 3063 | } |
| 3188 | 3064 | |
| 3189 | 3065 | pub fn name(self) -> Name { |
| ... | ... | @@ -3859,14 +3735,13 @@ impl GenericDef { |
| 3859 | 3735 | #[derive(Debug)] |
| 3860 | 3736 | pub struct GenericSubstitution<'db> { |
| 3861 | 3737 | def: GenericDefId, |
| 3862 | subst: Substitution, | |
| 3738 | subst: GenericArgs<'db>, | |
| 3863 | 3739 | env: Arc<TraitEnvironment<'db>>, |
| 3864 | _pd: PhantomCovariantLifetime<'db>, | |
| 3865 | 3740 | } |
| 3866 | 3741 | |
| 3867 | 3742 | impl<'db> GenericSubstitution<'db> { |
| 3868 | fn new(def: GenericDefId, subst: Substitution, env: Arc<TraitEnvironment<'db>>) -> Self { | |
| 3869 | Self { def, subst, env, _pd: PhantomCovariantLifetime::new() } | |
| 3743 | fn new(def: GenericDefId, subst: GenericArgs<'db>, env: Arc<TraitEnvironment<'db>>) -> Self { | |
| 3744 | Self { def, subst, env } | |
| 3870 | 3745 | } |
| 3871 | 3746 | |
| 3872 | 3747 | pub fn types(&self, db: &'db dyn HirDatabase) -> Vec<(Symbol, Type<'db>)> { |
| ... | ... | @@ -3896,26 +3771,23 @@ impl<'db> GenericSubstitution<'db> { |
| 3896 | 3771 | TypeOrConstParamData::TypeParamData(param) => Some(param.name.clone()), |
| 3897 | 3772 | TypeOrConstParamData::ConstParamData(_) => None, |
| 3898 | 3773 | }); |
| 3899 | let parent_len = self.subst.len(Interner) | |
| 3774 | let parent_len = self.subst.len() | |
| 3900 | 3775 | - generics |
| 3901 | 3776 | .iter_type_or_consts() |
| 3902 | 3777 | .filter(|g| matches!(g.1, TypeOrConstParamData::TypeParamData(..))) |
| 3903 | 3778 | .count(); |
| 3904 | let container_params = self.subst.as_slice(Interner)[..parent_len] | |
| 3779 | let container_params = self.subst.as_slice()[..parent_len] | |
| 3905 | 3780 | .iter() |
| 3906 | .filter_map(|param| param.ty(Interner).cloned()) | |
| 3781 | .filter_map(|param| param.ty()) | |
| 3907 | 3782 | .zip(container_type_params.into_iter().flatten()); |
| 3908 | let self_params = self.subst.as_slice(Interner)[parent_len..] | |
| 3783 | let self_params = self.subst.as_slice()[parent_len..] | |
| 3909 | 3784 | .iter() |
| 3910 | .filter_map(|param| param.ty(Interner).cloned()) | |
| 3785 | .filter_map(|param| param.ty()) | |
| 3911 | 3786 | .zip(type_params); |
| 3912 | 3787 | container_params |
| 3913 | 3788 | .chain(self_params) |
| 3914 | 3789 | .filter_map(|(ty, name)| { |
| 3915 | Some(( | |
| 3916 | name?.symbol().clone(), | |
| 3917 | Type { ty, env: self.env.clone(), _pd: PhantomCovariantLifetime::new() }, | |
| 3918 | )) | |
| 3790 | Some((name?.symbol().clone(), Type { ty, env: self.env.clone() })) | |
| 3919 | 3791 | }) |
| 3920 | 3792 | .collect() |
| 3921 | 3793 | } |
| ... | ... | @@ -4021,7 +3893,7 @@ impl Local { |
| 4021 | 3893 | pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> { |
| 4022 | 3894 | let def = self.parent; |
| 4023 | 3895 | let infer = db.infer(def); |
| 4024 | let ty = infer[self.binding_id].clone(); | |
| 3896 | let ty = infer[self.binding_id]; | |
| 4025 | 3897 | Type::new(db, def, ty) |
| 4026 | 3898 | } |
| 4027 | 3899 | |
| ... | ... | @@ -4277,8 +4149,10 @@ impl TypeParam { |
| 4277 | 4149 | |
| 4278 | 4150 | pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> { |
| 4279 | 4151 | let resolver = self.id.parent().resolver(db); |
| 4280 | let ty = TyKind::Placeholder(hir_ty::to_placeholder_idx_no_index(db, self.id.into())) | |
| 4281 | .intern(Interner); | |
| 4152 | let interner = DbInterner::new_with(db, None, None); | |
| 4153 | let index = hir_ty::param_idx(db, self.id.into()).unwrap(); | |
| 4154 | let name = self.name(db).symbol().clone(); | |
| 4155 | let ty = Ty::new_param(interner, self.id, index as u32, name); | |
| 4282 | 4156 | Type::new_with_resolver_inner(db, &resolver, ty) |
| 4283 | 4157 | } |
| 4284 | 4158 | |
| ... | ... | @@ -4298,9 +4172,9 @@ impl TypeParam { |
| 4298 | 4172 | pub fn default(self, db: &dyn HirDatabase) -> Option<Type<'_>> { |
| 4299 | 4173 | let ty = generic_arg_from_param(db, self.id.into())?; |
| 4300 | 4174 | let resolver = self.id.parent().resolver(db); |
| 4301 | match ty.data(Interner) { | |
| 4302 | GenericArgData::Ty(it) if *it.kind(Interner) != TyKind::Error => { | |
| 4303 | Some(Type::new_with_resolver_inner(db, &resolver, it.clone())) | |
| 4175 | match ty { | |
| 4176 | GenericArg::Ty(it) if !it.is_ty_error() => { | |
| 4177 | Some(Type::new_with_resolver_inner(db, &resolver, it)) | |
| 4304 | 4178 | } |
| 4305 | 4179 | _ => None, |
| 4306 | 4180 | } |
| ... | ... | @@ -4361,7 +4235,7 @@ impl ConstParam { |
| 4361 | 4235 | } |
| 4362 | 4236 | |
| 4363 | 4237 | pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> { |
| 4364 | Type::new(db, self.id.parent(), db.const_param_ty(self.id)) | |
| 4238 | Type::new(db, self.id.parent(), db.const_param_ty_ns(self.id)) | |
| 4365 | 4239 | } |
| 4366 | 4240 | |
| 4367 | 4241 | pub fn default( |
| ... | ... | @@ -4370,17 +4244,16 @@ impl ConstParam { |
| 4370 | 4244 | display_target: DisplayTarget, |
| 4371 | 4245 | ) -> Option<ast::ConstArg> { |
| 4372 | 4246 | let arg = generic_arg_from_param(db, self.id.into())?; |
| 4373 | known_const_to_ast(arg.constant(Interner)?, db, display_target) | |
| 4247 | known_const_to_ast(arg.konst()?, db, display_target) | |
| 4374 | 4248 | } |
| 4375 | 4249 | } |
| 4376 | 4250 | |
| 4377 | fn generic_arg_from_param(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option<GenericArg> { | |
| 4251 | fn generic_arg_from_param(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option<GenericArg<'_>> { | |
| 4378 | 4252 | let local_idx = hir_ty::param_idx(db, id)?; |
| 4379 | let defaults = db.generic_defaults(id.parent); | |
| 4380 | let ty = defaults.get(local_idx)?.clone(); | |
| 4381 | let full_subst = TyBuilder::placeholder_subst(db, id.parent); | |
| 4382 | let subst = &full_subst.as_slice(Interner)[..local_idx]; | |
| 4383 | Some(ty.substitute(Interner, &subst)) | |
| 4253 | let defaults = db.generic_defaults_ns(id.parent); | |
| 4254 | let ty = defaults.get(local_idx)?; | |
| 4255 | // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. | |
| 4256 | Some(ty.instantiate_identity()) | |
| 4384 | 4257 | } |
| 4385 | 4258 | |
| 4386 | 4259 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
| ... | ... | @@ -4462,11 +4335,8 @@ impl Impl { |
| 4462 | 4335 | module.id.def_map(db)[module.id.local_id].scope.impls().map(Into::into).collect() |
| 4463 | 4336 | } |
| 4464 | 4337 | |
| 4465 | pub fn all_for_type<'db>( | |
| 4466 | db: &'db dyn HirDatabase, | |
| 4467 | Type { ty, env, _pd: _ }: Type<'db>, | |
| 4468 | ) -> Vec<Impl> { | |
| 4469 | let def_crates = match method_resolution::def_crates(db, &ty, env.krate) { | |
| 4338 | pub fn all_for_type<'db>(db: &'db dyn HirDatabase, Type { ty, env }: Type<'db>) -> Vec<Impl> { | |
| 4339 | let def_crates = match method_resolution::def_crates(db, ty, env.krate) { | |
| 4470 | 4340 | Some(def_crates) => def_crates, |
| 4471 | 4341 | None => return Vec::new(), |
| 4472 | 4342 | }; |
| ... | ... | @@ -4474,10 +4344,10 @@ impl Impl { |
| 4474 | 4344 | let filter = |impl_def: &Impl| { |
| 4475 | 4345 | let self_ty = impl_def.self_ty(db); |
| 4476 | 4346 | let rref = self_ty.remove_ref(); |
| 4477 | ty.equals_ctor(rref.as_ref().map_or(&self_ty.ty, |it| &it.ty)) | |
| 4347 | ty.equals_ctor(rref.as_ref().map_or(self_ty.ty, |it| it.ty)) | |
| 4478 | 4348 | }; |
| 4479 | 4349 | |
| 4480 | let fp = TyFingerprint::for_inherent_impl(&ty); | |
| 4350 | let fp = TyFingerprint::for_inherent_impl(ty); | |
| 4481 | 4351 | let fp = match fp { |
| 4482 | 4352 | Some(fp) => fp, |
| 4483 | 4353 | None => return Vec::new(), |
| ... | ... | @@ -4487,7 +4357,7 @@ impl Impl { |
| 4487 | 4357 | def_crates.iter().for_each(|&id| { |
| 4488 | 4358 | all.extend( |
| 4489 | 4359 | db.inherent_impls_in_crate(id) |
| 4490 | .for_self_ty(&ty) | |
| 4360 | .for_self_ty(ty) | |
| 4491 | 4361 | .iter() |
| 4492 | 4362 | .cloned() |
| 4493 | 4363 | .map(Self::from) |
| ... | ... | @@ -4508,11 +4378,10 @@ impl Impl { |
| 4508 | 4378 | ); |
| 4509 | 4379 | } |
| 4510 | 4380 | |
| 4511 | if let Some(block) = ty.adt_id(Interner).and_then(|def| def.0.module(db).containing_block()) | |
| 4512 | { | |
| 4381 | if let Some(block) = ty.as_adt().and_then(|(def, _)| def.module(db).containing_block()) { | |
| 4513 | 4382 | if let Some(inherent_impls) = db.inherent_impls_in_block(block) { |
| 4514 | 4383 | all.extend( |
| 4515 | inherent_impls.for_self_ty(&ty).iter().cloned().map(Self::from).filter(filter), | |
| 4384 | inherent_impls.for_self_ty(ty).iter().cloned().map(Self::from).filter(filter), | |
| 4516 | 4385 | ); |
| 4517 | 4386 | } |
| 4518 | 4387 | if let Some(trait_impls) = db.trait_impls_in_block(block) { |
| ... | ... | @@ -4558,10 +4427,8 @@ impl Impl { |
| 4558 | 4427 | |
| 4559 | 4428 | pub fn self_ty(self, db: &dyn HirDatabase) -> Type<'_> { |
| 4560 | 4429 | let resolver = self.id.resolver(db); |
| 4561 | let interner = DbInterner::new_with(db, Some(resolver.krate()), None); | |
| 4562 | let substs = TyBuilder::placeholder_subst(db, self.id); | |
| 4563 | let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 4564 | let ty = db.impl_self_ty(self.id).instantiate(interner, args).to_chalk(interner); | |
| 4430 | // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. | |
| 4431 | let ty = db.impl_self_ty(self.id).instantiate_identity(); | |
| 4565 | 4432 | Type::new_with_resolver_inner(db, &resolver, ty) |
| 4566 | 4433 | } |
| 4567 | 4434 | |
| ... | ... | @@ -4623,7 +4490,6 @@ impl Impl { |
| 4623 | 4490 | pub struct TraitRef<'db> { |
| 4624 | 4491 | env: Arc<TraitEnvironment<'db>>, |
| 4625 | 4492 | trait_ref: hir_ty::next_solver::TraitRef<'db>, |
| 4626 | _pd: PhantomCovariantLifetime<'db>, | |
| 4627 | 4493 | } |
| 4628 | 4494 | |
| 4629 | 4495 | impl<'db> TraitRef<'db> { |
| ... | ... | @@ -4635,7 +4501,7 @@ impl<'db> TraitRef<'db> { |
| 4635 | 4501 | let env = resolver |
| 4636 | 4502 | .generic_def() |
| 4637 | 4503 | .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d)); |
| 4638 | TraitRef { env, trait_ref, _pd: PhantomCovariantLifetime::new() } | |
| 4504 | TraitRef { env, trait_ref } | |
| 4639 | 4505 | } |
| 4640 | 4506 | |
| 4641 | 4507 | pub fn trait_(&self) -> Trait { |
| ... | ... | @@ -4644,57 +4510,51 @@ impl<'db> TraitRef<'db> { |
| 4644 | 4510 | |
| 4645 | 4511 | pub fn self_ty(&self) -> TypeNs<'_> { |
| 4646 | 4512 | let ty = self.trait_ref.self_ty(); |
| 4647 | TypeNs { env: self.env.clone(), ty, _pd: PhantomCovariantLifetime::new() } | |
| 4513 | TypeNs { env: self.env.clone(), ty } | |
| 4648 | 4514 | } |
| 4649 | 4515 | |
| 4650 | 4516 | /// Returns `idx`-th argument of this trait reference if it is a type argument. Note that the |
| 4651 | 4517 | /// first argument is the `Self` type. |
| 4652 | 4518 | pub fn get_type_argument(&self, idx: usize) -> Option<TypeNs<'db>> { |
| 4653 | self.trait_ref.args.as_slice().get(idx).and_then(|arg| arg.ty()).map(|ty| TypeNs { | |
| 4654 | env: self.env.clone(), | |
| 4655 | ty, | |
| 4656 | _pd: PhantomCovariantLifetime::new(), | |
| 4657 | }) | |
| 4519 | self.trait_ref | |
| 4520 | .args | |
| 4521 | .as_slice() | |
| 4522 | .get(idx) | |
| 4523 | .and_then(|arg| arg.ty()) | |
| 4524 | .map(|ty| TypeNs { env: self.env.clone(), ty }) | |
| 4658 | 4525 | } |
| 4659 | 4526 | } |
| 4660 | 4527 | |
| 4661 | 4528 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] |
| 4662 | pub struct Closure { | |
| 4663 | id: ClosureId, | |
| 4664 | subst: Substitution, | |
| 4529 | pub struct Closure<'db> { | |
| 4530 | id: InternedClosureId, | |
| 4531 | subst: GenericArgs<'db>, | |
| 4665 | 4532 | } |
| 4666 | 4533 | |
| 4667 | impl From<Closure> for ClosureId { | |
| 4668 | fn from(value: Closure) -> Self { | |
| 4669 | value.id | |
| 4670 | } | |
| 4671 | } | |
| 4672 | ||
| 4673 | impl Closure { | |
| 4674 | fn as_ty(self) -> Ty { | |
| 4675 | TyKind::Closure(self.id, self.subst).intern(Interner) | |
| 4534 | impl<'db> Closure<'db> { | |
| 4535 | fn as_ty(&self, db: &'db dyn HirDatabase) -> Ty<'db> { | |
| 4536 | let interner = DbInterner::new_with(db, None, None); | |
| 4537 | Ty::new_closure(interner, self.id.into(), self.subst) | |
| 4676 | 4538 | } |
| 4677 | 4539 | |
| 4678 | 4540 | pub fn display_with_id(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String { |
| 4679 | self.clone() | |
| 4680 | .as_ty() | |
| 4541 | self.as_ty(db) | |
| 4681 | 4542 | .display(db, display_target) |
| 4682 | 4543 | .with_closure_style(ClosureStyle::ClosureWithId) |
| 4683 | 4544 | .to_string() |
| 4684 | 4545 | } |
| 4685 | 4546 | |
| 4686 | 4547 | pub fn display_with_impl(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String { |
| 4687 | self.clone() | |
| 4688 | .as_ty() | |
| 4548 | self.as_ty(db) | |
| 4689 | 4549 | .display(db, display_target) |
| 4690 | 4550 | .with_closure_style(ClosureStyle::ImplFn) |
| 4691 | 4551 | .to_string() |
| 4692 | 4552 | } |
| 4693 | 4553 | |
| 4694 | pub fn captured_items(&self, db: &dyn HirDatabase) -> Vec<ClosureCapture> { | |
| 4695 | let owner = db.lookup_intern_closure((self.id).into()).0; | |
| 4696 | let infer = &db.infer(owner); | |
| 4697 | let info = infer.closure_info(&self.id); | |
| 4554 | pub fn captured_items(&self, db: &'db dyn HirDatabase) -> Vec<ClosureCapture<'db>> { | |
| 4555 | let owner = db.lookup_intern_closure(self.id).0; | |
| 4556 | let infer = db.infer(owner); | |
| 4557 | let info = infer.closure_info(self.id); | |
| 4698 | 4558 | info.0 |
| 4699 | 4559 | .iter() |
| 4700 | 4560 | .cloned() |
| ... | ... | @@ -4702,36 +4562,33 @@ impl Closure { |
| 4702 | 4562 | .collect() |
| 4703 | 4563 | } |
| 4704 | 4564 | |
| 4705 | pub fn capture_types<'db>(&self, db: &'db dyn HirDatabase) -> Vec<Type<'db>> { | |
| 4706 | let owner = db.lookup_intern_closure((self.id).into()).0; | |
| 4707 | let infer = &db.infer(owner); | |
| 4708 | let (captures, _) = infer.closure_info(&self.id); | |
| 4565 | pub fn capture_types(&self, db: &'db dyn HirDatabase) -> Vec<Type<'db>> { | |
| 4566 | let owner = db.lookup_intern_closure(self.id).0; | |
| 4567 | let infer = db.infer(owner); | |
| 4568 | let (captures, _) = infer.closure_info(self.id); | |
| 4569 | let env = db.trait_environment_for_body(owner); | |
| 4709 | 4570 | captures |
| 4710 | 4571 | .iter() |
| 4711 | .map(|capture| Type { | |
| 4712 | env: db.trait_environment_for_body(owner), | |
| 4713 | ty: capture.ty(db, &self.subst), | |
| 4714 | _pd: PhantomCovariantLifetime::new(), | |
| 4715 | }) | |
| 4572 | .map(|capture| Type { env: env.clone(), ty: capture.ty(db, self.subst) }) | |
| 4716 | 4573 | .collect() |
| 4717 | 4574 | } |
| 4718 | 4575 | |
| 4719 | 4576 | pub fn fn_trait(&self, db: &dyn HirDatabase) -> FnTrait { |
| 4720 | let owner = db.lookup_intern_closure((self.id).into()).0; | |
| 4721 | let infer = &db.infer(owner); | |
| 4722 | let info = infer.closure_info(&self.id); | |
| 4577 | let owner = db.lookup_intern_closure(self.id).0; | |
| 4578 | let infer = db.infer(owner); | |
| 4579 | let info = infer.closure_info(self.id); | |
| 4723 | 4580 | info.1 |
| 4724 | 4581 | } |
| 4725 | 4582 | } |
| 4726 | 4583 | |
| 4727 | 4584 | #[derive(Clone, Debug, PartialEq, Eq)] |
| 4728 | pub struct ClosureCapture { | |
| 4585 | pub struct ClosureCapture<'db> { | |
| 4729 | 4586 | owner: DefWithBodyId, |
| 4730 | closure: ClosureId, | |
| 4731 | capture: hir_ty::CapturedItem, | |
| 4587 | closure: InternedClosureId, | |
| 4588 | capture: hir_ty::CapturedItem<'db>, | |
| 4732 | 4589 | } |
| 4733 | 4590 | |
| 4734 | impl ClosureCapture { | |
| 4591 | impl<'db> ClosureCapture<'db> { | |
| 4735 | 4592 | pub fn local(&self) -> Local { |
| 4736 | 4593 | Local { parent: self.owner, binding_id: self.capture.local() } |
| 4737 | 4594 | } |
| ... | ... | @@ -4845,15 +4702,14 @@ impl CaptureUsageSource { |
| 4845 | 4702 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
| 4846 | 4703 | pub struct Type<'db> { |
| 4847 | 4704 | env: Arc<TraitEnvironment<'db>>, |
| 4848 | ty: Ty, | |
| 4849 | _pd: PhantomCovariantLifetime<'db>, | |
| 4705 | ty: Ty<'db>, | |
| 4850 | 4706 | } |
| 4851 | 4707 | |
| 4852 | 4708 | impl<'db> Type<'db> { |
| 4853 | 4709 | pub(crate) fn new_with_resolver( |
| 4854 | 4710 | db: &'db dyn HirDatabase, |
| 4855 | 4711 | resolver: &Resolver<'_>, |
| 4856 | ty: Ty, | |
| 4712 | ty: Ty<'db>, | |
| 4857 | 4713 | ) -> Self { |
| 4858 | 4714 | Type::new_with_resolver_inner(db, resolver, ty) |
| 4859 | 4715 | } |
| ... | ... | @@ -4861,275 +4717,252 @@ impl<'db> Type<'db> { |
| 4861 | 4717 | pub(crate) fn new_with_resolver_inner( |
| 4862 | 4718 | db: &'db dyn HirDatabase, |
| 4863 | 4719 | resolver: &Resolver<'_>, |
| 4864 | ty: Ty, | |
| 4720 | ty: Ty<'db>, | |
| 4865 | 4721 | ) -> Self { |
| 4866 | 4722 | let environment = resolver |
| 4867 | 4723 | .generic_def() |
| 4868 | 4724 | .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d)); |
| 4869 | Type { env: environment, ty, _pd: PhantomCovariantLifetime::new() } | |
| 4725 | Type { env: environment, ty } | |
| 4870 | 4726 | } |
| 4871 | 4727 | |
| 4872 | pub(crate) fn new_for_crate(krate: base_db::Crate, ty: Ty) -> Self { | |
| 4873 | Type { env: TraitEnvironment::empty(krate), ty, _pd: PhantomCovariantLifetime::new() } | |
| 4728 | pub(crate) fn new_for_crate(krate: base_db::Crate, ty: Ty<'db>) -> Self { | |
| 4729 | Type { env: TraitEnvironment::empty(krate), ty } | |
| 4874 | 4730 | } |
| 4875 | 4731 | |
| 4876 | fn new(db: &'db dyn HirDatabase, lexical_env: impl HasResolver, ty: Ty) -> Self { | |
| 4732 | fn new(db: &'db dyn HirDatabase, lexical_env: impl HasResolver, ty: Ty<'db>) -> Self { | |
| 4877 | 4733 | let resolver = lexical_env.resolver(db); |
| 4878 | 4734 | let environment = resolver |
| 4879 | 4735 | .generic_def() |
| 4880 | 4736 | .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d)); |
| 4881 | Type { env: environment, ty, _pd: PhantomCovariantLifetime::new() } | |
| 4737 | Type { env: environment, ty } | |
| 4882 | 4738 | } |
| 4883 | 4739 | |
| 4884 | 4740 | fn from_def(db: &'db dyn HirDatabase, def: impl Into<TyDefId> + HasResolver) -> Self { |
| 4885 | 4741 | let interner = DbInterner::new_with(db, None, None); |
| 4886 | 4742 | let ty = db.ty(def.into()); |
| 4887 | let substs = TyBuilder::unknown_subst( | |
| 4888 | db, | |
| 4889 | match def.into() { | |
| 4890 | TyDefId::AdtId(it) => GenericDefId::AdtId(it), | |
| 4891 | TyDefId::TypeAliasId(it) => GenericDefId::TypeAliasId(it), | |
| 4892 | TyDefId::BuiltinType(_) => { | |
| 4893 | return Type::new(db, def, ty.skip_binder().to_chalk(interner)); | |
| 4894 | } | |
| 4895 | }, | |
| 4896 | ); | |
| 4897 | let args: hir_ty::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 4898 | Type::new(db, def, ty.instantiate(interner, args).to_chalk(interner)) | |
| 4743 | let def = match def.into() { | |
| 4744 | TyDefId::AdtId(it) => GenericDefId::AdtId(it), | |
| 4745 | TyDefId::TypeAliasId(it) => GenericDefId::TypeAliasId(it), | |
| 4746 | TyDefId::BuiltinType(_) => { | |
| 4747 | return Type::new(db, def, ty.skip_binder()); | |
| 4748 | } | |
| 4749 | }; | |
| 4750 | let args = GenericArgs::error_for_item(interner, def.into()); | |
| 4751 | Type::new(db, def, ty.instantiate(interner, args)) | |
| 4899 | 4752 | } |
| 4900 | 4753 | |
| 4901 | fn from_def_placeholders( | |
| 4902 | db: &'db dyn HirDatabase, | |
| 4903 | def: impl Into<TyDefId> + HasResolver, | |
| 4904 | ) -> Self { | |
| 4905 | let interner = DbInterner::new_with(db, None, None); | |
| 4754 | // FIXME: We shouldn't leak `TyKind::Param`s. | |
| 4755 | fn from_def_params(db: &'db dyn HirDatabase, def: impl Into<TyDefId> + HasResolver) -> Self { | |
| 4906 | 4756 | let ty = db.ty(def.into()); |
| 4907 | let substs = TyBuilder::placeholder_subst( | |
| 4908 | db, | |
| 4909 | match def.into() { | |
| 4910 | TyDefId::AdtId(it) => GenericDefId::AdtId(it), | |
| 4911 | TyDefId::TypeAliasId(it) => GenericDefId::TypeAliasId(it), | |
| 4912 | TyDefId::BuiltinType(_) => { | |
| 4913 | return Type::new(db, def, ty.skip_binder().to_chalk(interner)); | |
| 4914 | } | |
| 4915 | }, | |
| 4916 | ); | |
| 4917 | let args: hir_ty::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 4918 | Type::new(db, def, ty.instantiate(interner, args).to_chalk(interner)) | |
| 4757 | Type::new(db, def, ty.instantiate_identity()) | |
| 4919 | 4758 | } |
| 4920 | 4759 | |
| 4921 | 4760 | fn from_value_def( |
| 4922 | 4761 | db: &'db dyn HirDatabase, |
| 4923 | 4762 | def: impl Into<ValueTyDefId> + HasResolver, |
| 4924 | 4763 | ) -> Self { |
| 4764 | let interner = DbInterner::new_with(db, None, None); | |
| 4925 | 4765 | let Some(ty) = db.value_ty(def.into()) else { |
| 4926 | return Type::new(db, def, TyKind::Error.intern(Interner)); | |
| 4766 | return Type::new(db, def, Ty::new_error(interner, ErrorGuaranteed)); | |
| 4927 | 4767 | }; |
| 4928 | let interner = DbInterner::new_with(db, None, None); | |
| 4929 | let substs = TyBuilder::unknown_subst( | |
| 4930 | db, | |
| 4931 | match def.into() { | |
| 4932 | ValueTyDefId::ConstId(it) => GenericDefId::ConstId(it), | |
| 4933 | ValueTyDefId::FunctionId(it) => GenericDefId::FunctionId(it), | |
| 4934 | ValueTyDefId::StructId(it) => GenericDefId::AdtId(AdtId::StructId(it)), | |
| 4935 | ValueTyDefId::UnionId(it) => GenericDefId::AdtId(AdtId::UnionId(it)), | |
| 4936 | ValueTyDefId::EnumVariantId(it) => { | |
| 4937 | GenericDefId::AdtId(AdtId::EnumId(it.lookup(db).parent)) | |
| 4938 | } | |
| 4939 | ValueTyDefId::StaticId(_) => { | |
| 4940 | return Type::new(db, def, ty.skip_binder().to_chalk(interner)); | |
| 4941 | } | |
| 4942 | }, | |
| 4943 | ); | |
| 4944 | let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 4945 | Type::new(db, def, ty.instantiate(interner, args).to_chalk(interner)) | |
| 4768 | let def = match def.into() { | |
| 4769 | ValueTyDefId::ConstId(it) => GenericDefId::ConstId(it), | |
| 4770 | ValueTyDefId::FunctionId(it) => GenericDefId::FunctionId(it), | |
| 4771 | ValueTyDefId::StructId(it) => GenericDefId::AdtId(AdtId::StructId(it)), | |
| 4772 | ValueTyDefId::UnionId(it) => GenericDefId::AdtId(AdtId::UnionId(it)), | |
| 4773 | ValueTyDefId::EnumVariantId(it) => { | |
| 4774 | GenericDefId::AdtId(AdtId::EnumId(it.lookup(db).parent)) | |
| 4775 | } | |
| 4776 | ValueTyDefId::StaticId(_) => { | |
| 4777 | return Type::new(db, def, ty.skip_binder()); | |
| 4778 | } | |
| 4779 | }; | |
| 4780 | let args = GenericArgs::error_for_item(interner, def.into()); | |
| 4781 | Type::new(db, def, ty.instantiate(interner, args)) | |
| 4946 | 4782 | } |
| 4947 | 4783 | |
| 4948 | 4784 | pub fn new_slice(ty: Self) -> Self { |
| 4949 | Type { env: ty.env, ty: TyBuilder::slice(ty.ty), _pd: PhantomCovariantLifetime::new() } | |
| 4785 | let interner = DbInterner::conjure(); | |
| 4786 | Type { env: ty.env, ty: Ty::new_slice(interner, ty.ty) } | |
| 4950 | 4787 | } |
| 4951 | 4788 | |
| 4952 | 4789 | pub fn new_tuple(krate: base_db::Crate, tys: &[Self]) -> Self { |
| 4953 | let tys = tys.iter().map(|it| it.ty.clone()); | |
| 4954 | Type { | |
| 4955 | env: TraitEnvironment::empty(krate), | |
| 4956 | ty: TyBuilder::tuple_with(tys), | |
| 4957 | _pd: PhantomCovariantLifetime::new(), | |
| 4958 | } | |
| 4790 | let tys = tys.iter().map(|it| it.ty); | |
| 4791 | let interner = DbInterner::conjure(); | |
| 4792 | Type { env: TraitEnvironment::empty(krate), ty: Ty::new_tup_from_iter(interner, tys) } | |
| 4959 | 4793 | } |
| 4960 | 4794 | |
| 4961 | 4795 | pub fn is_unit(&self) -> bool { |
| 4962 | matches!(self.ty.kind(Interner), TyKind::Tuple(0, ..)) | |
| 4796 | self.ty.is_unit() | |
| 4963 | 4797 | } |
| 4964 | 4798 | |
| 4965 | 4799 | pub fn is_bool(&self) -> bool { |
| 4966 | matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Bool)) | |
| 4800 | matches!(self.ty.kind(), TyKind::Bool) | |
| 4967 | 4801 | } |
| 4968 | 4802 | |
| 4969 | 4803 | pub fn is_str(&self) -> bool { |
| 4970 | matches!(self.ty.kind(Interner), TyKind::Str) | |
| 4804 | matches!(self.ty.kind(), TyKind::Str) | |
| 4971 | 4805 | } |
| 4972 | 4806 | |
| 4973 | 4807 | pub fn is_never(&self) -> bool { |
| 4974 | matches!(self.ty.kind(Interner), TyKind::Never) | |
| 4808 | matches!(self.ty.kind(), TyKind::Never) | |
| 4975 | 4809 | } |
| 4976 | 4810 | |
| 4977 | 4811 | pub fn is_mutable_reference(&self) -> bool { |
| 4978 | matches!(self.ty.kind(Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..)) | |
| 4812 | matches!(self.ty.kind(), TyKind::Ref(.., hir_ty::next_solver::Mutability::Mut)) | |
| 4979 | 4813 | } |
| 4980 | 4814 | |
| 4981 | 4815 | pub fn is_reference(&self) -> bool { |
| 4982 | matches!(self.ty.kind(Interner), TyKind::Ref(..)) | |
| 4816 | matches!(self.ty.kind(), TyKind::Ref(..)) | |
| 4983 | 4817 | } |
| 4984 | 4818 | |
| 4985 | 4819 | pub fn contains_reference(&self, db: &'db dyn HirDatabase) -> bool { |
| 4986 | return go(db, &self.ty); | |
| 4820 | let interner = DbInterner::new_with(db, None, None); | |
| 4821 | return self.ty.visit_with(&mut Visitor { interner }).is_break(); | |
| 4987 | 4822 | |
| 4988 | 4823 | fn is_phantom_data(db: &dyn HirDatabase, adt_id: AdtId) -> bool { |
| 4989 | 4824 | match adt_id { |
| 4990 | hir_def::AdtId::StructId(s) => { | |
| 4825 | AdtId::StructId(s) => { | |
| 4991 | 4826 | let flags = db.struct_signature(s).flags; |
| 4992 | 4827 | flags.contains(StructFlags::IS_PHANTOM_DATA) |
| 4993 | 4828 | } |
| 4994 | hir_def::AdtId::UnionId(_) => false, | |
| 4995 | hir_def::AdtId::EnumId(_) => false, | |
| 4829 | AdtId::UnionId(_) | AdtId::EnumId(_) => false, | |
| 4996 | 4830 | } |
| 4997 | 4831 | } |
| 4998 | 4832 | |
| 4999 | fn go(db: &dyn HirDatabase, ty: &Ty) -> bool { | |
| 5000 | match ty.kind(Interner) { | |
| 5001 | // Reference itself | |
| 5002 | TyKind::Ref(_, _, _) => true, | |
| 4833 | struct Visitor<'db> { | |
| 4834 | interner: DbInterner<'db>, | |
| 4835 | } | |
| 5003 | 4836 | |
| 5004 | // For non-phantom_data adts we check variants/fields as well as generic parameters | |
| 5005 | TyKind::Adt(adt_id, substitution) if !is_phantom_data(db, adt_id.0) => { | |
| 5006 | let _variant_id_to_fields = |id: VariantId| { | |
| 5007 | let variant_data = &id.fields(db); | |
| 5008 | if variant_data.fields().is_empty() { | |
| 5009 | vec![] | |
| 5010 | } else { | |
| 5011 | let field_types = db.field_types(id); | |
| 5012 | variant_data | |
| 5013 | .fields() | |
| 5014 | .iter() | |
| 5015 | .map(|(idx, _)| { | |
| 5016 | field_types[idx].clone().substitute(Interner, substitution) | |
| 5017 | }) | |
| 5018 | .filter(|it| !it.contains_unknown()) | |
| 5019 | .collect() | |
| 5020 | } | |
| 5021 | }; | |
| 5022 | let variant_id_to_fields = |_: VariantId| vec![]; | |
| 4837 | impl<'db> TypeVisitor<DbInterner<'db>> for Visitor<'db> { | |
| 4838 | type Result = ControlFlow<()>; | |
| 5023 | 4839 | |
| 5024 | let variants = match adt_id.0 { | |
| 5025 | hir_def::AdtId::StructId(id) => { | |
| 5026 | vec![variant_id_to_fields(id.into())] | |
| 5027 | } | |
| 5028 | hir_def::AdtId::EnumId(id) => id | |
| 5029 | .enum_variants(db) | |
| 5030 | .variants | |
| 5031 | .iter() | |
| 5032 | .map(|&(variant_id, _, _)| variant_id_to_fields(variant_id.into())) | |
| 5033 | .collect(), | |
| 5034 | hir_def::AdtId::UnionId(id) => { | |
| 5035 | vec![variant_id_to_fields(id.into())] | |
| 5036 | } | |
| 5037 | }; | |
| 4840 | fn visit_ty(&mut self, ty: Ty<'db>) -> Self::Result { | |
| 4841 | match ty.kind() { | |
| 4842 | // Reference itself | |
| 4843 | TyKind::Ref(..) => ControlFlow::Break(()), | |
| 5038 | 4844 | |
| 5039 | variants | |
| 5040 | .into_iter() | |
| 5041 | .flat_map(|variant| variant.into_iter()) | |
| 5042 | .any(|ty| go(db, &ty)) | |
| 5043 | || substitution | |
| 5044 | .iter(Interner) | |
| 5045 | .filter_map(|x| x.ty(Interner)) | |
| 5046 | .any(|ty| go(db, ty)) | |
| 5047 | } | |
| 5048 | // And for `PhantomData<T>`, we check `T`. | |
| 5049 | TyKind::Adt(_, substitution) | |
| 5050 | | TyKind::Tuple(_, substitution) | |
| 5051 | | TyKind::OpaqueType(_, substitution) | |
| 5052 | | TyKind::AssociatedType(_, substitution) | |
| 5053 | | TyKind::Alias(AliasTy::Projection(ProjectionTy { substitution, .. })) | |
| 5054 | | TyKind::FnDef(_, substitution) => { | |
| 5055 | substitution.iter(Interner).filter_map(|x| x.ty(Interner)).any(|ty| go(db, ty)) | |
| 5056 | } | |
| 4845 | // For non-phantom_data adts we check variants/fields as well as generic parameters | |
| 4846 | TyKind::Adt(adt_def, args) | |
| 4847 | if !is_phantom_data(self.interner.db(), adt_def.def_id().0) => | |
| 4848 | { | |
| 4849 | let _variant_id_to_fields = |id: VariantId| { | |
| 4850 | let variant_data = &id.fields(self.interner.db()); | |
| 4851 | if variant_data.fields().is_empty() { | |
| 4852 | vec![] | |
| 4853 | } else { | |
| 4854 | let field_types = self.interner.db().field_types_ns(id); | |
| 4855 | variant_data | |
| 4856 | .fields() | |
| 4857 | .iter() | |
| 4858 | .map(|(idx, _)| { | |
| 4859 | field_types[idx].instantiate(self.interner, args) | |
| 4860 | }) | |
| 4861 | .filter(|it| !it.references_non_lt_error()) | |
| 4862 | .collect() | |
| 4863 | } | |
| 4864 | }; | |
| 4865 | let variant_id_to_fields = |_: VariantId| vec![]; | |
| 5057 | 4866 | |
| 5058 | // For `[T]` or `*T` we check `T` | |
| 5059 | TyKind::Array(ty, _) | TyKind::Slice(ty) | TyKind::Raw(_, ty) => go(db, ty), | |
| 4867 | let variants: Vec<Vec<Ty<'db>>> = match adt_def.def_id().0 { | |
| 4868 | AdtId::StructId(id) => { | |
| 4869 | vec![variant_id_to_fields(id.into())] | |
| 4870 | } | |
| 4871 | AdtId::EnumId(id) => id | |
| 4872 | .enum_variants(self.interner.db()) | |
| 4873 | .variants | |
| 4874 | .iter() | |
| 4875 | .map(|&(variant_id, _, _)| variant_id_to_fields(variant_id.into())) | |
| 4876 | .collect(), | |
| 4877 | AdtId::UnionId(id) => { | |
| 4878 | vec![variant_id_to_fields(id.into())] | |
| 4879 | } | |
| 4880 | }; | |
| 5060 | 4881 | |
| 5061 | // Consider everything else as not reference | |
| 5062 | _ => false, | |
| 4882 | variants | |
| 4883 | .into_iter() | |
| 4884 | .flat_map(|variant| variant.into_iter()) | |
| 4885 | .try_for_each(|ty| ty.visit_with(self))?; | |
| 4886 | args.visit_with(self) | |
| 4887 | } | |
| 4888 | // And for `PhantomData<T>`, we check `T`. | |
| 4889 | _ => ty.super_visit_with(self), | |
| 4890 | } | |
| 5063 | 4891 | } |
| 5064 | 4892 | } |
| 5065 | 4893 | } |
| 5066 | 4894 | |
| 5067 | 4895 | pub fn as_reference(&self) -> Option<(Type<'db>, Mutability)> { |
| 5068 | let (ty, _lt, m) = self.ty.as_reference()?; | |
| 5069 | let m = Mutability::from_mutable(matches!(m, hir_ty::Mutability::Mut)); | |
| 5070 | Some((self.derived(ty.clone()), m)) | |
| 4896 | let TyKind::Ref(_lt, ty, m) = self.ty.kind() else { return None }; | |
| 4897 | let m = Mutability::from_mutable(matches!(m, hir_ty::next_solver::Mutability::Mut)); | |
| 4898 | Some((self.derived(ty), m)) | |
| 5071 | 4899 | } |
| 5072 | 4900 | |
| 5073 | 4901 | pub fn add_reference(&self, mutability: Mutability) -> Self { |
| 4902 | let interner = DbInterner::conjure(); | |
| 5074 | 4903 | let ty_mutability = match mutability { |
| 5075 | Mutability::Shared => hir_ty::Mutability::Not, | |
| 5076 | Mutability::Mut => hir_ty::Mutability::Mut, | |
| 4904 | Mutability::Shared => hir_ty::next_solver::Mutability::Not, | |
| 4905 | Mutability::Mut => hir_ty::next_solver::Mutability::Mut, | |
| 5077 | 4906 | }; |
| 5078 | self.derived(TyKind::Ref(ty_mutability, error_lifetime(), self.ty.clone()).intern(Interner)) | |
| 4907 | self.derived(Ty::new_ref(interner, Region::error(interner), self.ty, ty_mutability)) | |
| 5079 | 4908 | } |
| 5080 | 4909 | |
| 5081 | 4910 | pub fn is_slice(&self) -> bool { |
| 5082 | matches!(self.ty.kind(Interner), TyKind::Slice(..)) | |
| 4911 | matches!(self.ty.kind(), TyKind::Slice(..)) | |
| 5083 | 4912 | } |
| 5084 | 4913 | |
| 5085 | 4914 | pub fn is_usize(&self) -> bool { |
| 5086 | matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize))) | |
| 4915 | matches!(self.ty.kind(), TyKind::Uint(rustc_type_ir::UintTy::Usize)) | |
| 5087 | 4916 | } |
| 5088 | 4917 | |
| 5089 | 4918 | pub fn is_float(&self) -> bool { |
| 5090 | matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Float(_))) | |
| 4919 | matches!(self.ty.kind(), TyKind::Float(_)) | |
| 5091 | 4920 | } |
| 5092 | 4921 | |
| 5093 | 4922 | pub fn is_char(&self) -> bool { |
| 5094 | matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Char)) | |
| 4923 | matches!(self.ty.kind(), TyKind::Char) | |
| 5095 | 4924 | } |
| 5096 | 4925 | |
| 5097 | 4926 | pub fn is_int_or_uint(&self) -> bool { |
| 5098 | matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_))) | |
| 4927 | matches!(self.ty.kind(), TyKind::Int(_) | TyKind::Uint(_)) | |
| 5099 | 4928 | } |
| 5100 | 4929 | |
| 5101 | 4930 | pub fn is_scalar(&self) -> bool { |
| 5102 | matches!(self.ty.kind(Interner), TyKind::Scalar(_)) | |
| 4931 | matches!( | |
| 4932 | self.ty.kind(), | |
| 4933 | TyKind::Bool | TyKind::Char | TyKind::Int(_) | TyKind::Uint(_) | TyKind::Float(_) | |
| 4934 | ) | |
| 5103 | 4935 | } |
| 5104 | 4936 | |
| 5105 | 4937 | pub fn is_tuple(&self) -> bool { |
| 5106 | matches!(self.ty.kind(Interner), TyKind::Tuple(..)) | |
| 4938 | matches!(self.ty.kind(), TyKind::Tuple(..)) | |
| 5107 | 4939 | } |
| 5108 | 4940 | |
| 5109 | 4941 | pub fn remove_ref(&self) -> Option<Type<'db>> { |
| 5110 | match &self.ty.kind(Interner) { | |
| 5111 | TyKind::Ref(.., ty) => Some(self.derived(ty.clone())), | |
| 4942 | match self.ty.kind() { | |
| 4943 | TyKind::Ref(_, ty, _) => Some(self.derived(ty)), | |
| 5112 | 4944 | _ => None, |
| 5113 | 4945 | } |
| 5114 | 4946 | } |
| 5115 | 4947 | |
| 5116 | 4948 | pub fn as_slice(&self) -> Option<Type<'db>> { |
| 5117 | match &self.ty.kind(Interner) { | |
| 5118 | TyKind::Slice(ty) => Some(self.derived(ty.clone())), | |
| 4949 | match self.ty.kind() { | |
| 4950 | TyKind::Slice(ty) => Some(self.derived(ty)), | |
| 5119 | 4951 | _ => None, |
| 5120 | 4952 | } |
| 5121 | 4953 | } |
| 5122 | 4954 | |
| 5123 | 4955 | pub fn strip_references(&self) -> Self { |
| 5124 | self.derived(self.ty.strip_references().clone()) | |
| 4956 | self.derived(self.ty.strip_references()) | |
| 5125 | 4957 | } |
| 5126 | 4958 | |
| 4959 | // FIXME: This is the same as `remove_ref()`, remove one of these methods. | |
| 5127 | 4960 | pub fn strip_reference(&self) -> Self { |
| 5128 | self.derived(self.ty.strip_reference().clone()) | |
| 4961 | self.derived(self.ty.strip_reference()) | |
| 5129 | 4962 | } |
| 5130 | 4963 | |
| 5131 | 4964 | pub fn is_unknown(&self) -> bool { |
| 5132 | self.ty.is_unknown() | |
| 4965 | self.ty.is_ty_error() | |
| 5133 | 4966 | } |
| 5134 | 4967 | |
| 5135 | 4968 | /// Checks that particular type `ty` implements `std::future::IntoFuture` or |
| ... | ... | @@ -5145,9 +4978,7 @@ impl<'db> Type<'db> { |
| 5145 | 4978 | }) |
| 5146 | 4979 | .or_else(|| LangItem::Future.resolve_trait(db, self.env.krate))?; |
| 5147 | 4980 | |
| 5148 | let canonical_ty = | |
| 5149 | Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) }; | |
| 5150 | if !method_resolution::implements_trait_unique(&canonical_ty, db, &self.env, trait_) { | |
| 4981 | if !traits::implements_trait_unique(self.ty, db, self.env.clone(), trait_) { | |
| 5151 | 4982 | return None; |
| 5152 | 4983 | } |
| 5153 | 4984 | |
| ... | ... | @@ -5175,9 +5006,7 @@ impl<'db> Type<'db> { |
| 5175 | 5006 | let Some(iterator_trait) = LangItem::Iterator.resolve_trait(db, self.env.krate) else { |
| 5176 | 5007 | return false; |
| 5177 | 5008 | }; |
| 5178 | let canonical_ty = | |
| 5179 | Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) }; | |
| 5180 | method_resolution::implements_trait_unique(&canonical_ty, db, &self.env, iterator_trait) | |
| 5009 | traits::implements_trait_unique(self.ty, db, self.env.clone(), iterator_trait) | |
| 5181 | 5010 | } |
| 5182 | 5011 | |
| 5183 | 5012 | /// Resolves the projection `<Self as IntoIterator>::IntoIter` and returns the resulting type |
| ... | ... | @@ -5190,9 +5019,7 @@ impl<'db> Type<'db> { |
| 5190 | 5019 | }, |
| 5191 | 5020 | )?; |
| 5192 | 5021 | |
| 5193 | let canonical_ty = | |
| 5194 | Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) }; | |
| 5195 | if !method_resolution::implements_trait_unique(&canonical_ty, db, &self.env, trait_) { | |
| 5022 | if !traits::implements_trait_unique(self.ty, db, self.env.clone(), trait_) { | |
| 5196 | 5023 | return None; |
| 5197 | 5024 | } |
| 5198 | 5025 | |
| ... | ... | @@ -5212,43 +5039,18 @@ impl<'db> Type<'db> { |
| 5212 | 5039 | None => return false, |
| 5213 | 5040 | }; |
| 5214 | 5041 | |
| 5215 | let canonical_ty = | |
| 5216 | Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) }; | |
| 5217 | method_resolution::implements_trait_unique(&canonical_ty, db, &self.env, fnonce_trait) | |
| 5042 | traits::implements_trait_unique(self.ty, db, self.env.clone(), fnonce_trait) | |
| 5218 | 5043 | } |
| 5219 | 5044 | |
| 5220 | 5045 | // FIXME: Find better API that also handles const generics |
| 5221 | 5046 | pub fn impls_trait(&self, db: &'db dyn HirDatabase, trait_: Trait, args: &[Type<'db>]) -> bool { |
| 5222 | let mut it = args.iter().map(|t| t.ty.clone()); | |
| 5223 | let trait_ref = TyBuilder::trait_ref(db, trait_.id) | |
| 5224 | .push(self.ty.clone()) | |
| 5225 | .fill(|x| { | |
| 5226 | match x { | |
| 5227 | ParamKind::Type => { | |
| 5228 | it.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner) | |
| 5229 | } | |
| 5230 | ParamKind::Const(ty) => { | |
| 5231 | // FIXME: this code is not covered in tests. | |
| 5232 | unknown_const_as_generic(ty.clone()) | |
| 5233 | } | |
| 5234 | ParamKind::Lifetime => error_lifetime().cast(Interner), | |
| 5235 | } | |
| 5236 | }) | |
| 5237 | .build(); | |
| 5238 | ||
| 5239 | let goal = Canonical { | |
| 5240 | value: hir_ty::InEnvironment::new( | |
| 5241 | &self.env.env.to_chalk(DbInterner::new_with( | |
| 5242 | db, | |
| 5243 | Some(self.env.krate), | |
| 5244 | self.env.block, | |
| 5245 | )), | |
| 5246 | trait_ref.cast(Interner), | |
| 5247 | ), | |
| 5248 | binders: CanonicalVarKinds::empty(Interner), | |
| 5249 | }; | |
| 5250 | ||
| 5251 | !db.trait_solve(self.env.krate, self.env.block, goal).no_solution() | |
| 5047 | let interner = DbInterner::new_with(db, None, None); | |
| 5048 | let args = generic_args_from_tys( | |
| 5049 | interner, | |
| 5050 | trait_.id.into(), | |
| 5051 | std::iter::once(self.ty).chain(args.iter().map(|ty| ty.ty)), | |
| 5052 | ); | |
| 5053 | traits::implements_trait_unique_with_args(db, self.env.clone(), trait_.id, args) | |
| 5252 | 5054 | } |
| 5253 | 5055 | |
| 5254 | 5056 | pub fn normalize_trait_assoc_type( |
| ... | ... | @@ -5257,27 +5059,25 @@ impl<'db> Type<'db> { |
| 5257 | 5059 | args: &[Type<'db>], |
| 5258 | 5060 | alias: TypeAlias, |
| 5259 | 5061 | ) -> Option<Type<'db>> { |
| 5260 | let mut args = args.iter(); | |
| 5261 | let trait_id = match alias.id.lookup(db).container { | |
| 5262 | ItemContainerId::TraitId(id) => id, | |
| 5263 | _ => unreachable!("non assoc type alias reached in normalize_trait_assoc_type()"), | |
| 5264 | }; | |
| 5265 | let parent_subst = TyBuilder::subst_for_def(db, trait_id, None) | |
| 5266 | .push(self.ty.clone()) | |
| 5267 | .fill(|it| { | |
| 5268 | // FIXME: this code is not covered in tests. | |
| 5269 | match it { | |
| 5270 | ParamKind::Type => args.next().unwrap().ty.clone().cast(Interner), | |
| 5271 | ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()), | |
| 5272 | ParamKind::Lifetime => error_lifetime().cast(Interner), | |
| 5273 | } | |
| 5274 | }) | |
| 5275 | .build(); | |
| 5062 | let interner = DbInterner::new_with(db, Some(self.env.krate), self.env.block); | |
| 5063 | let args = generic_args_from_tys( | |
| 5064 | interner, | |
| 5065 | alias.id.into(), | |
| 5066 | std::iter::once(self.ty).chain(args.iter().map(|ty| ty.ty)), | |
| 5067 | ); | |
| 5276 | 5068 | // FIXME: We don't handle GATs yet. |
| 5277 | let projection = TyBuilder::assoc_type_projection(db, alias.id, Some(parent_subst)).build(); | |
| 5069 | let projection = Ty::new_alias( | |
| 5070 | interner, | |
| 5071 | AliasTyKind::Projection, | |
| 5072 | AliasTy::new(interner, alias.id.into(), args), | |
| 5073 | ); | |
| 5278 | 5074 | |
| 5279 | let ty = db.normalize_projection(projection, self.env.clone()); | |
| 5280 | if ty.is_unknown() { None } else { Some(self.derived(ty)) } | |
| 5075 | // FIXME(next-solver): This needs to be `PostAnalysis`, but this currently causes errors due to our incorrect | |
| 5076 | // handling of opaques. `non_body_analysis()` will also cause errors (from not revealing opaques inside their | |
| 5077 | // defining places), so we choose between two bad options. | |
| 5078 | let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); | |
| 5079 | let ty = structurally_normalize_ty(&infcx, projection, self.env.clone()); | |
| 5080 | if ty.is_ty_error() { None } else { Some(self.derived(ty)) } | |
| 5281 | 5081 | } |
| 5282 | 5082 | |
| 5283 | 5083 | pub fn is_copy(&self, db: &'db dyn HirDatabase) -> bool { |
| ... | ... | @@ -5288,23 +5088,27 @@ impl<'db> Type<'db> { |
| 5288 | 5088 | } |
| 5289 | 5089 | |
| 5290 | 5090 | pub fn as_callable(&self, db: &'db dyn HirDatabase) -> Option<Callable<'db>> { |
| 5291 | let callee = match self.ty.kind(Interner) { | |
| 5292 | TyKind::Closure(id, subst) => Callee::Closure(*id, subst.clone()), | |
| 5293 | TyKind::Function(_) => Callee::FnPtr, | |
| 5294 | TyKind::FnDef(..) => Callee::Def(self.ty.callable_def(db)?), | |
| 5091 | let interner = DbInterner::new_with(db, None, None); | |
| 5092 | let callee = match self.ty.kind() { | |
| 5093 | TyKind::Closure(id, subst) => Callee::Closure(id.0, subst), | |
| 5094 | TyKind::FnPtr(..) => Callee::FnPtr, | |
| 5095 | TyKind::FnDef(id, _) => Callee::Def(id.0), | |
| 5295 | 5096 | kind => { |
| 5296 | 5097 | // This will happen when it implements fn or fn mut, since we add an autoborrow adjustment |
| 5297 | let (ty, kind) = if let TyKind::Ref(_, _, ty) = kind { | |
| 5298 | (ty, ty.kind(Interner)) | |
| 5098 | let (ty, kind) = if let TyKind::Ref(_, ty, _) = kind { | |
| 5099 | (ty, ty.kind()) | |
| 5299 | 5100 | } else { |
| 5300 | (&self.ty, kind) | |
| 5101 | (self.ty, kind) | |
| 5301 | 5102 | }; |
| 5302 | 5103 | if let TyKind::Closure(closure, subst) = kind { |
| 5303 | let sig = ty.callable_sig(db)?; | |
| 5104 | let sig = subst | |
| 5105 | .split_closure_args_untupled() | |
| 5106 | .closure_sig_as_fn_ptr_ty | |
| 5107 | .callable_sig(interner)?; | |
| 5304 | 5108 | return Some(Callable { |
| 5305 | 5109 | ty: self.clone(), |
| 5306 | 5110 | sig, |
| 5307 | callee: Callee::Closure(*closure, subst.clone()), | |
| 5111 | callee: Callee::Closure(closure.0, subst), | |
| 5308 | 5112 | is_bound_method: false, |
| 5309 | 5113 | }); |
| 5310 | 5114 | } |
| ... | ... | @@ -5318,32 +5122,32 @@ impl<'db> Type<'db> { |
| 5318 | 5122 | } |
| 5319 | 5123 | }; |
| 5320 | 5124 | |
| 5321 | let sig = self.ty.callable_sig(db)?; | |
| 5125 | let sig = self.ty.callable_sig(interner)?; | |
| 5322 | 5126 | Some(Callable { ty: self.clone(), sig, callee, is_bound_method: false }) |
| 5323 | 5127 | } |
| 5324 | 5128 | |
| 5325 | 5129 | pub fn is_closure(&self) -> bool { |
| 5326 | matches!(self.ty.kind(Interner), TyKind::Closure { .. }) | |
| 5130 | matches!(self.ty.kind(), TyKind::Closure { .. }) | |
| 5327 | 5131 | } |
| 5328 | 5132 | |
| 5329 | pub fn as_closure(&self) -> Option<Closure> { | |
| 5330 | match self.ty.kind(Interner) { | |
| 5331 | TyKind::Closure(id, subst) => Some(Closure { id: *id, subst: subst.clone() }), | |
| 5133 | pub fn as_closure(&self) -> Option<Closure<'db>> { | |
| 5134 | match self.ty.kind() { | |
| 5135 | TyKind::Closure(id, subst) => Some(Closure { id: id.0, subst }), | |
| 5332 | 5136 | _ => None, |
| 5333 | 5137 | } |
| 5334 | 5138 | } |
| 5335 | 5139 | |
| 5336 | 5140 | pub fn is_fn(&self) -> bool { |
| 5337 | matches!(self.ty.kind(Interner), TyKind::FnDef(..) | TyKind::Function { .. }) | |
| 5141 | matches!(self.ty.kind(), TyKind::FnDef(..) | TyKind::FnPtr { .. }) | |
| 5338 | 5142 | } |
| 5339 | 5143 | |
| 5340 | 5144 | pub fn is_array(&self) -> bool { |
| 5341 | matches!(self.ty.kind(Interner), TyKind::Array(..)) | |
| 5145 | matches!(self.ty.kind(), TyKind::Array(..)) | |
| 5342 | 5146 | } |
| 5343 | 5147 | |
| 5344 | 5148 | pub fn is_packed(&self, db: &'db dyn HirDatabase) -> bool { |
| 5345 | let adt_id = match *self.ty.kind(Interner) { | |
| 5346 | TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id, | |
| 5149 | let adt_id = match self.ty.kind() { | |
| 5150 | TyKind::Adt(adt_def, ..) => adt_def.def_id().0, | |
| 5347 | 5151 | _ => return false, |
| 5348 | 5152 | }; |
| 5349 | 5153 | |
| ... | ... | @@ -5355,99 +5159,64 @@ impl<'db> Type<'db> { |
| 5355 | 5159 | } |
| 5356 | 5160 | |
| 5357 | 5161 | pub fn is_raw_ptr(&self) -> bool { |
| 5358 | matches!(self.ty.kind(Interner), TyKind::Raw(..)) | |
| 5162 | matches!(self.ty.kind(), TyKind::RawPtr(..)) | |
| 5359 | 5163 | } |
| 5360 | 5164 | |
| 5361 | 5165 | pub fn remove_raw_ptr(&self) -> Option<Type<'db>> { |
| 5362 | if let TyKind::Raw(_, ty) = self.ty.kind(Interner) { | |
| 5363 | Some(self.derived(ty.clone())) | |
| 5364 | } else { | |
| 5365 | None | |
| 5366 | } | |
| 5166 | if let TyKind::RawPtr(ty, _) = self.ty.kind() { Some(self.derived(ty)) } else { None } | |
| 5367 | 5167 | } |
| 5368 | 5168 | |
| 5369 | 5169 | pub fn contains_unknown(&self) -> bool { |
| 5370 | // FIXME: When we get rid of `ConstScalar::Unknown`, we can just look at precomputed | |
| 5371 | // `TypeFlags` in `TyData`. | |
| 5372 | return go(&self.ty); | |
| 5373 | ||
| 5374 | fn go(ty: &Ty) -> bool { | |
| 5375 | match ty.kind(Interner) { | |
| 5376 | TyKind::Error => true, | |
| 5377 | ||
| 5378 | TyKind::Adt(_, substs) | |
| 5379 | | TyKind::AssociatedType(_, substs) | |
| 5380 | | TyKind::Tuple(_, substs) | |
| 5381 | | TyKind::OpaqueType(_, substs) | |
| 5382 | | TyKind::FnDef(_, substs) | |
| 5383 | | TyKind::Closure(_, substs) => { | |
| 5384 | substs.iter(Interner).filter_map(|a| a.ty(Interner)).any(go) | |
| 5385 | } | |
| 5386 | ||
| 5387 | TyKind::Array(_ty, len) if len.is_unknown() => true, | |
| 5388 | TyKind::Array(ty, _) | |
| 5389 | | TyKind::Slice(ty) | |
| 5390 | | TyKind::Raw(_, ty) | |
| 5391 | | TyKind::Ref(_, _, ty) => go(ty), | |
| 5392 | ||
| 5393 | TyKind::Scalar(_) | |
| 5394 | | TyKind::Str | |
| 5395 | | TyKind::Never | |
| 5396 | | TyKind::Placeholder(_) | |
| 5397 | | TyKind::BoundVar(_) | |
| 5398 | | TyKind::InferenceVar(_, _) | |
| 5399 | | TyKind::Dyn(_) | |
| 5400 | | TyKind::Function(_) | |
| 5401 | | TyKind::Alias(_) | |
| 5402 | | TyKind::Foreign(_) | |
| 5403 | | TyKind::Coroutine(..) | |
| 5404 | | TyKind::CoroutineWitness(..) => false, | |
| 5405 | } | |
| 5406 | } | |
| 5170 | self.ty.references_non_lt_error() | |
| 5407 | 5171 | } |
| 5408 | 5172 | |
| 5409 | 5173 | pub fn fields(&self, db: &'db dyn HirDatabase) -> Vec<(Field, Self)> { |
| 5410 | let (variant_id, substs) = match self.ty.kind(Interner) { | |
| 5411 | TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), substs) => ((*s).into(), substs), | |
| 5412 | TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), substs) => ((*u).into(), substs), | |
| 5174 | let interner = DbInterner::new_with(db, None, None); | |
| 5175 | let (variant_id, substs) = match self.ty.kind() { | |
| 5176 | TyKind::Adt(adt_def, substs) => { | |
| 5177 | let id = match adt_def.def_id().0 { | |
| 5178 | AdtId::StructId(id) => id.into(), | |
| 5179 | AdtId::UnionId(id) => id.into(), | |
| 5180 | AdtId::EnumId(_) => return Vec::new(), | |
| 5181 | }; | |
| 5182 | (id, substs) | |
| 5183 | } | |
| 5413 | 5184 | _ => return Vec::new(), |
| 5414 | 5185 | }; |
| 5415 | 5186 | |
| 5416 | db.field_types(variant_id) | |
| 5187 | db.field_types_ns(variant_id) | |
| 5417 | 5188 | .iter() |
| 5418 | 5189 | .map(|(local_id, ty)| { |
| 5419 | 5190 | let def = Field { parent: variant_id.into(), id: local_id }; |
| 5420 | let ty = ty.clone().substitute(Interner, substs); | |
| 5191 | let ty = ty.instantiate(interner, substs); | |
| 5421 | 5192 | (def, self.derived(ty)) |
| 5422 | 5193 | }) |
| 5423 | 5194 | .collect() |
| 5424 | 5195 | } |
| 5425 | 5196 | |
| 5426 | 5197 | pub fn tuple_fields(&self, _db: &'db dyn HirDatabase) -> Vec<Self> { |
| 5427 | if let TyKind::Tuple(_, substs) = &self.ty.kind(Interner) { | |
| 5428 | substs | |
| 5429 | .iter(Interner) | |
| 5430 | .map(|ty| self.derived(ty.assert_ty_ref(Interner).clone())) | |
| 5431 | .collect() | |
| 5198 | if let TyKind::Tuple(substs) = self.ty.kind() { | |
| 5199 | substs.iter().map(|ty| self.derived(ty)).collect() | |
| 5432 | 5200 | } else { |
| 5433 | 5201 | Vec::new() |
| 5434 | 5202 | } |
| 5435 | 5203 | } |
| 5436 | 5204 | |
| 5437 | 5205 | pub fn as_array(&self, db: &'db dyn HirDatabase) -> Option<(Self, usize)> { |
| 5438 | if let TyKind::Array(ty, len) = &self.ty.kind(Interner) { | |
| 5439 | try_const_usize(db, len).map(|it| (self.derived(ty.clone()), it as usize)) | |
| 5206 | if let TyKind::Array(ty, len) = self.ty.kind() { | |
| 5207 | try_const_usize(db, len).map(|it| (self.derived(ty), it as usize)) | |
| 5440 | 5208 | } else { |
| 5441 | 5209 | None |
| 5442 | 5210 | } |
| 5443 | 5211 | } |
| 5444 | 5212 | |
| 5445 | 5213 | pub fn fingerprint_for_trait_impl(&self) -> Option<TyFingerprint> { |
| 5446 | TyFingerprint::for_trait_impl(&self.ty) | |
| 5214 | TyFingerprint::for_trait_impl(self.ty) | |
| 5447 | 5215 | } |
| 5448 | 5216 | |
| 5449 | pub(crate) fn canonical(&self) -> Canonical<Ty> { | |
| 5450 | hir_ty::replace_errors_with_variables(&self.ty) | |
| 5217 | pub(crate) fn canonical(&self, db: &'db dyn HirDatabase) -> Canonical<'db, Ty<'db>> { | |
| 5218 | let interner = DbInterner::new_with(db, None, None); | |
| 5219 | hir_ty::replace_errors_with_variables(interner, &self.ty) | |
| 5451 | 5220 | } |
| 5452 | 5221 | |
| 5453 | 5222 | /// Returns types that this type dereferences to (including this type itself). The returned |
| ... | ... | @@ -5459,9 +5228,10 @@ impl<'db> Type<'db> { |
| 5459 | 5228 | self.autoderef_(db).map(move |ty| self.derived(ty)) |
| 5460 | 5229 | } |
| 5461 | 5230 | |
| 5462 | fn autoderef_(&self, db: &'db dyn HirDatabase) -> impl Iterator<Item = Ty> { | |
| 5231 | fn autoderef_(&self, db: &'db dyn HirDatabase) -> impl Iterator<Item = Ty<'db>> { | |
| 5232 | let interner = DbInterner::new_with(db, None, None); | |
| 5463 | 5233 | // There should be no inference vars in types passed here |
| 5464 | let canonical = hir_ty::replace_errors_with_variables(&self.ty); | |
| 5234 | let canonical = hir_ty::replace_errors_with_variables(interner, &self.ty); | |
| 5465 | 5235 | autoderef(db, self.env.clone(), canonical) |
| 5466 | 5236 | } |
| 5467 | 5237 | |
| ... | ... | @@ -5487,14 +5257,15 @@ impl<'db> Type<'db> { |
| 5487 | 5257 | krate: Crate, |
| 5488 | 5258 | callback: &mut dyn FnMut(AssocItemId) -> bool, |
| 5489 | 5259 | ) { |
| 5490 | let def_crates = match method_resolution::def_crates(db, &self.ty, krate.id) { | |
| 5260 | let ty_ns = self.ty; | |
| 5261 | let def_crates = match method_resolution::def_crates(db, ty_ns, krate.id) { | |
| 5491 | 5262 | Some(it) => it, |
| 5492 | 5263 | None => return, |
| 5493 | 5264 | }; |
| 5494 | 5265 | for krate in def_crates { |
| 5495 | 5266 | let impls = db.inherent_impls_in_crate(krate); |
| 5496 | 5267 | |
| 5497 | for impl_def in impls.for_self_ty(&self.ty) { | |
| 5268 | for impl_def in impls.for_self_ty(ty_ns) { | |
| 5498 | 5269 | for &(_, item) in impl_def.impl_items(db).items.iter() { |
| 5499 | 5270 | if callback(item) { |
| 5500 | 5271 | return; |
| ... | ... | @@ -5523,15 +5294,13 @@ impl<'db> Type<'db> { |
| 5523 | 5294 | /// - "U" |
| 5524 | 5295 | /// ``` |
| 5525 | 5296 | pub fn type_arguments(&self) -> impl Iterator<Item = Type<'db>> + '_ { |
| 5526 | self.ty | |
| 5527 | .strip_references() | |
| 5528 | .as_adt() | |
| 5529 | .map(|(_, substs)| substs) | |
| 5530 | .or_else(|| self.ty.strip_references().as_tuple()) | |
| 5531 | .into_iter() | |
| 5532 | .flat_map(|substs| substs.iter(Interner)) | |
| 5533 | .filter_map(|arg| arg.ty(Interner).cloned()) | |
| 5534 | .map(move |ty| self.derived(ty)) | |
| 5297 | match self.ty.strip_references().kind() { | |
| 5298 | TyKind::Adt(_, substs) => Either::Left(substs.types().map(move |ty| self.derived(ty))), | |
| 5299 | TyKind::Tuple(substs) => { | |
| 5300 | Either::Right(Either::Left(substs.iter().map(move |ty| self.derived(ty)))) | |
| 5301 | } | |
| 5302 | _ => Either::Right(Either::Right(std::iter::empty())), | |
| 5303 | } | |
| 5535 | 5304 | } |
| 5536 | 5305 | |
| 5537 | 5306 | /// Iterates its type and const arguments |
| ... | ... | @@ -5561,15 +5330,13 @@ impl<'db> Type<'db> { |
| 5561 | 5330 | .strip_references() |
| 5562 | 5331 | .as_adt() |
| 5563 | 5332 | .into_iter() |
| 5564 | .flat_map(|(_, substs)| substs.iter(Interner)) | |
| 5565 | .filter_map(move |arg| { | |
| 5566 | // arg can be either a `Ty` or `constant` | |
| 5567 | if let Some(ty) = arg.ty(Interner) { | |
| 5568 | Some(format_smolstr!("{}", ty.display(db, display_target))) | |
| 5569 | } else { | |
| 5570 | arg.constant(Interner) | |
| 5571 | .map(|const_| format_smolstr!("{}", const_.display(db, display_target))) | |
| 5333 | .flat_map(|(_, substs)| substs.iter()) | |
| 5334 | .filter_map(move |arg| match arg { | |
| 5335 | GenericArg::Ty(ty) => Some(format_smolstr!("{}", ty.display(db, display_target))), | |
| 5336 | GenericArg::Const(const_) => { | |
| 5337 | Some(format_smolstr!("{}", const_.display(db, display_target))) | |
| 5572 | 5338 | } |
| 5339 | GenericArg::Lifetime(_) => None, | |
| 5573 | 5340 | }) |
| 5574 | 5341 | } |
| 5575 | 5342 | |
| ... | ... | @@ -5686,8 +5453,9 @@ impl<'db> Type<'db> { |
| 5686 | 5453 | ?name, |
| 5687 | 5454 | ) |
| 5688 | 5455 | .entered(); |
| 5456 | let interner = DbInterner::new_with(db, None, None); | |
| 5689 | 5457 | // There should be no inference vars in types passed here |
| 5690 | let canonical = hir_ty::replace_errors_with_variables(&self.ty); | |
| 5458 | let canonical = hir_ty::replace_errors_with_variables(interner, &self.ty); | |
| 5691 | 5459 | |
| 5692 | 5460 | let krate = scope.krate(); |
| 5693 | 5461 | let environment = scope |
| ... | ... | @@ -5696,11 +5464,7 @@ impl<'db> Type<'db> { |
| 5696 | 5464 | .map_or_else(|| TraitEnvironment::empty(krate.id), |d| db.trait_environment(d)); |
| 5697 | 5465 | |
| 5698 | 5466 | _ = method_resolution::iterate_method_candidates_dyn( |
| 5699 | &canonical.to_nextsolver(DbInterner::new_with( | |
| 5700 | db, | |
| 5701 | Some(environment.krate), | |
| 5702 | environment.block, | |
| 5703 | )), | |
| 5467 | &canonical, | |
| 5704 | 5468 | db, |
| 5705 | 5469 | environment, |
| 5706 | 5470 | traits_in_scope, |
| ... | ... | @@ -5778,7 +5542,8 @@ impl<'db> Type<'db> { |
| 5778 | 5542 | } |
| 5779 | 5543 | } |
| 5780 | 5544 | |
| 5781 | let canonical = hir_ty::replace_errors_with_variables(&self.ty); | |
| 5545 | let interner = DbInterner::new_with(db, None, None); | |
| 5546 | let canonical = hir_ty::replace_errors_with_variables(interner, &self.ty); | |
| 5782 | 5547 | |
| 5783 | 5548 | let krate = scope.krate(); |
| 5784 | 5549 | let environment = scope |
| ... | ... | @@ -5787,11 +5552,7 @@ impl<'db> Type<'db> { |
| 5787 | 5552 | .map_or_else(|| TraitEnvironment::empty(krate.id), |d| db.trait_environment(d)); |
| 5788 | 5553 | |
| 5789 | 5554 | _ = method_resolution::iterate_path_candidates( |
| 5790 | &canonical.to_nextsolver(DbInterner::new_with( | |
| 5791 | db, | |
| 5792 | Some(environment.krate), | |
| 5793 | environment.block, | |
| 5794 | )), | |
| 5555 | &canonical, | |
| 5795 | 5556 | db, |
| 5796 | 5557 | environment, |
| 5797 | 5558 | traits_in_scope, |
| ... | ... | @@ -5830,7 +5591,7 @@ impl<'db> Type<'db> { |
| 5830 | 5591 | pub fn env_traits(&self, db: &'db dyn HirDatabase) -> impl Iterator<Item = Trait> { |
| 5831 | 5592 | let _p = tracing::info_span!("env_traits").entered(); |
| 5832 | 5593 | self.autoderef_(db) |
| 5833 | .filter(|ty| matches!(ty.kind(Interner), TyKind::Placeholder(_))) | |
| 5594 | .filter(|ty| matches!(ty.kind(), TyKind::Param(_))) | |
| 5834 | 5595 | .flat_map(|ty| { |
| 5835 | 5596 | self.env |
| 5836 | 5597 | .traits_in_scope_from_clauses(ty) |
| ... | ... | @@ -5841,136 +5602,66 @@ impl<'db> Type<'db> { |
| 5841 | 5602 | |
| 5842 | 5603 | pub fn as_impl_traits(&self, db: &'db dyn HirDatabase) -> Option<impl Iterator<Item = Trait>> { |
| 5843 | 5604 | self.ty.impl_trait_bounds(db).map(|it| { |
| 5844 | it.into_iter().filter_map(|pred| match pred.skip_binders() { | |
| 5845 | hir_ty::WhereClause::Implemented(trait_ref) => { | |
| 5846 | Some(Trait::from(trait_ref.hir_trait_id())) | |
| 5847 | } | |
| 5605 | it.into_iter().filter_map(|pred| match pred.kind().skip_binder() { | |
| 5606 | ClauseKind::Trait(trait_ref) => Some(Trait::from(trait_ref.def_id().0)), | |
| 5848 | 5607 | _ => None, |
| 5849 | 5608 | }) |
| 5850 | 5609 | }) |
| 5851 | 5610 | } |
| 5852 | 5611 | |
| 5853 | 5612 | pub fn as_associated_type_parent_trait(&self, db: &'db dyn HirDatabase) -> Option<Trait> { |
| 5854 | self.ty.associated_type_parent_trait(db).map(Into::into) | |
| 5613 | let TyKind::Alias(AliasTyKind::Projection, alias) = self.ty.kind() else { return None }; | |
| 5614 | match alias.def_id.expect_type_alias().loc(db).container { | |
| 5615 | ItemContainerId::TraitId(id) => Some(Trait { id }), | |
| 5616 | _ => None, | |
| 5617 | } | |
| 5855 | 5618 | } |
| 5856 | 5619 | |
| 5857 | fn derived(&self, ty: Ty) -> Self { | |
| 5858 | Type { env: self.env.clone(), ty, _pd: PhantomCovariantLifetime::new() } | |
| 5620 | fn derived(&self, ty: Ty<'db>) -> Self { | |
| 5621 | Type { env: self.env.clone(), ty } | |
| 5859 | 5622 | } |
| 5860 | 5623 | |
| 5861 | /// Visits every type, including generic arguments, in this type. `cb` is called with type | |
| 5624 | /// Visits every type, including generic arguments, in this type. `callback` is called with type | |
| 5862 | 5625 | /// itself first, and then with its generic arguments. |
| 5863 | pub fn walk(&self, db: &'db dyn HirDatabase, mut cb: impl FnMut(Type<'db>)) { | |
| 5864 | fn walk_substs<'db>( | |
| 5626 | pub fn walk(&self, db: &'db dyn HirDatabase, callback: impl FnMut(Type<'db>)) { | |
| 5627 | struct Visitor<'db, F> { | |
| 5865 | 5628 | db: &'db dyn HirDatabase, |
| 5866 | type_: &Type<'db>, | |
| 5867 | substs: &Substitution, | |
| 5868 | cb: &mut impl FnMut(Type<'db>), | |
| 5869 | ) { | |
| 5870 | for ty in substs.iter(Interner).filter_map(|a| a.ty(Interner)) { | |
| 5871 | walk_type(db, &type_.derived(ty.clone()), cb); | |
| 5872 | } | |
| 5629 | env: Arc<TraitEnvironment<'db>>, | |
| 5630 | callback: F, | |
| 5631 | visited: FxHashSet<Ty<'db>>, | |
| 5873 | 5632 | } |
| 5633 | impl<'db, F> TypeVisitor<DbInterner<'db>> for Visitor<'db, F> | |
| 5634 | where | |
| 5635 | F: FnMut(Type<'db>), | |
| 5636 | { | |
| 5637 | type Result = (); | |
| 5874 | 5638 | |
| 5875 | fn walk_bounds<'db>( | |
| 5876 | db: &'db dyn HirDatabase, | |
| 5877 | type_: &Type<'db>, | |
| 5878 | bounds: &[QuantifiedWhereClause], | |
| 5879 | cb: &mut impl FnMut(Type<'db>), | |
| 5880 | ) { | |
| 5881 | for pred in bounds { | |
| 5882 | if let WhereClause::Implemented(trait_ref) = pred.skip_binders() { | |
| 5883 | cb(type_.clone()); | |
| 5884 | // skip the self type. it's likely the type we just got the bounds from | |
| 5885 | if let [self_ty, params @ ..] = trait_ref.substitution.as_slice(Interner) { | |
| 5886 | for ty in | |
| 5887 | params.iter().filter(|&ty| ty != self_ty).filter_map(|a| a.ty(Interner)) | |
| 5888 | { | |
| 5889 | walk_type(db, &type_.derived(ty.clone()), cb); | |
| 5890 | } | |
| 5891 | } | |
| 5639 | fn visit_ty(&mut self, ty: Ty<'db>) -> Self::Result { | |
| 5640 | if !self.visited.insert(ty) { | |
| 5641 | return; | |
| 5892 | 5642 | } |
| 5893 | } | |
| 5894 | } | |
| 5895 | 5643 | |
| 5896 | fn walk_type<'db>( | |
| 5897 | db: &'db dyn HirDatabase, | |
| 5898 | type_: &Type<'db>, | |
| 5899 | cb: &mut impl FnMut(Type<'db>), | |
| 5900 | ) { | |
| 5901 | let ty = type_.ty.strip_references(); | |
| 5902 | match ty.kind(Interner) { | |
| 5903 | TyKind::Adt(_, substs) => { | |
| 5904 | cb(type_.derived(ty.clone())); | |
| 5905 | walk_substs(db, type_, substs, cb); | |
| 5906 | } | |
| 5907 | TyKind::AssociatedType(_, substs) | |
| 5908 | | TyKind::Alias(AliasTy::Projection(hir_ty::ProjectionTy { | |
| 5909 | substitution: substs, | |
| 5910 | .. | |
| 5911 | })) => { | |
| 5912 | if ty.associated_type_parent_trait(db).is_some() { | |
| 5913 | cb(type_.derived(ty.clone())); | |
| 5914 | } | |
| 5915 | walk_substs(db, type_, substs, cb); | |
| 5916 | } | |
| 5917 | TyKind::OpaqueType(_, subst) => { | |
| 5918 | if let Some(bounds) = ty.impl_trait_bounds(db) { | |
| 5919 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); | |
| 5920 | } | |
| 5644 | (self.callback)(Type { env: self.env.clone(), ty }); | |
| 5921 | 5645 | |
| 5922 | walk_substs(db, type_, subst, cb); | |
| 5646 | if let Some(bounds) = ty.impl_trait_bounds(self.db) { | |
| 5647 | bounds.visit_with(self); | |
| 5923 | 5648 | } |
| 5924 | TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { | |
| 5925 | if let Some(bounds) = ty.impl_trait_bounds(db) { | |
| 5926 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); | |
| 5927 | } | |
| 5928 | 5649 | |
| 5929 | walk_substs(db, type_, &opaque_ty.substitution, cb); | |
| 5930 | } | |
| 5931 | TyKind::Placeholder(_) => { | |
| 5932 | cb(type_.derived(ty.clone())); | |
| 5933 | if let Some(bounds) = ty.impl_trait_bounds(db) { | |
| 5934 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); | |
| 5935 | } | |
| 5936 | } | |
| 5937 | TyKind::Dyn(bounds) => { | |
| 5938 | walk_bounds( | |
| 5939 | db, | |
| 5940 | &type_.derived(ty.clone()), | |
| 5941 | bounds.bounds.skip_binders().interned(), | |
| 5942 | cb, | |
| 5943 | ); | |
| 5944 | } | |
| 5945 | ||
| 5946 | TyKind::Ref(_, _, ty) | |
| 5947 | | TyKind::Raw(_, ty) | |
| 5948 | | TyKind::Array(ty, _) | |
| 5949 | | TyKind::Slice(ty) => { | |
| 5950 | walk_type(db, &type_.derived(ty.clone()), cb); | |
| 5951 | } | |
| 5952 | ||
| 5953 | TyKind::FnDef(_, substs) | |
| 5954 | | TyKind::Tuple(_, substs) | |
| 5955 | | TyKind::Closure(.., substs) => { | |
| 5956 | walk_substs(db, type_, substs, cb); | |
| 5957 | } | |
| 5958 | TyKind::Function(hir_ty::FnPointer { substitution, .. }) => { | |
| 5959 | walk_substs(db, type_, &substitution.0, cb); | |
| 5960 | } | |
| 5961 | ||
| 5962 | _ => {} | |
| 5650 | ty.super_visit_with(self); | |
| 5963 | 5651 | } |
| 5964 | 5652 | } |
| 5965 | 5653 | |
| 5966 | walk_type(db, self, &mut cb); | |
| 5654 | let mut visitor = | |
| 5655 | Visitor { db, env: self.env.clone(), callback, visited: FxHashSet::default() }; | |
| 5656 | self.ty.visit_with(&mut visitor); | |
| 5967 | 5657 | } |
| 5968 | 5658 | /// Check if type unifies with another type. |
| 5969 | 5659 | /// |
| 5970 | 5660 | /// Note that we consider placeholder types to unify with everything. |
| 5971 | 5661 | /// For example `Option<T>` and `Option<U>` unify although there is unresolved goal `T = U`. |
| 5972 | 5662 | pub fn could_unify_with(&self, db: &'db dyn HirDatabase, other: &Type<'db>) -> bool { |
| 5973 | let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), other.ty.clone())); | |
| 5663 | let interner = DbInterner::new_with(db, None, None); | |
| 5664 | let tys = hir_ty::replace_errors_with_variables(interner, &(self.ty, other.ty)); | |
| 5974 | 5665 | hir_ty::could_unify(db, self.env.clone(), &tys) |
| 5975 | 5666 | } |
| 5976 | 5667 | |
| ... | ... | @@ -5979,66 +5670,62 @@ impl<'db> Type<'db> { |
| 5979 | 5670 | /// This means that placeholder types are not considered to unify if there are any bounds set on |
| 5980 | 5671 | /// them. For example `Option<T>` and `Option<U>` do not unify as we cannot show that `T = U` |
| 5981 | 5672 | pub fn could_unify_with_deeply(&self, db: &'db dyn HirDatabase, other: &Type<'db>) -> bool { |
| 5982 | let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), other.ty.clone())); | |
| 5673 | let interner = DbInterner::new_with(db, None, None); | |
| 5674 | let tys = hir_ty::replace_errors_with_variables(interner, &(self.ty, other.ty)); | |
| 5983 | 5675 | hir_ty::could_unify_deeply(db, self.env.clone(), &tys) |
| 5984 | 5676 | } |
| 5985 | 5677 | |
| 5986 | 5678 | pub fn could_coerce_to(&self, db: &'db dyn HirDatabase, to: &Type<'db>) -> bool { |
| 5987 | let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), to.ty.clone())); | |
| 5679 | let interner = DbInterner::new_with(db, None, None); | |
| 5680 | let tys = hir_ty::replace_errors_with_variables(interner, &(self.ty, to.ty)); | |
| 5988 | 5681 | hir_ty::could_coerce(db, self.env.clone(), &tys) |
| 5989 | 5682 | } |
| 5990 | 5683 | |
| 5991 | pub fn as_type_param(&self, db: &'db dyn HirDatabase) -> Option<TypeParam> { | |
| 5992 | match self.ty.kind(Interner) { | |
| 5993 | TyKind::Placeholder(p) => Some(TypeParam { | |
| 5994 | id: TypeParamId::from_unchecked(hir_ty::from_placeholder_idx(db, *p).0), | |
| 5995 | }), | |
| 5684 | pub fn as_type_param(&self, _db: &'db dyn HirDatabase) -> Option<TypeParam> { | |
| 5685 | match self.ty.kind() { | |
| 5686 | TyKind::Param(param) => Some(TypeParam { id: param.id }), | |
| 5996 | 5687 | _ => None, |
| 5997 | 5688 | } |
| 5998 | 5689 | } |
| 5999 | 5690 | |
| 6000 | 5691 | /// Returns unique `GenericParam`s contained in this type. |
| 6001 | 5692 | pub fn generic_params(&self, db: &'db dyn HirDatabase) -> FxHashSet<GenericParam> { |
| 6002 | hir_ty::collect_placeholders(&self.ty, db) | |
| 5693 | hir_ty::collect_params(&self.ty) | |
| 6003 | 5694 | .into_iter() |
| 6004 | 5695 | .map(|id| TypeOrConstParam { id }.split(db).either_into()) |
| 6005 | 5696 | .collect() |
| 6006 | 5697 | } |
| 6007 | 5698 | |
| 6008 | 5699 | pub fn layout(&self, db: &'db dyn HirDatabase) -> Result<Layout, LayoutError> { |
| 6009 | let interner = DbInterner::new_with(db, None, None); | |
| 6010 | db.layout_of_ty(self.ty.to_nextsolver(interner), self.env.clone()) | |
| 5700 | db.layout_of_ty(self.ty, self.env.clone()) | |
| 6011 | 5701 | .map(|layout| Layout(layout, db.target_data_layout(self.env.krate).unwrap())) |
| 6012 | 5702 | } |
| 6013 | 5703 | |
| 6014 | 5704 | pub fn drop_glue(&self, db: &'db dyn HirDatabase) -> DropGlue { |
| 6015 | db.has_drop_glue(self.ty.clone(), self.env.clone()) | |
| 5705 | let interner = DbInterner::new_with(db, Some(self.env.krate), self.env.block); | |
| 5706 | // FIXME: This should be `PostAnalysis` I believe. | |
| 5707 | let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); | |
| 5708 | hir_ty::drop::has_drop_glue(&infcx, self.ty, self.env.clone()) | |
| 6016 | 5709 | } |
| 6017 | 5710 | } |
| 6018 | 5711 | |
| 6019 | 5712 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
| 6020 | 5713 | pub struct TypeNs<'db> { |
| 6021 | 5714 | env: Arc<TraitEnvironment<'db>>, |
| 6022 | ty: hir_ty::next_solver::Ty<'db>, | |
| 6023 | _pd: PhantomCovariantLifetime<'db>, | |
| 5715 | ty: Ty<'db>, | |
| 6024 | 5716 | } |
| 6025 | 5717 | |
| 6026 | 5718 | impl<'db> TypeNs<'db> { |
| 6027 | fn new( | |
| 6028 | db: &'db dyn HirDatabase, | |
| 6029 | lexical_env: impl HasResolver, | |
| 6030 | ty: hir_ty::next_solver::Ty<'db>, | |
| 6031 | ) -> Self { | |
| 5719 | fn new(db: &'db dyn HirDatabase, lexical_env: impl HasResolver, ty: Ty<'db>) -> Self { | |
| 6032 | 5720 | let resolver = lexical_env.resolver(db); |
| 6033 | 5721 | let environment = resolver |
| 6034 | 5722 | .generic_def() |
| 6035 | 5723 | .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d)); |
| 6036 | TypeNs { env: environment, ty, _pd: PhantomCovariantLifetime::new() } | |
| 5724 | TypeNs { env: environment, ty } | |
| 6037 | 5725 | } |
| 6038 | 5726 | |
| 6039 | pub fn to_type(&self, db: &'db dyn HirDatabase) -> Type<'db> { | |
| 6040 | let interner = DbInterner::new_with(db, Some(self.env.krate), self.env.block); | |
| 6041 | Type { env: self.env.clone(), ty: convert_ty_for_result(interner, self.ty), _pd: self._pd } | |
| 5727 | pub fn to_type(&self, _db: &'db dyn HirDatabase) -> Type<'db> { | |
| 5728 | Type { env: self.env.clone(), ty: self.ty } | |
| 6042 | 5729 | } |
| 6043 | 5730 | |
| 6044 | 5731 | // FIXME: Find better API that also handles const generics |
| ... | ... | @@ -6094,40 +5781,38 @@ impl InlineAsmOperand { |
| 6094 | 5781 | #[derive(Debug)] |
| 6095 | 5782 | pub struct Callable<'db> { |
| 6096 | 5783 | ty: Type<'db>, |
| 6097 | sig: CallableSig, | |
| 6098 | callee: Callee, | |
| 5784 | sig: PolyFnSig<'db>, | |
| 5785 | callee: Callee<'db>, | |
| 6099 | 5786 | /// Whether this is a method that was called with method call syntax. |
| 6100 | 5787 | is_bound_method: bool, |
| 6101 | 5788 | } |
| 6102 | 5789 | |
| 6103 | 5790 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
| 6104 | enum Callee { | |
| 5791 | enum Callee<'db> { | |
| 6105 | 5792 | Def(CallableDefId), |
| 6106 | Closure(ClosureId, Substitution), | |
| 5793 | Closure(InternedClosureId, GenericArgs<'db>), | |
| 6107 | 5794 | FnPtr, |
| 6108 | 5795 | FnImpl(FnTrait), |
| 6109 | 5796 | } |
| 6110 | 5797 | |
| 6111 | pub enum CallableKind { | |
| 5798 | pub enum CallableKind<'db> { | |
| 6112 | 5799 | Function(Function), |
| 6113 | 5800 | TupleStruct(Struct), |
| 6114 | 5801 | TupleEnumVariant(Variant), |
| 6115 | Closure(Closure), | |
| 5802 | Closure(Closure<'db>), | |
| 6116 | 5803 | FnPtr, |
| 6117 | 5804 | FnImpl(FnTrait), |
| 6118 | 5805 | } |
| 6119 | 5806 | |
| 6120 | 5807 | impl<'db> Callable<'db> { |
| 6121 | pub fn kind(&self) -> CallableKind { | |
| 5808 | pub fn kind(&self) -> CallableKind<'db> { | |
| 6122 | 5809 | match self.callee { |
| 6123 | 5810 | Callee::Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()), |
| 6124 | 5811 | Callee::Def(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()), |
| 6125 | 5812 | Callee::Def(CallableDefId::EnumVariantId(it)) => { |
| 6126 | 5813 | CallableKind::TupleEnumVariant(it.into()) |
| 6127 | 5814 | } |
| 6128 | Callee::Closure(id, ref subst) => { | |
| 6129 | CallableKind::Closure(Closure { id, subst: subst.clone() }) | |
| 6130 | } | |
| 5815 | Callee::Closure(id, ref subst) => CallableKind::Closure(Closure { id, subst: *subst }), | |
| 6131 | 5816 | Callee::FnPtr => CallableKind::FnPtr, |
| 6132 | 5817 | Callee::FnImpl(fn_) => CallableKind::FnImpl(fn_), |
| 6133 | 5818 | } |
| ... | ... | @@ -6138,25 +5823,31 @@ impl<'db> Callable<'db> { |
| 6138 | 5823 | _ => return None, |
| 6139 | 5824 | }; |
| 6140 | 5825 | let func = Function { id: func }; |
| 6141 | Some((func.self_param(db)?, self.ty.derived(self.sig.params()[0].clone()))) | |
| 5826 | Some(( | |
| 5827 | func.self_param(db)?, | |
| 5828 | self.ty.derived(self.sig.skip_binder().inputs_and_output.inputs()[0]), | |
| 5829 | )) | |
| 6142 | 5830 | } |
| 6143 | 5831 | pub fn n_params(&self) -> usize { |
| 6144 | self.sig.params().len() - if self.is_bound_method { 1 } else { 0 } | |
| 5832 | self.sig.skip_binder().inputs_and_output.inputs().len() | |
| 5833 | - if self.is_bound_method { 1 } else { 0 } | |
| 6145 | 5834 | } |
| 6146 | 5835 | pub fn params(&self) -> Vec<Param<'db>> { |
| 6147 | 5836 | self.sig |
| 6148 | .params() | |
| 5837 | .skip_binder() | |
| 5838 | .inputs_and_output | |
| 5839 | .inputs() | |
| 6149 | 5840 | .iter() |
| 6150 | 5841 | .enumerate() |
| 6151 | 5842 | .skip(if self.is_bound_method { 1 } else { 0 }) |
| 6152 | .map(|(idx, ty)| (idx, self.ty.derived(ty.clone()))) | |
| 5843 | .map(|(idx, ty)| (idx, self.ty.derived(*ty))) | |
| 6153 | 5844 | .map(|(idx, ty)| Param { func: self.callee.clone(), idx, ty }) |
| 6154 | 5845 | .collect() |
| 6155 | 5846 | } |
| 6156 | 5847 | pub fn return_type(&self) -> Type<'db> { |
| 6157 | self.ty.derived(self.sig.ret().clone()) | |
| 5848 | self.ty.derived(self.sig.skip_binder().output()) | |
| 6158 | 5849 | } |
| 6159 | pub fn sig(&self) -> &CallableSig { | |
| 5850 | pub fn sig(&self) -> impl Eq { | |
| 6160 | 5851 | &self.sig |
| 6161 | 5852 | } |
| 6162 | 5853 | |
| ... | ... | @@ -6708,5 +6399,37 @@ fn as_name_opt(name: Option<impl AsName>) -> Name { |
| 6708 | 6399 | name.map_or_else(Name::missing, |name| name.as_name()) |
| 6709 | 6400 | } |
| 6710 | 6401 | |
| 6402 | fn generic_args_from_tys<'db>( | |
| 6403 | interner: DbInterner<'db>, | |
| 6404 | def_id: SolverDefId, | |
| 6405 | args: impl IntoIterator<Item = Ty<'db>>, | |
| 6406 | ) -> GenericArgs<'db> { | |
| 6407 | let mut args = args.into_iter(); | |
| 6408 | GenericArgs::for_item(interner, def_id, |_, _, id, _| { | |
| 6409 | if matches!(id, GenericParamId::TypeParamId(_)) | |
| 6410 | && let Some(arg) = args.next() | |
| 6411 | { | |
| 6412 | arg.into() | |
| 6413 | } else { | |
| 6414 | next_solver::GenericArg::error_from_id(interner, id) | |
| 6415 | } | |
| 6416 | }) | |
| 6417 | } | |
| 6418 | ||
| 6419 | fn has_non_default_type_params(db: &dyn HirDatabase, generic_def: GenericDefId) -> bool { | |
| 6420 | let params = db.generic_params(generic_def); | |
| 6421 | let defaults = db.generic_defaults_ns(generic_def); | |
| 6422 | params | |
| 6423 | .iter_type_or_consts() | |
| 6424 | .filter(|(_, param)| matches!(param, TypeOrConstParamData::TypeParamData(_))) | |
| 6425 | .map(|(local_id, _)| TypeOrConstParamId { parent: generic_def, local_id }) | |
| 6426 | .any(|param| { | |
| 6427 | let Some(param) = hir_ty::param_idx(db, param) else { | |
| 6428 | return false; | |
| 6429 | }; | |
| 6430 | defaults.get(param).is_none() | |
| 6431 | }) | |
| 6432 | } | |
| 6433 | ||
| 6711 | 6434 | pub use hir_ty::next_solver; |
| 6712 | 6435 | pub use hir_ty::setup_tracing; |
src/tools/rust-analyzer/crates/hir/src/semantics.rs+19-9| ... | ... | @@ -28,7 +28,10 @@ use hir_expand::{ |
| 28 | 28 | mod_path::{ModPath, PathKind}, |
| 29 | 29 | name::AsName, |
| 30 | 30 | }; |
| 31 | use hir_ty::diagnostics::{unsafe_operations, unsafe_operations_for_body}; | |
| 31 | use hir_ty::{ | |
| 32 | diagnostics::{unsafe_operations, unsafe_operations_for_body}, | |
| 33 | next_solver::DbInterner, | |
| 34 | }; | |
| 32 | 35 | use intern::{Interned, Symbol, sym}; |
| 33 | 36 | use itertools::Itertools; |
| 34 | 37 | use rustc_hash::{FxHashMap, FxHashSet}; |
| ... | ... | @@ -1553,8 +1556,8 @@ impl<'db> SemanticsImpl<'db> { |
| 1553 | 1556 | |
| 1554 | 1557 | pub fn expr_adjustments(&self, expr: &ast::Expr) -> Option<Vec<Adjustment<'db>>> { |
| 1555 | 1558 | let mutability = |m| match m { |
| 1556 | hir_ty::Mutability::Not => Mutability::Shared, | |
| 1557 | hir_ty::Mutability::Mut => Mutability::Mut, | |
| 1559 | hir_ty::next_solver::Mutability::Not => Mutability::Shared, | |
| 1560 | hir_ty::next_solver::Mutability::Mut => Mutability::Mut, | |
| 1558 | 1561 | }; |
| 1559 | 1562 | |
| 1560 | 1563 | let analyzer = self.analyze(expr.syntax())?; |
| ... | ... | @@ -1565,7 +1568,7 @@ impl<'db> SemanticsImpl<'db> { |
| 1565 | 1568 | it.iter() |
| 1566 | 1569 | .map(|adjust| { |
| 1567 | 1570 | let target = |
| 1568 | Type::new_with_resolver(self.db, &analyzer.resolver, adjust.target.clone()); | |
| 1571 | Type::new_with_resolver(self.db, &analyzer.resolver, adjust.target); | |
| 1569 | 1572 | let kind = match adjust.kind { |
| 1570 | 1573 | hir_ty::Adjust::NeverToAny => Adjust::NeverToAny, |
| 1571 | 1574 | hir_ty::Adjust::Deref(Some(hir_ty::OverloadedDeref(m))) => { |
| ... | ... | @@ -1652,11 +1655,18 @@ impl<'db> SemanticsImpl<'db> { |
| 1652 | 1655 | func: Function, |
| 1653 | 1656 | subst: impl IntoIterator<Item = Type<'db>>, |
| 1654 | 1657 | ) -> Option<Function> { |
| 1655 | let mut substs = hir_ty::TyBuilder::subst_for_def(self.db, TraitId::from(trait_), None); | |
| 1656 | for s in subst { | |
| 1657 | substs = substs.push(s.ty); | |
| 1658 | } | |
| 1659 | Some(self.db.lookup_impl_method(env.env, func.into(), substs.build()).0.into()) | |
| 1658 | let interner = DbInterner::new_with(self.db, None, None); | |
| 1659 | let mut subst = subst.into_iter(); | |
| 1660 | let substs = hir_ty::next_solver::GenericArgs::for_item( | |
| 1661 | interner, | |
| 1662 | trait_.id.into(), | |
| 1663 | |_, _, id, _| { | |
| 1664 | assert!(matches!(id, hir_def::GenericParamId::TypeParamId(_)), "expected a type"); | |
| 1665 | subst.next().expect("too few subst").ty.into() | |
| 1666 | }, | |
| 1667 | ); | |
| 1668 | assert!(subst.next().is_none(), "too many subst"); | |
| 1669 | Some(self.db.lookup_impl_method(env.env, func.into(), substs).0.into()) | |
| 1660 | 1670 | } |
| 1661 | 1671 | |
| 1662 | 1672 | fn resolve_range_pat(&self, range_pat: &ast::RangePat) -> Option<StructId> { |
src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs+127-130| ... | ... | @@ -7,18 +7,10 @@ |
| 7 | 7 | //! purely for "IDE needs". |
| 8 | 8 | use std::iter::{self, once}; |
| 9 | 9 | |
| 10 | use crate::{ | |
| 11 | Adt, AssocItem, BindingMode, BuiltinAttr, BuiltinType, Callable, Const, DeriveHelper, Field, | |
| 12 | Function, GenericSubstitution, Local, Macro, ModuleDef, Static, Struct, ToolModule, Trait, | |
| 13 | TupleField, Type, TypeAlias, Variant, | |
| 14 | db::HirDatabase, | |
| 15 | semantics::{PathResolution, PathResolutionPerNs}, | |
| 16 | }; | |
| 17 | use base_db::salsa; | |
| 18 | 10 | use either::Either; |
| 19 | 11 | use hir_def::{ |
| 20 | 12 | AdtId, AssocItemId, CallableDefId, ConstId, DefWithBodyId, FieldId, FunctionId, GenericDefId, |
| 21 | ItemContainerId, LocalFieldId, Lookup, ModuleDefId, StructId, TraitId, VariantId, | |
| 13 | LocalFieldId, ModuleDefId, StructId, TraitId, VariantId, | |
| 22 | 14 | expr_store::{ |
| 23 | 15 | Body, BodySourceMap, ExpressionStore, ExpressionStoreSourceMap, HygieneId, |
| 24 | 16 | lower::ExprCollector, |
| ... | ... | @@ -37,22 +29,24 @@ use hir_expand::{ |
| 37 | 29 | name::{AsName, Name}, |
| 38 | 30 | }; |
| 39 | 31 | use hir_ty::{ |
| 40 | Adjustment, AliasTy, InferenceResult, Interner, LifetimeElisionKind, ProjectionTy, | |
| 41 | Substitution, ToChalk, TraitEnvironment, Ty, TyExt, TyKind, TyLoweringContext, | |
| 32 | Adjustment, InferenceResult, LifetimeElisionKind, TraitEnvironment, TyLoweringContext, | |
| 42 | 33 | diagnostics::{ |
| 43 | 34 | InsideUnsafeBlock, record_literal_missing_fields, record_pattern_missing_fields, |
| 44 | 35 | unsafe_operations, |
| 45 | 36 | }, |
| 46 | from_assoc_type_id, | |
| 47 | 37 | lang_items::lang_items_for_bin_op, |
| 48 | 38 | method_resolution, |
| 49 | 39 | next_solver::{ |
| 50 | DbInterner, | |
| 51 | mapping::{ChalkToNextSolver, NextSolverToChalk}, | |
| 40 | DbInterner, ErrorGuaranteed, GenericArgs, Ty, TyKind, TypingMode, infer::DbInternerInferExt, | |
| 52 | 41 | }, |
| 42 | traits::structurally_normalize_ty, | |
| 53 | 43 | }; |
| 54 | 44 | use intern::sym; |
| 55 | 45 | use itertools::Itertools; |
| 46 | use rustc_type_ir::{ | |
| 47 | AliasTyKind, | |
| 48 | inherent::{AdtDef, IntoKind, Ty as _}, | |
| 49 | }; | |
| 56 | 50 | use smallvec::SmallVec; |
| 57 | 51 | use stdx::never; |
| 58 | 52 | use syntax::{ |
| ... | ... | @@ -61,22 +55,30 @@ use syntax::{ |
| 61 | 55 | }; |
| 62 | 56 | use triomphe::Arc; |
| 63 | 57 | |
| 58 | use crate::{ | |
| 59 | Adt, AssocItem, BindingMode, BuiltinAttr, BuiltinType, Callable, Const, DeriveHelper, Field, | |
| 60 | Function, GenericSubstitution, Local, Macro, ModuleDef, Static, Struct, ToolModule, Trait, | |
| 61 | TupleField, Type, TypeAlias, Variant, | |
| 62 | db::HirDatabase, | |
| 63 | semantics::{PathResolution, PathResolutionPerNs}, | |
| 64 | }; | |
| 65 | ||
| 64 | 66 | /// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of |
| 65 | 67 | /// original source files. It should not be used inside the HIR itself. |
| 66 | 68 | #[derive(Debug)] |
| 67 | 69 | pub(crate) struct SourceAnalyzer<'db> { |
| 68 | 70 | pub(crate) file_id: HirFileId, |
| 69 | 71 | pub(crate) resolver: Resolver<'db>, |
| 70 | pub(crate) body_or_sig: Option<BodyOrSig>, | |
| 72 | pub(crate) body_or_sig: Option<BodyOrSig<'db>>, | |
| 71 | 73 | } |
| 72 | 74 | |
| 73 | 75 | #[derive(Debug)] |
| 74 | pub(crate) enum BodyOrSig { | |
| 76 | pub(crate) enum BodyOrSig<'db> { | |
| 75 | 77 | Body { |
| 76 | 78 | def: DefWithBodyId, |
| 77 | 79 | body: Arc<Body>, |
| 78 | 80 | source_map: Arc<BodySourceMap>, |
| 79 | infer: Option<Arc<InferenceResult>>, | |
| 81 | infer: Option<Arc<InferenceResult<'db>>>, | |
| 80 | 82 | }, |
| 81 | 83 | // To be folded into body once it is considered one |
| 82 | 84 | VariantFields { |
| ... | ... | @@ -116,7 +118,7 @@ impl<'db> SourceAnalyzer<'db> { |
| 116 | 118 | def: DefWithBodyId, |
| 117 | 119 | node @ InFile { file_id, .. }: InFile<&SyntaxNode>, |
| 118 | 120 | offset: Option<TextSize>, |
| 119 | infer: Option<Arc<InferenceResult>>, | |
| 121 | infer: Option<Arc<InferenceResult<'db>>>, | |
| 120 | 122 | ) -> SourceAnalyzer<'db> { |
| 121 | 123 | let (body, source_map) = db.body_with_source_map(def); |
| 122 | 124 | let scopes = db.expr_scopes(def); |
| ... | ... | @@ -182,7 +184,9 @@ impl<'db> SourceAnalyzer<'db> { |
| 182 | 184 | } |
| 183 | 185 | |
| 184 | 186 | // FIXME: Remove this |
| 185 | fn body_(&self) -> Option<(DefWithBodyId, &Body, &BodySourceMap, Option<&InferenceResult>)> { | |
| 187 | fn body_( | |
| 188 | &self, | |
| 189 | ) -> Option<(DefWithBodyId, &Body, &BodySourceMap, Option<&InferenceResult<'db>>)> { | |
| 186 | 190 | self.body_or_sig.as_ref().and_then(|it| match it { |
| 187 | 191 | BodyOrSig::Body { def, body, source_map, infer } => { |
| 188 | 192 | Some((*def, &**body, &**source_map, infer.as_deref())) |
| ... | ... | @@ -191,7 +195,7 @@ impl<'db> SourceAnalyzer<'db> { |
| 191 | 195 | }) |
| 192 | 196 | } |
| 193 | 197 | |
| 194 | fn infer(&self) -> Option<&InferenceResult> { | |
| 198 | fn infer(&self) -> Option<&InferenceResult<'db>> { | |
| 195 | 199 | self.body_or_sig.as_ref().and_then(|it| match it { |
| 196 | 200 | BodyOrSig::Sig { .. } => None, |
| 197 | 201 | BodyOrSig::VariantFields { .. } => None, |
| ... | ... | @@ -250,7 +254,7 @@ impl<'db> SourceAnalyzer<'db> { |
| 250 | 254 | if let Pat::Bind { id, .. } = self.store()?[pat_id.as_pat()?] { Some(id) } else { None } |
| 251 | 255 | } |
| 252 | 256 | |
| 253 | pub(crate) fn expr_adjustments(&self, expr: &ast::Expr) -> Option<&[Adjustment]> { | |
| 257 | pub(crate) fn expr_adjustments(&self, expr: &ast::Expr) -> Option<&[Adjustment<'db>]> { | |
| 254 | 258 | // It is safe to omit destructuring assignments here because they have no adjustments (neither |
| 255 | 259 | // expressions nor patterns). |
| 256 | 260 | let expr_id = self.expr_id(expr.clone())?.as_expr()?; |
| ... | ... | @@ -288,9 +292,9 @@ impl<'db> SourceAnalyzer<'db> { |
| 288 | 292 | let coerced = expr_id |
| 289 | 293 | .as_expr() |
| 290 | 294 | .and_then(|expr_id| infer.expr_adjustment(expr_id)) |
| 291 | .and_then(|adjusts| adjusts.last().map(|adjust| adjust.target.clone())); | |
| 292 | let ty = infer[expr_id].clone(); | |
| 293 | let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty); | |
| 295 | .and_then(|adjusts| adjusts.last().map(|adjust| adjust.target)); | |
| 296 | let ty = infer[expr_id]; | |
| 297 | let mk_ty = |ty: Ty<'db>| Type::new_with_resolver(db, &self.resolver, ty); | |
| 294 | 298 | Some((mk_ty(ty), coerced.map(mk_ty))) |
| 295 | 299 | } |
| 296 | 300 | |
| ... | ... | @@ -311,8 +315,8 @@ impl<'db> SourceAnalyzer<'db> { |
| 311 | 315 | } |
| 312 | 316 | }; |
| 313 | 317 | |
| 314 | let ty = infer[expr_or_pat_id].clone(); | |
| 315 | let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty); | |
| 318 | let ty = infer[expr_or_pat_id]; | |
| 319 | let mk_ty = |ty: Ty<'db>| Type::new_with_resolver(db, &self.resolver, ty); | |
| 316 | 320 | Some((mk_ty(ty), coerced.map(mk_ty))) |
| 317 | 321 | } |
| 318 | 322 | |
| ... | ... | @@ -323,8 +327,8 @@ impl<'db> SourceAnalyzer<'db> { |
| 323 | 327 | ) -> Option<Type<'db>> { |
| 324 | 328 | let binding_id = self.binding_id_of_pat(pat)?; |
| 325 | 329 | let infer = self.infer()?; |
| 326 | let ty = infer[binding_id].clone(); | |
| 327 | let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty); | |
| 330 | let ty = infer[binding_id]; | |
| 331 | let mk_ty = |ty: Ty<'db>| Type::new_with_resolver(db, &self.resolver, ty); | |
| 328 | 332 | Some(mk_ty(ty)) |
| 329 | 333 | } |
| 330 | 334 | |
| ... | ... | @@ -334,7 +338,7 @@ impl<'db> SourceAnalyzer<'db> { |
| 334 | 338 | _param: &ast::SelfParam, |
| 335 | 339 | ) -> Option<Type<'db>> { |
| 336 | 340 | let binding = self.body()?.self_param?; |
| 337 | let ty = self.infer()?[binding].clone(); | |
| 341 | let ty = self.infer()?[binding]; | |
| 338 | 342 | Some(Type::new_with_resolver(db, &self.resolver, ty)) |
| 339 | 343 | } |
| 340 | 344 | |
| ... | ... | @@ -347,8 +351,10 @@ impl<'db> SourceAnalyzer<'db> { |
| 347 | 351 | let infer = self.infer()?; |
| 348 | 352 | infer.binding_mode(id.as_pat()?).map(|bm| match bm { |
| 349 | 353 | hir_ty::BindingMode::Move => BindingMode::Move, |
| 350 | hir_ty::BindingMode::Ref(hir_ty::Mutability::Mut) => BindingMode::Ref(Mutability::Mut), | |
| 351 | hir_ty::BindingMode::Ref(hir_ty::Mutability::Not) => { | |
| 354 | hir_ty::BindingMode::Ref(hir_ty::next_solver::Mutability::Mut) => { | |
| 355 | BindingMode::Ref(Mutability::Mut) | |
| 356 | } | |
| 357 | hir_ty::BindingMode::Ref(hir_ty::next_solver::Mutability::Not) => { | |
| 352 | 358 | BindingMode::Ref(Mutability::Shared) |
| 353 | 359 | } |
| 354 | 360 | }) |
| ... | ... | @@ -364,7 +370,7 @@ impl<'db> SourceAnalyzer<'db> { |
| 364 | 370 | infer |
| 365 | 371 | .pat_adjustment(pat_id.as_pat()?)? |
| 366 | 372 | .iter() |
| 367 | .map(|ty| Type::new_with_resolver(db, &self.resolver, ty.clone())) | |
| 373 | .map(|ty| Type::new_with_resolver(db, &self.resolver, *ty)) | |
| 368 | 374 | .collect(), |
| 369 | 375 | ) |
| 370 | 376 | } |
| ... | ... | @@ -375,11 +381,10 @@ impl<'db> SourceAnalyzer<'db> { |
| 375 | 381 | call: &ast::MethodCallExpr, |
| 376 | 382 | ) -> Option<Callable<'db>> { |
| 377 | 383 | let expr_id = self.expr_id(call.clone().into())?.as_expr()?; |
| 378 | let (func, substs) = self.infer()?.method_resolution(expr_id)?; | |
| 384 | let (func, args) = self.infer()?.method_resolution(expr_id)?; | |
| 379 | 385 | let interner = DbInterner::new_with(db, None, None); |
| 380 | let args: hir_ty::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); | |
| 381 | 386 | let ty = db.value_ty(func.into())?.instantiate(interner, args); |
| 382 | let ty = Type::new_with_resolver(db, &self.resolver, ty.to_chalk(interner)); | |
| 387 | let ty = Type::new_with_resolver(db, &self.resolver, ty); | |
| 383 | 388 | let mut res = ty.as_callable(db)?; |
| 384 | 389 | res.is_bound_method = true; |
| 385 | 390 | Some(res) |
| ... | ... | @@ -443,17 +448,13 @@ impl<'db> SourceAnalyzer<'db> { |
| 443 | 448 | fn field_subst( |
| 444 | 449 | &self, |
| 445 | 450 | field_expr: ExprId, |
| 446 | infer: &InferenceResult, | |
| 451 | infer: &InferenceResult<'db>, | |
| 447 | 452 | db: &'db dyn HirDatabase, |
| 448 | 453 | ) -> Option<GenericSubstitution<'db>> { |
| 449 | 454 | let body = self.store()?; |
| 450 | 455 | if let Expr::Field { expr: object_expr, name: _ } = body[field_expr] { |
| 451 | 456 | let (adt, subst) = infer.type_of_expr_with_adjust(object_expr)?.as_adt()?; |
| 452 | return Some(GenericSubstitution::new( | |
| 453 | adt.into(), | |
| 454 | subst.clone(), | |
| 455 | self.trait_environment(db), | |
| 456 | )); | |
| 457 | return Some(GenericSubstitution::new(adt.into(), subst, self.trait_environment(db))); | |
| 457 | 458 | } |
| 458 | 459 | None |
| 459 | 460 | } |
| ... | ... | @@ -536,7 +537,7 @@ impl<'db> SourceAnalyzer<'db> { |
| 536 | 537 | db: &'db dyn HirDatabase, |
| 537 | 538 | await_expr: &ast::AwaitExpr, |
| 538 | 539 | ) -> Option<FunctionId> { |
| 539 | let mut ty = self.ty_of_expr(await_expr.expr()?)?.clone(); | |
| 540 | let mut ty = self.ty_of_expr(await_expr.expr()?)?; | |
| 540 | 541 | |
| 541 | 542 | let into_future_trait = self |
| 542 | 543 | .resolver |
| ... | ... | @@ -544,7 +545,7 @@ impl<'db> SourceAnalyzer<'db> { |
| 544 | 545 | .map(Trait::from); |
| 545 | 546 | |
| 546 | 547 | if let Some(into_future_trait) = into_future_trait { |
| 547 | let type_ = Type::new_with_resolver(db, &self.resolver, ty.clone()); | |
| 548 | let type_ = Type::new_with_resolver(db, &self.resolver, ty); | |
| 548 | 549 | if type_.impls_trait(db, into_future_trait, &[]) { |
| 549 | 550 | let items = into_future_trait.items(db); |
| 550 | 551 | let into_future_type = items.into_iter().find_map(|item| match item { |
| ... | ... | @@ -560,11 +561,11 @@ impl<'db> SourceAnalyzer<'db> { |
| 560 | 561 | } |
| 561 | 562 | } |
| 562 | 563 | |
| 563 | let future_trait = LangItem::Future.resolve_trait(db, self.resolver.krate())?; | |
| 564 | 564 | let poll_fn = LangItem::FuturePoll.resolve_function(db, self.resolver.krate())?; |
| 565 | 565 | // HACK: subst for `poll()` coincides with that for `Future` because `poll()` itself |
| 566 | 566 | // doesn't have any generic parameters, so we skip building another subst for `poll()`. |
| 567 | let substs = hir_ty::TyBuilder::subst_for_def(db, future_trait, None).push(ty).build(); | |
| 567 | let interner = DbInterner::new_with(db, None, None); | |
| 568 | let substs = GenericArgs::new_from_iter(interner, [ty.into()]); | |
| 568 | 569 | Some(self.resolve_impl_method_or_trait_def(db, poll_fn, substs)) |
| 569 | 570 | } |
| 570 | 571 | |
| ... | ... | @@ -573,7 +574,7 @@ impl<'db> SourceAnalyzer<'db> { |
| 573 | 574 | db: &'db dyn HirDatabase, |
| 574 | 575 | prefix_expr: &ast::PrefixExpr, |
| 575 | 576 | ) -> Option<FunctionId> { |
| 576 | let (op_trait, op_fn) = match prefix_expr.op_kind()? { | |
| 577 | let (_op_trait, op_fn) = match prefix_expr.op_kind()? { | |
| 577 | 578 | ast::UnaryOp::Deref => { |
| 578 | 579 | // This can be either `Deref::deref` or `DerefMut::deref_mut`. |
| 579 | 580 | // Since deref kind is inferenced and stored in `InferenceResult.method_resolution`, |
| ... | ... | @@ -603,9 +604,10 @@ impl<'db> SourceAnalyzer<'db> { |
| 603 | 604 | |
| 604 | 605 | let ty = self.ty_of_expr(prefix_expr.expr()?)?; |
| 605 | 606 | |
| 607 | let interner = DbInterner::new_with(db, None, None); | |
| 606 | 608 | // HACK: subst for all methods coincides with that for their trait because the methods |
| 607 | 609 | // don't have any generic parameters, so we skip building another subst for the methods. |
| 608 | let substs = hir_ty::TyBuilder::subst_for_def(db, op_trait, None).push(ty.clone()).build(); | |
| 610 | let substs = GenericArgs::new_from_iter(interner, [ty.into()]); | |
| 609 | 611 | |
| 610 | 612 | Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs)) |
| 611 | 613 | } |
| ... | ... | @@ -618,27 +620,25 @@ impl<'db> SourceAnalyzer<'db> { |
| 618 | 620 | let base_ty = self.ty_of_expr(index_expr.base()?)?; |
| 619 | 621 | let index_ty = self.ty_of_expr(index_expr.index()?)?; |
| 620 | 622 | |
| 621 | let (index_trait, index_fn) = | |
| 623 | let (_index_trait, index_fn) = | |
| 622 | 624 | self.lang_trait_fn(db, LangItem::Index, &Name::new_symbol_root(sym::index))?; |
| 623 | let (op_trait, op_fn) = self | |
| 625 | let op_fn = self | |
| 624 | 626 | .infer() |
| 625 | 627 | .and_then(|infer| { |
| 626 | 628 | let expr = self.expr_id(index_expr.clone().into())?.as_expr()?; |
| 627 | 629 | let (func, _) = infer.method_resolution(expr)?; |
| 628 | let (index_mut_trait, index_mut_fn) = self.lang_trait_fn( | |
| 630 | let (_index_mut_trait, index_mut_fn) = self.lang_trait_fn( | |
| 629 | 631 | db, |
| 630 | 632 | LangItem::IndexMut, |
| 631 | 633 | &Name::new_symbol_root(sym::index_mut), |
| 632 | 634 | )?; |
| 633 | if func == index_mut_fn { Some((index_mut_trait, index_mut_fn)) } else { None } | |
| 635 | if func == index_mut_fn { Some(index_mut_fn) } else { None } | |
| 634 | 636 | }) |
| 635 | .unwrap_or((index_trait, index_fn)); | |
| 637 | .unwrap_or(index_fn); | |
| 636 | 638 | // HACK: subst for all methods coincides with that for their trait because the methods |
| 637 | 639 | // don't have any generic parameters, so we skip building another subst for the methods. |
| 638 | let substs = hir_ty::TyBuilder::subst_for_def(db, op_trait, None) | |
| 639 | .push(base_ty.clone()) | |
| 640 | .push(index_ty.clone()) | |
| 641 | .build(); | |
| 640 | let interner = DbInterner::new_with(db, None, None); | |
| 641 | let substs = GenericArgs::new_from_iter(interner, [base_ty.into(), index_ty.into()]); | |
| 642 | 642 | Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs)) |
| 643 | 643 | } |
| 644 | 644 | |
| ... | ... | @@ -651,14 +651,12 @@ impl<'db> SourceAnalyzer<'db> { |
| 651 | 651 | let lhs = self.ty_of_expr(binop_expr.lhs()?)?; |
| 652 | 652 | let rhs = self.ty_of_expr(binop_expr.rhs()?)?; |
| 653 | 653 | |
| 654 | let (op_trait, op_fn) = lang_items_for_bin_op(op) | |
| 654 | let (_op_trait, op_fn) = lang_items_for_bin_op(op) | |
| 655 | 655 | .and_then(|(name, lang_item)| self.lang_trait_fn(db, lang_item, &name))?; |
| 656 | 656 | // HACK: subst for `index()` coincides with that for `Index` because `index()` itself |
| 657 | 657 | // doesn't have any generic parameters, so we skip building another subst for `index()`. |
| 658 | let substs = hir_ty::TyBuilder::subst_for_def(db, op_trait, None) | |
| 659 | .push(lhs.clone()) | |
| 660 | .push(rhs.clone()) | |
| 661 | .build(); | |
| 658 | let interner = DbInterner::new_with(db, None, None); | |
| 659 | let substs = GenericArgs::new_from_iter(interner, [lhs.into(), rhs.into()]); | |
| 662 | 660 | |
| 663 | 661 | Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs)) |
| 664 | 662 | } |
| ... | ... | @@ -671,13 +669,10 @@ impl<'db> SourceAnalyzer<'db> { |
| 671 | 669 | let ty = self.ty_of_expr(try_expr.expr()?)?; |
| 672 | 670 | |
| 673 | 671 | let op_fn = LangItem::TryTraitBranch.resolve_function(db, self.resolver.krate())?; |
| 674 | let op_trait = match op_fn.lookup(db).container { | |
| 675 | ItemContainerId::TraitId(id) => id, | |
| 676 | _ => return None, | |
| 677 | }; | |
| 678 | 672 | // HACK: subst for `branch()` coincides with that for `Try` because `branch()` itself |
| 679 | 673 | // doesn't have any generic parameters, so we skip building another subst for `branch()`. |
| 680 | let substs = hir_ty::TyBuilder::subst_for_def(db, op_trait, None).push(ty.clone()).build(); | |
| 674 | let interner = DbInterner::new_with(db, None, None); | |
| 675 | let substs = GenericArgs::new_from_iter(interner, [ty.into()]); | |
| 681 | 676 | |
| 682 | 677 | Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs)) |
| 683 | 678 | } |
| ... | ... | @@ -690,6 +685,7 @@ impl<'db> SourceAnalyzer<'db> { |
| 690 | 685 | let record_expr = ast::RecordExpr::cast(field.syntax().parent().and_then(|p| p.parent())?)?; |
| 691 | 686 | let expr = ast::Expr::from(record_expr); |
| 692 | 687 | let expr_id = self.store_sm()?.node_expr(InFile::new(self.file_id, &expr))?; |
| 688 | let interner = DbInterner::new_with(db, None, None); | |
| 693 | 689 | |
| 694 | 690 | let ast_name = field.field_name()?; |
| 695 | 691 | let local_name = ast_name.as_name(); |
| ... | ... | @@ -717,12 +713,12 @@ impl<'db> SourceAnalyzer<'db> { |
| 717 | 713 | let variant_data = variant.fields(db); |
| 718 | 714 | let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? }; |
| 719 | 715 | let field_ty = |
| 720 | db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst); | |
| 716 | (*db.field_types_ns(variant).get(field.local_id)?).instantiate(interner, subst); | |
| 721 | 717 | Some(( |
| 722 | 718 | field.into(), |
| 723 | 719 | local, |
| 724 | 720 | Type::new_with_resolver(db, &self.resolver, field_ty), |
| 725 | GenericSubstitution::new(adt.into(), subst.clone(), self.trait_environment(db)), | |
| 721 | GenericSubstitution::new(adt.into(), subst, self.trait_environment(db)), | |
| 726 | 722 | )) |
| 727 | 723 | } |
| 728 | 724 | |
| ... | ... | @@ -731,6 +727,7 @@ impl<'db> SourceAnalyzer<'db> { |
| 731 | 727 | db: &'db dyn HirDatabase, |
| 732 | 728 | field: &ast::RecordPatField, |
| 733 | 729 | ) -> Option<(Field, Type<'db>, GenericSubstitution<'db>)> { |
| 730 | let interner = DbInterner::new_with(db, None, None); | |
| 734 | 731 | let field_name = field.field_name()?.as_name(); |
| 735 | 732 | let record_pat = ast::RecordPat::cast(field.syntax().parent().and_then(|p| p.parent())?)?; |
| 736 | 733 | let pat_id = self.pat_id(&record_pat.into())?; |
| ... | ... | @@ -739,11 +736,11 @@ impl<'db> SourceAnalyzer<'db> { |
| 739 | 736 | let field = FieldId { parent: variant, local_id: variant_data.field(&field_name)? }; |
| 740 | 737 | let (adt, subst) = self.infer()?[pat_id.as_pat()?].as_adt()?; |
| 741 | 738 | let field_ty = |
| 742 | db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst); | |
| 739 | (*db.field_types_ns(variant).get(field.local_id)?).instantiate(interner, subst); | |
| 743 | 740 | Some(( |
| 744 | 741 | field.into(), |
| 745 | 742 | Type::new_with_resolver(db, &self.resolver, field_ty), |
| 746 | GenericSubstitution::new(adt.into(), subst.clone(), self.trait_environment(db)), | |
| 743 | GenericSubstitution::new(adt.into(), subst, self.trait_environment(db)), | |
| 747 | 744 | )) |
| 748 | 745 | } |
| 749 | 746 | |
| ... | ... | @@ -792,43 +789,40 @@ impl<'db> SourceAnalyzer<'db> { |
| 792 | 789 | let container = self.type_of_type(db, &container)?; |
| 793 | 790 | |
| 794 | 791 | let trait_env = container.env; |
| 792 | ||
| 793 | let interner = DbInterner::new_with(db, Some(trait_env.krate), trait_env.block); | |
| 794 | let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); | |
| 795 | ||
| 795 | 796 | let mut container = Either::Right(container.ty); |
| 796 | 797 | for field_name in offset_of_expr.fields() { |
| 797 | if let Some( | |
| 798 | TyKind::Alias(AliasTy::Projection(ProjectionTy { associated_ty_id, substitution })) | |
| 799 | | TyKind::AssociatedType(associated_ty_id, substitution), | |
| 800 | ) = container.as_ref().right().map(|it| it.kind(Interner)) | |
| 801 | { | |
| 802 | let projection = ProjectionTy { | |
| 803 | associated_ty_id: *associated_ty_id, | |
| 804 | substitution: substitution.clone(), | |
| 805 | }; | |
| 806 | container = Either::Right(db.normalize_projection(projection, trait_env.clone())); | |
| 798 | if let Either::Right(container) = &mut container { | |
| 799 | *container = structurally_normalize_ty(&infcx, *container, trait_env.clone()); | |
| 807 | 800 | } |
| 808 | let handle_variants = |variant: VariantId, subst: &Substitution, container: &mut _| { | |
| 809 | let fields = variant.fields(db); | |
| 810 | let field = fields.field(&field_name.as_name())?; | |
| 811 | let field_types = db.field_types(variant); | |
| 812 | *container = Either::Right(field_types[field].clone().substitute(Interner, subst)); | |
| 813 | let generic_def = match variant { | |
| 814 | VariantId::EnumVariantId(it) => it.loc(db).parent.into(), | |
| 815 | VariantId::StructId(it) => it.into(), | |
| 816 | VariantId::UnionId(it) => it.into(), | |
| 801 | let handle_variants = | |
| 802 | |variant: VariantId, subst: GenericArgs<'db>, container: &mut _| { | |
| 803 | let fields = variant.fields(db); | |
| 804 | let field = fields.field(&field_name.as_name())?; | |
| 805 | let field_types = db.field_types_ns(variant); | |
| 806 | *container = Either::Right(field_types[field].instantiate(interner, subst)); | |
| 807 | let generic_def = match variant { | |
| 808 | VariantId::EnumVariantId(it) => it.loc(db).parent.into(), | |
| 809 | VariantId::StructId(it) => it.into(), | |
| 810 | VariantId::UnionId(it) => it.into(), | |
| 811 | }; | |
| 812 | Some(( | |
| 813 | Either::Right(Field { parent: variant.into(), id: field }), | |
| 814 | generic_def, | |
| 815 | subst, | |
| 816 | )) | |
| 817 | 817 | }; |
| 818 | Some(( | |
| 819 | Either::Right(Field { parent: variant.into(), id: field }), | |
| 820 | generic_def, | |
| 821 | subst.clone(), | |
| 822 | )) | |
| 823 | }; | |
| 824 | let temp_ty = TyKind::Error.intern(Interner); | |
| 818 | let temp_ty = Ty::new_error(interner, ErrorGuaranteed); | |
| 825 | 819 | let (field_def, generic_def, subst) = |
| 826 | match std::mem::replace(&mut container, Either::Right(temp_ty.clone())) { | |
| 820 | match std::mem::replace(&mut container, Either::Right(temp_ty)) { | |
| 827 | 821 | Either::Left((variant_id, subst)) => { |
| 828 | handle_variants(VariantId::from(variant_id), &subst, &mut container)? | |
| 822 | handle_variants(VariantId::from(variant_id), subst, &mut container)? | |
| 829 | 823 | } |
| 830 | Either::Right(container_ty) => match container_ty.kind(Interner) { | |
| 831 | TyKind::Adt(adt_id, subst) => match adt_id.0 { | |
| 824 | Either::Right(container_ty) => match container_ty.kind() { | |
| 825 | TyKind::Adt(adt_def, subst) => match adt_def.def_id().0 { | |
| 832 | 826 | AdtId::StructId(id) => { |
| 833 | 827 | handle_variants(id.into(), subst, &mut container)? |
| 834 | 828 | } |
| ... | ... | @@ -838,8 +832,8 @@ impl<'db> SourceAnalyzer<'db> { |
| 838 | 832 | AdtId::EnumId(id) => { |
| 839 | 833 | let variants = id.enum_variants(db); |
| 840 | 834 | let variant = variants.variant(&field_name.as_name())?; |
| 841 | container = Either::Left((variant, subst.clone())); | |
| 842 | (Either::Left(Variant { id: variant }), id.into(), subst.clone()) | |
| 835 | container = Either::Left((variant, subst)); | |
| 836 | (Either::Left(Variant { id: variant }), id.into(), subst) | |
| 843 | 837 | } |
| 844 | 838 | }, |
| 845 | 839 | _ => return None, |
| ... | ... | @@ -880,12 +874,10 @@ impl<'db> SourceAnalyzer<'db> { |
| 880 | 874 | (assoc, subst) |
| 881 | 875 | } |
| 882 | 876 | Some(func_ty) => { |
| 883 | if let TyKind::FnDef(_fn_def, subs) = func_ty.kind(Interner) { | |
| 877 | if let TyKind::FnDef(_fn_def, subs) = func_ty.kind() { | |
| 884 | 878 | let (fn_, subst) = self |
| 885 | 879 | .resolve_impl_method_or_trait_def_with_subst( |
| 886 | db, | |
| 887 | f_in_trait, | |
| 888 | subs.clone(), | |
| 880 | db, f_in_trait, subs, | |
| 889 | 881 | ); |
| 890 | 882 | let subst = GenericSubstitution::new( |
| 891 | 883 | fn_.into(), |
| ... | ... | @@ -1152,33 +1144,35 @@ impl<'db> SourceAnalyzer<'db> { |
| 1152 | 1144 | self.infer()?.type_of_expr_or_pat(expr_id)? |
| 1153 | 1145 | } else if let Some(pat) = ast::Pat::cast(parent) { |
| 1154 | 1146 | let pat_id = self.pat_id(&pat)?; |
| 1155 | &self.infer()?[pat_id] | |
| 1147 | self.infer()?[pat_id] | |
| 1156 | 1148 | } else { |
| 1157 | 1149 | return None; |
| 1158 | 1150 | }; |
| 1159 | 1151 | let env = self.trait_environment(db); |
| 1160 | let (subst, expected_resolution) = match ty.kind(Interner) { | |
| 1161 | TyKind::Adt(adt_id, subst) => ( | |
| 1162 | GenericSubstitution::new(adt_id.0.into(), subst.clone(), env), | |
| 1163 | PathResolution::Def(ModuleDef::Adt(adt_id.0.into())), | |
| 1164 | ), | |
| 1165 | TyKind::AssociatedType(assoc_id, subst) => { | |
| 1166 | let assoc_id = from_assoc_type_id(*assoc_id); | |
| 1152 | let (subst, expected_resolution) = match ty.kind() { | |
| 1153 | TyKind::Adt(adt_def, subst) => { | |
| 1154 | let adt_id = adt_def.def_id().0; | |
| 1167 | 1155 | ( |
| 1168 | GenericSubstitution::new(assoc_id.into(), subst.clone(), env), | |
| 1156 | GenericSubstitution::new(adt_id.into(), subst, env), | |
| 1157 | PathResolution::Def(ModuleDef::Adt(adt_id.into())), | |
| 1158 | ) | |
| 1159 | } | |
| 1160 | TyKind::Alias(AliasTyKind::Projection, alias) => { | |
| 1161 | let assoc_id = alias.def_id.expect_type_alias(); | |
| 1162 | ( | |
| 1163 | GenericSubstitution::new(assoc_id.into(), alias.args, env), | |
| 1169 | 1164 | PathResolution::Def(ModuleDef::TypeAlias(assoc_id.into())), |
| 1170 | 1165 | ) |
| 1171 | 1166 | } |
| 1172 | 1167 | TyKind::FnDef(fn_id, subst) => { |
| 1173 | let fn_id = ToChalk::from_chalk(db, *fn_id); | |
| 1174 | let generic_def_id = match fn_id { | |
| 1168 | let generic_def_id = match fn_id.0 { | |
| 1175 | 1169 | CallableDefId::StructId(id) => id.into(), |
| 1176 | 1170 | CallableDefId::FunctionId(id) => id.into(), |
| 1177 | 1171 | CallableDefId::EnumVariantId(_) => return None, |
| 1178 | 1172 | }; |
| 1179 | 1173 | ( |
| 1180 | GenericSubstitution::new(generic_def_id, subst.clone(), env), | |
| 1181 | PathResolution::Def(ModuleDefId::from(fn_id).into()), | |
| 1174 | GenericSubstitution::new(generic_def_id, subst, env), | |
| 1175 | PathResolution::Def(ModuleDefId::from(fn_id.0).into()), | |
| 1182 | 1176 | ) |
| 1183 | 1177 | } |
| 1184 | 1178 | _ => return None, |
| ... | ... | @@ -1256,17 +1250,18 @@ impl<'db> SourceAnalyzer<'db> { |
| 1256 | 1250 | fn missing_fields( |
| 1257 | 1251 | &self, |
| 1258 | 1252 | db: &'db dyn HirDatabase, |
| 1259 | substs: &Substitution, | |
| 1253 | substs: GenericArgs<'db>, | |
| 1260 | 1254 | variant: VariantId, |
| 1261 | 1255 | missing_fields: Vec<LocalFieldId>, |
| 1262 | 1256 | ) -> Vec<(Field, Type<'db>)> { |
| 1263 | let field_types = db.field_types(variant); | |
| 1257 | let interner = DbInterner::new_with(db, None, None); | |
| 1258 | let field_types = db.field_types_ns(variant); | |
| 1264 | 1259 | |
| 1265 | 1260 | missing_fields |
| 1266 | 1261 | .into_iter() |
| 1267 | 1262 | .map(|local_id| { |
| 1268 | 1263 | let field = FieldId { parent: variant, local_id }; |
| 1269 | let ty = field_types[local_id].clone().substitute(Interner, substs); | |
| 1264 | let ty = field_types[local_id].instantiate(interner, substs); | |
| 1270 | 1265 | (field.into(), Type::new_with_resolver_inner(db, &self.resolver, ty)) |
| 1271 | 1266 | }) |
| 1272 | 1267 | .collect() |
| ... | ... | @@ -1379,7 +1374,7 @@ impl<'db> SourceAnalyzer<'db> { |
| 1379 | 1374 | &self, |
| 1380 | 1375 | db: &'db dyn HirDatabase, |
| 1381 | 1376 | func: FunctionId, |
| 1382 | substs: Substitution, | |
| 1377 | substs: GenericArgs<'db>, | |
| 1383 | 1378 | ) -> FunctionId { |
| 1384 | 1379 | self.resolve_impl_method_or_trait_def_with_subst(db, func, substs).0 |
| 1385 | 1380 | } |
| ... | ... | @@ -1388,8 +1383,8 @@ impl<'db> SourceAnalyzer<'db> { |
| 1388 | 1383 | &self, |
| 1389 | 1384 | db: &'db dyn HirDatabase, |
| 1390 | 1385 | func: FunctionId, |
| 1391 | substs: Substitution, | |
| 1392 | ) -> (FunctionId, Substitution) { | |
| 1386 | substs: GenericArgs<'db>, | |
| 1387 | ) -> (FunctionId, GenericArgs<'db>) { | |
| 1393 | 1388 | let owner = match self.resolver.body_owner() { |
| 1394 | 1389 | Some(it) => it, |
| 1395 | 1390 | None => return (func, substs), |
| ... | ... | @@ -1402,14 +1397,16 @@ impl<'db> SourceAnalyzer<'db> { |
| 1402 | 1397 | &self, |
| 1403 | 1398 | db: &'db dyn HirDatabase, |
| 1404 | 1399 | const_id: ConstId, |
| 1405 | subs: Substitution, | |
| 1406 | ) -> (ConstId, Substitution) { | |
| 1400 | subs: GenericArgs<'db>, | |
| 1401 | ) -> (ConstId, GenericArgs<'db>) { | |
| 1407 | 1402 | let owner = match self.resolver.body_owner() { |
| 1408 | 1403 | Some(it) => it, |
| 1409 | 1404 | None => return (const_id, subs), |
| 1410 | 1405 | }; |
| 1411 | 1406 | let env = db.trait_environment_for_body(owner); |
| 1412 | method_resolution::lookup_impl_const(db, env, const_id, subs) | |
| 1407 | let interner = DbInterner::new_with(db, Some(env.krate), env.block); | |
| 1408 | let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); | |
| 1409 | method_resolution::lookup_impl_const(&infcx, env, const_id, subs) | |
| 1413 | 1410 | } |
| 1414 | 1411 | |
| 1415 | 1412 | fn lang_trait_fn( |
| ... | ... | @@ -1423,7 +1420,7 @@ impl<'db> SourceAnalyzer<'db> { |
| 1423 | 1420 | Some((trait_id, fn_id)) |
| 1424 | 1421 | } |
| 1425 | 1422 | |
| 1426 | fn ty_of_expr(&self, expr: ast::Expr) -> Option<&Ty> { | |
| 1423 | fn ty_of_expr(&self, expr: ast::Expr) -> Option<Ty<'db>> { | |
| 1427 | 1424 | self.infer()?.type_of_expr_or_pat(self.expr_id(expr)?) |
| 1428 | 1425 | } |
| 1429 | 1426 | } |
| ... | ... | @@ -1599,7 +1596,7 @@ fn resolve_hir_path_( |
| 1599 | 1596 | Some(unresolved) => resolver |
| 1600 | 1597 | .generic_def() |
| 1601 | 1598 | .and_then(|def| { |
| 1602 | salsa::attach(db, || { | |
| 1599 | hir_ty::attach_db(db, || { | |
| 1603 | 1600 | hir_ty::associated_type_shorthand_candidates( |
| 1604 | 1601 | db, |
| 1605 | 1602 | def, |
src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs+13-9| ... | ... | @@ -10,20 +10,21 @@ |
| 10 | 10 | |
| 11 | 11 | use std::iter; |
| 12 | 12 | |
| 13 | use hir_ty::TyBuilder; | |
| 14 | use hir_ty::db::HirDatabase; | |
| 15 | use hir_ty::mir::BorrowKind; | |
| 13 | use hir_ty::{ | |
| 14 | db::HirDatabase, | |
| 15 | mir::BorrowKind, | |
| 16 | next_solver::{DbInterner, Ty}, | |
| 17 | }; | |
| 16 | 18 | use itertools::Itertools; |
| 17 | 19 | use rustc_hash::FxHashSet; |
| 20 | use rustc_type_ir::inherent::Ty as _; | |
| 18 | 21 | use span::Edition; |
| 19 | 22 | |
| 20 | 23 | use crate::{ |
| 21 | 24 | Adt, AssocItem, GenericDef, GenericParam, HasAttrs, HasVisibility, Impl, ModuleDef, ScopeDef, |
| 22 | Type, TypeParam, | |
| 25 | Type, TypeParam, term_search::Expr, | |
| 23 | 26 | }; |
| 24 | 27 | |
| 25 | use crate::term_search::Expr; | |
| 26 | ||
| 27 | 28 | use super::{LookupTable, NewTypesKey, TermSearchCtx}; |
| 28 | 29 | |
| 29 | 30 | /// # Trivial tactic |
| ... | ... | @@ -596,10 +597,13 @@ pub(super) fn famous_types<'a, 'lt, 'db, DB: HirDatabase>( |
| 596 | 597 | ) -> impl Iterator<Item = Expr<'db>> + use<'a, 'db, 'lt, DB> { |
| 597 | 598 | let db = ctx.sema.db; |
| 598 | 599 | let module = ctx.scope.module(); |
| 600 | let interner = DbInterner::new_with(db, None, None); | |
| 601 | let bool_ty = Ty::new_bool(interner); | |
| 602 | let unit_ty = Ty::new_unit(interner); | |
| 599 | 603 | [ |
| 600 | Expr::FamousType { ty: Type::new(db, module.id, TyBuilder::bool()), value: "true" }, | |
| 601 | Expr::FamousType { ty: Type::new(db, module.id, TyBuilder::bool()), value: "false" }, | |
| 602 | Expr::FamousType { ty: Type::new(db, module.id, TyBuilder::unit()), value: "()" }, | |
| 604 | Expr::FamousType { ty: Type::new(db, module.id, bool_ty), value: "true" }, | |
| 605 | Expr::FamousType { ty: Type::new(db, module.id, bool_ty), value: "false" }, | |
| 606 | Expr::FamousType { ty: Type::new(db, module.id, unit_ty), value: "()" }, | |
| 603 | 607 | ] |
| 604 | 608 | .into_iter() |
| 605 | 609 | .inspect(|exprs| { |
src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs+1-1| ... | ... | @@ -38,7 +38,7 @@ impl AssistConfig { |
| 38 | 38 | } |
| 39 | 39 | } |
| 40 | 40 | |
| 41 | pub fn find_path_confg(&self, allow_unstable: bool) -> FindPathConfig { | |
| 41 | pub fn find_path_config(&self, allow_unstable: bool) -> FindPathConfig { | |
| 42 | 42 | FindPathConfig { |
| 43 | 43 | prefer_no_std: self.prefer_no_std, |
| 44 | 44 | prefer_prelude: self.prefer_prelude, |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_explicit_type.rs+18-2| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | use either::Either; | |
| 1 | 2 | use hir::HirDisplay; |
| 2 | 3 | use ide_db::syntax_helpers::node_ext::walk_ty; |
| 3 | 4 | use syntax::ast::{self, AstNode, LetStmt, Param}; |
| ... | ... | @@ -20,7 +21,8 @@ use crate::{AssistContext, AssistId, Assists}; |
| 20 | 21 | // } |
| 21 | 22 | // ``` |
| 22 | 23 | pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { |
| 23 | let (ascribed_ty, expr, pat) = if let Some(let_stmt) = ctx.find_node_at_offset::<LetStmt>() { | |
| 24 | let syntax_node = ctx.find_node_at_offset::<Either<LetStmt, Param>>()?; | |
| 25 | let (ascribed_ty, expr, pat) = if let Either::Left(let_stmt) = syntax_node { | |
| 24 | 26 | let cursor_in_range = { |
| 25 | 27 | let eq_range = let_stmt.eq_token()?.text_range(); |
| 26 | 28 | ctx.offset() < eq_range.start() |
| ... | ... | @@ -31,7 +33,7 @@ pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> O |
| 31 | 33 | } |
| 32 | 34 | |
| 33 | 35 | (let_stmt.ty(), let_stmt.initializer(), let_stmt.pat()?) |
| 34 | } else if let Some(param) = ctx.find_node_at_offset::<Param>() { | |
| 36 | } else if let Either::Right(param) = syntax_node { | |
| 35 | 37 | if param.syntax().ancestors().nth(2).and_then(ast::ClosureExpr::cast).is_none() { |
| 36 | 38 | cov_mark::hit!(add_explicit_type_not_applicable_in_fn_param); |
| 37 | 39 | return None; |
| ... | ... | @@ -298,6 +300,20 @@ fn f() { |
| 298 | 300 | let x: i32 = y; |
| 299 | 301 | }; |
| 300 | 302 | } |
| 303 | "#, | |
| 304 | ); | |
| 305 | ||
| 306 | check_assist( | |
| 307 | add_explicit_type, | |
| 308 | r#" | |
| 309 | fn f() { | |
| 310 | let f: fn(i32) = |y$0| {}; | |
| 311 | } | |
| 312 | "#, | |
| 313 | r#" | |
| 314 | fn f() { | |
| 315 | let f: fn(i32) = |y: i32| {}; | |
| 316 | } | |
| 301 | 317 | "#, |
| 302 | 318 | ); |
| 303 | 319 | } |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs+1-1| ... | ... | @@ -80,7 +80,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) |
| 80 | 80 | |
| 81 | 81 | let scope = ctx.sema.scope(expr.syntax())?; |
| 82 | 82 | let module = scope.module(); |
| 83 | let cfg = ctx.config.find_path_confg(ctx.sema.is_nightly(scope.krate())); | |
| 83 | let cfg = ctx.config.find_path_config(ctx.sema.is_nightly(scope.krate())); | |
| 84 | 84 | let self_ty = if ctx.config.prefer_self_ty { |
| 85 | 85 | scope |
| 86 | 86 | .containing_function() |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_return_type.rs+16-1| ... | ... | @@ -18,7 +18,7 @@ use crate::{AssistContext, AssistId, Assists}; |
| 18 | 18 | pub(crate) fn add_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { |
| 19 | 19 | let (fn_type, tail_expr, builder_edit_pos) = extract_tail(ctx)?; |
| 20 | 20 | let module = ctx.sema.scope(tail_expr.syntax())?.module(); |
| 21 | let ty = ctx.sema.type_of_expr(&peel_blocks(tail_expr.clone()))?.original(); | |
| 21 | let ty = ctx.sema.type_of_expr(&peel_blocks(tail_expr.clone()))?.adjusted(); | |
| 22 | 22 | if ty.is_unit() { |
| 23 | 23 | return None; |
| 24 | 24 | } |
| ... | ... | @@ -421,6 +421,21 @@ mod tests { |
| 421 | 421 | ); |
| 422 | 422 | } |
| 423 | 423 | |
| 424 | #[test] | |
| 425 | fn infer_coerced_return_type_closure() { | |
| 426 | check_assist( | |
| 427 | add_return_type, | |
| 428 | r#"fn foo() { | |
| 429 | let f = ||$0 {loop {}}; | |
| 430 | let _: fn() -> i8 = f; | |
| 431 | }"#, | |
| 432 | r#"fn foo() { | |
| 433 | let f = || -> i8 {loop {}}; | |
| 434 | let _: fn() -> i8 = f; | |
| 435 | }"#, | |
| 436 | ); | |
| 437 | } | |
| 438 | ||
| 424 | 439 | #[test] |
| 425 | 440 | fn not_applicable_ret_type_specified_closure() { |
| 426 | 441 | cov_mark::check!(existing_ret_type_closure); |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs+1-1| ... | ... | @@ -346,7 +346,7 @@ fn augment_references_with_imports( |
| 346 | 346 | ImportScope::find_insert_use_container(name.syntax(), &ctx.sema).and_then( |
| 347 | 347 | |import_scope| { |
| 348 | 348 | let cfg = |
| 349 | ctx.config.find_path_confg(ctx.sema.is_nightly(target_module.krate())); | |
| 349 | ctx.config.find_path_config(ctx.sema.is_nightly(target_module.krate())); | |
| 350 | 350 | let path = ref_module |
| 351 | 351 | .find_use_path( |
| 352 | 352 | ctx.sema.db, |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs+1-1| ... | ... | @@ -506,7 +506,7 @@ fn wrap_capture_in_deref_if_needed( |
| 506 | 506 | make::expr_prefix(T![*], capture_name).into() |
| 507 | 507 | } |
| 508 | 508 | |
| 509 | fn capture_as_arg(ctx: &AssistContext<'_>, capture: &ClosureCapture) -> ast::Expr { | |
| 509 | fn capture_as_arg(ctx: &AssistContext<'_>, capture: &ClosureCapture<'_>) -> ast::Expr { | |
| 510 | 510 | let place = parse_expr_from_str(&capture.display_place_source_code(ctx.db()), ctx.edition()) |
| 511 | 511 | .expect("`display_place_source_code()` produced an invalid expr"); |
| 512 | 512 | let needs_mut = match capture.kind() { |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs+1-1| ... | ... | @@ -43,7 +43,7 @@ pub(crate) fn convert_into_to_from(acc: &mut Assists, ctx: &AssistContext<'_>) - |
| 43 | 43 | return None; |
| 44 | 44 | } |
| 45 | 45 | |
| 46 | let cfg = ctx.config.find_path_confg(ctx.sema.is_nightly(module.krate())); | |
| 46 | let cfg = ctx.config.find_path_config(ctx.sema.is_nightly(module.krate())); | |
| 47 | 47 | |
| 48 | 48 | let src_type_path = { |
| 49 | 49 | let src_type_path = src_type.syntax().descendants().find_map(ast::Path::cast)?; |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs+88-16| ... | ... | @@ -17,7 +17,7 @@ use syntax::{ |
| 17 | 17 | use crate::{ |
| 18 | 18 | AssistId, |
| 19 | 19 | assist_context::{AssistContext, Assists}, |
| 20 | utils::invert_boolean_expression_legacy, | |
| 20 | utils::{invert_boolean_expression_legacy, is_never_block}, | |
| 21 | 21 | }; |
| 22 | 22 | |
| 23 | 23 | // Assist: convert_to_guarded_return |
| ... | ... | @@ -54,9 +54,13 @@ fn if_expr_to_guarded_return( |
| 54 | 54 | acc: &mut Assists, |
| 55 | 55 | ctx: &AssistContext<'_>, |
| 56 | 56 | ) -> Option<()> { |
| 57 | if if_expr.else_branch().is_some() { | |
| 58 | return None; | |
| 59 | } | |
| 57 | let else_block = match if_expr.else_branch() { | |
| 58 | Some(ast::ElseBranch::Block(block_expr)) if is_never_block(&ctx.sema, &block_expr) => { | |
| 59 | Some(block_expr) | |
| 60 | } | |
| 61 | Some(_) => return None, | |
| 62 | _ => None, | |
| 63 | }; | |
| 60 | 64 | |
| 61 | 65 | let cond = if_expr.condition()?; |
| 62 | 66 | |
| ... | ... | @@ -96,7 +100,11 @@ fn if_expr_to_guarded_return( |
| 96 | 100 | |
| 97 | 101 | let parent_container = parent_block.syntax().parent()?; |
| 98 | 102 | |
| 99 | let early_expression: ast::Expr = early_expression(parent_container, &ctx.sema)?; | |
| 103 | let early_expression = else_block | |
| 104 | .or_else(|| { | |
| 105 | early_expression(parent_container, &ctx.sema).map(ast::make::tail_only_block_expr) | |
| 106 | })? | |
| 107 | .reset_indent(); | |
| 100 | 108 | |
| 101 | 109 | then_block.syntax().first_child_or_token().map(|t| t.kind() == T!['{'])?; |
| 102 | 110 | |
| ... | ... | @@ -123,21 +131,14 @@ fn if_expr_to_guarded_return( |
| 123 | 131 | && let (Some(pat), Some(expr)) = (let_expr.pat(), let_expr.expr()) |
| 124 | 132 | { |
| 125 | 133 | // If-let. |
| 126 | let let_else_stmt = make::let_else_stmt( | |
| 127 | pat, | |
| 128 | None, | |
| 129 | expr, | |
| 130 | ast::make::tail_only_block_expr(early_expression.clone()), | |
| 131 | ); | |
| 134 | let let_else_stmt = | |
| 135 | make::let_else_stmt(pat, None, expr, early_expression.clone()); | |
| 132 | 136 | let let_else_stmt = let_else_stmt.indent(if_indent_level); |
| 133 | 137 | let_else_stmt.syntax().clone() |
| 134 | 138 | } else { |
| 135 | 139 | // If. |
| 136 | 140 | let new_expr = { |
| 137 | let then_branch = make::block_expr( | |
| 138 | once(make::expr_stmt(early_expression.clone()).into()), | |
| 139 | None, | |
| 140 | ); | |
| 141 | let then_branch = clean_stmt_block(&early_expression); | |
| 141 | 142 | let cond = invert_boolean_expression_legacy(expr); |
| 142 | 143 | make::expr_if(cond, then_branch, None).indent(if_indent_level) |
| 143 | 144 | }; |
| ... | ... | @@ -182,7 +183,7 @@ fn let_stmt_to_guarded_return( |
| 182 | 183 | let cursor_in_range = |
| 183 | 184 | let_token_range.cover(let_pattern_range).contains_range(ctx.selection_trimmed()); |
| 184 | 185 | |
| 185 | if !cursor_in_range { | |
| 186 | if !cursor_in_range || let_stmt.let_else().is_some() { | |
| 186 | 187 | return None; |
| 187 | 188 | } |
| 188 | 189 | |
| ... | ... | @@ -272,6 +273,17 @@ fn flat_let_chain(mut expr: ast::Expr) -> Vec<ast::Expr> { |
| 272 | 273 | chains |
| 273 | 274 | } |
| 274 | 275 | |
| 276 | fn clean_stmt_block(block: &ast::BlockExpr) -> ast::BlockExpr { | |
| 277 | if block.statements().next().is_none() | |
| 278 | && let Some(tail_expr) = block.tail_expr() | |
| 279 | && block.modifier().is_none() | |
| 280 | { | |
| 281 | make::block_expr(once(make::expr_stmt(tail_expr).into()), None) | |
| 282 | } else { | |
| 283 | block.clone() | |
| 284 | } | |
| 285 | } | |
| 286 | ||
| 275 | 287 | #[cfg(test)] |
| 276 | 288 | mod tests { |
| 277 | 289 | use crate::tests::{check_assist, check_assist_not_applicable}; |
| ... | ... | @@ -421,6 +433,53 @@ fn main() { |
| 421 | 433 | ); |
| 422 | 434 | } |
| 423 | 435 | |
| 436 | #[test] | |
| 437 | fn convert_if_let_has_never_type_else_block() { | |
| 438 | check_assist( | |
| 439 | convert_to_guarded_return, | |
| 440 | r#" | |
| 441 | fn main() { | |
| 442 | if$0 let Ok(x) = Err(92) { | |
| 443 | foo(x); | |
| 444 | } else { | |
| 445 | // needless comment | |
| 446 | return; | |
| 447 | } | |
| 448 | } | |
| 449 | "#, | |
| 450 | r#" | |
| 451 | fn main() { | |
| 452 | let Ok(x) = Err(92) else { | |
| 453 | // needless comment | |
| 454 | return; | |
| 455 | }; | |
| 456 | foo(x); | |
| 457 | } | |
| 458 | "#, | |
| 459 | ); | |
| 460 | ||
| 461 | check_assist( | |
| 462 | convert_to_guarded_return, | |
| 463 | r#" | |
| 464 | fn main() { | |
| 465 | if$0 let Ok(x) = Err(92) { | |
| 466 | foo(x); | |
| 467 | } else { | |
| 468 | return | |
| 469 | } | |
| 470 | } | |
| 471 | "#, | |
| 472 | r#" | |
| 473 | fn main() { | |
| 474 | let Ok(x) = Err(92) else { | |
| 475 | return | |
| 476 | }; | |
| 477 | foo(x); | |
| 478 | } | |
| 479 | "#, | |
| 480 | ); | |
| 481 | } | |
| 482 | ||
| 424 | 483 | #[test] |
| 425 | 484 | fn convert_if_let_result_inside_let() { |
| 426 | 485 | check_assist( |
| ... | ... | @@ -911,6 +970,19 @@ fn main() { |
| 911 | 970 | ); |
| 912 | 971 | } |
| 913 | 972 | |
| 973 | #[test] | |
| 974 | fn ignore_let_else_branch() { | |
| 975 | check_assist_not_applicable( | |
| 976 | convert_to_guarded_return, | |
| 977 | r#" | |
| 978 | //- minicore: option | |
| 979 | fn main() { | |
| 980 | let$0 Some(x) = Some(2) else { return }; | |
| 981 | } | |
| 982 | "#, | |
| 983 | ); | |
| 984 | } | |
| 985 | ||
| 914 | 986 | #[test] |
| 915 | 987 | fn ignore_statements_after_if() { |
| 916 | 988 | check_assist_not_applicable( |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs+1-1| ... | ... | @@ -199,7 +199,7 @@ fn augment_references_with_imports( |
| 199 | 199 | { |
| 200 | 200 | visited_modules.insert(ref_module); |
| 201 | 201 | |
| 202 | let cfg = ctx.config.find_path_confg(ctx.sema.is_nightly(ref_module.krate())); | |
| 202 | let cfg = ctx.config.find_path_config(ctx.sema.is_nightly(ref_module.krate())); | |
| 203 | 203 | let import_scope = |
| 204 | 204 | ImportScope::find_insert_use_container(new_name.syntax(), &ctx.sema); |
| 205 | 205 | let path = ref_module |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs+1-1| ... | ... | @@ -88,7 +88,7 @@ fn collect_data(ident_pat: ast::IdentPat, ctx: &AssistContext<'_>) -> Option<Str |
| 88 | 88 | let hir::Adt::Struct(struct_type) = ty.strip_references().as_adt()? else { return None }; |
| 89 | 89 | |
| 90 | 90 | let module = ctx.sema.scope(ident_pat.syntax())?.module(); |
| 91 | let cfg = ctx.config.find_path_confg(ctx.sema.is_nightly(module.krate())); | |
| 91 | let cfg = ctx.config.find_path_config(ctx.sema.is_nightly(module.krate())); | |
| 92 | 92 | let struct_def = hir::ModuleDef::from(struct_type); |
| 93 | 93 | let kind = struct_type.kind(ctx.db()); |
| 94 | 94 | let struct_def_path = module.find_path(ctx.db(), struct_def, cfg)?; |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs+1-3| ... | ... | @@ -108,9 +108,7 @@ pub(crate) fn extract_expressions_from_format_string( |
| 108 | 108 | match arg { |
| 109 | 109 | Arg::Expr(s) => { |
| 110 | 110 | // insert arg |
| 111 | // FIXME: use the crate's edition for parsing | |
| 112 | let expr = | |
| 113 | ast::Expr::parse(&s, syntax::Edition::CURRENT_FIXME).syntax_node(); | |
| 111 | let expr = ast::Expr::parse(&s, ctx.edition()).syntax_node(); | |
| 114 | 112 | let mut expr_tt = utils::tt_from_syntax(expr); |
| 115 | 113 | new_tt_bits.append(&mut expr_tt); |
| 116 | 114 | } |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs+1-1| ... | ... | @@ -209,7 +209,7 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op |
| 209 | 209 | FamousDefs(&ctx.sema, module.krate()).core_ops_ControlFlow(); |
| 210 | 210 | |
| 211 | 211 | if let Some(control_flow_enum) = control_flow_enum { |
| 212 | let cfg = ctx.config.find_path_confg(ctx.sema.is_nightly(module.krate())); | |
| 212 | let cfg = ctx.config.find_path_config(ctx.sema.is_nightly(module.krate())); | |
| 213 | 213 | let mod_path = module.find_use_path( |
| 214 | 214 | ctx.sema.db, |
| 215 | 215 | ModuleDef::from(control_flow_enum), |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs+1-1| ... | ... | @@ -400,7 +400,7 @@ fn process_references( |
| 400 | 400 | let segment = builder.make_mut(segment); |
| 401 | 401 | let scope_node = builder.make_syntax_mut(scope_node); |
| 402 | 402 | if !visited_modules.contains(&module) { |
| 403 | let cfg = ctx.config.find_path_confg(ctx.sema.is_nightly(module.krate())); | |
| 403 | let cfg = ctx.config.find_path_config(ctx.sema.is_nightly(module.krate())); | |
| 404 | 404 | let mod_path = module.find_use_path( |
| 405 | 405 | ctx.sema.db, |
| 406 | 406 | *enum_module_def, |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs+7-5| ... | ... | @@ -61,11 +61,13 @@ pub(crate) fn extract_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) -> |
| 61 | 61 | generics.map(|it| make::generic_param_list(it.into_iter().cloned())); |
| 62 | 62 | |
| 63 | 63 | // Replace original type with the alias |
| 64 | let ty_args = generic_params | |
| 65 | .as_ref() | |
| 66 | .map_or(String::new(), |it| it.to_generic_args().to_string()); | |
| 67 | // FIXME: replace with a `ast::make` constructor | |
| 68 | let new_ty = make::ty(&format!("Type{ty_args}")).clone_for_update(); | |
| 64 | let ty_args = generic_params.as_ref().map(|it| it.to_generic_args().generic_args()); | |
| 65 | let new_ty = if let Some(ty_args) = ty_args { | |
| 66 | make::generic_ty_path_segment(make::name_ref("Type"), ty_args) | |
| 67 | } else { | |
| 68 | make::path_segment(make::name_ref("Type")) | |
| 69 | } | |
| 70 | .clone_for_update(); | |
| 69 | 71 | edit.replace(ty.syntax(), new_ty.syntax()); |
| 70 | 72 | |
| 71 | 73 | // Insert new alias |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_blanket_trait_impl.rs created+1595| ... | ... | @@ -0,0 +1,1595 @@ |
| 1 | use crate::{ | |
| 2 | AssistConfig, | |
| 3 | assist_context::{AssistContext, Assists}, | |
| 4 | }; | |
| 5 | use hir::{HasCrate, Semantics}; | |
| 6 | use ide_db::{ | |
| 7 | RootDatabase, | |
| 8 | assists::{AssistId, AssistKind, ExprFillDefaultMode}, | |
| 9 | famous_defs::FamousDefs, | |
| 10 | syntax_helpers::suggest_name, | |
| 11 | }; | |
| 12 | use syntax::{ | |
| 13 | AstNode, | |
| 14 | ast::{ | |
| 15 | self, AssocItem, BlockExpr, GenericParam, HasAttrs, HasGenericParams, HasName, | |
| 16 | HasTypeBounds, HasVisibility, edit_in_place::Indent, make, | |
| 17 | }, | |
| 18 | syntax_editor::Position, | |
| 19 | }; | |
| 20 | ||
| 21 | // Assist: generate_blanket_trait_impl | |
| 22 | // | |
| 23 | // Generate blanket trait implementation. | |
| 24 | // | |
| 25 | // ``` | |
| 26 | // trait $0Foo<T: Send>: ToOwned | |
| 27 | // where | |
| 28 | // Self::Owned: Default, | |
| 29 | // { | |
| 30 | // fn foo(&self) -> T; | |
| 31 | // | |
| 32 | // fn print_foo(&self) { | |
| 33 | // println!("{}", self.foo()); | |
| 34 | // } | |
| 35 | // } | |
| 36 | // ``` | |
| 37 | // -> | |
| 38 | // ``` | |
| 39 | // trait Foo<T: Send>: ToOwned | |
| 40 | // where | |
| 41 | // Self::Owned: Default, | |
| 42 | // { | |
| 43 | // fn foo(&self) -> T; | |
| 44 | // | |
| 45 | // fn print_foo(&self) { | |
| 46 | // println!("{}", self.foo()); | |
| 47 | // } | |
| 48 | // } | |
| 49 | // | |
| 50 | // impl<T: Send, T1: ToOwned + ?Sized> Foo<T> for $0T1 | |
| 51 | // where | |
| 52 | // Self::Owned: Default, | |
| 53 | // { | |
| 54 | // fn foo(&self) -> T { | |
| 55 | // todo!() | |
| 56 | // } | |
| 57 | // } | |
| 58 | // ``` | |
| 59 | pub(crate) fn generate_blanket_trait_impl( | |
| 60 | acc: &mut Assists, | |
| 61 | ctx: &AssistContext<'_>, | |
| 62 | ) -> Option<()> { | |
| 63 | let name = ctx.find_node_at_offset::<ast::Name>()?; | |
| 64 | let traitd = ast::Trait::cast(name.syntax().parent()?)?; | |
| 65 | ||
| 66 | if existing_any_impl(&traitd, &ctx.sema).is_some() { | |
| 67 | cov_mark::hit!(existing_any_impl); | |
| 68 | return None; | |
| 69 | } | |
| 70 | ||
| 71 | acc.add( | |
| 72 | AssistId("generate_blanket_trait_impl", AssistKind::Generate, None), | |
| 73 | "Generate blanket trait implementation", | |
| 74 | name.syntax().text_range(), | |
| 75 | |builder| { | |
| 76 | let mut edit = builder.make_editor(traitd.syntax()); | |
| 77 | let namety = make::ty_path(make::path_from_text(&name.text())); | |
| 78 | let trait_where_clause = traitd.where_clause().map(|it| it.clone_for_update()); | |
| 79 | let bounds = traitd.type_bound_list().and_then(exlucde_sized); | |
| 80 | let is_unsafe = traitd.unsafe_token().is_some(); | |
| 81 | let thisname = this_name(&traitd); | |
| 82 | let thisty = make::ty_path(make::path_from_text(&thisname.text())); | |
| 83 | let indent = traitd.indent_level(); | |
| 84 | ||
| 85 | let gendecl = make::generic_param_list([GenericParam::TypeParam(make::type_param( | |
| 86 | thisname.clone(), | |
| 87 | apply_sized(has_sized(&traitd, &ctx.sema), bounds), | |
| 88 | ))]); | |
| 89 | ||
| 90 | let trait_gen_args = | |
| 91 | traitd.generic_param_list().map(|param_list| param_list.to_generic_args()); | |
| 92 | ||
| 93 | if let Some(ref where_clause) = trait_where_clause { | |
| 94 | where_clause.reindent_to(0.into()); | |
| 95 | } | |
| 96 | ||
| 97 | let impl_ = make::impl_trait( | |
| 98 | cfg_attrs(&traitd), | |
| 99 | is_unsafe, | |
| 100 | traitd.generic_param_list(), | |
| 101 | trait_gen_args, | |
| 102 | Some(gendecl), | |
| 103 | None, | |
| 104 | false, | |
| 105 | namety, | |
| 106 | thisty.clone(), | |
| 107 | trait_where_clause, | |
| 108 | None, | |
| 109 | None, | |
| 110 | ) | |
| 111 | .clone_for_update(); | |
| 112 | ||
| 113 | if let Some(trait_assoc_list) = traitd.assoc_item_list() { | |
| 114 | let assoc_item_list = impl_.get_or_create_assoc_item_list(); | |
| 115 | for method in trait_assoc_list.assoc_items() { | |
| 116 | let AssocItem::Fn(method) = method else { | |
| 117 | continue; | |
| 118 | }; | |
| 119 | if method.body().is_some() { | |
| 120 | continue; | |
| 121 | } | |
| 122 | let f = todo_fn(&method, ctx.config).clone_for_update(); | |
| 123 | f.indent(1.into()); | |
| 124 | assoc_item_list.add_item(AssocItem::Fn(f)); | |
| 125 | } | |
| 126 | } | |
| 127 | ||
| 128 | impl_.indent(indent); | |
| 129 | ||
| 130 | edit.insert_all( | |
| 131 | Position::after(traitd.syntax()), | |
| 132 | vec![ | |
| 133 | make::tokens::whitespace(&format!("\n\n{indent}")).into(), | |
| 134 | impl_.syntax().clone().into(), | |
| 135 | ], | |
| 136 | ); | |
| 137 | ||
| 138 | if let Some(cap) = ctx.config.snippet_cap | |
| 139 | && let Some(self_ty) = impl_.self_ty() | |
| 140 | { | |
| 141 | builder.add_tabstop_before(cap, self_ty); | |
| 142 | } | |
| 143 | ||
| 144 | builder.add_file_edits(ctx.vfs_file_id(), edit); | |
| 145 | }, | |
| 146 | ); | |
| 147 | ||
| 148 | Some(()) | |
| 149 | } | |
| 150 | ||
| 151 | fn existing_any_impl(traitd: &ast::Trait, sema: &Semantics<'_, RootDatabase>) -> Option<hir::Impl> { | |
| 152 | let db = sema.db; | |
| 153 | let traitd = sema.to_def(traitd)?; | |
| 154 | traitd | |
| 155 | .module(db) | |
| 156 | .impl_defs(db) | |
| 157 | .into_iter() | |
| 158 | .find(|impl_| impl_.trait_(db).is_some_and(|it| it == traitd)) | |
| 159 | } | |
| 160 | ||
| 161 | fn has_sized(traitd: &ast::Trait, sema: &Semantics<'_, RootDatabase>) -> bool { | |
| 162 | if let Some(sized) = find_bound("Sized", traitd.type_bound_list()) { | |
| 163 | sized.question_mark_token().is_none() | |
| 164 | } else if let Some(is_sized) = where_clause_sized(traitd.where_clause()) { | |
| 165 | is_sized | |
| 166 | } else { | |
| 167 | contained_owned_self_method(traitd.assoc_item_list()) | |
| 168 | || super_traits_has_sized(traitd, sema) == Some(true) | |
| 169 | } | |
| 170 | } | |
| 171 | ||
| 172 | fn super_traits_has_sized(traitd: &ast::Trait, sema: &Semantics<'_, RootDatabase>) -> Option<bool> { | |
| 173 | let traitd = sema.to_def(traitd)?; | |
| 174 | let sized = FamousDefs(sema, traitd.krate(sema.db)).core_marker_Sized()?; | |
| 175 | ||
| 176 | Some(traitd.all_supertraits(sema.db).contains(&sized)) | |
| 177 | } | |
| 178 | ||
| 179 | fn contained_owned_self_method(item_list: Option<ast::AssocItemList>) -> bool { | |
| 180 | item_list.into_iter().flat_map(|assoc_item_list| assoc_item_list.assoc_items()).any(|item| { | |
| 181 | match item { | |
| 182 | AssocItem::Fn(f) => { | |
| 183 | has_owned_self(&f) && where_clause_sized(f.where_clause()).is_none() | |
| 184 | } | |
| 185 | _ => false, | |
| 186 | } | |
| 187 | }) | |
| 188 | } | |
| 189 | ||
| 190 | fn has_owned_self(f: &ast::Fn) -> bool { | |
| 191 | has_owned_self_param(f) || has_ret_owned_self(f) | |
| 192 | } | |
| 193 | ||
| 194 | fn has_owned_self_param(f: &ast::Fn) -> bool { | |
| 195 | f.param_list() | |
| 196 | .and_then(|param_list| param_list.self_param()) | |
| 197 | .is_some_and(|sp| sp.amp_token().is_none() && sp.colon_token().is_none()) | |
| 198 | } | |
| 199 | ||
| 200 | fn has_ret_owned_self(f: &ast::Fn) -> bool { | |
| 201 | f.ret_type() | |
| 202 | .and_then(|ret| match ret.ty() { | |
| 203 | Some(ast::Type::PathType(ty)) => ty.path(), | |
| 204 | _ => None, | |
| 205 | }) | |
| 206 | .is_some_and(|path| { | |
| 207 | path.segment() | |
| 208 | .and_then(|seg| seg.name_ref()) | |
| 209 | .is_some_and(|name| path.qualifier().is_none() && name.text() == "Self") | |
| 210 | }) | |
| 211 | } | |
| 212 | ||
| 213 | fn where_clause_sized(where_clause: Option<ast::WhereClause>) -> Option<bool> { | |
| 214 | where_clause?.predicates().find_map(|pred| { | |
| 215 | find_bound("Sized", pred.type_bound_list()) | |
| 216 | .map(|bound| bound.question_mark_token().is_none()) | |
| 217 | }) | |
| 218 | } | |
| 219 | ||
| 220 | fn apply_sized(has_sized: bool, bounds: Option<ast::TypeBoundList>) -> Option<ast::TypeBoundList> { | |
| 221 | if has_sized { | |
| 222 | return bounds; | |
| 223 | } | |
| 224 | let bounds = bounds | |
| 225 | .into_iter() | |
| 226 | .flat_map(|bounds| bounds.bounds()) | |
| 227 | .chain([make::type_bound_text("?Sized")]); | |
| 228 | make::type_bound_list(bounds) | |
| 229 | } | |
| 230 | ||
| 231 | fn exlucde_sized(bounds: ast::TypeBoundList) -> Option<ast::TypeBoundList> { | |
| 232 | make::type_bound_list(bounds.bounds().filter(|bound| !ty_bound_is(bound, "Sized"))) | |
| 233 | } | |
| 234 | ||
| 235 | fn this_name(traitd: &ast::Trait) -> ast::Name { | |
| 236 | let has_iter = find_bound("Iterator", traitd.type_bound_list()).is_some(); | |
| 237 | ||
| 238 | let params = traitd | |
| 239 | .generic_param_list() | |
| 240 | .into_iter() | |
| 241 | .flat_map(|param_list| param_list.generic_params()) | |
| 242 | .filter_map(|param| match param { | |
| 243 | GenericParam::LifetimeParam(_) => None, | |
| 244 | GenericParam::ConstParam(cp) => cp.name(), | |
| 245 | GenericParam::TypeParam(tp) => tp.name(), | |
| 246 | }) | |
| 247 | .map(|name| name.to_string()) | |
| 248 | .collect::<Vec<_>>(); | |
| 249 | ||
| 250 | let mut name_gen = | |
| 251 | suggest_name::NameGenerator::new_with_names(params.iter().map(String::as_str)); | |
| 252 | ||
| 253 | make::name(&name_gen.suggest_name(if has_iter { "I" } else { "T" })) | |
| 254 | } | |
| 255 | ||
| 256 | fn find_bound(s: &str, bounds: Option<ast::TypeBoundList>) -> Option<ast::TypeBound> { | |
| 257 | bounds.into_iter().flat_map(|bounds| bounds.bounds()).find(|bound| ty_bound_is(bound, s)) | |
| 258 | } | |
| 259 | ||
| 260 | fn ty_bound_is(bound: &ast::TypeBound, s: &str) -> bool { | |
| 261 | matches!(bound.ty(), | |
| 262 | Some(ast::Type::PathType(ty)) if ty.path() | |
| 263 | .and_then(|path| path.segment()) | |
| 264 | .and_then(|segment| segment.name_ref()) | |
| 265 | .is_some_and(|name| name.text() == s)) | |
| 266 | } | |
| 267 | ||
| 268 | fn todo_fn(f: &ast::Fn, config: &AssistConfig) -> ast::Fn { | |
| 269 | let params = f.param_list().unwrap_or_else(|| make::param_list(None, None)); | |
| 270 | make::fn_( | |
| 271 | cfg_attrs(f), | |
| 272 | f.visibility(), | |
| 273 | f.name().unwrap_or_else(|| make::name("unnamed")), | |
| 274 | f.generic_param_list(), | |
| 275 | f.where_clause(), | |
| 276 | params, | |
| 277 | default_block(config), | |
| 278 | f.ret_type(), | |
| 279 | f.async_token().is_some(), | |
| 280 | f.const_token().is_some(), | |
| 281 | f.unsafe_token().is_some(), | |
| 282 | f.gen_token().is_some(), | |
| 283 | ) | |
| 284 | } | |
| 285 | ||
| 286 | fn default_block(config: &AssistConfig) -> BlockExpr { | |
| 287 | let expr = match config.expr_fill_default { | |
| 288 | ExprFillDefaultMode::Todo => make::ext::expr_todo(), | |
| 289 | ExprFillDefaultMode::Underscore => make::ext::expr_underscore(), | |
| 290 | ExprFillDefaultMode::Default => make::ext::expr_todo(), | |
| 291 | }; | |
| 292 | make::block_expr(None, Some(expr)) | |
| 293 | } | |
| 294 | ||
| 295 | fn cfg_attrs(node: &impl HasAttrs) -> impl Iterator<Item = ast::Attr> { | |
| 296 | node.attrs().filter(|attr| attr.as_simple_call().is_some_and(|(name, _arg)| name == "cfg")) | |
| 297 | } | |
| 298 | ||
| 299 | #[cfg(test)] | |
| 300 | mod test { | |
| 301 | ||
| 302 | use super::*; | |
| 303 | use crate::tests::{check_assist, check_assist_not_applicable}; | |
| 304 | ||
| 305 | #[test] | |
| 306 | fn test_gen_blanket_works() { | |
| 307 | check_assist( | |
| 308 | generate_blanket_trait_impl, | |
| 309 | r#" | |
| 310 | trait $0Foo<T: Send>: ToOwned | |
| 311 | where | |
| 312 | Self::Owned: Default, | |
| 313 | { | |
| 314 | fn foo(&self) -> T; | |
| 315 | ||
| 316 | fn print_foo(&self) { | |
| 317 | println!("{}", self.foo()); | |
| 318 | } | |
| 319 | } | |
| 320 | "#, | |
| 321 | r#" | |
| 322 | trait Foo<T: Send>: ToOwned | |
| 323 | where | |
| 324 | Self::Owned: Default, | |
| 325 | { | |
| 326 | fn foo(&self) -> T; | |
| 327 | ||
| 328 | fn print_foo(&self) { | |
| 329 | println!("{}", self.foo()); | |
| 330 | } | |
| 331 | } | |
| 332 | ||
| 333 | impl<T: Send, T1: ToOwned + ?Sized> Foo<T> for $0T1 | |
| 334 | where | |
| 335 | Self::Owned: Default, | |
| 336 | { | |
| 337 | fn foo(&self) -> T { | |
| 338 | todo!() | |
| 339 | } | |
| 340 | } | |
| 341 | "#, | |
| 342 | ); | |
| 343 | } | |
| 344 | ||
| 345 | #[test] | |
| 346 | fn test_gen_blanket_sized() { | |
| 347 | check_assist( | |
| 348 | generate_blanket_trait_impl, | |
| 349 | r#" | |
| 350 | trait $0Foo: Iterator + Sized { | |
| 351 | fn foo(mut self) -> Self::Item { | |
| 352 | self.next().unwrap() | |
| 353 | } | |
| 354 | } | |
| 355 | "#, | |
| 356 | r#" | |
| 357 | trait Foo: Iterator + Sized { | |
| 358 | fn foo(mut self) -> Self::Item { | |
| 359 | self.next().unwrap() | |
| 360 | } | |
| 361 | } | |
| 362 | ||
| 363 | impl<I: Iterator> Foo for $0I {} | |
| 364 | "#, | |
| 365 | ); | |
| 366 | ||
| 367 | check_assist( | |
| 368 | generate_blanket_trait_impl, | |
| 369 | r#" | |
| 370 | trait $0Foo: Iterator { | |
| 371 | fn foo(self) -> Self::Item; | |
| 372 | } | |
| 373 | "#, | |
| 374 | r#" | |
| 375 | trait Foo: Iterator { | |
| 376 | fn foo(self) -> Self::Item; | |
| 377 | } | |
| 378 | ||
| 379 | impl<I: Iterator> Foo for $0I { | |
| 380 | fn foo(self) -> Self::Item { | |
| 381 | todo!() | |
| 382 | } | |
| 383 | } | |
| 384 | "#, | |
| 385 | ); | |
| 386 | ||
| 387 | check_assist( | |
| 388 | generate_blanket_trait_impl, | |
| 389 | r#" | |
| 390 | trait $0Foo { | |
| 391 | fn foo(&self) -> Self; | |
| 392 | } | |
| 393 | "#, | |
| 394 | r#" | |
| 395 | trait Foo { | |
| 396 | fn foo(&self) -> Self; | |
| 397 | } | |
| 398 | ||
| 399 | impl<T> Foo for $0T { | |
| 400 | fn foo(&self) -> Self { | |
| 401 | todo!() | |
| 402 | } | |
| 403 | } | |
| 404 | "#, | |
| 405 | ); | |
| 406 | } | |
| 407 | ||
| 408 | #[test] | |
| 409 | fn test_gen_blanket_super_sized() { | |
| 410 | check_assist( | |
| 411 | generate_blanket_trait_impl, | |
| 412 | r#" | |
| 413 | //- minicore: default | |
| 414 | trait $0Foo: Default { | |
| 415 | fn foo(&self); | |
| 416 | } | |
| 417 | "#, | |
| 418 | r#" | |
| 419 | trait Foo: Default { | |
| 420 | fn foo(&self); | |
| 421 | } | |
| 422 | ||
| 423 | impl<T: Default> Foo for $0T { | |
| 424 | fn foo(&self) { | |
| 425 | todo!() | |
| 426 | } | |
| 427 | } | |
| 428 | "#, | |
| 429 | ); | |
| 430 | } | |
| 431 | ||
| 432 | #[test] | |
| 433 | fn test_gen_blanket_non_sized() { | |
| 434 | check_assist( | |
| 435 | generate_blanket_trait_impl, | |
| 436 | r#" | |
| 437 | trait $0Foo: Iterator { | |
| 438 | fn foo(&self) -> Self::Item; | |
| 439 | } | |
| 440 | "#, | |
| 441 | r#" | |
| 442 | trait Foo: Iterator { | |
| 443 | fn foo(&self) -> Self::Item; | |
| 444 | } | |
| 445 | ||
| 446 | impl<I: Iterator + ?Sized> Foo for $0I { | |
| 447 | fn foo(&self) -> Self::Item { | |
| 448 | todo!() | |
| 449 | } | |
| 450 | } | |
| 451 | "#, | |
| 452 | ); | |
| 453 | check_assist( | |
| 454 | generate_blanket_trait_impl, | |
| 455 | r#" | |
| 456 | trait $0Foo: Iterator { | |
| 457 | fn foo(&self) -> Self::Item; | |
| 458 | ||
| 459 | fn each(self) where Self: Sized; | |
| 460 | } | |
| 461 | "#, | |
| 462 | r#" | |
| 463 | trait Foo: Iterator { | |
| 464 | fn foo(&self) -> Self::Item; | |
| 465 | ||
| 466 | fn each(self) where Self: Sized; | |
| 467 | } | |
| 468 | ||
| 469 | impl<I: Iterator + ?Sized> Foo for $0I { | |
| 470 | fn foo(&self) -> Self::Item { | |
| 471 | todo!() | |
| 472 | } | |
| 473 | ||
| 474 | fn each(self) where Self: Sized { | |
| 475 | todo!() | |
| 476 | } | |
| 477 | } | |
| 478 | "#, | |
| 479 | ); | |
| 480 | check_assist( | |
| 481 | generate_blanket_trait_impl, | |
| 482 | r#" | |
| 483 | trait $0Foo: Iterator { | |
| 484 | fn foo(&self) -> Self::Item; | |
| 485 | ||
| 486 | fn each(&self) -> Self where Self: Sized; | |
| 487 | } | |
| 488 | "#, | |
| 489 | r#" | |
| 490 | trait Foo: Iterator { | |
| 491 | fn foo(&self) -> Self::Item; | |
| 492 | ||
| 493 | fn each(&self) -> Self where Self: Sized; | |
| 494 | } | |
| 495 | ||
| 496 | impl<I: Iterator + ?Sized> Foo for $0I { | |
| 497 | fn foo(&self) -> Self::Item { | |
| 498 | todo!() | |
| 499 | } | |
| 500 | ||
| 501 | fn each(&self) -> Self where Self: Sized { | |
| 502 | todo!() | |
| 503 | } | |
| 504 | } | |
| 505 | "#, | |
| 506 | ); | |
| 507 | } | |
| 508 | ||
| 509 | #[test] | |
| 510 | fn test_gen_blanket_indent() { | |
| 511 | check_assist( | |
| 512 | generate_blanket_trait_impl, | |
| 513 | r#" | |
| 514 | mod foo { | |
| 515 | trait $0Foo<T: Send>: ToOwned | |
| 516 | where | |
| 517 | Self::Owned: Default, | |
| 518 | { | |
| 519 | fn foo(&self) -> T; | |
| 520 | ||
| 521 | fn print_foo(&self) { | |
| 522 | println!("{}", self.foo()); | |
| 523 | } | |
| 524 | } | |
| 525 | } | |
| 526 | "#, | |
| 527 | r#" | |
| 528 | mod foo { | |
| 529 | trait Foo<T: Send>: ToOwned | |
| 530 | where | |
| 531 | Self::Owned: Default, | |
| 532 | { | |
| 533 | fn foo(&self) -> T; | |
| 534 | ||
| 535 | fn print_foo(&self) { | |
| 536 | println!("{}", self.foo()); | |
| 537 | } | |
| 538 | } | |
| 539 | ||
| 540 | impl<T: Send, T1: ToOwned + ?Sized> Foo<T> for $0T1 | |
| 541 | where | |
| 542 | Self::Owned: Default, | |
| 543 | { | |
| 544 | fn foo(&self) -> T { | |
| 545 | todo!() | |
| 546 | } | |
| 547 | } | |
| 548 | } | |
| 549 | "#, | |
| 550 | ); | |
| 551 | check_assist( | |
| 552 | generate_blanket_trait_impl, | |
| 553 | r#" | |
| 554 | mod foo { | |
| 555 | trait $0Foo<T: Send>: ToOwned | |
| 556 | where | |
| 557 | Self::Owned: Default, | |
| 558 | Self: Send, | |
| 559 | { | |
| 560 | fn foo(&self) -> T; | |
| 561 | ||
| 562 | fn print_foo(&self) { | |
| 563 | println!("{}", self.foo()); | |
| 564 | } | |
| 565 | } | |
| 566 | } | |
| 567 | "#, | |
| 568 | r#" | |
| 569 | mod foo { | |
| 570 | trait Foo<T: Send>: ToOwned | |
| 571 | where | |
| 572 | Self::Owned: Default, | |
| 573 | Self: Send, | |
| 574 | { | |
| 575 | fn foo(&self) -> T; | |
| 576 | ||
| 577 | fn print_foo(&self) { | |
| 578 | println!("{}", self.foo()); | |
| 579 | } | |
| 580 | } | |
| 581 | ||
| 582 | impl<T: Send, T1: ToOwned + ?Sized> Foo<T> for $0T1 | |
| 583 | where | |
| 584 | Self::Owned: Default, | |
| 585 | Self: Send, | |
| 586 | { | |
| 587 | fn foo(&self) -> T { | |
| 588 | todo!() | |
| 589 | } | |
| 590 | } | |
| 591 | } | |
| 592 | "#, | |
| 593 | ); | |
| 594 | check_assist( | |
| 595 | generate_blanket_trait_impl, | |
| 596 | r#" | |
| 597 | mod foo { | |
| 598 | mod bar { | |
| 599 | trait $0Foo<T: Send>: ToOwned | |
| 600 | where | |
| 601 | Self::Owned: Default, | |
| 602 | Self: Send, | |
| 603 | { | |
| 604 | fn foo(&self) -> T; | |
| 605 | ||
| 606 | fn print_foo(&self) { | |
| 607 | println!("{}", self.foo()); | |
| 608 | } | |
| 609 | } | |
| 610 | } | |
| 611 | } | |
| 612 | "#, | |
| 613 | r#" | |
| 614 | mod foo { | |
| 615 | mod bar { | |
| 616 | trait Foo<T: Send>: ToOwned | |
| 617 | where | |
| 618 | Self::Owned: Default, | |
| 619 | Self: Send, | |
| 620 | { | |
| 621 | fn foo(&self) -> T; | |
| 622 | ||
| 623 | fn print_foo(&self) { | |
| 624 | println!("{}", self.foo()); | |
| 625 | } | |
| 626 | } | |
| 627 | ||
| 628 | impl<T: Send, T1: ToOwned + ?Sized> Foo<T> for $0T1 | |
| 629 | where | |
| 630 | Self::Owned: Default, | |
| 631 | Self: Send, | |
| 632 | { | |
| 633 | fn foo(&self) -> T { | |
| 634 | todo!() | |
| 635 | } | |
| 636 | } | |
| 637 | } | |
| 638 | } | |
| 639 | "#, | |
| 640 | ); | |
| 641 | check_assist( | |
| 642 | generate_blanket_trait_impl, | |
| 643 | r#" | |
| 644 | mod foo { | |
| 645 | trait $0Foo { | |
| 646 | fn foo(&self) -> i32; | |
| 647 | ||
| 648 | fn print_foo(&self) { | |
| 649 | println!("{}", self.foo()); | |
| 650 | } | |
| 651 | } | |
| 652 | } | |
| 653 | "#, | |
| 654 | r#" | |
| 655 | mod foo { | |
| 656 | trait Foo { | |
| 657 | fn foo(&self) -> i32; | |
| 658 | ||
| 659 | fn print_foo(&self) { | |
| 660 | println!("{}", self.foo()); | |
| 661 | } | |
| 662 | } | |
| 663 | ||
| 664 | impl<T: ?Sized> Foo for $0T { | |
| 665 | fn foo(&self) -> i32 { | |
| 666 | todo!() | |
| 667 | } | |
| 668 | } | |
| 669 | } | |
| 670 | "#, | |
| 671 | ); | |
| 672 | check_assist( | |
| 673 | generate_blanket_trait_impl, | |
| 674 | r#" | |
| 675 | mod foo { | |
| 676 | mod bar { | |
| 677 | trait $0Foo { | |
| 678 | fn foo(&self) -> i32; | |
| 679 | ||
| 680 | fn print_foo(&self) { | |
| 681 | println!("{}", self.foo()); | |
| 682 | } | |
| 683 | } | |
| 684 | } | |
| 685 | } | |
| 686 | "#, | |
| 687 | r#" | |
| 688 | mod foo { | |
| 689 | mod bar { | |
| 690 | trait Foo { | |
| 691 | fn foo(&self) -> i32; | |
| 692 | ||
| 693 | fn print_foo(&self) { | |
| 694 | println!("{}", self.foo()); | |
| 695 | } | |
| 696 | } | |
| 697 | ||
| 698 | impl<T: ?Sized> Foo for $0T { | |
| 699 | fn foo(&self) -> i32 { | |
| 700 | todo!() | |
| 701 | } | |
| 702 | } | |
| 703 | } | |
| 704 | } | |
| 705 | "#, | |
| 706 | ); | |
| 707 | check_assist( | |
| 708 | generate_blanket_trait_impl, | |
| 709 | r#" | |
| 710 | mod foo { | |
| 711 | mod bar { | |
| 712 | #[cfg(test)] | |
| 713 | trait $0Foo { | |
| 714 | fn foo(&self) -> i32; | |
| 715 | ||
| 716 | fn print_foo(&self) { | |
| 717 | println!("{}", self.foo()); | |
| 718 | } | |
| 719 | } | |
| 720 | } | |
| 721 | } | |
| 722 | "#, | |
| 723 | r#" | |
| 724 | mod foo { | |
| 725 | mod bar { | |
| 726 | #[cfg(test)] | |
| 727 | trait Foo { | |
| 728 | fn foo(&self) -> i32; | |
| 729 | ||
| 730 | fn print_foo(&self) { | |
| 731 | println!("{}", self.foo()); | |
| 732 | } | |
| 733 | } | |
| 734 | ||
| 735 | #[cfg(test)] | |
| 736 | impl<T: ?Sized> Foo for $0T { | |
| 737 | fn foo(&self) -> i32 { | |
| 738 | todo!() | |
| 739 | } | |
| 740 | } | |
| 741 | } | |
| 742 | } | |
| 743 | "#, | |
| 744 | ); | |
| 745 | } | |
| 746 | ||
| 747 | #[test] | |
| 748 | fn test_gen_blanket_remove_attribute() { | |
| 749 | check_assist( | |
| 750 | generate_blanket_trait_impl, | |
| 751 | r#" | |
| 752 | trait $0Foo<T: Send>: ToOwned | |
| 753 | where | |
| 754 | Self::Owned: Default, | |
| 755 | { | |
| 756 | #[doc(hidden)] | |
| 757 | fn foo(&self) -> T; | |
| 758 | ||
| 759 | /// foo | |
| 760 | fn print_foo(&self) { | |
| 761 | println!("{}", self.foo()); | |
| 762 | } | |
| 763 | } | |
| 764 | "#, | |
| 765 | r#" | |
| 766 | trait Foo<T: Send>: ToOwned | |
| 767 | where | |
| 768 | Self::Owned: Default, | |
| 769 | { | |
| 770 | #[doc(hidden)] | |
| 771 | fn foo(&self) -> T; | |
| 772 | ||
| 773 | /// foo | |
| 774 | fn print_foo(&self) { | |
| 775 | println!("{}", self.foo()); | |
| 776 | } | |
| 777 | } | |
| 778 | ||
| 779 | impl<T: Send, T1: ToOwned + ?Sized> Foo<T> for $0T1 | |
| 780 | where | |
| 781 | Self::Owned: Default, | |
| 782 | { | |
| 783 | fn foo(&self) -> T { | |
| 784 | todo!() | |
| 785 | } | |
| 786 | } | |
| 787 | "#, | |
| 788 | ); | |
| 789 | } | |
| 790 | ||
| 791 | #[test] | |
| 792 | fn test_gen_blanket_not_gen_type_alias() { | |
| 793 | check_assist( | |
| 794 | generate_blanket_trait_impl, | |
| 795 | r#" | |
| 796 | trait $0Foo<T: Send>: ToOwned | |
| 797 | where | |
| 798 | Self::Owned: Default, | |
| 799 | { | |
| 800 | type X: Sync; | |
| 801 | ||
| 802 | fn foo(&self, x: Self::X) -> T; | |
| 803 | ||
| 804 | fn print_foo(&self) { | |
| 805 | println!("{}", self.foo()); | |
| 806 | } | |
| 807 | } | |
| 808 | "#, | |
| 809 | r#" | |
| 810 | trait Foo<T: Send>: ToOwned | |
| 811 | where | |
| 812 | Self::Owned: Default, | |
| 813 | { | |
| 814 | type X: Sync; | |
| 815 | ||
| 816 | fn foo(&self, x: Self::X) -> T; | |
| 817 | ||
| 818 | fn print_foo(&self) { | |
| 819 | println!("{}", self.foo()); | |
| 820 | } | |
| 821 | } | |
| 822 | ||
| 823 | impl<T: Send, T1: ToOwned + ?Sized> Foo<T> for $0T1 | |
| 824 | where | |
| 825 | Self::Owned: Default, | |
| 826 | { | |
| 827 | fn foo(&self, x: Self::X) -> T { | |
| 828 | todo!() | |
| 829 | } | |
| 830 | } | |
| 831 | "#, | |
| 832 | ); | |
| 833 | } | |
| 834 | ||
| 835 | #[test] | |
| 836 | fn test_gen_blanket_no_quick_bound() { | |
| 837 | check_assist( | |
| 838 | generate_blanket_trait_impl, | |
| 839 | r#" | |
| 840 | trait $0Foo<T: Send> | |
| 841 | where | |
| 842 | Self: ToOwned, | |
| 843 | Self::Owned: Default, | |
| 844 | { | |
| 845 | type X: Sync; | |
| 846 | ||
| 847 | fn foo(&self, x: Self::X) -> T; | |
| 848 | ||
| 849 | fn print_foo(&self) { | |
| 850 | println!("{}", self.foo()); | |
| 851 | } | |
| 852 | } | |
| 853 | "#, | |
| 854 | r#" | |
| 855 | trait Foo<T: Send> | |
| 856 | where | |
| 857 | Self: ToOwned, | |
| 858 | Self::Owned: Default, | |
| 859 | { | |
| 860 | type X: Sync; | |
| 861 | ||
| 862 | fn foo(&self, x: Self::X) -> T; | |
| 863 | ||
| 864 | fn print_foo(&self) { | |
| 865 | println!("{}", self.foo()); | |
| 866 | } | |
| 867 | } | |
| 868 | ||
| 869 | impl<T: Send, T1: ?Sized> Foo<T> for $0T1 | |
| 870 | where | |
| 871 | Self: ToOwned, | |
| 872 | Self::Owned: Default, | |
| 873 | { | |
| 874 | fn foo(&self, x: Self::X) -> T { | |
| 875 | todo!() | |
| 876 | } | |
| 877 | } | |
| 878 | "#, | |
| 879 | ); | |
| 880 | } | |
| 881 | ||
| 882 | #[test] | |
| 883 | fn test_gen_blanket_no_where_clause() { | |
| 884 | check_assist( | |
| 885 | generate_blanket_trait_impl, | |
| 886 | r#" | |
| 887 | trait $0Foo<T: Send> { | |
| 888 | type X: Sync; | |
| 889 | ||
| 890 | fn foo(&self, x: Self::X) -> T; | |
| 891 | ||
| 892 | fn print_foo(&self) { | |
| 893 | println!("{}", self.foo()); | |
| 894 | } | |
| 895 | } | |
| 896 | "#, | |
| 897 | r#" | |
| 898 | trait Foo<T: Send> { | |
| 899 | type X: Sync; | |
| 900 | ||
| 901 | fn foo(&self, x: Self::X) -> T; | |
| 902 | ||
| 903 | fn print_foo(&self) { | |
| 904 | println!("{}", self.foo()); | |
| 905 | } | |
| 906 | } | |
| 907 | ||
| 908 | impl<T: Send, T1: ?Sized> Foo<T> for $0T1 { | |
| 909 | fn foo(&self, x: Self::X) -> T { | |
| 910 | todo!() | |
| 911 | } | |
| 912 | } | |
| 913 | "#, | |
| 914 | ); | |
| 915 | } | |
| 916 | ||
| 917 | #[test] | |
| 918 | fn test_gen_blanket_basic() { | |
| 919 | check_assist( | |
| 920 | generate_blanket_trait_impl, | |
| 921 | r#" | |
| 922 | trait $0Foo { | |
| 923 | type X: Sync; | |
| 924 | ||
| 925 | fn foo(&self, x: Self::X) -> i32; | |
| 926 | ||
| 927 | fn print_foo(&self) { | |
| 928 | println!("{}", self.foo()); | |
| 929 | } | |
| 930 | } | |
| 931 | "#, | |
| 932 | r#" | |
| 933 | trait Foo { | |
| 934 | type X: Sync; | |
| 935 | ||
| 936 | fn foo(&self, x: Self::X) -> i32; | |
| 937 | ||
| 938 | fn print_foo(&self) { | |
| 939 | println!("{}", self.foo()); | |
| 940 | } | |
| 941 | } | |
| 942 | ||
| 943 | impl<T: ?Sized> Foo for $0T { | |
| 944 | fn foo(&self, x: Self::X) -> i32 { | |
| 945 | todo!() | |
| 946 | } | |
| 947 | } | |
| 948 | "#, | |
| 949 | ); | |
| 950 | } | |
| 951 | ||
| 952 | #[test] | |
| 953 | fn test_gen_blanket_cfg_attrs() { | |
| 954 | check_assist( | |
| 955 | generate_blanket_trait_impl, | |
| 956 | r#" | |
| 957 | #[cfg(test)] | |
| 958 | trait $0Foo { | |
| 959 | fn foo(&self, x: i32) -> i32; | |
| 960 | ||
| 961 | fn print_foo(&self) { | |
| 962 | println!("{}", self.foo()); | |
| 963 | } | |
| 964 | } | |
| 965 | "#, | |
| 966 | r#" | |
| 967 | #[cfg(test)] | |
| 968 | trait Foo { | |
| 969 | fn foo(&self, x: i32) -> i32; | |
| 970 | ||
| 971 | fn print_foo(&self) { | |
| 972 | println!("{}", self.foo()); | |
| 973 | } | |
| 974 | } | |
| 975 | ||
| 976 | #[cfg(test)] | |
| 977 | impl<T: ?Sized> Foo for $0T { | |
| 978 | fn foo(&self, x: i32) -> i32 { | |
| 979 | todo!() | |
| 980 | } | |
| 981 | } | |
| 982 | "#, | |
| 983 | ); | |
| 984 | check_assist( | |
| 985 | generate_blanket_trait_impl, | |
| 986 | r#" | |
| 987 | #[cfg(test)] | |
| 988 | trait $0Foo { | |
| 989 | /// ... | |
| 990 | #[cfg(test)] | |
| 991 | fn foo(&self, x: i32) -> i32; | |
| 992 | ||
| 993 | fn print_foo(&self) { | |
| 994 | println!("{}", self.foo()); | |
| 995 | } | |
| 996 | } | |
| 997 | "#, | |
| 998 | r#" | |
| 999 | #[cfg(test)] | |
| 1000 | trait Foo { | |
| 1001 | /// ... | |
| 1002 | #[cfg(test)] | |
| 1003 | fn foo(&self, x: i32) -> i32; | |
| 1004 | ||
| 1005 | fn print_foo(&self) { | |
| 1006 | println!("{}", self.foo()); | |
| 1007 | } | |
| 1008 | } | |
| 1009 | ||
| 1010 | #[cfg(test)] | |
| 1011 | impl<T: ?Sized> Foo for $0T { | |
| 1012 | #[cfg(test)] | |
| 1013 | fn foo(&self, x: i32) -> i32 { | |
| 1014 | todo!() | |
| 1015 | } | |
| 1016 | } | |
| 1017 | "#, | |
| 1018 | ); | |
| 1019 | } | |
| 1020 | ||
| 1021 | #[test] | |
| 1022 | fn test_gen_blanket_empty_trait() { | |
| 1023 | check_assist( | |
| 1024 | generate_blanket_trait_impl, | |
| 1025 | r#" | |
| 1026 | trait $0Foo {} | |
| 1027 | "#, | |
| 1028 | r#" | |
| 1029 | trait Foo {} | |
| 1030 | ||
| 1031 | impl<T: ?Sized> Foo for $0T {} | |
| 1032 | "#, | |
| 1033 | ); | |
| 1034 | } | |
| 1035 | ||
| 1036 | #[test] | |
| 1037 | fn test_gen_blanket_empty_trait_with_quick_bounds() { | |
| 1038 | check_assist( | |
| 1039 | generate_blanket_trait_impl, | |
| 1040 | r#" | |
| 1041 | trait $0Foo: Copy {} | |
| 1042 | "#, | |
| 1043 | r#" | |
| 1044 | trait Foo: Copy {} | |
| 1045 | ||
| 1046 | impl<T: Copy + ?Sized> Foo for $0T {} | |
| 1047 | "#, | |
| 1048 | ); | |
| 1049 | } | |
| 1050 | ||
| 1051 | #[test] | |
| 1052 | fn test_gen_blanket_empty_trait_with_where_clause() { | |
| 1053 | check_assist( | |
| 1054 | generate_blanket_trait_impl, | |
| 1055 | r#" | |
| 1056 | trait $0Foo where Self: Copy {} | |
| 1057 | "#, | |
| 1058 | r#" | |
| 1059 | trait Foo where Self: Copy {} | |
| 1060 | ||
| 1061 | impl<T: ?Sized> Foo for $0T | |
| 1062 | where Self: Copy | |
| 1063 | { | |
| 1064 | } | |
| 1065 | "#, | |
| 1066 | ); | |
| 1067 | } | |
| 1068 | ||
| 1069 | #[test] | |
| 1070 | fn test_gen_blanket_empty_trait_with_where_clause_comma() { | |
| 1071 | check_assist( | |
| 1072 | generate_blanket_trait_impl, | |
| 1073 | r#" | |
| 1074 | trait $0Foo where Self: Copy, {} | |
| 1075 | "#, | |
| 1076 | r#" | |
| 1077 | trait Foo where Self: Copy, {} | |
| 1078 | ||
| 1079 | impl<T: ?Sized> Foo for $0T | |
| 1080 | where Self: Copy, | |
| 1081 | { | |
| 1082 | } | |
| 1083 | "#, | |
| 1084 | ); | |
| 1085 | } | |
| 1086 | ||
| 1087 | #[test] | |
| 1088 | fn test_gen_blanket_empty_trait_with_where_clause_newline() { | |
| 1089 | check_assist( | |
| 1090 | generate_blanket_trait_impl, | |
| 1091 | r#" | |
| 1092 | trait $0Foo | |
| 1093 | where Self: Copy | |
| 1094 | {} | |
| 1095 | "#, | |
| 1096 | r#" | |
| 1097 | trait Foo | |
| 1098 | where Self: Copy | |
| 1099 | {} | |
| 1100 | ||
| 1101 | impl<T: ?Sized> Foo for $0T | |
| 1102 | where Self: Copy | |
| 1103 | { | |
| 1104 | } | |
| 1105 | "#, | |
| 1106 | ); | |
| 1107 | } | |
| 1108 | ||
| 1109 | #[test] | |
| 1110 | fn test_gen_blanket_empty_trait_with_where_clause_newline_newline() { | |
| 1111 | check_assist( | |
| 1112 | generate_blanket_trait_impl, | |
| 1113 | r#" | |
| 1114 | trait $0Foo | |
| 1115 | where | |
| 1116 | Self: Copy | |
| 1117 | {} | |
| 1118 | "#, | |
| 1119 | r#" | |
| 1120 | trait Foo | |
| 1121 | where | |
| 1122 | Self: Copy | |
| 1123 | {} | |
| 1124 | ||
| 1125 | impl<T: ?Sized> Foo for $0T | |
| 1126 | where | |
| 1127 | Self: Copy | |
| 1128 | { | |
| 1129 | } | |
| 1130 | "#, | |
| 1131 | ); | |
| 1132 | } | |
| 1133 | ||
| 1134 | #[test] | |
| 1135 | fn test_gen_blanket_empty_trait_with_where_clause_newline_newline_comma() { | |
| 1136 | check_assist( | |
| 1137 | generate_blanket_trait_impl, | |
| 1138 | r#" | |
| 1139 | trait $0Foo | |
| 1140 | where | |
| 1141 | Self: Copy, | |
| 1142 | {} | |
| 1143 | "#, | |
| 1144 | r#" | |
| 1145 | trait Foo | |
| 1146 | where | |
| 1147 | Self: Copy, | |
| 1148 | {} | |
| 1149 | ||
| 1150 | impl<T: ?Sized> Foo for $0T | |
| 1151 | where | |
| 1152 | Self: Copy, | |
| 1153 | { | |
| 1154 | } | |
| 1155 | "#, | |
| 1156 | ); | |
| 1157 | } | |
| 1158 | ||
| 1159 | #[test] | |
| 1160 | fn test_gen_blanket_empty_trait_with_multiple_where_clause() { | |
| 1161 | check_assist( | |
| 1162 | generate_blanket_trait_impl, | |
| 1163 | r#" | |
| 1164 | trait $0Foo | |
| 1165 | where | |
| 1166 | Self: Copy, | |
| 1167 | (): Into<Self>, | |
| 1168 | {} | |
| 1169 | "#, | |
| 1170 | r#" | |
| 1171 | trait Foo | |
| 1172 | where | |
| 1173 | Self: Copy, | |
| 1174 | (): Into<Self>, | |
| 1175 | {} | |
| 1176 | ||
| 1177 | impl<T: ?Sized> Foo for $0T | |
| 1178 | where | |
| 1179 | Self: Copy, | |
| 1180 | (): Into<Self>, | |
| 1181 | { | |
| 1182 | } | |
| 1183 | "#, | |
| 1184 | ); | |
| 1185 | } | |
| 1186 | ||
| 1187 | #[test] | |
| 1188 | fn test_gen_blanket_empty_trait_with_multiple_bounds_where_clause() { | |
| 1189 | check_assist( | |
| 1190 | generate_blanket_trait_impl, | |
| 1191 | r#" | |
| 1192 | trait $0Foo | |
| 1193 | where | |
| 1194 | Self: Copy + Sync, | |
| 1195 | (): Into<Self>, | |
| 1196 | {} | |
| 1197 | "#, | |
| 1198 | r#" | |
| 1199 | trait Foo | |
| 1200 | where | |
| 1201 | Self: Copy + Sync, | |
| 1202 | (): Into<Self>, | |
| 1203 | {} | |
| 1204 | ||
| 1205 | impl<T: ?Sized> Foo for $0T | |
| 1206 | where | |
| 1207 | Self: Copy + Sync, | |
| 1208 | (): Into<Self>, | |
| 1209 | { | |
| 1210 | } | |
| 1211 | "#, | |
| 1212 | ); | |
| 1213 | } | |
| 1214 | ||
| 1215 | #[test] | |
| 1216 | fn test_gen_blanket_empty_generate() { | |
| 1217 | check_assist( | |
| 1218 | generate_blanket_trait_impl, | |
| 1219 | r#" | |
| 1220 | trait $0Foo { | |
| 1221 | fn foo(&self) {} | |
| 1222 | } | |
| 1223 | "#, | |
| 1224 | r#" | |
| 1225 | trait Foo { | |
| 1226 | fn foo(&self) {} | |
| 1227 | } | |
| 1228 | ||
| 1229 | impl<T: ?Sized> Foo for $0T {} | |
| 1230 | "#, | |
| 1231 | ); | |
| 1232 | } | |
| 1233 | ||
| 1234 | #[test] | |
| 1235 | fn test_gen_blanket_trait_with_doc() { | |
| 1236 | check_assist( | |
| 1237 | generate_blanket_trait_impl, | |
| 1238 | r#" | |
| 1239 | /// some docs | |
| 1240 | trait $0Foo {} | |
| 1241 | "#, | |
| 1242 | r#" | |
| 1243 | /// some docs | |
| 1244 | trait Foo {} | |
| 1245 | ||
| 1246 | impl<T: ?Sized> Foo for $0T {} | |
| 1247 | "#, | |
| 1248 | ); | |
| 1249 | } | |
| 1250 | ||
| 1251 | #[test] | |
| 1252 | fn test_gen_blanket_multiple_method() { | |
| 1253 | check_assist( | |
| 1254 | generate_blanket_trait_impl, | |
| 1255 | r#" | |
| 1256 | trait $0Foo { | |
| 1257 | fn foo(&self); | |
| 1258 | fn bar(&self); | |
| 1259 | } | |
| 1260 | "#, | |
| 1261 | r#" | |
| 1262 | trait Foo { | |
| 1263 | fn foo(&self); | |
| 1264 | fn bar(&self); | |
| 1265 | } | |
| 1266 | ||
| 1267 | impl<T: ?Sized> Foo for $0T { | |
| 1268 | fn foo(&self) { | |
| 1269 | todo!() | |
| 1270 | } | |
| 1271 | ||
| 1272 | fn bar(&self) { | |
| 1273 | todo!() | |
| 1274 | } | |
| 1275 | } | |
| 1276 | "#, | |
| 1277 | ); | |
| 1278 | } | |
| 1279 | ||
| 1280 | #[test] | |
| 1281 | fn test_gen_blanket_method_with_generic() { | |
| 1282 | check_assist( | |
| 1283 | generate_blanket_trait_impl, | |
| 1284 | r#" | |
| 1285 | trait $0Foo { | |
| 1286 | fn foo<T>(&self, value: i32) -> i32; | |
| 1287 | fn bar<T>(&self, value: i32) -> i32 { todo!() } | |
| 1288 | } | |
| 1289 | "#, | |
| 1290 | r#" | |
| 1291 | trait Foo { | |
| 1292 | fn foo<T>(&self, value: i32) -> i32; | |
| 1293 | fn bar<T>(&self, value: i32) -> i32 { todo!() } | |
| 1294 | } | |
| 1295 | ||
| 1296 | impl<T: ?Sized> Foo for $0T { | |
| 1297 | fn foo<T>(&self, value: i32) -> i32 { | |
| 1298 | todo!() | |
| 1299 | } | |
| 1300 | } | |
| 1301 | "#, | |
| 1302 | ); | |
| 1303 | } | |
| 1304 | ||
| 1305 | #[test] | |
| 1306 | fn test_gen_blanket_method_with_lifetimes() { | |
| 1307 | check_assist( | |
| 1308 | generate_blanket_trait_impl, | |
| 1309 | r#" | |
| 1310 | trait $0Foo<'a> { | |
| 1311 | fn foo(&self) -> &'a str; | |
| 1312 | } | |
| 1313 | "#, | |
| 1314 | r#" | |
| 1315 | trait Foo<'a> { | |
| 1316 | fn foo(&self) -> &'a str; | |
| 1317 | } | |
| 1318 | ||
| 1319 | impl<'a, T: ?Sized> Foo<'a> for $0T { | |
| 1320 | fn foo(&self) -> &'a str { | |
| 1321 | todo!() | |
| 1322 | } | |
| 1323 | } | |
| 1324 | "#, | |
| 1325 | ); | |
| 1326 | } | |
| 1327 | ||
| 1328 | #[test] | |
| 1329 | fn test_gen_blanket_method_with_lifetime_bounds() { | |
| 1330 | check_assist( | |
| 1331 | generate_blanket_trait_impl, | |
| 1332 | r#" | |
| 1333 | trait $0Foo<'a: 'static> { | |
| 1334 | fn foo(&self) -> &'a str; | |
| 1335 | } | |
| 1336 | "#, | |
| 1337 | r#" | |
| 1338 | trait Foo<'a: 'static> { | |
| 1339 | fn foo(&self) -> &'a str; | |
| 1340 | } | |
| 1341 | ||
| 1342 | impl<'a: 'static, T: ?Sized> Foo<'a> for $0T { | |
| 1343 | fn foo(&self) -> &'a str { | |
| 1344 | todo!() | |
| 1345 | } | |
| 1346 | } | |
| 1347 | "#, | |
| 1348 | ); | |
| 1349 | } | |
| 1350 | ||
| 1351 | #[test] | |
| 1352 | fn test_gen_blanket_method_with_lifetime_quick_bounds() { | |
| 1353 | check_assist( | |
| 1354 | generate_blanket_trait_impl, | |
| 1355 | r#" | |
| 1356 | trait $0Foo<'a>: 'a { | |
| 1357 | fn foo(&self) -> &'a str; | |
| 1358 | } | |
| 1359 | "#, | |
| 1360 | r#" | |
| 1361 | trait Foo<'a>: 'a { | |
| 1362 | fn foo(&self) -> &'a str; | |
| 1363 | } | |
| 1364 | ||
| 1365 | impl<'a, T: 'a + ?Sized> Foo<'a> for $0T { | |
| 1366 | fn foo(&self) -> &'a str { | |
| 1367 | todo!() | |
| 1368 | } | |
| 1369 | } | |
| 1370 | "#, | |
| 1371 | ); | |
| 1372 | } | |
| 1373 | ||
| 1374 | #[test] | |
| 1375 | fn test_gen_blanket_method_with_multiple_lifetimes() { | |
| 1376 | check_assist( | |
| 1377 | generate_blanket_trait_impl, | |
| 1378 | r#" | |
| 1379 | trait $0Foo<'a, 'b> { | |
| 1380 | fn foo(&self) -> &'a &'b str; | |
| 1381 | } | |
| 1382 | "#, | |
| 1383 | r#" | |
| 1384 | trait Foo<'a, 'b> { | |
| 1385 | fn foo(&self) -> &'a &'b str; | |
| 1386 | } | |
| 1387 | ||
| 1388 | impl<'a, 'b, T: ?Sized> Foo<'a, 'b> for $0T { | |
| 1389 | fn foo(&self) -> &'a &'b str { | |
| 1390 | todo!() | |
| 1391 | } | |
| 1392 | } | |
| 1393 | "#, | |
| 1394 | ); | |
| 1395 | } | |
| 1396 | ||
| 1397 | #[test] | |
| 1398 | fn test_gen_blanket_method_with_lifetime_bounds_at_where_clause() { | |
| 1399 | check_assist( | |
| 1400 | generate_blanket_trait_impl, | |
| 1401 | r#" | |
| 1402 | trait $0Foo<'a> | |
| 1403 | where 'a: 'static, | |
| 1404 | { | |
| 1405 | fn foo(&self) -> &'a str; | |
| 1406 | } | |
| 1407 | "#, | |
| 1408 | r#" | |
| 1409 | trait Foo<'a> | |
| 1410 | where 'a: 'static, | |
| 1411 | { | |
| 1412 | fn foo(&self) -> &'a str; | |
| 1413 | } | |
| 1414 | ||
| 1415 | impl<'a, T: ?Sized> Foo<'a> for $0T | |
| 1416 | where 'a: 'static, | |
| 1417 | { | |
| 1418 | fn foo(&self) -> &'a str { | |
| 1419 | todo!() | |
| 1420 | } | |
| 1421 | } | |
| 1422 | "#, | |
| 1423 | ); | |
| 1424 | } | |
| 1425 | ||
| 1426 | #[test] | |
| 1427 | fn test_gen_blanket_not_on_name() { | |
| 1428 | check_assist_not_applicable( | |
| 1429 | generate_blanket_trait_impl, | |
| 1430 | r#" | |
| 1431 | trait Foo<T: Send>: $0ToOwned | |
| 1432 | where | |
| 1433 | Self::Owned: Default, | |
| 1434 | { | |
| 1435 | fn foo(&self) -> T; | |
| 1436 | ||
| 1437 | fn print_foo(&self) { | |
| 1438 | println!("{}", self.foo()); | |
| 1439 | } | |
| 1440 | } | |
| 1441 | "#, | |
| 1442 | ); | |
| 1443 | ||
| 1444 | check_assist_not_applicable( | |
| 1445 | generate_blanket_trait_impl, | |
| 1446 | r#" | |
| 1447 | trait Foo<T: Send>: ToOwned | |
| 1448 | where | |
| 1449 | Self::Owned: Default, | |
| 1450 | { | |
| 1451 | $0fn foo(&self) -> T; | |
| 1452 | ||
| 1453 | fn print_foo(&self) { | |
| 1454 | println!("{}", self.foo()); | |
| 1455 | } | |
| 1456 | } | |
| 1457 | "#, | |
| 1458 | ); | |
| 1459 | ||
| 1460 | check_assist_not_applicable( | |
| 1461 | generate_blanket_trait_impl, | |
| 1462 | r#" | |
| 1463 | trait Foo<T: Send>: ToOwned | |
| 1464 | where | |
| 1465 | Self::Owned: Default, | |
| 1466 | { | |
| 1467 | fn $0foo(&self) -> T; | |
| 1468 | ||
| 1469 | fn print_foo(&self) { | |
| 1470 | println!("{}", self.foo()); | |
| 1471 | } | |
| 1472 | } | |
| 1473 | "#, | |
| 1474 | ); | |
| 1475 | } | |
| 1476 | ||
| 1477 | #[test] | |
| 1478 | fn test_gen_blanket_existing_impl() { | |
| 1479 | cov_mark::check!(existing_any_impl); | |
| 1480 | check_assist_not_applicable( | |
| 1481 | generate_blanket_trait_impl, | |
| 1482 | r#" | |
| 1483 | trait $0Foo: Default { | |
| 1484 | fn foo(&self) -> Self; | |
| 1485 | } | |
| 1486 | impl Foo for () {} | |
| 1487 | "#, | |
| 1488 | ); | |
| 1489 | } | |
| 1490 | ||
| 1491 | #[test] | |
| 1492 | fn test_gen_blanket_existing_other_impl() { | |
| 1493 | check_assist( | |
| 1494 | generate_blanket_trait_impl, | |
| 1495 | r#" | |
| 1496 | trait $0Foo: Default { | |
| 1497 | fn foo(&self) -> Self; | |
| 1498 | } | |
| 1499 | trait Bar: Default { | |
| 1500 | fn bar(&self) -> Self; | |
| 1501 | } | |
| 1502 | impl Bar for () {} | |
| 1503 | "#, | |
| 1504 | r#" | |
| 1505 | trait Foo: Default { | |
| 1506 | fn foo(&self) -> Self; | |
| 1507 | } | |
| 1508 | ||
| 1509 | impl<T: Default> Foo for $0T { | |
| 1510 | fn foo(&self) -> Self { | |
| 1511 | todo!() | |
| 1512 | } | |
| 1513 | } | |
| 1514 | trait Bar: Default { | |
| 1515 | fn bar(&self) -> Self; | |
| 1516 | } | |
| 1517 | impl Bar for () {} | |
| 1518 | "#, | |
| 1519 | ); | |
| 1520 | } | |
| 1521 | ||
| 1522 | #[test] | |
| 1523 | fn test_gen_blanket_apply_on_other_impl_block() { | |
| 1524 | check_assist( | |
| 1525 | generate_blanket_trait_impl, | |
| 1526 | r#" | |
| 1527 | trait $0Foo { | |
| 1528 | fn foo(&self) -> i32; | |
| 1529 | ||
| 1530 | fn print_foo(&self) { | |
| 1531 | println!("{}", self.foo()); | |
| 1532 | } | |
| 1533 | } | |
| 1534 | ||
| 1535 | trait Bar {} | |
| 1536 | impl Bar for i32 {} | |
| 1537 | "#, | |
| 1538 | r#" | |
| 1539 | trait Foo { | |
| 1540 | fn foo(&self) -> i32; | |
| 1541 | ||
| 1542 | fn print_foo(&self) { | |
| 1543 | println!("{}", self.foo()); | |
| 1544 | } | |
| 1545 | } | |
| 1546 | ||
| 1547 | impl<T: ?Sized> Foo for $0T { | |
| 1548 | fn foo(&self) -> i32 { | |
| 1549 | todo!() | |
| 1550 | } | |
| 1551 | } | |
| 1552 | ||
| 1553 | trait Bar {} | |
| 1554 | impl Bar for i32 {} | |
| 1555 | "#, | |
| 1556 | ); | |
| 1557 | } | |
| 1558 | ||
| 1559 | #[test] | |
| 1560 | fn test_gen_blanket_apply_on_other_blanket_impl_block() { | |
| 1561 | check_assist( | |
| 1562 | generate_blanket_trait_impl, | |
| 1563 | r#" | |
| 1564 | trait $0Foo { | |
| 1565 | fn foo(&self) -> i32; | |
| 1566 | ||
| 1567 | fn print_foo(&self) { | |
| 1568 | println!("{}", self.foo()); | |
| 1569 | } | |
| 1570 | } | |
| 1571 | ||
| 1572 | trait Bar {} | |
| 1573 | impl<T> Bar for T {} | |
| 1574 | "#, | |
| 1575 | r#" | |
| 1576 | trait Foo { | |
| 1577 | fn foo(&self) -> i32; | |
| 1578 | ||
| 1579 | fn print_foo(&self) { | |
| 1580 | println!("{}", self.foo()); | |
| 1581 | } | |
| 1582 | } | |
| 1583 | ||
| 1584 | impl<T: ?Sized> Foo for $0T { | |
| 1585 | fn foo(&self) -> i32 { | |
| 1586 | todo!() | |
| 1587 | } | |
| 1588 | } | |
| 1589 | ||
| 1590 | trait Bar {} | |
| 1591 | impl<T> Bar for T {} | |
| 1592 | "#, | |
| 1593 | ); | |
| 1594 | } | |
| 1595 | } |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs+2-2| ... | ... | @@ -57,7 +57,7 @@ fn generate_record_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<( |
| 57 | 57 | }; |
| 58 | 58 | |
| 59 | 59 | let module = ctx.sema.to_def(&strukt)?.module(ctx.db()); |
| 60 | let cfg = ctx.config.find_path_confg(ctx.sema.is_nightly(module.krate())); | |
| 60 | let cfg = ctx.config.find_path_config(ctx.sema.is_nightly(module.krate())); | |
| 61 | 61 | let trait_ = deref_type_to_generate.to_trait(&ctx.sema, module.krate())?; |
| 62 | 62 | let trait_path = module.find_path(ctx.db(), ModuleDef::Trait(trait_), cfg)?; |
| 63 | 63 | |
| ... | ... | @@ -99,7 +99,7 @@ fn generate_tuple_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<() |
| 99 | 99 | }; |
| 100 | 100 | |
| 101 | 101 | let module = ctx.sema.to_def(&strukt)?.module(ctx.db()); |
| 102 | let cfg = ctx.config.find_path_confg(ctx.sema.is_nightly(module.krate())); | |
| 102 | let cfg = ctx.config.find_path_config(ctx.sema.is_nightly(module.krate())); | |
| 103 | 103 | let trait_ = deref_type_to_generate.to_trait(&ctx.sema, module.krate())?; |
| 104 | 104 | let trait_path = module.find_path(ctx.db(), ModuleDef::Trait(trait_), cfg)?; |
| 105 | 105 |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs+1-1| ... | ... | @@ -77,7 +77,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option |
| 77 | 77 | |
| 78 | 78 | let item_in_ns = hir::ItemInNs::from(hir::ModuleDef::from(ty.as_adt()?)); |
| 79 | 79 | |
| 80 | let cfg = ctx.config.find_path_confg(ctx.sema.is_nightly(current_module.krate())); | |
| 80 | let cfg = ctx.config.find_path_config(ctx.sema.is_nightly(current_module.krate())); | |
| 81 | 81 | let type_path = current_module.find_path( |
| 82 | 82 | ctx.sema.db, |
| 83 | 83 | item_for_path_search(ctx.sema.db, item_in_ns)?, |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_single_field_struct_from.rs+1-1| ... | ... | @@ -169,7 +169,7 @@ fn make_constructors( |
| 169 | 169 | types: &[ast::Type], |
| 170 | 170 | ) -> Vec<Option<ast::Expr>> { |
| 171 | 171 | let (db, sema) = (ctx.db(), &ctx.sema); |
| 172 | let cfg = ctx.config.find_path_confg(ctx.sema.is_nightly(module.krate())); | |
| 172 | let cfg = ctx.config.find_path_config(ctx.sema.is_nightly(module.krate())); | |
| 173 | 173 | types |
| 174 | 174 | .iter() |
| 175 | 175 | .map(|ty| { |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/pull_assignment_up.rs+31-2| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | use either::Either; | |
| 1 | 2 | use syntax::{ |
| 2 | 3 | AstNode, |
| 3 | 4 | algo::find_node_at_range, |
| ... | ... | @@ -52,14 +53,15 @@ pub(crate) fn pull_assignment_up(acc: &mut Assists, ctx: &AssistContext<'_>) -> |
| 52 | 53 | assignments: Vec::new(), |
| 53 | 54 | }; |
| 54 | 55 | |
| 55 | let tgt: ast::Expr = if let Some(if_expr) = ctx.find_node_at_offset::<ast::IfExpr>() { | |
| 56 | let node: Either<ast::IfExpr, ast::MatchExpr> = ctx.find_node_at_offset()?; | |
| 57 | let tgt: ast::Expr = if let Either::Left(if_expr) = node { | |
| 56 | 58 | let if_expr = std::iter::successors(Some(if_expr), |it| { |
| 57 | 59 | it.syntax().parent().and_then(ast::IfExpr::cast) |
| 58 | 60 | }) |
| 59 | 61 | .last()?; |
| 60 | 62 | collector.collect_if(&if_expr)?; |
| 61 | 63 | if_expr.into() |
| 62 | } else if let Some(match_expr) = ctx.find_node_at_offset::<ast::MatchExpr>() { | |
| 64 | } else if let Either::Right(match_expr) = node { | |
| 63 | 65 | collector.collect_match(&match_expr)?; |
| 64 | 66 | match_expr.into() |
| 65 | 67 | } else { |
| ... | ... | @@ -311,6 +313,33 @@ fn foo() { |
| 311 | 313 | ); |
| 312 | 314 | } |
| 313 | 315 | |
| 316 | #[test] | |
| 317 | fn test_pull_assignment_up_match_in_if_expr() { | |
| 318 | check_assist( | |
| 319 | pull_assignment_up, | |
| 320 | r#" | |
| 321 | fn foo() { | |
| 322 | let x; | |
| 323 | if true { | |
| 324 | match true { | |
| 325 | true => $0x = 2, | |
| 326 | false => x = 3, | |
| 327 | } | |
| 328 | } | |
| 329 | }"#, | |
| 330 | r#" | |
| 331 | fn foo() { | |
| 332 | let x; | |
| 333 | if true { | |
| 334 | x = match true { | |
| 335 | true => 2, | |
| 336 | false => 3, | |
| 337 | }; | |
| 338 | } | |
| 339 | }"#, | |
| 340 | ); | |
| 341 | } | |
| 342 | ||
| 314 | 343 | #[test] |
| 315 | 344 | fn test_pull_assignment_up_assignment_expressions() { |
| 316 | 345 | check_assist( |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs+1-1| ... | ... | @@ -45,7 +45,7 @@ pub(crate) fn qualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>) -> |
| 45 | 45 | let current_edition = current_module.krate().edition(ctx.db()); |
| 46 | 46 | let target_module_def = ModuleDef::from(resolved_call); |
| 47 | 47 | let item_in_ns = ItemInNs::from(target_module_def); |
| 48 | let cfg = ctx.config.find_path_confg(ctx.sema.is_nightly(current_module.krate())); | |
| 48 | let cfg = ctx.config.find_path_config(ctx.sema.is_nightly(current_module.krate())); | |
| 49 | 49 | let receiver_path = current_module.find_path( |
| 50 | 50 | ctx.sema.db, |
| 51 | 51 | item_for_path_search(ctx.sema.db, item_in_ns)?, |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/raw_string.rs+133-44| ... | ... | @@ -1,10 +1,12 @@ |
| 1 | use std::borrow::Cow; | |
| 2 | ||
| 3 | use syntax::{AstToken, TextRange, TextSize, ast, ast::IsString}; | |
| 1 | use ide_db::source_change::SourceChangeBuilder; | |
| 2 | use syntax::{ | |
| 3 | AstToken, | |
| 4 | ast::{self, IsString, make::tokens::literal}, | |
| 5 | }; | |
| 4 | 6 | |
| 5 | 7 | use crate::{ |
| 6 | 8 | AssistContext, AssistId, Assists, |
| 7 | utils::{required_hashes, string_suffix}, | |
| 9 | utils::{required_hashes, string_prefix, string_suffix}, | |
| 8 | 10 | }; |
| 9 | 11 | |
| 10 | 12 | // Assist: make_raw_string |
| ... | ... | @@ -23,8 +25,7 @@ use crate::{ |
| 23 | 25 | // } |
| 24 | 26 | // ``` |
| 25 | 27 | pub(crate) fn make_raw_string(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { |
| 26 | // FIXME: This should support byte and c strings as well. | |
| 27 | let token = ctx.find_token_at_offset::<ast::String>()?; | |
| 28 | let token = ctx.find_token_at_offset::<ast::AnyString>()?; | |
| 28 | 29 | if token.is_raw() { |
| 29 | 30 | return None; |
| 30 | 31 | } |
| ... | ... | @@ -36,16 +37,10 @@ pub(crate) fn make_raw_string(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt |
| 36 | 37 | target, |
| 37 | 38 | |edit| { |
| 38 | 39 | let hashes = "#".repeat(required_hashes(&value).max(1)); |
| 39 | let range = token.syntax().text_range(); | |
| 40 | let raw_prefix = token.raw_prefix(); | |
| 40 | 41 | let suffix = string_suffix(token.text()).unwrap_or_default(); |
| 41 | let range = TextRange::new(range.start(), range.end() - TextSize::of(suffix)); | |
| 42 | if matches!(value, Cow::Borrowed(_)) { | |
| 43 | // Avoid replacing the whole string to better position the cursor. | |
| 44 | edit.insert(range.start(), format!("r{hashes}")); | |
| 45 | edit.insert(range.end(), hashes); | |
| 46 | } else { | |
| 47 | edit.replace(range, format!("r{hashes}\"{value}\"{hashes}")); | |
| 48 | } | |
| 42 | let new_str = format!("{raw_prefix}{hashes}\"{value}\"{hashes}{suffix}"); | |
| 43 | replace_literal(&token, &new_str, edit, ctx); | |
| 49 | 44 | }, |
| 50 | 45 | ) |
| 51 | 46 | } |
| ... | ... | @@ -66,7 +61,7 @@ pub(crate) fn make_raw_string(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt |
| 66 | 61 | // } |
| 67 | 62 | // ``` |
| 68 | 63 | pub(crate) fn make_usual_string(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { |
| 69 | let token = ctx.find_token_at_offset::<ast::String>()?; | |
| 64 | let token = ctx.find_token_at_offset::<ast::AnyString>()?; | |
| 70 | 65 | if !token.is_raw() { |
| 71 | 66 | return None; |
| 72 | 67 | } |
| ... | ... | @@ -80,18 +75,9 @@ pub(crate) fn make_usual_string(acc: &mut Assists, ctx: &AssistContext<'_>) -> O |
| 80 | 75 | // parse inside string to escape `"` |
| 81 | 76 | let escaped = value.escape_default().to_string(); |
| 82 | 77 | let suffix = string_suffix(token.text()).unwrap_or_default(); |
| 83 | if let Some(offsets) = token.quote_offsets() | |
| 84 | && token.text()[offsets.contents - token.syntax().text_range().start()] == escaped | |
| 85 | { | |
| 86 | let end_quote = offsets.quotes.1; | |
| 87 | let end_quote = | |
| 88 | TextRange::new(end_quote.start(), end_quote.end() - TextSize::of(suffix)); | |
| 89 | edit.replace(offsets.quotes.0, "\""); | |
| 90 | edit.replace(end_quote, "\""); | |
| 91 | return; | |
| 92 | } | |
| 93 | ||
| 94 | edit.replace(token.syntax().text_range(), format!("\"{escaped}\"{suffix}")); | |
| 78 | let prefix = string_prefix(token.text()).map_or("", |s| s.trim_end_matches('r')); | |
| 79 | let new_str = format!("{prefix}\"{escaped}\"{suffix}"); | |
| 80 | replace_literal(&token, &new_str, edit, ctx); | |
| 95 | 81 | }, |
| 96 | 82 | ) |
| 97 | 83 | } |
| ... | ... | @@ -112,16 +98,18 @@ pub(crate) fn make_usual_string(acc: &mut Assists, ctx: &AssistContext<'_>) -> O |
| 112 | 98 | // } |
| 113 | 99 | // ``` |
| 114 | 100 | pub(crate) fn add_hash(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { |
| 115 | let token = ctx.find_token_at_offset::<ast::String>()?; | |
| 101 | let token = ctx.find_token_at_offset::<ast::AnyString>()?; | |
| 116 | 102 | if !token.is_raw() { |
| 117 | 103 | return None; |
| 118 | 104 | } |
| 119 | let text_range = token.syntax().text_range(); | |
| 120 | let target = text_range; | |
| 105 | let target = token.syntax().text_range(); | |
| 121 | 106 | acc.add(AssistId::refactor("add_hash"), "Add #", target, |edit| { |
| 122 | let suffix = string_suffix(token.text()).unwrap_or_default(); | |
| 123 | edit.insert(text_range.start() + TextSize::of('r'), "#"); | |
| 124 | edit.insert(text_range.end() - TextSize::of(suffix), "#"); | |
| 107 | let str = token.text(); | |
| 108 | let suffix = string_suffix(str).unwrap_or_default(); | |
| 109 | let raw_prefix = token.raw_prefix(); | |
| 110 | let wrap_range = raw_prefix.len()..str.len() - suffix.len(); | |
| 111 | let new_str = [raw_prefix, "#", &str[wrap_range], "#", suffix].concat(); | |
| 112 | replace_literal(&token, &new_str, edit, ctx); | |
| 125 | 113 | }) |
| 126 | 114 | } |
| 127 | 115 | |
| ... | ... | @@ -141,17 +129,15 @@ pub(crate) fn add_hash(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> |
| 141 | 129 | // } |
| 142 | 130 | // ``` |
| 143 | 131 | pub(crate) fn remove_hash(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { |
| 144 | let token = ctx.find_token_at_offset::<ast::String>()?; | |
| 132 | let token = ctx.find_token_at_offset::<ast::AnyString>()?; | |
| 145 | 133 | if !token.is_raw() { |
| 146 | 134 | return None; |
| 147 | 135 | } |
| 148 | 136 | |
| 149 | 137 | let text = token.text(); |
| 150 | if !text.starts_with("r#") && text.ends_with('#') { | |
| 151 | return None; | |
| 152 | } | |
| 153 | 138 | |
| 154 | let existing_hashes = text.chars().skip(1).take_while(|&it| it == '#').count(); | |
| 139 | let existing_hashes = | |
| 140 | text.chars().skip(token.raw_prefix().len()).take_while(|&it| it == '#').count(); | |
| 155 | 141 | |
| 156 | 142 | let text_range = token.syntax().text_range(); |
| 157 | 143 | let internal_text = &text[token.text_range_between_quotes()? - text_range.start()]; |
| ... | ... | @@ -163,14 +149,38 @@ pub(crate) fn remove_hash(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< |
| 163 | 149 | |
| 164 | 150 | acc.add(AssistId::refactor_rewrite("remove_hash"), "Remove #", text_range, |edit| { |
| 165 | 151 | let suffix = string_suffix(text).unwrap_or_default(); |
| 166 | edit.delete(TextRange::at(text_range.start() + TextSize::of('r'), TextSize::of('#'))); | |
| 167 | edit.delete( | |
| 168 | TextRange::new(text_range.end() - TextSize::of('#'), text_range.end()) | |
| 169 | - TextSize::of(suffix), | |
| 170 | ); | |
| 152 | let prefix = token.raw_prefix(); | |
| 153 | let wrap_range = prefix.len() + 1..text.len() - suffix.len() - 1; | |
| 154 | let new_str = [prefix, &text[wrap_range], suffix].concat(); | |
| 155 | replace_literal(&token, &new_str, edit, ctx); | |
| 171 | 156 | }) |
| 172 | 157 | } |
| 173 | 158 | |
| 159 | fn replace_literal( | |
| 160 | token: &impl AstToken, | |
| 161 | new: &str, | |
| 162 | builder: &mut SourceChangeBuilder, | |
| 163 | ctx: &AssistContext<'_>, | |
| 164 | ) { | |
| 165 | let token = token.syntax(); | |
| 166 | let node = token.parent().expect("no parent token"); | |
| 167 | let mut edit = builder.make_editor(&node); | |
| 168 | let new_literal = literal(new); | |
| 169 | ||
| 170 | edit.replace(token, mut_token(new_literal)); | |
| 171 | ||
| 172 | builder.add_file_edits(ctx.vfs_file_id(), edit); | |
| 173 | } | |
| 174 | ||
| 175 | fn mut_token(token: syntax::SyntaxToken) -> syntax::SyntaxToken { | |
| 176 | let node = token.parent().expect("no parent token"); | |
| 177 | node.clone_for_update() | |
| 178 | .children_with_tokens() | |
| 179 | .filter_map(|it| it.into_token()) | |
| 180 | .find(|it| it.text_range() == token.text_range() && it.text() == token.text()) | |
| 181 | .unwrap() | |
| 182 | } | |
| 183 | ||
| 174 | 184 | #[cfg(test)] |
| 175 | 185 | mod tests { |
| 176 | 186 | use super::*; |
| ... | ... | @@ -224,6 +234,42 @@ string"#; |
| 224 | 234 | ) |
| 225 | 235 | } |
| 226 | 236 | |
| 237 | #[test] | |
| 238 | fn make_raw_byte_string_works() { | |
| 239 | check_assist( | |
| 240 | make_raw_string, | |
| 241 | r#" | |
| 242 | fn f() { | |
| 243 | let s = $0b"random\nstring"; | |
| 244 | } | |
| 245 | "#, | |
| 246 | r##" | |
| 247 | fn f() { | |
| 248 | let s = br#"random | |
| 249 | string"#; | |
| 250 | } | |
| 251 | "##, | |
| 252 | ) | |
| 253 | } | |
| 254 | ||
| 255 | #[test] | |
| 256 | fn make_raw_c_string_works() { | |
| 257 | check_assist( | |
| 258 | make_raw_string, | |
| 259 | r#" | |
| 260 | fn f() { | |
| 261 | let s = $0c"random\nstring"; | |
| 262 | } | |
| 263 | "#, | |
| 264 | r##" | |
| 265 | fn f() { | |
| 266 | let s = cr#"random | |
| 267 | string"#; | |
| 268 | } | |
| 269 | "##, | |
| 270 | ) | |
| 271 | } | |
| 272 | ||
| 227 | 273 | #[test] |
| 228 | 274 | fn make_raw_string_hashes_inside_works() { |
| 229 | 275 | check_assist( |
| ... | ... | @@ -348,6 +394,23 @@ string"###; |
| 348 | 394 | ) |
| 349 | 395 | } |
| 350 | 396 | |
| 397 | #[test] | |
| 398 | fn add_hash_works_for_c_str() { | |
| 399 | check_assist( | |
| 400 | add_hash, | |
| 401 | r#" | |
| 402 | fn f() { | |
| 403 | let s = $0cr"random string"; | |
| 404 | } | |
| 405 | "#, | |
| 406 | r##" | |
| 407 | fn f() { | |
| 408 | let s = cr#"random string"#; | |
| 409 | } | |
| 410 | "##, | |
| 411 | ) | |
| 412 | } | |
| 413 | ||
| 351 | 414 | #[test] |
| 352 | 415 | fn add_hash_has_suffix_works() { |
| 353 | 416 | check_assist( |
| ... | ... | @@ -433,6 +496,15 @@ string"###; |
| 433 | 496 | ) |
| 434 | 497 | } |
| 435 | 498 | |
| 499 | #[test] | |
| 500 | fn remove_hash_works_for_c_str() { | |
| 501 | check_assist( | |
| 502 | remove_hash, | |
| 503 | r##"fn f() { let s = $0cr#"random string"#; }"##, | |
| 504 | r#"fn f() { let s = cr"random string"; }"#, | |
| 505 | ) | |
| 506 | } | |
| 507 | ||
| 436 | 508 | #[test] |
| 437 | 509 | fn remove_hash_has_suffix_works() { |
| 438 | 510 | check_assist( |
| ... | ... | @@ -529,6 +601,23 @@ string"###; |
| 529 | 601 | ) |
| 530 | 602 | } |
| 531 | 603 | |
| 604 | #[test] | |
| 605 | fn make_usual_string_for_c_str() { | |
| 606 | check_assist( | |
| 607 | make_usual_string, | |
| 608 | r##" | |
| 609 | fn f() { | |
| 610 | let s = $0cr#"random string"#; | |
| 611 | } | |
| 612 | "##, | |
| 613 | r#" | |
| 614 | fn f() { | |
| 615 | let s = c"random string"; | |
| 616 | } | |
| 617 | "#, | |
| 618 | ) | |
| 619 | } | |
| 620 | ||
| 532 | 621 | #[test] |
| 533 | 622 | fn make_usual_string_has_suffix_works() { |
| 534 | 623 | check_assist( |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs+1-1| ... | ... | @@ -71,7 +71,7 @@ pub(crate) fn replace_derive_with_manual_impl( |
| 71 | 71 | let current_module = ctx.sema.scope(adt.syntax())?.module(); |
| 72 | 72 | let current_crate = current_module.krate(); |
| 73 | 73 | let current_edition = current_crate.edition(ctx.db()); |
| 74 | let cfg = ctx.config.find_path_confg(ctx.sema.is_nightly(current_crate)); | |
| 74 | let cfg = ctx.config.find_path_config(ctx.sema.is_nightly(current_crate)); | |
| 75 | 75 | |
| 76 | 76 | let found_traits = items_locator::items_with_name( |
| 77 | 77 | ctx.db(), |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs+1-1| ... | ... | @@ -64,7 +64,7 @@ pub(crate) fn replace_qualified_name_with_use( |
| 64 | 64 | let path_to_qualifier = starts_with_name_ref |
| 65 | 65 | .then(|| { |
| 66 | 66 | let mod_ = ctx.sema.scope(original_path.syntax())?.module(); |
| 67 | let cfg = ctx.config.find_path_confg(ctx.sema.is_nightly(mod_.krate())); | |
| 67 | let cfg = ctx.config.find_path_config(ctx.sema.is_nightly(mod_.krate())); | |
| 68 | 68 | mod_.find_use_path(ctx.sema.db, module, ctx.config.insert_use.prefix_kind, cfg) |
| 69 | 69 | }) |
| 70 | 70 | .flatten(); |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs+1-1| ... | ... | @@ -55,7 +55,7 @@ pub(crate) fn term_search(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< |
| 55 | 55 | path.gen_source_code( |
| 56 | 56 | &scope, |
| 57 | 57 | &mut formatter, |
| 58 | ctx.config.find_path_confg(ctx.sema.is_nightly(scope.module().krate())), | |
| 58 | ctx.config.find_path_config(ctx.sema.is_nightly(scope.module().krate())), | |
| 59 | 59 | scope.krate().to_display_target(ctx.db()), |
| 60 | 60 | ) |
| 61 | 61 | .ok() |
src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs+1-1| ... | ... | @@ -132,7 +132,7 @@ pub(crate) fn desugar_async_into_impl_future( |
| 132 | 132 | |
| 133 | 133 | let scope = ctx.sema.scope(function.syntax())?; |
| 134 | 134 | let module = scope.module(); |
| 135 | let cfg = ctx.config.find_path_confg(ctx.sema.is_nightly(module.krate())); | |
| 135 | let cfg = ctx.config.find_path_config(ctx.sema.is_nightly(module.krate())); | |
| 136 | 136 | let future_trait = FamousDefs(&ctx.sema, scope.krate()).core_future_Future()?; |
| 137 | 137 | let trait_path = module.find_path(ctx.db(), ModuleDef::Trait(future_trait), cfg)?; |
| 138 | 138 | let edition = scope.krate().edition(ctx.db()); |
src/tools/rust-analyzer/crates/ide-assists/src/lib.rs+2| ... | ... | @@ -153,6 +153,7 @@ mod handlers { |
| 153 | 153 | mod flip_comma; |
| 154 | 154 | mod flip_or_pattern; |
| 155 | 155 | mod flip_trait_bound; |
| 156 | mod generate_blanket_trait_impl; | |
| 156 | 157 | mod generate_constant; |
| 157 | 158 | mod generate_default_from_enum_variant; |
| 158 | 159 | mod generate_default_from_new; |
| ... | ... | @@ -308,6 +309,7 @@ mod handlers { |
| 308 | 309 | generate_new::generate_new, |
| 309 | 310 | generate_trait_from_impl::generate_trait_from_impl, |
| 310 | 311 | generate_single_field_struct_from::generate_single_field_struct_from, |
| 312 | generate_blanket_trait_impl::generate_blanket_trait_impl, | |
| 311 | 313 | inline_call::inline_call, |
| 312 | 314 | inline_call::inline_into_callers, |
| 313 | 315 | inline_const_as_literal::inline_const_as_literal, |
src/tools/rust-analyzer/crates/ide-assists/src/tests.rs+3-3| ... | ... | @@ -5,7 +5,7 @@ use hir::{Semantics, db::HirDatabase, setup_tracing}; |
| 5 | 5 | use ide_db::{ |
| 6 | 6 | EditionedFileId, FileRange, RootDatabase, SnippetCap, |
| 7 | 7 | assists::ExprFillDefaultMode, |
| 8 | base_db::{SourceDatabase, salsa}, | |
| 8 | base_db::SourceDatabase, | |
| 9 | 9 | imports::insert_use::{ImportGranularity, InsertUseConfig}, |
| 10 | 10 | source_change::FileSystemEdit, |
| 11 | 11 | }; |
| ... | ... | @@ -109,7 +109,7 @@ fn assists( |
| 109 | 109 | resolve: AssistResolveStrategy, |
| 110 | 110 | range: ide_db::FileRange, |
| 111 | 111 | ) -> Vec<Assist> { |
| 112 | salsa::attach(db, || { | |
| 112 | hir::attach_db(db, || { | |
| 113 | 113 | HirDatabase::zalsa_register_downcaster(db); |
| 114 | 114 | crate::assists(db, config, resolve, range) |
| 115 | 115 | }) |
| ... | ... | @@ -332,7 +332,7 @@ fn check_with_config( |
| 332 | 332 | _ => AssistResolveStrategy::All, |
| 333 | 333 | }; |
| 334 | 334 | let mut acc = Assists::new(&ctx, resolve); |
| 335 | salsa::attach(&db, || { | |
| 335 | hir::attach_db(&db, || { | |
| 336 | 336 | HirDatabase::zalsa_register_downcaster(&db); |
| 337 | 337 | handler(&mut acc, &ctx); |
| 338 | 338 | }); |
src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs+40| ... | ... | @@ -1345,6 +1345,46 @@ fn foo<T: Copy + Clone>() { } |
| 1345 | 1345 | ) |
| 1346 | 1346 | } |
| 1347 | 1347 | |
| 1348 | #[test] | |
| 1349 | fn doctest_generate_blanket_trait_impl() { | |
| 1350 | check_doc_test( | |
| 1351 | "generate_blanket_trait_impl", | |
| 1352 | r#####" | |
| 1353 | trait $0Foo<T: Send>: ToOwned | |
| 1354 | where | |
| 1355 | Self::Owned: Default, | |
| 1356 | { | |
| 1357 | fn foo(&self) -> T; | |
| 1358 | ||
| 1359 | fn print_foo(&self) { | |
| 1360 | println!("{}", self.foo()); | |
| 1361 | } | |
| 1362 | } | |
| 1363 | "#####, | |
| 1364 | r#####" | |
| 1365 | trait Foo<T: Send>: ToOwned | |
| 1366 | where | |
| 1367 | Self::Owned: Default, | |
| 1368 | { | |
| 1369 | fn foo(&self) -> T; | |
| 1370 | ||
| 1371 | fn print_foo(&self) { | |
| 1372 | println!("{}", self.foo()); | |
| 1373 | } | |
| 1374 | } | |
| 1375 | ||
| 1376 | impl<T: Send, T1: ToOwned + ?Sized> Foo<T> for $0T1 | |
| 1377 | where | |
| 1378 | Self::Owned: Default, | |
| 1379 | { | |
| 1380 | fn foo(&self) -> T { | |
| 1381 | todo!() | |
| 1382 | } | |
| 1383 | } | |
| 1384 | "#####, | |
| 1385 | ) | |
| 1386 | } | |
| 1387 | ||
| 1348 | 1388 | #[test] |
| 1349 | 1389 | fn doctest_generate_constant() { |
| 1350 | 1390 | check_doc_test( |
src/tools/rust-analyzer/crates/ide-assists/src/utils.rs+31| ... | ... | @@ -1057,6 +1057,21 @@ fn test_string_suffix() { |
| 1057 | 1057 | assert_eq!(Some("i32"), string_suffix(r##"r#""#i32"##)); |
| 1058 | 1058 | } |
| 1059 | 1059 | |
| 1060 | /// Calculate the string literal prefix length | |
| 1061 | pub(crate) fn string_prefix(s: &str) -> Option<&str> { | |
| 1062 | s.split_once(['"', '\'', '#']).map(|(prefix, _)| prefix) | |
| 1063 | } | |
| 1064 | #[test] | |
| 1065 | fn test_string_prefix() { | |
| 1066 | assert_eq!(Some(""), string_prefix(r#""abc""#)); | |
| 1067 | assert_eq!(Some(""), string_prefix(r#""""#)); | |
| 1068 | assert_eq!(Some(""), string_prefix(r#"""suffix"#)); | |
| 1069 | assert_eq!(Some("c"), string_prefix(r#"c"""#)); | |
| 1070 | assert_eq!(Some("r"), string_prefix(r#"r"""#)); | |
| 1071 | assert_eq!(Some("cr"), string_prefix(r#"cr"""#)); | |
| 1072 | assert_eq!(Some("r"), string_prefix(r##"r#""#"##)); | |
| 1073 | } | |
| 1074 | ||
| 1060 | 1075 | /// Replaces the record expression, handling field shorthands including inside macros. |
| 1061 | 1076 | pub(crate) fn replace_record_field_expr( |
| 1062 | 1077 | ctx: &AssistContext<'_>, |
| ... | ... | @@ -1150,3 +1165,19 @@ pub fn is_body_const(sema: &Semantics<'_, RootDatabase>, expr: &ast::Expr) -> bo |
| 1150 | 1165 | }); |
| 1151 | 1166 | is_const |
| 1152 | 1167 | } |
| 1168 | ||
| 1169 | // FIXME: #20460 When hir-ty can analyze the `never` statement at the end of block, remove it | |
| 1170 | pub(crate) fn is_never_block( | |
| 1171 | sema: &Semantics<'_, RootDatabase>, | |
| 1172 | block_expr: &ast::BlockExpr, | |
| 1173 | ) -> bool { | |
| 1174 | if let Some(tail_expr) = block_expr.tail_expr() { | |
| 1175 | sema.type_of_expr(&tail_expr).is_some_and(|ty| ty.original.is_never()) | |
| 1176 | } else if let Some(ast::Stmt::ExprStmt(expr_stmt)) = block_expr.statements().last() | |
| 1177 | && let Some(expr) = expr_stmt.expr() | |
| 1178 | { | |
| 1179 | sema.type_of_expr(&expr).is_some_and(|ty| ty.original.is_never()) | |
| 1180 | } else { | |
| 1181 | false | |
| 1182 | } | |
| 1183 | } |
src/tools/rust-analyzer/crates/ide-completion/src/completions.rs+2-2| ... | ... | @@ -630,7 +630,7 @@ fn enum_variants_with_paths( |
| 630 | 630 | acc: &mut Completions, |
| 631 | 631 | ctx: &CompletionContext<'_>, |
| 632 | 632 | enum_: hir::Enum, |
| 633 | impl_: &Option<ast::Impl>, | |
| 633 | impl_: Option<&ast::Impl>, | |
| 634 | 634 | cb: impl Fn(&mut Completions, &CompletionContext<'_>, hir::Variant, hir::ModPath), |
| 635 | 635 | ) { |
| 636 | 636 | let mut process_variant = |variant: Variant| { |
| ... | ... | @@ -644,7 +644,7 @@ fn enum_variants_with_paths( |
| 644 | 644 | |
| 645 | 645 | let variants = enum_.variants(ctx.db); |
| 646 | 646 | |
| 647 | if let Some(impl_) = impl_.as_ref().and_then(|impl_| ctx.sema.to_def(impl_)) | |
| 647 | if let Some(impl_) = impl_.and_then(|impl_| ctx.sema.to_def(impl_)) | |
| 648 | 648 | && impl_.self_ty(ctx.db).as_adt() == Some(hir::Adt::Enum(enum_)) |
| 649 | 649 | { |
| 650 | 650 | variants.iter().for_each(|variant| process_variant(*variant)); |
src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs+1-1| ... | ... | @@ -39,7 +39,7 @@ pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext<'_>) { |
| 39 | 39 | "target_os" => KNOWN_OS.iter().copied().for_each(add_completion), |
| 40 | 40 | "target_vendor" => KNOWN_VENDOR.iter().copied().for_each(add_completion), |
| 41 | 41 | "target_endian" => ["little", "big"].into_iter().for_each(add_completion), |
| 42 | name => ctx.krate.potential_cfg(ctx.db).get_cfg_values(name).cloned().for_each(|s| { | |
| 42 | name => ctx.krate.potential_cfg(ctx.db).get_cfg_values(name).for_each(|s| { | |
| 43 | 43 | let s = s.as_str(); |
| 44 | 44 | let insert_text = format!(r#""{s}""#); |
| 45 | 45 | let mut item = CompletionItem::new( |
src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs+1-2| ... | ... | @@ -794,8 +794,7 @@ struct T(S); |
| 794 | 794 | |
| 795 | 795 | impl T { |
| 796 | 796 | fn foo(&self) { |
| 797 | // FIXME: This doesn't work without the trailing `a` as `0.` is a float | |
| 798 | self.0.a$0 | |
| 797 | self.0.$0 | |
| 799 | 798 | } |
| 800 | 799 | } |
| 801 | 800 | "#, |
src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs+13-6| ... | ... | @@ -9,7 +9,7 @@ use syntax::ast; |
| 9 | 9 | use crate::{ |
| 10 | 10 | CompletionContext, Completions, |
| 11 | 11 | completions::record::add_default_update, |
| 12 | context::{BreakableKind, PathCompletionCtx, PathExprCtx, Qualified}, | |
| 12 | context::{PathCompletionCtx, PathExprCtx, Qualified}, | |
| 13 | 13 | }; |
| 14 | 14 | |
| 15 | 15 | struct PathCallback<'a, F> { |
| ... | ... | @@ -57,7 +57,6 @@ pub(crate) fn complete_expr_path( |
| 57 | 57 | |
| 58 | 58 | let &PathExprCtx { |
| 59 | 59 | in_block_expr, |
| 60 | in_breakable, | |
| 61 | 60 | after_if_expr, |
| 62 | 61 | before_else_kw, |
| 63 | 62 | in_condition, |
| ... | ... | @@ -68,6 +67,7 @@ pub(crate) fn complete_expr_path( |
| 68 | 67 | after_amp, |
| 69 | 68 | ref is_func_update, |
| 70 | 69 | ref innermost_ret_ty, |
| 70 | ref innermost_breakable_ty, | |
| 71 | 71 | ref impl_, |
| 72 | 72 | in_match_guard, |
| 73 | 73 | .. |
| ... | ... | @@ -297,7 +297,7 @@ pub(crate) fn complete_expr_path( |
| 297 | 297 | acc, |
| 298 | 298 | ctx, |
| 299 | 299 | e, |
| 300 | impl_, | |
| 300 | impl_.as_ref(), | |
| 301 | 301 | |acc, ctx, variant, path| { |
| 302 | 302 | acc.add_qualified_enum_variant(ctx, path_ctx, variant, path) |
| 303 | 303 | }, |
| ... | ... | @@ -405,14 +405,21 @@ pub(crate) fn complete_expr_path( |
| 405 | 405 | add_keyword("mut", "mut "); |
| 406 | 406 | } |
| 407 | 407 | |
| 408 | if in_breakable != BreakableKind::None { | |
| 408 | if let Some(loop_ty) = innermost_breakable_ty { | |
| 409 | 409 | if in_block_expr { |
| 410 | 410 | add_keyword("continue", "continue;"); |
| 411 | add_keyword("break", "break;"); | |
| 412 | 411 | } else { |
| 413 | 412 | add_keyword("continue", "continue"); |
| 414 | add_keyword("break", "break"); | |
| 415 | 413 | } |
| 414 | add_keyword( | |
| 415 | "break", | |
| 416 | match (loop_ty.is_unit(), in_block_expr) { | |
| 417 | (true, true) => "break;", | |
| 418 | (true, false) => "break", | |
| 419 | (false, true) => "break $0;", | |
| 420 | (false, false) => "break $0", | |
| 421 | }, | |
| 422 | ); | |
| 416 | 423 | } |
| 417 | 424 | |
| 418 | 425 | if let Some(ret_ty) = innermost_ret_ty { |
src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs+8-7| ... | ... | @@ -2,6 +2,7 @@ |
| 2 | 2 | |
| 3 | 3 | use hir::HirDisplay; |
| 4 | 4 | use ide_db::FxHashMap; |
| 5 | use itertools::Either; | |
| 5 | 6 | use syntax::{ |
| 6 | 7 | AstNode, Direction, SyntaxKind, TextRange, TextSize, algo, |
| 7 | 8 | ast::{self, HasModuleItem}, |
| ... | ... | @@ -24,8 +25,8 @@ pub(crate) fn complete_fn_param( |
| 24 | 25 | ctx: &CompletionContext<'_>, |
| 25 | 26 | pattern_ctx: &PatternContext, |
| 26 | 27 | ) -> Option<()> { |
| 27 | let (ParamContext { param_list, kind, .. }, impl_) = match pattern_ctx { | |
| 28 | PatternContext { param_ctx: Some(kind), impl_, .. } => (kind, impl_), | |
| 28 | let (ParamContext { param_list, kind, .. }, impl_or_trait) = match pattern_ctx { | |
| 29 | PatternContext { param_ctx: Some(kind), impl_or_trait, .. } => (kind, impl_or_trait), | |
| 29 | 30 | _ => return None, |
| 30 | 31 | }; |
| 31 | 32 | |
| ... | ... | @@ -45,7 +46,7 @@ pub(crate) fn complete_fn_param( |
| 45 | 46 | |
| 46 | 47 | match kind { |
| 47 | 48 | ParamKind::Function(function) => { |
| 48 | fill_fn_params(ctx, function, param_list, impl_, add_new_item_to_acc); | |
| 49 | fill_fn_params(ctx, function, param_list, impl_or_trait, add_new_item_to_acc); | |
| 49 | 50 | } |
| 50 | 51 | ParamKind::Closure(closure) => { |
| 51 | 52 | let stmt_list = closure.syntax().ancestors().find_map(ast::StmtList::cast)?; |
| ... | ... | @@ -62,7 +63,7 @@ fn fill_fn_params( |
| 62 | 63 | ctx: &CompletionContext<'_>, |
| 63 | 64 | function: &ast::Fn, |
| 64 | 65 | param_list: &ast::ParamList, |
| 65 | impl_: &Option<ast::Impl>, | |
| 66 | impl_or_trait: &Option<Either<ast::Impl, ast::Trait>>, | |
| 66 | 67 | mut add_new_item_to_acc: impl FnMut(&str), |
| 67 | 68 | ) { |
| 68 | 69 | let mut file_params = FxHashMap::default(); |
| ... | ... | @@ -107,7 +108,7 @@ fn fill_fn_params( |
| 107 | 108 | } |
| 108 | 109 | remove_duplicated(&mut file_params, param_list.params()); |
| 109 | 110 | let self_completion_items = ["self", "&self", "mut self", "&mut self"]; |
| 110 | if should_add_self_completions(ctx.token.text_range().start(), param_list, impl_) { | |
| 111 | if should_add_self_completions(ctx.token.text_range().start(), param_list, impl_or_trait) { | |
| 111 | 112 | self_completion_items.into_iter().for_each(&mut add_new_item_to_acc); |
| 112 | 113 | } |
| 113 | 114 | |
| ... | ... | @@ -161,9 +162,9 @@ fn remove_duplicated( |
| 161 | 162 | fn should_add_self_completions( |
| 162 | 163 | cursor: TextSize, |
| 163 | 164 | param_list: &ast::ParamList, |
| 164 | impl_: &Option<ast::Impl>, | |
| 165 | impl_or_trait: &Option<Either<ast::Impl, ast::Trait>>, | |
| 165 | 166 | ) -> bool { |
| 166 | if impl_.is_none() || param_list.self_param().is_some() { | |
| 167 | if impl_or_trait.is_none() || param_list.self_param().is_some() { | |
| 167 | 168 | return false; |
| 168 | 169 | } |
| 169 | 170 | match param_list.params().next() { |
src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs+1-1| ... | ... | @@ -70,7 +70,7 @@ pub(crate) fn complete_pattern( |
| 70 | 70 | acc, |
| 71 | 71 | ctx, |
| 72 | 72 | e, |
| 73 | &pattern_ctx.impl_, | |
| 73 | pattern_ctx.impl_or_trait.as_ref().and_then(|it| it.as_ref().left()), | |
| 74 | 74 | |acc, ctx, variant, path| { |
| 75 | 75 | acc.add_qualified_variant_pat(ctx, pattern_ctx, variant, path); |
| 76 | 76 | }, |
src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs+54-10| ... | ... | @@ -11,12 +11,12 @@ use ide_db::{ |
| 11 | 11 | text_edit::TextEdit, |
| 12 | 12 | ty_filter::TryEnum, |
| 13 | 13 | }; |
| 14 | use itertools::Either; | |
| 15 | 14 | use stdx::never; |
| 16 | 15 | use syntax::{ |
| 17 | 16 | SyntaxKind::{BLOCK_EXPR, EXPR_STMT, FOR_EXPR, IF_EXPR, LOOP_EXPR, STMT_LIST, WHILE_EXPR}, |
| 18 | TextRange, TextSize, | |
| 17 | T, TextRange, TextSize, | |
| 19 | 18 | ast::{self, AstNode, AstToken}, |
| 19 | match_ast, | |
| 20 | 20 | }; |
| 21 | 21 | |
| 22 | 22 | use crate::{ |
| ... | ... | @@ -113,12 +113,8 @@ pub(crate) fn complete_postfix( |
| 113 | 113 | if let Some(parent) = dot_receiver_including_refs.syntax().parent() |
| 114 | 114 | && let Some(second_ancestor) = parent.parent() |
| 115 | 115 | { |
| 116 | let sec_ancestor_kind = second_ancestor.kind(); | |
| 117 | if let Some(expr) = <Either<ast::IfExpr, ast::WhileExpr>>::cast(second_ancestor) { | |
| 118 | is_in_cond = match expr { | |
| 119 | Either::Left(it) => it.condition().is_some_and(|cond| *cond.syntax() == parent), | |
| 120 | Either::Right(it) => it.condition().is_some_and(|cond| *cond.syntax() == parent), | |
| 121 | } | |
| 116 | if let Some(parent_expr) = ast::Expr::cast(parent) { | |
| 117 | is_in_cond = is_in_condition(&parent_expr); | |
| 122 | 118 | } |
| 123 | 119 | match &try_enum { |
| 124 | 120 | Some(try_enum) if is_in_cond => match try_enum { |
| ... | ... | @@ -147,7 +143,7 @@ pub(crate) fn complete_postfix( |
| 147 | 143 | .add_to(acc, ctx.db); |
| 148 | 144 | } |
| 149 | 145 | }, |
| 150 | _ if matches!(sec_ancestor_kind, STMT_LIST | EXPR_STMT) => { | |
| 146 | _ if matches!(second_ancestor.kind(), STMT_LIST | EXPR_STMT) => { | |
| 151 | 147 | postfix_snippet("let", "let", &format!("let $0 = {receiver_text};")) |
| 152 | 148 | .add_to(acc, ctx.db); |
| 153 | 149 | postfix_snippet("letm", "let mut", &format!("let mut $0 = {receiver_text};")) |
| ... | ... | @@ -295,7 +291,7 @@ pub(crate) fn complete_postfix( |
| 295 | 291 | ) |
| 296 | 292 | .add_to(acc, ctx.db); |
| 297 | 293 | |
| 298 | if let BreakableKind::Block | BreakableKind::Loop = expr_ctx.in_breakable { | |
| 294 | if let Some(BreakableKind::Block | BreakableKind::Loop) = expr_ctx.in_breakable { | |
| 299 | 295 | postfix_snippet( |
| 300 | 296 | "break", |
| 301 | 297 | "break expr", |
| ... | ... | @@ -454,6 +450,22 @@ fn add_custom_postfix_completions( |
| 454 | 450 | None |
| 455 | 451 | } |
| 456 | 452 | |
| 453 | pub(crate) fn is_in_condition(it: &ast::Expr) -> bool { | |
| 454 | it.syntax() | |
| 455 | .parent() | |
| 456 | .and_then(|parent| { | |
| 457 | Some(match_ast! { match parent { | |
| 458 | ast::IfExpr(expr) => expr.condition()? == *it, | |
| 459 | ast::WhileExpr(expr) => expr.condition()? == *it, | |
| 460 | ast::MatchGuard(guard) => guard.condition()? == *it, | |
| 461 | ast::BinExpr(bin_expr) => (bin_expr.op_token()?.kind() == T![&&]) | |
| 462 | .then(|| is_in_condition(&bin_expr.into()))?, | |
| 463 | _ => return None, | |
| 464 | } }) | |
| 465 | }) | |
| 466 | .unwrap_or(false) | |
| 467 | } | |
| 468 | ||
| 457 | 469 | #[cfg(test)] |
| 458 | 470 | mod tests { |
| 459 | 471 | use expect_test::expect; |
| ... | ... | @@ -648,6 +660,38 @@ fn main() { |
| 648 | 660 | let bar = Some(true); |
| 649 | 661 | if let Some($0) = bar |
| 650 | 662 | } |
| 663 | "#, | |
| 664 | ); | |
| 665 | check_edit( | |
| 666 | "let", | |
| 667 | r#" | |
| 668 | //- minicore: option | |
| 669 | fn main() { | |
| 670 | let bar = Some(true); | |
| 671 | if true && bar.$0 | |
| 672 | } | |
| 673 | "#, | |
| 674 | r#" | |
| 675 | fn main() { | |
| 676 | let bar = Some(true); | |
| 677 | if true && let Some($0) = bar | |
| 678 | } | |
| 679 | "#, | |
| 680 | ); | |
| 681 | check_edit( | |
| 682 | "let", | |
| 683 | r#" | |
| 684 | //- minicore: option | |
| 685 | fn main() { | |
| 686 | let bar = Some(true); | |
| 687 | if true && true && bar.$0 | |
| 688 | } | |
| 689 | "#, | |
| 690 | r#" | |
| 691 | fn main() { | |
| 692 | let bar = Some(true); | |
| 693 | if true && true && let Some($0) = bar | |
| 694 | } | |
| 651 | 695 | "#, |
| 652 | 696 | ); |
| 653 | 697 | } |
src/tools/rust-analyzer/crates/ide-completion/src/completions/record.rs+1-4| ... | ... | @@ -135,10 +135,7 @@ fn complete_fields( |
| 135 | 135 | receiver: None, |
| 136 | 136 | receiver_ty: None, |
| 137 | 137 | kind: DotAccessKind::Field { receiver_is_ambiguous_float_literal: false }, |
| 138 | ctx: DotAccessExprCtx { | |
| 139 | in_block_expr: false, | |
| 140 | in_breakable: crate::context::BreakableKind::None, | |
| 141 | }, | |
| 138 | ctx: DotAccessExprCtx { in_block_expr: false, in_breakable: None }, | |
| 142 | 139 | }, |
| 143 | 140 | None, |
| 144 | 141 | field, |
src/tools/rust-analyzer/crates/ide-completion/src/context.rs+5-4| ... | ... | @@ -15,6 +15,7 @@ use ide_db::{ |
| 15 | 15 | FilePosition, FxHashMap, FxHashSet, RootDatabase, famous_defs::FamousDefs, |
| 16 | 16 | helpers::is_editable_crate, |
| 17 | 17 | }; |
| 18 | use itertools::Either; | |
| 18 | 19 | use syntax::{ |
| 19 | 20 | AstNode, Edition, SmolStr, |
| 20 | 21 | SyntaxKind::{self, *}, |
| ... | ... | @@ -142,7 +143,7 @@ pub(crate) struct AttrCtx { |
| 142 | 143 | #[derive(Debug, PartialEq, Eq)] |
| 143 | 144 | pub(crate) struct PathExprCtx<'db> { |
| 144 | 145 | pub(crate) in_block_expr: bool, |
| 145 | pub(crate) in_breakable: BreakableKind, | |
| 146 | pub(crate) in_breakable: Option<BreakableKind>, | |
| 146 | 147 | pub(crate) after_if_expr: bool, |
| 147 | 148 | pub(crate) before_else_kw: bool, |
| 148 | 149 | /// Whether this expression is the direct condition of an if or while expression |
| ... | ... | @@ -156,6 +157,7 @@ pub(crate) struct PathExprCtx<'db> { |
| 156 | 157 | pub(crate) is_func_update: Option<ast::RecordExpr>, |
| 157 | 158 | pub(crate) self_param: Option<hir::SelfParam>, |
| 158 | 159 | pub(crate) innermost_ret_ty: Option<hir::Type<'db>>, |
| 160 | pub(crate) innermost_breakable_ty: Option<hir::Type<'db>>, | |
| 159 | 161 | pub(crate) impl_: Option<ast::Impl>, |
| 160 | 162 | /// Whether this expression occurs in match arm guard position: before the |
| 161 | 163 | /// fat arrow token |
| ... | ... | @@ -282,7 +284,7 @@ pub(crate) struct PatternContext { |
| 282 | 284 | pub(crate) mut_token: Option<SyntaxToken>, |
| 283 | 285 | /// The record pattern this name or ref is a field of |
| 284 | 286 | pub(crate) record_pat: Option<ast::RecordPat>, |
| 285 | pub(crate) impl_: Option<ast::Impl>, | |
| 287 | pub(crate) impl_or_trait: Option<Either<ast::Impl, ast::Trait>>, | |
| 286 | 288 | /// List of missing variants in a match expr |
| 287 | 289 | pub(crate) missing_variants: Vec<hir::Variant>, |
| 288 | 290 | } |
| ... | ... | @@ -411,12 +413,11 @@ pub(crate) enum DotAccessKind { |
| 411 | 413 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| 412 | 414 | pub(crate) struct DotAccessExprCtx { |
| 413 | 415 | pub(crate) in_block_expr: bool, |
| 414 | pub(crate) in_breakable: BreakableKind, | |
| 416 | pub(crate) in_breakable: Option<BreakableKind>, | |
| 415 | 417 | } |
| 416 | 418 | |
| 417 | 419 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
| 418 | 420 | pub(crate) enum BreakableKind { |
| 419 | None, | |
| 420 | 421 | Loop, |
| 421 | 422 | For, |
| 422 | 423 | While, |
src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs+47-47| ... | ... | @@ -1,7 +1,6 @@ |
| 1 | 1 | //! Module responsible for analyzing the code surrounding the cursor for completion. |
| 2 | 2 | use std::iter; |
| 3 | 3 | |
| 4 | use base_db::salsa; | |
| 5 | 4 | use hir::{ExpandResult, InFile, Semantics, Type, TypeInfo, Variant}; |
| 6 | 5 | use ide_db::{RootDatabase, active_parameter::ActiveParameter}; |
| 7 | 6 | use itertools::Either; |
| ... | ... | @@ -20,12 +19,15 @@ use syntax::{ |
| 20 | 19 | match_ast, |
| 21 | 20 | }; |
| 22 | 21 | |
| 23 | use crate::context::{ | |
| 24 | AttrCtx, BreakableKind, COMPLETION_MARKER, CompletionAnalysis, DotAccess, DotAccessExprCtx, | |
| 25 | DotAccessKind, ItemListKind, LifetimeContext, LifetimeKind, NameContext, NameKind, | |
| 26 | NameRefContext, NameRefKind, ParamContext, ParamKind, PathCompletionCtx, PathExprCtx, PathKind, | |
| 27 | PatternContext, PatternRefutability, Qualified, QualifierCtx, TypeAscriptionTarget, | |
| 28 | TypeLocation, | |
| 22 | use crate::{ | |
| 23 | completions::postfix::is_in_condition, | |
| 24 | context::{ | |
| 25 | AttrCtx, BreakableKind, COMPLETION_MARKER, CompletionAnalysis, DotAccess, DotAccessExprCtx, | |
| 26 | DotAccessKind, ItemListKind, LifetimeContext, LifetimeKind, NameContext, NameKind, | |
| 27 | NameRefContext, NameRefKind, ParamContext, ParamKind, PathCompletionCtx, PathExprCtx, | |
| 28 | PathKind, PatternContext, PatternRefutability, Qualified, QualifierCtx, | |
| 29 | TypeAscriptionTarget, TypeLocation, | |
| 30 | }, | |
| 29 | 31 | }; |
| 30 | 32 | |
| 31 | 33 | #[derive(Debug)] |
| ... | ... | @@ -86,7 +88,7 @@ pub(super) fn expand_and_analyze<'db>( |
| 86 | 88 | let original_offset = expansion.original_offset + relative_offset; |
| 87 | 89 | let token = expansion.original_file.token_at_offset(original_offset).left_biased()?; |
| 88 | 90 | |
| 89 | salsa::attach(sema.db, || analyze(sema, expansion, original_token, &token)).map( | |
| 91 | hir::attach_db(sema.db, || analyze(sema, expansion, original_token, &token)).map( | |
| 90 | 92 | |(analysis, expected, qualifier_ctx)| AnalysisResult { |
| 91 | 93 | analysis, |
| 92 | 94 | expected, |
| ... | ... | @@ -563,10 +565,10 @@ fn analyze<'db>( |
| 563 | 565 | /// Calculate the expected type and name of the cursor position. |
| 564 | 566 | fn expected_type_and_name<'db>( |
| 565 | 567 | sema: &Semantics<'db, RootDatabase>, |
| 566 | token: &SyntaxToken, | |
| 568 | self_token: &SyntaxToken, | |
| 567 | 569 | name_like: &ast::NameLike, |
| 568 | 570 | ) -> (Option<Type<'db>>, Option<NameOrNameRef>) { |
| 569 | let token = prev_special_biased_token_at_trivia(token.clone()); | |
| 571 | let token = prev_special_biased_token_at_trivia(self_token.clone()); | |
| 570 | 572 | let mut node = match token.parent() { |
| 571 | 573 | Some(it) => it, |
| 572 | 574 | None => return (None, None), |
| ... | ... | @@ -756,7 +758,15 @@ fn expected_type_and_name<'db>( |
| 756 | 758 | .map(|c| (Some(c.return_type()), None)) |
| 757 | 759 | .unwrap_or((None, None)) |
| 758 | 760 | }, |
| 759 | ast::ParamList(_) => (None, None), | |
| 761 | ast::ParamList(it) => { | |
| 762 | let closure = it.syntax().parent().and_then(ast::ClosureExpr::cast); | |
| 763 | let ty = closure | |
| 764 | .filter(|_| it.syntax().text_range().end() <= self_token.text_range().start()) | |
| 765 | .and_then(|it| sema.type_of_expr(&it.into())); | |
| 766 | ty.and_then(|ty| ty.original.as_callable(sema.db)) | |
| 767 | .map(|c| (Some(c.return_type()), None)) | |
| 768 | .unwrap_or((None, None)) | |
| 769 | }, | |
| 760 | 770 | ast::Stmt(_) => (None, None), |
| 761 | 771 | ast::Item(_) => (None, None), |
| 762 | 772 | _ => { |
| ... | ... | @@ -916,7 +926,7 @@ fn classify_name_ref<'db>( |
| 916 | 926 | receiver_ty, |
| 917 | 927 | kind: DotAccessKind::Field { receiver_is_ambiguous_float_literal }, |
| 918 | 928 | receiver, |
| 919 | ctx: DotAccessExprCtx { in_block_expr: is_in_block(field.syntax()), in_breakable: is_in_breakable(field.syntax()) } | |
| 929 | ctx: DotAccessExprCtx { in_block_expr: is_in_block(field.syntax()), in_breakable: is_in_breakable(field.syntax()).unzip().0 } | |
| 920 | 930 | }); |
| 921 | 931 | return Some(make_res(kind)); |
| 922 | 932 | }, |
| ... | ... | @@ -931,7 +941,7 @@ fn classify_name_ref<'db>( |
| 931 | 941 | receiver_ty: receiver.as_ref().and_then(|it| sema.type_of_expr(it)), |
| 932 | 942 | kind: DotAccessKind::Method { has_parens }, |
| 933 | 943 | receiver, |
| 934 | ctx: DotAccessExprCtx { in_block_expr: is_in_block(method.syntax()), in_breakable: is_in_breakable(method.syntax()) } | |
| 944 | ctx: DotAccessExprCtx { in_block_expr: is_in_block(method.syntax()), in_breakable: is_in_breakable(method.syntax()).unzip().0 } | |
| 935 | 945 | }); |
| 936 | 946 | return Some(make_res(kind)); |
| 937 | 947 | }, |
| ... | ... | @@ -1216,28 +1226,10 @@ fn classify_name_ref<'db>( |
| 1216 | 1226 | Some(res) |
| 1217 | 1227 | }; |
| 1218 | 1228 | |
| 1219 | fn is_in_condition(it: &ast::Expr) -> bool { | |
| 1220 | (|| { | |
| 1221 | let parent = it.syntax().parent()?; | |
| 1222 | if let Some(expr) = ast::WhileExpr::cast(parent.clone()) { | |
| 1223 | Some(expr.condition()? == *it) | |
| 1224 | } else if let Some(expr) = ast::IfExpr::cast(parent.clone()) { | |
| 1225 | Some(expr.condition()? == *it) | |
| 1226 | } else if let Some(expr) = ast::BinExpr::cast(parent) | |
| 1227 | && expr.op_token()?.kind() == T![&&] | |
| 1228 | { | |
| 1229 | Some(is_in_condition(&expr.into())) | |
| 1230 | } else { | |
| 1231 | None | |
| 1232 | } | |
| 1233 | })() | |
| 1234 | .unwrap_or(false) | |
| 1235 | } | |
| 1236 | ||
| 1237 | 1229 | let make_path_kind_expr = |expr: ast::Expr| { |
| 1238 | 1230 | let it = expr.syntax(); |
| 1239 | 1231 | let in_block_expr = is_in_block(it); |
| 1240 | let in_loop_body = is_in_breakable(it); | |
| 1232 | let (in_loop_body, innermost_breakable) = is_in_breakable(it).unzip(); | |
| 1241 | 1233 | let after_if_expr = after_if_expr(it.clone()); |
| 1242 | 1234 | let ref_expr_parent = |
| 1243 | 1235 | path.as_single_name_ref().and_then(|_| it.parent()).and_then(ast::RefExpr::cast); |
| ... | ... | @@ -1291,6 +1283,11 @@ fn classify_name_ref<'db>( |
| 1291 | 1283 | None => (None, None), |
| 1292 | 1284 | } |
| 1293 | 1285 | }; |
| 1286 | let innermost_breakable_ty = innermost_breakable | |
| 1287 | .and_then(ast::Expr::cast) | |
| 1288 | .and_then(|expr| find_node_in_file_compensated(sema, original_file, &expr)) | |
| 1289 | .and_then(|expr| sema.type_of_expr(&expr)) | |
| 1290 | .map(|ty| if ty.original.is_never() { ty.adjusted() } else { ty.original() }); | |
| 1294 | 1291 | let is_func_update = func_update_record(it); |
| 1295 | 1292 | let in_condition = is_in_condition(&expr); |
| 1296 | 1293 | let after_incomplete_let = after_incomplete_let(it.clone()).is_some(); |
| ... | ... | @@ -1303,7 +1300,8 @@ fn classify_name_ref<'db>( |
| 1303 | 1300 | .is_some_and(|it| it.semicolon_token().is_none()) |
| 1304 | 1301 | || after_incomplete_let && incomplete_expr_stmt.unwrap_or(true) && !before_else_kw; |
| 1305 | 1302 | let in_value = it.parent().and_then(Either::<ast::LetStmt, ast::ArgList>::cast).is_some(); |
| 1306 | let impl_ = fetch_immediate_impl(sema, original_file, expr.syntax()); | |
| 1303 | let impl_ = fetch_immediate_impl_or_trait(sema, original_file, expr.syntax()) | |
| 1304 | .and_then(Either::left); | |
| 1307 | 1305 | |
| 1308 | 1306 | let in_match_guard = match it.parent().and_then(ast::MatchArm::cast) { |
| 1309 | 1307 | Some(arm) => arm |
| ... | ... | @@ -1323,6 +1321,7 @@ fn classify_name_ref<'db>( |
| 1323 | 1321 | after_amp, |
| 1324 | 1322 | is_func_update, |
| 1325 | 1323 | innermost_ret_ty, |
| 1324 | innermost_breakable_ty, | |
| 1326 | 1325 | self_param, |
| 1327 | 1326 | in_value, |
| 1328 | 1327 | incomplete_let, |
| ... | ... | @@ -1756,27 +1755,29 @@ fn pattern_context_for( |
| 1756 | 1755 | mut_token, |
| 1757 | 1756 | ref_token, |
| 1758 | 1757 | record_pat: None, |
| 1759 | impl_: fetch_immediate_impl(sema, original_file, pat.syntax()), | |
| 1758 | impl_or_trait: fetch_immediate_impl_or_trait(sema, original_file, pat.syntax()), | |
| 1760 | 1759 | missing_variants, |
| 1761 | 1760 | } |
| 1762 | 1761 | } |
| 1763 | 1762 | |
| 1764 | fn fetch_immediate_impl( | |
| 1763 | fn fetch_immediate_impl_or_trait( | |
| 1765 | 1764 | sema: &Semantics<'_, RootDatabase>, |
| 1766 | 1765 | original_file: &SyntaxNode, |
| 1767 | 1766 | node: &SyntaxNode, |
| 1768 | ) -> Option<ast::Impl> { | |
| 1767 | ) -> Option<Either<ast::Impl, ast::Trait>> { | |
| 1769 | 1768 | let mut ancestors = ancestors_in_file_compensated(sema, original_file, node)? |
| 1770 | 1769 | .filter_map(ast::Item::cast) |
| 1771 | 1770 | .filter(|it| !matches!(it, ast::Item::MacroCall(_))); |
| 1772 | 1771 | |
| 1773 | 1772 | match ancestors.next()? { |
| 1774 | 1773 | ast::Item::Const(_) | ast::Item::Fn(_) | ast::Item::TypeAlias(_) => (), |
| 1775 | ast::Item::Impl(it) => return Some(it), | |
| 1774 | ast::Item::Impl(it) => return Some(Either::Left(it)), | |
| 1775 | ast::Item::Trait(it) => return Some(Either::Right(it)), | |
| 1776 | 1776 | _ => return None, |
| 1777 | 1777 | } |
| 1778 | 1778 | match ancestors.next()? { |
| 1779 | ast::Item::Impl(it) => Some(it), | |
| 1779 | ast::Item::Impl(it) => Some(Either::Left(it)), | |
| 1780 | ast::Item::Trait(it) => Some(Either::Right(it)), | |
| 1780 | 1781 | _ => None, |
| 1781 | 1782 | } |
| 1782 | 1783 | } |
| ... | ... | @@ -1870,24 +1871,22 @@ fn is_in_token_of_for_loop(path: &ast::Path) -> bool { |
| 1870 | 1871 | .unwrap_or(false) |
| 1871 | 1872 | } |
| 1872 | 1873 | |
| 1873 | fn is_in_breakable(node: &SyntaxNode) -> BreakableKind { | |
| 1874 | fn is_in_breakable(node: &SyntaxNode) -> Option<(BreakableKind, SyntaxNode)> { | |
| 1874 | 1875 | node.ancestors() |
| 1875 | 1876 | .take_while(|it| it.kind() != SyntaxKind::FN && it.kind() != SyntaxKind::CLOSURE_EXPR) |
| 1876 | 1877 | .find_map(|it| { |
| 1877 | 1878 | let (breakable, loop_body) = match_ast! { |
| 1878 | 1879 | match it { |
| 1879 | ast::ForExpr(it) => (BreakableKind::For, it.loop_body()), | |
| 1880 | ast::WhileExpr(it) => (BreakableKind::While, it.loop_body()), | |
| 1881 | ast::LoopExpr(it) => (BreakableKind::Loop, it.loop_body()), | |
| 1882 | ast::BlockExpr(it) => return it.label().map(|_| BreakableKind::Block), | |
| 1880 | ast::ForExpr(it) => (BreakableKind::For, it.loop_body()?), | |
| 1881 | ast::WhileExpr(it) => (BreakableKind::While, it.loop_body()?), | |
| 1882 | ast::LoopExpr(it) => (BreakableKind::Loop, it.loop_body()?), | |
| 1883 | ast::BlockExpr(it) => return it.label().map(|_| (BreakableKind::Block, it.syntax().clone())), | |
| 1883 | 1884 | _ => return None, |
| 1884 | 1885 | } |
| 1885 | 1886 | }; |
| 1886 | loop_body | |
| 1887 | .filter(|it| it.syntax().text_range().contains_range(node.text_range())) | |
| 1888 | .map(|_| breakable) | |
| 1887 | loop_body.syntax().text_range().contains_range(node.text_range()) | |
| 1888 | .then_some((breakable, it)) | |
| 1889 | 1889 | }) |
| 1890 | .unwrap_or(BreakableKind::None) | |
| 1891 | 1890 | } |
| 1892 | 1891 | |
| 1893 | 1892 | fn is_in_block(node: &SyntaxNode) -> bool { |
| ... | ... | @@ -1938,6 +1937,7 @@ fn prev_special_biased_token_at_trivia(mut token: SyntaxToken) -> SyntaxToken { |
| 1938 | 1937 | | T![|=] |
| 1939 | 1938 | | T![&=] |
| 1940 | 1939 | | T![^=] |
| 1940 | | T![|] | |
| 1941 | 1941 | | T![return] |
| 1942 | 1942 | | T![break] |
| 1943 | 1943 | | T![continue] = prev.kind() |
src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs+14-4| ... | ... | @@ -1,4 +1,3 @@ |
| 1 | use base_db::salsa; | |
| 2 | 1 | use expect_test::{Expect, expect}; |
| 3 | 2 | use hir::HirDisplay; |
| 4 | 3 | |
| ... | ... | @@ -11,12 +10,12 @@ fn check_expected_type_and_name(#[rust_analyzer::rust_fixture] ra_fixture: &str, |
| 11 | 10 | let (db, pos) = position(ra_fixture); |
| 12 | 11 | let config = TEST_CONFIG; |
| 13 | 12 | let (completion_context, _analysis) = |
| 14 | salsa::attach(&db, || CompletionContext::new(&db, pos, &config).unwrap()); | |
| 13 | hir::attach_db(&db, || CompletionContext::new(&db, pos, &config).unwrap()); | |
| 15 | 14 | |
| 16 | 15 | let ty = completion_context |
| 17 | 16 | .expected_type |
| 18 | 17 | .map(|t| { |
| 19 | salsa::attach(&db, || { | |
| 18 | hir::attach_db(&db, || { | |
| 20 | 19 | t.display_test(&db, completion_context.krate.to_display_target(&db)).to_string() |
| 21 | 20 | }) |
| 22 | 21 | }) |
| ... | ... | @@ -374,7 +373,6 @@ fn foo() -> u32 { |
| 374 | 373 | |
| 375 | 374 | #[test] |
| 376 | 375 | fn expected_type_closure_param_return() { |
| 377 | // FIXME: make this work with `|| $0` | |
| 378 | 376 | check_expected_type_and_name( |
| 379 | 377 | r#" |
| 380 | 378 | //- minicore: fn |
| ... | ... | @@ -382,6 +380,18 @@ fn foo() { |
| 382 | 380 | bar(|| a$0); |
| 383 | 381 | } |
| 384 | 382 | |
| 383 | fn bar(f: impl FnOnce() -> u32) {} | |
| 384 | "#, | |
| 385 | expect![[r#"ty: u32, name: ?"#]], | |
| 386 | ); | |
| 387 | ||
| 388 | check_expected_type_and_name( | |
| 389 | r#" | |
| 390 | //- minicore: fn | |
| 391 | fn foo() { | |
| 392 | bar(|| $0); | |
| 393 | } | |
| 394 | ||
| 385 | 395 | fn bar(f: impl FnOnce() -> u32) {} |
| 386 | 396 | "#, |
| 387 | 397 | expect![[r#"ty: u32, name: ?"#]], |
src/tools/rust-analyzer/crates/ide-completion/src/render.rs+1-1| ... | ... | @@ -2987,7 +2987,6 @@ fn main() { |
| 2987 | 2987 | &[CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(SymbolKind::Method)], |
| 2988 | 2988 | expect![[r#" |
| 2989 | 2989 | sn not !expr [snippet] |
| 2990 | me not() fn(self) -> <Self as Not>::Output [type_could_unify+requires_import] | |
| 2991 | 2990 | sn box Box::new(expr) [] |
| 2992 | 2991 | sn call function(expr) [] |
| 2993 | 2992 | sn const const {} [] |
| ... | ... | @@ -3001,6 +3000,7 @@ fn main() { |
| 3001 | 3000 | sn return return expr [] |
| 3002 | 3001 | sn unsafe unsafe {} [] |
| 3003 | 3002 | sn while while expr {} [] |
| 3003 | me not() fn(self) -> <Self as Not>::Output [requires_import] | |
| 3004 | 3004 | "#]], |
| 3005 | 3005 | ); |
| 3006 | 3006 | } |
src/tools/rust-analyzer/crates/ide-completion/src/tests.rs+3-3| ... | ... | @@ -24,7 +24,7 @@ mod type_pos; |
| 24 | 24 | mod use_tree; |
| 25 | 25 | mod visibility; |
| 26 | 26 | |
| 27 | use base_db::{SourceDatabase, salsa}; | |
| 27 | use base_db::SourceDatabase; | |
| 28 | 28 | use expect_test::Expect; |
| 29 | 29 | use hir::db::HirDatabase; |
| 30 | 30 | use hir::{PrefixKind, setup_tracing}; |
| ... | ... | @@ -244,7 +244,7 @@ pub(crate) fn check_edit_with_config( |
| 244 | 244 | let ra_fixture_after = trim_indent(ra_fixture_after); |
| 245 | 245 | let (db, position) = position(ra_fixture_before); |
| 246 | 246 | let completions: Vec<CompletionItem> = |
| 247 | salsa::attach(&db, || crate::completions(&db, &config, position, None).unwrap()); | |
| 247 | hir::attach_db(&db, || crate::completions(&db, &config, position, None).unwrap()); | |
| 248 | 248 | let (completion,) = completions |
| 249 | 249 | .iter() |
| 250 | 250 | .filter(|it| it.lookup() == what) |
| ... | ... | @@ -307,7 +307,7 @@ pub(crate) fn get_all_items( |
| 307 | 307 | trigger_character: Option<char>, |
| 308 | 308 | ) -> Vec<CompletionItem> { |
| 309 | 309 | let (db, position) = position(code); |
| 310 | let res = salsa::attach(&db, || { | |
| 310 | let res = hir::attach_db(&db, || { | |
| 311 | 311 | HirDatabase::zalsa_register_downcaster(&db); |
| 312 | 312 | crate::completions(&db, &config, position, trigger_character) |
| 313 | 313 | }) |
src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs+39| ... | ... | @@ -1090,6 +1090,45 @@ fn return_value_no_block() { |
| 1090 | 1090 | ); |
| 1091 | 1091 | } |
| 1092 | 1092 | |
| 1093 | #[test] | |
| 1094 | fn break_unit_block() { | |
| 1095 | check_edit("break", r#"fn f() { loop { break; $0 } }"#, r#"fn f() { loop { break; break; } }"#); | |
| 1096 | check_edit("break", r#"fn f() { loop { $0 } }"#, r#"fn f() { loop { break; } }"#); | |
| 1097 | } | |
| 1098 | ||
| 1099 | #[test] | |
| 1100 | fn break_unit_no_block() { | |
| 1101 | check_edit( | |
| 1102 | "break", | |
| 1103 | r#"fn f() { loop { break; match () { () => $0 } } }"#, | |
| 1104 | r#"fn f() { loop { break; match () { () => break } } }"#, | |
| 1105 | ); | |
| 1106 | ||
| 1107 | check_edit( | |
| 1108 | "break", | |
| 1109 | r#"fn f() { loop { match () { () => $0 } } }"#, | |
| 1110 | r#"fn f() { loop { match () { () => break } } }"#, | |
| 1111 | ); | |
| 1112 | } | |
| 1113 | ||
| 1114 | #[test] | |
| 1115 | fn break_value_block() { | |
| 1116 | check_edit( | |
| 1117 | "break", | |
| 1118 | r#"fn f() -> i32 { loop { $0 } }"#, | |
| 1119 | r#"fn f() -> i32 { loop { break $0; } }"#, | |
| 1120 | ); | |
| 1121 | } | |
| 1122 | ||
| 1123 | #[test] | |
| 1124 | fn break_value_no_block() { | |
| 1125 | check_edit( | |
| 1126 | "break", | |
| 1127 | r#"fn f() -> i32 { loop { match () { () => $0 } } }"#, | |
| 1128 | r#"fn f() -> i32 { loop { match () { () => break $0 } } }"#, | |
| 1129 | ); | |
| 1130 | } | |
| 1131 | ||
| 1093 | 1132 | #[test] |
| 1094 | 1133 | fn else_completion_after_if() { |
| 1095 | 1134 | check( |
src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs+1-2| ... | ... | @@ -1,4 +1,3 @@ |
| 1 | use base_db::salsa; | |
| 2 | 1 | use expect_test::{Expect, expect}; |
| 3 | 2 | |
| 4 | 3 | use crate::{ |
| ... | ... | @@ -20,7 +19,7 @@ fn check_with_config( |
| 20 | 19 | let (ctx, analysis) = crate::context::CompletionContext::new(&db, position, &config).unwrap(); |
| 21 | 20 | |
| 22 | 21 | let mut acc = crate::completions::Completions::default(); |
| 23 | salsa::attach(ctx.db, || { | |
| 22 | hir::attach_db(ctx.db, || { | |
| 24 | 23 | if let CompletionAnalysis::Name(NameContext { kind: NameKind::IdentPat(pat_ctx), .. }) = |
| 25 | 24 | &analysis |
| 26 | 25 | { |
src/tools/rust-analyzer/crates/ide-completion/src/tests/fn_param.rs+42| ... | ... | @@ -85,7 +85,11 @@ pub(crate) trait SourceRoot { |
| 85 | 85 | } |
| 86 | 86 | "#, |
| 87 | 87 | expect![[r#" |
| 88 | bn &mut self | |
| 89 | bn &self | |
| 88 | 90 | bn file_id: usize |
| 91 | bn mut self | |
| 92 | bn self | |
| 89 | 93 | kw mut |
| 90 | 94 | kw ref |
| 91 | 95 | "#]], |
| ... | ... | @@ -183,6 +187,44 @@ impl A { |
| 183 | 187 | ) |
| 184 | 188 | } |
| 185 | 189 | |
| 190 | #[test] | |
| 191 | fn in_trait_only_param() { | |
| 192 | check( | |
| 193 | r#" | |
| 194 | trait A { | |
| 195 | fn foo(file_id: usize) {} | |
| 196 | fn new($0) {} | |
| 197 | } | |
| 198 | "#, | |
| 199 | expect![[r#" | |
| 200 | bn &mut self | |
| 201 | bn &self | |
| 202 | bn file_id: usize | |
| 203 | bn mut self | |
| 204 | bn self | |
| 205 | kw mut | |
| 206 | kw ref | |
| 207 | "#]], | |
| 208 | ) | |
| 209 | } | |
| 210 | ||
| 211 | #[test] | |
| 212 | fn in_trait_after_self() { | |
| 213 | check( | |
| 214 | r#" | |
| 215 | trait A { | |
| 216 | fn foo(file_id: usize) {} | |
| 217 | fn new(self, $0) {} | |
| 218 | } | |
| 219 | "#, | |
| 220 | expect![[r#" | |
| 221 | bn file_id: usize | |
| 222 | kw mut | |
| 223 | kw ref | |
| 224 | "#]], | |
| 225 | ) | |
| 226 | } | |
| 227 | ||
| 186 | 228 | // doesn't complete qux due to there being no expression after |
| 187 | 229 | // see source_analyzer::adjust comment |
| 188 | 230 | #[test] |
src/tools/rust-analyzer/crates/ide-db/src/assists.rs+2-6| ... | ... | @@ -170,14 +170,10 @@ impl AssistResolveStrategy { |
| 170 | 170 | #[derive(Clone, Debug)] |
| 171 | 171 | pub struct GroupLabel(pub String); |
| 172 | 172 | |
| 173 | #[derive(Clone, Debug, PartialEq, Eq)] | |
| 173 | #[derive(Clone, Debug, PartialEq, Eq, Default)] | |
| 174 | 174 | pub enum ExprFillDefaultMode { |
| 175 | #[default] | |
| 175 | 176 | Todo, |
| 176 | 177 | Default, |
| 177 | 178 | Underscore, |
| 178 | 179 | } |
| 179 | impl Default for ExprFillDefaultMode { | |
| 180 | fn default() -> Self { | |
| 181 | Self::Todo | |
| 182 | } | |
| 183 | } |
src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs+12-6| ... | ... | @@ -27,9 +27,6 @@ pub use hir::PrefixKind; |
| 27 | 27 | /// How imports should be grouped into use statements. |
| 28 | 28 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
| 29 | 29 | pub enum ImportGranularity { |
| 30 | /// Do not change the granularity of any imports and preserve the original structure written | |
| 31 | /// by the developer. | |
| 32 | Preserve, | |
| 33 | 30 | /// Merge imports from the same crate into a single use statement. |
| 34 | 31 | Crate, |
| 35 | 32 | /// Merge imports from the same module into a single use statement. |
| ... | ... | @@ -174,7 +171,7 @@ fn insert_use_with_alias_option( |
| 174 | 171 | ImportGranularity::Crate => Some(MergeBehavior::Crate), |
| 175 | 172 | ImportGranularity::Module => Some(MergeBehavior::Module), |
| 176 | 173 | ImportGranularity::One => Some(MergeBehavior::One), |
| 177 | ImportGranularity::Item | ImportGranularity::Preserve => None, | |
| 174 | ImportGranularity::Item => None, | |
| 178 | 175 | }; |
| 179 | 176 | if !cfg.enforce_granularity { |
| 180 | 177 | let file_granularity = guess_granularity_from_scope(scope); |
| ... | ... | @@ -182,9 +179,18 @@ fn insert_use_with_alias_option( |
| 182 | 179 | ImportGranularityGuess::Unknown => mb, |
| 183 | 180 | ImportGranularityGuess::Item => None, |
| 184 | 181 | ImportGranularityGuess::Module => Some(MergeBehavior::Module), |
| 185 | ImportGranularityGuess::ModuleOrItem => mb.and(Some(MergeBehavior::Module)), | |
| 182 | // We use the user's setting to infer if this is module or item. | |
| 183 | ImportGranularityGuess::ModuleOrItem => match mb { | |
| 184 | Some(MergeBehavior::Module) | None => mb, | |
| 185 | // There isn't really a way to decide between module or item here, so we just pick one. | |
| 186 | // FIXME: Maybe it is possible to infer based on semantic analysis? | |
| 187 | Some(MergeBehavior::One | MergeBehavior::Crate) => Some(MergeBehavior::Module), | |
| 188 | }, | |
| 186 | 189 | ImportGranularityGuess::Crate => Some(MergeBehavior::Crate), |
| 187 | ImportGranularityGuess::CrateOrModule => mb.or(Some(MergeBehavior::Crate)), | |
| 190 | ImportGranularityGuess::CrateOrModule => match mb { | |
| 191 | Some(MergeBehavior::Crate | MergeBehavior::Module) => mb, | |
| 192 | Some(MergeBehavior::One) | None => Some(MergeBehavior::Crate), | |
| 193 | }, | |
| 188 | 194 | ImportGranularityGuess::One => Some(MergeBehavior::One), |
| 189 | 195 | }; |
| 190 | 196 | } |
src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs+2-2| ... | ... | @@ -134,7 +134,7 @@ fn library_symbols(db: &dyn SymbolsDatabase, source_root_id: SourceRootId) -> Ar |
| 134 | 134 | let _p = tracing::info_span!("library_symbols").entered(); |
| 135 | 135 | |
| 136 | 136 | // We call this without attaching because this runs in parallel, so we need to attach here. |
| 137 | salsa::attach(db, || { | |
| 137 | hir::attach_db(db, || { | |
| 138 | 138 | let mut symbol_collector = SymbolCollector::new(db); |
| 139 | 139 | |
| 140 | 140 | db.source_root_crates(source_root_id) |
| ... | ... | @@ -153,7 +153,7 @@ fn module_symbols(db: &dyn SymbolsDatabase, module: Module) -> Arc<SymbolIndex> |
| 153 | 153 | let _p = tracing::info_span!("module_symbols").entered(); |
| 154 | 154 | |
| 155 | 155 | // We call this without attaching because this runs in parallel, so we need to attach here. |
| 156 | salsa::attach(db, || Arc::new(SymbolIndex::new(SymbolCollector::new_module(db, module)))) | |
| 156 | hir::attach_db(db, || Arc::new(SymbolIndex::new(SymbolCollector::new_module(db, module)))) | |
| 157 | 157 | } |
| 158 | 158 | |
| 159 | 159 | pub fn crate_symbols(db: &dyn SymbolsDatabase, krate: Crate) -> Box<[Arc<SymbolIndex>]> { |
src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs+1-1| ... | ... | @@ -473,7 +473,7 @@ mod tests { |
| 473 | 473 | frange.range, |
| 474 | 474 | "selection is not an expression(yet contained in one)" |
| 475 | 475 | ); |
| 476 | let name = salsa::attach(sema.db, || NameGenerator::default().for_variable(&expr, &sema)); | |
| 476 | let name = hir::attach_db(sema.db, || NameGenerator::default().for_variable(&expr, &sema)); | |
| 477 | 477 | assert_eq!(&name, expected); |
| 478 | 478 | } |
| 479 | 479 |
src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_generics_len.rs+17| ... | ... | @@ -203,6 +203,23 @@ impl WithSignals for Player { |
| 203 | 203 | fn __signals_from_external(&self) -> Self::SignalCollection<'_, Self> { |
| 204 | 204 | Self::SignalCollection { _v: self } |
| 205 | 205 | } |
| 206 | } | |
| 207 | "#, | |
| 208 | ); | |
| 209 | } | |
| 210 | ||
| 211 | #[test] | |
| 212 | fn enum_type_alias_default_param() { | |
| 213 | check_diagnostics( | |
| 214 | r#" | |
| 215 | //- minicore: result | |
| 216 | ||
| 217 | struct Error; | |
| 218 | ||
| 219 | type Result<T, E = Error> = core::result::Result<T, E>; | |
| 220 | ||
| 221 | fn main() { | |
| 222 | let _ = Result::<()>::Ok(()); | |
| 206 | 223 | } |
| 207 | 224 | "#, |
| 208 | 225 | ); |
src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs+38-1| ... | ... | @@ -50,7 +50,12 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingUnsafe) -> Option<Vec<Ass |
| 50 | 50 | |
| 51 | 51 | let node_to_add_unsafe_block = pick_best_node_to_add_unsafe_block(&expr)?; |
| 52 | 52 | |
| 53 | let replacement = format!("unsafe {{ {} }}", node_to_add_unsafe_block.text()); | |
| 53 | let mut replacement = format!("unsafe {{ {} }}", node_to_add_unsafe_block.text()); | |
| 54 | if let Some(expr) = ast::Expr::cast(node_to_add_unsafe_block.clone()) | |
| 55 | && needs_parentheses(&expr) | |
| 56 | { | |
| 57 | replacement = format!("({replacement})"); | |
| 58 | } | |
| 54 | 59 | let edit = TextEdit::replace(node_to_add_unsafe_block.text_range(), replacement); |
| 55 | 60 | let source_change = SourceChange::from_text_edit( |
| 56 | 61 | d.node.file_id.original_file(ctx.sema.db).file_id(ctx.sema.db), |
| ... | ... | @@ -112,6 +117,17 @@ fn pick_best_node_to_add_unsafe_block(unsafe_expr: &ast::Expr) -> Option<SyntaxN |
| 112 | 117 | None |
| 113 | 118 | } |
| 114 | 119 | |
| 120 | fn needs_parentheses(expr: &ast::Expr) -> bool { | |
| 121 | let node = expr.syntax(); | |
| 122 | node.ancestors() | |
| 123 | .skip(1) | |
| 124 | .take_while(|it| it.text_range().start() == node.text_range().start()) | |
| 125 | .map_while(ast::Expr::cast) | |
| 126 | .last() | |
| 127 | .and_then(|it| Some(it.syntax().parent()?.kind())) | |
| 128 | .is_some_and(|kind| ast::ExprStmt::can_cast(kind) || ast::StmtList::can_cast(kind)) | |
| 129 | } | |
| 130 | ||
| 115 | 131 | #[cfg(test)] |
| 116 | 132 | mod tests { |
| 117 | 133 | use crate::tests::{check_diagnostics, check_fix, check_no_fix}; |
| ... | ... | @@ -570,6 +586,27 @@ fn main() { |
| 570 | 586 | ) |
| 571 | 587 | } |
| 572 | 588 | |
| 589 | #[test] | |
| 590 | fn needs_parentheses_for_unambiguous() { | |
| 591 | check_fix( | |
| 592 | r#" | |
| 593 | //- minicore: copy | |
| 594 | static mut STATIC_MUT: u8 = 0; | |
| 595 | ||
| 596 | fn foo() -> u8 { | |
| 597 | STATIC_MUT$0 * 2 | |
| 598 | } | |
| 599 | "#, | |
| 600 | r#" | |
| 601 | static mut STATIC_MUT: u8 = 0; | |
| 602 | ||
| 603 | fn foo() -> u8 { | |
| 604 | (unsafe { STATIC_MUT }) * 2 | |
| 605 | } | |
| 606 | "#, | |
| 607 | ) | |
| 608 | } | |
| 609 | ||
| 573 | 610 | #[test] |
| 574 | 611 | fn ref_to_unsafe_expr() { |
| 575 | 612 | check_fix( |
src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mutability_errors.rs+16| ... | ... | @@ -1302,6 +1302,22 @@ fn main() { |
| 1302 | 1302 | 	let mut var = 1; |
| 1303 | 1303 | 	let mut func = || (var,) = (2,); |
| 1304 | 1304 | 	func(); |
| 1305 | } | |
| 1306 | "#, | |
| 1307 | ); | |
| 1308 | } | |
| 1309 | ||
| 1310 | #[test] | |
| 1311 | fn regression_20662() { | |
| 1312 | check_diagnostics( | |
| 1313 | r#" | |
| 1314 | //- minicore: index | |
| 1315 | pub trait A: core::ops::IndexMut<usize> { | |
| 1316 | type T: A; | |
| 1317 | } | |
| 1318 | ||
| 1319 | fn func(a: &mut impl A, b: &mut [i32]) { | |
| 1320 | b[0] += 1; | |
| 1305 | 1321 | } |
| 1306 | 1322 | "#, |
| 1307 | 1323 | ); |
src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_incorrect_safety.rs+9| ... | ... | @@ -127,4 +127,13 @@ struct S; |
| 127 | 127 | "#, |
| 128 | 128 | ); |
| 129 | 129 | } |
| 130 | ||
| 131 | #[test] | |
| 132 | fn unsafe_unresolved_trait() { | |
| 133 | check_diagnostics( | |
| 134 | r#" | |
| 135 | unsafe impl TestTrait for u32 {} | |
| 136 | "#, | |
| 137 | ); | |
| 138 | } | |
| 130 | 139 | } |
src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs+1-1| ... | ... | @@ -1170,7 +1170,7 @@ trait B {} |
| 1170 | 1170 | |
| 1171 | 1171 | fn test(a: &dyn A) -> &dyn B { |
| 1172 | 1172 | a |
| 1173 | //^ error: expected &dyn B, found &dyn A | |
| 1173 | //^ error: expected &(dyn B + 'static), found &(dyn A + 'static) | |
| 1174 | 1174 | } |
| 1175 | 1175 | "#, |
| 1176 | 1176 | ); |
src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs+1-1| ... | ... | @@ -253,7 +253,7 @@ impl DiagnosticsConfig { |
| 253 | 253 | style_lints: true, |
| 254 | 254 | snippet_cap: SnippetCap::new(true), |
| 255 | 255 | insert_use: InsertUseConfig { |
| 256 | granularity: ImportGranularity::Preserve, | |
| 256 | granularity: ImportGranularity::Item, | |
| 257 | 257 | enforce_granularity: false, |
| 258 | 258 | prefix_kind: PrefixKind::Plain, |
| 259 | 259 | group: false, |
src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs+7-7| ... | ... | @@ -6,7 +6,7 @@ use hir::setup_tracing; |
| 6 | 6 | use ide_db::{ |
| 7 | 7 | LineIndexDatabase, RootDatabase, |
| 8 | 8 | assists::{AssistResolveStrategy, ExprFillDefaultMode}, |
| 9 | base_db::{SourceDatabase, salsa}, | |
| 9 | base_db::SourceDatabase, | |
| 10 | 10 | }; |
| 11 | 11 | use itertools::Itertools; |
| 12 | 12 | use stdx::trim_indent; |
| ... | ... | @@ -74,7 +74,7 @@ fn check_nth_fix_with_config( |
| 74 | 74 | let after = trim_indent(ra_fixture_after); |
| 75 | 75 | |
| 76 | 76 | let (db, file_position) = RootDatabase::with_position(ra_fixture_before); |
| 77 | let diagnostic = salsa::attach(&db, || { | |
| 77 | let diagnostic = hir::attach_db(&db, || { | |
| 78 | 78 | super::full_diagnostics( |
| 79 | 79 | &db, |
| 80 | 80 | &config, |
| ... | ... | @@ -129,7 +129,7 @@ pub(crate) fn check_has_fix( |
| 129 | 129 | let (db, file_position) = RootDatabase::with_position(ra_fixture_before); |
| 130 | 130 | let mut conf = DiagnosticsConfig::test_sample(); |
| 131 | 131 | conf.expr_fill_default = ExprFillDefaultMode::Default; |
| 132 | let fix = salsa::attach(&db, || { | |
| 132 | let fix = hir::attach_db(&db, || { | |
| 133 | 133 | super::full_diagnostics( |
| 134 | 134 | &db, |
| 135 | 135 | &conf, |
| ... | ... | @@ -170,7 +170,7 @@ pub(crate) fn check_has_fix( |
| 170 | 170 | /// Checks that there's a diagnostic *without* fix at `$0`. |
| 171 | 171 | pub(crate) fn check_no_fix(#[rust_analyzer::rust_fixture] ra_fixture: &str) { |
| 172 | 172 | let (db, file_position) = RootDatabase::with_position(ra_fixture); |
| 173 | let diagnostic = salsa::attach(&db, || { | |
| 173 | let diagnostic = hir::attach_db(&db, || { | |
| 174 | 174 | super::full_diagnostics( |
| 175 | 175 | &db, |
| 176 | 176 | &DiagnosticsConfig::test_sample(), |
| ... | ... | @@ -212,7 +212,7 @@ pub(crate) fn check_diagnostics_with_config( |
| 212 | 212 | .iter() |
| 213 | 213 | .copied() |
| 214 | 214 | .flat_map(|file_id| { |
| 215 | salsa::attach(&db, || { | |
| 215 | hir::attach_db(&db, || { | |
| 216 | 216 | super::full_diagnostics( |
| 217 | 217 | &db, |
| 218 | 218 | &config, |
| ... | ... | @@ -288,12 +288,12 @@ fn test_disabled_diagnostics() { |
| 288 | 288 | let (db, file_id) = RootDatabase::with_single_file(r#"mod foo;"#); |
| 289 | 289 | let file_id = file_id.file_id(&db); |
| 290 | 290 | |
| 291 | let diagnostics = salsa::attach(&db, || { | |
| 291 | let diagnostics = hir::attach_db(&db, || { | |
| 292 | 292 | super::full_diagnostics(&db, &config, &AssistResolveStrategy::All, file_id) |
| 293 | 293 | }); |
| 294 | 294 | assert!(diagnostics.is_empty()); |
| 295 | 295 | |
| 296 | let diagnostics = salsa::attach(&db, || { | |
| 296 | let diagnostics = hir::attach_db(&db, || { | |
| 297 | 297 | super::full_diagnostics( |
| 298 | 298 | &db, |
| 299 | 299 | &DiagnosticsConfig::test_sample(), |
src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs+30-28| ... | ... | @@ -799,33 +799,35 @@ mod tests { |
| 799 | 799 | let input = "fn foo() {} fn bar() {} fn main() { foo(1+2); }"; |
| 800 | 800 | |
| 801 | 801 | let (db, position, selections) = crate::tests::single_file(input); |
| 802 | let position = ide_db::FilePosition { | |
| 803 | file_id: position.file_id.file_id(&db), | |
| 804 | offset: position.offset, | |
| 805 | }; | |
| 806 | let mut match_finder = MatchFinder::in_context( | |
| 807 | &db, | |
| 808 | position, | |
| 809 | selections | |
| 810 | .into_iter() | |
| 811 | .map(|frange| ide_db::FileRange { | |
| 812 | file_id: frange.file_id.file_id(&db), | |
| 813 | range: frange.range, | |
| 814 | }) | |
| 815 | .collect(), | |
| 816 | ) | |
| 817 | .unwrap(); | |
| 818 | match_finder.add_rule(rule).unwrap(); | |
| 819 | let matches = match_finder.matches(); | |
| 820 | assert_eq!(matches.matches.len(), 1); | |
| 821 | assert_eq!(matches.matches[0].matched_node.text(), "foo(1+2)"); | |
| 822 | assert_eq!(matches.matches[0].placeholder_values.len(), 1); | |
| 823 | ||
| 824 | let edits = match_finder.edits(); | |
| 825 | assert_eq!(edits.len(), 1); | |
| 826 | let edit = &edits[&position.file_id]; | |
| 827 | let mut after = input.to_owned(); | |
| 828 | edit.apply(&mut after); | |
| 829 | assert_eq!(after, "fn foo() {} fn bar() {} fn main() { bar(1+2); }"); | |
| 802 | hir::attach_db(&db, || { | |
| 803 | let position = ide_db::FilePosition { | |
| 804 | file_id: position.file_id.file_id(&db), | |
| 805 | offset: position.offset, | |
| 806 | }; | |
| 807 | let mut match_finder = MatchFinder::in_context( | |
| 808 | &db, | |
| 809 | position, | |
| 810 | selections | |
| 811 | .into_iter() | |
| 812 | .map(|frange| ide_db::FileRange { | |
| 813 | file_id: frange.file_id.file_id(&db), | |
| 814 | range: frange.range, | |
| 815 | }) | |
| 816 | .collect(), | |
| 817 | ) | |
| 818 | .unwrap(); | |
| 819 | match_finder.add_rule(rule).unwrap(); | |
| 820 | let matches = match_finder.matches(); | |
| 821 | assert_eq!(matches.matches.len(), 1); | |
| 822 | assert_eq!(matches.matches[0].matched_node.text(), "foo(1+2)"); | |
| 823 | assert_eq!(matches.matches[0].placeholder_values.len(), 1); | |
| 824 | ||
| 825 | let edits = match_finder.edits(); | |
| 826 | assert_eq!(edits.len(), 1); | |
| 827 | let edit = &edits[&position.file_id]; | |
| 828 | let mut after = input.to_owned(); | |
| 829 | edit.apply(&mut after); | |
| 830 | assert_eq!(after, "fn foo() {} fn bar() {} fn main() { bar(1+2); }"); | |
| 831 | }); | |
| 830 | 832 | } |
| 831 | 833 | } |
src/tools/rust-analyzer/crates/ide-ssr/src/resolving.rs+2-2| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | //! This module is responsible for resolving paths within rules. |
| 2 | 2 | |
| 3 | 3 | use hir::AsAssocItem; |
| 4 | use ide_db::{FxHashMap, base_db::salsa}; | |
| 4 | use ide_db::FxHashMap; | |
| 5 | 5 | use parsing::Placeholder; |
| 6 | 6 | use syntax::{ |
| 7 | 7 | SmolStr, SyntaxKind, SyntaxNode, SyntaxToken, |
| ... | ... | @@ -48,7 +48,7 @@ impl<'db> ResolvedRule<'db> { |
| 48 | 48 | resolution_scope: &ResolutionScope<'db>, |
| 49 | 49 | index: usize, |
| 50 | 50 | ) -> Result<ResolvedRule<'db>, SsrError> { |
| 51 | salsa::attach(resolution_scope.scope.db, || { | |
| 51 | hir::attach_db(resolution_scope.scope.db, || { | |
| 52 | 52 | let resolver = Resolver { |
| 53 | 53 | resolution_scope, |
| 54 | 54 | placeholders_by_stand_in: rule.placeholders_by_stand_in, |
src/tools/rust-analyzer/crates/ide-ssr/src/tests.rs+79-72| ... | ... | @@ -2,10 +2,7 @@ use expect_test::{Expect, expect}; |
| 2 | 2 | use hir::{FilePosition, FileRange}; |
| 3 | 3 | use ide_db::{ |
| 4 | 4 | EditionedFileId, FxHashSet, |
| 5 | base_db::{ | |
| 6 | SourceDatabase, | |
| 7 | salsa::{self, Durability}, | |
| 8 | }, | |
| 5 | base_db::{SourceDatabase, salsa::Durability}, | |
| 9 | 6 | }; |
| 10 | 7 | use test_utils::RangeOrOffset; |
| 11 | 8 | use triomphe::Arc; |
| ... | ... | @@ -101,33 +98,37 @@ fn assert_ssr_transform(rule: &str, input: &str, expected: Expect) { |
| 101 | 98 | |
| 102 | 99 | fn assert_ssr_transforms(rules: &[&str], input: &str, expected: Expect) { |
| 103 | 100 | let (db, position, selections) = single_file(input); |
| 104 | let position = | |
| 105 | ide_db::FilePosition { file_id: position.file_id.file_id(&db), offset: position.offset }; | |
| 106 | let mut match_finder = MatchFinder::in_context( | |
| 107 | &db, | |
| 108 | position, | |
| 109 | selections | |
| 110 | .into_iter() | |
| 111 | .map(|selection| ide_db::FileRange { | |
| 112 | file_id: selection.file_id.file_id(&db), | |
| 113 | range: selection.range, | |
| 114 | }) | |
| 115 | .collect(), | |
| 116 | ) | |
| 117 | .unwrap(); | |
| 118 | for rule in rules { | |
| 119 | let rule: SsrRule = rule.parse().unwrap(); | |
| 120 | match_finder.add_rule(rule).unwrap(); | |
| 121 | } | |
| 122 | let edits = salsa::attach(&db, || match_finder.edits()); | |
| 123 | if edits.is_empty() { | |
| 124 | panic!("No edits were made"); | |
| 125 | } | |
| 126 | // Note, db.file_text is not necessarily the same as `input`, since fixture parsing alters | |
| 127 | // stuff. | |
| 128 | let mut actual = db.file_text(position.file_id).text(&db).to_string(); | |
| 129 | edits[&position.file_id].apply(&mut actual); | |
| 130 | expected.assert_eq(&actual); | |
| 101 | hir::attach_db(&db, || { | |
| 102 | let position = ide_db::FilePosition { | |
| 103 | file_id: position.file_id.file_id(&db), | |
| 104 | offset: position.offset, | |
| 105 | }; | |
| 106 | let mut match_finder = MatchFinder::in_context( | |
| 107 | &db, | |
| 108 | position, | |
| 109 | selections | |
| 110 | .into_iter() | |
| 111 | .map(|selection| ide_db::FileRange { | |
| 112 | file_id: selection.file_id.file_id(&db), | |
| 113 | range: selection.range, | |
| 114 | }) | |
| 115 | .collect(), | |
| 116 | ) | |
| 117 | .unwrap(); | |
| 118 | for rule in rules { | |
| 119 | let rule: SsrRule = rule.parse().unwrap(); | |
| 120 | match_finder.add_rule(rule).unwrap(); | |
| 121 | } | |
| 122 | let edits = match_finder.edits(); | |
| 123 | if edits.is_empty() { | |
| 124 | panic!("No edits were made"); | |
| 125 | } | |
| 126 | // Note, db.file_text is not necessarily the same as `input`, since fixture parsing alters | |
| 127 | // stuff. | |
| 128 | let mut actual = db.file_text(position.file_id).text(&db).to_string(); | |
| 129 | edits[&position.file_id].apply(&mut actual); | |
| 130 | expected.assert_eq(&actual); | |
| 131 | }) | |
| 131 | 132 | } |
| 132 | 133 | |
| 133 | 134 | #[allow(clippy::print_stdout)] |
| ... | ... | @@ -145,51 +146,57 @@ fn print_match_debug_info(match_finder: &MatchFinder<'_>, file_id: EditionedFile |
| 145 | 146 | |
| 146 | 147 | fn assert_matches(pattern: &str, code: &str, expected: &[&str]) { |
| 147 | 148 | let (db, position, selections) = single_file(code); |
| 148 | let mut match_finder = MatchFinder::in_context( | |
| 149 | &db, | |
| 150 | ide_db::FilePosition { file_id: position.file_id.file_id(&db), offset: position.offset }, | |
| 151 | selections | |
| 152 | .into_iter() | |
| 153 | .map(|selection| ide_db::FileRange { | |
| 154 | file_id: selection.file_id.file_id(&db), | |
| 155 | range: selection.range, | |
| 156 | }) | |
| 157 | .collect(), | |
| 158 | ) | |
| 159 | .unwrap(); | |
| 160 | match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap(); | |
| 161 | let matched_strings: Vec<String> = salsa::attach(&db, || match_finder.matches()) | |
| 162 | .flattened() | |
| 163 | .matches | |
| 164 | .iter() | |
| 165 | .map(|m| m.matched_text()) | |
| 166 | .collect(); | |
| 167 | if matched_strings != expected && !expected.is_empty() { | |
| 168 | print_match_debug_info(&match_finder, position.file_id, expected[0]); | |
| 169 | } | |
| 170 | assert_eq!(matched_strings, expected); | |
| 149 | hir::attach_db(&db, || { | |
| 150 | let mut match_finder = MatchFinder::in_context( | |
| 151 | &db, | |
| 152 | ide_db::FilePosition { | |
| 153 | file_id: position.file_id.file_id(&db), | |
| 154 | offset: position.offset, | |
| 155 | }, | |
| 156 | selections | |
| 157 | .into_iter() | |
| 158 | .map(|selection| ide_db::FileRange { | |
| 159 | file_id: selection.file_id.file_id(&db), | |
| 160 | range: selection.range, | |
| 161 | }) | |
| 162 | .collect(), | |
| 163 | ) | |
| 164 | .unwrap(); | |
| 165 | match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap(); | |
| 166 | let matched_strings: Vec<String> = | |
| 167 | match_finder.matches().flattened().matches.iter().map(|m| m.matched_text()).collect(); | |
| 168 | if matched_strings != expected && !expected.is_empty() { | |
| 169 | print_match_debug_info(&match_finder, position.file_id, expected[0]); | |
| 170 | } | |
| 171 | assert_eq!(matched_strings, expected); | |
| 172 | }) | |
| 171 | 173 | } |
| 172 | 174 | |
| 173 | 175 | fn assert_no_match(pattern: &str, code: &str) { |
| 174 | 176 | let (db, position, selections) = single_file(code); |
| 175 | let mut match_finder = MatchFinder::in_context( | |
| 176 | &db, | |
| 177 | ide_db::FilePosition { file_id: position.file_id.file_id(&db), offset: position.offset }, | |
| 178 | selections | |
| 179 | .into_iter() | |
| 180 | .map(|selection| ide_db::FileRange { | |
| 181 | file_id: selection.file_id.file_id(&db), | |
| 182 | range: selection.range, | |
| 183 | }) | |
| 184 | .collect(), | |
| 185 | ) | |
| 186 | .unwrap(); | |
| 187 | match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap(); | |
| 188 | let matches = match_finder.matches().flattened().matches; | |
| 189 | if !matches.is_empty() { | |
| 190 | print_match_debug_info(&match_finder, position.file_id, &matches[0].matched_text()); | |
| 191 | panic!("Got {} matches when we expected none: {matches:#?}", matches.len()); | |
| 192 | } | |
| 177 | hir::attach_db(&db, || { | |
| 178 | let mut match_finder = MatchFinder::in_context( | |
| 179 | &db, | |
| 180 | ide_db::FilePosition { | |
| 181 | file_id: position.file_id.file_id(&db), | |
| 182 | offset: position.offset, | |
| 183 | }, | |
| 184 | selections | |
| 185 | .into_iter() | |
| 186 | .map(|selection| ide_db::FileRange { | |
| 187 | file_id: selection.file_id.file_id(&db), | |
| 188 | range: selection.range, | |
| 189 | }) | |
| 190 | .collect(), | |
| 191 | ) | |
| 192 | .unwrap(); | |
| 193 | match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap(); | |
| 194 | let matches = match_finder.matches().flattened().matches; | |
| 195 | if !matches.is_empty() { | |
| 196 | print_match_debug_info(&match_finder, position.file_id, &matches[0].matched_text()); | |
| 197 | panic!("Got {} matches when we expected none: {matches:#?}", matches.len()); | |
| 198 | } | |
| 199 | }); | |
| 193 | 200 | } |
| 194 | 201 | |
| 195 | 202 | fn assert_match_failure_reason(pattern: &str, code: &str, snippet: &str, expected_reason: &str) { |
src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs+2-3| ... | ... | @@ -4,7 +4,6 @@ use expect_test::{Expect, expect}; |
| 4 | 4 | use hir::Semantics; |
| 5 | 5 | use ide_db::{ |
| 6 | 6 | FilePosition, FileRange, RootDatabase, |
| 7 | base_db::salsa, | |
| 8 | 7 | defs::Definition, |
| 9 | 8 | documentation::{DocsRangeMap, Documentation, HasDocs}, |
| 10 | 9 | }; |
| ... | ... | @@ -48,7 +47,7 @@ fn check_rewrite(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect |
| 48 | 47 | let sema = &Semantics::new(&analysis.db); |
| 49 | 48 | let (cursor_def, docs, range) = def_under_cursor(sema, &position); |
| 50 | 49 | let res = |
| 51 | salsa::attach(sema.db, || rewrite_links(sema.db, docs.as_str(), cursor_def, Some(range))); | |
| 50 | hir::attach_db(sema.db, || rewrite_links(sema.db, docs.as_str(), cursor_def, Some(range))); | |
| 52 | 51 | expect.assert_eq(&res) |
| 53 | 52 | } |
| 54 | 53 | |
| ... | ... | @@ -65,7 +64,7 @@ fn check_doc_links(#[rust_analyzer::rust_fixture] ra_fixture: &str) { |
| 65 | 64 | .flat_map(|(text_range, link, ns)| { |
| 66 | 65 | let attr = range.map(text_range); |
| 67 | 66 | let is_inner_attr = attr.map(|(_file, attr)| attr.is_inner_attr()).unwrap_or(false); |
| 68 | let def = salsa::attach(sema.db, || { | |
| 67 | let def = hir::attach_db(sema.db, || { | |
| 69 | 68 | resolve_doc_path_for_def(sema.db, cursor_def, &link, ns, is_inner_attr) |
| 70 | 69 | .unwrap_or_else(|| panic!("Failed to resolve {link}")) |
| 71 | 70 | }); |
src/tools/rust-analyzer/crates/ide/src/hover/render.rs+4-4| ... | ... | @@ -695,7 +695,7 @@ pub(super) fn definition( |
| 695 | 695 | DropInfo { drop_glue: field.ty(db).to_type(db).drop_glue(db), has_dtor: None } |
| 696 | 696 | } |
| 697 | 697 | Definition::Adt(Adt::Struct(strukt)) => { |
| 698 | let struct_drop_glue = strukt.ty_placeholders(db).drop_glue(db); | |
| 698 | let struct_drop_glue = strukt.ty_params(db).drop_glue(db); | |
| 699 | 699 | let mut fields_drop_glue = strukt |
| 700 | 700 | .fields(db) |
| 701 | 701 | .iter() |
| ... | ... | @@ -716,10 +716,10 @@ pub(super) fn definition( |
| 716 | 716 | // Unions cannot have fields with drop glue. |
| 717 | 717 | Definition::Adt(Adt::Union(union)) => DropInfo { |
| 718 | 718 | drop_glue: DropGlue::None, |
| 719 | has_dtor: Some(union.ty_placeholders(db).drop_glue(db) != DropGlue::None), | |
| 719 | has_dtor: Some(union.ty_params(db).drop_glue(db) != DropGlue::None), | |
| 720 | 720 | }, |
| 721 | 721 | Definition::Adt(Adt::Enum(enum_)) => { |
| 722 | let enum_drop_glue = enum_.ty_placeholders(db).drop_glue(db); | |
| 722 | let enum_drop_glue = enum_.ty_params(db).drop_glue(db); | |
| 723 | 723 | let fields_drop_glue = enum_ |
| 724 | 724 | .variants(db) |
| 725 | 725 | .iter() |
| ... | ... | @@ -748,7 +748,7 @@ pub(super) fn definition( |
| 748 | 748 | DropInfo { drop_glue: fields_drop_glue, has_dtor: None } |
| 749 | 749 | } |
| 750 | 750 | Definition::TypeAlias(type_alias) => { |
| 751 | DropInfo { drop_glue: type_alias.ty_placeholders(db).drop_glue(db), has_dtor: None } | |
| 751 | DropInfo { drop_glue: type_alias.ty_params(db).drop_glue(db), has_dtor: None } | |
| 752 | 752 | } |
| 753 | 753 | Definition::Local(local) => { |
| 754 | 754 | DropInfo { drop_glue: local.ty(db).drop_glue(db), has_dtor: None } |
src/tools/rust-analyzer/crates/ide/src/hover/tests.rs+8-2| ... | ... | @@ -6306,6 +6306,8 @@ const FOO$0: (&str, &str) = { |
| 6306 | 6306 | ); |
| 6307 | 6307 | } |
| 6308 | 6308 | |
| 6309 | // FIXME(next-solver): this fails to normalize the const, probably due to the solver | |
| 6310 | // refusing to give the impl because of the error type. | |
| 6309 | 6311 | #[test] |
| 6310 | 6312 | fn hover_const_eval_in_generic_trait() { |
| 6311 | 6313 | // Doesn't compile, but we shouldn't crash. |
| ... | ... | @@ -6327,12 +6329,16 @@ fn test() { |
| 6327 | 6329 | *FOO* |
| 6328 | 6330 | |
| 6329 | 6331 | ```rust |
| 6330 | ra_test_fixture::S | |
| 6332 | ra_test_fixture::Trait | |
| 6331 | 6333 | ``` |
| 6332 | 6334 | |
| 6333 | 6335 | ```rust |
| 6334 | const FOO: bool = true | |
| 6336 | const FOO: bool = false | |
| 6335 | 6337 | ``` |
| 6338 | ||
| 6339 | --- | |
| 6340 | ||
| 6341 | `Self` = `S<{unknown}>` | |
| 6336 | 6342 | "#]], |
| 6337 | 6343 | ); |
| 6338 | 6344 | } |
src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs+3-5| ... | ... | @@ -8,9 +8,7 @@ use hir::{ |
| 8 | 8 | ClosureStyle, DisplayTarget, EditionedFileId, HasVisibility, HirDisplay, HirDisplayError, |
| 9 | 9 | HirWrite, InRealFile, ModuleDef, ModuleDefId, Semantics, sym, |
| 10 | 10 | }; |
| 11 | use ide_db::{ | |
| 12 | FileRange, RootDatabase, base_db::salsa, famous_defs::FamousDefs, text_edit::TextEditBuilder, | |
| 13 | }; | |
| 11 | use ide_db::{FileRange, RootDatabase, famous_defs::FamousDefs, text_edit::TextEditBuilder}; | |
| 14 | 12 | use ide_db::{FxHashSet, text_edit::TextEdit}; |
| 15 | 13 | use itertools::Itertools; |
| 16 | 14 | use smallvec::{SmallVec, smallvec}; |
| ... | ... | @@ -107,7 +105,7 @@ pub(crate) fn inlay_hints( |
| 107 | 105 | } |
| 108 | 106 | }; |
| 109 | 107 | let mut preorder = file.preorder(); |
| 110 | salsa::attach(sema.db, || { | |
| 108 | hir::attach_db(sema.db, || { | |
| 111 | 109 | while let Some(event) = preorder.next() { |
| 112 | 110 | if matches!((&event, range_limit), (WalkEvent::Enter(node), Some(range)) if range.intersect(node.text_range()).is_none()) |
| 113 | 111 | { |
| ... | ... | @@ -739,7 +737,7 @@ fn label_of_ty( |
| 739 | 737 | config: &InlayHintsConfig, |
| 740 | 738 | display_target: DisplayTarget, |
| 741 | 739 | ) -> Result<(), HirDisplayError> { |
| 742 | salsa::attach(sema.db, || { | |
| 740 | hir::attach_db(sema.db, || { | |
| 743 | 741 | let iter_item_type = hint_iterator(sema, famous_defs, ty); |
| 744 | 742 | match iter_item_type { |
| 745 | 743 | Some((iter_trait, item, ty)) => { |
src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs+2-2| ... | ... | @@ -10,7 +10,7 @@ use hir::{ |
| 10 | 10 | Adjust, Adjustment, AutoBorrow, DisplayTarget, HirDisplay, Mutability, OverloadedDeref, |
| 11 | 11 | PointerCast, Safety, |
| 12 | 12 | }; |
| 13 | use ide_db::{base_db::salsa, famous_defs::FamousDefs}; | |
| 13 | use ide_db::famous_defs::FamousDefs; | |
| 14 | 14 | |
| 15 | 15 | use ide_db::text_edit::TextEditBuilder; |
| 16 | 16 | use syntax::ast::{self, AstNode, prec::ExprPrecedence}; |
| ... | ... | @@ -216,7 +216,7 @@ pub(super) fn hints( |
| 216 | 216 | text: if postfix { format!(".{}", text.trim_end()) } else { text.to_owned() }, |
| 217 | 217 | linked_location: None, |
| 218 | 218 | tooltip: Some(config.lazy_tooltip(|| { |
| 219 | salsa::attach(sema.db, || { | |
| 219 | hir::attach_db(sema.db, || { | |
| 220 | 220 | InlayTooltip::Markdown(format!( |
| 221 | 221 | "`{}` → `{}`\n\n**{}**\n\n{}", |
| 222 | 222 | source.display(sema.db, display_target), |
src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs+2-2| ... | ... | @@ -646,9 +646,9 @@ auto trait Sync {} |
| 646 | 646 | fn main() { |
| 647 | 647 | // The block expression wrapping disables the constructor hint hiding logic |
| 648 | 648 | let _v = { Vec::<Box<&(dyn Display + Sync)>>::new() }; |
| 649 | //^^ Vec<Box<&(dyn Display + Sync)>> | |
| 649 | //^^ Vec<Box<&(dyn Display + Sync + 'static)>> | |
| 650 | 650 | let _v = { Vec::<Box<*const (dyn Display + Sync)>>::new() }; |
| 651 | //^^ Vec<Box<*const (dyn Display + Sync)>> | |
| 651 | //^^ Vec<Box<*const (dyn Display + Sync + 'static)>> | |
| 652 | 652 | let _v = { Vec::<Box<dyn Display + Sync + 'static>>::new() }; |
| 653 | 653 | //^^ Vec<Box<dyn Display + Sync + 'static>> |
| 654 | 654 | } |
src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs+2-2| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | //! } |
| 7 | 7 | //! ``` |
| 8 | 8 | use hir::{ |
| 9 | ChalkTyInterner, DefWithBody, | |
| 9 | DefWithBody, | |
| 10 | 10 | db::{DefDatabase as _, HirDatabase as _}, |
| 11 | 11 | mir::{MirSpan, TerminatorKind}, |
| 12 | 12 | }; |
| ... | ... | @@ -46,7 +46,7 @@ pub(super) fn hints( |
| 46 | 46 | if !place.projection.is_empty() { |
| 47 | 47 | continue; // Ignore complex cases for now |
| 48 | 48 | } |
| 49 | if mir.locals[place.local].ty.adt_id(ChalkTyInterner).is_none() { | |
| 49 | if mir.locals[place.local].ty.as_adt().is_none() { | |
| 50 | 50 | continue; // Arguably only ADTs have significant drop impls |
| 51 | 51 | } |
| 52 | 52 | let Some(&binding_idx) = local_to_binding.get(place.local) else { |
src/tools/rust-analyzer/crates/ide/src/interpret.rs+1-1| ... | ... | @@ -60,7 +60,7 @@ fn find_and_interpret(db: &RootDatabase, position: FilePosition) -> Option<(Dura |
| 60 | 60 | |
| 61 | 61 | pub(crate) fn render_const_eval_error( |
| 62 | 62 | db: &RootDatabase, |
| 63 | e: ConstEvalError, | |
| 63 | e: ConstEvalError<'_>, | |
| 64 | 64 | display_target: DisplayTarget, |
| 65 | 65 | ) -> String { |
| 66 | 66 | let span_formatter = |file_id, text_range: TextRange| { |
src/tools/rust-analyzer/crates/ide/src/lib.rs+3-3| ... | ... | @@ -67,7 +67,7 @@ use ide_db::{ |
| 67 | 67 | FxHashMap, FxIndexSet, LineIndexDatabase, |
| 68 | 68 | base_db::{ |
| 69 | 69 | CrateOrigin, CrateWorkspaceData, Env, FileSet, RootQueryDb, SourceDatabase, VfsPath, |
| 70 | salsa::{self, Cancelled}, | |
| 70 | salsa::Cancelled, | |
| 71 | 71 | }, |
| 72 | 72 | prime_caches, symbol_index, |
| 73 | 73 | }; |
| ... | ... | @@ -480,7 +480,7 @@ impl Analysis { |
| 480 | 480 | // if we were to attach it here. |
| 481 | 481 | Cancelled::catch(|| { |
| 482 | 482 | let symbols = symbol_index::world_symbols(&self.db, query); |
| 483 | salsa::attach(&self.db, || { | |
| 483 | hir::attach_db(&self.db, || { | |
| 484 | 484 | symbols |
| 485 | 485 | .into_iter() |
| 486 | 486 | .filter_map(|s| s.try_to_nav(&Semantics::new(&self.db))) |
| ... | ... | @@ -899,7 +899,7 @@ impl Analysis { |
| 899 | 899 | where |
| 900 | 900 | F: FnOnce(&RootDatabase) -> T + std::panic::UnwindSafe, |
| 901 | 901 | { |
| 902 | salsa::attach(&self.db, || { | |
| 902 | hir::attach_db(&self.db, || { | |
| 903 | 903 | // the trait solver code may invoke `as_view<HirDatabase>` outside of queries, |
| 904 | 904 | // so technically we might run into a panic in salsa if the downcaster has not yet been registered. |
| 905 | 905 | HirDatabase::zalsa_register_downcaster(&self.db); |
src/tools/rust-analyzer/crates/ide/src/navigation_target.rs+3-3| ... | ... | @@ -10,7 +10,7 @@ use hir::{ |
| 10 | 10 | }; |
| 11 | 11 | use ide_db::{ |
| 12 | 12 | FileId, FileRange, RootDatabase, SymbolKind, |
| 13 | base_db::{CrateOrigin, LangCrateOrigin, RootQueryDb, salsa}, | |
| 13 | base_db::{CrateOrigin, LangCrateOrigin, RootQueryDb}, | |
| 14 | 14 | defs::{Definition, find_std_module}, |
| 15 | 15 | documentation::{Documentation, HasDocs}, |
| 16 | 16 | famous_defs::FamousDefs, |
| ... | ... | @@ -399,7 +399,7 @@ where |
| 399 | 399 | ) |
| 400 | 400 | .map(|mut res| { |
| 401 | 401 | res.docs = self.docs(db); |
| 402 | res.description = salsa::attach(db, || { | |
| 402 | res.description = hir::attach_db(db, || { | |
| 403 | 403 | Some(self.display(db, self.krate(db).to_display_target(db)).to_string()) |
| 404 | 404 | }); |
| 405 | 405 | res.container_name = self.container_name(db); |
| ... | ... | @@ -520,7 +520,7 @@ impl TryToNav for hir::Field { |
| 520 | 520 | NavigationTarget::from_named(db, src.with_value(it), SymbolKind::Field).map( |
| 521 | 521 | |mut res| { |
| 522 | 522 | res.docs = self.docs(db); |
| 523 | res.description = salsa::attach(db, || { | |
| 523 | res.description = hir::attach_db(db, || { | |
| 524 | 524 | Some(self.display(db, krate.to_display_target(db)).to_string()) |
| 525 | 525 | }); |
| 526 | 526 | res |
src/tools/rust-analyzer/crates/ide/src/runnables.rs+3-3| ... | ... | @@ -10,7 +10,7 @@ use hir::{ |
| 10 | 10 | use ide_assists::utils::{has_test_related_attribute, test_related_attribute_syn}; |
| 11 | 11 | use ide_db::{ |
| 12 | 12 | FilePosition, FxHashMap, FxIndexMap, FxIndexSet, RootDatabase, SymbolKind, |
| 13 | base_db::{RootQueryDb, salsa}, | |
| 13 | base_db::RootQueryDb, | |
| 14 | 14 | defs::Definition, |
| 15 | 15 | documentation::docs_from_attrs, |
| 16 | 16 | helpers::visit_file_defs, |
| ... | ... | @@ -413,7 +413,7 @@ pub(crate) fn runnable_impl( |
| 413 | 413 | let ty = def.self_ty(sema.db); |
| 414 | 414 | let adt_name = ty.as_adt()?.name(sema.db); |
| 415 | 415 | let mut ty_args = ty.generic_parameters(sema.db, display_target).peekable(); |
| 416 | let params = salsa::attach(sema.db, || { | |
| 416 | let params = hir::attach_db(sema.db, || { | |
| 417 | 417 | if ty_args.peek().is_some() { |
| 418 | 418 | format!("<{}>", ty_args.format_with(",", |ty, cb| cb(&ty))) |
| 419 | 419 | } else { |
| ... | ... | @@ -522,7 +522,7 @@ fn module_def_doctest(sema: &Semantics<'_, RootDatabase>, def: Definition) -> Op |
| 522 | 522 | let mut ty_args = ty.generic_parameters(db, display_target).peekable(); |
| 523 | 523 | format_to!(path, "{}", name.display(db, edition)); |
| 524 | 524 | if ty_args.peek().is_some() { |
| 525 | salsa::attach(db, || { | |
| 525 | hir::attach_db(db, || { | |
| 526 | 526 | format_to!(path, "<{}>", ty_args.format_with(",", |ty, cb| cb(&ty))); |
| 527 | 527 | }); |
| 528 | 528 | } |
src/tools/rust-analyzer/crates/ide/src/signature_help.rs+3-4| ... | ... | @@ -11,7 +11,6 @@ use hir::{ |
| 11 | 11 | use ide_db::{ |
| 12 | 12 | FilePosition, FxIndexMap, |
| 13 | 13 | active_parameter::{callable_for_arg_list, generic_def_for_node}, |
| 14 | base_db::salsa, | |
| 15 | 14 | documentation::{Documentation, HasDocs}, |
| 16 | 15 | }; |
| 17 | 16 | use itertools::Itertools; |
| ... | ... | @@ -267,7 +266,7 @@ fn signature_help_for_call( |
| 267 | 266 | // In that case, fall back to render definitions of the respective parameters. |
| 268 | 267 | // This is overly conservative: we do not substitute known type vars |
| 269 | 268 | // (see FIXME in tests::impl_trait) and falling back on any unknowns. |
| 270 | salsa::attach(db, || match (p.ty().contains_unknown(), fn_params.as_deref()) { | |
| 269 | hir::attach_db(db, || match (p.ty().contains_unknown(), fn_params.as_deref()) { | |
| 271 | 270 | (true, Some(fn_params)) => { |
| 272 | 271 | format_to!(buf, "{}", fn_params[idx].ty().display(db, display_target)) |
| 273 | 272 | } |
| ... | ... | @@ -730,7 +729,7 @@ fn signature_help_for_tuple_pat_ish<'db>( |
| 730 | 729 | mod tests { |
| 731 | 730 | |
| 732 | 731 | use expect_test::{Expect, expect}; |
| 733 | use ide_db::{FilePosition, base_db::salsa}; | |
| 732 | use ide_db::FilePosition; | |
| 734 | 733 | use stdx::format_to; |
| 735 | 734 | use test_fixture::ChangeFixture; |
| 736 | 735 | |
| ... | ... | @@ -759,7 +758,7 @@ mod tests { |
| 759 | 758 | "# |
| 760 | 759 | ); |
| 761 | 760 | let (db, position) = position(&fixture); |
| 762 | let sig_help = salsa::attach(&db, || crate::signature_help::signature_help(&db, position)); | |
| 761 | let sig_help = hir::attach_db(&db, || crate::signature_help::signature_help(&db, position)); | |
| 763 | 762 | let actual = match sig_help { |
| 764 | 763 | Some(sig_help) => { |
| 765 | 764 | let mut rendered = String::new(); |
src/tools/rust-analyzer/crates/ide/src/static_index.rs+58-57| ... | ... | @@ -5,7 +5,7 @@ use arrayvec::ArrayVec; |
| 5 | 5 | use hir::{Crate, Module, Semantics, db::HirDatabase}; |
| 6 | 6 | use ide_db::{ |
| 7 | 7 | FileId, FileRange, FxHashMap, FxHashSet, RootDatabase, |
| 8 | base_db::{RootQueryDb, SourceDatabase, VfsPath, salsa}, | |
| 8 | base_db::{RootQueryDb, SourceDatabase, VfsPath}, | |
| 9 | 9 | defs::{Definition, IdentClass}, |
| 10 | 10 | documentation::Documentation, |
| 11 | 11 | famous_defs::FamousDefs, |
| ... | ... | @@ -228,32 +228,30 @@ impl StaticIndex<'_> { |
| 228 | 228 | let id = if let Some(it) = self.def_map.get(&def) { |
| 229 | 229 | *it |
| 230 | 230 | } else { |
| 231 | let it = salsa::attach(sema.db, || { | |
| 232 | self.tokens.insert(TokenStaticData { | |
| 233 | documentation: documentation_for_definition(&sema, def, scope_node), | |
| 234 | hover: Some(hover_for_definition( | |
| 235 | &sema, | |
| 236 | file_id, | |
| 237 | def, | |
| 238 | None, | |
| 239 | scope_node, | |
| 240 | None, | |
| 241 | false, | |
| 242 | &hover_config, | |
| 243 | edition, | |
| 244 | display_target, | |
| 245 | )), | |
| 246 | definition: def.try_to_nav(&sema).map(UpmappingResult::call_site).map( | |
| 247 | |it| FileRange { file_id: it.file_id, range: it.focus_or_full_range() }, | |
| 248 | ), | |
| 249 | references: vec![], | |
| 250 | moniker: current_crate.and_then(|cc| def_to_moniker(self.db, def, cc)), | |
| 251 | display_name: def | |
| 252 | .name(self.db) | |
| 253 | .map(|name| name.display(self.db, edition).to_string()), | |
| 254 | signature: Some(def.label(self.db, display_target)), | |
| 255 | kind: def_to_kind(self.db, def), | |
| 256 | }) | |
| 231 | let it = self.tokens.insert(TokenStaticData { | |
| 232 | documentation: documentation_for_definition(&sema, def, scope_node), | |
| 233 | hover: Some(hover_for_definition( | |
| 234 | &sema, | |
| 235 | file_id, | |
| 236 | def, | |
| 237 | None, | |
| 238 | scope_node, | |
| 239 | None, | |
| 240 | false, | |
| 241 | &hover_config, | |
| 242 | edition, | |
| 243 | display_target, | |
| 244 | )), | |
| 245 | definition: def.try_to_nav(&sema).map(UpmappingResult::call_site).map(|it| { | |
| 246 | FileRange { file_id: it.file_id, range: it.focus_or_full_range() } | |
| 247 | }), | |
| 248 | references: vec![], | |
| 249 | moniker: current_crate.and_then(|cc| def_to_moniker(self.db, def, cc)), | |
| 250 | display_name: def | |
| 251 | .name(self.db) | |
| 252 | .map(|name| name.display(self.db, edition).to_string()), | |
| 253 | signature: Some(def.label(self.db, display_target)), | |
| 254 | kind: def_to_kind(self.db, def), | |
| 257 | 255 | }); |
| 258 | 256 | self.def_map.insert(def, it); |
| 259 | 257 | it |
| ... | ... | @@ -278,7 +276,7 @@ impl StaticIndex<'_> { |
| 278 | 276 | for token in tokens { |
| 279 | 277 | let range = token.text_range(); |
| 280 | 278 | let node = token.parent().unwrap(); |
| 281 | match salsa::attach(self.db, || get_definitions(&sema, token.clone())) { | |
| 279 | match hir::attach_db(self.db, || get_definitions(&sema, token.clone())) { | |
| 282 | 280 | Some(it) => { |
| 283 | 281 | for i in it { |
| 284 | 282 | add_token(i, range, &node); |
| ... | ... | @@ -295,37 +293,40 @@ impl StaticIndex<'_> { |
| 295 | 293 | vendored_libs_config: VendoredLibrariesConfig<'_>, |
| 296 | 294 | ) -> StaticIndex<'a> { |
| 297 | 295 | let db = &analysis.db; |
| 298 | let work = all_modules(db).into_iter().filter(|module| { | |
| 299 | let file_id = module.definition_source_file_id(db).original_file(db); | |
| 300 | let source_root = db.file_source_root(file_id.file_id(&analysis.db)).source_root_id(db); | |
| 301 | let source_root = db.source_root(source_root).source_root(db); | |
| 302 | let is_vendored = match vendored_libs_config { | |
| 303 | VendoredLibrariesConfig::Included { workspace_root } => source_root | |
| 304 | .path_for_file(&file_id.file_id(&analysis.db)) | |
| 305 | .is_some_and(|module_path| module_path.starts_with(workspace_root)), | |
| 306 | VendoredLibrariesConfig::Excluded => false, | |
| 296 | hir::attach_db(db, || { | |
| 297 | let work = all_modules(db).into_iter().filter(|module| { | |
| 298 | let file_id = module.definition_source_file_id(db).original_file(db); | |
| 299 | let source_root = | |
| 300 | db.file_source_root(file_id.file_id(&analysis.db)).source_root_id(db); | |
| 301 | let source_root = db.source_root(source_root).source_root(db); | |
| 302 | let is_vendored = match vendored_libs_config { | |
| 303 | VendoredLibrariesConfig::Included { workspace_root } => source_root | |
| 304 | .path_for_file(&file_id.file_id(&analysis.db)) | |
| 305 | .is_some_and(|module_path| module_path.starts_with(workspace_root)), | |
| 306 | VendoredLibrariesConfig::Excluded => false, | |
| 307 | }; | |
| 308 | ||
| 309 | !source_root.is_library || is_vendored | |
| 310 | }); | |
| 311 | let mut this = StaticIndex { | |
| 312 | files: vec![], | |
| 313 | tokens: Default::default(), | |
| 314 | analysis, | |
| 315 | db, | |
| 316 | def_map: Default::default(), | |
| 307 | 317 | }; |
| 308 | ||
| 309 | !source_root.is_library || is_vendored | |
| 310 | }); | |
| 311 | let mut this = StaticIndex { | |
| 312 | files: vec![], | |
| 313 | tokens: Default::default(), | |
| 314 | analysis, | |
| 315 | db, | |
| 316 | def_map: Default::default(), | |
| 317 | }; | |
| 318 | let mut visited_files = FxHashSet::default(); | |
| 319 | for module in work { | |
| 320 | let file_id = module.definition_source_file_id(db).original_file(db); | |
| 321 | if visited_files.contains(&file_id) { | |
| 322 | continue; | |
| 318 | let mut visited_files = FxHashSet::default(); | |
| 319 | for module in work { | |
| 320 | let file_id = module.definition_source_file_id(db).original_file(db); | |
| 321 | if visited_files.contains(&file_id) { | |
| 322 | continue; | |
| 323 | } | |
| 324 | this.add_file(file_id.file_id(&analysis.db)); | |
| 325 | // mark the file | |
| 326 | visited_files.insert(file_id); | |
| 323 | 327 | } |
| 324 | this.add_file(file_id.file_id(&analysis.db)); | |
| 325 | // mark the file | |
| 326 | visited_files.insert(file_id); | |
| 327 | } | |
| 328 | this | |
| 328 | this | |
| 329 | }) | |
| 329 | 330 | } |
| 330 | 331 | } |
| 331 | 332 |
src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs+10-7| ... | ... | @@ -16,7 +16,7 @@ use std::ops::ControlFlow; |
| 16 | 16 | |
| 17 | 17 | use either::Either; |
| 18 | 18 | use hir::{DefWithBody, EditionedFileId, InFile, InRealFile, MacroKind, Name, Semantics}; |
| 19 | use ide_db::{FxHashMap, FxHashSet, Ranker, RootDatabase, SymbolKind, base_db::salsa}; | |
| 19 | use ide_db::{FxHashMap, FxHashSet, Ranker, RootDatabase, SymbolKind}; | |
| 20 | 20 | use syntax::{ |
| 21 | 21 | AstNode, AstToken, NodeOrToken, |
| 22 | 22 | SyntaxKind::*, |
| ... | ... | @@ -116,7 +116,7 @@ pub struct HighlightConfig { |
| 116 | 116 | // |arithmetic| Emitted for the arithmetic operators `+`, `-`, `*`, `/`, `+=`, `-=`, `*=`, `/=`.| |
| 117 | 117 | // |bitwise| Emitted for the bitwise operators `|`, `&`, `!`, `^`, `|=`, `&=`, `^=`.| |
| 118 | 118 | // |comparison| Emitted for the comparison oerators `>`, `<`, `==`, `>=`, `<=`, `!=`.| |
| 119 | // |logical| Emitted for the logical operatos `||`, `&&`, `!`.| | |
| 119 | // |logical| Emitted for the logical operators `||`, `&&`, `!`.| | |
| 120 | 120 | // |
| 121 | 121 | // - For punctuation: |
| 122 | 122 | // |
| ... | ... | @@ -426,9 +426,12 @@ fn traverse( |
| 426 | 426 | let edition = descended_element.file_id.edition(sema.db); |
| 427 | 427 | let (unsafe_ops, bindings_shadow_count) = match current_body { |
| 428 | 428 | Some(current_body) => { |
| 429 | let (ops, bindings) = per_body_cache | |
| 430 | .entry(current_body) | |
| 431 | .or_insert_with(|| (sema.get_unsafe_ops(current_body), Default::default())); | |
| 429 | let (ops, bindings) = per_body_cache.entry(current_body).or_insert_with(|| { | |
| 430 | ( | |
| 431 | hir::attach_db(sema.db, || sema.get_unsafe_ops(current_body)), | |
| 432 | Default::default(), | |
| 433 | ) | |
| 434 | }); | |
| 432 | 435 | (&*ops, Some(bindings)) |
| 433 | 436 | } |
| 434 | 437 | None => (&empty, None), |
| ... | ... | @@ -437,7 +440,7 @@ fn traverse( |
| 437 | 440 | |node| unsafe_ops.contains(&InFile::new(descended_element.file_id, node)); |
| 438 | 441 | let element = match descended_element.value { |
| 439 | 442 | NodeOrToken::Node(name_like) => { |
| 440 | let hl = salsa::attach(sema.db, || { | |
| 443 | let hl = hir::attach_db(sema.db, || { | |
| 441 | 444 | highlight::name_like( |
| 442 | 445 | sema, |
| 443 | 446 | krate, |
| ... | ... | @@ -455,7 +458,7 @@ fn traverse( |
| 455 | 458 | } |
| 456 | 459 | hl |
| 457 | 460 | } |
| 458 | NodeOrToken::Token(token) => salsa::attach(sema.db, || { | |
| 461 | NodeOrToken::Token(token) => hir::attach_db(sema.db, || { | |
| 459 | 462 | highlight::token(sema, token, edition, &is_unsafe_node, tt_level > 0) |
| 460 | 463 | .zip(Some(None)) |
| 461 | 464 | }), |
src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs+3-3| ... | ... | @@ -5,7 +5,7 @@ use std::mem; |
| 5 | 5 | use either::Either; |
| 6 | 6 | use hir::{EditionedFileId, HirFileId, InFile, Semantics, sym}; |
| 7 | 7 | use ide_db::{ |
| 8 | SymbolKind, active_parameter::ActiveParameter, base_db::salsa, defs::Definition, | |
| 8 | SymbolKind, active_parameter::ActiveParameter, defs::Definition, | |
| 9 | 9 | documentation::docs_with_rangemap, rust_doc::is_rust_fence, |
| 10 | 10 | }; |
| 11 | 11 | use syntax::{ |
| ... | ... | @@ -27,7 +27,7 @@ pub(super) fn ra_fixture( |
| 27 | 27 | expanded: &ast::String, |
| 28 | 28 | ) -> Option<()> { |
| 29 | 29 | let active_parameter = |
| 30 | salsa::attach(sema.db, || ActiveParameter::at_token(sema, expanded.syntax().clone()))?; | |
| 30 | hir::attach_db(sema.db, || ActiveParameter::at_token(sema, expanded.syntax().clone()))?; | |
| 31 | 31 | let has_rust_fixture_attr = active_parameter.attrs().is_some_and(|attrs| { |
| 32 | 32 | attrs.filter_map(|attr| attr.as_simple_path()).any(|path| { |
| 33 | 33 | path.segments() |
| ... | ... | @@ -128,7 +128,7 @@ pub(super) fn doc_comment( |
| 128 | 128 | |
| 129 | 129 | // Extract intra-doc links and emit highlights for them. |
| 130 | 130 | if let Some((docs, doc_mapping)) = docs_with_rangemap(sema.db, &attributes) { |
| 131 | salsa::attach(sema.db, || { | |
| 131 | hir::attach_db(sema.db, || { | |
| 132 | 132 | extract_definitions_from_docs(&docs) |
| 133 | 133 | .into_iter() |
| 134 | 134 | .filter_map(|(range, link, ns)| { |
src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs+11-14| ... | ... | @@ -3,7 +3,6 @@ use std::fmt; |
| 3 | 3 | use hir::{DisplayTarget, Field, HirDisplay, Layout, Semantics, Type}; |
| 4 | 4 | use ide_db::{ |
| 5 | 5 | RootDatabase, |
| 6 | base_db::salsa, | |
| 7 | 6 | defs::Definition, |
| 8 | 7 | helpers::{get_definition, pick_best_token}, |
| 9 | 8 | }; |
| ... | ... | @@ -94,14 +93,14 @@ pub(crate) fn view_memory_layout( |
| 94 | 93 | let def = get_definition(&sema, token)?; |
| 95 | 94 | |
| 96 | 95 | let ty = match def { |
| 97 | Definition::Adt(it) => salsa::attach(db, || it.ty(db)), | |
| 98 | Definition::TypeAlias(it) => salsa::attach(db, || it.ty(db)), | |
| 96 | Definition::Adt(it) => it.ty(db), | |
| 97 | Definition::TypeAlias(it) => it.ty(db), | |
| 99 | 98 | Definition::BuiltinType(it) => it.ty(db), |
| 100 | 99 | Definition::SelfType(it) => it.self_ty(db), |
| 101 | 100 | Definition::Local(it) => it.ty(db), |
| 102 | Definition::Field(it) => salsa::attach(db, || it.ty(db).to_type(db)), | |
| 103 | Definition::Const(it) => salsa::attach(db, || it.ty(db)), | |
| 104 | Definition::Static(it) => salsa::attach(db, || it.ty(db)), | |
| 101 | Definition::Field(it) => it.ty(db).to_type(db), | |
| 102 | Definition::Const(it) => it.ty(db), | |
| 103 | Definition::Static(it) => it.ty(db), | |
| 105 | 104 | _ => return None, |
| 106 | 105 | }; |
| 107 | 106 | |
| ... | ... | @@ -139,12 +138,10 @@ pub(crate) fn view_memory_layout( |
| 139 | 138 | nodes[parent_idx].children_len = fields.len() as u64; |
| 140 | 139 | |
| 141 | 140 | for (field, child_ty) in fields.iter() { |
| 142 | if let Ok(child_layout) = salsa::attach(db, || child_ty.layout(db)) { | |
| 141 | if let Ok(child_layout) = child_ty.layout(db) { | |
| 143 | 142 | nodes.push(MemoryLayoutNode { |
| 144 | 143 | item_name: field.name(db), |
| 145 | typename: salsa::attach(db, || { | |
| 146 | child_ty.display(db, display_target).to_string() | |
| 147 | }), | |
| 144 | typename: { child_ty.display(db, display_target).to_string() }, | |
| 148 | 145 | size: child_layout.size(), |
| 149 | 146 | alignment: child_layout.align(), |
| 150 | 147 | offset: match *field { |
| ... | ... | @@ -172,13 +169,13 @@ pub(crate) fn view_memory_layout( |
| 172 | 169 | } |
| 173 | 170 | |
| 174 | 171 | for (i, (_, child_ty)) in fields.iter().enumerate() { |
| 175 | if let Ok(child_layout) = salsa::attach(db, || child_ty.layout(db)) { | |
| 172 | if let Ok(child_layout) = child_ty.layout(db) { | |
| 176 | 173 | read_layout(nodes, db, child_ty, &child_layout, children_start + i, display_target); |
| 177 | 174 | } |
| 178 | 175 | } |
| 179 | 176 | } |
| 180 | 177 | |
| 181 | salsa::attach(db, || ty.layout(db)) | |
| 178 | ty.layout(db) | |
| 182 | 179 | .map(|layout| { |
| 183 | 180 | let item_name = match def { |
| 184 | 181 | // def is a datatype |
| ... | ... | @@ -191,7 +188,7 @@ pub(crate) fn view_memory_layout( |
| 191 | 188 | def => def.name(db).map(|n| n.as_str().to_owned()).unwrap_or("[ROOT]".to_owned()), |
| 192 | 189 | }; |
| 193 | 190 | |
| 194 | let typename = salsa::attach(db, || ty.display(db, display_target).to_string()); | |
| 191 | let typename = ty.display(db, display_target).to_string(); | |
| 195 | 192 | |
| 196 | 193 | let mut nodes = vec![MemoryLayoutNode { |
| 197 | 194 | item_name, |
| ... | ... | @@ -222,7 +219,7 @@ mod tests { |
| 222 | 219 | ) -> Option<RecursiveMemoryLayout> { |
| 223 | 220 | let (analysis, position, _) = fixture::annotations(ra_fixture); |
| 224 | 221 | |
| 225 | view_memory_layout(&analysis.db, position) | |
| 222 | hir::attach_db(&analysis.db, || view_memory_layout(&analysis.db, position)) | |
| 226 | 223 | } |
| 227 | 224 | |
| 228 | 225 | #[test] |
src/tools/rust-analyzer/crates/macros/Cargo.toml created+19| ... | ... | @@ -0,0 +1,19 @@ |
| 1 | [package] | |
| 2 | name = "macros" | |
| 3 | version = "0.0.0" | |
| 4 | repository.workspace = true | |
| 5 | description = "Proc macros for rust-analyzer." | |
| 6 | ||
| 7 | authors.workspace = true | |
| 8 | edition.workspace = true | |
| 9 | license.workspace = true | |
| 10 | rust-version.workspace = true | |
| 11 | ||
| 12 | [lib] | |
| 13 | proc-macro = true | |
| 14 | ||
| 15 | [dependencies] | |
| 16 | proc-macro2 = "1" | |
| 17 | quote = "1" | |
| 18 | syn = "2.0.9" | |
| 19 | synstructure = "0.13.0" |
src/tools/rust-analyzer/crates/macros/src/lib.rs created+164| ... | ... | @@ -0,0 +1,164 @@ |
| 1 | //! Proc macros for rust-analyzer. | |
| 2 | ||
| 3 | use quote::{ToTokens, quote}; | |
| 4 | use syn::parse_quote; | |
| 5 | use synstructure::decl_derive; | |
| 6 | ||
| 7 | decl_derive!( | |
| 8 | [TypeFoldable, attributes(type_foldable)] => | |
| 9 | /// Derives `TypeFoldable` for the annotated `struct` or `enum` (`union` is not supported). | |
| 10 | /// | |
| 11 | /// The fold will produce a value of the same struct or enum variant as the input, with | |
| 12 | /// each field respectively folded using the `TypeFoldable` implementation for its type. | |
| 13 | /// However, if a field of a struct or an enum variant is annotated with | |
| 14 | /// `#[type_foldable(identity)]` then that field will retain its incumbent value (and its | |
| 15 | /// type is not required to implement `TypeFoldable`). | |
| 16 | type_foldable_derive | |
| 17 | ); | |
| 18 | decl_derive!( | |
| 19 | [TypeVisitable, attributes(type_visitable)] => | |
| 20 | /// Derives `TypeVisitable` for the annotated `struct` or `enum` (`union` is not supported). | |
| 21 | /// | |
| 22 | /// Each field of the struct or enum variant will be visited in definition order, using the | |
| 23 | /// `TypeVisitable` implementation for its type. However, if a field of a struct or an enum | |
| 24 | /// variant is annotated with `#[type_visitable(ignore)]` then that field will not be | |
| 25 | /// visited (and its type is not required to implement `TypeVisitable`). | |
| 26 | type_visitable_derive | |
| 27 | ); | |
| 28 | ||
| 29 | fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { | |
| 30 | if let syn::Data::Union(_) = s.ast().data { | |
| 31 | panic!("cannot derive on union") | |
| 32 | } | |
| 33 | ||
| 34 | // ignore fields with #[type_visitable(ignore)] | |
| 35 | s.filter(|bi| { | |
| 36 | let mut ignored = false; | |
| 37 | ||
| 38 | bi.ast().attrs.iter().for_each(|attr| { | |
| 39 | if !attr.path().is_ident("type_visitable") { | |
| 40 | return; | |
| 41 | } | |
| 42 | let _ = attr.parse_nested_meta(|nested| { | |
| 43 | if nested.path.is_ident("ignore") { | |
| 44 | ignored = true; | |
| 45 | } | |
| 46 | Ok(()) | |
| 47 | }); | |
| 48 | }); | |
| 49 | ||
| 50 | !ignored | |
| 51 | }); | |
| 52 | ||
| 53 | if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "db") { | |
| 54 | s.add_impl_generic(parse_quote! { 'db }); | |
| 55 | } | |
| 56 | ||
| 57 | s.add_bounds(synstructure::AddBounds::Generics); | |
| 58 | let body_visit = s.each(|bind| { | |
| 59 | quote! { | |
| 60 | match ::rustc_type_ir::VisitorResult::branch( | |
| 61 | ::rustc_type_ir::TypeVisitable::visit_with(#bind, __visitor) | |
| 62 | ) { | |
| 63 | ::core::ops::ControlFlow::Continue(()) => {}, | |
| 64 | ::core::ops::ControlFlow::Break(r) => { | |
| 65 | return ::rustc_type_ir::VisitorResult::from_residual(r); | |
| 66 | }, | |
| 67 | } | |
| 68 | } | |
| 69 | }); | |
| 70 | s.bind_with(|_| synstructure::BindStyle::Move); | |
| 71 | ||
| 72 | s.bound_impl( | |
| 73 | quote!(::rustc_type_ir::TypeVisitable<::hir_ty::next_solver::DbInterner<'db>>), | |
| 74 | quote! { | |
| 75 | fn visit_with<__V: ::rustc_type_ir::TypeVisitor<::hir_ty::next_solver::DbInterner<'db>>>( | |
| 76 | &self, | |
| 77 | __visitor: &mut __V | |
| 78 | ) -> __V::Result { | |
| 79 | match *self { #body_visit } | |
| 80 | <__V::Result as ::rustc_type_ir::VisitorResult>::output() | |
| 81 | } | |
| 82 | }, | |
| 83 | ) | |
| 84 | } | |
| 85 | ||
| 86 | fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { | |
| 87 | if let syn::Data::Union(_) = s.ast().data { | |
| 88 | panic!("cannot derive on union") | |
| 89 | } | |
| 90 | ||
| 91 | if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "db") { | |
| 92 | s.add_impl_generic(parse_quote! { 'db }); | |
| 93 | } | |
| 94 | ||
| 95 | s.add_bounds(synstructure::AddBounds::Generics); | |
| 96 | s.bind_with(|_| synstructure::BindStyle::Move); | |
| 97 | let try_body_fold = s.each_variant(|vi| { | |
| 98 | let bindings = vi.bindings(); | |
| 99 | vi.construct(|_, index| { | |
| 100 | let bind = &bindings[index]; | |
| 101 | ||
| 102 | // retain value of fields with #[type_foldable(identity)] | |
| 103 | if has_ignore_attr(&bind.ast().attrs, "type_foldable", "identity") { | |
| 104 | bind.to_token_stream() | |
| 105 | } else { | |
| 106 | quote! { | |
| 107 | ::rustc_type_ir::TypeFoldable::try_fold_with(#bind, __folder)? | |
| 108 | } | |
| 109 | } | |
| 110 | }) | |
| 111 | }); | |
| 112 | ||
| 113 | let body_fold = s.each_variant(|vi| { | |
| 114 | let bindings = vi.bindings(); | |
| 115 | vi.construct(|_, index| { | |
| 116 | let bind = &bindings[index]; | |
| 117 | ||
| 118 | // retain value of fields with #[type_foldable(identity)] | |
| 119 | if has_ignore_attr(&bind.ast().attrs, "type_foldable", "identity") { | |
| 120 | bind.to_token_stream() | |
| 121 | } else { | |
| 122 | quote! { | |
| 123 | ::rustc_type_ir::TypeFoldable::fold_with(#bind, __folder) | |
| 124 | } | |
| 125 | } | |
| 126 | }) | |
| 127 | }); | |
| 128 | ||
| 129 | s.bound_impl( | |
| 130 | quote!(::rustc_type_ir::TypeFoldable<::hir_ty::next_solver::DbInterner<'db>>), | |
| 131 | quote! { | |
| 132 | fn try_fold_with<__F: ::rustc_type_ir::FallibleTypeFolder<::hir_ty::next_solver::DbInterner<'db>>>( | |
| 133 | self, | |
| 134 | __folder: &mut __F | |
| 135 | ) -> Result<Self, __F::Error> { | |
| 136 | Ok(match self { #try_body_fold }) | |
| 137 | } | |
| 138 | ||
| 139 | fn fold_with<__F: ::rustc_type_ir::TypeFolder<::hir_ty::next_solver::DbInterner<'db>>>( | |
| 140 | self, | |
| 141 | __folder: &mut __F | |
| 142 | ) -> Self { | |
| 143 | match self { #body_fold } | |
| 144 | } | |
| 145 | }, | |
| 146 | ) | |
| 147 | } | |
| 148 | ||
| 149 | fn has_ignore_attr(attrs: &[syn::Attribute], name: &'static str, meta: &'static str) -> bool { | |
| 150 | let mut ignored = false; | |
| 151 | attrs.iter().for_each(|attr| { | |
| 152 | if !attr.path().is_ident(name) { | |
| 153 | return; | |
| 154 | } | |
| 155 | let _ = attr.parse_nested_meta(|nested| { | |
| 156 | if nested.path.is_ident(meta) { | |
| 157 | ignored = true; | |
| 158 | } | |
| 159 | Ok(()) | |
| 160 | }); | |
| 161 | }); | |
| 162 | ||
| 163 | ignored | |
| 164 | } |
src/tools/rust-analyzer/crates/parser/src/grammar/items/consts.rs+17-10| ... | ... | @@ -25,21 +25,28 @@ fn const_or_static(p: &mut Parser<'_>, m: Marker, is_const: bool) { |
| 25 | 25 | } |
| 26 | 26 | |
| 27 | 27 | // FIXME: Recover on statics with generic params/where clause. |
| 28 | if is_const { | |
| 29 | // test generic_const | |
| 30 | // const C<i32>: u32 = 0; | |
| 31 | // impl Foo { | |
| 32 | // const C<'a>: &'a () = &(); | |
| 33 | // } | |
| 34 | generic_params::opt_generic_param_list(p); | |
| 28 | if !is_const && p.at(T![<]) { | |
| 29 | // test_err generic_static | |
| 30 | // static C<i32>: u32 = 0; | |
| 31 | p.error("`static` may not have generic parameters"); | |
| 35 | 32 | } |
| 36 | // test_err generic_static | |
| 37 | // static C<i32>: u32 = 0; | |
| 33 | // test generic_const | |
| 34 | // const C<i32>: u32 = 0; | |
| 35 | // impl Foo { | |
| 36 | // const C<'a>: &'a () = &(); | |
| 37 | // } | |
| 38 | generic_params::opt_generic_param_list(p); | |
| 38 | 39 | |
| 39 | 40 | if p.at(T![:]) { |
| 40 | 41 | types::ascription(p); |
| 42 | } else if is_const { | |
| 43 | // test_err missing_const_type | |
| 44 | // const C = 0; | |
| 45 | p.error("missing type for `const`"); | |
| 41 | 46 | } else { |
| 42 | p.error("missing type for `const` or `static`"); | |
| 47 | // test_err missing_static_type | |
| 48 | // static C = 0; | |
| 49 | p.error("missing type for `static`"); | |
| 43 | 50 | } |
| 44 | 51 | if p.eat(T![=]) { |
| 45 | 52 | expressions::expr(p); |
src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs+8| ... | ... | @@ -824,10 +824,18 @@ mod err { |
| 824 | 824 | run_and_expect_errors("test_data/parser/inline/err/misplaced_label_err.rs"); |
| 825 | 825 | } |
| 826 | 826 | #[test] |
| 827 | fn missing_const_type() { | |
| 828 | run_and_expect_errors("test_data/parser/inline/err/missing_const_type.rs"); | |
| 829 | } | |
| 830 | #[test] | |
| 827 | 831 | fn missing_fn_param_type() { |
| 828 | 832 | run_and_expect_errors("test_data/parser/inline/err/missing_fn_param_type.rs"); |
| 829 | 833 | } |
| 830 | 834 | #[test] |
| 835 | fn missing_static_type() { | |
| 836 | run_and_expect_errors("test_data/parser/inline/err/missing_static_type.rs"); | |
| 837 | } | |
| 838 | #[test] | |
| 831 | 839 | fn path_item_without_excl() { |
| 832 | 840 | run_and_expect_errors("test_data/parser/inline/err/path_item_without_excl.rs"); |
| 833 | 841 | } |
src/tools/rust-analyzer/crates/parser/test_data/parser/err/0044_item_modifiers.rast+1-1| ... | ... | @@ -42,7 +42,7 @@ SOURCE_FILE |
| 42 | 42 | WHITESPACE "\n" |
| 43 | 43 | error 6: expected fn, trait or impl |
| 44 | 44 | error 38: expected a name |
| 45 | error 40: missing type for `const` or `static` | |
| 45 | error 40: missing type for `const` | |
| 46 | 46 | error 40: expected SEMICOLON |
| 47 | 47 | error 44: expected an item |
| 48 | 48 | error 44: expected an item |
src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_static.rast+16-31| ... | ... | @@ -4,39 +4,24 @@ SOURCE_FILE |
| 4 | 4 | WHITESPACE " " |
| 5 | 5 | NAME |
| 6 | 6 | IDENT "C" |
| 7 | ERROR | |
| 8 | L_ANGLE "<" | |
| 9 | ERROR | |
| 10 | PATH | |
| 11 | PATH_SEGMENT | |
| 12 | NAME_REF | |
| 7 | GENERIC_PARAM_LIST | |
| 8 | L_ANGLE "<" | |
| 9 | TYPE_PARAM | |
| 10 | NAME | |
| 13 | 11 | IDENT "i32" |
| 14 | ERROR | |
| 15 | R_ANGLE ">" | |
| 16 | ERROR | |
| 12 | R_ANGLE ">" | |
| 17 | 13 | COLON ":" |
| 18 | WHITESPACE " " | |
| 19 | ERROR | |
| 20 | PATH | |
| 21 | PATH_SEGMENT | |
| 22 | NAME_REF | |
| 23 | IDENT "u32" | |
| 24 | WHITESPACE " " | |
| 25 | ERROR | |
| 14 | WHITESPACE " " | |
| 15 | PATH_TYPE | |
| 16 | PATH | |
| 17 | PATH_SEGMENT | |
| 18 | NAME_REF | |
| 19 | IDENT "u32" | |
| 20 | WHITESPACE " " | |
| 26 | 21 | EQ "=" |
| 27 | WHITESPACE " " | |
| 28 | ERROR | |
| 29 | INT_NUMBER "0" | |
| 30 | ERROR | |
| 22 | WHITESPACE " " | |
| 23 | LITERAL | |
| 24 | INT_NUMBER "0" | |
| 31 | 25 | SEMICOLON ";" |
| 32 | 26 | WHITESPACE "\n" |
| 33 | error 8: missing type for `const` or `static` | |
| 34 | error 8: expected SEMICOLON | |
| 35 | error 8: expected an item | |
| 36 | error 12: expected an item | |
| 37 | error 12: expected an item | |
| 38 | error 13: expected an item | |
| 39 | error 18: expected an item | |
| 40 | error 19: expected an item | |
| 41 | error 21: expected an item | |
| 42 | error 22: expected an item | |
| 27 | error 8: `static` may not have generic parameters |
src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/missing_const_type.rast created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | SOURCE_FILE | |
| 2 | CONST | |
| 3 | CONST_KW "const" | |
| 4 | WHITESPACE " " | |
| 5 | NAME | |
| 6 | IDENT "C" | |
| 7 | WHITESPACE " " | |
| 8 | EQ "=" | |
| 9 | WHITESPACE " " | |
| 10 | LITERAL | |
| 11 | INT_NUMBER "0" | |
| 12 | SEMICOLON ";" | |
| 13 | WHITESPACE "\n" | |
| 14 | error 7: missing type for `const` |
src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/missing_const_type.rs created+1| ... | ... | @@ -0,0 +1 @@ |
| 1 | const C = 0; |
src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/missing_static_type.rast created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | SOURCE_FILE | |
| 2 | STATIC | |
| 3 | STATIC_KW "static" | |
| 4 | WHITESPACE " " | |
| 5 | NAME | |
| 6 | IDENT "C" | |
| 7 | WHITESPACE " " | |
| 8 | EQ "=" | |
| 9 | WHITESPACE " " | |
| 10 | LITERAL | |
| 11 | INT_NUMBER "0" | |
| 12 | SEMICOLON ";" | |
| 13 | WHITESPACE "\n" | |
| 14 | error 8: missing type for `static` |
src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/missing_static_type.rs created+1| ... | ... | @@ -0,0 +1 @@ |
| 1 | static C = 0; |
src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs+5-4| ... | ... | @@ -13,12 +13,12 @@ use serde_derive::Deserialize; |
| 13 | 13 | use serde_json::from_value; |
| 14 | 14 | use span::Edition; |
| 15 | 15 | use stdx::process::spawn_with_streaming_output; |
| 16 | use toolchain::Tool; | |
| 16 | use toolchain::{NO_RUSTUP_AUTO_INSTALL_ENV, Tool}; | |
| 17 | 17 | use triomphe::Arc; |
| 18 | 18 | |
| 19 | use crate::cargo_config_file::make_lockfile_copy; | |
| 20 | use crate::{CfgOverrides, InvocationStrategy}; | |
| 21 | use crate::{ManifestPath, Sysroot}; | |
| 19 | use crate::{ | |
| 20 | CfgOverrides, InvocationStrategy, ManifestPath, Sysroot, cargo_config_file::make_lockfile_copy, | |
| 21 | }; | |
| 22 | 22 | |
| 23 | 23 | pub(crate) const MINIMUM_TOOLCHAIN_VERSION_SUPPORTING_LOCKFILE_PATH: semver::Version = |
| 24 | 24 | semver::Version { |
| ... | ... | @@ -632,6 +632,7 @@ impl FetchMetadata { |
| 632 | 632 | ) -> Self { |
| 633 | 633 | let cargo = sysroot.tool(Tool::Cargo, current_dir, &config.extra_env); |
| 634 | 634 | let mut command = MetadataCommand::new(); |
| 635 | command.env(NO_RUSTUP_AUTO_INSTALL_ENV.0, NO_RUSTUP_AUTO_INSTALL_ENV.1); | |
| 635 | 636 | command.cargo_path(cargo.get_program()); |
| 636 | 637 | cargo.get_envs().for_each(|(var, val)| _ = command.env(var, val.unwrap_or_default())); |
| 637 | 638 | command.manifest_path(cargo_toml.to_path_buf()); |
src/tools/rust-analyzer/crates/project-model/src/workspace.rs+3-2| ... | ... | @@ -16,8 +16,9 @@ use paths::{AbsPath, AbsPathBuf, Utf8PathBuf}; |
| 16 | 16 | use rustc_hash::{FxHashMap, FxHashSet}; |
| 17 | 17 | use semver::Version; |
| 18 | 18 | use span::{Edition, FileId}; |
| 19 | use toolchain::Tool; | |
| 19 | use toolchain::{NO_RUSTUP_AUTO_INSTALL_ENV, Tool}; | |
| 20 | 20 | use tracing::instrument; |
| 21 | use tracing::{debug, error, info}; | |
| 21 | 22 | use triomphe::Arc; |
| 22 | 23 | |
| 23 | 24 | use crate::{ |
| ... | ... | @@ -33,7 +34,6 @@ use crate::{ |
| 33 | 34 | toolchain_info::{QueryConfig, rustc_cfg, target_data, target_tuple, version}, |
| 34 | 35 | utf8_stdout, |
| 35 | 36 | }; |
| 36 | use tracing::{debug, error, info}; | |
| 37 | 37 | |
| 38 | 38 | pub type FileLoader<'a> = &'a mut dyn for<'b> FnMut(&'b AbsPath) -> Option<FileId>; |
| 39 | 39 | |
| ... | ... | @@ -1907,6 +1907,7 @@ fn cargo_target_dir( |
| 1907 | 1907 | ) -> Option<Utf8PathBuf> { |
| 1908 | 1908 | let cargo = sysroot.tool(Tool::Cargo, manifest.parent(), extra_env); |
| 1909 | 1909 | let mut meta = cargo_metadata::MetadataCommand::new(); |
| 1910 | meta.env(NO_RUSTUP_AUTO_INSTALL_ENV.0, NO_RUSTUP_AUTO_INSTALL_ENV.1); | |
| 1910 | 1911 | meta.cargo_path(cargo.get_program()); |
| 1911 | 1912 | meta.manifest_path(manifest); |
| 1912 | 1913 | // `--no-deps` doesn't (over)write lockfiles as it doesn't do any package resolve. |
src/tools/rust-analyzer/crates/query-group-macro/src/queries.rs+2-1| ... | ... | @@ -327,7 +327,8 @@ impl ToTokens for Lookup { |
| 327 | 327 | let wrapper_struct = self.interned_struct_path.to_token_stream(); |
| 328 | 328 | let method = quote! { |
| 329 | 329 | #sig { |
| 330 | #wrapper_struct::ingredient(self).data(self.as_dyn_database(), id.as_id()).0.clone() | |
| 330 | let zalsa = self.zalsa(); | |
| 331 | #wrapper_struct::ingredient(zalsa).data(zalsa, id.as_id()).0.clone() | |
| 331 | 332 | } |
| 332 | 333 | }; |
| 333 | 334 |
src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml+2| ... | ... | @@ -75,6 +75,8 @@ vfs-notify.workspace = true |
| 75 | 75 | vfs.workspace = true |
| 76 | 76 | paths.workspace = true |
| 77 | 77 | |
| 78 | ra-ap-rustc_type_ir.workspace = true | |
| 79 | ||
| 78 | 80 | [target.'cfg(windows)'.dependencies] |
| 79 | 81 | windows-sys = { version = "0.60", features = [ |
| 80 | 82 | "Win32_System_Diagnostics_Debug", |
src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs+35-35| ... | ... | @@ -20,7 +20,6 @@ use hir_def::{ |
| 20 | 20 | expr_store::BodySourceMap, |
| 21 | 21 | hir::{ExprId, PatId}, |
| 22 | 22 | }; |
| 23 | use hir_ty::{Interner, TyExt, TypeFlags}; | |
| 24 | 23 | use ide::{ |
| 25 | 24 | Analysis, AnalysisHost, AnnotationConfig, DiagnosticsConfig, Edition, InlayFieldsToResolve, |
| 26 | 25 | InlayHintsConfig, LineCol, RootDatabase, |
| ... | ... | @@ -36,6 +35,7 @@ use profile::StopWatch; |
| 36 | 35 | use project_model::{CargoConfig, CfgOverrides, ProjectManifest, ProjectWorkspace, RustLibSource}; |
| 37 | 36 | use rayon::prelude::*; |
| 38 | 37 | use rustc_hash::{FxHashMap, FxHashSet}; |
| 38 | use rustc_type_ir::inherent::Ty as _; | |
| 39 | 39 | use syntax::AstNode; |
| 40 | 40 | use vfs::{AbsPathBuf, Vfs, VfsPath}; |
| 41 | 41 | |
| ... | ... | @@ -312,32 +312,37 @@ impl flags::AnalysisStats { |
| 312 | 312 | shuffle(&mut rng, &mut bodies); |
| 313 | 313 | } |
| 314 | 314 | |
| 315 | if !self.skip_lowering { | |
| 316 | self.run_body_lowering(db, &vfs, &bodies, verbosity); | |
| 317 | } | |
| 315 | hir::attach_db(db, || { | |
| 316 | if !self.skip_lowering { | |
| 317 | self.run_body_lowering(db, &vfs, &bodies, verbosity); | |
| 318 | } | |
| 318 | 319 | |
| 319 | if !self.skip_inference { | |
| 320 | self.run_inference(db, &vfs, &bodies, verbosity); | |
| 321 | } | |
| 320 | if !self.skip_inference { | |
| 321 | self.run_inference(db, &vfs, &bodies, verbosity); | |
| 322 | } | |
| 322 | 323 | |
| 323 | if !self.skip_mir_stats { | |
| 324 | self.run_mir_lowering(db, &bodies, verbosity); | |
| 325 | } | |
| 324 | if !self.skip_mir_stats { | |
| 325 | self.run_mir_lowering(db, &bodies, verbosity); | |
| 326 | } | |
| 326 | 327 | |
| 327 | if !self.skip_data_layout { | |
| 328 | self.run_data_layout(db, &adts, verbosity); | |
| 329 | } | |
| 328 | if !self.skip_data_layout { | |
| 329 | self.run_data_layout(db, &adts, verbosity); | |
| 330 | } | |
| 330 | 331 | |
| 331 | if !self.skip_const_eval { | |
| 332 | self.run_const_eval(db, &bodies, verbosity); | |
| 333 | } | |
| 332 | if !self.skip_const_eval { | |
| 333 | self.run_const_eval(db, &bodies, verbosity); | |
| 334 | } | |
| 335 | }); | |
| 336 | ||
| 337 | file_ids.sort(); | |
| 338 | file_ids.dedup(); | |
| 334 | 339 | |
| 335 | 340 | if self.run_all_ide_things { |
| 336 | self.run_ide_things(host.analysis(), file_ids.clone(), db, &vfs, verbosity); | |
| 341 | self.run_ide_things(host.analysis(), &file_ids, db, &vfs, verbosity); | |
| 337 | 342 | } |
| 338 | 343 | |
| 339 | 344 | if self.run_term_search { |
| 340 | self.run_term_search(&workspace, db, &vfs, file_ids, verbosity); | |
| 345 | self.run_term_search(&workspace, db, &vfs, &file_ids, verbosity); | |
| 341 | 346 | } |
| 342 | 347 | |
| 343 | 348 | let db = host.raw_database_mut(); |
| ... | ... | @@ -433,12 +438,13 @@ impl flags::AnalysisStats { |
| 433 | 438 | report_metric("const eval time", const_eval_time.time.as_millis() as u64, "ms"); |
| 434 | 439 | } |
| 435 | 440 | |
| 441 | /// Invariant: `file_ids` must be sorted and deduped before passing into here | |
| 436 | 442 | fn run_term_search( |
| 437 | 443 | &self, |
| 438 | 444 | ws: &ProjectWorkspace, |
| 439 | 445 | db: &RootDatabase, |
| 440 | 446 | vfs: &Vfs, |
| 441 | mut file_ids: Vec<EditionedFileId>, | |
| 447 | file_ids: &[EditionedFileId], | |
| 442 | 448 | verbosity: Verbosity, |
| 443 | 449 | ) { |
| 444 | 450 | let cargo_config = CargoConfig { |
| ... | ... | @@ -456,9 +462,6 @@ impl flags::AnalysisStats { |
| 456 | 462 | _ => ProgressReport::new(file_ids.len()), |
| 457 | 463 | }; |
| 458 | 464 | |
| 459 | file_ids.sort(); | |
| 460 | file_ids.dedup(); | |
| 461 | ||
| 462 | 465 | #[derive(Debug, Default)] |
| 463 | 466 | struct Acc { |
| 464 | 467 | tail_expr_syntax_hits: u64, |
| ... | ... | @@ -472,7 +475,7 @@ impl flags::AnalysisStats { |
| 472 | 475 | bar.tick(); |
| 473 | 476 | let mut sw = self.stop_watch(); |
| 474 | 477 | |
| 475 | for &file_id in &file_ids { | |
| 478 | for &file_id in file_ids { | |
| 476 | 479 | let file_id = file_id.editioned_file_id(db); |
| 477 | 480 | let sema = hir::Semantics::new(db); |
| 478 | 481 | let display_target = match sema.first_crate(file_id.file_id()) { |
| ... | ... | @@ -814,7 +817,7 @@ impl flags::AnalysisStats { |
| 814 | 817 | for (expr_id, _) in body.exprs() { |
| 815 | 818 | let ty = &inference_result[expr_id]; |
| 816 | 819 | num_exprs += 1; |
| 817 | let unknown_or_partial = if ty.is_unknown() { | |
| 820 | let unknown_or_partial = if ty.is_ty_error() { | |
| 818 | 821 | num_exprs_unknown += 1; |
| 819 | 822 | if verbosity.is_spammy() { |
| 820 | 823 | if let Some((path, start, end)) = expr_syntax_range(db, vfs, &sm(), expr_id) |
| ... | ... | @@ -836,8 +839,7 @@ impl flags::AnalysisStats { |
| 836 | 839 | } |
| 837 | 840 | true |
| 838 | 841 | } else { |
| 839 | let is_partially_unknown = | |
| 840 | ty.data(Interner).flags.contains(TypeFlags::HAS_ERROR); | |
| 842 | let is_partially_unknown = ty.references_non_lt_error(); | |
| 841 | 843 | if is_partially_unknown { |
| 842 | 844 | num_exprs_partially_unknown += 1; |
| 843 | 845 | } |
| ... | ... | @@ -919,7 +921,7 @@ impl flags::AnalysisStats { |
| 919 | 921 | for (pat_id, _) in body.pats() { |
| 920 | 922 | let ty = &inference_result[pat_id]; |
| 921 | 923 | num_pats += 1; |
| 922 | let unknown_or_partial = if ty.is_unknown() { | |
| 924 | let unknown_or_partial = if ty.is_ty_error() { | |
| 923 | 925 | num_pats_unknown += 1; |
| 924 | 926 | if verbosity.is_spammy() { |
| 925 | 927 | if let Some((path, start, end)) = pat_syntax_range(db, vfs, &sm(), pat_id) { |
| ... | ... | @@ -940,8 +942,7 @@ impl flags::AnalysisStats { |
| 940 | 942 | } |
| 941 | 943 | true |
| 942 | 944 | } else { |
| 943 | let is_partially_unknown = | |
| 944 | ty.data(Interner).flags.contains(TypeFlags::HAS_ERROR); | |
| 945 | let is_partially_unknown = ty.references_non_lt_error(); | |
| 945 | 946 | if is_partially_unknown { |
| 946 | 947 | num_pats_partially_unknown += 1; |
| 947 | 948 | } |
| ... | ... | @@ -1106,10 +1107,11 @@ impl flags::AnalysisStats { |
| 1106 | 1107 | report_metric("body lowering time", body_lowering_time.time.as_millis() as u64, "ms"); |
| 1107 | 1108 | } |
| 1108 | 1109 | |
| 1110 | /// Invariant: `file_ids` must be sorted and deduped before passing into here | |
| 1109 | 1111 | fn run_ide_things( |
| 1110 | 1112 | &self, |
| 1111 | 1113 | analysis: Analysis, |
| 1112 | mut file_ids: Vec<EditionedFileId>, | |
| 1114 | file_ids: &[EditionedFileId], | |
| 1113 | 1115 | db: &RootDatabase, |
| 1114 | 1116 | vfs: &Vfs, |
| 1115 | 1117 | verbosity: Verbosity, |
| ... | ... | @@ -1121,12 +1123,10 @@ impl flags::AnalysisStats { |
| 1121 | 1123 | _ => ProgressReport::new(len), |
| 1122 | 1124 | }; |
| 1123 | 1125 | |
| 1124 | file_ids.sort(); | |
| 1125 | file_ids.dedup(); | |
| 1126 | 1126 | let mut sw = self.stop_watch(); |
| 1127 | 1127 | |
| 1128 | 1128 | let mut bar = create_bar(); |
| 1129 | for &file_id in &file_ids { | |
| 1129 | for &file_id in file_ids { | |
| 1130 | 1130 | let msg = format!("diagnostics: {}", vfs.file_path(file_id.file_id(db))); |
| 1131 | 1131 | bar.set_message(move || msg.clone()); |
| 1132 | 1132 | _ = analysis.full_diagnostics( |
| ... | ... | @@ -1160,7 +1160,7 @@ impl flags::AnalysisStats { |
| 1160 | 1160 | bar.finish_and_clear(); |
| 1161 | 1161 | |
| 1162 | 1162 | let mut bar = create_bar(); |
| 1163 | for &file_id in &file_ids { | |
| 1163 | for &file_id in file_ids { | |
| 1164 | 1164 | let msg = format!("inlay hints: {}", vfs.file_path(file_id.file_id(db))); |
| 1165 | 1165 | bar.set_message(move || msg.clone()); |
| 1166 | 1166 | _ = analysis.inlay_hints( |
| ... | ... | @@ -1203,7 +1203,7 @@ impl flags::AnalysisStats { |
| 1203 | 1203 | bar.finish_and_clear(); |
| 1204 | 1204 | |
| 1205 | 1205 | let mut bar = create_bar(); |
| 1206 | for &file_id in &file_ids { | |
| 1206 | for &file_id in file_ids { | |
| 1207 | 1207 | let msg = format!("annotations: {}", vfs.file_path(file_id.file_id(db))); |
| 1208 | 1208 | bar.set_message(move || msg.clone()); |
| 1209 | 1209 | analysis |
src/tools/rust-analyzer/crates/rust-analyzer/src/command.rs+23-3| ... | ... | @@ -3,13 +3,15 @@ |
| 3 | 3 | |
| 4 | 4 | use std::{ |
| 5 | 5 | ffi::OsString, |
| 6 | fmt, io, | |
| 6 | fmt, | |
| 7 | io::{self, BufWriter, Write}, | |
| 7 | 8 | marker::PhantomData, |
| 8 | 9 | path::PathBuf, |
| 9 | 10 | process::{ChildStderr, ChildStdout, Command, Stdio}, |
| 10 | 11 | }; |
| 11 | 12 | |
| 12 | 13 | use crossbeam_channel::Sender; |
| 14 | use paths::Utf8PathBuf; | |
| 13 | 15 | use process_wrap::std::{StdChildWrapper, StdCommandWrap}; |
| 14 | 16 | use stdx::process::streaming_output; |
| 15 | 17 | |
| ... | ... | @@ -40,7 +42,7 @@ impl<T: Sized + Send + 'static> CargoActor<T> { |
| 40 | 42 | } |
| 41 | 43 | |
| 42 | 44 | impl<T: Sized + Send + 'static> CargoActor<T> { |
| 43 | fn run(self) -> io::Result<(bool, String)> { | |
| 45 | fn run(self, outfile: Option<Utf8PathBuf>) -> io::Result<(bool, String)> { | |
| 44 | 46 | // We manually read a line at a time, instead of using serde's |
| 45 | 47 | // stream deserializers, because the deserializer cannot recover |
| 46 | 48 | // from an error, resulting in it getting stuck, because we try to |
| ... | ... | @@ -50,6 +52,15 @@ impl<T: Sized + Send + 'static> CargoActor<T> { |
| 50 | 52 | // simply skip a line if it doesn't parse, which just ignores any |
| 51 | 53 | // erroneous output. |
| 52 | 54 | |
| 55 | let mut stdout = outfile.as_ref().and_then(|path| { | |
| 56 | _ = std::fs::create_dir_all(path); | |
| 57 | Some(BufWriter::new(std::fs::File::create(path.join("stdout")).ok()?)) | |
| 58 | }); | |
| 59 | let mut stderr = outfile.as_ref().and_then(|path| { | |
| 60 | _ = std::fs::create_dir_all(path); | |
| 61 | Some(BufWriter::new(std::fs::File::create(path.join("stderr")).ok()?)) | |
| 62 | }); | |
| 63 | ||
| 53 | 64 | let mut stdout_errors = String::new(); |
| 54 | 65 | let mut stderr_errors = String::new(); |
| 55 | 66 | let mut read_at_least_one_stdout_message = false; |
| ... | ... | @@ -67,11 +78,19 @@ impl<T: Sized + Send + 'static> CargoActor<T> { |
| 67 | 78 | self.stdout, |
| 68 | 79 | self.stderr, |
| 69 | 80 | &mut |line| { |
| 81 | if let Some(stdout) = &mut stdout { | |
| 82 | _ = stdout.write_all(line.as_bytes()); | |
| 83 | _ = stdout.write_all(b"\n"); | |
| 84 | } | |
| 70 | 85 | if process_line(line, &mut stdout_errors) { |
| 71 | 86 | read_at_least_one_stdout_message = true; |
| 72 | 87 | } |
| 73 | 88 | }, |
| 74 | 89 | &mut |line| { |
| 90 | if let Some(stderr) = &mut stderr { | |
| 91 | _ = stderr.write_all(line.as_bytes()); | |
| 92 | _ = stderr.write_all(b"\n"); | |
| 93 | } | |
| 75 | 94 | if process_line(line, &mut stderr_errors) { |
| 76 | 95 | read_at_least_one_stderr_message = true; |
| 77 | 96 | } |
| ... | ... | @@ -130,6 +149,7 @@ impl<T: Sized + Send + 'static> CommandHandle<T> { |
| 130 | 149 | mut command: Command, |
| 131 | 150 | parser: impl CargoParser<T>, |
| 132 | 151 | sender: Sender<T>, |
| 152 | out_file: Option<Utf8PathBuf>, | |
| 133 | 153 | ) -> std::io::Result<Self> { |
| 134 | 154 | command.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::null()); |
| 135 | 155 | |
| ... | ... | @@ -150,7 +170,7 @@ impl<T: Sized + Send + 'static> CommandHandle<T> { |
| 150 | 170 | let actor = CargoActor::<T>::new(parser, sender, stdout, stderr); |
| 151 | 171 | let thread = |
| 152 | 172 | stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker, "CommandHandle") |
| 153 | .spawn(move || actor.run()) | |
| 173 | .spawn(move || actor.run(out_file)) | |
| 154 | 174 | .expect("failed to spawn thread"); |
| 155 | 175 | Ok(CommandHandle { program, arguments, current_dir, child, thread, _phantom: PhantomData }) |
| 156 | 176 | } |
src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs+21-10| ... | ... | @@ -895,7 +895,7 @@ config_data! { |
| 895 | 895 | /// [custom test harness](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-harness-field), |
| 896 | 896 | /// they will end up being interpreted as options to |
| 897 | 897 | /// [`rustc`’s built-in test harness (“libtest”)](https://doc.rust-lang.org/rustc/tests/index.html#cli-arguments). |
| 898 | runnables_extraTestBinaryArgs: Vec<String> = vec!["--show-output".to_owned()], | |
| 898 | runnables_extraTestBinaryArgs: Vec<String> = vec!["--nocapture".to_owned()], | |
| 899 | 899 | |
| 900 | 900 | /// Path to the Cargo.toml of the rust compiler workspace, for usage in rustc_private |
| 901 | 901 | /// projects, or "discover" to try to automatically find it if the `rustc-dev` component |
| ... | ... | @@ -1944,8 +1944,9 @@ impl Config { |
| 1944 | 1944 | fn insert_use_config(&self, source_root: Option<SourceRootId>) -> InsertUseConfig { |
| 1945 | 1945 | InsertUseConfig { |
| 1946 | 1946 | granularity: match self.imports_granularity_group(source_root) { |
| 1947 | ImportGranularityDef::Preserve => ImportGranularity::Preserve, | |
| 1948 | ImportGranularityDef::Item => ImportGranularity::Item, | |
| 1947 | ImportGranularityDef::Item | ImportGranularityDef::Preserve => { | |
| 1948 | ImportGranularity::Item | |
| 1949 | } | |
| 1949 | 1950 | ImportGranularityDef::Crate => ImportGranularity::Crate, |
| 1950 | 1951 | ImportGranularityDef::Module => ImportGranularity::Module, |
| 1951 | 1952 | ImportGranularityDef::One => ImportGranularity::One, |
| ... | ... | @@ -3504,13 +3505,23 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json |
| 3504 | 3505 | }, |
| 3505 | 3506 | "ImportGranularityDef" => set! { |
| 3506 | 3507 | "type": "string", |
| 3507 | "enum": ["preserve", "crate", "module", "item", "one"], | |
| 3508 | "enumDescriptions": [ | |
| 3509 | "Do not change the granularity of any imports and preserve the original structure written by the developer.", | |
| 3510 | "Merge imports from the same crate into a single use statement. Conversely, imports from different crates are split into separate statements.", | |
| 3511 | "Merge imports from the same module into a single use statement. Conversely, imports from different modules are split into separate statements.", | |
| 3512 | "Flatten imports so that each has its own use statement.", | |
| 3513 | "Merge all imports into a single use statement as long as they have the same visibility and attributes." | |
| 3508 | "anyOf": [ | |
| 3509 | { | |
| 3510 | "enum": ["crate", "module", "item", "one"], | |
| 3511 | "enumDescriptions": [ | |
| 3512 | "Merge imports from the same crate into a single use statement. Conversely, imports from different crates are split into separate statements.", | |
| 3513 | "Merge imports from the same module into a single use statement. Conversely, imports from different modules are split into separate statements.", | |
| 3514 | "Flatten imports so that each has its own use statement.", | |
| 3515 | "Merge all imports into a single use statement as long as they have the same visibility and attributes." | |
| 3516 | ], | |
| 3517 | }, | |
| 3518 | { | |
| 3519 | "enum": ["preserve"], | |
| 3520 | "enumDescriptions": [ | |
| 3521 | "Deprecated - unless `enforceGranularity` is `true`, the style of the current file is preferred over this setting. Behaves like `item`.", | |
| 3522 | ], | |
| 3523 | "deprecated": true, | |
| 3524 | } | |
| 3514 | 3525 | ], |
| 3515 | 3526 | }, |
| 3516 | 3527 | "ImportPrefixDef" => set! { |
src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs+1-1| ... | ... | @@ -67,7 +67,7 @@ impl DiscoverCommand { |
| 67 | 67 | cmd.args(args); |
| 68 | 68 | |
| 69 | 69 | Ok(DiscoverHandle { |
| 70 | _handle: CommandHandle::spawn(cmd, DiscoverProjectParser, self.sender.clone())?, | |
| 70 | _handle: CommandHandle::spawn(cmd, DiscoverProjectParser, self.sender.clone(), None)?, | |
| 71 | 71 | span: info_span!("discover_command").entered(), |
| 72 | 72 | }) |
| 73 | 73 | } |
src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs+16-1| ... | ... | @@ -423,7 +423,21 @@ impl FlycheckActor { |
| 423 | 423 | |
| 424 | 424 | tracing::debug!(?command, "will restart flycheck"); |
| 425 | 425 | let (sender, receiver) = unbounded(); |
| 426 | match CommandHandle::spawn(command, CargoCheckParser, sender) { | |
| 426 | match CommandHandle::spawn( | |
| 427 | command, | |
| 428 | CargoCheckParser, | |
| 429 | sender, | |
| 430 | match &self.config { | |
| 431 | FlycheckConfig::CargoCommand { options, .. } => Some( | |
| 432 | options | |
| 433 | .target_dir | |
| 434 | .as_deref() | |
| 435 | .unwrap_or("target".as_ref()) | |
| 436 | .join(format!("rust-analyzer/flycheck{}", self.id)), | |
| 437 | ), | |
| 438 | _ => None, | |
| 439 | }, | |
| 440 | ) { | |
| 427 | 441 | Ok(command_handle) => { |
| 428 | 442 | tracing::debug!(command = formatted_command, "did restart flycheck"); |
| 429 | 443 | self.command_handle = Some(command_handle); |
| ... | ... | @@ -622,6 +636,7 @@ impl FlycheckActor { |
| 622 | 636 | { |
| 623 | 637 | cmd.env("RUSTUP_TOOLCHAIN", AsRef::<std::path::Path>::as_ref(sysroot_root)); |
| 624 | 638 | } |
| 639 | cmd.env("CARGO_LOG", "cargo::core::compiler::fingerprint=info"); | |
| 625 | 640 | cmd.arg(command); |
| 626 | 641 | |
| 627 | 642 | match scope { |
src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs+2| ... | ... | @@ -9,6 +9,8 @@ |
| 9 | 9 | //! The `cli` submodule implements some batch-processing analysis, primarily as |
| 10 | 10 | //! a debugging aid. |
| 11 | 11 | |
| 12 | extern crate ra_ap_rustc_type_ir as rustc_type_ir; | |
| 13 | ||
| 12 | 14 | /// Any toolchain less than this version will likely not work with rust-analyzer built from this revision. |
| 13 | 15 | pub const MINIMUM_SUPPORTED_TOOLCHAIN_VERSION: semver::Version = semver::Version { |
| 14 | 16 | major: 1, |
src/tools/rust-analyzer/crates/rust-analyzer/src/test_runner.rs+6-1| ... | ... | @@ -136,7 +136,12 @@ impl CargoTestHandle { |
| 136 | 136 | } |
| 137 | 137 | |
| 138 | 138 | Ok(Self { |
| 139 | _handle: CommandHandle::spawn(cmd, CargoTestOutputParser::new(&test_target), sender)?, | |
| 139 | _handle: CommandHandle::spawn( | |
| 140 | cmd, | |
| 141 | CargoTestOutputParser::new(&test_target), | |
| 142 | sender, | |
| 143 | None, | |
| 144 | )?, | |
| 140 | 145 | }) |
| 141 | 146 | } |
| 142 | 147 | } |
src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs+2-2| ... | ... | @@ -256,7 +256,7 @@ fn main() {} |
| 256 | 256 | { |
| 257 | 257 | "args": { |
| 258 | 258 | "cargoArgs": ["test", "--package", "foo", "--test", "spam"], |
| 259 | "executableArgs": ["test_eggs", "--exact", "--show-output"], | |
| 259 | "executableArgs": ["test_eggs", "--exact", "--nocapture"], | |
| 260 | 260 | "overrideCargo": null, |
| 261 | 261 | "cwd": server.path().join("foo"), |
| 262 | 262 | "workspaceRoot": server.path().join("foo") |
| ... | ... | @@ -289,7 +289,7 @@ fn main() {} |
| 289 | 289 | ], |
| 290 | 290 | "executableArgs": [ |
| 291 | 291 | "", |
| 292 | "--show-output" | |
| 292 | "--nocapture" | |
| 293 | 293 | ] |
| 294 | 294 | }, |
| 295 | 295 | "kind": "cargo", |
src/tools/rust-analyzer/crates/span/src/hygiene.rs+73-24| ... | ... | @@ -67,6 +67,16 @@ const _: () = { |
| 67 | 67 | self.parent.hash(state); |
| 68 | 68 | } |
| 69 | 69 | } |
| 70 | ||
| 71 | impl zalsa_::HasJar for SyntaxContext { | |
| 72 | type Jar = zalsa_struct_::JarImpl<SyntaxContext>; | |
| 73 | const KIND: zalsa_::JarKind = zalsa_::JarKind::Struct; | |
| 74 | } | |
| 75 | ||
| 76 | zalsa_::register_jar! { | |
| 77 | zalsa_::ErasedJar::erase::<SyntaxContext>() | |
| 78 | } | |
| 79 | ||
| 70 | 80 | /// Key to use during hash lookups. Each field is some type that implements `Lookup<T>` |
| 71 | 81 | /// for the owned type. This permits interning with an `&str` when a `String` is required and so forth. |
| 72 | 82 | #[derive(Hash)] |
| ... | ... | @@ -98,21 +108,38 @@ const _: () = { |
| 98 | 108 | salsa::plumbing::Location { file: file!(), line: line!() }; |
| 99 | 109 | const DEBUG_NAME: &'static str = "SyntaxContextData"; |
| 100 | 110 | const REVISIONS: std::num::NonZeroUsize = std::num::NonZeroUsize::MAX; |
| 111 | const PERSIST: bool = false; | |
| 112 | ||
| 101 | 113 | type Fields<'a> = SyntaxContextData; |
| 102 | 114 | type Struct<'a> = SyntaxContext; |
| 103 | } | |
| 104 | impl SyntaxContext { | |
| 105 | pub fn ingredient<Db>(db: &Db) -> &zalsa_struct_::IngredientImpl<Self> | |
| 115 | ||
| 116 | fn serialize<S>(_: &Self::Fields<'_>, _: S) -> Result<S::Ok, S::Error> | |
| 106 | 117 | where |
| 107 | Db: ?Sized + zalsa_::Database, | |
| 118 | S: zalsa_::serde::Serializer, | |
| 119 | { | |
| 120 | unimplemented!("attempted to serialize value that set `PERSIST` to false") | |
| 121 | } | |
| 122 | ||
| 123 | fn deserialize<'de, D>(_: D) -> Result<Self::Fields<'static>, D::Error> | |
| 124 | where | |
| 125 | D: zalsa_::serde::Deserializer<'de>, | |
| 108 | 126 | { |
| 127 | unimplemented!("attempted to deserialize value that cannot set `PERSIST` to false"); | |
| 128 | } | |
| 129 | } | |
| 130 | ||
| 131 | impl SyntaxContext { | |
| 132 | pub fn ingredient(zalsa: &zalsa_::Zalsa) -> &zalsa_struct_::IngredientImpl<Self> { | |
| 109 | 133 | static CACHE: zalsa_::IngredientCache<zalsa_struct_::IngredientImpl<SyntaxContext>> = |
| 110 | 134 | zalsa_::IngredientCache::new(); |
| 111 | CACHE.get_or_create(db.zalsa(), || { | |
| 112 | db.zalsa() | |
| 113 | .lookup_jar_by_type::<zalsa_struct_::JarImpl<SyntaxContext>>() | |
| 114 | .get_or_create() | |
| 115 | }) | |
| 135 | ||
| 136 | // SAFETY: `lookup_jar_by_type` returns a valid ingredient index, and the only | |
| 137 | // ingredient created by our jar is the struct ingredient. | |
| 138 | unsafe { | |
| 139 | CACHE.get_or_create(zalsa, || { | |
| 140 | zalsa.lookup_jar_by_type::<zalsa_struct_::JarImpl<SyntaxContext>>() | |
| 141 | }) | |
| 142 | } | |
| 116 | 143 | } |
| 117 | 144 | } |
| 118 | 145 | impl zalsa_::AsId for SyntaxContext { |
| ... | ... | @@ -132,13 +159,14 @@ const _: () = { |
| 132 | 159 | impl zalsa_::SalsaStructInDb for SyntaxContext { |
| 133 | 160 | type MemoIngredientMap = salsa::plumbing::MemoIngredientSingletonIndex; |
| 134 | 161 | |
| 135 | fn lookup_or_create_ingredient_index( | |
| 136 | zalsa: &salsa::plumbing::Zalsa, | |
| 137 | ) -> salsa::plumbing::IngredientIndices { | |
| 138 | zalsa | |
| 139 | .lookup_jar_by_type::<zalsa_struct_::JarImpl<SyntaxContext>>() | |
| 140 | .get_or_create() | |
| 141 | .into() | |
| 162 | fn lookup_ingredient_index(aux: &zalsa_::Zalsa) -> salsa::plumbing::IngredientIndices { | |
| 163 | aux.lookup_jar_by_type::<zalsa_struct_::JarImpl<SyntaxContext>>().into() | |
| 164 | } | |
| 165 | ||
| 166 | fn entries(zalsa: &zalsa_::Zalsa) -> impl Iterator<Item = zalsa_::DatabaseKeyIndex> + '_ { | |
| 167 | let _ingredient_index = | |
| 168 | zalsa.lookup_jar_by_type::<zalsa_struct_::JarImpl<SyntaxContext>>(); | |
| 169 | <SyntaxContext>::ingredient(zalsa).entries(zalsa).map(|entry| entry.key()) | |
| 142 | 170 | } |
| 143 | 171 | |
| 144 | 172 | #[inline] |
| ... | ... | @@ -149,6 +177,18 @@ const _: () = { |
| 149 | 177 | None |
| 150 | 178 | } |
| 151 | 179 | } |
| 180 | ||
| 181 | #[inline] | |
| 182 | unsafe fn memo_table( | |
| 183 | zalsa: &zalsa_::Zalsa, | |
| 184 | id: zalsa_::Id, | |
| 185 | current_revision: zalsa_::Revision, | |
| 186 | ) -> zalsa_::MemoTableWithTypes<'_> { | |
| 187 | // SAFETY: Guaranteed by caller. | |
| 188 | unsafe { | |
| 189 | zalsa.table().memos::<zalsa_struct_::Value<SyntaxContext>>(id, current_revision) | |
| 190 | } | |
| 191 | } | |
| 152 | 192 | } |
| 153 | 193 | |
| 154 | 194 | unsafe impl salsa::plumbing::Update for SyntaxContext { |
| ... | ... | @@ -184,8 +224,11 @@ const _: () = { |
| 184 | 224 | Edition: zalsa_::interned::HashEqLike<T2>, |
| 185 | 225 | SyntaxContext: zalsa_::interned::HashEqLike<T3>, |
| 186 | 226 | { |
| 187 | SyntaxContext::ingredient(db).intern( | |
| 188 | db.as_dyn_database(), | |
| 227 | let (zalsa, zalsa_local) = db.zalsas(); | |
| 228 | ||
| 229 | SyntaxContext::ingredient(zalsa).intern( | |
| 230 | zalsa, | |
| 231 | zalsa_local, | |
| 189 | 232 | StructKey::<'db>( |
| 190 | 233 | outer_expn, |
| 191 | 234 | outer_transparency, |
| ... | ... | @@ -216,7 +259,8 @@ const _: () = { |
| 216 | 259 | Db: ?Sized + zalsa_::Database, |
| 217 | 260 | { |
| 218 | 261 | let id = self.as_salsa_id()?; |
| 219 | let fields = SyntaxContext::ingredient(db).data(db.as_dyn_database(), id); | |
| 262 | let zalsa = db.zalsa(); | |
| 263 | let fields = SyntaxContext::ingredient(zalsa).data(zalsa, id); | |
| 220 | 264 | fields.outer_expn |
| 221 | 265 | } |
| 222 | 266 | |
| ... | ... | @@ -225,7 +269,8 @@ const _: () = { |
| 225 | 269 | Db: ?Sized + zalsa_::Database, |
| 226 | 270 | { |
| 227 | 271 | let Some(id) = self.as_salsa_id() else { return Transparency::Opaque }; |
| 228 | let fields = SyntaxContext::ingredient(db).data(db.as_dyn_database(), id); | |
| 272 | let zalsa = db.zalsa(); | |
| 273 | let fields = SyntaxContext::ingredient(zalsa).data(zalsa, id); | |
| 229 | 274 | fields.outer_transparency |
| 230 | 275 | } |
| 231 | 276 | |
| ... | ... | @@ -235,7 +280,8 @@ const _: () = { |
| 235 | 280 | { |
| 236 | 281 | match self.as_salsa_id() { |
| 237 | 282 | Some(id) => { |
| 238 | let fields = SyntaxContext::ingredient(db).data(db.as_dyn_database(), id); | |
| 283 | let zalsa = db.zalsa(); | |
| 284 | let fields = SyntaxContext::ingredient(zalsa).data(zalsa, id); | |
| 239 | 285 | fields.edition |
| 240 | 286 | } |
| 241 | 287 | None => Edition::from_u32(SyntaxContext::MAX_ID - self.into_u32()), |
| ... | ... | @@ -248,7 +294,8 @@ const _: () = { |
| 248 | 294 | { |
| 249 | 295 | match self.as_salsa_id() { |
| 250 | 296 | Some(id) => { |
| 251 | let fields = SyntaxContext::ingredient(db).data(db.as_dyn_database(), id); | |
| 297 | let zalsa = db.zalsa(); | |
| 298 | let fields = SyntaxContext::ingredient(zalsa).data(zalsa, id); | |
| 252 | 299 | fields.parent |
| 253 | 300 | } |
| 254 | 301 | None => self, |
| ... | ... | @@ -262,7 +309,8 @@ const _: () = { |
| 262 | 309 | { |
| 263 | 310 | match self.as_salsa_id() { |
| 264 | 311 | Some(id) => { |
| 265 | let fields = SyntaxContext::ingredient(db).data(db.as_dyn_database(), id); | |
| 312 | let zalsa = db.zalsa(); | |
| 313 | let fields = SyntaxContext::ingredient(zalsa).data(zalsa, id); | |
| 266 | 314 | fields.opaque |
| 267 | 315 | } |
| 268 | 316 | None => self, |
| ... | ... | @@ -276,7 +324,8 @@ const _: () = { |
| 276 | 324 | { |
| 277 | 325 | match self.as_salsa_id() { |
| 278 | 326 | Some(id) => { |
| 279 | let fields = SyntaxContext::ingredient(db).data(db.as_dyn_database(), id); | |
| 327 | let zalsa = db.zalsa(); | |
| 328 | let fields = SyntaxContext::ingredient(zalsa).data(zalsa, id); | |
| 280 | 329 | fields.opaque_and_semitransparent |
| 281 | 330 | } |
| 282 | 331 | None => self, |
src/tools/rust-analyzer/crates/stdx/src/thread.rs-1| ... | ... | @@ -101,7 +101,6 @@ impl<T> Drop for JoinHandle<T> { |
| 101 | 101 | } |
| 102 | 102 | } |
| 103 | 103 | |
| 104 | #[expect(clippy::min_ident_chars, reason = "trait impl")] | |
| 105 | 104 | impl<T> fmt::Debug for JoinHandle<T> { |
| 106 | 105 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 107 | 106 | f.pad("JoinHandle { .. }") |
src/tools/rust-analyzer/crates/syntax/src/ast.rs+3-1| ... | ... | @@ -29,7 +29,9 @@ pub use self::{ |
| 29 | 29 | SlicePatComponents, StructKind, TypeBoundKind, TypeOrConstParam, VisibilityKind, |
| 30 | 30 | }, |
| 31 | 31 | operators::{ArithOp, BinaryOp, CmpOp, LogicOp, Ordering, RangeOp, UnaryOp}, |
| 32 | token_ext::{CommentKind, CommentPlacement, CommentShape, IsString, QuoteOffsets, Radix}, | |
| 32 | token_ext::{ | |
| 33 | AnyString, CommentKind, CommentPlacement, CommentShape, IsString, QuoteOffsets, Radix, | |
| 34 | }, | |
| 33 | 35 | traits::{ |
| 34 | 36 | AttrDocCommentIter, DocCommentIter, HasArgList, HasAttrs, HasDocComments, HasGenericArgs, |
| 35 | 37 | HasGenericParams, HasLoopBody, HasModuleItem, HasName, HasTypeBounds, HasVisibility, |
src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs+84-10| ... | ... | @@ -151,10 +151,10 @@ impl QuoteOffsets { |
| 151 | 151 | } |
| 152 | 152 | |
| 153 | 153 | pub trait IsString: AstToken { |
| 154 | const RAW_PREFIX: &'static str; | |
| 155 | fn unescape(s: &str, callback: impl FnMut(Range<usize>, Result<char, EscapeError>)); | |
| 154 | fn raw_prefix(&self) -> &'static str; | |
| 155 | fn unescape(&self, s: &str, callback: impl FnMut(Range<usize>, Result<char, EscapeError>)); | |
| 156 | 156 | fn is_raw(&self) -> bool { |
| 157 | self.text().starts_with(Self::RAW_PREFIX) | |
| 157 | self.text().starts_with(self.raw_prefix()) | |
| 158 | 158 | } |
| 159 | 159 | fn quote_offsets(&self) -> Option<QuoteOffsets> { |
| 160 | 160 | let text = self.text(); |
| ... | ... | @@ -187,7 +187,7 @@ pub trait IsString: AstToken { |
| 187 | 187 | let text = &self.text()[text_range_no_quotes - start]; |
| 188 | 188 | let offset = text_range_no_quotes.start() - start; |
| 189 | 189 | |
| 190 | Self::unescape(text, &mut |range: Range<usize>, unescaped_char| { | |
| 190 | self.unescape(text, &mut |range: Range<usize>, unescaped_char| { | |
| 191 | 191 | if let Some((s, e)) = range.start.try_into().ok().zip(range.end.try_into().ok()) { |
| 192 | 192 | cb(TextRange::new(s, e) + offset, unescaped_char); |
| 193 | 193 | } |
| ... | ... | @@ -204,8 +204,10 @@ pub trait IsString: AstToken { |
| 204 | 204 | } |
| 205 | 205 | |
| 206 | 206 | impl IsString for ast::String { |
| 207 | const RAW_PREFIX: &'static str = "r"; | |
| 208 | fn unescape(s: &str, cb: impl FnMut(Range<usize>, Result<char, EscapeError>)) { | |
| 207 | fn raw_prefix(&self) -> &'static str { | |
| 208 | "r" | |
| 209 | } | |
| 210 | fn unescape(&self, s: &str, cb: impl FnMut(Range<usize>, Result<char, EscapeError>)) { | |
| 209 | 211 | unescape_str(s, cb) |
| 210 | 212 | } |
| 211 | 213 | } |
| ... | ... | @@ -246,8 +248,10 @@ impl ast::String { |
| 246 | 248 | } |
| 247 | 249 | |
| 248 | 250 | impl IsString for ast::ByteString { |
| 249 | const RAW_PREFIX: &'static str = "br"; | |
| 250 | fn unescape(s: &str, mut callback: impl FnMut(Range<usize>, Result<char, EscapeError>)) { | |
| 251 | fn raw_prefix(&self) -> &'static str { | |
| 252 | "br" | |
| 253 | } | |
| 254 | fn unescape(&self, s: &str, mut callback: impl FnMut(Range<usize>, Result<char, EscapeError>)) { | |
| 251 | 255 | unescape_byte_str(s, |range, res| callback(range, res.map(char::from))) |
| 252 | 256 | } |
| 253 | 257 | } |
| ... | ... | @@ -288,10 +292,12 @@ impl ast::ByteString { |
| 288 | 292 | } |
| 289 | 293 | |
| 290 | 294 | impl IsString for ast::CString { |
| 291 | const RAW_PREFIX: &'static str = "cr"; | |
| 295 | fn raw_prefix(&self) -> &'static str { | |
| 296 | "cr" | |
| 297 | } | |
| 292 | 298 | // NOTE: This method should only be used for highlighting ranges. The unescaped |
| 293 | 299 | // char/byte is not used. For simplicity, we return an arbitrary placeholder char. |
| 294 | fn unescape(s: &str, mut callback: impl FnMut(Range<usize>, Result<char, EscapeError>)) { | |
| 300 | fn unescape(&self, s: &str, mut callback: impl FnMut(Range<usize>, Result<char, EscapeError>)) { | |
| 295 | 301 | unescape_c_str(s, |range, _res| callback(range, Ok('_'))) |
| 296 | 302 | } |
| 297 | 303 | } |
| ... | ... | @@ -465,6 +471,74 @@ impl ast::Byte { |
| 465 | 471 | } |
| 466 | 472 | } |
| 467 | 473 | |
| 474 | pub enum AnyString { | |
| 475 | ByteString(ast::ByteString), | |
| 476 | CString(ast::CString), | |
| 477 | String(ast::String), | |
| 478 | } | |
| 479 | ||
| 480 | impl AnyString { | |
| 481 | pub fn value(&self) -> Result<Cow<'_, str>, EscapeError> { | |
| 482 | fn from_utf8(s: Cow<'_, [u8]>) -> Result<Cow<'_, str>, EscapeError> { | |
| 483 | match s { | |
| 484 | Cow::Borrowed(s) => str::from_utf8(s) | |
| 485 | .map_err(|_| EscapeError::NonAsciiCharInByte) | |
| 486 | .map(Cow::Borrowed), | |
| 487 | Cow::Owned(s) => String::from_utf8(s) | |
| 488 | .map_err(|_| EscapeError::NonAsciiCharInByte) | |
| 489 | .map(Cow::Owned), | |
| 490 | } | |
| 491 | } | |
| 492 | ||
| 493 | match self { | |
| 494 | AnyString::String(s) => s.value(), | |
| 495 | AnyString::ByteString(s) => s.value().and_then(from_utf8), | |
| 496 | AnyString::CString(s) => s.value().and_then(from_utf8), | |
| 497 | } | |
| 498 | } | |
| 499 | } | |
| 500 | ||
| 501 | impl ast::AstToken for AnyString { | |
| 502 | fn can_cast(kind: crate::SyntaxKind) -> bool { | |
| 503 | ast::String::can_cast(kind) | |
| 504 | || ast::ByteString::can_cast(kind) | |
| 505 | || ast::CString::can_cast(kind) | |
| 506 | } | |
| 507 | ||
| 508 | fn cast(syntax: crate::SyntaxToken) -> Option<Self> { | |
| 509 | ast::String::cast(syntax.clone()) | |
| 510 | .map(Self::String) | |
| 511 | .or_else(|| ast::ByteString::cast(syntax.clone()).map(Self::ByteString)) | |
| 512 | .or_else(|| ast::CString::cast(syntax).map(Self::CString)) | |
| 513 | } | |
| 514 | ||
| 515 | fn syntax(&self) -> &crate::SyntaxToken { | |
| 516 | match self { | |
| 517 | Self::ByteString(it) => it.syntax(), | |
| 518 | Self::CString(it) => it.syntax(), | |
| 519 | Self::String(it) => it.syntax(), | |
| 520 | } | |
| 521 | } | |
| 522 | } | |
| 523 | ||
| 524 | impl IsString for AnyString { | |
| 525 | fn raw_prefix(&self) -> &'static str { | |
| 526 | match self { | |
| 527 | AnyString::ByteString(s) => s.raw_prefix(), | |
| 528 | AnyString::CString(s) => s.raw_prefix(), | |
| 529 | AnyString::String(s) => s.raw_prefix(), | |
| 530 | } | |
| 531 | } | |
| 532 | ||
| 533 | fn unescape(&self, s: &str, callback: impl FnMut(Range<usize>, Result<char, EscapeError>)) { | |
| 534 | match self { | |
| 535 | AnyString::ByteString(it) => it.unescape(s, callback), | |
| 536 | AnyString::CString(it) => it.unescape(s, callback), | |
| 537 | AnyString::String(it) => it.unescape(s, callback), | |
| 538 | } | |
| 539 | } | |
| 540 | } | |
| 541 | ||
| 468 | 542 | #[cfg(test)] |
| 469 | 543 | mod tests { |
| 470 | 544 | use rustc_apfloat::ieee::Quad as f128; |
src/tools/rust-analyzer/crates/toolchain/src/lib.rs+4| ... | ... | @@ -71,6 +71,9 @@ impl Tool { |
| 71 | 71 | } |
| 72 | 72 | } |
| 73 | 73 | |
| 74 | // Prevent rustup from automatically installing toolchains, see https://github.com/rust-lang/rust-analyzer/issues/20719. | |
| 75 | pub const NO_RUSTUP_AUTO_INSTALL_ENV: (&str, &str) = ("RUSTUP_AUTO_INSTALL", "0"); | |
| 76 | ||
| 74 | 77 | #[allow(clippy::disallowed_types)] /* generic parameter allows for FxHashMap */ |
| 75 | 78 | pub fn command<H>( |
| 76 | 79 | cmd: impl AsRef<OsStr>, |
| ... | ... | @@ -81,6 +84,7 @@ pub fn command<H>( |
| 81 | 84 | #[allow(clippy::disallowed_methods)] |
| 82 | 85 | let mut cmd = Command::new(cmd); |
| 83 | 86 | cmd.current_dir(working_directory); |
| 87 | cmd.env(NO_RUSTUP_AUTO_INSTALL_ENV.0, NO_RUSTUP_AUTO_INSTALL_ENV.1); | |
| 84 | 88 | for env in extra_env { |
| 85 | 89 | match env { |
| 86 | 90 | (key, Some(val)) => cmd.env(key, val), |
src/tools/rust-analyzer/docs/book/src/configuration.md+6-1| ... | ... | @@ -13,7 +13,7 @@ Vim](./other_editors.md#coc-rust-analyzer) provide `rust-analyzer` specific conf |
| 13 | 13 | UIs. Others may require you to know a bit more about the interaction |
| 14 | 14 | with `rust-analyzer`. |
| 15 | 15 | |
| 16 | For the later category, it might help to know that the initial | |
| 16 | For the latter category, it might help to know that the initial | |
| 17 | 17 | configuration is specified as a value of the `initializationOptions` |
| 18 | 18 | field of the [`InitializeParams` message, in the LSP |
| 19 | 19 | protocol](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#initialize). |
| ... | ... | @@ -46,6 +46,11 @@ To verify which configuration is actually used by `rust-analyzer`, set |
| 46 | 46 | config-related messages. Logs should show both the JSON that |
| 47 | 47 | `rust-analyzer` sees as well as the updated config. |
| 48 | 48 | |
| 49 | (Work in progress:) It is also possible to place configuration in a | |
| 50 | `rust-analyzer.toml` file. It should be located in the project root or in your | |
| 51 | user configuration directory (e.g. `~/.config/rust-analyzer/`). This is a work in | |
| 52 | progress, many configuration options aren't supported yet. | |
| 53 | ||
| 49 | 54 | This is the list of config options `rust-analyzer` supports: |
| 50 | 55 | |
| 51 | 56 | {{#include configuration_generated.md}} |
src/tools/rust-analyzer/docs/book/src/configuration_generated.md+1-1| ... | ... | @@ -1323,7 +1323,7 @@ tests or binaries. For example, it may be `--release`. |
| 1323 | 1323 | Default: |
| 1324 | 1324 | ```json |
| 1325 | 1325 | [ |
| 1326 | "--show-output" | |
| 1326 | "--nocapture" | |
| 1327 | 1327 | ] |
| 1328 | 1328 | ``` |
| 1329 | 1329 |
src/tools/rust-analyzer/docs/book/src/contributing/guide.md+1-1| ... | ... | @@ -235,7 +235,7 @@ of type `V`. Queries come in two basic varieties: |
| 235 | 235 | intelligently) when we can re-use these memoized values and when we have to |
| 236 | 236 | recompute them. |
| 237 | 237 | |
| 238 | For further discussion, its important to understand one bit of "fairly | |
| 238 | For further discussion, it's important to understand one bit of "fairly | |
| 239 | 239 | intelligently". Suppose we have two functions, `f1` and `f2`, and one input, |
| 240 | 240 | `z`. We call `f1(X)` which in turn calls `f2(Y)` which inspects `i(Z)`. `i(Z)` |
| 241 | 241 | returns some value `V1`, `f2` uses that and returns `R1`, `f1` uses that and |
src/tools/rust-analyzer/docs/book/src/contributing/lsp-extensions.md+11-11| ... | ... | @@ -455,7 +455,7 @@ interface TestItem { |
| 455 | 455 | // A human readable name for this test |
| 456 | 456 | label: string; |
| 457 | 457 | // The kind of this test item. Based on the kind, |
| 458 | 	// an icon is chosen by the editor. | |
| 458 | // an icon is chosen by the editor. | |
| 459 | 459 | kind: "package" | "module" | "test"; |
| 460 | 460 | // True if this test may have children not available eagerly |
| 461 | 461 | canResolveChildren: boolean; |
| ... | ... | @@ -467,7 +467,7 @@ interface TestItem { |
| 467 | 467 | // like debugging, this field is useful. |
| 468 | 468 | // Note that this field includes some information about label and location as well, but |
| 469 | 469 | // those exist just for keeping things in sync with other methods of running runnables |
| 470 | // (for example using one consistent name in the vscode's launch.json) so for any propose | |
| 470 | // (for example using one consistent name in the vscode's launch.json) so for any purpose | |
| 471 | 471 | // other than running tests this field should not be used. |
| 472 | 472 | runnable?: Runnable | undefined; |
| 473 | 473 | }; |
| ... | ... | @@ -475,11 +475,11 @@ interface TestItem { |
| 475 | 475 | interface DiscoverTestResults { |
| 476 | 476 | // The discovered tests. |
| 477 | 477 | tests: TestItem[]; |
| 478 | // For each test which its id is in this list, the response | |
| 478 | // For each test whose id is in this list, the response | |
| 479 | 479 | // contains all tests that are children of this test, and |
| 480 | 480 | // client should remove old tests not included in the response. |
| 481 | 481 | scope: string[] | undefined; |
| 482 | // For each file which its uri is in this list, the response | |
| 482 | // For each file whose uri is in this list, the response | |
| 483 | 483 | // contains all tests that are located in this file, and |
| 484 | 484 | // client should remove old tests not included in the response. |
| 485 | 485 | scopeFile: lc.TextDocumentIdentifier[] | undefined; |
| ... | ... | @@ -491,7 +491,7 @@ interface DiscoverTestResults { |
| 491 | 491 | **Notification:** `DiscoverTestResults` |
| 492 | 492 | |
| 493 | 493 | This notification is sent from the server to the client when the |
| 494 | server detect changes in the existing tests. The `DiscoverTestResults` is | |
| 494 | server detects changes in the existing tests. The `DiscoverTestResults` is | |
| 495 | 495 | the same as the one in `experimental/discoverTest` response. |
| 496 | 496 | |
| 497 | 497 | **Method:** `experimental/runTest` |
| ... | ... | @@ -527,7 +527,7 @@ after this. |
| 527 | 527 | |
| 528 | 528 | This notification is sent from the client to the server when the user is no longer |
| 529 | 529 | interested in the test results. The server should clean up its resources and send |
| 530 | a `experimental/endRunTest` when is done. | |
| 530 | a `experimental/endRunTest` when it is done. | |
| 531 | 531 | |
| 532 | 532 | **Method:** `experimental/changeTestState` |
| 533 | 533 | |
| ... | ... | @@ -648,8 +648,8 @@ interface ServerStatusParams { |
| 648 | 648 | ``` |
| 649 | 649 | |
| 650 | 650 | This notification is sent from server to client. |
| 651 | The client can use it to display *persistent* status to the user (in modline). | |
| 652 | It is similar to the `showMessage`, but is intended for stares rather than point-in-time events. | |
| 651 | The client can use it to display *persistent* status to the user (in the mode line). | |
| 652 | It is similar to the `showMessage`, but is intended for status rather than point-in-time events. | |
| 653 | 653 | |
| 654 | 654 | Note that this functionality is intended primarily to inform the end user about the state of the server. |
| 655 | 655 | In particular, it's valid for the client to completely ignore this extension. |
| ... | ... | @@ -1070,13 +1070,13 @@ export interface RecursiveMemoryLayoutNode = { |
| 1070 | 1070 | size: number; |
| 1071 | 1071 | /// Alignment of the type in bytes |
| 1072 | 1072 | alignment: number; |
| 1073 | /// Offset of the type relative to its parent (or 0 if its the root) | |
| 1073 | /// Offset of the type relative to its parent (or 0 if it's the root) | |
| 1074 | 1074 | offset: number; |
| 1075 | /// Index of the node's parent (or -1 if its the root) | |
| 1075 | /// Index of the node's parent (or -1 if it's the root) | |
| 1076 | 1076 | parent_idx: number; |
| 1077 | 1077 | /// Index of the node's children (or -1 if it does not have children) |
| 1078 | 1078 | children_start: number; |
| 1079 | /// Number of child nodes (unspecified it does not have children) | |
| 1079 | /// Number of child nodes (unspecified if it does not have children) | |
| 1080 | 1080 | children_len: number; |
| 1081 | 1081 | }; |
| 1082 | 1082 |
src/tools/rust-analyzer/docs/book/src/contributing/syntax.md+1-1| ... | ... | @@ -192,7 +192,7 @@ Modeling this with immutable trees is possible, but annoying. |
| 192 | 192 | |
| 193 | 193 | A function green tree is not super-convenient to use. |
| 194 | 194 | The biggest problem is accessing parents (there are no parent pointers!). |
| 195 | But there are also "identify" issues. | |
| 195 | But there are also "identity" issues. | |
| 196 | 196 | Let's say you want to write a code which builds a list of expressions in a file: `fn collect_expressions(file: GreenNode) -> HashSet<GreenNode>`. |
| 197 | 197 | For the input like |
| 198 | 198 |
src/tools/rust-analyzer/editors/code/package.json+25-14| ... | ... | @@ -2009,19 +2009,30 @@ |
| 2009 | 2009 | "markdownDescription": "How imports should be grouped into use statements.", |
| 2010 | 2010 | "default": "crate", |
| 2011 | 2011 | "type": "string", |
| 2012 | "enum": [ | |
| 2013 | "preserve", | |
| 2014 | "crate", | |
| 2015 | "module", | |
| 2016 | "item", | |
| 2017 | "one" | |
| 2018 | ], | |
| 2019 | "enumDescriptions": [ | |
| 2020 | "Do not change the granularity of any imports and preserve the original structure written by the developer.", | |
| 2021 | "Merge imports from the same crate into a single use statement. Conversely, imports from different crates are split into separate statements.", | |
| 2022 | "Merge imports from the same module into a single use statement. Conversely, imports from different modules are split into separate statements.", | |
| 2023 | "Flatten imports so that each has its own use statement.", | |
| 2024 | "Merge all imports into a single use statement as long as they have the same visibility and attributes." | |
| 2012 | "anyOf": [ | |
| 2013 | { | |
| 2014 | "enum": [ | |
| 2015 | "crate", | |
| 2016 | "module", | |
| 2017 | "item", | |
| 2018 | "one" | |
| 2019 | ], | |
| 2020 | "enumDescriptions": [ | |
| 2021 | "Merge imports from the same crate into a single use statement. Conversely, imports from different crates are split into separate statements.", | |
| 2022 | "Merge imports from the same module into a single use statement. Conversely, imports from different modules are split into separate statements.", | |
| 2023 | "Flatten imports so that each has its own use statement.", | |
| 2024 | "Merge all imports into a single use statement as long as they have the same visibility and attributes." | |
| 2025 | ] | |
| 2026 | }, | |
| 2027 | { | |
| 2028 | "enum": [ | |
| 2029 | "preserve" | |
| 2030 | ], | |
| 2031 | "enumDescriptions": [ | |
| 2032 | "Deprecated - unless `enforceGranularity` is `true`, the style of the current file is preferred over this setting. Behaves like `item`." | |
| 2033 | ], | |
| 2034 | "deprecated": true | |
| 2035 | } | |
| 2025 | 2036 | ] |
| 2026 | 2037 | } |
| 2027 | 2038 | } |
| ... | ... | @@ -2789,7 +2800,7 @@ |
| 2789 | 2800 | "rust-analyzer.runnables.extraTestBinaryArgs": { |
| 2790 | 2801 | "markdownDescription": "Additional arguments to be passed through Cargo to launched tests, benchmarks, or\ndoc-tests.\n\nUnless the launched target uses a\n[custom test harness](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-harness-field),\nthey will end up being interpreted as options to\n[`rustc`’s built-in test harness (“libtest”)](https://doc.rust-lang.org/rustc/tests/index.html#cli-arguments).", |
| 2791 | 2802 | "default": [ |
| 2792 | "--show-output" | |
| 2803 | "--nocapture" | |
| 2793 | 2804 | ], |
| 2794 | 2805 | "type": "array", |
| 2795 | 2806 | "items": { |
src/tools/rust-analyzer/josh-sync.toml+4| ... | ... | @@ -1,2 +1,6 @@ |
| 1 | 1 | repo = "rust-analyzer" |
| 2 | 2 | filter = ":rev(55d9a533b309119c8acd13061581b43ae8840823:prefix=src/tools/rust-analyzer):/src/tools/rust-analyzer" |
| 3 | ||
| 4 | [[post-pull]] | |
| 5 | cmd = ["cargo", "fmt"] | |
| 6 | commit-message = "Format code" |
src/tools/rust-analyzer/rust-version+1-1| ... | ... | @@ -1 +1 @@ |
| 1 | f957826bff7a68b267ce75b1ea56352aed0cca0a | |
| 1 | fb24b04b096a980bffd80154f6aba22fd07cb3d9 |
src/tools/rust-analyzer/xtask/src/install.rs+2-2| ... | ... | @@ -145,12 +145,12 @@ fn install_server(sh: &Shell, opts: ServerOpt) -> anyhow::Result<()> { |
| 145 | 145 | ); |
| 146 | 146 | |
| 147 | 147 | if let Some(train_crate) = opts.pgo { |
| 148 | let target = detect_target(sh); | |
| 148 | 149 | let build_cmd = cmd!( |
| 149 | 150 | sh, |
| 150 | "cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --profile={profile} --locked --features force-always-assert {features...}" | |
| 151 | "cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --target {target} --profile={profile} --locked --features force-always-assert {features...}" | |
| 151 | 152 | ); |
| 152 | 153 | |
| 153 | let target = detect_target(sh); | |
| 154 | 154 | let profile = crate::pgo::gather_pgo_profile(sh, build_cmd, &target, train_crate)?; |
| 155 | 155 | install_cmd = crate::pgo::apply_pgo_to_cmd(install_cmd, &profile); |
| 156 | 156 | } |
src/tools/rust-analyzer/xtask/src/pgo.rs+17-8| ... | ... | @@ -53,14 +53,23 @@ pub(crate) fn gather_pgo_profile<'a>( |
| 53 | 53 | |
| 54 | 54 | // Merge profiles into a single file |
| 55 | 55 | let merged_profile = pgo_dir.join("merged.profdata"); |
| 56 | let profile_files = std::fs::read_dir(pgo_dir)?.filter_map(|entry| { | |
| 57 | let entry = entry.ok()?; | |
| 58 | if entry.path().extension() == Some(OsStr::new("profraw")) { | |
| 59 | Some(entry.path().to_str().unwrap().to_owned()) | |
| 60 | } else { | |
| 61 | None | |
| 62 | } | |
| 63 | }); | |
| 56 | let profile_files = std::fs::read_dir(pgo_dir)? | |
| 57 | .filter_map(|entry| { | |
| 58 | let entry = entry.ok()?; | |
| 59 | if entry.path().extension() == Some(OsStr::new("profraw")) { | |
| 60 | Some(entry.path().to_str().unwrap().to_owned()) | |
| 61 | } else { | |
| 62 | None | |
| 63 | } | |
| 64 | }) | |
| 65 | .collect::<Vec<_>>(); | |
| 66 | ||
| 67 | if profile_files.is_empty() { | |
| 68 | anyhow::bail!( | |
| 69 | "rust-analyzer analysis-stats produced no pgo files. This is a bug in rust-analyzer; please file an issue." | |
| 70 | ); | |
| 71 | } | |
| 72 | ||
| 64 | 73 | cmd!(sh, "{llvm_profdata} merge {profile_files...} -o {merged_profile}").run().context( |
| 65 | 74 | "cannot merge PGO profiles. Do you have the rustup `llvm-tools` component installed?", |
| 66 | 75 | )?; |