diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index 5a29379ba4818..17dea1ba4cdec 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -259,9 +259,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
name = "chalk-derive"
-version = "0.103.0"
+version = "0.104.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb4899682de915ca7c0b025bdd0a3d34c75fe12184122fda6805a7baddaa293c"
+checksum = "9ea9b1e80910f66ae87c772247591432032ef3f6a67367ff17f8343db05beafa"
dependencies = [
"proc-macro2",
"quote",
@@ -271,43 +271,14 @@ dependencies = [
[[package]]
name = "chalk-ir"
-version = "0.103.0"
+version = "0.104.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90a37d2ab99352b4caca135061e7b4ac67024b648c28ed0b787feec4bea4caed"
+checksum = "7047a516de16226cd17344d41a319d0ea1064bf9e60bd612ab341ab4a34bbfa8"
dependencies = [
"bitflags 2.9.1",
"chalk-derive",
]
-[[package]]
-name = "chalk-recursive"
-version = "0.103.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c855be60e646664bc37c2496d3dc81ca5ef60520930e5e0f0057a0575aff6c19"
-dependencies = [
- "chalk-derive",
- "chalk-ir",
- "chalk-solve",
- "rustc-hash 1.1.0",
- "tracing",
-]
-
-[[package]]
-name = "chalk-solve"
-version = "0.103.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "477ac6cdfd2013e9f93b09b036c2b607a67b2e728f4777b8422d55a79e9e3a34"
-dependencies = [
- "chalk-derive",
- "chalk-ir",
- "ena",
- "indexmap",
- "itertools 0.12.1",
- "petgraph",
- "rustc-hash 1.1.0",
- "tracing",
-]
-
[[package]]
name = "clap"
version = "4.5.42"
@@ -445,6 +416,17 @@ dependencies = [
"powerfmt",
]
+[[package]]
+name = "derive-where"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "510c292c8cf384b1a340b816a9a6cf2599eb8f566a44949024af88418000c50b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "derive_arbitrary"
version = "1.4.1"
@@ -563,12 +545,6 @@ dependencies = [
"windows-sys 0.59.0",
]
-[[package]]
-name = "fixedbitset"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
-
[[package]]
name = "flate2"
version = "1.1.2"
@@ -695,7 +671,8 @@ dependencies = [
"hir-ty",
"indexmap",
"intern",
- "itertools 0.14.0",
+ "itertools",
+ "ra-ap-rustc_type_ir",
"rustc-hash 2.1.1",
"smallvec",
"span",
@@ -705,6 +682,8 @@ dependencies = [
"test-fixture",
"test-utils",
"tracing",
+ "tracing-subscriber",
+ "tracing-tree",
"triomphe",
"tt",
]
@@ -725,7 +704,7 @@ dependencies = [
"hir-expand",
"indexmap",
"intern",
- "itertools 0.14.0",
+ "itertools",
"la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"mbe",
"query-group-macro",
@@ -759,7 +738,7 @@ dependencies = [
"either",
"expect-test",
"intern",
- "itertools 0.14.0",
+ "itertools",
"mbe",
"parser",
"query-group-macro",
@@ -785,8 +764,6 @@ dependencies = [
"bitflags 2.9.1",
"chalk-derive",
"chalk-ir",
- "chalk-recursive",
- "chalk-solve",
"cov-mark",
"either",
"ena",
@@ -795,14 +772,17 @@ dependencies = [
"hir-expand",
"indexmap",
"intern",
- "itertools 0.14.0",
+ "itertools",
"la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"oorandom",
"project-model",
"query-group-macro",
"ra-ap-rustc_abi",
+ "ra-ap-rustc_ast_ir",
"ra-ap-rustc_index",
+ "ra-ap-rustc_next_trait_solver",
"ra-ap-rustc_pattern_analysis",
+ "ra-ap-rustc_type_ir",
"rustc-hash 2.1.1",
"rustc_apfloat",
"salsa",
@@ -932,7 +912,7 @@ dependencies = [
"ide-db",
"ide-diagnostics",
"ide-ssr",
- "itertools 0.14.0",
+ "itertools",
"nohash-hasher",
"oorandom",
"profile",
@@ -960,7 +940,7 @@ dependencies = [
"expect-test",
"hir",
"ide-db",
- "itertools 0.14.0",
+ "itertools",
"smallvec",
"stdx",
"syntax",
@@ -978,7 +958,7 @@ dependencies = [
"expect-test",
"hir",
"ide-db",
- "itertools 0.14.0",
+ "itertools",
"smallvec",
"stdx",
"syntax",
@@ -1001,7 +981,7 @@ dependencies = [
"fst",
"hir",
"indexmap",
- "itertools 0.14.0",
+ "itertools",
"line-index 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr",
"nohash-hasher",
@@ -1032,7 +1012,7 @@ dependencies = [
"expect-test",
"hir",
"ide-db",
- "itertools 0.14.0",
+ "itertools",
"paths",
"serde_json",
"stdx",
@@ -1050,7 +1030,7 @@ dependencies = [
"expect-test",
"hir",
"ide-db",
- "itertools 0.14.0",
+ "itertools",
"parser",
"syntax",
"test-fixture",
@@ -1129,15 +1109,6 @@ dependencies = [
"memoffset",
]
-[[package]]
-name = "itertools"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
-dependencies = [
- "either",
-]
-
[[package]]
name = "itertools"
version = "0.14.0"
@@ -1266,7 +1237,7 @@ dependencies = [
"hir-expand",
"ide-db",
"intern",
- "itertools 0.14.0",
+ "itertools",
"proc-macro-api",
"project-model",
"span",
@@ -1294,7 +1265,7 @@ checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
[[package]]
name = "lsp-server"
-version = "0.7.8"
+version = "0.7.9"
dependencies = [
"anyhow",
"crossbeam-channel",
@@ -1310,9 +1281,9 @@ dependencies = [
[[package]]
name = "lsp-server"
-version = "0.7.8"
+version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9462c4dc73e17f971ec1f171d44bfffb72e65a130117233388a0ebc7ec5656f9"
+checksum = "7d6ada348dbc2703cbe7637b2dda05cff84d3da2819c24abcb305dd613e0ba2e"
dependencies = [
"crossbeam-channel",
"log",
@@ -1343,7 +1314,7 @@ dependencies = [
"expect-test",
"intern",
"parser",
- "ra-ap-rustc_lexer 0.123.0",
+ "ra-ap-rustc_lexer",
"rustc-hash 2.1.1",
"smallvec",
"span",
@@ -1579,8 +1550,8 @@ dependencies = [
"drop_bomb",
"edition",
"expect-test",
- "ra-ap-rustc_lexer 0.123.0",
- "rustc-literal-escaper",
+ "ra-ap-rustc_lexer",
+ "rustc-literal-escaper 0.0.4",
"stdx",
"tracing",
]
@@ -1623,16 +1594,6 @@ dependencies = [
"libc",
]
-[[package]]
-name = "petgraph"
-version = "0.6.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
-dependencies = [
- "fixedbitset",
- "indexmap",
-]
-
[[package]]
name = "pin-project-lite"
version = "0.2.16"
@@ -1700,7 +1661,7 @@ dependencies = [
"object",
"paths",
"proc-macro-test",
- "ra-ap-rustc_lexer 0.123.0",
+ "ra-ap-rustc_lexer",
"span",
"syntax-bridge",
"temp-dir",
@@ -1767,7 +1728,7 @@ dependencies = [
"cfg",
"expect-test",
"intern",
- "itertools 0.14.0",
+ "itertools",
"la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"paths",
"rustc-hash 2.1.1",
@@ -1846,9 +1807,9 @@ dependencies = [
[[package]]
name = "ra-ap-rustc_abi"
-version = "0.123.0"
+version = "0.132.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f18c877575c259d127072e9bfc41d985202262fb4d6bfdae3d1252147c2562c2"
+checksum = "597bb303548ddcca3a2eb05af254508aaf39cf334d4350bb5da51de1eb728859"
dependencies = [
"bitflags 2.9.1",
"ra-ap-rustc_hashes",
@@ -1856,20 +1817,26 @@ dependencies = [
"tracing",
]
+[[package]]
+name = "ra-ap-rustc_ast_ir"
+version = "0.132.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78982b4e4432ee4b938e47bb5c8f1a5a5a88c27c782f193aefcc12a3250bd2e2"
+
[[package]]
name = "ra-ap-rustc_hashes"
-version = "0.123.0"
+version = "0.132.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2439ed1df3472443133b66949f81080dff88089b42f825761455463709ee1cad"
+checksum = "2f7f33a422f724cc1ab43972cdd76a556b17fc256f301d23be620adfc8351df7"
dependencies = [
"rustc-stable-hash",
]
[[package]]
name = "ra-ap-rustc_index"
-version = "0.123.0"
+version = "0.132.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57a24fe0be21be1f8ebc21dcb40129214fb4cefb0f2753f3d46b6dbe656a1a45"
+checksum = "8a6006023c8be18c3ac225d69c1b42f55b3f597f3db03fb40764b4cf1454fd13"
dependencies = [
"ra-ap-rustc_index_macros",
"smallvec",
@@ -1877,9 +1844,9 @@ dependencies = [
[[package]]
name = "ra-ap-rustc_index_macros"
-version = "0.123.0"
+version = "0.132.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "844a27ddcad0116facae2df8e741fd788662cf93dc13029cd864f2b8013b81f9"
+checksum = "9217c29f7fcc30d07ed13a62262144f665410ef1460202599ae924f9ae47ad78"
dependencies = [
"proc-macro2",
"quote",
@@ -1888,9 +1855,9 @@ dependencies = [
[[package]]
name = "ra-ap-rustc_lexer"
-version = "0.121.0"
+version = "0.132.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22944e31fb91e9b3e75bcbc91e37d958b8c0825a6160927f2856831d2ce83b36"
+checksum = "573ad4f5da620e8ba1849d8862866abd7bc765c3d81cb2488c3ecbef33ce2c69"
dependencies = [
"memchr",
"unicode-properties",
@@ -1898,31 +1865,33 @@ dependencies = [
]
[[package]]
-name = "ra-ap-rustc_lexer"
-version = "0.123.0"
+name = "ra-ap-rustc_next_trait_solver"
+version = "0.132.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b734cfcb577d09877799a22742f1bd398be6c00bc428d9de56d48d11ece5771"
+checksum = "0d42b095b99e988aeb94622ae62ebda4b7de55d7d98846eec352b8a5a2b8a858"
dependencies = [
- "memchr",
- "unicode-properties",
- "unicode-xid",
+ "derive-where",
+ "ra-ap-rustc_index",
+ "ra-ap-rustc_type_ir",
+ "ra-ap-rustc_type_ir_macros",
+ "tracing",
]
[[package]]
name = "ra-ap-rustc_parse_format"
-version = "0.121.0"
+version = "0.132.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81057891bc2063ad9e353f29462fbc47a0f5072560af34428ae9313aaa5e9d97"
+checksum = "a21b4e95cb45f840c172493c05f5b9471cf44adb2eccf95d76a0d76e88007870"
dependencies = [
- "ra-ap-rustc_lexer 0.121.0",
- "rustc-literal-escaper",
+ "ra-ap-rustc_lexer",
+ "rustc-literal-escaper 0.0.5",
]
[[package]]
name = "ra-ap-rustc_pattern_analysis"
-version = "0.123.0"
+version = "0.132.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75b0ee1f059b9dea0818c6c7267478926eee95ba4c7dcf89c8db32fa165d3904"
+checksum = "b6aeacef1248066f7b67e7296ef135eeab6446d5d2a5c7f02b8d7b747b41e39b"
dependencies = [
"ra-ap-rustc_index",
"rustc-hash 2.1.1",
@@ -1931,6 +1900,38 @@ dependencies = [
"tracing",
]
+[[package]]
+name = "ra-ap-rustc_type_ir"
+version = "0.132.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52e35ee9e052406035016b8e6d54ca202bc39ccba1702780b33b2d5fb10d1da8"
+dependencies = [
+ "arrayvec",
+ "bitflags 2.9.1",
+ "derive-where",
+ "ena",
+ "indexmap",
+ "ra-ap-rustc_ast_ir",
+ "ra-ap-rustc_index",
+ "ra-ap-rustc_type_ir_macros",
+ "rustc-hash 2.1.1",
+ "smallvec",
+ "thin-vec",
+ "tracing",
+]
+
+[[package]]
+name = "ra-ap-rustc_type_ir_macros"
+version = "0.132.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b934c956b0c88df8176803416b69d85d2c392a69c8aa794a4c338f22c527d38"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
[[package]]
name = "rayon"
version = "1.10.0"
@@ -2005,9 +2006,9 @@ dependencies = [
"ide-ssr",
"indexmap",
"intern",
- "itertools 0.14.0",
+ "itertools",
"load-cargo",
- "lsp-server 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lsp-server 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)",
"lsp-types",
"memchr",
"mimalloc",
@@ -2073,6 +2074,12 @@ version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab03008eb631b703dd16978282ae36c73282e7922fe101a4bd072a40ecea7b8b"
+[[package]]
+name = "rustc-literal-escaper"
+version = "0.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4ee29da77c5a54f42697493cd4c9b9f31b74df666a6c04dfc4fde77abe0438b"
+
[[package]]
name = "rustc-stable-hash"
version = "0.1.2"
@@ -2337,7 +2344,7 @@ dependencies = [
"backtrace",
"crossbeam-channel",
"crossbeam-utils",
- "itertools 0.14.0",
+ "itertools",
"jod-thread",
"libc",
"miow",
@@ -2373,12 +2380,12 @@ version = "0.0.0"
dependencies = [
"either",
"expect-test",
- "itertools 0.14.0",
+ "itertools",
"parser",
"rayon",
"rowan",
"rustc-hash 2.1.1",
- "rustc-literal-escaper",
+ "rustc-literal-escaper 0.0.4",
"rustc_apfloat",
"smol_str",
"stdx",
@@ -2671,9 +2678,9 @@ dependencies = [
[[package]]
name = "tracing-subscriber"
-version = "0.3.19"
+version = "0.3.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
+checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5"
dependencies = [
"sharded-slab",
"thread_local",
@@ -2706,7 +2713,7 @@ version = "0.0.0"
dependencies = [
"arrayvec",
"intern",
- "ra-ap-rustc_lexer 0.123.0",
+ "ra-ap-rustc_lexer",
"stdx",
"text-size",
]
@@ -3222,7 +3229,7 @@ dependencies = [
"edition",
"either",
"flate2",
- "itertools 0.14.0",
+ "itertools",
"proc-macro2",
"quote",
"stdx",
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index e7cf0212bf2a8..0401367f78647 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -37,9 +37,7 @@ debug = 2
[patch.'crates-io']
# rowan = { path = "../rowan" }
-# chalk-solve = { path = "../chalk/chalk-solve" }
# chalk-ir = { path = "../chalk/chalk-ir" }
-# chalk-recursive = { path = "../chalk/chalk-recursive" }
# chalk-derive = { path = "../chalk/chalk-derive" }
# line-index = { path = "lib/line-index" }
# la-arena = { path = "lib/la-arena" }
@@ -89,18 +87,21 @@ vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
vfs = { path = "./crates/vfs", version = "0.0.0" }
edition = { path = "./crates/edition", version = "0.0.0" }
-ra-ap-rustc_lexer = { version = "0.123", default-features = false }
-ra-ap-rustc_parse_format = { version = "0.121", default-features = false }
-ra-ap-rustc_index = { version = "0.123", default-features = false }
-ra-ap-rustc_abi = { version = "0.123", default-features = false }
-ra-ap-rustc_pattern_analysis = { version = "0.123", default-features = false }
+ra-ap-rustc_lexer = { version = "0.132", default-features = false }
+ra-ap-rustc_parse_format = { version = "0.132", default-features = false }
+ra-ap-rustc_index = { version = "0.132", default-features = false }
+ra-ap-rustc_abi = { version = "0.132", default-features = false }
+ra-ap-rustc_pattern_analysis = { version = "0.132", default-features = false }
+ra-ap-rustc_ast_ir = { version = "0.132", default-features = false }
+ra-ap-rustc_type_ir = { version = "0.132", default-features = false }
+ra-ap-rustc_next_trait_solver = { version = "0.132", default-features = false }
# local crates that aren't published to crates.io. These should not have versions.
# in-tree crates that are published separately and follow semver. See lib/README.md
line-index = { version = "0.1.2" }
la-arena = { version = "0.3.1" }
-lsp-server = { version = "0.7.8" }
+lsp-server = { version = "0.7.9" }
# non-local crates
anyhow = "1.0.98"
@@ -108,10 +109,8 @@ arrayvec = "0.7.6"
bitflags = "2.9.1"
cargo_metadata = "0.21.0"
camino = "1.1.10"
-chalk-solve = { version = "0.103.0", default-features = false }
-chalk-ir = "0.103.0"
-chalk-recursive = { version = "0.103.0", default-features = false }
-chalk-derive = "0.103.0"
+chalk-ir = "0.104.0"
+chalk-derive = "0.104.0"
crossbeam-channel = "0.5.15"
dissimilar = "1.0.10"
dot = "0.1.4"
@@ -125,11 +124,11 @@ memmap2 = "0.9.5"
nohash-hasher = "0.2.0"
oorandom = "11.1.5"
object = { version = "0.36.7", default-features = false, features = [
- "std",
- "read_core",
- "elf",
- "macho",
- "pe",
+ "std",
+ "read_core",
+ "elf",
+ "macho",
+ "pe",
] }
process-wrap = { version = "8.2.1", features = ["std"] }
pulldown-cmark-to-cmark = "10.0.4"
@@ -139,9 +138,9 @@ rowan = "=0.15.15"
# Ideally we'd not enable the macros feature but unfortunately the `tracked` attribute does not work
# on impls without it
salsa = { version = "0.23.0", default-features = true, features = [
- "rayon",
- "salsa_unstable",
- "macros",
+ "rayon",
+ "salsa_unstable",
+ "macros",
] }
salsa-macros = "0.23.0"
semver = "1.0.26"
@@ -151,22 +150,22 @@ serde_json = "1.0.140"
rustc-hash = "2.1.1"
rustc-literal-escaper = "0.0.4"
smallvec = { version = "1.15.1", features = [
- "const_new",
- "union",
- "const_generics",
+ "const_new",
+ "union",
+ "const_generics",
] }
smol_str = "0.3.2"
temp-dir = "0.1.16"
text-size = "1.1.1"
tracing = "0.1.41"
tracing-tree = "0.4.0"
-tracing-subscriber = { version = "0.3.19", default-features = false, features = [
- "registry",
- "fmt",
- "local-time",
- "std",
- "time",
- "tracing-log",
+tracing-subscriber = { version = "0.3.20", default-features = false, features = [
+ "registry",
+ "fmt",
+ "local-time",
+ "std",
+ "time",
+ "tracing-log",
] }
triomphe = { version = "0.1.14", default-features = false, features = ["std"] }
url = "2.5.4"
@@ -176,7 +175,7 @@ xshell = "0.2.7"
dashmap = { version = "=6.1.0", features = ["raw-api", "inline"] }
# We need to freeze the version of the crate, as it needs to match with dashmap
hashbrown = { version = "0.14.*", features = [
- "inline-more",
+ "inline-more",
], default-features = false }
[workspace.lints.rust]
diff --git a/src/tools/rust-analyzer/README.md b/src/tools/rust-analyzer/README.md
index 4360dea4a113c..cb3a41eec5a62 100644
--- a/src/tools/rust-analyzer/README.md
+++ b/src/tools/rust-analyzer/README.md
@@ -4,8 +4,21 @@
alt="rust-analyzer logo">
-rust-analyzer is a modular compiler frontend for the Rust language.
-It is a part of a larger rls-2.0 effort to create excellent IDE support for Rust.
+rust-analyzer is a language server that provides IDE functionality for
+writing Rust programs. You can use it with any editor that supports
+the [Language Server
+Protocol](https://microsoft.github.io/language-server-protocol/) (VS
+Code, Vim, Emacs, Zed, etc).
+
+rust-analyzer features include go-to-definition, find-all-references,
+refactorings and code completion. rust-analyzer also supports
+integrated formatting (with rustfmt) and integrated diagnostics (with
+rustc and clippy).
+
+Internally, rust-analyzer is structured as a set of libraries for
+analyzing Rust code. See
+[Architecture](https://rust-analyzer.github.io/book/contributing/architecture.html)
+in the manual.
## Quick Start
diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs
index 0bf4fbdfbd691..cac74778a26b0 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/input.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs
@@ -295,8 +295,6 @@ impl CrateDisplayName {
}
}
-pub type TargetLayoutLoadResult = Result, Arc>;
-
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum ReleaseChannel {
Stable,
@@ -929,7 +927,7 @@ mod tests {
use super::{CrateGraphBuilder, CrateName, CrateOrigin, Edition::Edition2018, Env, FileId};
fn empty_ws_data() -> Arc {
- Arc::new(CrateWorkspaceData { data_layout: Err("".into()), toolchain: None })
+ Arc::new(CrateWorkspaceData { target: Err("".into()), toolchain: None })
}
#[test]
diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
index b8eadb608fea5..0e411bcfae60e 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
@@ -6,8 +6,14 @@ pub use salsa_macros;
// FIXME: Rename this crate, base db is non descriptive
mod change;
mod input;
+pub mod target;
-use std::{cell::RefCell, hash::BuildHasherDefault, panic, sync::Once};
+use std::{
+ cell::RefCell,
+ hash::BuildHasherDefault,
+ panic,
+ sync::{Once, atomic::AtomicUsize},
+};
pub use crate::{
change::FileChange,
@@ -15,8 +21,7 @@ pub use crate::{
BuiltCrateData, BuiltDependency, Crate, CrateBuilder, CrateBuilderId, CrateDataBuilder,
CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CratesIdMap, CratesMap,
DependencyBuilder, Env, ExtraCrateData, LangCrateOrigin, ProcMacroLoadingError,
- ProcMacroPaths, ReleaseChannel, SourceRoot, SourceRootId, TargetLayoutLoadResult,
- UniqueCrateData,
+ ProcMacroPaths, ReleaseChannel, SourceRoot, SourceRootId, UniqueCrateData,
},
};
use dashmap::{DashMap, mapref::entry::Entry};
@@ -30,6 +35,8 @@ use triomphe::Arc;
pub use vfs::{AnchoredPath, AnchoredPathBuf, FileId, VfsPath, file_set::FileSet};
pub type FxIndexSet = indexmap::IndexSet;
+pub type FxIndexMap =
+ indexmap::IndexMap>;
#[macro_export]
macro_rules! impl_intern_key {
@@ -326,13 +333,33 @@ pub trait SourceDatabase: salsa::Database {
#[doc(hidden)]
fn crates_map(&self) -> Arc;
+
+ fn nonce_and_revision(&self) -> (Nonce, salsa::Revision);
+}
+
+static NEXT_NONCE: AtomicUsize = AtomicUsize::new(0);
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct Nonce(usize);
+
+impl Default for Nonce {
+ #[inline]
+ fn default() -> Self {
+ Nonce::new()
+ }
+}
+
+impl Nonce {
+ #[inline]
+ pub fn new() -> Nonce {
+ Nonce(NEXT_NONCE.fetch_add(1, std::sync::atomic::Ordering::SeqCst))
+ }
}
/// Crate related data shared by the whole workspace.
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct CrateWorkspaceData {
- // FIXME: Consider removing this, making HirDatabase::target_data_layout an input query
- pub data_layout: TargetLayoutLoadResult,
+ pub target: Result,
/// Toolchain version used to compile the crate.
pub toolchain: Option,
}
diff --git a/src/tools/rust-analyzer/crates/base-db/src/target.rs b/src/tools/rust-analyzer/crates/base-db/src/target.rs
new file mode 100644
index 0000000000000..19d3407bf3c80
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/base-db/src/target.rs
@@ -0,0 +1,50 @@
+//! Information about the target.
+
+use std::fmt;
+
+use triomphe::Arc;
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum Arch {
+ // Only what we need is present here.
+ Wasm32,
+ Wasm64,
+ Other,
+}
+
+#[derive(Debug, PartialEq, Eq, Hash, Clone)]
+pub struct TargetData {
+ pub data_layout: Box,
+ pub arch: Arch,
+}
+
+#[derive(Clone, PartialEq, Eq, Hash)]
+pub struct TargetLoadError(Arc);
+
+impl fmt::Debug for TargetLoadError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Debug::fmt(&self.0, f)
+ }
+}
+
+impl fmt::Display for TargetLoadError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(&self.0, f)
+ }
+}
+
+impl std::error::Error for TargetLoadError {}
+
+impl From for TargetLoadError {
+ fn from(value: String) -> Self {
+ Self(value.into())
+ }
+}
+
+impl From<&str> for TargetLoadError {
+ fn from(value: &str) -> Self {
+ Self(value.into())
+ }
+}
+
+pub type TargetLoadResult = Result;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
index 53250510f875c..b4fcfa11aea74 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
@@ -554,7 +554,6 @@ impl AttrsWithOwner {
AdtId::UnionId(it) => attrs_from_ast_id_loc(db, it),
},
AttrDefId::TraitId(it) => attrs_from_ast_id_loc(db, it),
- AttrDefId::TraitAliasId(it) => attrs_from_ast_id_loc(db, it),
AttrDefId::MacroId(it) => match it {
MacroId::Macro2Id(it) => attrs_from_ast_id_loc(db, it),
MacroId::MacroRulesId(it) => attrs_from_ast_id_loc(db, it),
@@ -659,7 +658,6 @@ impl AttrsWithOwner {
AttrDefId::StaticId(id) => any_has_attrs(db, id),
AttrDefId::ConstId(id) => any_has_attrs(db, id),
AttrDefId::TraitId(id) => any_has_attrs(db, id),
- AttrDefId::TraitAliasId(id) => any_has_attrs(db, id),
AttrDefId::TypeAliasId(id) => any_has_attrs(db, id),
AttrDefId::MacroId(id) => match id {
MacroId::Macro2Id(id) => any_has_attrs(db, id),
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
index c67bb2422ac65..4e1d598623abe 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
@@ -15,8 +15,8 @@ use crate::{
EnumVariantId, EnumVariantLoc, ExternBlockId, ExternBlockLoc, ExternCrateId, ExternCrateLoc,
FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalFieldId, Macro2Id, Macro2Loc,
MacroExpander, MacroId, MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ProcMacroId,
- ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, TraitAliasId, TraitAliasLoc, TraitId,
- TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc, VariantId,
+ ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, TraitId, TraitLoc, TypeAliasId,
+ TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc, VariantId,
attr::{Attrs, AttrsWithOwner},
expr_store::{
Body, BodySourceMap, ExpressionStore, ExpressionStoreSourceMap, scope::ExprScopes,
@@ -28,7 +28,7 @@ use crate::{
nameres::crate_def_map,
signatures::{
ConstSignature, EnumSignature, FunctionSignature, ImplSignature, StaticSignature,
- StructSignature, TraitAliasSignature, TraitSignature, TypeAliasSignature, UnionSignature,
+ StructSignature, TraitSignature, TypeAliasSignature, UnionSignature,
},
tt,
visibility::{self, Visibility},
@@ -69,9 +69,6 @@ pub trait InternDatabase: RootQueryDb {
#[salsa::interned]
fn intern_trait(&self, loc: TraitLoc) -> TraitId;
- #[salsa::interned]
- fn intern_trait_alias(&self, loc: TraitAliasLoc) -> TraitAliasId;
-
#[salsa::interned]
fn intern_type_alias(&self, loc: TypeAliasLoc) -> TypeAliasId;
@@ -152,11 +149,6 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase {
self.function_signature_with_source_map(e).0
}
- #[salsa::tracked]
- fn trait_alias_signature(&self, e: TraitAliasId) -> Arc {
- self.trait_alias_signature_with_source_map(e).0
- }
-
#[salsa::tracked]
fn type_alias_signature(&self, e: TypeAliasId) -> Arc {
self.type_alias_signature_with_source_map(e).0
@@ -210,12 +202,6 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase {
e: FunctionId,
) -> (Arc, Arc);
- #[salsa::invoke(TraitAliasSignature::query)]
- fn trait_alias_signature_with_source_map(
- &self,
- e: TraitAliasId,
- ) -> (Arc, Arc);
-
#[salsa::invoke(TypeAliasSignature::query)]
fn type_alias_signature_with_source_map(
&self,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs
index 20018b61e5cc0..7d3a94b038330 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs
@@ -33,8 +33,8 @@ pub mod keys {
use crate::{
BlockId, ConstId, EnumId, EnumVariantId, ExternBlockId, ExternCrateId, FieldId, FunctionId,
- ImplId, LifetimeParamId, Macro2Id, MacroRulesId, ProcMacroId, StaticId, StructId,
- TraitAliasId, TraitId, TypeAliasId, TypeOrConstParamId, UnionId, UseId,
+ ImplId, LifetimeParamId, Macro2Id, MacroRulesId, ProcMacroId, StaticId, StructId, TraitId,
+ TypeAliasId, TypeOrConstParamId, UnionId, UseId,
dyn_map::{DynMap, Policy},
};
@@ -48,7 +48,6 @@ pub mod keys {
pub const IMPL: Key = Key::new();
pub const EXTERN_BLOCK: Key = Key::new();
pub const TRAIT: Key = Key::new();
- pub const TRAIT_ALIAS: Key = Key::new();
pub const STRUCT: Key = Key::new();
pub const UNION: Key = Key::new();
pub const ENUM: Key = Key::new();
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs
index 3b9281ffb9c12..3794cb18e9360 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs
@@ -33,7 +33,7 @@ use tt::TextRange;
use crate::{
AdtId, BlockId, BlockLoc, DefWithBodyId, FunctionId, GenericDefId, ImplId, MacroId,
- ModuleDefId, ModuleId, TraitAliasId, TraitId, TypeAliasId, UnresolvedMacro,
+ ModuleDefId, ModuleId, TraitId, TypeAliasId, UnresolvedMacro,
builtin_type::BuiltinUint,
db::DefDatabase,
expr_store::{
@@ -252,28 +252,6 @@ pub(crate) fn lower_trait(
(store, source_map, params)
}
-pub(crate) fn lower_trait_alias(
- db: &dyn DefDatabase,
- module: ModuleId,
- trait_syntax: InFile,
- trait_id: TraitAliasId,
-) -> (ExpressionStore, ExpressionStoreSourceMap, Arc) {
- let mut expr_collector = ExprCollector::new(db, module, trait_syntax.file_id);
- let mut collector = generics::GenericParamsCollector::with_self_param(
- &mut expr_collector,
- trait_id.into(),
- trait_syntax.value.type_bound_list(),
- );
- collector.lower(
- &mut expr_collector,
- trait_syntax.value.generic_param_list(),
- trait_syntax.value.where_clause(),
- );
- let params = collector.finish();
- let (store, source_map) = expr_collector.store.finish();
- (store, source_map, params)
-}
-
pub(crate) fn lower_type_alias(
db: &dyn DefDatabase,
module: ModuleId,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs
index b81dcc1fe96df..5b9da3c5e6680 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs
@@ -183,7 +183,6 @@ pub fn print_signature(db: &dyn DefDatabase, owner: GenericDefId, edition: Editi
}
GenericDefId::ImplId(id) => format!("unimplemented {id:?}"),
GenericDefId::StaticId(id) => format!("unimplemented {id:?}"),
- GenericDefId::TraitAliasId(id) => format!("unimplemented {id:?}"),
GenericDefId::TraitId(id) => format!("unimplemented {id:?}"),
GenericDefId::TypeAliasId(id) => format!("unimplemented {id:?}"),
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/signatures.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/signatures.rs
index efb558a775816..b68674c7a74f4 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/signatures.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/signatures.rs
@@ -24,7 +24,6 @@ fn lower_and_print(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expe
ModuleDefId::ConstId(id) => id.into(),
ModuleDefId::StaticId(id) => id.into(),
ModuleDefId::TraitId(id) => id.into(),
- ModuleDefId::TraitAliasId(id) => id.into(),
ModuleDefId::TypeAliasId(id) => id.into(),
ModuleDefId::EnumVariantId(_) => continue,
ModuleDefId::BuiltinType(_) => continue,
@@ -51,7 +50,6 @@ fn lower_and_print(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expe
GenericDefId::ImplId(_id) => (),
GenericDefId::StaticId(_id) => (),
- GenericDefId::TraitAliasId(_id) => (),
GenericDefId::TraitId(_id) => (),
GenericDefId::TypeAliasId(_id) => (),
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs
index faa0ef8ceec7b..e8a6ebcffa0a5 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs
@@ -12,7 +12,7 @@ use intern::sym;
use rustc_hash::FxHashSet;
use crate::{
- ImportPathConfig, ModuleDefId, ModuleId,
+ FindPathConfig, ModuleDefId, ModuleId,
db::DefDatabase,
item_scope::ItemInNs,
nameres::DefMap,
@@ -27,7 +27,7 @@ pub fn find_path(
from: ModuleId,
mut prefix_kind: PrefixKind,
ignore_local_imports: bool,
- mut cfg: ImportPathConfig,
+ mut cfg: FindPathConfig,
) -> Option {
let _p = tracing::info_span!("find_path").entered();
@@ -96,7 +96,7 @@ impl PrefixKind {
struct FindPathCtx<'db> {
db: &'db dyn DefDatabase,
prefix: PrefixKind,
- cfg: ImportPathConfig,
+ cfg: FindPathConfig,
ignore_local_imports: bool,
is_std_item: bool,
from: ModuleId,
@@ -718,7 +718,7 @@ mod tests {
module,
prefix,
ignore_local_imports,
- ImportPathConfig { prefer_no_std, prefer_prelude, prefer_absolute, allow_unstable },
+ FindPathConfig { prefer_no_std, prefer_prelude, prefer_absolute, allow_unstable },
);
format_to!(
res,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/generics.rs
index 94e683cb0f8fa..60cd66bf6b082 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/hir/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/generics.rs
@@ -203,9 +203,6 @@ impl GenericParams {
}
GenericDefId::ImplId(impl_id) => db.impl_signature(impl_id).generic_params.clone(),
GenericDefId::StaticId(_) => EMPTY.clone(),
- GenericDefId::TraitAliasId(trait_alias_id) => {
- db.trait_alias_signature(trait_alias_id).generic_params.clone()
- }
GenericDefId::TraitId(trait_id) => db.trait_signature(trait_id).generic_params.clone(),
GenericDefId::TypeAliasId(type_alias_id) => {
db.type_alias_signature(type_alias_id).generic_params.clone()
@@ -246,10 +243,6 @@ impl GenericParams {
let sig = db.static_signature(id);
(EMPTY.clone(), sig.store.clone())
}
- GenericDefId::TraitAliasId(id) => {
- let sig = db.trait_alias_signature(id);
- (sig.generic_params.clone(), sig.store.clone())
- }
GenericDefId::TraitId(id) => {
let sig = db.trait_signature(id);
(sig.generic_params.clone(), sig.store.clone())
@@ -294,10 +287,6 @@ impl GenericParams {
let (sig, sm) = db.static_signature_with_source_map(id);
(EMPTY.clone(), sig.store.clone(), sm)
}
- GenericDefId::TraitAliasId(id) => {
- let (sig, sm) = db.trait_alias_signature_with_source_map(id);
- (sig.generic_params.clone(), sig.store.clone(), sm)
- }
GenericDefId::TraitId(id) => {
let (sig, sm) = db.trait_signature_with_source_map(id);
(sig.generic_params.clone(), sig.store.clone(), sm)
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
index 8f526d1a2369a..77ed664f4443d 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
@@ -872,7 +872,6 @@ impl PerNs {
PerNs::values(def, v, import.and_then(ImportOrExternCrate::import_or_glob))
}
ModuleDefId::TraitId(_) => PerNs::types(def, v, import),
- ModuleDefId::TraitAliasId(_) => PerNs::types(def, v, import),
ModuleDefId::TypeAliasId(_) => PerNs::types(def, v, import),
ModuleDefId::BuiltinType(_) => PerNs::types(def, v, import),
ModuleDefId::MacroId(mac) => PerNs::macros(mac, v, import),
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
index c633339857492..f35df8d3a7e11 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
@@ -276,7 +276,6 @@ enum SmallModItem {
Static(Static),
Struct(Struct),
Trait(Trait),
- TraitAlias(TraitAlias),
TypeAlias(TypeAlias),
Union(Union),
}
@@ -404,7 +403,6 @@ ModItemId ->
Static in small_data -> ast::Static,
Struct in small_data -> ast::Struct,
Trait in small_data -> ast::Trait,
- TraitAlias in small_data -> ast::TraitAlias,
TypeAlias in small_data -> ast::TypeAlias,
Union in small_data -> ast::Union,
Use in big_data -> ast::Use,
@@ -583,12 +581,6 @@ pub struct Trait {
pub(crate) visibility: RawVisibilityId,
}
-#[derive(Debug, Clone, Eq, PartialEq)]
-pub struct TraitAlias {
- pub name: Name,
- pub(crate) visibility: RawVisibilityId,
-}
-
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Impl {}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
index 032b287cd6a82..454e06399583c 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
@@ -23,7 +23,7 @@ use crate::{
BigModItem, Const, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl,
ImportAlias, Interned, ItemTree, ItemTreeAstId, Macro2, MacroCall, MacroRules, Mod,
ModItemId, ModKind, ModPath, RawAttrs, RawVisibility, RawVisibilityId, SmallModItem,
- Static, Struct, StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind,
+ Static, Struct, StructKind, Trait, TypeAlias, Union, Use, UseTree, UseTreeKind,
VisibilityExplicitness,
},
};
@@ -134,7 +134,6 @@ impl<'a> Ctx<'a> {
ast::Item::Const(ast) => self.lower_const(ast).into(),
ast::Item::Module(ast) => self.lower_module(ast)?.into(),
ast::Item::Trait(ast) => self.lower_trait(ast)?.into(),
- ast::Item::TraitAlias(ast) => self.lower_trait_alias(ast)?.into(),
ast::Item::Impl(ast) => self.lower_impl(ast).into(),
ast::Item::Use(ast) => self.lower_use(ast)?.into(),
ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast)?.into(),
@@ -267,19 +266,6 @@ impl<'a> Ctx<'a> {
Some(ast_id)
}
- fn lower_trait_alias(
- &mut self,
- trait_alias_def: &ast::TraitAlias,
- ) -> Option> {
- let name = trait_alias_def.name()?.as_name();
- let visibility = self.lower_visibility(trait_alias_def);
- let ast_id = self.source_ast_id_map.ast_id(trait_alias_def);
-
- let alias = TraitAlias { name, visibility };
- self.tree.small_data.insert(ast_id.upcast(), SmallModItem::TraitAlias(alias));
- Some(ast_id)
- }
-
fn lower_impl(&mut self, impl_def: &ast::Impl) -> ItemTreeAstId {
let ast_id = self.source_ast_id_map.ast_id(impl_def);
// Note that trait impls don't get implicit `Self` unlike traits, because here they are a
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
index 696174cb072bf..94a6cce3ce33a 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
@@ -8,7 +8,7 @@ use crate::{
item_tree::{
Const, DefDatabase, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl, ItemTree,
Macro2, MacroCall, MacroRules, Mod, ModItemId, ModKind, RawAttrs, RawVisibilityId, Static,
- Struct, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind,
+ Struct, Trait, TypeAlias, Union, Use, UseTree, UseTreeKind,
},
visibility::RawVisibility,
};
@@ -250,12 +250,6 @@ impl Printer<'_> {
self.print_visibility(*visibility);
w!(self, "trait {} {{ ... }}", name.display(self.db, self.edition));
}
- ModItemId::TraitAlias(ast_id) => {
- let TraitAlias { name, visibility } = &self.tree[ast_id];
- self.print_ast_id(ast_id.erase());
- self.print_visibility(*visibility);
- wln!(self, "trait {} = ..;", name.display(self.db, self.edition));
- }
ModItemId::Impl(ast_id) => {
let Impl {} = &self.tree[ast_id];
self.print_ast_id(ast_id.erase());
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
index d431f2140165e..df0705bf90cbc 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
@@ -12,7 +12,7 @@ use crate::{
StaticId, StructId, TraitId, TypeAliasId, UnionId,
db::DefDatabase,
expr_store::path::Path,
- nameres::{assoc::TraitItems, crate_def_map},
+ nameres::{assoc::TraitItems, crate_def_map, crate_local_def_map},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -84,6 +84,15 @@ impl LangItemTarget {
_ => None,
}
}
+
+ pub fn as_adt(self) -> Option {
+ match self {
+ LangItemTarget::Union(it) => Some(it.into()),
+ LangItemTarget::EnumId(it) => Some(it.into()),
+ LangItemTarget::Struct(it) => Some(it.into()),
+ _ => None,
+ }
+ }
}
/// Salsa query. This will look for lang items in a specific crate.
@@ -170,7 +179,19 @@ pub fn lang_item(
{
return Some(target);
}
- start_crate.data(db).dependencies.iter().find_map(|dep| lang_item(db, dep.crate_id, item))
+
+ // Our `CrateGraph` eagerly inserts sysroot dependencies like `core` or `std` into dependencies
+ // even if the target crate has `#![no_std]`, `#![no_core]` or shadowed sysroot dependencies
+ // like `dependencies.std.path = ".."`. So we use `extern_prelude()` instead of
+ // `CrateData.dependencies` here, which has already come through such sysroot complexities
+ // while nameres.
+ //
+ // See https://github.com/rust-lang/rust-analyzer/pull/20475 for details.
+ crate_local_def_map(db, start_crate).local(db).extern_prelude().find_map(|(_, (krate, _))| {
+ // Some crates declares themselves as extern crate like `extern crate self as core`.
+ // Ignore these to prevent cycles.
+ if krate.krate == start_crate { None } else { lang_item(db, krate.krate, item) }
+ })
}
#[derive(Default, Debug, Clone, PartialEq, Eq)]
@@ -277,6 +298,10 @@ impl LangItem {
lang_item(db, start_crate, self).and_then(|t| t.as_trait())
}
+ pub fn resolve_adt(self, db: &dyn DefDatabase, start_crate: Crate) -> Option {
+ lang_item(db, start_crate, self).and_then(|t| t.as_adt())
+ }
+
pub fn resolve_enum(self, db: &dyn DefDatabase, start_crate: Crate) -> Option {
lang_item(db, start_crate, self).and_then(|t| t.as_enum())
}
@@ -383,12 +408,17 @@ language_item_table! {
AsyncFnMut, sym::async_fn_mut, async_fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);
AsyncFnOnce, sym::async_fn_once, async_fn_once_trait, Target::Trait, GenericRequirement::Exact(1);
- AsyncFnOnceOutput, sym::async_fn_once_output,async_fn_once_output, Target::AssocTy, GenericRequirement::None;
+ CallRefFuture, sym::call_ref_future, call_ref_future_ty, Target::AssocTy, GenericRequirement::None;
+ CallOnceFuture, sym::call_once_future, call_once_future_ty, Target::AssocTy, GenericRequirement::None;
+ AsyncFnOnceOutput, sym::async_fn_once_output, async_fn_once_output_ty, Target::AssocTy, GenericRequirement::None;
+
FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None;
Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0);
CoroutineState, sym::coroutine_state, coroutine_state, Target::Enum, GenericRequirement::None;
Coroutine, sym::coroutine, coroutine_trait, Target::Trait, GenericRequirement::Minimum(1);
+ CoroutineReturn, sym::coroutine_return, coroutine_return_ty, Target::AssocTy, GenericRequirement::None;
+ CoroutineYield, sym::coroutine_yield, coroutine_yield_ty, Target::AssocTy, GenericRequirement::None;
Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None;
Pin, sym::pin, pin_type, Target::Struct, GenericRequirement::None;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
index bdf8b453e2d65..301d4cca0666c 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
@@ -101,7 +101,7 @@ use crate::{
type FxIndexMap = indexmap::IndexMap;
/// A wrapper around three booleans
#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
-pub struct ImportPathConfig {
+pub struct FindPathConfig {
/// If true, prefer to unconditionally use imports of the `core` and `alloc` crate
/// over the std.
pub prefer_no_std: bool,
@@ -318,9 +318,6 @@ impl TraitId {
}
}
-pub type TraitAliasLoc = ItemLoc;
-impl_intern!(TraitAliasId, TraitAliasLoc, intern_trait_alias, lookup_intern_trait_alias);
-
type TypeAliasLoc = AssocItemLoc;
impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias);
@@ -742,7 +739,6 @@ pub enum ModuleDefId {
ConstId(ConstId),
StaticId(StaticId),
TraitId(TraitId),
- TraitAliasId(TraitAliasId),
TypeAliasId(TypeAliasId),
BuiltinType(BuiltinType),
MacroId(MacroId),
@@ -756,7 +752,6 @@ impl_from!(
ConstId,
StaticId,
TraitId,
- TraitAliasId,
TypeAliasId,
BuiltinType
for ModuleDefId
@@ -862,7 +857,6 @@ pub enum GenericDefId {
// More importantly, this completes the set of items that contain type references
// which is to be used by the signature expression store in the future.
StaticId(StaticId),
- TraitAliasId(TraitAliasId),
TraitId(TraitId),
TypeAliasId(TypeAliasId),
}
@@ -872,7 +866,6 @@ impl_from!(
FunctionId,
ImplId,
StaticId,
- TraitAliasId,
TraitId,
TypeAliasId
for GenericDefId
@@ -902,7 +895,6 @@ impl GenericDefId {
GenericDefId::AdtId(AdtId::UnionId(it)) => file_id_and_params_of_item_loc(db, it),
GenericDefId::AdtId(AdtId::EnumId(it)) => file_id_and_params_of_item_loc(db, it),
GenericDefId::TraitId(it) => file_id_and_params_of_item_loc(db, it),
- GenericDefId::TraitAliasId(it) => file_id_and_params_of_item_loc(db, it),
GenericDefId::ImplId(it) => file_id_and_params_of_item_loc(db, it),
GenericDefId::ConstId(it) => (it.lookup(db).id.file_id, None),
GenericDefId::StaticId(it) => (it.lookup(db).id.file_id, None),
@@ -978,7 +970,6 @@ pub enum AttrDefId {
StaticId(StaticId),
ConstId(ConstId),
TraitId(TraitId),
- TraitAliasId(TraitAliasId),
TypeAliasId(TypeAliasId),
MacroId(MacroId),
ImplId(ImplId),
@@ -997,7 +988,6 @@ impl_from!(
ConstId,
FunctionId,
TraitId,
- TraitAliasId,
TypeAliasId,
MacroId(Macro2Id, MacroRulesId, ProcMacroId),
ImplId,
@@ -1020,7 +1010,6 @@ impl TryFrom for AttrDefId {
ModuleDefId::StaticId(it) => Ok(it.into()),
ModuleDefId::TraitId(it) => Ok(it.into()),
ModuleDefId::TypeAliasId(it) => Ok(it.into()),
- ModuleDefId::TraitAliasId(id) => Ok(id.into()),
ModuleDefId::MacroId(id) => Ok(id.into()),
ModuleDefId::BuiltinType(_) => Err(()),
}
@@ -1266,7 +1255,6 @@ impl HasModule for GenericDefId {
GenericDefId::FunctionId(it) => it.module(db),
GenericDefId::AdtId(it) => it.module(db),
GenericDefId::TraitId(it) => it.module(db),
- GenericDefId::TraitAliasId(it) => it.module(db),
GenericDefId::TypeAliasId(it) => it.module(db),
GenericDefId::ImplId(it) => it.module(db),
GenericDefId::ConstId(it) => it.module(db),
@@ -1286,7 +1274,6 @@ impl HasModule for AttrDefId {
AttrDefId::StaticId(it) => it.module(db),
AttrDefId::ConstId(it) => it.module(db),
AttrDefId::TraitId(it) => it.module(db),
- AttrDefId::TraitAliasId(it) => it.module(db),
AttrDefId::TypeAliasId(it) => it.module(db),
AttrDefId::ImplId(it) => it.module(db),
AttrDefId::ExternBlockId(it) => it.module(db),
@@ -1316,7 +1303,6 @@ impl ModuleDefId {
ModuleDefId::ConstId(id) => id.module(db),
ModuleDefId::StaticId(id) => id.module(db),
ModuleDefId::TraitId(id) => id.module(db),
- ModuleDefId::TraitAliasId(id) => id.module(db),
ModuleDefId::TypeAliasId(id) => id.module(db),
ModuleDefId::MacroId(id) => id.module(db),
ModuleDefId::BuiltinType(_) => return None,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
index 5030585147dee..7d5e627964eb1 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
@@ -192,8 +192,6 @@ struct DefMapCrateData {
exported_derives: FxHashMap>,
fn_proc_macro_mapping: FxHashMap,
- /// Custom attributes registered with `#![register_attr]`.
- registered_attrs: Vec,
/// Custom tool modules registered with `#![register_tool]`.
registered_tools: Vec,
/// Unstable features of Rust enabled with `#![feature(A, B)]`.
@@ -212,7 +210,6 @@ impl DefMapCrateData {
Self {
exported_derives: FxHashMap::default(),
fn_proc_macro_mapping: FxHashMap::default(),
- registered_attrs: Vec::new(),
registered_tools: PREDEFINED_TOOLS.iter().map(|it| Symbol::intern(it)).collect(),
unstable_features: FxHashSet::default(),
rustc_coherence_is_core: false,
@@ -227,7 +224,6 @@ impl DefMapCrateData {
let Self {
exported_derives,
fn_proc_macro_mapping,
- registered_attrs,
registered_tools,
unstable_features,
rustc_coherence_is_core: _,
@@ -238,7 +234,6 @@ impl DefMapCrateData {
} = self;
exported_derives.shrink_to_fit();
fn_proc_macro_mapping.shrink_to_fit();
- registered_attrs.shrink_to_fit();
registered_tools.shrink_to_fit();
unstable_features.shrink_to_fit();
}
@@ -529,10 +524,6 @@ impl DefMap {
&self.data.registered_tools
}
- pub fn registered_attrs(&self) -> &[Symbol] {
- &self.data.registered_attrs
- }
-
pub fn is_unstable_feature_enabled(&self, feature: &Symbol) -> bool {
self.data.unstable_features.contains(feature)
}
@@ -545,6 +536,10 @@ impl DefMap {
self.data.no_std || self.data.no_core
}
+ pub fn is_no_core(&self) -> bool {
+ self.data.no_core
+ }
+
pub fn fn_as_proc_macro(&self, id: FunctionId) -> Option {
self.data.fn_proc_macro_mapping.get(&id).copied()
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs
index 07210df887369..8d2a386de8ecc 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs
@@ -51,10 +51,18 @@ impl TraitItems {
tr: TraitId,
) -> (TraitItems, DefDiagnostics) {
let ItemLoc { container: module_id, id: ast_id } = tr.lookup(db);
+ let ast_id_map = db.ast_id_map(ast_id.file_id);
+ let source = ast_id.with_value(ast_id_map.get(ast_id.value)).to_node(db);
+ if source.eq_token().is_some() {
+ // FIXME(trait-alias) probably needs special handling here
+ return (
+ TraitItems { macro_calls: ThinVec::new(), items: Box::default() },
+ DefDiagnostics::new(vec![]),
+ );
+ }
let collector =
AssocItemCollector::new(db, module_id, ItemContainerId::TraitId(tr), ast_id.file_id);
- let source = ast_id.with_value(collector.ast_id_map.get(ast_id.value)).to_node(db);
let (items, macro_calls, diagnostics) = collector.collect(source.assoc_item_list());
(TraitItems { macro_calls, items }, DefDiagnostics::new(diagnostics))
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs
index e7e96804ae737..2f56d608fcbf4 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs
@@ -90,13 +90,8 @@ impl DefMap {
return true;
}
- if segments.len() == 1 {
- if find_builtin_attr_idx(name).is_some() {
- return true;
- }
- if self.data.registered_attrs.iter().any(pred) {
- return true;
- }
+ if segments.len() == 1 && find_builtin_attr_idx(name).is_some() {
+ return true;
}
}
false
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
index 267c4451b9d71..a2ce538356515 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
@@ -27,10 +27,11 @@ use triomphe::Arc;
use crate::{
AdtId, AssocItemId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, ExternBlockLoc,
- ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern, ItemContainerId,
- LocalModuleId, Lookup, Macro2Id, Macro2Loc, MacroExpander, MacroId, MacroRulesId,
- MacroRulesLoc, MacroRulesLocFlags, ModuleDefId, ModuleId, ProcMacroId, ProcMacroLoc, StaticLoc,
- StructLoc, TraitAliasLoc, TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro, UseId, UseLoc,
+ ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, FxIndexMap, ImplLoc, Intern,
+ ItemContainerId, LocalModuleId, Lookup, Macro2Id, Macro2Loc, MacroExpander, MacroId,
+ MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ModuleDefId, ModuleId, ProcMacroId,
+ ProcMacroLoc, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro, UseId,
+ UseLoc,
attr::Attrs,
db::DefDatabase,
item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports},
@@ -69,7 +70,7 @@ pub(super) fn collect_defs(
// populate external prelude and dependency list
let mut deps =
- FxHashMap::with_capacity_and_hasher(krate.dependencies.len(), Default::default());
+ FxIndexMap::with_capacity_and_hasher(krate.dependencies.len(), Default::default());
for dep in &krate.dependencies {
tracing::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
@@ -220,7 +221,7 @@ struct DefCollector<'db> {
/// Set only in case of blocks.
crate_local_def_map: Option<&'db LocalDefMap>,
// The dependencies of the current crate, including optional deps like `test`.
- deps: FxHashMap,
+ deps: FxIndexMap,
glob_imports: FxHashMap>,
unresolved_imports: Vec,
indeterminate_imports: Vec<(ImportDirective, PerNs)>,
@@ -297,12 +298,6 @@ impl<'db> DefCollector<'db> {
);
crate_data.unstable_features.extend(features);
}
- () if *attr_name == sym::register_attr => {
- if let Some(ident) = attr.single_ident_value() {
- crate_data.registered_attrs.push(ident.sym.clone());
- cov_mark::hit!(register_attr);
- }
- }
() if *attr_name == sym::register_tool => {
if let Some(ident) = attr.single_ident_value() {
crate_data.registered_tools.push(ident.sym.clone());
@@ -332,7 +327,9 @@ impl<'db> DefCollector<'db> {
let skip = dep.is_sysroot()
&& match dep.crate_id.data(self.db).origin {
CrateOrigin::Lang(LangCrateOrigin::Core) => crate_data.no_core,
- CrateOrigin::Lang(LangCrateOrigin::Std) => crate_data.no_std,
+ CrateOrigin::Lang(LangCrateOrigin::Std) => {
+ crate_data.no_core || crate_data.no_std
+ }
_ => false,
};
if skip {
@@ -1954,20 +1951,6 @@ impl ModCollector<'_, '_> {
false,
);
}
- ModItemId::TraitAlias(id) => {
- let it = &self.item_tree[id];
-
- let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
- update_def(
- self.def_collector,
- TraitAliasLoc { container: module, id: InFile::new(self.file_id(), id) }
- .intern(db)
- .into(),
- &it.name,
- vis,
- false,
- );
- }
ModItemId::TypeAlias(id) => {
let it = &self.item_tree[id];
@@ -2564,7 +2547,7 @@ mod tests {
def_map,
local_def_map: LocalDefMap::default(),
crate_local_def_map: None,
- deps: FxHashMap::default(),
+ deps: FxIndexMap::default(),
glob_imports: FxHashMap::default(),
unresolved_imports: Vec::new(),
indeterminate_imports: Vec::new(),
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs
index 338851b715bf0..6afa04bc412aa 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs
@@ -84,7 +84,7 @@ pub const BAZ: u32 = 0;
)
.unwrap(),
),
- Arc::new(CrateWorkspaceData { data_layout: Err("".into()), toolchain: None }),
+ Arc::new(CrateWorkspaceData { target: Err("".into()), toolchain: None }),
)
};
let a = add_crate("a", 0);
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
index a10990e6a8f9f..698292c2fbea4 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
@@ -20,7 +20,7 @@ use crate::{
EnumVariantId, ExternBlockId, ExternCrateId, FunctionId, FxIndexMap, GenericDefId,
GenericParamId, HasModule, ImplId, ItemContainerId, LifetimeParamId, LocalModuleId, Lookup,
Macro2Id, MacroId, MacroRulesId, ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId,
- TraitAliasId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, UseId, VariantId,
+ TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, UseId, VariantId,
builtin_type::BuiltinType,
db::DefDatabase,
expr_store::{
@@ -105,7 +105,6 @@ pub enum TypeNs {
TypeAliasId(TypeAliasId),
BuiltinType(BuiltinType),
TraitId(TraitId),
- TraitAliasId(TraitAliasId),
ModuleId(ModuleId),
}
@@ -1150,7 +1149,6 @@ impl<'db> ModuleItemMap<'db> {
let ty = match def.def {
ModuleDefId::AdtId(it) => TypeNs::AdtId(it),
ModuleDefId::TraitId(it) => TypeNs::TraitId(it),
- ModuleDefId::TraitAliasId(it) => TypeNs::TraitAliasId(it),
ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it),
ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it),
@@ -1195,7 +1193,6 @@ fn to_value_ns(per_ns: PerNs) -> Option<(ValueNs, Option)> {
ModuleDefId::AdtId(AdtId::EnumId(_) | AdtId::UnionId(_))
| ModuleDefId::TraitId(_)
- | ModuleDefId::TraitAliasId(_)
| ModuleDefId::TypeAliasId(_)
| ModuleDefId::BuiltinType(_)
| ModuleDefId::MacroId(_)
@@ -1214,7 +1211,6 @@ fn to_type_ns(per_ns: PerNs) -> Option<(TypeNs, Option)> {
ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it),
ModuleDefId::TraitId(it) => TypeNs::TraitId(it),
- ModuleDefId::TraitAliasId(it) => TypeNs::TraitAliasId(it),
ModuleDefId::ModuleId(it) => TypeNs::ModuleId(it),
@@ -1320,12 +1316,6 @@ impl HasResolver for TraitId {
}
}
-impl HasResolver for TraitAliasId {
- fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
- lookup_resolver(db, self).push_generic_params_scope(db, self.into())
- }
-}
-
impl + Copy> HasResolver for T {
fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
let def = self.into();
@@ -1410,7 +1400,6 @@ impl HasResolver for GenericDefId {
GenericDefId::FunctionId(inner) => inner.resolver(db),
GenericDefId::AdtId(adt) => adt.resolver(db),
GenericDefId::TraitId(inner) => inner.resolver(db),
- GenericDefId::TraitAliasId(inner) => inner.resolver(db),
GenericDefId::TypeAliasId(inner) => inner.resolver(db),
GenericDefId::ImplId(inner) => inner.resolver(db),
GenericDefId::ConstId(inner) => inner.resolver(db),
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs b/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs
index 92e610b36acd0..47638610ed734 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs
@@ -20,15 +20,13 @@ use triomphe::Arc;
use crate::{
ConstId, EnumId, EnumVariantId, EnumVariantLoc, ExternBlockId, FunctionId, HasModule, ImplId,
- ItemContainerId, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, UnionId,
- VariantId,
+ ItemContainerId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
attr::Attrs,
db::DefDatabase,
expr_store::{
ExpressionStore, ExpressionStoreSourceMap,
lower::{
- ExprCollector, lower_function, lower_generic_params, lower_trait, lower_trait_alias,
- lower_type_alias,
+ ExprCollector, lower_function, lower_generic_params, lower_trait, lower_type_alias,
},
},
hir::{ExprId, PatId, generics::GenericParams},
@@ -395,7 +393,7 @@ impl ImplSignature {
bitflags::bitflags! {
#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
- pub struct TraitFlags: u8 {
+ pub struct TraitFlags: u16 {
const RUSTC_HAS_INCOHERENT_INHERENT_IMPLS = 1 << 1;
const FUNDAMENTAL = 1 << 2;
const UNSAFE = 1 << 3;
@@ -403,6 +401,8 @@ bitflags::bitflags! {
const SKIP_ARRAY_DURING_METHOD_DISPATCH = 1 << 5;
const SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH = 1 << 6;
const RUSTC_PAREN_SUGAR = 1 << 7;
+ const COINDUCTIVE = 1 << 8;
+ const ALIAS = 1 << 9;
}
}
@@ -427,6 +427,9 @@ impl TraitSignature {
if source.value.unsafe_token().is_some() {
flags.insert(TraitFlags::UNSAFE);
}
+ if source.value.eq_token().is_some() {
+ flags.insert(TraitFlags::ALIAS);
+ }
if attrs.by_key(sym::fundamental).exists() {
flags |= TraitFlags::FUNDAMENTAL;
}
@@ -436,6 +439,9 @@ impl TraitSignature {
if attrs.by_key(sym::rustc_paren_sugar).exists() {
flags |= TraitFlags::RUSTC_PAREN_SUGAR;
}
+ if attrs.by_key(sym::rustc_coinductive).exists() {
+ flags |= TraitFlags::COINDUCTIVE;
+ }
let mut skip_array_during_method_dispatch =
attrs.by_key(sym::rustc_skip_array_during_method_dispatch).exists();
let mut skip_boxed_slice_during_method_dispatch = false;
@@ -465,31 +471,6 @@ impl TraitSignature {
}
}
-#[derive(Debug, PartialEq, Eq)]
-pub struct TraitAliasSignature {
- pub name: Name,
- pub generic_params: Arc,
- pub store: Arc,
-}
-
-impl TraitAliasSignature {
- pub fn query(
- db: &dyn DefDatabase,
- id: TraitAliasId,
- ) -> (Arc, Arc) {
- let loc = id.lookup(db);
-
- let source = loc.source(db);
- let name = as_name_opt(source.value.name());
- let (store, source_map, generic_params) = lower_trait_alias(db, loc.container, source, id);
-
- (
- Arc::new(TraitAliasSignature { generic_params, store: Arc::new(store), name }),
- Arc::new(source_map),
- )
- }
-}
-
bitflags! {
#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
pub struct FnFlags: u16 {
@@ -508,6 +489,7 @@ bitflags! {
const HAS_TARGET_FEATURE = 1 << 9;
const DEPRECATED_SAFE_2024 = 1 << 10;
const EXPLICIT_SAFE = 1 << 11;
+ const RUSTC_INTRINSIC = 1 << 12;
}
}
@@ -541,6 +523,9 @@ impl FunctionSignature {
if attrs.by_key(sym::target_feature).exists() {
flags.insert(FnFlags::HAS_TARGET_FEATURE);
}
+ if attrs.by_key(sym::rustc_intrinsic).exists() {
+ flags.insert(FnFlags::RUSTC_INTRINSIC);
+ }
let legacy_const_generics_indices = attrs.rustc_legacy_const_generics();
let source = loc.source(db);
@@ -636,6 +621,21 @@ impl FunctionSignature {
pub fn has_target_feature(&self) -> bool {
self.flags.contains(FnFlags::HAS_TARGET_FEATURE)
}
+
+ pub fn is_intrinsic(db: &dyn DefDatabase, id: FunctionId) -> bool {
+ let data = db.function_signature(id);
+ data.flags.contains(FnFlags::RUSTC_INTRINSIC)
+ // Keep this around for a bit until extern "rustc-intrinsic" abis are no longer used
+ || match &data.abi {
+ Some(abi) => *abi == sym::rust_dash_intrinsic,
+ None => match id.lookup(db).container {
+ ItemContainerId::ExternBlockId(block) => {
+ block.abi(db) == Some(sym::rust_dash_intrinsic)
+ }
+ _ => false,
+ },
+ }
+ }
}
bitflags! {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/src.rs b/src/tools/rust-analyzer/crates/hir-def/src/src.rs
index aa373a27b0d52..367b543cf9080 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/src.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/src.rs
@@ -71,7 +71,7 @@ impl HasChildSource> for UseId {
}
impl HasChildSource for GenericDefId {
- type Value = Either;
+ type Value = Either;
fn child_source(
&self,
db: &dyn DefDatabase,
@@ -89,12 +89,7 @@ impl HasChildSource for GenericDefId {
GenericDefId::TraitId(id) => {
let trait_ref = id.lookup(db).source(db).value;
let idx = idx_iter.next().unwrap();
- params.insert(idx, Either::Right(ast::TraitOrAlias::Trait(trait_ref)));
- }
- GenericDefId::TraitAliasId(id) => {
- let alias = id.lookup(db).source(db).value;
- let idx = idx_iter.next().unwrap();
- params.insert(idx, Either::Right(ast::TraitOrAlias::TraitAlias(alias)));
+ params.insert(idx, Either::Right(trait_ref));
}
_ => {}
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs
index e30a5b65a1f79..1e2f354f975cb 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs
@@ -3,7 +3,7 @@
use std::{fmt, panic, sync::Mutex};
use base_db::{
- Crate, CrateGraphBuilder, CratesMap, FileSourceRootInput, FileText, RootQueryDb,
+ Crate, CrateGraphBuilder, CratesMap, FileSourceRootInput, FileText, Nonce, RootQueryDb,
SourceDatabase, SourceRoot, SourceRootId, SourceRootInput,
};
use hir_expand::{InFile, files::FilePosition};
@@ -20,12 +20,12 @@ use crate::{
};
#[salsa_macros::db]
-#[derive(Clone)]
pub(crate) struct TestDB {
storage: salsa::Storage,
files: Arc,
crates_map: Arc,
events: Arc>>>,
+ nonce: Nonce,
}
impl Default for TestDB {
@@ -44,6 +44,7 @@ impl Default for TestDB {
events,
files: Default::default(),
crates_map: Default::default(),
+ nonce: Nonce::new(),
};
this.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH);
// This needs to be here otherwise `CrateGraphBuilder` panics.
@@ -53,6 +54,18 @@ impl Default for TestDB {
}
}
+impl Clone for TestDB {
+ fn clone(&self) -> Self {
+ Self {
+ storage: self.storage.clone(),
+ files: self.files.clone(),
+ crates_map: self.crates_map.clone(),
+ events: self.events.clone(),
+ nonce: Nonce::new(),
+ }
+ }
+}
+
#[salsa_macros::db]
impl salsa::Database for TestDB {}
@@ -117,6 +130,10 @@ impl SourceDatabase for TestDB {
fn crates_map(&self) -> Arc {
self.crates_map.clone()
}
+
+ fn nonce_and_revision(&self) -> (Nonce, salsa::Revision) {
+ (self.nonce, salsa::plumbing::ZalsaDatabase::zalsa(self).current_revision())
+ }
}
impl TestDB {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
index 7cc0a26d37c80..138d02e5a6105 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
@@ -24,9 +24,7 @@ oorandom = "11.1.5"
tracing.workspace = true
rustc-hash.workspace = true
scoped-tls = "1.0.1"
-chalk-solve.workspace = true
chalk-ir.workspace = true
-chalk-recursive.workspace = true
chalk-derive.workspace = true
la-arena.workspace = true
triomphe.workspace = true
@@ -40,7 +38,14 @@ salsa-macros.workspace = true
ra-ap-rustc_abi.workspace = true
ra-ap-rustc_index.workspace = true
ra-ap-rustc_pattern_analysis.workspace = true
+ra-ap-rustc_ast_ir.workspace = true
+ra-ap-rustc_type_ir.workspace = true
+ra-ap-rustc_next_trait_solver.workspace = true
+# These moved to dev deps if `setup_tracing` was a macro and dependents also
+# included these
+tracing-subscriber.workspace = true
+tracing-tree.workspace = true
# local deps
stdx.workspace = true
@@ -53,9 +58,6 @@ span.workspace = true
[dev-dependencies]
expect-test = "1.5.1"
-tracing.workspace = true
-tracing-subscriber.workspace = true
-tracing-tree.workspace = true
project-model.workspace = true
# local deps
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
index 26ca7fb9a15ec..fd60ffcf24b0a 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
@@ -3,27 +3,28 @@
//! reference to a type with the field `bar`. This is an approximation of the
//! logic in rustc (which lives in rustc_hir_analysis/check/autoderef.rs).
-use std::mem;
+use std::fmt;
-use chalk_ir::cast::Cast;
-use hir_def::lang_item::LangItem;
-use hir_expand::name::Name;
-use intern::sym;
+use hir_def::{TypeAliasId, lang_item::LangItem};
+use rustc_type_ir::inherent::{IntoKind, Ty as _};
+use tracing::debug;
use triomphe::Arc;
+use crate::next_solver::infer::InferOk;
use crate::{
- Canonical, Goal, Interner, ProjectionTyExt, TraitEnvironment, Ty, TyBuilder, TyKind,
- db::HirDatabase, infer::unify::InferenceTable,
+ TraitEnvironment,
+ db::HirDatabase,
+ infer::unify::InferenceTable,
+ next_solver::{
+ Ty, TyKind,
+ infer::traits::{ObligationCause, PredicateObligations},
+ mapping::{ChalkToNextSolver, NextSolverToChalk},
+ obligation_ctxt::ObligationCtxt,
+ },
};
const AUTODEREF_RECURSION_LIMIT: usize = 20;
-#[derive(Debug)]
-pub(crate) enum AutoderefKind {
- Builtin,
- Overloaded,
-}
-
/// Returns types that `ty` transitively dereferences to. This function is only meant to be used
/// outside `hir-ty`.
///
@@ -34,16 +35,17 @@ pub(crate) enum AutoderefKind {
pub fn autoderef(
db: &dyn HirDatabase,
env: Arc,
- ty: Canonical,
-) -> impl Iterator- {
+ ty: crate::Canonical,
+) -> impl Iterator
- {
let mut table = InferenceTable::new(db, env);
+ let interner = table.interner;
let ty = table.instantiate_canonical(ty);
- let mut autoderef = Autoderef::new_no_tracking(&mut table, ty, false, false);
+ let mut autoderef = Autoderef::new_no_tracking(&mut table, ty.to_nextsolver(interner));
let mut v = Vec::new();
while let Some((ty, _steps)) = autoderef.next() {
// `ty` may contain unresolved inference variables. Since there's no chance they would be
// resolved, just replace with fallback type.
- let resolved = autoderef.table.resolve_completely(ty);
+ let resolved = autoderef.table.resolve_completely(ty.to_chalk(interner));
// If the deref chain contains a cycle (e.g. `A` derefs to `B` and `B` derefs to `A`), we
// would revisit some already visited types. Stop here to avoid duplication.
@@ -59,176 +61,267 @@ pub fn autoderef(
v.into_iter()
}
-trait TrackAutoderefSteps {
+pub(crate) trait TrackAutoderefSteps<'db>: Default + fmt::Debug {
fn len(&self) -> usize;
- fn push(&mut self, kind: AutoderefKind, ty: &Ty);
+ fn push(&mut self, ty: Ty<'db>, kind: AutoderefKind);
}
-impl TrackAutoderefSteps for usize {
+impl<'db> TrackAutoderefSteps<'db> for usize {
fn len(&self) -> usize {
*self
}
- fn push(&mut self, _: AutoderefKind, _: &Ty) {
+ fn push(&mut self, _: Ty<'db>, _: AutoderefKind) {
*self += 1;
}
}
-impl TrackAutoderefSteps for Vec<(AutoderefKind, Ty)> {
+impl<'db> TrackAutoderefSteps<'db> for Vec<(Ty<'db>, AutoderefKind)> {
fn len(&self) -> usize {
self.len()
}
- fn push(&mut self, kind: AutoderefKind, ty: &Ty) {
- self.push((kind, ty.clone()));
+ fn push(&mut self, ty: Ty<'db>, kind: AutoderefKind) {
+ self.push((ty, kind));
}
}
-#[derive(Debug)]
-pub(crate) struct Autoderef<'table, 'db, T = Vec<(AutoderefKind, Ty)>> {
- pub(crate) table: &'table mut InferenceTable<'db>,
- ty: Ty,
- at_start: bool,
- steps: T,
- explicit: bool,
- use_receiver_trait: bool,
+#[derive(Copy, Clone, Debug)]
+pub(crate) enum AutoderefKind {
+ /// A true pointer type, such as `&T` and `*mut T`.
+ Builtin,
+ /// A type which must dispatch to a `Deref` implementation.
+ Overloaded,
}
-impl<'table, 'db> Autoderef<'table, 'db> {
- pub(crate) fn new(
- table: &'table mut InferenceTable<'db>,
- ty: Ty,
- explicit: bool,
- use_receiver_trait: bool,
- ) -> Self {
- let ty = table.resolve_ty_shallow(&ty);
- Autoderef { table, ty, at_start: true, steps: Vec::new(), explicit, use_receiver_trait }
- }
-
- pub(crate) fn steps(&self) -> &[(AutoderefKind, Ty)] {
- &self.steps
- }
+struct AutoderefSnapshot<'db, Steps> {
+ at_start: bool,
+ reached_recursion_limit: bool,
+ steps: Steps,
+ cur_ty: Ty<'db>,
+ obligations: PredicateObligations<'db>,
}
-impl<'table, 'db> Autoderef<'table, 'db, usize> {
- pub(crate) fn new_no_tracking(
- table: &'table mut InferenceTable<'db>,
- ty: Ty,
- explicit: bool,
- use_receiver_trait: bool,
- ) -> Self {
- let ty = table.resolve_ty_shallow(&ty);
- Autoderef { table, ty, at_start: true, steps: 0, explicit, use_receiver_trait }
- }
+#[derive(Clone, Copy)]
+struct AutoderefTraits {
+ trait_target: TypeAliasId,
}
-#[allow(private_bounds)]
-impl Autoderef<'_, '_, T> {
- pub(crate) fn step_count(&self) -> usize {
- self.steps.len()
- }
+/// Recursively dereference a type, considering both built-in
+/// dereferences (`*`) and the `Deref` trait.
+/// Although called `Autoderef` it can be configured to use the
+/// `Receiver` trait instead of the `Deref` trait.
+pub(crate) struct Autoderef<'a, 'db, Steps = Vec<(Ty<'db>, AutoderefKind)>> {
+ // Meta infos:
+ pub(crate) table: &'a mut InferenceTable<'db>,
+ traits: Option,
- pub(crate) fn final_ty(&self) -> Ty {
- self.ty.clone()
- }
+ // Current state:
+ state: AutoderefSnapshot<'db, Steps>,
+
+ // Configurations:
+ include_raw_pointers: bool,
+ use_receiver_trait: bool,
}
-impl Iterator for Autoderef<'_, '_, T> {
- type Item = (Ty, usize);
+impl<'a, 'db, Steps: TrackAutoderefSteps<'db>> Iterator for Autoderef<'a, 'db, Steps> {
+ type Item = (Ty<'db>, usize);
- #[tracing::instrument(skip_all)]
fn next(&mut self) -> Option {
- if mem::take(&mut self.at_start) {
- return Some((self.ty.clone(), 0));
+ debug!("autoderef: steps={:?}, cur_ty={:?}", self.state.steps, self.state.cur_ty);
+ if self.state.at_start {
+ self.state.at_start = false;
+ debug!("autoderef stage #0 is {:?}", self.state.cur_ty);
+ return Some((self.state.cur_ty, 0));
}
- if self.steps.len() > AUTODEREF_RECURSION_LIMIT {
+ // If we have reached the recursion limit, error gracefully.
+ if self.state.steps.len() >= AUTODEREF_RECURSION_LIMIT {
+ self.state.reached_recursion_limit = true;
return None;
}
- let (kind, new_ty) =
- autoderef_step(self.table, self.ty.clone(), self.explicit, self.use_receiver_trait)?;
+ if self.state.cur_ty.is_ty_var() {
+ return None;
+ }
+
+ // Otherwise, deref if type is derefable:
+ // NOTE: in the case of self.use_receiver_trait = true, you might think it would
+ // be better to skip this clause and use the Overloaded case only, since &T
+ // and &mut T implement Receiver. But built-in derefs apply equally to Receiver
+ // and Deref, and this has benefits for const and the emitted MIR.
+ let (kind, new_ty) = if let Some(ty) =
+ self.state.cur_ty.builtin_deref(self.table.db, self.include_raw_pointers)
+ {
+ debug_assert_eq!(ty, self.table.infer_ctxt.resolve_vars_if_possible(ty));
+ // NOTE: we may still need to normalize the built-in deref in case
+ // we have some type like `&::Assoc`, since users of
+ // autoderef expect this type to have been structurally normalized.
+ if let TyKind::Alias(..) = ty.kind() {
+ let (normalized_ty, obligations) = structurally_normalize_ty(self.table, ty)?;
+ self.state.obligations.extend(obligations);
+ (AutoderefKind::Builtin, normalized_ty)
+ } else {
+ (AutoderefKind::Builtin, ty)
+ }
+ } else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
+ // The overloaded deref check already normalizes the pointee type.
+ (AutoderefKind::Overloaded, ty)
+ } else {
+ return None;
+ };
- self.steps.push(kind, &self.ty);
- self.ty = new_ty;
+ self.state.steps.push(self.state.cur_ty, kind);
+ debug!(
+ "autoderef stage #{:?} is {:?} from {:?}",
+ self.step_count(),
+ new_ty,
+ (self.state.cur_ty, kind)
+ );
+ self.state.cur_ty = new_ty;
- Some((self.ty.clone(), self.step_count()))
+ Some((self.state.cur_ty, self.step_count()))
}
}
-pub(crate) fn autoderef_step(
- table: &mut InferenceTable<'_>,
- ty: Ty,
- explicit: bool,
- use_receiver_trait: bool,
-) -> Option<(AutoderefKind, Ty)> {
- if let Some(derefed) = builtin_deref(table.db, &ty, explicit) {
- Some((AutoderefKind::Builtin, table.resolve_ty_shallow(derefed)))
- } else {
- Some((AutoderefKind::Overloaded, deref_by_trait(table, ty, use_receiver_trait)?))
+impl<'a, 'db> Autoderef<'a, 'db> {
+ pub(crate) fn new(table: &'a mut InferenceTable<'db>, base_ty: Ty<'db>) -> Self {
+ Self::new_impl(table, base_ty)
}
}
-pub(crate) fn builtin_deref<'ty>(
- db: &dyn HirDatabase,
- ty: &'ty Ty,
- explicit: bool,
-) -> Option<&'ty Ty> {
- match ty.kind(Interner) {
- TyKind::Ref(.., ty) => Some(ty),
- TyKind::Raw(.., ty) if explicit => Some(ty),
- &TyKind::Adt(chalk_ir::AdtId(adt), ref substs) if crate::lang_items::is_box(db, adt) => {
- substs.at(Interner, 0).ty(Interner)
- }
- _ => None,
+impl<'a, 'db> Autoderef<'a, 'db, usize> {
+ pub(crate) fn new_no_tracking(table: &'a mut InferenceTable<'db>, base_ty: Ty<'db>) -> Self {
+ Self::new_impl(table, base_ty)
}
}
-pub(crate) fn deref_by_trait(
- table @ &mut InferenceTable { db, .. }: &mut InferenceTable<'_>,
- ty: Ty,
- use_receiver_trait: bool,
-) -> Option {
- let _p = tracing::info_span!("deref_by_trait").entered();
- if table.resolve_ty_shallow(&ty).inference_var(Interner).is_some() {
- // don't try to deref unknown variables
- return None;
+impl<'a, 'db, Steps: TrackAutoderefSteps<'db>> Autoderef<'a, 'db, Steps> {
+ fn new_impl(table: &'a mut InferenceTable<'db>, base_ty: Ty<'db>) -> Self {
+ Autoderef {
+ state: AutoderefSnapshot {
+ steps: Steps::default(),
+ cur_ty: table.infer_ctxt.resolve_vars_if_possible(base_ty),
+ obligations: PredicateObligations::new(),
+ at_start: true,
+ reached_recursion_limit: false,
+ },
+ table,
+ traits: None,
+ include_raw_pointers: false,
+ use_receiver_trait: false,
+ }
}
- let trait_id = || {
- // FIXME: Remove the `false` once `Receiver` needs to be stabilized, doing so will
- // effectively bump the MSRV of rust-analyzer to 1.84 due to 1.83 and below lacking the
- // blanked impl on `Deref`.
- #[expect(clippy::overly_complex_bool_expr)]
- if use_receiver_trait
- && false
- && let Some(receiver) = LangItem::Receiver.resolve_trait(db, table.trait_env.krate)
- {
- return Some(receiver);
+ fn autoderef_traits(&mut self) -> Option {
+ match &mut self.traits {
+ Some(it) => Some(*it),
+ None => {
+ let traits = if self.use_receiver_trait {
+ AutoderefTraits {
+ trait_target: LangItem::ReceiverTarget
+ .resolve_type_alias(self.table.db, self.table.trait_env.krate)
+ .or_else(|| {
+ LangItem::DerefTarget
+ .resolve_type_alias(self.table.db, self.table.trait_env.krate)
+ })?,
+ }
+ } else {
+ AutoderefTraits {
+ trait_target: LangItem::DerefTarget
+ .resolve_type_alias(self.table.db, self.table.trait_env.krate)?,
+ }
+ };
+ Some(*self.traits.insert(traits))
+ }
}
- // Old rustc versions might not have `Receiver` trait.
- // Fallback to `Deref` if they don't
- LangItem::Deref.resolve_trait(db, table.trait_env.krate)
- };
- let trait_id = trait_id()?;
- let target =
- trait_id.trait_items(db).associated_type_by_name(&Name::new_symbol_root(sym::Target))?;
-
- let projection = {
- let b = TyBuilder::subst_for_def(db, trait_id, None);
- if b.remaining() != 1 {
- // the Target type + Deref trait should only have one generic parameter,
- // namely Deref's Self type
- return None;
- }
- let deref_subst = b.push(ty).build();
- TyBuilder::assoc_type_projection(db, target, Some(deref_subst)).build()
+ }
+
+ fn overloaded_deref_ty(&mut self, ty: Ty<'db>) -> Option> {
+ debug!("overloaded_deref_ty({:?})", ty);
+ let interner = self.table.interner;
+
+ // , or whatever the equivalent trait is that we've been asked to walk.
+ let AutoderefTraits { trait_target } = self.autoderef_traits()?;
+
+ let (normalized_ty, obligations) = structurally_normalize_ty(
+ self.table,
+ Ty::new_projection(interner, trait_target.into(), [ty]),
+ )?;
+ debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
+ self.state.obligations.extend(obligations);
+
+ Some(self.table.infer_ctxt.resolve_vars_if_possible(normalized_ty))
+ }
+
+ /// Returns the final type we ended up with, which may be an unresolved
+ /// inference variable.
+ pub(crate) fn final_ty(&self) -> Ty<'db> {
+ self.state.cur_ty
+ }
+
+ pub(crate) fn step_count(&self) -> usize {
+ self.state.steps.len()
+ }
+
+ pub(crate) fn take_obligations(&mut self) -> PredicateObligations<'db> {
+ std::mem::take(&mut self.state.obligations)
+ }
+
+ pub(crate) fn steps(&self) -> &Steps {
+ &self.state.steps
+ }
+
+ #[expect(dead_code)]
+ pub(crate) fn reached_recursion_limit(&self) -> bool {
+ self.state.reached_recursion_limit
+ }
+
+ /// also dereference through raw pointer types
+ /// e.g., assuming ptr_to_Foo is the type `*const Foo`
+ /// fcx.autoderef(span, ptr_to_Foo) => [*const Foo]
+ /// fcx.autoderef(span, ptr_to_Foo).include_raw_ptrs() => [*const Foo, Foo]
+ pub(crate) fn include_raw_pointers(mut self) -> Self {
+ self.include_raw_pointers = true;
+ self
+ }
+
+ /// Use `core::ops::Receiver` and `core::ops::Receiver::Target` as
+ /// the trait and associated type to iterate, instead of
+ /// `core::ops::Deref` and `core::ops::Deref::Target`
+ pub(crate) fn use_receiver_trait(mut self) -> Self {
+ self.use_receiver_trait = true;
+ self
+ }
+}
+
+fn structurally_normalize_ty<'db>(
+ table: &InferenceTable<'db>,
+ ty: Ty<'db>,
+) -> Option<(Ty<'db>, PredicateObligations<'db>)> {
+ let mut ocx = ObligationCtxt::new(&table.infer_ctxt);
+ let Ok(normalized_ty) =
+ ocx.structurally_normalize_ty(&ObligationCause::misc(), table.param_env, ty)
+ else {
+ // We shouldn't have errors here in the old solver, except for
+ // evaluate/fulfill mismatches, but that's not a reason for an ICE.
+ return None;
};
+ let errors = ocx.select_where_possible();
+ if !errors.is_empty() {
+ unreachable!();
+ }
+
+ Some((normalized_ty, ocx.into_pending_obligations()))
+}
+
+pub(crate) fn overloaded_deref_ty<'db>(
+ table: &InferenceTable<'db>,
+ ty: Ty<'db>,
+) -> Option>> {
+ let interner = table.interner;
- // Check that the type implements Deref at all
- let trait_ref = projection.trait_ref(db);
- let implements_goal: Goal = trait_ref.cast(Interner);
- table.try_obligation(implements_goal.clone())?;
+ let trait_target = LangItem::DerefTarget.resolve_type_alias(table.db, table.trait_env.krate)?;
- table.register_obligation(implements_goal);
+ let (normalized_ty, obligations) =
+ structurally_normalize_ty(table, Ty::new_projection(interner, trait_target.into(), [ty]))?;
- let result = table.normalize_projection_ty(projection);
- Some(table.resolve_ty_shallow(&result))
+ Some(InferOk { value: normalized_ty, obligations })
}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs b/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs
index 8af8fb73f344e..3755175cf5163 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs
@@ -1,16 +1,12 @@
//! `TyBuilder`, a helper for building instances of `Ty` and related types.
-use std::iter;
-
use chalk_ir::{
AdtId, DebruijnIndex, Scalar,
cast::{Cast, CastTo, Caster},
fold::TypeFoldable,
interner::HasInterner,
};
-use hir_def::{
- DefWithBodyId, GenericDefId, GenericParamId, TraitId, TypeAliasId, builtin_type::BuiltinType,
-};
+use hir_def::{GenericDefId, GenericParamId, TraitId, TypeAliasId, builtin_type::BuiltinType};
use smallvec::SmallVec;
use crate::{
@@ -246,47 +242,6 @@ impl TyBuilder<()> {
TyBuilder::new((), params, parent_subst)
}
- /// Creates a `TyBuilder` to build `Substitution` for a coroutine defined in `parent`.
- ///
- /// A coroutine's substitution consists of:
- /// - resume type of coroutine
- /// - yield type of coroutine ([`Coroutine::Yield`](std::ops::Coroutine::Yield))
- /// - return type of coroutine ([`Coroutine::Return`](std::ops::Coroutine::Return))
- /// - generic parameters in scope on `parent`
- ///
- /// in this order.
- ///
- /// This method prepopulates the builder with placeholder substitution of `parent`, so you
- /// should only push exactly 3 `GenericArg`s before building.
- pub fn subst_for_coroutine(db: &dyn HirDatabase, parent: DefWithBodyId) -> TyBuilder<()> {
- let parent_subst =
- parent.as_generic_def_id(db).map(|p| generics(db, p).placeholder_subst(db));
- // These represent resume type, yield type, and return type of coroutine.
- let params = std::iter::repeat_n(ParamKind::Type, 3).collect();
- TyBuilder::new((), params, parent_subst)
- }
-
- pub fn subst_for_closure(
- db: &dyn HirDatabase,
- parent: DefWithBodyId,
- sig_ty: Ty,
- ) -> Substitution {
- let sig_ty = sig_ty.cast(Interner);
- let self_subst = iter::once(&sig_ty);
- let Some(parent) = parent.as_generic_def_id(db) else {
- return Substitution::from_iter(Interner, self_subst);
- };
- Substitution::from_iter(
- Interner,
- generics(db, parent)
- .placeholder_subst(db)
- .iter(Interner)
- .chain(self_subst)
- .cloned()
- .collect::>(),
- )
- }
-
pub fn build(self) -> Substitution {
let ((), subst) = self.build_internal();
subst
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
index 3ba7c93d4fb76..546991cf6571e 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
@@ -1,602 +1,15 @@
//! The implementation of `RustIrDatabase` for Chalk, which provides information
//! about the code that Chalk needs.
-use core::ops;
-use std::{iter, ops::ControlFlow, sync::Arc};
+use hir_def::{CallableDefId, GenericDefId};
-use hir_expand::name::Name;
-use intern::sym;
-use span::Edition;
-use tracing::debug;
-
-use chalk_ir::{CanonicalVarKinds, cast::Caster, fold::shift::Shift};
-use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait};
-
-use base_db::Crate;
-use hir_def::{
- AssocItemId, BlockId, CallableDefId, GenericDefId, HasModule, ItemContainerId, Lookup,
- TypeAliasId, VariantId,
- hir::Movability,
- lang_item::LangItem,
- signatures::{ImplFlags, StructFlags, TraitFlags},
-};
-
-use crate::{
- AliasEq, AliasTy, BoundVar, DebruijnIndex, Interner, ProjectionTy, ProjectionTyExt,
- QuantifiedWhereClause, Substitution, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind,
- WhereClause,
- db::{HirDatabase, InternedCoroutine},
- from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
- generics::generics,
- lower::LifetimeElisionKind,
- make_binders, make_single_type_binders,
- mapping::{ToChalk, TypeAliasAsValue, from_chalk},
- method_resolution::{ALL_FLOAT_FPS, ALL_INT_FPS, TraitImpls, TyFingerprint},
- to_assoc_type_id, to_chalk_trait_id,
- traits::ChalkContext,
- utils::ClosureSubst,
- wrap_empty_binders,
-};
-
-pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum;
-pub(crate) type TraitDatum = chalk_solve::rust_ir::TraitDatum;
-pub(crate) type AdtDatum = chalk_solve::rust_ir::AdtDatum;
-pub(crate) type ImplDatum = chalk_solve::rust_ir::ImplDatum;
-pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum;
+use crate::{Interner, Substitution, db::HirDatabase, mapping::from_chalk};
pub(crate) type AssocTypeId = chalk_ir::AssocTypeId;
pub(crate) type TraitId = chalk_ir::TraitId;
pub(crate) type AdtId = chalk_ir::AdtId;
pub(crate) type ImplId = chalk_ir::ImplId;
-pub(crate) type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId;
-pub(crate) type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue;
-pub(crate) type FnDefDatum = chalk_solve::rust_ir::FnDefDatum;
pub(crate) type Variances = chalk_ir::Variances;
-impl chalk_solve::RustIrDatabase for ChalkContext<'_> {
- fn associated_ty_data(&self, id: AssocTypeId) -> Arc {
- self.db.associated_ty_data(from_assoc_type_id(id))
- }
- fn associated_ty_from_impl(
- &self,
- impl_id: chalk_ir::ImplId,
- assoc_type_id: chalk_ir::AssocTypeId,
- ) -> Option> {
- let alias_id = from_assoc_type_id(assoc_type_id);
- let trait_sig = self.db.type_alias_signature(alias_id);
- hir_def::ImplId::from_chalk(self.db, impl_id).impl_items(self.db).items.iter().find_map(
- |(name, item)| match item {
- AssocItemId::TypeAliasId(alias) if &trait_sig.name == name => {
- Some(TypeAliasAsValue(*alias).to_chalk(self.db))
- }
- _ => None,
- },
- )
- }
- fn trait_datum(&self, trait_id: TraitId) -> Arc {
- self.db.trait_datum(self.krate, trait_id)
- }
- fn adt_datum(&self, struct_id: AdtId) -> Arc {
- self.db.adt_datum(self.krate, struct_id)
- }
- fn adt_repr(&self, _struct_id: AdtId) -> Arc> {
- // FIXME: keep track of these
- Arc::new(rust_ir::AdtRepr { c: false, packed: false, int: None })
- }
- fn discriminant_type(&self, ty: chalk_ir::Ty) -> chalk_ir::Ty {
- if let chalk_ir::TyKind::Adt(id, _) = ty.kind(Interner)
- && let hir_def::AdtId::EnumId(e) = id.0
- {
- let enum_data = self.db.enum_signature(e);
- let ty = enum_data.repr.unwrap_or_default().discr_type();
- return chalk_ir::TyKind::Scalar(match ty {
- hir_def::layout::IntegerType::Pointer(is_signed) => match is_signed {
- true => chalk_ir::Scalar::Int(chalk_ir::IntTy::Isize),
- false => chalk_ir::Scalar::Uint(chalk_ir::UintTy::Usize),
- },
- hir_def::layout::IntegerType::Fixed(size, is_signed) => match is_signed {
- true => chalk_ir::Scalar::Int(match size {
- hir_def::layout::Integer::I8 => chalk_ir::IntTy::I8,
- hir_def::layout::Integer::I16 => chalk_ir::IntTy::I16,
- hir_def::layout::Integer::I32 => chalk_ir::IntTy::I32,
- hir_def::layout::Integer::I64 => chalk_ir::IntTy::I64,
- hir_def::layout::Integer::I128 => chalk_ir::IntTy::I128,
- }),
- false => chalk_ir::Scalar::Uint(match size {
- hir_def::layout::Integer::I8 => chalk_ir::UintTy::U8,
- hir_def::layout::Integer::I16 => chalk_ir::UintTy::U16,
- hir_def::layout::Integer::I32 => chalk_ir::UintTy::U32,
- hir_def::layout::Integer::I64 => chalk_ir::UintTy::U64,
- hir_def::layout::Integer::I128 => chalk_ir::UintTy::U128,
- }),
- },
- })
- .intern(Interner);
- }
- chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::U8)).intern(Interner)
- }
- fn impl_datum(&self, impl_id: ImplId) -> Arc {
- self.db.impl_datum(self.krate, impl_id)
- }
-
- fn fn_def_datum(
- &self,
- fn_def_id: chalk_ir::FnDefId,
- ) -> Arc> {
- self.db.fn_def_datum(from_chalk(self.db, fn_def_id))
- }
-
- fn impls_for_trait(
- &self,
- trait_id: TraitId,
- parameters: &[chalk_ir::GenericArg],
- binders: &CanonicalVarKinds,
- ) -> Vec {
- debug!("impls_for_trait {:?}", trait_id);
- let trait_: hir_def::TraitId = from_chalk_trait_id(trait_id);
-
- let ty: Ty = parameters[0].assert_ty_ref(Interner).clone();
-
- fn binder_kind(
- ty: &Ty,
- binders: &CanonicalVarKinds,
- ) -> Option {
- if let TyKind::BoundVar(bv) = ty.kind(Interner) {
- let binders = binders.as_slice(Interner);
- if bv.debruijn == DebruijnIndex::INNERMOST
- && let chalk_ir::VariableKind::Ty(tk) = binders[bv.index].kind
- {
- return Some(tk);
- }
- }
- None
- }
-
- let self_ty_fp = TyFingerprint::for_trait_impl(&ty);
- let fps: &[TyFingerprint] = match binder_kind(&ty, binders) {
- Some(chalk_ir::TyVariableKind::Integer) => &ALL_INT_FPS,
- Some(chalk_ir::TyVariableKind::Float) => &ALL_FLOAT_FPS,
- _ => self_ty_fp.as_slice(),
- };
-
- let id_to_chalk = |id: hir_def::ImplId| id.to_chalk(self.db);
-
- let mut result = vec![];
- if fps.is_empty() {
- debug!("Unrestricted search for {:?} impls...", trait_);
- _ = self.for_trait_impls(trait_, self_ty_fp, |impls| {
- result.extend(impls.for_trait(trait_).map(id_to_chalk));
- ControlFlow::Continue(())
- });
- } else {
- _ =
- self.for_trait_impls(trait_, self_ty_fp, |impls| {
- result.extend(fps.iter().flat_map(move |fp| {
- impls.for_trait_and_self_ty(trait_, *fp).map(id_to_chalk)
- }));
- ControlFlow::Continue(())
- });
- };
-
- debug!("impls_for_trait returned {} impls", result.len());
- result
- }
-
- fn impl_provided_for(&self, auto_trait_id: TraitId, kind: &chalk_ir::TyKind) -> bool {
- debug!("impl_provided_for {:?}, {:?}", auto_trait_id, kind);
-
- let trait_id = from_chalk_trait_id(auto_trait_id);
- let self_ty = kind.clone().intern(Interner);
- // We cannot filter impls by `TyFingerprint` for the following types:
- let self_ty_fp = match kind {
- // because we need to find any impl whose Self type is a ref with the same mutability
- // (we don't care about the inner type).
- TyKind::Ref(..) => None,
- // because we need to find any impl whose Self type is a tuple with the same arity.
- TyKind::Tuple(..) => None,
- _ => TyFingerprint::for_trait_impl(&self_ty),
- };
-
- let check_kind = |impl_id| {
- let impl_self_ty = self.db.impl_self_ty(impl_id);
- // NOTE(skip_binders): it's safe to skip binders here as we don't check substitutions.
- let impl_self_kind = impl_self_ty.skip_binders().kind(Interner);
-
- match (kind, impl_self_kind) {
- (TyKind::Adt(id_a, _), TyKind::Adt(id_b, _)) => id_a == id_b,
- (TyKind::AssociatedType(id_a, _), TyKind::AssociatedType(id_b, _)) => id_a == id_b,
- (TyKind::Scalar(scalar_a), TyKind::Scalar(scalar_b)) => scalar_a == scalar_b,
- (TyKind::Error, TyKind::Error)
- | (TyKind::Str, TyKind::Str)
- | (TyKind::Slice(_), TyKind::Slice(_))
- | (TyKind::Never, TyKind::Never)
- | (TyKind::Array(_, _), TyKind::Array(_, _)) => true,
- (TyKind::Tuple(arity_a, _), TyKind::Tuple(arity_b, _)) => arity_a == arity_b,
- (TyKind::OpaqueType(id_a, _), TyKind::OpaqueType(id_b, _)) => id_a == id_b,
- (TyKind::FnDef(id_a, _), TyKind::FnDef(id_b, _)) => id_a == id_b,
- (TyKind::Ref(id_a, _, _), TyKind::Ref(id_b, _, _))
- | (TyKind::Raw(id_a, _), TyKind::Raw(id_b, _)) => id_a == id_b,
- (TyKind::Closure(id_a, _), TyKind::Closure(id_b, _)) => id_a == id_b,
- (TyKind::Coroutine(id_a, _), TyKind::Coroutine(id_b, _))
- | (TyKind::CoroutineWitness(id_a, _), TyKind::CoroutineWitness(id_b, _)) => {
- id_a == id_b
- }
- (TyKind::Foreign(id_a), TyKind::Foreign(id_b)) => id_a == id_b,
- (_, _) => false,
- }
- };
-
- if let Some(fp) = self_ty_fp {
- self.for_trait_impls(trait_id, self_ty_fp, |impls| {
- match impls.for_trait_and_self_ty(trait_id, fp).any(check_kind) {
- true => ControlFlow::Break(()),
- false => ControlFlow::Continue(()),
- }
- })
- } else {
- self.for_trait_impls(trait_id, self_ty_fp, |impls| {
- match impls.for_trait(trait_id).any(check_kind) {
- true => ControlFlow::Break(()),
- false => ControlFlow::Continue(()),
- }
- })
- }
- .is_break()
- }
-
- fn associated_ty_value(&self, id: AssociatedTyValueId) -> Arc {
- self.db.associated_ty_value(self.krate, id)
- }
-
- fn custom_clauses(&self) -> Vec> {
- vec![]
- }
- fn local_impls_to_coherence_check(&self, _trait_id: TraitId) -> Vec {
- // We don't do coherence checking (yet)
- unimplemented!()
- }
- fn interner(&self) -> Interner {
- Interner
- }
- fn well_known_trait_id(
- &self,
- well_known_trait: WellKnownTrait,
- ) -> Option> {
- let lang_item = lang_item_from_well_known_trait(well_known_trait);
- let trait_ = lang_item.resolve_trait(self.db, self.krate)?;
- Some(to_chalk_trait_id(trait_))
- }
- fn well_known_assoc_type_id(
- &self,
- assoc_type: rust_ir::WellKnownAssocType,
- ) -> Option> {
- let lang_item = match assoc_type {
- rust_ir::WellKnownAssocType::AsyncFnOnceOutput => LangItem::AsyncFnOnceOutput,
- };
- let alias = lang_item.resolve_type_alias(self.db, self.krate)?;
- Some(to_assoc_type_id(alias))
- }
-
- fn program_clauses_for_env(
- &self,
- environment: &chalk_ir::Environment,
- ) -> chalk_ir::ProgramClauses {
- self.db.program_clauses_for_chalk_env(self.krate, self.block, environment.clone())
- }
-
- fn opaque_ty_data(&self, id: chalk_ir::OpaqueTyId) -> Arc {
- let full_id = self.db.lookup_intern_impl_trait_id(id.into());
- let bound = match full_id {
- crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => {
- let datas = self
- .db
- .return_type_impl_traits(func)
- .expect("impl trait id without impl traits");
- let (datas, binders) = (*datas).as_ref().into_value_and_skipped_binders();
- let data = &datas.impl_traits[idx];
- let bound = OpaqueTyDatumBound {
- bounds: make_single_type_binders(data.bounds.skip_binders().to_vec()),
- where_clauses: chalk_ir::Binders::empty(Interner, vec![]),
- };
- chalk_ir::Binders::new(binders, bound)
- }
- crate::ImplTraitId::TypeAliasImplTrait(alias, idx) => {
- let datas = self
- .db
- .type_alias_impl_traits(alias)
- .expect("impl trait id without impl traits");
- let (datas, binders) = (*datas).as_ref().into_value_and_skipped_binders();
- let data = &datas.impl_traits[idx];
- let bound = OpaqueTyDatumBound {
- bounds: make_single_type_binders(data.bounds.skip_binders().to_vec()),
- where_clauses: chalk_ir::Binders::empty(Interner, vec![]),
- };
- chalk_ir::Binders::new(binders, bound)
- }
- crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => {
- if let Some((future_trait, future_output)) =
- LangItem::Future.resolve_trait(self.db, self.krate).and_then(|trait_| {
- let alias = trait_
- .trait_items(self.db)
- .associated_type_by_name(&Name::new_symbol_root(sym::Output))?;
- Some((trait_, alias))
- })
- {
- // Making up Symbol’s value as variable is void: AsyncBlock:
- //
- // |--------------------OpaqueTyDatum-------------------|
- // |-------------OpaqueTyDatumBound--------------|
- // for [Future, Future::Output = T]
- // ^1 ^0 ^0 ^0 ^1
- let impl_bound = WhereClause::Implemented(TraitRef {
- trait_id: to_chalk_trait_id(future_trait),
- // Self type as the first parameter.
- substitution: Substitution::from1(
- Interner,
- TyKind::BoundVar(BoundVar {
- debruijn: DebruijnIndex::INNERMOST,
- index: 0,
- })
- .intern(Interner),
- ),
- });
- let mut binder = vec![];
- binder.push(crate::wrap_empty_binders(impl_bound));
- let sized_trait = LangItem::Sized.resolve_trait(self.db, self.krate);
- if let Some(sized_trait_) = sized_trait {
- let sized_bound = WhereClause::Implemented(TraitRef {
- trait_id: to_chalk_trait_id(sized_trait_),
- // Self type as the first parameter.
- substitution: Substitution::from1(
- Interner,
- TyKind::BoundVar(BoundVar {
- debruijn: DebruijnIndex::INNERMOST,
- index: 0,
- })
- .intern(Interner),
- ),
- });
- binder.push(crate::wrap_empty_binders(sized_bound));
- }
- let proj_bound = WhereClause::AliasEq(AliasEq {
- alias: AliasTy::Projection(ProjectionTy {
- associated_ty_id: to_assoc_type_id(future_output),
- // Self type as the first parameter.
- substitution: Substitution::from1(
- Interner,
- TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
- .intern(Interner),
- ),
- }),
- // The parameter of the opaque type.
- ty: TyKind::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 })
- .intern(Interner),
- });
- binder.push(crate::wrap_empty_binders(proj_bound));
- let bound = OpaqueTyDatumBound {
- bounds: make_single_type_binders(binder),
- where_clauses: chalk_ir::Binders::empty(Interner, vec![]),
- };
- // The opaque type has 1 parameter.
- make_single_type_binders(bound)
- } else {
- // If failed to find Symbol’s value as variable is void: Future::Output, return empty bounds as fallback.
- let bound = OpaqueTyDatumBound {
- bounds: chalk_ir::Binders::empty(Interner, vec![]),
- where_clauses: chalk_ir::Binders::empty(Interner, vec![]),
- };
- // The opaque type has 1 parameter.
- make_single_type_binders(bound)
- }
- }
- };
-
- Arc::new(OpaqueTyDatum { opaque_ty_id: id, bound })
- }
-
- fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId) -> chalk_ir::Ty {
- // FIXME: actually provide the hidden type; it is relevant for auto traits
- TyKind::Error.intern(Interner)
- }
-
- // object safety was renamed to dyn-compatibility but still remains here in chalk.
- // This will be removed since we are going to migrate to next-gen trait solver.
- fn is_object_safe(&self, trait_id: chalk_ir::TraitId) -> bool {
- let trait_ = from_chalk_trait_id(trait_id);
- crate::dyn_compatibility::dyn_compatibility(self.db, trait_).is_none()
- }
-
- fn closure_kind(
- &self,
- _closure_id: chalk_ir::ClosureId,
- _substs: &chalk_ir::Substitution,
- ) -> rust_ir::ClosureKind {
- // Fn is the closure kind that implements all three traits
- rust_ir::ClosureKind::Fn
- }
- fn closure_inputs_and_output(
- &self,
- _closure_id: chalk_ir::ClosureId,
- substs: &chalk_ir::Substitution,
- ) -> chalk_ir::Binders> {
- let sig_ty = ClosureSubst(substs).sig_ty();
- let sig = &sig_ty.callable_sig(self.db).expect("first closure param should be fn ptr");
- let io = rust_ir::FnDefInputsAndOutputDatum {
- argument_types: sig.params().to_vec(),
- return_type: sig.ret().clone(),
- };
- chalk_ir::Binders::empty(Interner, io.shifted_in(Interner))
- }
- fn closure_upvars(
- &self,
- _closure_id: chalk_ir::ClosureId,
- _substs: &chalk_ir::Substitution,
- ) -> chalk_ir::Binders> {
- let ty = TyBuilder::unit();
- chalk_ir::Binders::empty(Interner, ty)
- }
- fn closure_fn_substitution(
- &self,
- _closure_id: chalk_ir::ClosureId,
- _substs: &chalk_ir::Substitution,
- ) -> chalk_ir::Substitution {
- Substitution::empty(Interner)
- }
-
- fn trait_name(&self, trait_id: chalk_ir::TraitId) -> String {
- let id = from_chalk_trait_id(trait_id);
- self.db.trait_signature(id).name.display(self.db, self.edition()).to_string()
- }
- fn adt_name(&self, chalk_ir::AdtId(adt_id): AdtId) -> String {
- let edition = self.edition();
- match adt_id {
- hir_def::AdtId::StructId(id) => {
- self.db.struct_signature(id).name.display(self.db, edition).to_string()
- }
- hir_def::AdtId::EnumId(id) => {
- self.db.enum_signature(id).name.display(self.db, edition).to_string()
- }
- hir_def::AdtId::UnionId(id) => {
- self.db.union_signature(id).name.display(self.db, edition).to_string()
- }
- }
- }
- fn adt_size_align(&self, _id: chalk_ir::AdtId) -> Arc {
- // FIXME
- Arc::new(rust_ir::AdtSizeAlign::from_one_zst(false))
- }
- fn assoc_type_name(&self, assoc_ty_id: chalk_ir::AssocTypeId) -> String {
- let id = self.db.associated_ty_data(from_assoc_type_id(assoc_ty_id)).name;
- self.db.type_alias_signature(id).name.display(self.db, self.edition()).to_string()
- }
- fn opaque_type_name(&self, opaque_ty_id: chalk_ir::OpaqueTyId) -> String {
- format!("Opaque_{:?}", opaque_ty_id.0)
- }
- fn fn_def_name(&self, fn_def_id: chalk_ir::FnDefId) -> String {
- format!("fn_{:?}", fn_def_id.0)
- }
- fn coroutine_datum(
- &self,
- id: chalk_ir::CoroutineId,
- ) -> Arc> {
- let InternedCoroutine(parent, expr) = self.db.lookup_intern_coroutine(id.into());
-
- // We fill substitution with unknown type, because we only need to know whether the generic
- // params are types or consts to build `Binders` and those being filled up are for
- // `resume_type`, `yield_type`, and `return_type` of the coroutine in question.
- let subst = TyBuilder::subst_for_coroutine(self.db, parent).fill_with_unknown().build();
-
- let len = subst.len(Interner);
- let input_output = rust_ir::CoroutineInputOutputDatum {
- resume_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, len - 3))
- .intern(Interner),
- yield_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, len - 2))
- .intern(Interner),
- return_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, len - 1))
- .intern(Interner),
- // FIXME: calculate upvars
- upvars: vec![],
- };
-
- let it = subst
- .iter(Interner)
- .map(|it| it.constant(Interner).map(|c| c.data(Interner).ty.clone()));
- let input_output = crate::make_type_and_const_binders(it, input_output);
-
- let movability = match self.db.body(parent)[expr] {
- hir_def::hir::Expr::Closure {
- closure_kind: hir_def::hir::ClosureKind::Coroutine(movability),
- ..
- } => movability,
- _ => unreachable!("non coroutine expression interned as coroutine"),
- };
- let movability = match movability {
- Movability::Static => rust_ir::Movability::Static,
- Movability::Movable => rust_ir::Movability::Movable,
- };
-
- Arc::new(rust_ir::CoroutineDatum { movability, input_output })
- }
- fn coroutine_witness_datum(
- &self,
- id: chalk_ir::CoroutineId,
- ) -> Arc> {
- // FIXME: calculate inner types
- let inner_types =
- rust_ir::CoroutineWitnessExistential { types: wrap_empty_binders(vec![]) };
-
- let InternedCoroutine(parent, _) = self.db.lookup_intern_coroutine(id.into());
- // See the comment in `coroutine_datum()` for unknown types.
- let subst = TyBuilder::subst_for_coroutine(self.db, parent).fill_with_unknown().build();
- let it = subst
- .iter(Interner)
- .map(|it| it.constant(Interner).map(|c| c.data(Interner).ty.clone()));
- let inner_types = crate::make_type_and_const_binders(it, inner_types);
-
- Arc::new(rust_ir::CoroutineWitnessDatum { inner_types })
- }
-
- fn unification_database(&self) -> &dyn chalk_ir::UnificationDatabase {
- &self.db
- }
-}
-
-impl ChalkContext<'_> {
- fn edition(&self) -> Edition {
- self.krate.data(self.db).edition
- }
-
- fn for_trait_impls(
- &self,
- trait_id: hir_def::TraitId,
- self_ty_fp: Option,
- mut f: impl FnMut(&TraitImpls) -> ControlFlow<()>,
- ) -> ControlFlow<()> {
- // Note: Since we're using `impls_for_trait` and `impl_provided_for`,
- // only impls where the trait can be resolved should ever reach Chalk.
- // `impl_datum` relies on that and will panic if the trait can't be resolved.
- let in_deps = self.db.trait_impls_in_deps(self.krate);
- let in_self = self.db.trait_impls_in_crate(self.krate);
- let trait_module = trait_id.module(self.db);
- let type_module = match self_ty_fp {
- Some(TyFingerprint::Adt(adt_id)) => Some(adt_id.module(self.db)),
- Some(TyFingerprint::ForeignType(type_id)) => {
- Some(from_foreign_def_id(type_id).module(self.db))
- }
- Some(TyFingerprint::Dyn(trait_id)) => Some(trait_id.module(self.db)),
- _ => None,
- };
-
- let mut def_blocks =
- [trait_module.containing_block(), type_module.and_then(|it| it.containing_block())];
-
- let block_impls = iter::successors(self.block, |&block_id| {
- cov_mark::hit!(block_local_impls);
- block_id.loc(self.db).module.containing_block()
- })
- .inspect(|&block_id| {
- // make sure we don't search the same block twice
- def_blocks.iter_mut().for_each(|block| {
- if *block == Some(block_id) {
- *block = None;
- }
- });
- })
- .filter_map(|block_id| self.db.trait_impls_in_block(block_id));
- f(&in_self)?;
- for it in in_deps.iter().map(ops::Deref::deref) {
- f(it)?;
- }
- for it in block_impls {
- f(&it)?;
- }
- for it in def_blocks.into_iter().flatten().filter_map(|it| self.db.trait_impls_in_block(it))
- {
- f(&it)?;
- }
- ControlFlow::Continue(())
- }
-}
-
impl chalk_ir::UnificationDatabase for &dyn HirDatabase {
fn fn_def_variance(
&self,
@@ -610,374 +23,6 @@ impl chalk_ir::UnificationDatabase for &dyn HirDatabase {
}
}
-pub(crate) fn program_clauses_for_chalk_env_query(
- db: &dyn HirDatabase,
- krate: Crate,
- block: Option,
- environment: chalk_ir::Environment,
-) -> chalk_ir::ProgramClauses {
- chalk_solve::program_clauses_for_env(&ChalkContext { db, krate, block }, &environment)
-}
-
-pub(crate) fn associated_ty_data_query(
- db: &dyn HirDatabase,
- type_alias: TypeAliasId,
-) -> Arc {
- debug!("associated_ty_data {:?}", type_alias);
- let trait_ = match type_alias.lookup(db).container {
- ItemContainerId::TraitId(t) => t,
- _ => panic!("associated type not in trait"),
- };
-
- // Lower bounds -- we could/should maybe move this to a separate query in `lower`
- let type_alias_data = db.type_alias_signature(type_alias);
- let generic_params = generics(db, type_alias.into());
- let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db);
- let mut ctx = crate::TyLoweringContext::new(
- db,
- &resolver,
- &type_alias_data.store,
- type_alias.into(),
- LifetimeElisionKind::AnonymousReportError,
- )
- .with_type_param_mode(crate::lower::ParamLoweringMode::Variable);
-
- let trait_subst = TyBuilder::subst_for_def(db, trait_, None)
- .fill_with_bound_vars(crate::DebruijnIndex::INNERMOST, 0)
- .build();
- let pro_ty = TyBuilder::assoc_type_projection(db, type_alias, Some(trait_subst))
- .fill_with_bound_vars(
- crate::DebruijnIndex::INNERMOST,
- generic_params.parent_generics().map_or(0, |it| it.len()),
- )
- .build();
- let self_ty = TyKind::Alias(AliasTy::Projection(pro_ty)).intern(Interner);
-
- let mut bounds = Vec::new();
- for bound in &type_alias_data.bounds {
- ctx.lower_type_bound(bound, self_ty.clone(), false).for_each(|pred| {
- if let Some(pred) = generic_predicate_to_inline_bound(db, &pred, &self_ty) {
- bounds.push(pred);
- }
- });
- }
-
- if !ctx.unsized_types.contains(&self_ty) {
- let sized_trait =
- LangItem::Sized.resolve_trait(db, resolver.krate()).map(to_chalk_trait_id);
- let sized_bound = sized_trait.into_iter().map(|sized_trait| {
- let trait_bound =
- rust_ir::TraitBound { trait_id: sized_trait, args_no_self: Default::default() };
- let inline_bound = rust_ir::InlineBound::TraitBound(trait_bound);
- chalk_ir::Binders::empty(Interner, inline_bound)
- });
- bounds.extend(sized_bound);
- bounds.shrink_to_fit();
- }
-
- // FIXME: Re-enable where clauses on associated types when an upstream chalk bug is fixed.
- // (rust-analyzer#9052)
- // let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars);
- let bound_data = rust_ir::AssociatedTyDatumBound { bounds, where_clauses: vec![] };
- let datum = AssociatedTyDatum {
- trait_id: to_chalk_trait_id(trait_),
- id: to_assoc_type_id(type_alias),
- name: type_alias,
- binders: make_binders(db, &generic_params, bound_data),
- };
- Arc::new(datum)
-}
-
-pub(crate) fn trait_datum_query(
- db: &dyn HirDatabase,
- krate: Crate,
- trait_id: TraitId,
-) -> Arc {
- debug!("trait_datum {:?}", trait_id);
- let trait_ = from_chalk_trait_id(trait_id);
- let trait_data = db.trait_signature(trait_);
- debug!("trait {:?} = {:?}", trait_id, trait_data.name);
- let generic_params = generics(db, trait_.into());
- let bound_vars = generic_params.bound_vars_subst(db, DebruijnIndex::INNERMOST);
- let flags = rust_ir::TraitFlags {
- auto: trait_data.flags.contains(TraitFlags::AUTO),
- upstream: trait_.lookup(db).container.krate() != krate,
- non_enumerable: true,
- coinductive: false, // only relevant for Chalk testing
- // FIXME: set these flags correctly
- marker: false,
- fundamental: trait_data.flags.contains(TraitFlags::FUNDAMENTAL),
- };
- let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars);
- let associated_ty_ids =
- trait_.trait_items(db).associated_types().map(to_assoc_type_id).collect();
- let trait_datum_bound = rust_ir::TraitDatumBound { where_clauses };
- let well_known = db.lang_attr(trait_.into()).and_then(well_known_trait_from_lang_item);
- let trait_datum = TraitDatum {
- id: trait_id,
- binders: make_binders(db, &generic_params, trait_datum_bound),
- flags,
- associated_ty_ids,
- well_known,
- };
- Arc::new(trait_datum)
-}
-
-fn well_known_trait_from_lang_item(item: LangItem) -> Option {
- Some(match item {
- LangItem::Clone => WellKnownTrait::Clone,
- LangItem::CoerceUnsized => WellKnownTrait::CoerceUnsized,
- LangItem::Copy => WellKnownTrait::Copy,
- LangItem::DiscriminantKind => WellKnownTrait::DiscriminantKind,
- LangItem::DispatchFromDyn => WellKnownTrait::DispatchFromDyn,
- LangItem::Drop => WellKnownTrait::Drop,
- LangItem::Fn => WellKnownTrait::Fn,
- LangItem::FnMut => WellKnownTrait::FnMut,
- LangItem::FnOnce => WellKnownTrait::FnOnce,
- LangItem::AsyncFn => WellKnownTrait::AsyncFn,
- LangItem::AsyncFnMut => WellKnownTrait::AsyncFnMut,
- LangItem::AsyncFnOnce => WellKnownTrait::AsyncFnOnce,
- LangItem::Coroutine => WellKnownTrait::Coroutine,
- LangItem::Sized => WellKnownTrait::Sized,
- LangItem::Unpin => WellKnownTrait::Unpin,
- LangItem::Unsize => WellKnownTrait::Unsize,
- LangItem::Tuple => WellKnownTrait::Tuple,
- LangItem::PointeeTrait => WellKnownTrait::Pointee,
- LangItem::FnPtrTrait => WellKnownTrait::FnPtr,
- LangItem::Future => WellKnownTrait::Future,
- _ => return None,
- })
-}
-
-fn lang_item_from_well_known_trait(trait_: WellKnownTrait) -> LangItem {
- match trait_ {
- WellKnownTrait::Clone => LangItem::Clone,
- WellKnownTrait::CoerceUnsized => LangItem::CoerceUnsized,
- WellKnownTrait::Copy => LangItem::Copy,
- WellKnownTrait::DiscriminantKind => LangItem::DiscriminantKind,
- WellKnownTrait::DispatchFromDyn => LangItem::DispatchFromDyn,
- WellKnownTrait::Drop => LangItem::Drop,
- WellKnownTrait::Fn => LangItem::Fn,
- WellKnownTrait::FnMut => LangItem::FnMut,
- WellKnownTrait::FnOnce => LangItem::FnOnce,
- WellKnownTrait::AsyncFn => LangItem::AsyncFn,
- WellKnownTrait::AsyncFnMut => LangItem::AsyncFnMut,
- WellKnownTrait::AsyncFnOnce => LangItem::AsyncFnOnce,
- WellKnownTrait::Coroutine => LangItem::Coroutine,
- WellKnownTrait::Sized => LangItem::Sized,
- WellKnownTrait::Tuple => LangItem::Tuple,
- WellKnownTrait::Unpin => LangItem::Unpin,
- WellKnownTrait::Unsize => LangItem::Unsize,
- WellKnownTrait::Pointee => LangItem::PointeeTrait,
- WellKnownTrait::FnPtr => LangItem::FnPtrTrait,
- WellKnownTrait::Future => LangItem::Future,
- }
-}
-
-pub(crate) fn adt_datum_query(
- db: &dyn HirDatabase,
- krate: Crate,
- chalk_ir::AdtId(adt_id): AdtId,
-) -> Arc {
- debug!("adt_datum {:?}", adt_id);
- let generic_params = generics(db, adt_id.into());
- let bound_vars_subst = generic_params.bound_vars_subst(db, DebruijnIndex::INNERMOST);
- let where_clauses = convert_where_clauses(db, adt_id.into(), &bound_vars_subst);
-
- let (fundamental, phantom_data) = match adt_id {
- hir_def::AdtId::StructId(s) => {
- let flags = db.struct_signature(s).flags;
- (flags.contains(StructFlags::FUNDAMENTAL), flags.contains(StructFlags::IS_PHANTOM_DATA))
- }
- // FIXME set fundamental flags correctly
- hir_def::AdtId::UnionId(_) => (false, false),
- hir_def::AdtId::EnumId(_) => (false, false),
- };
- let flags = rust_ir::AdtFlags {
- upstream: adt_id.module(db).krate() != krate,
- fundamental,
- phantom_data,
- };
-
- // this slows down rust-analyzer by quite a bit unfortunately, so enabling this is currently not worth it
- let _variant_id_to_fields = |id: VariantId| {
- let variant_data = &id.fields(db);
- let fields = if variant_data.fields().is_empty() {
- vec![]
- } else {
- let field_types = db.field_types(id);
- variant_data
- .fields()
- .iter()
- .map(|(idx, _)| field_types[idx].clone().substitute(Interner, &bound_vars_subst))
- .filter(|it| !it.contains_unknown())
- .collect()
- };
- rust_ir::AdtVariantDatum { fields }
- };
- let variant_id_to_fields = |_: VariantId| rust_ir::AdtVariantDatum { fields: vec![] };
-
- let (kind, variants) = match adt_id {
- hir_def::AdtId::StructId(id) => {
- (rust_ir::AdtKind::Struct, vec![variant_id_to_fields(id.into())])
- }
- hir_def::AdtId::EnumId(id) => {
- let variants = id
- .enum_variants(db)
- .variants
- .iter()
- .map(|&(variant_id, _, _)| variant_id_to_fields(variant_id.into()))
- .collect();
- (rust_ir::AdtKind::Enum, variants)
- }
- hir_def::AdtId::UnionId(id) => {
- (rust_ir::AdtKind::Union, vec![variant_id_to_fields(id.into())])
- }
- };
-
- let struct_datum_bound = rust_ir::AdtDatumBound { variants, where_clauses };
- let struct_datum = AdtDatum {
- kind,
- id: chalk_ir::AdtId(adt_id),
- binders: make_binders(db, &generic_params, struct_datum_bound),
- flags,
- };
- Arc::new(struct_datum)
-}
-
-pub(crate) fn impl_datum_query(
- db: &dyn HirDatabase,
- krate: Crate,
- impl_id: ImplId,
-) -> Arc {
- let _p = tracing::info_span!("impl_datum_query").entered();
- debug!("impl_datum {:?}", impl_id);
- let impl_: hir_def::ImplId = from_chalk(db, impl_id);
- impl_def_datum(db, krate, impl_)
-}
-
-fn impl_def_datum(db: &dyn HirDatabase, krate: Crate, impl_id: hir_def::ImplId) -> Arc {
- let trait_ref = db
- .impl_trait(impl_id)
- // ImplIds for impls where the trait ref can't be resolved should never reach Chalk
- .expect("invalid impl passed to Chalk")
- .into_value_and_skipped_binders()
- .0;
- let impl_data = db.impl_signature(impl_id);
-
- let generic_params = generics(db, impl_id.into());
- let bound_vars = generic_params.bound_vars_subst(db, DebruijnIndex::INNERMOST);
- let trait_ = trait_ref.hir_trait_id();
- let impl_type = if impl_id.lookup(db).container.krate() == krate {
- rust_ir::ImplType::Local
- } else {
- rust_ir::ImplType::External
- };
- let where_clauses = convert_where_clauses(db, impl_id.into(), &bound_vars);
- let negative = impl_data.flags.contains(ImplFlags::NEGATIVE);
- let polarity = if negative { rust_ir::Polarity::Negative } else { rust_ir::Polarity::Positive };
-
- let impl_datum_bound = rust_ir::ImplDatumBound { trait_ref, where_clauses };
- let trait_data = trait_.trait_items(db);
- let associated_ty_value_ids = impl_id
- .impl_items(db)
- .items
- .iter()
- .filter_map(|(_, item)| match item {
- AssocItemId::TypeAliasId(type_alias) => Some(*type_alias),
- _ => None,
- })
- .filter(|&type_alias| {
- // don't include associated types that don't exist in the trait
- let name = &db.type_alias_signature(type_alias).name;
- trait_data.associated_type_by_name(name).is_some()
- })
- .map(|type_alias| TypeAliasAsValue(type_alias).to_chalk(db))
- .collect();
- debug!("impl_datum: {:?}", impl_datum_bound);
- let impl_datum = ImplDatum {
- binders: make_binders(db, &generic_params, impl_datum_bound),
- impl_type,
- polarity,
- associated_ty_value_ids,
- };
- Arc::new(impl_datum)
-}
-
-pub(crate) fn associated_ty_value_query(
- db: &dyn HirDatabase,
- krate: Crate,
- id: AssociatedTyValueId,
-) -> Arc {
- let type_alias: TypeAliasAsValue = from_chalk(db, id);
- type_alias_associated_ty_value(db, krate, type_alias.0)
-}
-
-fn type_alias_associated_ty_value(
- db: &dyn HirDatabase,
- _krate: Crate,
- type_alias: TypeAliasId,
-) -> Arc {
- let type_alias_data = db.type_alias_signature(type_alias);
- let impl_id = match type_alias.lookup(db).container {
- ItemContainerId::ImplId(it) => it,
- _ => panic!("assoc ty value should be in impl"),
- };
-
- let trait_ref = db
- .impl_trait(impl_id)
- .expect("assoc ty value should not exist")
- .into_value_and_skipped_binders()
- .0; // we don't return any assoc ty values if the impl'd trait can't be resolved
-
- let assoc_ty = trait_ref
- .hir_trait_id()
- .trait_items(db)
- .associated_type_by_name(&type_alias_data.name)
- .expect("assoc ty value should not exist"); // validated when building the impl data as well
- let (ty, binders) = db.ty(type_alias.into()).into_value_and_skipped_binders();
- let value_bound = rust_ir::AssociatedTyValueBound { ty };
- let value = rust_ir::AssociatedTyValue {
- impl_id: impl_id.to_chalk(db),
- associated_ty_id: to_assoc_type_id(assoc_ty),
- value: chalk_ir::Binders::new(binders, value_bound),
- };
- Arc::new(value)
-}
-
-pub(crate) fn fn_def_datum_query(
- db: &dyn HirDatabase,
- callable_def: CallableDefId,
-) -> Arc {
- let generic_def = GenericDefId::from_callable(db, callable_def);
- let generic_params = generics(db, generic_def);
- let (sig, binders) = db.callable_item_signature(callable_def).into_value_and_skipped_binders();
- let bound_vars = generic_params.bound_vars_subst(db, DebruijnIndex::INNERMOST);
- let where_clauses = convert_where_clauses(db, generic_def, &bound_vars);
- let bound = rust_ir::FnDefDatumBound {
- // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway
- inputs_and_output: chalk_ir::Binders::empty(
- Interner,
- rust_ir::FnDefInputsAndOutputDatum {
- argument_types: sig.params().to_vec(),
- return_type: sig.ret().clone(),
- }
- .shifted_in(Interner),
- ),
- where_clauses,
- };
- let datum = FnDefDatum {
- id: callable_def.to_chalk(db),
- sig: chalk_ir::FnSig {
- abi: sig.abi,
- safety: chalk_ir::Safety::Safe,
- variadic: sig.is_varargs,
- },
- binders: chalk_ir::Binders::new(binders, bound),
- };
- Arc::new(datum)
-}
-
pub(crate) fn fn_def_variance_query(
db: &dyn HirDatabase,
callable_def: CallableDefId,
@@ -1021,59 +66,3 @@ pub(super) fn convert_where_clauses(
.map(|pred| pred.substitute(Interner, substs))
.collect()
}
-
-pub(super) fn generic_predicate_to_inline_bound(
- db: &dyn HirDatabase,
- pred: &QuantifiedWhereClause,
- self_ty: &Ty,
-) -> Option>> {
- // An InlineBound is like a GenericPredicate, except the self type is left out.
- // We don't have a special type for this, but Chalk does.
- let self_ty_shifted_in = self_ty.clone().shifted_in_from(Interner, DebruijnIndex::ONE);
- let (pred, binders) = pred.as_ref().into_value_and_skipped_binders();
- match pred {
- WhereClause::Implemented(trait_ref) => {
- if trait_ref.self_type_parameter(Interner) != self_ty_shifted_in {
- // we can only convert predicates back to type bounds if they
- // have the expected self type
- return None;
- }
- let args_no_self = trait_ref.substitution.as_slice(Interner)[1..]
- .iter()
- .cloned()
- .casted(Interner)
- .collect();
- let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self };
- Some(chalk_ir::Binders::new(binders, rust_ir::InlineBound::TraitBound(trait_bound)))
- }
- WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
- let generics = generics(db, from_assoc_type_id(projection_ty.associated_ty_id).into());
- let parent_len = generics.parent_generics().map_or(0, |g| g.len_self());
- let (trait_args, assoc_args) =
- projection_ty.substitution.as_slice(Interner).split_at(parent_len);
- let (self_ty, args_no_self) =
- trait_args.split_first().expect("projection without trait self type");
- if self_ty.assert_ty_ref(Interner) != &self_ty_shifted_in {
- return None;
- }
-
- let args_no_self = args_no_self.iter().cloned().casted(Interner).collect();
- let parameters = assoc_args.to_vec();
-
- let alias_eq_bound = rust_ir::AliasEqBound {
- value: ty.clone(),
- trait_bound: rust_ir::TraitBound {
- trait_id: to_chalk_trait_id(projection_ty.trait_(db)),
- args_no_self,
- },
- associated_ty_id: projection_ty.associated_ty_id,
- parameters,
- };
- Some(chalk_ir::Binders::new(
- binders,
- rust_ir::InlineBound::AliasEqBound(alias_eq_bound),
- ))
- }
- _ => None,
- }
-}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs
index 836cc96233eb8..1faf9f66dc547 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs
@@ -14,10 +14,9 @@ use hir_def::{
use crate::{
AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Canonical, CanonicalVarKinds,
ClosureId, DynTy, FnPointer, ImplTraitId, InEnvironment, Interner, Lifetime, ProjectionTy,
- QuantifiedWhereClause, Substitution, TraitRef, Ty, TyBuilder, TyKind, TypeFlags, WhereClause,
- db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
- from_placeholder_idx, generics::generics, mapping::ToChalk, to_chalk_trait_id,
- utils::ClosureSubst,
+ QuantifiedWhereClause, Substitution, ToChalk, TraitRef, Ty, TyBuilder, TyKind, TypeFlags,
+ WhereClause, db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
+ from_placeholder_idx, generics::generics, to_chalk_trait_id, utils::ClosureSubst,
};
pub trait TyExt {
@@ -211,7 +210,7 @@ impl TyExt for Ty {
match self.kind(Interner) {
TyKind::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)),
TyKind::FnDef(def, parameters) => Some(CallableSig::from_def(db, *def, parameters)),
- TyKind::Closure(.., substs) => ClosureSubst(substs).sig_ty().callable_sig(db),
+ TyKind::Closure(.., substs) => ClosureSubst(substs).sig_ty(db).callable_sig(db),
_ => None,
}
}
@@ -246,26 +245,30 @@ impl TyExt for Ty {
}
fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option> {
+ let handle_async_block_type_impl_trait = |def: DefWithBodyId| {
+ let krate = def.module(db).krate();
+ if let Some(future_trait) = LangItem::Future.resolve_trait(db, krate) {
+ // This is only used by type walking.
+ // Parameters will be walked outside, and projection predicate is not used.
+ // So just provide the Future trait.
+ let impl_bound = Binders::empty(
+ Interner,
+ WhereClause::Implemented(TraitRef {
+ trait_id: to_chalk_trait_id(future_trait),
+ substitution: Substitution::empty(Interner),
+ }),
+ );
+ Some(vec![impl_bound])
+ } else {
+ None
+ }
+ };
+
match self.kind(Interner) {
TyKind::OpaqueType(opaque_ty_id, subst) => {
match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) {
ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => {
- let krate = def.module(db).krate();
- if let Some(future_trait) = LangItem::Future.resolve_trait(db, krate) {
- // This is only used by type walking.
- // Parameters will be walked outside, and projection predicate is not used.
- // So just provide the Future trait.
- let impl_bound = Binders::empty(
- Interner,
- WhereClause::Implemented(TraitRef {
- trait_id: to_chalk_trait_id(future_trait),
- substitution: Substitution::empty(Interner),
- }),
- );
- Some(vec![impl_bound])
- } else {
- None
- }
+ handle_async_block_type_impl_trait(def)
}
ImplTraitId::ReturnTypeImplTrait(func, idx) => {
db.return_type_impl_traits(func).map(|it| {
@@ -300,14 +303,15 @@ impl TyExt for Ty {
data.substitute(Interner, &opaque_ty.substitution)
})
}
- // It always has an parameter for Future::Output type.
- ImplTraitId::AsyncBlockTypeImplTrait(..) => unreachable!(),
+ ImplTraitId::AsyncBlockTypeImplTrait(def, _) => {
+ return handle_async_block_type_impl_trait(def);
+ }
};
predicates.map(|it| it.into_value_and_skipped_binders().0)
}
TyKind::Placeholder(idx) => {
- let id = from_placeholder_idx(db, *idx);
+ let id = from_placeholder_idx(db, *idx).0;
let generic_params = db.generic_params(id.parent);
let param_data = &generic_params[id.local_id];
match param_data {
@@ -371,7 +375,7 @@ impl TyExt for Ty {
value: InEnvironment::new(&env.env, trait_ref.cast(Interner)),
binders: CanonicalVarKinds::empty(Interner),
};
- db.trait_solve(crate_id, None, goal).is_some()
+ !db.trait_solve(crate_id, None, goal).no_solution()
}
fn equals_ctor(&self, other: &Ty) -> bool {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
index f30ec839a0096..0f2cc17f563dd 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
@@ -15,8 +15,14 @@ use triomphe::Arc;
use crate::{
Const, ConstData, ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, Substitution,
- TraitEnvironment, Ty, TyBuilder, db::HirDatabase, display::DisplayTarget, generics::Generics,
- infer::InferenceContext, lower::ParamLoweringMode, to_placeholder_idx,
+ TraitEnvironment, Ty, TyBuilder,
+ db::HirDatabase,
+ display::DisplayTarget,
+ generics::Generics,
+ infer::InferenceContext,
+ lower::ParamLoweringMode,
+ next_solver::{DbInterner, mapping::ChalkToNextSolver},
+ to_placeholder_idx,
};
use super::mir::{MirEvalError, MirLowerError, interpret_mir, lower_to_mir, pad16};
@@ -101,25 +107,24 @@ pub(crate) fn path_to_const<'g>(
match resolver.resolve_path_in_value_ns_fully(db, path, HygieneId::ROOT) {
Some(ValueNs::GenericParam(p)) => {
let ty = db.const_param_ty(p);
+ let args = args();
let value = match mode {
ParamLoweringMode::Placeholder => {
- ConstValue::Placeholder(to_placeholder_idx(db, p.into()))
+ let idx = args.type_or_const_param_idx(p.into()).unwrap();
+ ConstValue::Placeholder(to_placeholder_idx(db, p.into(), idx as u32))
}
- ParamLoweringMode::Variable => {
- let args = args();
- match args.type_or_const_param_idx(p.into()) {
- Some(it) => ConstValue::BoundVar(BoundVar::new(debruijn, it)),
- None => {
- never!(
- "Generic list doesn't contain this param: {:?}, {:?}, {:?}",
- args,
- path,
- p
- );
- return None;
- }
+ ParamLoweringMode::Variable => match args.type_or_const_param_idx(p.into()) {
+ Some(it) => ConstValue::BoundVar(BoundVar::new(debruijn, it)),
+ None => {
+ never!(
+ "Generic list doesn't contain this param: {:?}, {:?}, {:?}",
+ args,
+ path,
+ p
+ );
+ return None;
}
- }
+ },
};
Some(ConstData { ty, value }.intern(Interner))
}
@@ -157,7 +162,8 @@ pub fn intern_const_ref(
ty: Ty,
krate: Crate,
) -> Const {
- let layout = || db.layout_of_ty(ty.clone(), TraitEnvironment::empty(krate));
+ let interner = DbInterner::new_with(db, Some(krate), None);
+ let layout = || db.layout_of_ty(ty.to_nextsolver(interner), TraitEnvironment::empty(krate));
let bytes = match value {
LiteralConstRef::Int(i) => {
// FIXME: We should handle failure of layout better.
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
index 6449a4dc7e8c6..299b73a7d6cc4 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
@@ -11,7 +11,7 @@ use test_utils::skip_slow_tests;
use crate::{
Const, ConstScalar, Interner, MemoryMap, consteval::try_const_usize, db::HirDatabase,
- display::DisplayTarget, mir::pad16, test_db::TestDB,
+ display::DisplayTarget, mir::pad16, setup_tracing, test_db::TestDB,
};
use super::{
@@ -76,7 +76,7 @@ fn check_str(#[rust_analyzer::rust_fixture] ra_fixture: &str, answer: &str) {
#[track_caller]
fn check_answer(
#[rust_analyzer::rust_fixture] ra_fixture: &str,
- check: impl FnOnce(&[u8], &MemoryMap),
+ check: impl FnOnce(&[u8], &MemoryMap<'_>),
) {
let (db, file_ids) = TestDB::with_many_files(ra_fixture);
let file_id = *file_ids.last().unwrap();
@@ -116,6 +116,7 @@ fn pretty_print_err(e: ConstEvalError, db: TestDB) -> String {
}
fn eval_goal(db: &TestDB, file_id: EditionedFileId) -> Result {
+ let _tracing = setup_tracing();
let module_id = db.module_for_file(file_id.file_id(db));
let def_map = module_id.def_map(db);
let scope = &def_map[module_id.local_id].scope;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval_nextsolver.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval_nextsolver.rs
new file mode 100644
index 0000000000000..6e07d3afe5524
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval_nextsolver.rs
@@ -0,0 +1,256 @@
+//! Constant evaluation details
+// FIXME(next-solver): this should get removed as things get moved to rustc_type_ir from chalk_ir
+#![allow(unused)]
+
+use base_db::Crate;
+use hir_def::{
+ EnumVariantId, GeneralConstId,
+ expr_store::{Body, HygieneId, path::Path},
+ hir::{Expr, ExprId},
+ resolver::{Resolver, ValueNs},
+ type_ref::LiteralConstRef,
+};
+use hir_expand::Lookup;
+use rustc_type_ir::{
+ UnevaluatedConst,
+ inherent::{IntoKind, SliceLike},
+};
+use stdx::never;
+use triomphe::Arc;
+
+use crate::{
+ ConstScalar, Interner, MemoryMap, Substitution, TraitEnvironment,
+ consteval::ConstEvalError,
+ db::HirDatabase,
+ generics::Generics,
+ infer::InferenceContext,
+ next_solver::{
+ Const, ConstBytes, ConstKind, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs,
+ ParamConst, SolverDefId, Ty, ValueConst,
+ mapping::{ChalkToNextSolver, NextSolverToChalk, convert_binder_to_early_binder},
+ },
+};
+
+use super::mir::{interpret_mir, lower_to_mir, pad16};
+
+pub(crate) fn path_to_const<'a, 'g>(
+ db: &'a dyn HirDatabase,
+ resolver: &Resolver<'a>,
+ path: &Path,
+ args: impl FnOnce() -> &'g Generics,
+ expected_ty: Ty<'a>,
+) -> Option> {
+ let interner = DbInterner::new_with(db, Some(resolver.krate()), None);
+ match resolver.resolve_path_in_value_ns_fully(db, path, HygieneId::ROOT) {
+ Some(ValueNs::GenericParam(p)) => {
+ let args = args();
+ match args
+ .type_or_const_param(p.into())
+ .and_then(|(idx, p)| p.const_param().map(|p| (idx, p.clone())))
+ {
+ Some((idx, _param)) => {
+ Some(Const::new_param(interner, ParamConst { index: idx as u32, id: p }))
+ }
+ None => {
+ never!(
+ "Generic list doesn't contain this param: {:?}, {:?}, {:?}",
+ args,
+ path,
+ p
+ );
+ None
+ }
+ }
+ }
+ Some(ValueNs::ConstId(c)) => {
+ let args = GenericArgs::new_from_iter(interner, []);
+ Some(Const::new(
+ interner,
+ rustc_type_ir::ConstKind::Unevaluated(UnevaluatedConst::new(
+ SolverDefId::ConstId(c),
+ args,
+ )),
+ ))
+ }
+ _ => None,
+ }
+}
+
+pub fn unknown_const<'db>(ty: Ty<'db>) -> Const<'db> {
+ Const::new(DbInterner::conjure(), rustc_type_ir::ConstKind::Error(ErrorGuaranteed))
+}
+
+pub fn unknown_const_as_generic<'db>(ty: Ty<'db>) -> GenericArg<'db> {
+ unknown_const(ty).into()
+}
+
+/// Interns a constant scalar with the given type
+pub fn intern_const_ref<'a>(
+ db: &'a dyn HirDatabase,
+ value: &LiteralConstRef,
+ ty: Ty<'a>,
+ krate: Crate,
+) -> Const<'a> {
+ let interner = DbInterner::new_with(db, Some(krate), None);
+ let layout = db.layout_of_ty(ty, TraitEnvironment::empty(krate));
+ let kind = match value {
+ LiteralConstRef::Int(i) => {
+ // FIXME: We should handle failure of layout better.
+ let size = layout.map(|it| it.size.bytes_usize()).unwrap_or(16);
+ rustc_type_ir::ConstKind::Value(ValueConst::new(
+ ty,
+ ConstBytes(i.to_le_bytes()[0..size].into(), MemoryMap::default()),
+ ))
+ }
+ LiteralConstRef::UInt(i) => {
+ let size = layout.map(|it| it.size.bytes_usize()).unwrap_or(16);
+ rustc_type_ir::ConstKind::Value(ValueConst::new(
+ ty,
+ ConstBytes(i.to_le_bytes()[0..size].into(), MemoryMap::default()),
+ ))
+ }
+ LiteralConstRef::Bool(b) => rustc_type_ir::ConstKind::Value(ValueConst::new(
+ ty,
+ ConstBytes(Box::new([*b as u8]), MemoryMap::default()),
+ )),
+ LiteralConstRef::Char(c) => rustc_type_ir::ConstKind::Value(ValueConst::new(
+ ty,
+ ConstBytes((*c as u32).to_le_bytes().into(), MemoryMap::default()),
+ )),
+ LiteralConstRef::Unknown => rustc_type_ir::ConstKind::Error(ErrorGuaranteed),
+ };
+ Const::new(interner, kind)
+}
+
+/// Interns a possibly-unknown target usize
+pub fn usize_const<'db>(db: &'db dyn HirDatabase, value: Option, krate: Crate) -> Const<'db> {
+ intern_const_ref(
+ db,
+ &value.map_or(LiteralConstRef::Unknown, LiteralConstRef::UInt),
+ Ty::new_uint(DbInterner::new_with(db, Some(krate), None), rustc_type_ir::UintTy::Usize),
+ krate,
+ )
+}
+
+pub fn try_const_usize<'db>(db: &'db dyn HirDatabase, c: Const<'db>) -> Option {
+ let interner = DbInterner::new_with(db, None, None);
+ match c.kind() {
+ ConstKind::Param(_) => None,
+ ConstKind::Infer(_) => None,
+ ConstKind::Bound(_, _) => None,
+ ConstKind::Placeholder(_) => None,
+ ConstKind::Unevaluated(unevaluated_const) => {
+ let c = match unevaluated_const.def {
+ SolverDefId::ConstId(id) => GeneralConstId::ConstId(id),
+ SolverDefId::StaticId(id) => GeneralConstId::StaticId(id),
+ _ => unreachable!(),
+ };
+ let subst = unevaluated_const.args.to_chalk(interner);
+ let ec = db.const_eval(c, subst, None).ok()?.to_nextsolver(interner);
+ try_const_usize(db, ec)
+ }
+ ConstKind::Value(val) => Some(u128::from_le_bytes(pad16(&val.value.inner().0, false))),
+ ConstKind::Error(_) => None,
+ ConstKind::Expr(_) => None,
+ }
+}
+
+pub fn try_const_isize<'db>(db: &'db dyn HirDatabase, c: &Const<'db>) -> Option {
+ let interner = DbInterner::new_with(db, None, None);
+ match (*c).kind() {
+ ConstKind::Param(_) => None,
+ ConstKind::Infer(_) => None,
+ ConstKind::Bound(_, _) => None,
+ ConstKind::Placeholder(_) => None,
+ ConstKind::Unevaluated(unevaluated_const) => {
+ let c = match unevaluated_const.def {
+ SolverDefId::ConstId(id) => GeneralConstId::ConstId(id),
+ SolverDefId::StaticId(id) => GeneralConstId::StaticId(id),
+ _ => unreachable!(),
+ };
+ let subst = unevaluated_const.args.to_chalk(interner);
+ let ec = db.const_eval(c, subst, None).ok()?.to_nextsolver(interner);
+ try_const_isize(db, &ec)
+ }
+ ConstKind::Value(val) => Some(i128::from_le_bytes(pad16(&val.value.inner().0, true))),
+ ConstKind::Error(_) => None,
+ ConstKind::Expr(_) => None,
+ }
+}
+
+pub(crate) fn const_eval_discriminant_variant(
+ db: &dyn HirDatabase,
+ variant_id: EnumVariantId,
+) -> Result {
+ let interner = DbInterner::new_with(db, None, None);
+ let def = variant_id.into();
+ let body = db.body(def);
+ let loc = variant_id.lookup(db);
+ if matches!(body[body.body_expr], Expr::Missing) {
+ let prev_idx = loc.index.checked_sub(1);
+ let value = match prev_idx {
+ Some(prev_idx) => {
+ 1 + db.const_eval_discriminant(
+ loc.parent.enum_variants(db).variants[prev_idx as usize].0,
+ )?
+ }
+ _ => 0,
+ };
+ return Ok(value);
+ }
+
+ let repr = db.enum_signature(loc.parent).repr;
+ let is_signed = repr.and_then(|repr| repr.int).is_none_or(|int| int.is_signed());
+
+ let mir_body = db.monomorphized_mir_body(
+ def,
+ Substitution::empty(Interner),
+ db.trait_environment_for_body(def),
+ )?;
+ let c = interpret_mir(db, mir_body, false, None)?.0?;
+ let c = c.to_nextsolver(interner);
+ let c = if is_signed {
+ try_const_isize(db, &c).unwrap()
+ } else {
+ try_const_usize(db, c).unwrap() as i128
+ };
+ Ok(c)
+}
+
+// FIXME: Ideally constants in const eval should have separate body (issue #7434), and this function should
+// get an `InferenceResult` instead of an `InferenceContext`. And we should remove `ctx.clone().resolve_all()` here
+// and make this function private. See the fixme comment on `InferenceContext::resolve_all`.
+pub(crate) fn eval_to_const<'db>(expr: ExprId, ctx: &mut InferenceContext<'db>) -> Const<'db> {
+ let interner = DbInterner::new_with(ctx.db, None, None);
+ let infer = ctx.clone().resolve_all();
+ fn has_closure(body: &Body, expr: ExprId) -> bool {
+ if matches!(body[expr], Expr::Closure { .. }) {
+ return true;
+ }
+ let mut r = false;
+ body.walk_child_exprs(expr, |idx| r |= has_closure(body, idx));
+ r
+ }
+ if has_closure(ctx.body, expr) {
+ // Type checking clousres need an isolated body (See the above FIXME). Bail out early to prevent panic.
+ return unknown_const(infer[expr].clone().to_nextsolver(interner));
+ }
+ if let Expr::Path(p) = &ctx.body[expr] {
+ let resolver = &ctx.resolver;
+ if let Some(c) = path_to_const(
+ ctx.db,
+ resolver,
+ p,
+ || ctx.generics(),
+ infer[expr].to_nextsolver(interner),
+ ) {
+ return c;
+ }
+ }
+ if let Ok(mir_body) = lower_to_mir(ctx.db, ctx.owner, ctx.body, &infer, expr)
+ && let Ok((Ok(result), _)) = interpret_mir(ctx.db, Arc::new(mir_body), true, None)
+ {
+ return result.to_nextsolver(interner);
+ }
+ unknown_const(infer[expr].to_nextsolver(interner))
+}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
index b3d46845c443a..448fc4aede037 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
@@ -1,9 +1,8 @@
//! The home of `HirDatabase`, which is the Salsa database containing all the
//! type inference-related queries.
-use std::sync;
-
-use base_db::{Crate, impl_intern_key};
+use base_db::Crate;
+use base_db::target::TargetLoadError;
use hir_def::{
AdtId, BlockId, CallableDefId, ConstParamId, DefWithBodyId, EnumVariantId, FunctionId,
GeneralConstId, GenericDefId, ImplId, LifetimeParamId, LocalFieldId, StaticId, TraitId,
@@ -17,7 +16,7 @@ use smallvec::SmallVec;
use triomphe::Arc;
use crate::{
- Binders, Const, ImplTraitId, ImplTraits, InferenceResult, Interner, PolyFnSig, Substitution,
+ Binders, Const, ImplTraitId, ImplTraits, InferenceResult, PolyFnSig, Substitution,
TraitEnvironment, TraitRef, Ty, TyDefId, ValueTyDefId, chalk_db,
consteval::ConstEvalError,
drop::DropGlue,
@@ -26,6 +25,7 @@ use crate::{
lower::{Diagnostics, GenericDefaults, GenericPredicates},
method_resolution::{InherentImpls, TraitImpls, TyFingerprint},
mir::{BorrowckResult, MirBody, MirLowerError},
+ traits::NextTraitSolveResult,
};
#[query_group::query_group]
@@ -93,19 +93,23 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
#[salsa::invoke(crate::layout::layout_of_adt_query)]
#[salsa::cycle(cycle_result = crate::layout::layout_of_adt_cycle_result)]
- fn layout_of_adt(
- &self,
+ fn layout_of_adt<'db>(
+ &'db self,
def: AdtId,
- subst: Substitution,
- env: Arc,
+ args: crate::next_solver::GenericArgs<'db>,
+ trait_env: Arc,
) -> Result, LayoutError>;
#[salsa::invoke(crate::layout::layout_of_ty_query)]
#[salsa::cycle(cycle_result = crate::layout::layout_of_ty_cycle_result)]
- fn layout_of_ty(&self, ty: Ty, env: Arc) -> Result, LayoutError>;
+ fn layout_of_ty<'db>(
+ &'db self,
+ ty: crate::next_solver::Ty<'db>,
+ env: Arc,
+ ) -> Result, LayoutError>;
#[salsa::invoke(crate::layout::target_data_layout_query)]
- fn target_data_layout(&self, krate: Crate) -> Result, Arc>;
+ fn target_data_layout(&self, krate: Crate) -> Result, TargetLoadError>;
#[salsa::invoke(crate::dyn_compatibility::dyn_compatibility_of_trait_query)]
fn dyn_compatibility_of_trait(&self, trait_: TraitId) -> Option;
@@ -178,16 +182,6 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
#[salsa::invoke(crate::lower::generic_predicates_query)]
fn generic_predicates(&self, def: GenericDefId) -> GenericPredicates;
- #[salsa::invoke(crate::lower::generic_predicates_without_parent_with_diagnostics_query)]
- fn generic_predicates_without_parent_with_diagnostics(
- &self,
- def: GenericDefId,
- ) -> (GenericPredicates, Diagnostics);
-
- #[salsa::invoke(crate::lower::generic_predicates_without_parent_query)]
- #[salsa::transparent]
- fn generic_predicates_without_parent(&self, def: GenericDefId) -> GenericPredicates;
-
#[salsa::invoke(crate::lower::trait_environment_for_body_query)]
#[salsa::transparent]
fn trait_environment_for_body(&self, def: DefWithBodyId) -> Arc;
@@ -245,26 +239,6 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
#[salsa::interned]
fn intern_coroutine(&self, id: InternedCoroutine) -> InternedCoroutineId;
- #[salsa::invoke(chalk_db::associated_ty_data_query)]
- fn associated_ty_data(&self, id: TypeAliasId) -> sync::Arc;
-
- #[salsa::invoke(chalk_db::trait_datum_query)]
- fn trait_datum(
- &self,
- krate: Crate,
- trait_id: chalk_db::TraitId,
- ) -> sync::Arc;
-
- #[salsa::invoke(chalk_db::adt_datum_query)]
- fn adt_datum(&self, krate: Crate, struct_id: chalk_db::AdtId) -> sync::Arc;
-
- #[salsa::invoke(chalk_db::impl_datum_query)]
- fn impl_datum(&self, krate: Crate, impl_id: chalk_db::ImplId)
- -> sync::Arc;
-
- #[salsa::invoke(chalk_db::fn_def_datum_query)]
- fn fn_def_datum(&self, fn_def_id: CallableDefId) -> sync::Arc;
-
#[salsa::invoke(chalk_db::fn_def_variance_query)]
fn fn_def_variance(&self, fn_def_id: CallableDefId) -> chalk_db::Variances;
@@ -279,13 +253,6 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
)]
fn variances_of(&self, def: GenericDefId) -> Option>;
- #[salsa::invoke(chalk_db::associated_ty_value_query)]
- fn associated_ty_value(
- &self,
- krate: Crate,
- id: chalk_db::AssociatedTyValueId,
- ) -> sync::Arc;
-
#[salsa::invoke(crate::traits::normalize_projection_query)]
#[salsa::transparent]
fn normalize_projection(
@@ -295,24 +262,153 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
) -> Ty;
#[salsa::invoke(crate::traits::trait_solve_query)]
+ #[salsa::transparent]
fn trait_solve(
&self,
krate: Crate,
block: Option,
goal: crate::Canonical>,
- ) -> Option;
-
- #[salsa::invoke(chalk_db::program_clauses_for_chalk_env_query)]
- fn program_clauses_for_chalk_env(
- &self,
- krate: Crate,
- block: Option,
- env: chalk_ir::Environment,
- ) -> chalk_ir::ProgramClauses;
+ ) -> NextTraitSolveResult;
#[salsa::invoke(crate::drop::has_drop_glue)]
#[salsa::cycle(cycle_result = crate::drop::has_drop_glue_cycle_result)]
fn has_drop_glue(&self, ty: Ty, env: Arc) -> DropGlue;
+
+ // next trait solver
+
+ #[salsa::invoke(crate::lower_nextsolver::ty_query)]
+ #[salsa::transparent]
+ fn ty_ns<'db>(
+ &'db self,
+ def: TyDefId,
+ ) -> crate::next_solver::EarlyBinder<'db, crate::next_solver::Ty<'db>>;
+
+ /// Returns the type of the value of the given constant, or `None` if the `ValueTyDefId` is
+ /// a `StructId` or `EnumVariantId` with a record constructor.
+ #[salsa::invoke(crate::lower_nextsolver::value_ty_query)]
+ fn value_ty_ns<'db>(
+ &'db self,
+ def: ValueTyDefId,
+ ) -> Option>>;
+
+ #[salsa::invoke(crate::lower_nextsolver::type_for_type_alias_with_diagnostics_query)]
+ #[salsa::cycle(cycle_result = crate::lower_nextsolver::type_for_type_alias_with_diagnostics_cycle_result)]
+ fn type_for_type_alias_with_diagnostics_ns<'db>(
+ &'db self,
+ def: TypeAliasId,
+ ) -> (crate::next_solver::EarlyBinder<'db, crate::next_solver::Ty<'db>>, Diagnostics);
+
+ #[salsa::invoke(crate::lower_nextsolver::impl_self_ty_with_diagnostics_query)]
+ #[salsa::cycle(cycle_result = crate::lower_nextsolver::impl_self_ty_with_diagnostics_cycle_result)]
+ fn impl_self_ty_with_diagnostics_ns<'db>(
+ &'db self,
+ def: ImplId,
+ ) -> (crate::next_solver::EarlyBinder<'db, crate::next_solver::Ty<'db>>, Diagnostics);
+
+ #[salsa::invoke(crate::lower_nextsolver::impl_self_ty_query)]
+ #[salsa::transparent]
+ fn impl_self_ty_ns<'db>(
+ &'db self,
+ def: ImplId,
+ ) -> crate::next_solver::EarlyBinder<'db, crate::next_solver::Ty<'db>>;
+
+ // FIXME: Make this a non-interned query.
+ #[salsa::invoke_interned(crate::lower_nextsolver::const_param_ty_with_diagnostics_query)]
+ fn const_param_ty_with_diagnostics_ns<'db>(
+ &'db self,
+ def: ConstParamId,
+ ) -> (crate::next_solver::Ty<'db>, Diagnostics);
+
+ #[salsa::invoke(crate::lower_nextsolver::const_param_ty_query)]
+ #[salsa::transparent]
+ fn const_param_ty_ns<'db>(&'db self, def: ConstParamId) -> crate::next_solver::Ty<'db>;
+
+ #[salsa::invoke(crate::lower_nextsolver::impl_trait_with_diagnostics_query)]
+ fn impl_trait_with_diagnostics_ns<'db>(
+ &'db self,
+ def: ImplId,
+ ) -> Option<(
+ crate::next_solver::EarlyBinder<'db, crate::next_solver::TraitRef<'db>>,
+ Diagnostics,
+ )>;
+
+ #[salsa::invoke(crate::lower_nextsolver::impl_trait_query)]
+ #[salsa::transparent]
+ fn impl_trait_ns<'db>(
+ &'db self,
+ def: ImplId,
+ ) -> Option>>;
+
+ #[salsa::invoke(crate::lower_nextsolver::field_types_with_diagnostics_query)]
+ fn field_types_with_diagnostics_ns<'db>(
+ &'db self,
+ var: VariantId,
+ ) -> (
+ Arc<
+ ArenaMap<
+ LocalFieldId,
+ crate::next_solver::EarlyBinder<'db, crate::next_solver::Ty<'db>>,
+ >,
+ >,
+ Diagnostics,
+ );
+
+ #[salsa::invoke(crate::lower_nextsolver::field_types_query)]
+ #[salsa::transparent]
+ fn field_types_ns<'db>(
+ &'db self,
+ var: VariantId,
+ ) -> Arc<
+ ArenaMap>>,
+ >;
+
+ #[salsa::invoke(crate::lower_nextsolver::callable_item_signature_query)]
+ fn callable_item_signature_ns<'db>(
+ &'db self,
+ def: CallableDefId,
+ ) -> crate::next_solver::EarlyBinder<'db, crate::next_solver::PolyFnSig<'db>>;
+
+ #[salsa::invoke(crate::lower_nextsolver::return_type_impl_traits)]
+ fn return_type_impl_traits_ns<'db>(
+ &'db self,
+ def: FunctionId,
+ ) -> Option>>>;
+
+ #[salsa::invoke(crate::lower_nextsolver::type_alias_impl_traits)]
+ fn type_alias_impl_traits_ns<'db>(
+ &'db self,
+ def: TypeAliasId,
+ ) -> Option>>>;
+
+ #[salsa::invoke(crate::lower_nextsolver::generic_predicates_for_param_query)]
+ #[salsa::cycle(cycle_result = crate::lower_nextsolver::generic_predicates_for_param_cycle_result)]
+ fn generic_predicates_for_param_ns<'db>(
+ &'db self,
+ def: GenericDefId,
+ param_id: TypeOrConstParamId,
+ assoc_name: Option,
+ ) -> crate::lower_nextsolver::GenericPredicates<'db>;
+
+ #[salsa::invoke(crate::lower_nextsolver::generic_predicates_query)]
+ fn generic_predicates_ns<'db>(
+ &'db self,
+ def: GenericDefId,
+ ) -> crate::lower_nextsolver::GenericPredicates<'db>;
+
+ #[salsa::invoke(
+ crate::lower_nextsolver::generic_predicates_without_parent_with_diagnostics_query
+ )]
+ fn generic_predicates_without_parent_with_diagnostics_ns<'db>(
+ &'db self,
+ def: GenericDefId,
+ ) -> (crate::lower_nextsolver::GenericPredicates<'db>, Diagnostics);
+
+ #[salsa::invoke(crate::lower_nextsolver::generic_predicates_without_parent_query)]
+ #[salsa::transparent]
+ fn generic_predicates_without_parent_ns<'db>(
+ &'db self,
+ def: GenericDefId,
+ ) -> crate::lower_nextsolver::GenericPredicates<'db>;
}
#[test]
@@ -320,40 +416,46 @@ fn hir_database_is_dyn_compatible() {
fn _assert_dyn_compatible(_: &dyn HirDatabase) {}
}
-#[salsa_macros::interned(no_lifetime, revisions = usize::MAX)]
+#[salsa_macros::interned(no_lifetime, debug, revisions = usize::MAX)]
#[derive(PartialOrd, Ord)]
pub struct InternedTypeOrConstParamId {
- pub loc: TypeOrConstParamId,
-}
-impl ::std::fmt::Debug for InternedTypeOrConstParamId {
- fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
- f.debug_tuple(stringify!(InternedTypeOrConstParamId))
- .field(&format_args!("{:04x}", self.0.index()))
- .finish()
- }
+ /// This stores the param and its index.
+ pub loc: (TypeOrConstParamId, u32),
}
-#[salsa_macros::interned(no_lifetime, revisions = usize::MAX)]
+#[salsa_macros::interned(no_lifetime, debug, revisions = usize::MAX)]
#[derive(PartialOrd, Ord)]
pub struct InternedLifetimeParamId {
- pub loc: LifetimeParamId,
-}
-impl ::std::fmt::Debug for InternedLifetimeParamId {
- fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
- f.debug_tuple(stringify!(InternedLifetimeParamId))
- .field(&format_args!("{:04x}", self.0.index()))
- .finish()
- }
+ /// This stores the param and its index.
+ pub loc: (LifetimeParamId, u32),
}
-impl_intern_key!(InternedConstParamId, ConstParamId);
+#[salsa_macros::interned(no_lifetime, debug, revisions = usize::MAX)]
+#[derive(PartialOrd, Ord)]
+pub struct InternedConstParamId {
+ pub loc: ConstParamId,
+}
-impl_intern_key!(InternedOpaqueTyId, ImplTraitId);
+#[salsa_macros::interned(no_lifetime, debug, revisions = usize::MAX)]
+#[derive(PartialOrd, Ord)]
+pub struct InternedOpaqueTyId {
+ pub loc: ImplTraitId,
+}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct InternedClosure(pub DefWithBodyId, pub ExprId);
-impl_intern_key!(InternedClosureId, InternedClosure);
+
+#[salsa_macros::interned(no_lifetime, debug, revisions = usize::MAX)]
+#[derive(PartialOrd, Ord)]
+pub struct InternedClosureId {
+ pub loc: InternedClosure,
+}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct InternedCoroutine(pub DefWithBodyId, pub ExprId);
-impl_intern_key!(InternedCoroutineId, InternedCoroutine);
+
+#[salsa_macros::interned(no_lifetime, debug, revisions = usize::MAX)]
+#[derive(PartialOrd, Ord)]
+pub struct InternedCoroutineId {
+ pub loc: InternedCoroutine,
+}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
index b26bd2b8fa9c4..403ea05a4f53c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
@@ -5,7 +5,6 @@
use std::fmt;
use base_db::Crate;
-use chalk_solve::rust_ir::AdtKind;
use either::Either;
use hir_def::{
AdtId, AssocItemId, DefWithBodyId, HasModule, ItemContainerId, Lookup,
@@ -300,11 +299,7 @@ impl ExprValidator {
value_or_partial.is_none_or(|v| !matches!(v, ValueNs::StaticId(_)))
}
Expr::Field { expr, .. } => match self.infer.type_of_expr[*expr].kind(Interner) {
- TyKind::Adt(adt, ..)
- if db.adt_datum(self.owner.krate(db), *adt).kind == AdtKind::Union =>
- {
- false
- }
+ TyKind::Adt(adt, ..) if matches!(adt.0, AdtId::UnionId(_)) => false,
_ => self.is_known_valid_scrutinee(*expr, db),
},
Expr::Index { base, .. } => self.is_known_valid_scrutinee(*base, db),
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs
index 827585e50693a..3f04b72c2fc68 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs
@@ -14,9 +14,11 @@ use hir_def::{
};
use span::Edition;
+use crate::utils::TargetFeatureIsSafeInTarget;
use crate::{
- InferenceResult, Interner, TargetFeatures, TyExt, TyKind, db::HirDatabase,
- utils::is_fn_unsafe_to_call,
+ InferenceResult, Interner, TargetFeatures, TyExt, TyKind,
+ db::HirDatabase,
+ utils::{is_fn_unsafe_to_call, target_feature_is_safe_in_target},
};
#[derive(Debug, Default)]
@@ -119,11 +121,11 @@ pub fn unsafe_operations(
def: DefWithBodyId,
body: &Body,
current: ExprId,
- callback: &mut dyn FnMut(InsideUnsafeBlock),
+ callback: &mut dyn FnMut(ExprOrPatId, InsideUnsafeBlock),
) {
let mut visitor_callback = |diag| {
- if let UnsafeDiagnostic::UnsafeOperation { inside_unsafe_block, .. } = diag {
- callback(inside_unsafe_block);
+ if let UnsafeDiagnostic::UnsafeOperation { inside_unsafe_block, node, .. } = diag {
+ callback(node, inside_unsafe_block);
}
};
let mut visitor = UnsafeVisitor::new(db, infer, body, def, &mut visitor_callback);
@@ -144,6 +146,9 @@ struct UnsafeVisitor<'db> {
def_target_features: TargetFeatures,
// FIXME: This needs to be the edition of the span of each call.
edition: Edition,
+ /// On some targets (WASM), calling safe functions with `#[target_feature]` is always safe, even when
+ /// the target feature is not enabled. This flag encodes that.
+ target_feature_is_safe: TargetFeatureIsSafeInTarget,
}
impl<'db> UnsafeVisitor<'db> {
@@ -159,7 +164,12 @@ impl<'db> UnsafeVisitor<'db> {
DefWithBodyId::FunctionId(func) => TargetFeatures::from_attrs(&db.attrs(func.into())),
_ => TargetFeatures::default(),
};
- let edition = resolver.module().krate().data(db).edition;
+ let krate = resolver.module().krate();
+ let edition = krate.data(db).edition;
+ let target_feature_is_safe = match &krate.workspace_data(db).target {
+ Ok(target) => target_feature_is_safe_in_target(target),
+ Err(_) => TargetFeatureIsSafeInTarget::No,
+ };
Self {
db,
infer,
@@ -172,6 +182,7 @@ impl<'db> UnsafeVisitor<'db> {
callback: unsafe_expr_cb,
def_target_features,
edition,
+ target_feature_is_safe,
}
}
@@ -184,7 +195,13 @@ impl<'db> UnsafeVisitor<'db> {
}
fn check_call(&mut self, node: ExprId, func: FunctionId) {
- let unsafety = is_fn_unsafe_to_call(self.db, func, &self.def_target_features, self.edition);
+ let unsafety = is_fn_unsafe_to_call(
+ self.db,
+ func,
+ &self.def_target_features,
+ self.edition,
+ self.target_feature_is_safe,
+ );
match unsafety {
crate::utils::Unsafety::Safe => {}
crate::utils::Unsafety::Unsafe => {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
index 8f35a3c214551..519e4b59237f4 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -11,7 +11,7 @@ use base_db::Crate;
use chalk_ir::{BoundVar, Safety, TyKind};
use either::Either;
use hir_def::{
- GenericDefId, HasModule, ImportPathConfig, ItemContainerId, LocalFieldId, Lookup, ModuleDefId,
+ FindPathConfig, GeneralConstId, GenericDefId, HasModule, LocalFieldId, Lookup, ModuleDefId,
ModuleId, TraitId,
db::DefDatabase,
expr_store::{ExpressionStore, path::Path},
@@ -37,26 +37,36 @@ use rustc_apfloat::{
ieee::{Half as f16, Quad as f128},
};
use rustc_hash::FxHashSet;
+use rustc_type_ir::{
+ AliasTyKind, CoroutineArgsParts, RegionKind,
+ inherent::{AdtDef, GenericArgs as _, IntoKind, SliceLike},
+};
use smallvec::SmallVec;
use span::Edition;
use stdx::never;
use triomphe::Arc;
+use crate::next_solver::infer::DbInternerInferExt;
+use crate::next_solver::infer::traits::ObligationCause;
use crate::{
- AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, ConcreteConst, Const,
- ConstScalar, ConstValue, DomainGoal, FnAbi, GenericArg, ImplTraitId, Interner, Lifetime,
- LifetimeData, LifetimeOutlives, MemoryMap, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt,
- QuantifiedWhereClause, Scalar, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty,
- TyExt, WhereClause,
- consteval::try_const_usize,
+ AliasEq, AliasTy, Binders, CallableDefId, CallableSig, ConcreteConst, Const, ConstScalar,
+ ConstValue, DomainGoal, FnAbi, GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData,
+ LifetimeOutlives, MemoryMap, OpaqueTy, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause,
+ TraitEnvironment, TraitRef, TraitRefExt, Ty, TyExt, WhereClause, consteval_nextsolver,
db::{HirDatabase, InternedClosure},
- from_assoc_type_id, from_foreign_def_id, from_placeholder_idx,
+ from_assoc_type_id, from_placeholder_idx,
generics::generics,
infer::normalize,
layout::Layout,
lt_from_placeholder_idx,
- mapping::from_chalk,
mir::pad16,
+ next_solver::{
+ BoundExistentialPredicate, DbInterner, GenericArgs, SolverDefId,
+ mapping::{
+ ChalkToNextSolver, convert_args_for_result, convert_const_for_result,
+ convert_region_for_result, convert_ty_for_result,
+ },
+ },
primitive, to_assoc_type_id,
utils::{self, ClosureSubst, detect_variant_from_bytes},
};
@@ -185,6 +195,29 @@ impl HirFormatter<'_> {
DisplayLifetime::Never => false,
}
}
+
+ fn render_region(&self, lifetime: crate::next_solver::Region<'_>) -> bool {
+ match self.display_lifetimes {
+ DisplayLifetime::Always => true,
+ DisplayLifetime::OnlyStatic => {
+ matches!(lifetime.kind(), rustc_type_ir::RegionKind::ReStatic)
+ }
+ DisplayLifetime::OnlyNamed => {
+ matches!(
+ lifetime.kind(),
+ rustc_type_ir::RegionKind::RePlaceholder(_)
+ | rustc_type_ir::RegionKind::ReEarlyParam(_)
+ )
+ }
+ DisplayLifetime::OnlyNamedOrStatic => matches!(
+ lifetime.kind(),
+ rustc_type_ir::RegionKind::ReStatic
+ | rustc_type_ir::RegionKind::RePlaceholder(_)
+ | rustc_type_ir::RegionKind::ReEarlyParam(_)
+ ),
+ DisplayLifetime::Never => false,
+ }
+ }
}
pub trait HirDisplay {
@@ -476,10 +509,6 @@ impl DisplayKind {
matches!(self, Self::SourceCode { .. })
}
- fn is_test(self) -> bool {
- matches!(self, Self::Test)
- }
-
fn allows_opaque(self) -> bool {
match self {
Self::SourceCode { allow_opaque, .. } => allow_opaque,
@@ -613,7 +642,7 @@ impl HirDisplay for ProjectionTy {
&& !f.bounds_formatting_ctx.contains(self)
{
let db = f.db;
- let id = from_placeholder_idx(db, *idx);
+ let id = from_placeholder_idx(db, *idx).0;
let generics = generics(db, id.parent);
let substs = generics.placeholder_subst(db);
@@ -688,28 +717,55 @@ impl HirDisplay for GenericArg {
}
}
+impl<'db> HirDisplay for crate::next_solver::GenericArg<'db> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
+ match self.kind() {
+ rustc_type_ir::GenericArgKind::Type(ty) => ty.hir_fmt(f),
+ rustc_type_ir::GenericArgKind::Lifetime(lt) => lt.hir_fmt(f),
+ rustc_type_ir::GenericArgKind::Const(c) => c.hir_fmt(f),
+ }
+ }
+}
+
impl HirDisplay for Const {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
- let data = self.interned();
- match &data.value {
- ConstValue::BoundVar(idx) => idx.hir_fmt(f),
- ConstValue::InferenceVar(..) => write!(f, "#c#"),
- ConstValue::Placeholder(idx) => {
- let id = from_placeholder_idx(f.db, *idx);
- let generics = generics(f.db, id.parent);
- let param_data = &generics[id.local_id];
+ let c = self.to_nextsolver(DbInterner::new_with(f.db, None, None));
+ c.hir_fmt(f)
+ }
+}
+
+impl<'db> HirDisplay for crate::next_solver::Const<'db> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
+ match self.kind() {
+ rustc_type_ir::ConstKind::Placeholder(_) => write!(f, ""),
+ rustc_type_ir::ConstKind::Bound(db, bound_const) => {
+ write!(f, "?{}.{}", db.as_u32(), bound_const.var.as_u32())
+ }
+ rustc_type_ir::ConstKind::Infer(..) => write!(f, "#c#"),
+ rustc_type_ir::ConstKind::Param(param) => {
+ let generics = generics(f.db, param.id.parent());
+ let param_data = &generics[param.id.local_id()];
write!(f, "{}", param_data.name().unwrap().display(f.db, f.edition()))?;
Ok(())
}
- ConstValue::Concrete(c) => match &c.interned {
- ConstScalar::Bytes(b, m) => render_const_scalar(f, b, m, &data.ty),
- ConstScalar::UnevaluatedConst(c, parameters) => {
- write!(f, "{}", c.name(f.db))?;
- hir_fmt_generics(f, parameters.as_slice(Interner), c.generic_def(f.db), None)?;
- Ok(())
- }
- ConstScalar::Unknown => f.write_char('_'),
- },
+ rustc_type_ir::ConstKind::Value(const_bytes) => render_const_scalar_ns(
+ f,
+ &const_bytes.value.inner().0,
+ &const_bytes.value.inner().1,
+ const_bytes.ty,
+ ),
+ rustc_type_ir::ConstKind::Unevaluated(unev) => {
+ let c = match unev.def {
+ SolverDefId::ConstId(id) => GeneralConstId::ConstId(id),
+ SolverDefId::StaticId(id) => GeneralConstId::StaticId(id),
+ _ => unreachable!(),
+ };
+ write!(f, "{}", c.name(f.db))?;
+ hir_fmt_generics_ns(f, unev.args.as_slice(), c.generic_def(f.db), None)?;
+ Ok(())
+ }
+ rustc_type_ir::ConstKind::Error(..) => f.write_char('_'),
+ rustc_type_ir::ConstKind::Expr(..) => write!(f, ""),
}
}
}
@@ -717,63 +773,90 @@ impl HirDisplay for Const {
fn render_const_scalar(
f: &mut HirFormatter<'_>,
b: &[u8],
- memory_map: &MemoryMap,
+ memory_map: &MemoryMap<'_>,
ty: &Ty,
) -> Result<(), HirDisplayError> {
let trait_env = TraitEnvironment::empty(f.krate());
+ let interner = DbInterner::new_with(f.db, Some(trait_env.krate), trait_env.block);
let ty = normalize(f.db, trait_env.clone(), ty.clone());
- match ty.kind(Interner) {
- TyKind::Scalar(s) => match s {
- Scalar::Bool => write!(f, "{}", b[0] != 0),
- Scalar::Char => {
- let it = u128::from_le_bytes(pad16(b, false)) as u32;
- let Ok(c) = char::try_from(it) else {
- return f.write_str("");
- };
- write!(f, "{c:?}")
- }
- Scalar::Int(_) => {
- let it = i128::from_le_bytes(pad16(b, true));
- write!(f, "{it}")
- }
- Scalar::Uint(_) => {
- let it = u128::from_le_bytes(pad16(b, false));
- write!(f, "{it}")
- }
- Scalar::Float(fl) => match fl {
- chalk_ir::FloatTy::F16 => {
- // FIXME(#17451): Replace with builtins once they are stabilised.
- let it = f16::from_bits(u16::from_le_bytes(b.try_into().unwrap()).into());
- let s = it.to_string();
- if s.strip_prefix('-').unwrap_or(&s).chars().all(|c| c.is_ascii_digit()) {
- // Match Rust debug formatting
- write!(f, "{s}.0")
- } else {
- write!(f, "{s}")
- }
- }
- chalk_ir::FloatTy::F32 => {
- let it = f32::from_le_bytes(b.try_into().unwrap());
- write!(f, "{it:?}")
- }
- chalk_ir::FloatTy::F64 => {
- let it = f64::from_le_bytes(b.try_into().unwrap());
- write!(f, "{it:?}")
+ let ty = ty.to_nextsolver(interner);
+ render_const_scalar_inner(f, b, memory_map, ty, trait_env)
+}
+
+fn render_const_scalar_ns(
+ f: &mut HirFormatter<'_>,
+ b: &[u8],
+ memory_map: &MemoryMap<'_>,
+ ty: crate::next_solver::Ty<'_>,
+) -> Result<(), HirDisplayError> {
+ let trait_env = TraitEnvironment::empty(f.krate());
+ let interner = DbInterner::new_with(f.db, Some(trait_env.krate), trait_env.block);
+ let infcx = interner.infer_ctxt().build(rustc_type_ir::TypingMode::PostAnalysis);
+ let ty = infcx
+ .at(&ObligationCause::new(), trait_env.env.to_nextsolver(interner))
+ .deeply_normalize(ty)
+ .unwrap_or(ty);
+ render_const_scalar_inner(f, b, memory_map, ty, trait_env)
+}
+
+fn render_const_scalar_inner(
+ f: &mut HirFormatter<'_>,
+ b: &[u8],
+ memory_map: &MemoryMap<'_>,
+ ty: crate::next_solver::Ty<'_>,
+ trait_env: Arc,
+) -> Result<(), HirDisplayError> {
+ use rustc_type_ir::TyKind;
+ match ty.kind() {
+ TyKind::Bool => write!(f, "{}", b[0] != 0),
+ TyKind::Char => {
+ let it = u128::from_le_bytes(pad16(b, false)) as u32;
+ let Ok(c) = char::try_from(it) else {
+ return f.write_str("");
+ };
+ write!(f, "{c:?}")
+ }
+ TyKind::Int(_) => {
+ let it = i128::from_le_bytes(pad16(b, true));
+ write!(f, "{it}")
+ }
+ TyKind::Uint(_) => {
+ let it = u128::from_le_bytes(pad16(b, false));
+ write!(f, "{it}")
+ }
+ TyKind::Float(fl) => match fl {
+ rustc_type_ir::FloatTy::F16 => {
+ // FIXME(#17451): Replace with builtins once they are stabilised.
+ let it = f16::from_bits(u16::from_le_bytes(b.try_into().unwrap()).into());
+ let s = it.to_string();
+ if s.strip_prefix('-').unwrap_or(&s).chars().all(|c| c.is_ascii_digit()) {
+ // Match Rust debug formatting
+ write!(f, "{s}.0")
+ } else {
+ write!(f, "{s}")
}
- chalk_ir::FloatTy::F128 => {
- // FIXME(#17451): Replace with builtins once they are stabilised.
- let it = f128::from_bits(u128::from_le_bytes(b.try_into().unwrap()));
- let s = it.to_string();
- if s.strip_prefix('-').unwrap_or(&s).chars().all(|c| c.is_ascii_digit()) {
- // Match Rust debug formatting
- write!(f, "{s}.0")
- } else {
- write!(f, "{s}")
- }
+ }
+ rustc_type_ir::FloatTy::F32 => {
+ let it = f32::from_le_bytes(b.try_into().unwrap());
+ write!(f, "{it:?}")
+ }
+ rustc_type_ir::FloatTy::F64 => {
+ let it = f64::from_le_bytes(b.try_into().unwrap());
+ write!(f, "{it:?}")
+ }
+ rustc_type_ir::FloatTy::F128 => {
+ // FIXME(#17451): Replace with builtins once they are stabilised.
+ let it = f128::from_bits(u128::from_le_bytes(b.try_into().unwrap()));
+ let s = it.to_string();
+ if s.strip_prefix('-').unwrap_or(&s).chars().all(|c| c.is_ascii_digit()) {
+ // Match Rust debug formatting
+ write!(f, "{s}.0")
+ } else {
+ write!(f, "{s}")
}
- },
+ }
},
- TyKind::Ref(_, _, t) => match t.kind(Interner) {
+ TyKind::Ref(_, t, _) => match t.kind() {
TyKind::Str => {
let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
let size = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());
@@ -786,7 +869,7 @@ fn render_const_scalar(
TyKind::Slice(ty) => {
let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
let count = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());
- let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env) else {
+ let Ok(layout) = f.db.layout_of_ty(ty, trait_env) else {
return f.write_str("");
};
let size_one = layout.size.bytes_usize();
@@ -810,17 +893,17 @@ fn render_const_scalar(
f.write_str(", ")?;
}
let offset = size_one * i;
- render_const_scalar(f, &bytes[offset..offset + size_one], memory_map, ty)?;
+ render_const_scalar_ns(f, &bytes[offset..offset + size_one], memory_map, ty)?;
}
f.write_str("]")
}
- TyKind::Dyn(_) => {
+ TyKind::Dynamic(_, _) => {
let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
let ty_id = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());
let Ok(t) = memory_map.vtable_ty(ty_id) else {
return f.write_str("");
};
- let Ok(layout) = f.db.layout_of_ty(t.clone(), trait_env) else {
+ let Ok(layout) = f.db.layout_of_ty(t, trait_env) else {
return f.write_str("");
};
let size = layout.size.bytes_usize();
@@ -828,9 +911,9 @@ fn render_const_scalar(
return f.write_str("");
};
f.write_str("&")?;
- render_const_scalar(f, bytes, memory_map, t)
+ render_const_scalar_ns(f, bytes, memory_map, t)
}
- TyKind::Adt(adt, _) if b.len() == 2 * size_of::() => match adt.0 {
+ TyKind::Adt(adt, _) if b.len() == 2 * size_of::() => match adt.def_id().0 {
hir_def::AdtId::StructId(s) => {
let data = f.db.struct_signature(s);
write!(f, "&{}", data.name.display(f.db, f.edition()))?;
@@ -850,7 +933,7 @@ fn render_const_scalar(
return f.write_str("");
}
});
- let Ok(layout) = f.db.layout_of_ty(t.clone(), trait_env) else {
+ let Ok(layout) = f.db.layout_of_ty(t, trait_env) else {
return f.write_str("");
};
let size = layout.size.bytes_usize();
@@ -858,37 +941,37 @@ fn render_const_scalar(
return f.write_str("");
};
f.write_str("&")?;
- render_const_scalar(f, bytes, memory_map, t)
+ render_const_scalar_ns(f, bytes, memory_map, t)
}
},
- TyKind::Tuple(_, subst) => {
- let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env.clone()) else {
+ TyKind::Tuple(tys) => {
+ let Ok(layout) = f.db.layout_of_ty(ty, trait_env.clone()) else {
return f.write_str("");
};
f.write_str("(")?;
let mut first = true;
- for (id, ty) in subst.iter(Interner).enumerate() {
+ for (id, ty) in tys.iter().enumerate() {
if first {
first = false;
} else {
f.write_str(", ")?;
}
- let ty = ty.assert_ty_ref(Interner); // Tuple only has type argument
let offset = layout.fields.offset(id).bytes_usize();
- let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env.clone()) else {
+ let Ok(layout) = f.db.layout_of_ty(ty, trait_env.clone()) else {
f.write_str("")?;
continue;
};
let size = layout.size.bytes_usize();
- render_const_scalar(f, &b[offset..offset + size], memory_map, ty)?;
+ render_const_scalar_ns(f, &b[offset..offset + size], memory_map, ty)?;
}
f.write_str(")")
}
- TyKind::Adt(adt, subst) => {
- let Ok(layout) = f.db.layout_of_adt(adt.0, subst.clone(), trait_env.clone()) else {
+ TyKind::Adt(def, args) => {
+ let def = def.def_id().0;
+ let Ok(layout) = f.db.layout_of_adt(def, args, trait_env.clone()) else {
return f.write_str("");
};
- match adt.0 {
+ match def {
hir_def::AdtId::StructId(s) => {
let data = f.db.struct_signature(s);
write!(f, "{}", data.name.display(f.db, f.edition()))?;
@@ -897,9 +980,9 @@ fn render_const_scalar(
s.fields(f.db),
f,
&field_types,
- f.db.trait_environment(adt.0.into()),
+ f.db.trait_environment(def.into()),
&layout,
- subst,
+ args,
b,
memory_map,
)
@@ -929,9 +1012,9 @@ fn render_const_scalar(
var_id.fields(f.db),
f,
&field_types,
- f.db.trait_environment(adt.0.into()),
+ f.db.trait_environment(def.into()),
var_layout,
- subst,
+ args,
b,
memory_map,
)
@@ -939,16 +1022,16 @@ fn render_const_scalar(
}
}
TyKind::FnDef(..) => ty.hir_fmt(f),
- TyKind::Function(_) | TyKind::Raw(_, _) => {
+ TyKind::FnPtr(_, _) | TyKind::RawPtr(_, _) => {
let it = u128::from_le_bytes(pad16(b, false));
write!(f, "{it:#X} as ")?;
ty.hir_fmt(f)
}
TyKind::Array(ty, len) => {
- let Some(len) = try_const_usize(f.db, len) else {
+ let Some(len) = consteval_nextsolver::try_const_usize(f.db, len) else {
return f.write_str("");
};
- let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env) else {
+ let Ok(layout) = f.db.layout_of_ty(ty, trait_env) else {
return f.write_str("");
};
let size_one = layout.size.bytes_usize();
@@ -961,7 +1044,7 @@ fn render_const_scalar(
f.write_str(", ")?;
}
let offset = size_one * i;
- render_const_scalar(f, &b[offset..offset + size_one], memory_map, ty)?;
+ render_const_scalar_ns(f, &b[offset..offset + size_one], memory_map, ty)?;
}
f.write_str("]")
}
@@ -969,17 +1052,19 @@ fn render_const_scalar(
TyKind::Closure(_, _) => f.write_str(""),
TyKind::Coroutine(_, _) => f.write_str(""),
TyKind::CoroutineWitness(_, _) => f.write_str(""),
+ TyKind::CoroutineClosure(_, _) => f.write_str(""),
+ TyKind::UnsafeBinder(_) => f.write_str(""),
// The below arms are unreachable, since const eval will bail out before here.
TyKind::Foreign(_) => f.write_str(""),
- TyKind::Error
+ TyKind::Pat(_, _) => f.write_str(""),
+ TyKind::Error(..)
| TyKind::Placeholder(_)
- | TyKind::Alias(_)
- | TyKind::AssociatedType(_, _)
- | TyKind::OpaqueType(_, _)
- | TyKind::BoundVar(_)
- | TyKind::InferenceVar(_, _) => f.write_str(""),
+ | TyKind::Alias(_, _)
+ | TyKind::Param(_)
+ | TyKind::Bound(_, _)
+ | TyKind::Infer(_) => f.write_str(""),
// The below arms are unreachable, since we handled them in ref case.
- TyKind::Slice(_) | TyKind::Str | TyKind::Dyn(_) => f.write_str(""),
+ TyKind::Slice(_) | TyKind::Str | TyKind::Dynamic(_, _) => f.write_str(""),
}
}
@@ -989,16 +1074,20 @@ fn render_variant_after_name(
field_types: &ArenaMap>,
trait_env: Arc,
layout: &Layout,
- subst: &Substitution,
+ args: GenericArgs<'_>,
b: &[u8],
- memory_map: &MemoryMap,
+ memory_map: &MemoryMap<'_>,
) -> Result<(), HirDisplayError> {
+ let interner = DbInterner::new_with(f.db, Some(trait_env.krate), trait_env.block);
match data.shape {
FieldsShape::Record | FieldsShape::Tuple => {
let render_field = |f: &mut HirFormatter<'_>, id: LocalFieldId| {
let offset = layout.fields.offset(u32::from(id.into_raw()) as usize).bytes_usize();
- let ty = field_types[id].clone().substitute(Interner, subst);
- let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env.clone()) else {
+ let ty = field_types[id]
+ .clone()
+ .substitute(Interner, &convert_args_for_result(interner, args.as_slice()));
+ let Ok(layout) = f.db.layout_of_ty(ty.to_nextsolver(interner), trait_env.clone())
+ else {
return f.write_str("");
};
let size = layout.size.bytes_usize();
@@ -1045,18 +1134,30 @@ impl HirDisplay for Ty {
&self,
f @ &mut HirFormatter { db, .. }: &mut HirFormatter<'_>,
) -> Result<(), HirDisplayError> {
+ let ty = self.to_nextsolver(DbInterner::new_with(db, None, None));
+ ty.hir_fmt(f)
+ }
+}
+
+impl<'db> HirDisplay for crate::next_solver::Ty<'db> {
+ fn hir_fmt(
+ &self,
+ f @ &mut HirFormatter { db, .. }: &mut HirFormatter<'_>,
+ ) -> Result<(), HirDisplayError> {
+ let interner = DbInterner::new_with(db, None, None);
if f.should_truncate() {
return write!(f, "{TYPE_HINT_TRUNCATION}");
}
- match self.kind(Interner) {
+ use rustc_type_ir::TyKind;
+ match self.kind() {
TyKind::Never => write!(f, "!")?,
TyKind::Str => write!(f, "str")?,
- TyKind::Scalar(Scalar::Bool) => write!(f, "bool")?,
- TyKind::Scalar(Scalar::Char) => write!(f, "char")?,
- &TyKind::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?,
- &TyKind::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?,
- &TyKind::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?,
+ TyKind::Bool => write!(f, "bool")?,
+ TyKind::Char => write!(f, "char")?,
+ TyKind::Float(t) => write!(f, "{}", primitive::float_ty_to_string_ns(t))?,
+ TyKind::Int(t) => write!(f, "{}", primitive::int_ty_to_string_ns(t))?,
+ TyKind::Uint(t) => write!(f, "{}", primitive::uint_ty_to_string_ns(t))?,
TyKind::Slice(t) => {
write!(f, "[")?;
t.hir_fmt(f)?;
@@ -1066,27 +1167,27 @@ impl HirDisplay for Ty {
write!(f, "[")?;
t.hir_fmt(f)?;
write!(f, "; ")?;
- c.hir_fmt(f)?;
+ convert_const_for_result(interner, c).hir_fmt(f)?;
write!(f, "]")?;
}
- kind @ (TyKind::Raw(m, t) | TyKind::Ref(m, _, t)) => {
- if let TyKind::Ref(_, l, _) = kind {
+ kind @ (TyKind::RawPtr(t, m) | TyKind::Ref(_, t, m)) => {
+ if let TyKind::Ref(l, _, _) = kind {
f.write_char('&')?;
- if f.render_lifetime(l) {
- l.hir_fmt(f)?;
+ if f.render_region(l) {
+ convert_region_for_result(interner, l).hir_fmt(f)?;
f.write_char(' ')?;
}
match m {
- Mutability::Not => (),
- Mutability::Mut => f.write_str("mut ")?,
+ rustc_ast_ir::Mutability::Not => (),
+ rustc_ast_ir::Mutability::Mut => f.write_str("mut ")?,
}
} else {
write!(
f,
"*{}",
match m {
- Mutability::Not => "const ",
- Mutability::Mut => "mut ",
+ rustc_ast_ir::Mutability::Not => "const ",
+ rustc_ast_ir::Mutability::Mut => "mut ",
}
)?;
}
@@ -1102,25 +1203,39 @@ impl HirDisplay for Ty {
}
})
};
- let (preds_to_print, has_impl_fn_pred) = match t.kind(Interner) {
- TyKind::Dyn(dyn_ty) => {
- let bounds = dyn_ty.bounds.skip_binders().interned();
- let render_lifetime = f.render_lifetime(&dyn_ty.lifetime);
- (bounds.len() + render_lifetime as usize, contains_impl_fn(bounds))
+ let contains_impl_fn_ns = |bounds: &[BoundExistentialPredicate<'_>]| {
+ bounds.iter().any(|bound| match bound.skip_binder() {
+ rustc_type_ir::ExistentialPredicate::Trait(trait_ref) => {
+ let trait_ = trait_ref.def_id.0;
+ fn_traits(db, trait_).any(|it| it == trait_)
+ }
+ _ => false,
+ })
+ };
+ let (preds_to_print, has_impl_fn_pred) = match t.kind() {
+ TyKind::Dynamic(bounds, region) => {
+ let render_lifetime = f.render_region(region);
+ (
+ bounds.len() + render_lifetime as usize,
+ contains_impl_fn_ns(bounds.as_slice()),
+ )
}
- TyKind::Alias(AliasTy::Opaque(OpaqueTy {
- opaque_ty_id,
- substitution: parameters,
- }))
- | TyKind::OpaqueType(opaque_ty_id, parameters) => {
- let impl_trait_id = db.lookup_intern_impl_trait_id((*opaque_ty_id).into());
+ TyKind::Alias(AliasTyKind::Opaque, ty) => {
+ let opaque_ty_id = match ty.def_id {
+ SolverDefId::InternedOpaqueTyId(id) => id,
+ _ => unreachable!(),
+ };
+ let impl_trait_id = db.lookup_intern_impl_trait_id(opaque_ty_id);
if let ImplTraitId::ReturnTypeImplTrait(func, idx) = impl_trait_id {
let datas = db
.return_type_impl_traits(func)
.expect("impl trait id without data");
let data =
(*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
- let bounds = data.substitute(Interner, parameters);
+ let bounds = data.substitute(
+ Interner,
+ &convert_args_for_result(interner, ty.args.as_slice()),
+ );
let mut len = bounds.skip_binders().len();
// Don't count Sized but count when it absent
@@ -1167,24 +1282,26 @@ impl HirDisplay for Ty {
t.hir_fmt(f)?;
}
}
- TyKind::Tuple(_, substs) => {
- if substs.len(Interner) == 1 {
+ TyKind::Tuple(tys) => {
+ if tys.len() == 1 {
write!(f, "(")?;
- substs.at(Interner, 0).hir_fmt(f)?;
+ tys.as_slice()[0].hir_fmt(f)?;
write!(f, ",)")?;
} else {
write!(f, "(")?;
- f.write_joined(substs.as_slice(Interner), ", ")?;
+ f.write_joined(tys.as_slice(), ", ")?;
write!(f, ")")?;
}
}
- TyKind::Function(fn_ptr) => {
- let sig = CallableSig::from_fn_ptr(fn_ptr);
+ TyKind::FnPtr(sig, header) => {
+ let sig = CallableSig::from_fn_sig_and_header(interner, sig, header);
sig.hir_fmt(f)?;
}
- TyKind::FnDef(def, parameters) => {
- let def = from_chalk(db, *def);
- let sig = db.callable_item_signature(def).substitute(Interner, parameters);
+ TyKind::FnDef(def, args) => {
+ let def = def.0;
+ let sig = db
+ .callable_item_signature(def)
+ .substitute(Interner, &convert_args_for_result(interner, args.as_slice()));
if f.display_kind.is_source_code() {
// `FnDef` is anonymous and there's no surface syntax for it. Show it as a
@@ -1222,6 +1339,7 @@ impl HirDisplay for Ty {
};
f.end_location_link();
+ let parameters = convert_args_for_result(interner, args.as_slice());
if parameters.len(Interner) > 0 {
let generic_def_id = GenericDefId::from_callable(db, def);
let generics = generics(db, generic_def_id);
@@ -1280,11 +1398,12 @@ impl HirDisplay for Ty {
ret.hir_fmt(f)?;
}
}
- TyKind::Adt(AdtId(def_id), parameters) => {
- f.start_location_link((*def_id).into());
+ TyKind::Adt(def, parameters) => {
+ let def_id = def.def_id().0;
+ f.start_location_link(def_id.into());
match f.display_kind {
DisplayKind::Diagnostics | DisplayKind::Test => {
- let name = match *def_id {
+ let name = match def_id {
hir_def::AdtId::StructId(it) => db.struct_signature(it).name.clone(),
hir_def::AdtId::UnionId(it) => db.union_signature(it).name.clone(),
hir_def::AdtId::EnumId(it) => db.enum_signature(it).name.clone(),
@@ -1294,12 +1413,12 @@ impl HirDisplay for Ty {
DisplayKind::SourceCode { target_module_id: module_id, allow_opaque: _ } => {
if let Some(path) = find_path::find_path(
db,
- ItemInNs::Types((*def_id).into()),
+ ItemInNs::Types(def_id.into()),
module_id,
PrefixKind::Plain,
false,
// FIXME: no_std Cfg?
- ImportPathConfig {
+ FindPathConfig {
prefer_no_std: false,
prefer_prelude: true,
prefer_absolute: false,
@@ -1316,55 +1435,45 @@ impl HirDisplay for Ty {
}
f.end_location_link();
- let generic_def = self.as_generic_def(db);
-
- hir_fmt_generics(f, parameters.as_slice(Interner), generic_def, None)?;
+ hir_fmt_generics(
+ f,
+ convert_args_for_result(interner, parameters.as_slice()).as_slice(Interner),
+ Some(def.def_id().0.into()),
+ None,
+ )?;
}
- TyKind::AssociatedType(assoc_type_id, parameters) => {
- let type_alias = from_assoc_type_id(*assoc_type_id);
- let trait_ = match type_alias.lookup(db).container {
- ItemContainerId::TraitId(it) => it,
- _ => panic!("not an associated type"),
+ TyKind::Alias(AliasTyKind::Projection, alias_ty) => {
+ let type_alias = match alias_ty.def_id {
+ SolverDefId::TypeAliasId(id) => id,
+ _ => unreachable!(),
};
- let trait_data = db.trait_signature(trait_);
- let type_alias_data = db.type_alias_signature(type_alias);
-
- // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types)
- if f.display_kind.is_test() {
- f.start_location_link(trait_.into());
- write!(f, "{}", trait_data.name.display(f.db, f.edition()))?;
- f.end_location_link();
- write!(f, "::")?;
+ let parameters = convert_args_for_result(interner, alias_ty.args.as_slice());
- f.start_location_link(type_alias.into());
- write!(f, "{}", type_alias_data.name.display(f.db, f.edition()))?;
- f.end_location_link();
- // Note that the generic args for the associated type come before those for the
- // trait (including the self type).
- hir_fmt_generics(f, parameters.as_slice(Interner), None, None)
- } else {
- let projection_ty = ProjectionTy {
- associated_ty_id: to_assoc_type_id(type_alias),
- substitution: parameters.clone(),
- };
+ let projection_ty = ProjectionTy {
+ associated_ty_id: to_assoc_type_id(type_alias),
+ substitution: parameters.clone(),
+ };
- projection_ty.hir_fmt(f)
- }?;
+ projection_ty.hir_fmt(f)?;
}
- TyKind::Foreign(type_alias) => {
- let alias = from_foreign_def_id(*type_alias);
- let type_alias = db.type_alias_signature(alias);
- f.start_location_link(alias.into());
+ TyKind::Foreign(alias) => {
+ let type_alias = db.type_alias_signature(alias.0);
+ f.start_location_link(alias.0.into());
write!(f, "{}", type_alias.name.display(f.db, f.edition()))?;
f.end_location_link();
}
- TyKind::OpaqueType(opaque_ty_id, parameters) => {
+ TyKind::Alias(AliasTyKind::Opaque, alias_ty) => {
+ let opaque_ty_id = match alias_ty.def_id {
+ SolverDefId::InternedOpaqueTyId(id) => id,
+ _ => unreachable!(),
+ };
+ let parameters = convert_args_for_result(interner, alias_ty.args.as_slice());
if !f.display_kind.allows_opaque() {
return Err(HirDisplayError::DisplaySourceCodeError(
DisplaySourceCodeError::OpaqueType,
));
}
- let impl_trait_id = db.lookup_intern_impl_trait_id((*opaque_ty_id).into());
+ let impl_trait_id = db.lookup_intern_impl_trait_id(opaque_ty_id);
match impl_trait_id {
ImplTraitId::ReturnTypeImplTrait(func, idx) => {
let datas =
@@ -1376,7 +1485,7 @@ impl HirDisplay for Ty {
write_bounds_like_dyn_trait_with_prefix(
f,
"impl",
- Either::Left(self),
+ Either::Left(&convert_ty_for_result(interner, *self)),
bounds.skip_binders(),
SizedByDefault::Sized { anchor: krate },
)?;
@@ -1391,7 +1500,7 @@ impl HirDisplay for Ty {
write_bounds_like_dyn_trait_with_prefix(
f,
"impl",
- Either::Left(self),
+ Either::Left(&convert_ty_for_result(interner, *self)),
bounds.skip_binders(),
SizedByDefault::Sized { anchor: krate },
)?;
@@ -1426,6 +1535,8 @@ impl HirDisplay for Ty {
}
}
TyKind::Closure(id, substs) => {
+ let id = id.0;
+ let substs = convert_args_for_result(interner, substs.as_slice());
if f.display_kind.is_source_code() {
if !f.display_kind.allows_opaque() {
return Err(HirDisplayError::DisplaySourceCodeError(
@@ -1435,22 +1546,23 @@ impl HirDisplay for Ty {
never!("Only `impl Fn` is valid for displaying closures in source code");
}
}
+ let chalk_id: chalk_ir::ClosureId<_> = id.into();
match f.closure_style {
ClosureStyle::Hide => return write!(f, "{TYPE_HINT_TRUNCATION}"),
ClosureStyle::ClosureWithId => {
- return write!(f, "{{closure#{:?}}}", id.0.index());
+ return write!(f, "{{closure#{:?}}}", chalk_id.0.index());
}
ClosureStyle::ClosureWithSubst => {
- write!(f, "{{closure#{:?}}}", id.0.index())?;
+ write!(f, "{{closure#{:?}}}", chalk_id.0.index())?;
return hir_fmt_generics(f, substs.as_slice(Interner), None, None);
}
_ => (),
}
- let sig = ClosureSubst(substs).sig_ty().callable_sig(db);
+ let sig = ClosureSubst(&substs).sig_ty(db).callable_sig(db);
if let Some(sig) = sig {
- let InternedClosure(def, _) = db.lookup_intern_closure((*id).into());
+ let InternedClosure(def, _) = db.lookup_intern_closure(id);
let infer = db.infer(def);
- let (_, kind) = infer.closure_info(id);
+ let (_, kind) = infer.closure_info(&chalk_id);
match f.closure_style {
ClosureStyle::ImplFn => write!(f, "impl {kind:?}(")?,
ClosureStyle::RANotation => write!(f, "|")?,
@@ -1477,10 +1589,10 @@ impl HirDisplay for Ty {
write!(f, "{{closure}}")?;
}
}
- TyKind::Placeholder(idx) => {
- let id = from_placeholder_idx(db, *idx);
- let generics = generics(db, id.parent);
- let param_data = &generics[id.local_id];
+ TyKind::Placeholder(_) => write!(f, "{{placeholder}}")?,
+ TyKind::Param(param) => {
+ let generics = generics(db, param.id.parent());
+ let param_data = &generics[param.id.local_id()];
match param_data {
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
@@ -1496,27 +1608,33 @@ impl HirDisplay for Ty {
TypeParamProvenance::ArgumentImplTrait => {
let substs = generics.placeholder_subst(db);
let bounds = db
- .generic_predicates(id.parent)
+ .generic_predicates(param.id.parent())
.iter()
.map(|pred| pred.clone().substitute(Interner, &substs))
.filter(|wc| match wc.skip_binders() {
WhereClause::Implemented(tr) => {
- tr.self_type_parameter(Interner) == *self
+ tr.self_type_parameter(Interner)
+ == convert_ty_for_result(interner, *self)
}
WhereClause::AliasEq(AliasEq {
alias: AliasTy::Projection(proj),
ty: _,
- }) => proj.self_type_parameter(db) == *self,
+ }) => {
+ proj.self_type_parameter(db)
+ == convert_ty_for_result(interner, *self)
+ }
WhereClause::AliasEq(_) => false,
- WhereClause::TypeOutlives(to) => to.ty == *self,
+ WhereClause::TypeOutlives(to) => {
+ to.ty == convert_ty_for_result(interner, *self)
+ }
WhereClause::LifetimeOutlives(_) => false,
})
.collect::>();
- let krate = id.parent.module(db).krate();
+ let krate = param.id.parent().module(db).krate();
write_bounds_like_dyn_trait_with_prefix(
f,
"impl",
- Either::Left(self),
+ Either::Left(&convert_ty_for_result(interner, *self)),
&bounds,
SizedByDefault::Sized { anchor: krate },
)?;
@@ -1527,8 +1645,16 @@ impl HirDisplay for Ty {
}
}
}
- TyKind::BoundVar(idx) => idx.hir_fmt(f)?,
- TyKind::Dyn(dyn_ty) => {
+ TyKind::Bound(debruijn_index, ty) => {
+ let idx = chalk_ir::BoundVar {
+ debruijn: chalk_ir::DebruijnIndex::new(debruijn_index.as_u32()),
+ index: ty.var.as_usize(),
+ };
+ idx.hir_fmt(f)?
+ }
+ TyKind::Dynamic(..) => {
+ let ty = convert_ty_for_result(interner, *self);
+ let chalk_ir::TyKind::Dyn(dyn_ty) = ty.kind(Interner) else { unreachable!() };
// Reorder bounds to satisfy `write_bounds_like_dyn_trait()`'s expectation.
// FIXME: `Iterator::partition_in_place()` or `Vec::extract_if()` may make it
// more efficient when either of them hits stable.
@@ -1544,7 +1670,7 @@ impl HirDisplay for Ty {
bounds.push(Binders::empty(
Interner,
chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives {
- ty: self.clone(),
+ ty: ty.clone(),
lifetime: dyn_ty.lifetime.clone(),
}),
));
@@ -1553,90 +1679,42 @@ impl HirDisplay for Ty {
write_bounds_like_dyn_trait_with_prefix(
f,
"dyn",
- Either::Left(self),
+ Either::Left(&ty),
&bounds,
SizedByDefault::NotSized,
)?;
}
- TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?,
- TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
- if !f.display_kind.allows_opaque() {
- return Err(HirDisplayError::DisplaySourceCodeError(
- DisplaySourceCodeError::OpaqueType,
- ));
- }
- let impl_trait_id = db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into());
- match impl_trait_id {
- ImplTraitId::ReturnTypeImplTrait(func, idx) => {
- let datas =
- db.return_type_impl_traits(func).expect("impl trait id without data");
- let data =
- (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
- let bounds = data.substitute(Interner, &opaque_ty.substitution);
- let krate = func.krate(db);
- write_bounds_like_dyn_trait_with_prefix(
- f,
- "impl",
- Either::Left(self),
- bounds.skip_binders(),
- SizedByDefault::Sized { anchor: krate },
- )?;
- }
- ImplTraitId::TypeAliasImplTrait(alias, idx) => {
- let datas =
- db.type_alias_impl_traits(alias).expect("impl trait id without data");
- let data =
- (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
- let bounds = data.substitute(Interner, &opaque_ty.substitution);
- let krate = alias.krate(db);
- write_bounds_like_dyn_trait_with_prefix(
- f,
- "impl",
- Either::Left(self),
- bounds.skip_binders(),
- SizedByDefault::Sized { anchor: krate },
- )?;
- }
- ImplTraitId::AsyncBlockTypeImplTrait(..) => {
- write!(f, "{{async block}}")?;
- }
- };
- }
- TyKind::Error => {
+ TyKind::Error(_) => {
if f.display_kind.is_source_code() {
f.write_char('_')?;
} else {
write!(f, "{{unknown}}")?;
}
}
- TyKind::InferenceVar(..) => write!(f, "_")?,
+ TyKind::Infer(..) => write!(f, "_")?,
TyKind::Coroutine(_, subst) => {
if f.display_kind.is_source_code() {
return Err(HirDisplayError::DisplaySourceCodeError(
DisplaySourceCodeError::Coroutine,
));
}
- let subst = subst.as_slice(Interner);
- let a: Option> = subst
- .get(subst.len() - 3..)
- .and_then(|args| args.iter().map(|arg| arg.ty(Interner)).collect());
+ let CoroutineArgsParts { resume_ty, yield_ty, return_ty, .. } =
+ subst.split_coroutine_args();
+ write!(f, "|")?;
+ resume_ty.hir_fmt(f)?;
+ write!(f, "|")?;
- if let Some([resume_ty, yield_ty, ret_ty]) = a.as_deref() {
- write!(f, "|")?;
- resume_ty.hir_fmt(f)?;
- write!(f, "|")?;
+ write!(f, " yields ")?;
+ yield_ty.hir_fmt(f)?;
- write!(f, " yields ")?;
- yield_ty.hir_fmt(f)?;
-
- write!(f, " -> ")?;
- ret_ty.hir_fmt(f)?;
- } else {
- // This *should* be unreachable, but fallback just in case.
- write!(f, "{{coroutine}}")?;
- }
+ write!(f, " -> ")?;
+ return_ty.hir_fmt(f)?;
}
TyKind::CoroutineWitness(..) => write!(f, "{{coroutine witness}}")?,
+ TyKind::Pat(_, _) => write!(f, "{{pat}}")?,
+ TyKind::UnsafeBinder(_) => write!(f, "{{unsafe binder}}")?,
+ TyKind::CoroutineClosure(_, _) => write!(f, "{{coroutine closure}}")?,
+ TyKind::Alias(_, _) => write!(f, "{{alias}}")?,
}
Ok(())
}
@@ -1663,6 +1741,27 @@ fn hir_fmt_generics(
Ok(())
}
+fn hir_fmt_generics_ns<'db>(
+ f: &mut HirFormatter<'_>,
+ parameters: &[crate::next_solver::GenericArg<'db>],
+ generic_def: Option,
+ self_: Option>,
+) -> Result<(), HirDisplayError> {
+ if parameters.is_empty() {
+ return Ok(());
+ }
+
+ let parameters_to_write = generic_args_sans_defaults_ns(f, generic_def, parameters);
+
+ if !parameters_to_write.is_empty() {
+ write!(f, "<")?;
+ hir_fmt_generic_arguments_ns(f, parameters_to_write, self_)?;
+ write!(f, ">")?;
+ }
+
+ Ok(())
+}
+
fn generic_args_sans_defaults<'ga>(
f: &mut HirFormatter<'_>,
generic_def: Option,
@@ -1718,6 +1817,87 @@ fn generic_args_sans_defaults<'ga>(
}
}
+fn hir_fmt_generic_args<'db>(
+ f: &mut HirFormatter<'_>,
+ parameters: &[crate::next_solver::GenericArg<'db>],
+ generic_def: Option,
+ self_: Option>,
+) -> Result<(), HirDisplayError> {
+ if parameters.is_empty() {
+ return Ok(());
+ }
+
+ let parameters_to_write = generic_args_sans_defaults_ns(f, generic_def, parameters);
+
+ if !parameters_to_write.is_empty() {
+ write!(f, "<")?;
+ hir_fmt_generic_arguments_ns(f, parameters_to_write, self_)?;
+ write!(f, ">")?;
+ }
+
+ Ok(())
+}
+
+fn generic_args_sans_defaults_ns<'ga, 'db>(
+ f: &mut HirFormatter<'_>,
+ generic_def: Option,
+ parameters: &'ga [crate::next_solver::GenericArg<'db>],
+) -> &'ga [crate::next_solver::GenericArg<'db>] {
+ let interner = DbInterner::new_with(f.db, Some(f.krate()), None);
+ if f.display_kind.is_source_code() || f.omit_verbose_types() {
+ match generic_def
+ .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
+ .filter(|it| !it.is_empty())
+ {
+ None => parameters,
+ Some(default_parameters) => {
+ let should_show = |arg: &crate::next_solver::GenericArg<'db>, i: usize| {
+ let is_err = |arg: &crate::next_solver::GenericArg<'db>| match arg.kind() {
+ rustc_type_ir::GenericArgKind::Lifetime(it) => {
+ matches!(it.kind(), RegionKind::ReError(..))
+ }
+ rustc_type_ir::GenericArgKind::Type(it) => {
+ matches!(it.kind(), rustc_type_ir::TyKind::Error(..))
+ }
+ rustc_type_ir::GenericArgKind::Const(it) => {
+ matches!(it.kind(), rustc_type_ir::ConstKind::Error(..),)
+ }
+ };
+ // if the arg is error like, render it to inform the user
+ if is_err(arg) {
+ return true;
+ }
+ // otherwise, if the arg is equal to the param default, hide it (unless the
+ // default is an error which can happen for the trait Self type)
+ match default_parameters.get(i) {
+ None => true,
+ Some(default_parameter) => {
+ // !is_err(default_parameter.skip_binders())
+ // &&
+ arg != &default_parameter
+ .clone()
+ .substitute(
+ Interner,
+ &convert_args_for_result(interner, ¶meters[..i]),
+ )
+ .to_nextsolver(interner)
+ }
+ }
+ };
+ let mut default_from = 0;
+ for (i, parameter) in parameters.iter().enumerate() {
+ if should_show(parameter, i) {
+ default_from = i + 1;
+ }
+ }
+ ¶meters[0..default_from]
+ }
+ }
+ } else {
+ parameters
+ }
+}
+
fn hir_fmt_generic_arguments(
f: &mut HirFormatter<'_>,
parameters: &[GenericArg],
@@ -1742,6 +1922,30 @@ fn hir_fmt_generic_arguments(
Ok(())
}
+fn hir_fmt_generic_arguments_ns<'db>(
+ f: &mut HirFormatter<'_>,
+ parameters: &[crate::next_solver::GenericArg<'db>],
+ self_: Option>,
+) -> Result<(), HirDisplayError> {
+ let mut first = true;
+ let lifetime_offset = parameters.iter().position(|arg| arg.region().is_some());
+
+ let (ty_or_const, lifetimes) = match lifetime_offset {
+ Some(offset) => parameters.split_at(offset),
+ None => (parameters, &[][..]),
+ };
+ for generic_arg in lifetimes.iter().chain(ty_or_const) {
+ if !mem::take(&mut first) {
+ write!(f, ", ")?;
+ }
+ match self_ {
+ self_ @ Some(_) if generic_arg.ty() == self_ => write!(f, "Self")?,
+ _ => generic_arg.hir_fmt(f)?,
+ }
+ }
+ Ok(())
+}
+
impl HirDisplay for CallableSig {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
let CallableSig { params_and_return: _, is_varargs, safety, abi: _ } = *self;
@@ -1982,6 +2186,17 @@ impl HirDisplay for TraitRef {
}
}
+impl<'db> HirDisplay for crate::next_solver::TraitRef<'db> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
+ let trait_ = self.def_id.0;
+ f.start_location_link(trait_.into());
+ write!(f, "{}", f.db.trait_signature(trait_).name.display(f.db, f.edition()))?;
+ f.end_location_link();
+ let substs = self.args.as_slice();
+ hir_fmt_generic_args(f, &substs[1..], None, substs[0].ty())
+ }
+}
+
impl HirDisplay for WhereClause {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
if f.should_truncate() {
@@ -2040,7 +2255,7 @@ impl HirDisplay for LifetimeData {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
match self {
LifetimeData::Placeholder(idx) => {
- let id = lt_from_placeholder_idx(f.db, *idx);
+ let id = lt_from_placeholder_idx(f.db, *idx).0;
let generics = generics(f.db, id.parent);
let param_data = &generics[id.local_id];
write!(f, "{}", param_data.name.display(f.db, f.edition()))?;
@@ -2062,6 +2277,34 @@ impl HirDisplay for LifetimeData {
}
}
+impl<'db> HirDisplay for crate::next_solver::Region<'db> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
+ match self.kind() {
+ rustc_type_ir::RegionKind::ReEarlyParam(param) => {
+ let generics = generics(f.db, param.id.parent);
+ let param_data = &generics[param.id.local_id];
+ write!(f, "{}", param_data.name.display(f.db, f.edition()))?;
+ Ok(())
+ }
+ rustc_type_ir::RegionKind::ReBound(db, idx) => {
+ write!(f, "?{}.{}", db.as_u32(), idx.var.as_u32())
+ }
+ rustc_type_ir::RegionKind::ReVar(_) => write!(f, "_"),
+ rustc_type_ir::RegionKind::ReStatic => write!(f, "'static"),
+ rustc_type_ir::RegionKind::ReError(..) => {
+ if cfg!(test) {
+ write!(f, "'?")
+ } else {
+ write!(f, "'_")
+ }
+ }
+ rustc_type_ir::RegionKind::ReErased => write!(f, "'"),
+ rustc_type_ir::RegionKind::RePlaceholder(_) => write!(f, ""),
+ rustc_type_ir::RegionKind::ReLateParam(_) => write!(f, ""),
+ }
+ }
+}
+
impl HirDisplay for DomainGoal {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
match self {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs
index 5577be890da34..f5c2f41069ea0 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs
@@ -120,7 +120,7 @@ pub(crate) fn has_drop_glue(db: &dyn HirDatabase, ty: Ty, env: Arc