diff options
136 files changed, 3953 insertions, 1734 deletions
diff --git a/Cargo.lock b/Cargo.lock index 9f013c275..7f666ca61 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -35,9 +35,9 @@ dependencies = [ | |||
35 | 35 | ||
36 | [[package]] | 36 | [[package]] |
37 | name = "anyhow" | 37 | name = "anyhow" |
38 | version = "1.0.38" | 38 | version = "1.0.39" |
39 | source = "registry+https://github.com/rust-lang/crates.io-index" | 39 | source = "registry+https://github.com/rust-lang/crates.io-index" |
40 | checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1" | 40 | checksum = "81cddc5f91628367664cc7c69714ff08deee8a3efc54623011c772544d7b2767" |
41 | 41 | ||
42 | [[package]] | 42 | [[package]] |
43 | name = "anymap" | 43 | name = "anymap" |
@@ -111,9 +111,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" | |||
111 | 111 | ||
112 | [[package]] | 112 | [[package]] |
113 | name = "camino" | 113 | name = "camino" |
114 | version = "1.0.2" | 114 | version = "1.0.4" |
115 | source = "registry+https://github.com/rust-lang/crates.io-index" | 115 | source = "registry+https://github.com/rust-lang/crates.io-index" |
116 | checksum = "cd065703998b183ed0b348a22555691373a9345a1431141e5778b48bb17e4703" | 116 | checksum = "d4648c6d00a709aa069a236adcaae4f605a6241c72bf5bee79331a4b625921a9" |
117 | dependencies = [ | 117 | dependencies = [ |
118 | "serde", | 118 | "serde", |
119 | ] | 119 | ] |
@@ -794,9 +794,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" | |||
794 | 794 | ||
795 | [[package]] | 795 | [[package]] |
796 | name = "libc" | 796 | name = "libc" |
797 | version = "0.2.88" | 797 | version = "0.2.91" |
798 | source = "registry+https://github.com/rust-lang/crates.io-index" | 798 | source = "registry+https://github.com/rust-lang/crates.io-index" |
799 | checksum = "03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a" | 799 | checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7" |
800 | 800 | ||
801 | [[package]] | 801 | [[package]] |
802 | name = "libloading" | 802 | name = "libloading" |
@@ -946,9 +946,9 @@ dependencies = [ | |||
946 | 946 | ||
947 | [[package]] | 947 | [[package]] |
948 | name = "mio" | 948 | name = "mio" |
949 | version = "0.7.9" | 949 | version = "0.7.11" |
950 | source = "registry+https://github.com/rust-lang/crates.io-index" | 950 | source = "registry+https://github.com/rust-lang/crates.io-index" |
951 | checksum = "a5dede4e2065b3842b8b0af444119f3aa331cc7cc2dd20388bfb0f5d5a38823a" | 951 | checksum = "cf80d3e903b34e0bd7282b218398aec54e082c840d9baf8339e0080a0c542956" |
952 | dependencies = [ | 952 | dependencies = [ |
953 | "libc", | 953 | "libc", |
954 | "log", | 954 | "log", |
@@ -959,11 +959,10 @@ dependencies = [ | |||
959 | 959 | ||
960 | [[package]] | 960 | [[package]] |
961 | name = "miow" | 961 | name = "miow" |
962 | version = "0.3.6" | 962 | version = "0.3.7" |
963 | source = "registry+https://github.com/rust-lang/crates.io-index" | 963 | source = "registry+https://github.com/rust-lang/crates.io-index" |
964 | checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897" | 964 | checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" |
965 | dependencies = [ | 965 | dependencies = [ |
966 | "socket2", | ||
967 | "winapi", | 966 | "winapi", |
968 | ] | 967 | ] |
969 | 968 | ||
@@ -1299,9 +1298,9 @@ dependencies = [ | |||
1299 | 1298 | ||
1300 | [[package]] | 1299 | [[package]] |
1301 | name = "regex" | 1300 | name = "regex" |
1302 | version = "1.4.3" | 1301 | version = "1.4.5" |
1303 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1302 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1304 | checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" | 1303 | checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19" |
1305 | dependencies = [ | 1304 | dependencies = [ |
1306 | "regex-syntax", | 1305 | "regex-syntax", |
1307 | ] | 1306 | ] |
@@ -1318,15 +1317,15 @@ dependencies = [ | |||
1318 | 1317 | ||
1319 | [[package]] | 1318 | [[package]] |
1320 | name = "regex-syntax" | 1319 | name = "regex-syntax" |
1321 | version = "0.6.22" | 1320 | version = "0.6.23" |
1322 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1321 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1323 | checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" | 1322 | checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548" |
1324 | 1323 | ||
1325 | [[package]] | 1324 | [[package]] |
1326 | name = "rowan" | 1325 | name = "rowan" |
1327 | version = "0.13.0-pre.2" | 1326 | version = "0.13.0-pre.3" |
1328 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1327 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1329 | checksum = "8f300be7fa17c3fa563d2bc6ab5b1a8d5163162f9111599eda4f86a563714724" | 1328 | checksum = "77d315d6f2e33f294412faa47f41b56bdb3fce72c999d384b5e78c8d21551b13" |
1330 | dependencies = [ | 1329 | dependencies = [ |
1331 | "countme", | 1330 | "countme", |
1332 | "hashbrown", | 1331 | "hashbrown", |
@@ -1485,18 +1484,18 @@ dependencies = [ | |||
1485 | 1484 | ||
1486 | [[package]] | 1485 | [[package]] |
1487 | name = "serde" | 1486 | name = "serde" |
1488 | version = "1.0.124" | 1487 | version = "1.0.125" |
1489 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1488 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1490 | checksum = "bd761ff957cb2a45fbb9ab3da6512de9de55872866160b23c25f1a841e99d29f" | 1489 | checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171" |
1491 | dependencies = [ | 1490 | dependencies = [ |
1492 | "serde_derive", | 1491 | "serde_derive", |
1493 | ] | 1492 | ] |
1494 | 1493 | ||
1495 | [[package]] | 1494 | [[package]] |
1496 | name = "serde_derive" | 1495 | name = "serde_derive" |
1497 | version = "1.0.124" | 1496 | version = "1.0.125" |
1498 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1497 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1499 | checksum = "1800f7693e94e186f5e25a28291ae1570da908aff7d97a095dec1e56ff99069b" | 1498 | checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d" |
1500 | dependencies = [ | 1499 | dependencies = [ |
1501 | "proc-macro2", | 1500 | "proc-macro2", |
1502 | "quote", | 1501 | "quote", |
@@ -1566,17 +1565,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
1566 | checksum = "dc725476a1398f0480d56cd0ad381f6f32acf2642704456f8f59a35df464b59a" | 1565 | checksum = "dc725476a1398f0480d56cd0ad381f6f32acf2642704456f8f59a35df464b59a" |
1567 | 1566 | ||
1568 | [[package]] | 1567 | [[package]] |
1569 | name = "socket2" | ||
1570 | version = "0.3.19" | ||
1571 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1572 | checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" | ||
1573 | dependencies = [ | ||
1574 | "cfg-if", | ||
1575 | "libc", | ||
1576 | "winapi", | ||
1577 | ] | ||
1578 | |||
1579 | [[package]] | ||
1580 | name = "stdx" | 1568 | name = "stdx" |
1581 | version = "0.0.0" | 1569 | version = "0.0.0" |
1582 | dependencies = [ | 1570 | dependencies = [ |
@@ -1586,9 +1574,9 @@ dependencies = [ | |||
1586 | 1574 | ||
1587 | [[package]] | 1575 | [[package]] |
1588 | name = "syn" | 1576 | name = "syn" |
1589 | version = "1.0.63" | 1577 | version = "1.0.64" |
1590 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1578 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1591 | checksum = "8fd9bc7ccc2688b3344c2f48b9b546648b25ce0b20fc717ee7fa7981a8ca9717" | 1579 | checksum = "3fd9d1e9976102a03c542daa2eff1b43f9d72306342f3f8b3ed5fb8908195d6f" |
1592 | dependencies = [ | 1580 | dependencies = [ |
1593 | "proc-macro2", | 1581 | "proc-macro2", |
1594 | "quote", | 1582 | "quote", |
@@ -1718,9 +1706,9 @@ dependencies = [ | |||
1718 | 1706 | ||
1719 | [[package]] | 1707 | [[package]] |
1720 | name = "tracing-attributes" | 1708 | name = "tracing-attributes" |
1721 | version = "0.1.13" | 1709 | version = "0.1.15" |
1722 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1710 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1723 | checksum = "a8a9bd1db7706f2373a190b0d067146caa39350c486f3d455b0e33b431f94c07" | 1711 | checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2" |
1724 | dependencies = [ | 1712 | dependencies = [ |
1725 | "proc-macro2", | 1713 | "proc-macro2", |
1726 | "quote", | 1714 | "quote", |
@@ -1759,9 +1747,9 @@ dependencies = [ | |||
1759 | 1747 | ||
1760 | [[package]] | 1748 | [[package]] |
1761 | name = "tracing-subscriber" | 1749 | name = "tracing-subscriber" |
1762 | version = "0.2.16" | 1750 | version = "0.2.17" |
1763 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1751 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1764 | checksum = "8ab8966ac3ca27126141f7999361cc97dd6fb4b71da04c02044fa9045d98bb96" | 1752 | checksum = "705096c6f83bf68ea5d357a6aa01829ddbdac531b357b45abeca842938085baa" |
1765 | dependencies = [ | 1753 | dependencies = [ |
1766 | "ansi_term", | 1754 | "ansi_term", |
1767 | "chrono", | 1755 | "chrono", |
@@ -1867,9 +1855,9 @@ dependencies = [ | |||
1867 | 1855 | ||
1868 | [[package]] | 1856 | [[package]] |
1869 | name = "version_check" | 1857 | name = "version_check" |
1870 | version = "0.9.2" | 1858 | version = "0.9.3" |
1871 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1859 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1872 | checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" | 1860 | checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" |
1873 | 1861 | ||
1874 | [[package]] | 1862 | [[package]] |
1875 | name = "vfs" | 1863 | name = "vfs" |
@@ -1896,9 +1884,9 @@ dependencies = [ | |||
1896 | 1884 | ||
1897 | [[package]] | 1885 | [[package]] |
1898 | name = "walkdir" | 1886 | name = "walkdir" |
1899 | version = "2.3.1" | 1887 | version = "2.3.2" |
1900 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1888 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1901 | checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" | 1889 | checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" |
1902 | dependencies = [ | 1890 | dependencies = [ |
1903 | "same-file", | 1891 | "same-file", |
1904 | "winapi", | 1892 | "winapi", |
diff --git a/crates/base_db/src/input.rs b/crates/base_db/src/input.rs index d0def2181..07628935f 100644 --- a/crates/base_db/src/input.rs +++ b/crates/base_db/src/input.rs | |||
@@ -257,7 +257,8 @@ impl CrateGraph { | |||
257 | self.arena.keys().copied() | 257 | self.arena.keys().copied() |
258 | } | 258 | } |
259 | 259 | ||
260 | /// Returns an iterator over all transitive dependencies of the given crate. | 260 | /// Returns an iterator over all transitive dependencies of the given crate, |
261 | /// including the crate itself. | ||
261 | pub fn transitive_deps(&self, of: CrateId) -> impl Iterator<Item = CrateId> + '_ { | 262 | pub fn transitive_deps(&self, of: CrateId) -> impl Iterator<Item = CrateId> + '_ { |
262 | let mut worklist = vec![of]; | 263 | let mut worklist = vec![of]; |
263 | let mut deps = FxHashSet::default(); | 264 | let mut deps = FxHashSet::default(); |
@@ -270,17 +271,16 @@ impl CrateGraph { | |||
270 | worklist.extend(self[krate].dependencies.iter().map(|dep| dep.crate_id)); | 271 | worklist.extend(self[krate].dependencies.iter().map(|dep| dep.crate_id)); |
271 | } | 272 | } |
272 | 273 | ||
273 | deps.remove(&of); | ||
274 | deps.into_iter() | 274 | deps.into_iter() |
275 | } | 275 | } |
276 | 276 | ||
277 | /// Returns an iterator over all transitive reverse dependencies of the given crate. | 277 | /// Returns all transitive reverse dependencies of the given crate, |
278 | pub fn transitive_reverse_dependencies( | 278 | /// including the crate itself. |
279 | &self, | 279 | pub fn transitive_rev_deps(&self, of: CrateId) -> impl Iterator<Item = CrateId> + '_ { |
280 | of: CrateId, | ||
281 | ) -> impl Iterator<Item = CrateId> + '_ { | ||
282 | let mut worklist = vec![of]; | 280 | let mut worklist = vec![of]; |
283 | let mut rev_deps = FxHashSet::default(); | 281 | let mut rev_deps = FxHashSet::default(); |
282 | rev_deps.insert(of); | ||
283 | |||
284 | let mut inverted_graph = FxHashMap::<_, Vec<_>>::default(); | 284 | let mut inverted_graph = FxHashMap::<_, Vec<_>>::default(); |
285 | self.arena.iter().for_each(|(&krate, data)| { | 285 | self.arena.iter().for_each(|(&krate, data)| { |
286 | data.dependencies | 286 | data.dependencies |
@@ -410,7 +410,7 @@ impl CrateId { | |||
410 | 410 | ||
411 | impl CrateData { | 411 | impl CrateData { |
412 | fn add_dep(&mut self, name: CrateName, crate_id: CrateId) { | 412 | fn add_dep(&mut self, name: CrateName, crate_id: CrateId) { |
413 | self.dependencies.push(Dependency { name, crate_id }) | 413 | self.dependencies.push(Dependency { crate_id, name }) |
414 | } | 414 | } |
415 | } | 415 | } |
416 | 416 | ||
diff --git a/crates/cfg/src/dnf.rs b/crates/cfg/src/dnf.rs index 30f4bcdf7..75ded9aa1 100644 --- a/crates/cfg/src/dnf.rs +++ b/crates/cfg/src/dnf.rs | |||
@@ -255,9 +255,9 @@ impl Builder { | |||
255 | fn make_dnf(expr: CfgExpr) -> CfgExpr { | 255 | fn make_dnf(expr: CfgExpr) -> CfgExpr { |
256 | match expr { | 256 | match expr { |
257 | CfgExpr::Invalid | CfgExpr::Atom(_) | CfgExpr::Not(_) => expr, | 257 | CfgExpr::Invalid | CfgExpr::Atom(_) | CfgExpr::Not(_) => expr, |
258 | CfgExpr::Any(e) => CfgExpr::Any(e.into_iter().map(|expr| make_dnf(expr)).collect()), | 258 | CfgExpr::Any(e) => CfgExpr::Any(e.into_iter().map(make_dnf).collect()), |
259 | CfgExpr::All(e) => { | 259 | CfgExpr::All(e) => { |
260 | let e = e.into_iter().map(|expr| make_nnf(expr)).collect::<Vec<_>>(); | 260 | let e = e.into_iter().map(make_nnf).collect::<Vec<_>>(); |
261 | 261 | ||
262 | CfgExpr::Any(distribute_conj(&e)) | 262 | CfgExpr::Any(distribute_conj(&e)) |
263 | } | 263 | } |
@@ -300,8 +300,8 @@ fn distribute_conj(conj: &[CfgExpr]) -> Vec<CfgExpr> { | |||
300 | fn make_nnf(expr: CfgExpr) -> CfgExpr { | 300 | fn make_nnf(expr: CfgExpr) -> CfgExpr { |
301 | match expr { | 301 | match expr { |
302 | CfgExpr::Invalid | CfgExpr::Atom(_) => expr, | 302 | CfgExpr::Invalid | CfgExpr::Atom(_) => expr, |
303 | CfgExpr::Any(expr) => CfgExpr::Any(expr.into_iter().map(|expr| make_nnf(expr)).collect()), | 303 | CfgExpr::Any(expr) => CfgExpr::Any(expr.into_iter().map(make_nnf).collect()), |
304 | CfgExpr::All(expr) => CfgExpr::All(expr.into_iter().map(|expr| make_nnf(expr)).collect()), | 304 | CfgExpr::All(expr) => CfgExpr::All(expr.into_iter().map(make_nnf).collect()), |
305 | CfgExpr::Not(operand) => match *operand { | 305 | CfgExpr::Not(operand) => match *operand { |
306 | CfgExpr::Invalid | CfgExpr::Atom(_) => CfgExpr::Not(operand.clone()), // Original negated expr | 306 | CfgExpr::Invalid | CfgExpr::Atom(_) => CfgExpr::Not(operand.clone()), // Original negated expr |
307 | CfgExpr::Not(expr) => { | 307 | CfgExpr::Not(expr) => { |
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 9f6d7be48..97a78ca25 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs | |||
@@ -217,7 +217,7 @@ impl HirDisplay for Variant { | |||
217 | 217 | ||
218 | impl HirDisplay for Type { | 218 | impl HirDisplay for Type { |
219 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 219 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
220 | self.ty.value.hir_fmt(f) | 220 | self.ty.hir_fmt(f) |
221 | } | 221 | } |
222 | } | 222 | } |
223 | 223 | ||
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 746b4c942..6fa676c4d 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -56,9 +56,9 @@ use hir_ty::{ | |||
56 | primitive::UintTy, | 56 | primitive::UintTy, |
57 | to_assoc_type_id, | 57 | to_assoc_type_id, |
58 | traits::{FnTrait, Solution, SolutionVariables}, | 58 | traits::{FnTrait, Solution, SolutionVariables}, |
59 | AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, Cast, DebruijnIndex, | 59 | AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, |
60 | InEnvironment, Interner, ProjectionTy, Scalar, Substitution, Ty, TyDefId, TyKind, | 60 | DebruijnIndex, InEnvironment, Interner, ProjectionTy, QuantifiedWhereClause, Scalar, |
61 | TyVariableKind, WhereClause, | 61 | Substitution, TraitEnvironment, Ty, TyDefId, TyKind, TyVariableKind, WhereClause, |
62 | }; | 62 | }; |
63 | use itertools::Itertools; | 63 | use itertools::Itertools; |
64 | use rustc_hash::FxHashSet; | 64 | use rustc_hash::FxHashSet; |
@@ -154,11 +154,7 @@ impl Crate { | |||
154 | } | 154 | } |
155 | 155 | ||
156 | pub fn transitive_reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> { | 156 | pub fn transitive_reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> { |
157 | db.crate_graph() | 157 | db.crate_graph().transitive_rev_deps(self.id).into_iter().map(|id| Crate { id }).collect() |
158 | .transitive_reverse_dependencies(self.id) | ||
159 | .into_iter() | ||
160 | .map(|id| Crate { id }) | ||
161 | .collect() | ||
162 | } | 158 | } |
163 | 159 | ||
164 | pub fn root_module(self, db: &dyn HirDatabase) -> Module { | 160 | pub fn root_module(self, db: &dyn HirDatabase) -> Module { |
@@ -213,7 +209,7 @@ impl Crate { | |||
213 | Some(TokenTree::Leaf(Leaf::Literal(Literal{ref text, ..}))) => Some(text), | 209 | Some(TokenTree::Leaf(Leaf::Literal(Literal{ref text, ..}))) => Some(text), |
214 | _ => None | 210 | _ => None |
215 | } | 211 | } |
216 | }).flat_map(|t| t).next(); | 212 | }).flatten().next(); |
217 | 213 | ||
218 | doc_url.map(|s| s.trim_matches('"').trim_end_matches('/').to_owned() + "/") | 214 | doc_url.map(|s| s.trim_matches('"').trim_end_matches('/').to_owned() + "/") |
219 | } | 215 | } |
@@ -851,17 +847,12 @@ impl Function { | |||
851 | .iter() | 847 | .iter() |
852 | .enumerate() | 848 | .enumerate() |
853 | .map(|(idx, type_ref)| { | 849 | .map(|(idx, type_ref)| { |
854 | let ty = Type { | 850 | let ty = Type { krate, env: environment.clone(), ty: ctx.lower_ty(type_ref) }; |
855 | krate, | ||
856 | ty: InEnvironment { | ||
857 | value: ctx.lower_ty(type_ref), | ||
858 | environment: environment.clone(), | ||
859 | }, | ||
860 | }; | ||
861 | Param { func: self, ty, idx } | 851 | Param { func: self, ty, idx } |
862 | }) | 852 | }) |
863 | .collect() | 853 | .collect() |
864 | } | 854 | } |
855 | |||
865 | pub fn method_params(self, db: &dyn HirDatabase) -> Option<Vec<Param>> { | 856 | pub fn method_params(self, db: &dyn HirDatabase) -> Option<Vec<Param>> { |
866 | if self.self_param(db).is_none() { | 857 | if self.self_param(db).is_none() { |
867 | return None; | 858 | return None; |
@@ -919,7 +910,7 @@ impl From<hir_ty::Mutability> for Access { | |||
919 | } | 910 | } |
920 | } | 911 | } |
921 | 912 | ||
922 | #[derive(Debug)] | 913 | #[derive(Clone, Debug)] |
923 | pub struct Param { | 914 | pub struct Param { |
924 | func: Function, | 915 | func: Function, |
925 | /// The index in parameter list, including self parameter. | 916 | /// The index in parameter list, including self parameter. |
@@ -932,13 +923,25 @@ impl Param { | |||
932 | &self.ty | 923 | &self.ty |
933 | } | 924 | } |
934 | 925 | ||
926 | pub fn as_local(&self, db: &dyn HirDatabase) -> Local { | ||
927 | let parent = DefWithBodyId::FunctionId(self.func.into()); | ||
928 | let body = db.body(parent); | ||
929 | Local { parent, pat_id: body.params[self.idx] } | ||
930 | } | ||
931 | |||
935 | pub fn pattern_source(&self, db: &dyn HirDatabase) -> Option<ast::Pat> { | 932 | pub fn pattern_source(&self, db: &dyn HirDatabase) -> Option<ast::Pat> { |
936 | let params = self.func.source(db)?.value.param_list()?; | 933 | self.source(db).and_then(|p| p.value.pat()) |
934 | } | ||
935 | |||
936 | pub fn source(&self, db: &dyn HirDatabase) -> Option<InFile<ast::Param>> { | ||
937 | let InFile { file_id, value } = self.func.source(db)?; | ||
938 | let params = value.param_list()?; | ||
937 | if params.self_param().is_some() { | 939 | if params.self_param().is_some() { |
938 | params.params().nth(self.idx.checked_sub(1)?)?.pat() | 940 | params.params().nth(self.idx.checked_sub(1)?) |
939 | } else { | 941 | } else { |
940 | params.params().nth(self.idx)?.pat() | 942 | params.params().nth(self.idx) |
941 | } | 943 | } |
944 | .map(|value| InFile { file_id, value }) | ||
942 | } | 945 | } |
943 | } | 946 | } |
944 | 947 | ||
@@ -970,6 +973,14 @@ impl SelfParam { | |||
970 | Access::Owned => "self", | 973 | Access::Owned => "self", |
971 | } | 974 | } |
972 | } | 975 | } |
976 | |||
977 | pub fn source(&self, db: &dyn HirDatabase) -> Option<InFile<ast::SelfParam>> { | ||
978 | let InFile { file_id, value } = Function::from(self.func).source(db)?; | ||
979 | value | ||
980 | .param_list() | ||
981 | .and_then(|params| params.self_param()) | ||
982 | .map(|value| InFile { file_id, value }) | ||
983 | } | ||
973 | } | 984 | } |
974 | 985 | ||
975 | impl HasVisibility for Function { | 986 | impl HasVisibility for Function { |
@@ -1127,6 +1138,14 @@ impl BuiltinType { | |||
1127 | } | 1138 | } |
1128 | 1139 | ||
1129 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 1140 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
1141 | pub enum MacroKind { | ||
1142 | Declarative, | ||
1143 | ProcMacro, | ||
1144 | Derive, | ||
1145 | BuiltIn, | ||
1146 | } | ||
1147 | |||
1148 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
1130 | pub struct MacroDef { | 1149 | pub struct MacroDef { |
1131 | pub(crate) id: MacroDefId, | 1150 | pub(crate) id: MacroDefId, |
1132 | } | 1151 | } |
@@ -1150,15 +1169,15 @@ impl MacroDef { | |||
1150 | } | 1169 | } |
1151 | } | 1170 | } |
1152 | 1171 | ||
1153 | /// Indicate it is a proc-macro | 1172 | pub fn kind(&self) -> MacroKind { |
1154 | pub fn is_proc_macro(&self) -> bool { | 1173 | match self.id.kind { |
1155 | matches!(self.id.kind, MacroDefKind::ProcMacro(..)) | 1174 | MacroDefKind::Declarative(_) => MacroKind::Declarative, |
1156 | } | 1175 | MacroDefKind::BuiltIn(_, _) => MacroKind::BuiltIn, |
1157 | 1176 | MacroDefKind::BuiltInDerive(_, _) => MacroKind::Derive, | |
1158 | /// Indicate it is a derive macro | 1177 | MacroDefKind::BuiltInEager(_, _) => MacroKind::BuiltIn, |
1159 | pub fn is_derive_macro(&self) -> bool { | 1178 | // FIXME might be a derive |
1160 | // FIXME: wrong for `ProcMacro` | 1179 | MacroDefKind::ProcMacro(_, _) => MacroKind::ProcMacro, |
1161 | matches!(self.id.kind, MacroDefKind::ProcMacro(..) | MacroDefKind::BuiltInDerive(..)) | 1180 | } |
1162 | } | 1181 | } |
1163 | } | 1182 | } |
1164 | 1183 | ||
@@ -1337,6 +1356,13 @@ impl Local { | |||
1337 | } | 1356 | } |
1338 | } | 1357 | } |
1339 | 1358 | ||
1359 | pub fn as_self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> { | ||
1360 | match self.parent { | ||
1361 | DefWithBodyId::FunctionId(func) if self.is_self(db) => Some(SelfParam { func }), | ||
1362 | _ => None, | ||
1363 | } | ||
1364 | } | ||
1365 | |||
1340 | // FIXME: why is this an option? It shouldn't be? | 1366 | // FIXME: why is this an option? It shouldn't be? |
1341 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | 1367 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { |
1342 | let body = db.body(self.parent); | 1368 | let body = db.body(self.parent); |
@@ -1460,7 +1486,7 @@ impl TypeParam { | |||
1460 | pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> { | 1486 | pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> { |
1461 | db.generic_predicates_for_param(self.id) | 1487 | db.generic_predicates_for_param(self.id) |
1462 | .into_iter() | 1488 | .into_iter() |
1463 | .filter_map(|pred| match &pred.value { | 1489 | .filter_map(|pred| match &pred.skip_binders().skip_binders() { |
1464 | hir_ty::WhereClause::Implemented(trait_ref) => { | 1490 | hir_ty::WhereClause::Implemented(trait_ref) => { |
1465 | Some(Trait::from(trait_ref.hir_trait_id())) | 1491 | Some(Trait::from(trait_ref.hir_trait_id())) |
1466 | } | 1492 | } |
@@ -1540,8 +1566,8 @@ impl Impl { | |||
1540 | inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect() | 1566 | inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect() |
1541 | } | 1567 | } |
1542 | 1568 | ||
1543 | pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty }: Type) -> Vec<Impl> { | 1569 | pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty, .. }: Type) -> Vec<Impl> { |
1544 | let def_crates = match ty.value.def_crates(db, krate) { | 1570 | let def_crates = match ty.def_crates(db, krate) { |
1545 | Some(def_crates) => def_crates, | 1571 | Some(def_crates) => def_crates, |
1546 | None => return Vec::new(), | 1572 | None => return Vec::new(), |
1547 | }; | 1573 | }; |
@@ -1549,14 +1575,14 @@ impl Impl { | |||
1549 | let filter = |impl_def: &Impl| { | 1575 | let filter = |impl_def: &Impl| { |
1550 | let target_ty = impl_def.target_ty(db); | 1576 | let target_ty = impl_def.target_ty(db); |
1551 | let rref = target_ty.remove_ref(); | 1577 | let rref = target_ty.remove_ref(); |
1552 | ty.value.equals_ctor(rref.as_ref().map_or(&target_ty.ty.value, |it| &it.ty.value)) | 1578 | ty.equals_ctor(rref.as_ref().map_or(&target_ty.ty, |it| &it.ty)) |
1553 | }; | 1579 | }; |
1554 | 1580 | ||
1555 | let mut all = Vec::new(); | 1581 | let mut all = Vec::new(); |
1556 | def_crates.iter().for_each(|&id| { | 1582 | def_crates.iter().for_each(|&id| { |
1557 | all.extend(db.inherent_impls_in_crate(id).all_impls().map(Self::from).filter(filter)) | 1583 | all.extend(db.inherent_impls_in_crate(id).all_impls().map(Self::from).filter(filter)) |
1558 | }); | 1584 | }); |
1559 | let fp = TyFingerprint::for_impl(&ty.value); | 1585 | let fp = TyFingerprint::for_impl(&ty); |
1560 | for id in def_crates | 1586 | for id in def_crates |
1561 | .iter() | 1587 | .iter() |
1562 | .flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db)) | 1588 | .flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db)) |
@@ -1578,8 +1604,7 @@ impl Impl { | |||
1578 | pub fn all_for_trait(db: &dyn HirDatabase, trait_: Trait) -> Vec<Impl> { | 1604 | pub fn all_for_trait(db: &dyn HirDatabase, trait_: Trait) -> Vec<Impl> { |
1579 | let krate = trait_.module(db).krate(); | 1605 | let krate = trait_.module(db).krate(); |
1580 | let mut all = Vec::new(); | 1606 | let mut all = Vec::new(); |
1581 | for Crate { id } in krate.transitive_reverse_dependencies(db).into_iter().chain(Some(krate)) | 1607 | for Crate { id } in krate.transitive_reverse_dependencies(db).into_iter() { |
1582 | { | ||
1583 | let impls = db.trait_impls_in_crate(id); | 1608 | let impls = db.trait_impls_in_crate(id); |
1584 | all.extend(impls.for_trait(trait_.id).map(Self::from)) | 1609 | all.extend(impls.for_trait(trait_.id).map(Self::from)) |
1585 | } | 1610 | } |
@@ -1643,7 +1668,8 @@ impl Impl { | |||
1643 | #[derive(Clone, PartialEq, Eq, Debug)] | 1668 | #[derive(Clone, PartialEq, Eq, Debug)] |
1644 | pub struct Type { | 1669 | pub struct Type { |
1645 | krate: CrateId, | 1670 | krate: CrateId, |
1646 | ty: InEnvironment<Ty>, | 1671 | env: Arc<TraitEnvironment>, |
1672 | ty: Ty, | ||
1647 | } | 1673 | } |
1648 | 1674 | ||
1649 | impl Type { | 1675 | impl Type { |
@@ -1663,14 +1689,14 @@ impl Type { | |||
1663 | ) -> Type { | 1689 | ) -> Type { |
1664 | let environment = | 1690 | let environment = |
1665 | resolver.generic_def().map_or_else(Default::default, |d| db.trait_environment(d)); | 1691 | resolver.generic_def().map_or_else(Default::default, |d| db.trait_environment(d)); |
1666 | Type { krate, ty: InEnvironment { value: ty, environment } } | 1692 | Type { krate, env: environment, ty } |
1667 | } | 1693 | } |
1668 | 1694 | ||
1669 | fn new(db: &dyn HirDatabase, krate: CrateId, lexical_env: impl HasResolver, ty: Ty) -> Type { | 1695 | fn new(db: &dyn HirDatabase, krate: CrateId, lexical_env: impl HasResolver, ty: Ty) -> Type { |
1670 | let resolver = lexical_env.resolver(db.upcast()); | 1696 | let resolver = lexical_env.resolver(db.upcast()); |
1671 | let environment = | 1697 | let environment = |
1672 | resolver.generic_def().map_or_else(Default::default, |d| db.trait_environment(d)); | 1698 | resolver.generic_def().map_or_else(Default::default, |d| db.trait_environment(d)); |
1673 | Type { krate, ty: InEnvironment { value: ty, environment } } | 1699 | Type { krate, env: environment, ty } |
1674 | } | 1700 | } |
1675 | 1701 | ||
1676 | fn from_def( | 1702 | fn from_def( |
@@ -1684,29 +1710,29 @@ impl Type { | |||
1684 | } | 1710 | } |
1685 | 1711 | ||
1686 | pub fn is_unit(&self) -> bool { | 1712 | pub fn is_unit(&self) -> bool { |
1687 | matches!(self.ty.value.interned(&Interner), TyKind::Tuple(0, ..)) | 1713 | matches!(self.ty.interned(&Interner), TyKind::Tuple(0, ..)) |
1688 | } | 1714 | } |
1689 | pub fn is_bool(&self) -> bool { | 1715 | pub fn is_bool(&self) -> bool { |
1690 | matches!(self.ty.value.interned(&Interner), TyKind::Scalar(Scalar::Bool)) | 1716 | matches!(self.ty.interned(&Interner), TyKind::Scalar(Scalar::Bool)) |
1691 | } | 1717 | } |
1692 | 1718 | ||
1693 | pub fn is_mutable_reference(&self) -> bool { | 1719 | pub fn is_mutable_reference(&self) -> bool { |
1694 | matches!(self.ty.value.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..)) | 1720 | matches!(self.ty.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..)) |
1695 | } | 1721 | } |
1696 | 1722 | ||
1697 | pub fn is_usize(&self) -> bool { | 1723 | pub fn is_usize(&self) -> bool { |
1698 | matches!(self.ty.value.interned(&Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize))) | 1724 | matches!(self.ty.interned(&Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize))) |
1699 | } | 1725 | } |
1700 | 1726 | ||
1701 | pub fn remove_ref(&self) -> Option<Type> { | 1727 | pub fn remove_ref(&self) -> Option<Type> { |
1702 | match &self.ty.value.interned(&Interner) { | 1728 | match &self.ty.interned(&Interner) { |
1703 | TyKind::Ref(.., ty) => Some(self.derived(ty.clone())), | 1729 | TyKind::Ref(.., ty) => Some(self.derived(ty.clone())), |
1704 | _ => None, | 1730 | _ => None, |
1705 | } | 1731 | } |
1706 | } | 1732 | } |
1707 | 1733 | ||
1708 | pub fn is_unknown(&self) -> bool { | 1734 | pub fn is_unknown(&self) -> bool { |
1709 | self.ty.value.is_unknown() | 1735 | self.ty.is_unknown() |
1710 | } | 1736 | } |
1711 | 1737 | ||
1712 | /// Checks that particular type `ty` implements `std::future::Future`. | 1738 | /// Checks that particular type `ty` implements `std::future::Future`. |
@@ -1723,11 +1749,12 @@ impl Type { | |||
1723 | None => return false, | 1749 | None => return false, |
1724 | }; | 1750 | }; |
1725 | 1751 | ||
1726 | let canonical_ty = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; | 1752 | let canonical_ty = |
1753 | Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(&Interner) }; | ||
1727 | method_resolution::implements_trait( | 1754 | method_resolution::implements_trait( |
1728 | &canonical_ty, | 1755 | &canonical_ty, |
1729 | db, | 1756 | db, |
1730 | self.ty.environment.clone(), | 1757 | self.env.clone(), |
1731 | krate, | 1758 | krate, |
1732 | std_future_trait, | 1759 | std_future_trait, |
1733 | ) | 1760 | ) |
@@ -1745,11 +1772,12 @@ impl Type { | |||
1745 | None => return false, | 1772 | None => return false, |
1746 | }; | 1773 | }; |
1747 | 1774 | ||
1748 | let canonical_ty = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; | 1775 | let canonical_ty = |
1776 | Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(&Interner) }; | ||
1749 | method_resolution::implements_trait_unique( | 1777 | method_resolution::implements_trait_unique( |
1750 | &canonical_ty, | 1778 | &canonical_ty, |
1751 | db, | 1779 | db, |
1752 | self.ty.environment.clone(), | 1780 | self.env.clone(), |
1753 | krate, | 1781 | krate, |
1754 | fnonce_trait, | 1782 | fnonce_trait, |
1755 | ) | 1783 | ) |
@@ -1759,17 +1787,14 @@ impl Type { | |||
1759 | let trait_ref = hir_ty::TraitRef { | 1787 | let trait_ref = hir_ty::TraitRef { |
1760 | trait_id: hir_ty::to_chalk_trait_id(trait_.id), | 1788 | trait_id: hir_ty::to_chalk_trait_id(trait_.id), |
1761 | substitution: Substitution::build_for_def(db, trait_.id) | 1789 | substitution: Substitution::build_for_def(db, trait_.id) |
1762 | .push(self.ty.value.clone()) | 1790 | .push(self.ty.clone()) |
1763 | .fill(args.iter().map(|t| t.ty.value.clone())) | 1791 | .fill(args.iter().map(|t| t.ty.clone())) |
1764 | .build(), | 1792 | .build(), |
1765 | }; | 1793 | }; |
1766 | 1794 | ||
1767 | let goal = Canonical { | 1795 | let goal = Canonical { |
1768 | value: hir_ty::InEnvironment::new( | 1796 | value: hir_ty::InEnvironment::new(self.env.env.clone(), trait_ref.cast(&Interner)), |
1769 | self.ty.environment.clone(), | 1797 | binders: CanonicalVarKinds::empty(&Interner), |
1770 | trait_ref.cast(&Interner), | ||
1771 | ), | ||
1772 | kinds: Arc::new([]), | ||
1773 | }; | 1798 | }; |
1774 | 1799 | ||
1775 | db.trait_solve(self.krate, goal).is_some() | 1800 | db.trait_solve(self.krate, goal).is_some() |
@@ -1783,12 +1808,12 @@ impl Type { | |||
1783 | alias: TypeAlias, | 1808 | alias: TypeAlias, |
1784 | ) -> Option<Type> { | 1809 | ) -> Option<Type> { |
1785 | let subst = Substitution::build_for_def(db, trait_.id) | 1810 | let subst = Substitution::build_for_def(db, trait_.id) |
1786 | .push(self.ty.value.clone()) | 1811 | .push(self.ty.clone()) |
1787 | .fill(args.iter().map(|t| t.ty.value.clone())) | 1812 | .fill(args.iter().map(|t| t.ty.clone())) |
1788 | .build(); | 1813 | .build(); |
1789 | let goal = Canonical { | 1814 | let goal = Canonical::new( |
1790 | value: InEnvironment::new( | 1815 | InEnvironment::new( |
1791 | self.ty.environment.clone(), | 1816 | self.env.env.clone(), |
1792 | AliasEq { | 1817 | AliasEq { |
1793 | alias: AliasTy::Projection(ProjectionTy { | 1818 | alias: AliasTy::Projection(ProjectionTy { |
1794 | associated_ty_id: to_assoc_type_id(alias.id), | 1819 | associated_ty_id: to_assoc_type_id(alias.id), |
@@ -1799,8 +1824,8 @@ impl Type { | |||
1799 | } | 1824 | } |
1800 | .cast(&Interner), | 1825 | .cast(&Interner), |
1801 | ), | 1826 | ), |
1802 | kinds: Arc::new([TyVariableKind::General]), | 1827 | [TyVariableKind::General].iter().copied(), |
1803 | }; | 1828 | ); |
1804 | 1829 | ||
1805 | match db.trait_solve(self.krate, goal)? { | 1830 | match db.trait_solve(self.krate, goal)? { |
1806 | Solution::Unique(SolutionVariables(subst)) => { | 1831 | Solution::Unique(SolutionVariables(subst)) => { |
@@ -1820,22 +1845,22 @@ impl Type { | |||
1820 | } | 1845 | } |
1821 | 1846 | ||
1822 | pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> { | 1847 | pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> { |
1823 | let def = self.ty.value.callable_def(db); | 1848 | let def = self.ty.callable_def(db); |
1824 | 1849 | ||
1825 | let sig = self.ty.value.callable_sig(db)?; | 1850 | let sig = self.ty.callable_sig(db)?; |
1826 | Some(Callable { ty: self.clone(), sig, def, is_bound_method: false }) | 1851 | Some(Callable { ty: self.clone(), sig, def, is_bound_method: false }) |
1827 | } | 1852 | } |
1828 | 1853 | ||
1829 | pub fn is_closure(&self) -> bool { | 1854 | pub fn is_closure(&self) -> bool { |
1830 | matches!(&self.ty.value.interned(&Interner), TyKind::Closure { .. }) | 1855 | matches!(&self.ty.interned(&Interner), TyKind::Closure { .. }) |
1831 | } | 1856 | } |
1832 | 1857 | ||
1833 | pub fn is_fn(&self) -> bool { | 1858 | pub fn is_fn(&self) -> bool { |
1834 | matches!(&self.ty.value.interned(&Interner), TyKind::FnDef(..) | TyKind::Function { .. }) | 1859 | matches!(&self.ty.interned(&Interner), TyKind::FnDef(..) | TyKind::Function { .. }) |
1835 | } | 1860 | } |
1836 | 1861 | ||
1837 | pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { | 1862 | pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { |
1838 | let adt_id = match self.ty.value.interned(&Interner) { | 1863 | let adt_id = match self.ty.interned(&Interner) { |
1839 | &TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id, | 1864 | &TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id, |
1840 | _ => return false, | 1865 | _ => return false, |
1841 | }; | 1866 | }; |
@@ -1848,11 +1873,11 @@ impl Type { | |||
1848 | } | 1873 | } |
1849 | 1874 | ||
1850 | pub fn is_raw_ptr(&self) -> bool { | 1875 | pub fn is_raw_ptr(&self) -> bool { |
1851 | matches!(&self.ty.value.interned(&Interner), TyKind::Raw(..)) | 1876 | matches!(&self.ty.interned(&Interner), TyKind::Raw(..)) |
1852 | } | 1877 | } |
1853 | 1878 | ||
1854 | pub fn contains_unknown(&self) -> bool { | 1879 | pub fn contains_unknown(&self) -> bool { |
1855 | return go(&self.ty.value); | 1880 | return go(&self.ty); |
1856 | 1881 | ||
1857 | fn go(ty: &Ty) -> bool { | 1882 | fn go(ty: &Ty) -> bool { |
1858 | match ty.interned(&Interner) { | 1883 | match ty.interned(&Interner) { |
@@ -1884,7 +1909,7 @@ impl Type { | |||
1884 | } | 1909 | } |
1885 | 1910 | ||
1886 | pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { | 1911 | pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { |
1887 | let (variant_id, substs) = match self.ty.value.interned(&Interner) { | 1912 | let (variant_id, substs) = match self.ty.interned(&Interner) { |
1888 | &TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs), | 1913 | &TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs), |
1889 | &TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs), | 1914 | &TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs), |
1890 | _ => return Vec::new(), | 1915 | _ => return Vec::new(), |
@@ -1901,7 +1926,7 @@ impl Type { | |||
1901 | } | 1926 | } |
1902 | 1927 | ||
1903 | pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> { | 1928 | pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> { |
1904 | if let TyKind::Tuple(_, substs) = &self.ty.value.interned(&Interner) { | 1929 | if let TyKind::Tuple(_, substs) = &self.ty.interned(&Interner) { |
1905 | substs.iter().map(|ty| self.derived(ty.clone())).collect() | 1930 | substs.iter().map(|ty| self.derived(ty.clone())).collect() |
1906 | } else { | 1931 | } else { |
1907 | Vec::new() | 1932 | Vec::new() |
@@ -1911,9 +1936,10 @@ impl Type { | |||
1911 | pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a { | 1936 | pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a { |
1912 | // There should be no inference vars in types passed here | 1937 | // There should be no inference vars in types passed here |
1913 | // FIXME check that? | 1938 | // FIXME check that? |
1914 | let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; | 1939 | let canonical = |
1915 | let environment = self.ty.environment.clone(); | 1940 | Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(&Interner) }; |
1916 | let ty = InEnvironment { value: canonical, environment }; | 1941 | let environment = self.env.env.clone(); |
1942 | let ty = InEnvironment { goal: canonical, environment }; | ||
1917 | autoderef(db, Some(self.krate), ty) | 1943 | autoderef(db, Some(self.krate), ty) |
1918 | .map(|canonical| canonical.value) | 1944 | .map(|canonical| canonical.value) |
1919 | .map(move |ty| self.derived(ty)) | 1945 | .map(move |ty| self.derived(ty)) |
@@ -1927,10 +1953,10 @@ impl Type { | |||
1927 | krate: Crate, | 1953 | krate: Crate, |
1928 | mut callback: impl FnMut(AssocItem) -> Option<T>, | 1954 | mut callback: impl FnMut(AssocItem) -> Option<T>, |
1929 | ) -> Option<T> { | 1955 | ) -> Option<T> { |
1930 | for krate in self.ty.value.def_crates(db, krate.id)? { | 1956 | for krate in self.ty.def_crates(db, krate.id)? { |
1931 | let impls = db.inherent_impls_in_crate(krate); | 1957 | let impls = db.inherent_impls_in_crate(krate); |
1932 | 1958 | ||
1933 | for impl_def in impls.for_self_ty(&self.ty.value) { | 1959 | for impl_def in impls.for_self_ty(&self.ty) { |
1934 | for &item in db.impl_data(*impl_def).items.iter() { | 1960 | for &item in db.impl_data(*impl_def).items.iter() { |
1935 | if let Some(result) = callback(item.into()) { | 1961 | if let Some(result) = callback(item.into()) { |
1936 | return Some(result); | 1962 | return Some(result); |
@@ -1943,7 +1969,6 @@ impl Type { | |||
1943 | 1969 | ||
1944 | pub fn type_parameters(&self) -> impl Iterator<Item = Type> + '_ { | 1970 | pub fn type_parameters(&self) -> impl Iterator<Item = Type> + '_ { |
1945 | self.ty | 1971 | self.ty |
1946 | .value | ||
1947 | .strip_references() | 1972 | .strip_references() |
1948 | .substs() | 1973 | .substs() |
1949 | .into_iter() | 1974 | .into_iter() |
@@ -1962,9 +1987,10 @@ impl Type { | |||
1962 | // There should be no inference vars in types passed here | 1987 | // There should be no inference vars in types passed here |
1963 | // FIXME check that? | 1988 | // FIXME check that? |
1964 | // FIXME replace Unknown by bound vars here | 1989 | // FIXME replace Unknown by bound vars here |
1965 | let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; | 1990 | let canonical = |
1991 | Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(&Interner) }; | ||
1966 | 1992 | ||
1967 | let env = self.ty.environment.clone(); | 1993 | let env = self.env.clone(); |
1968 | let krate = krate.id; | 1994 | let krate = krate.id; |
1969 | 1995 | ||
1970 | method_resolution::iterate_method_candidates( | 1996 | method_resolution::iterate_method_candidates( |
@@ -1994,9 +2020,10 @@ impl Type { | |||
1994 | // There should be no inference vars in types passed here | 2020 | // There should be no inference vars in types passed here |
1995 | // FIXME check that? | 2021 | // FIXME check that? |
1996 | // FIXME replace Unknown by bound vars here | 2022 | // FIXME replace Unknown by bound vars here |
1997 | let canonical = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; | 2023 | let canonical = |
2024 | Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(&Interner) }; | ||
1998 | 2025 | ||
1999 | let env = self.ty.environment.clone(); | 2026 | let env = self.env.clone(); |
2000 | let krate = krate.id; | 2027 | let krate = krate.id; |
2001 | 2028 | ||
2002 | method_resolution::iterate_method_candidates( | 2029 | method_resolution::iterate_method_candidates( |
@@ -2013,18 +2040,18 @@ impl Type { | |||
2013 | } | 2040 | } |
2014 | 2041 | ||
2015 | pub fn as_adt(&self) -> Option<Adt> { | 2042 | pub fn as_adt(&self) -> Option<Adt> { |
2016 | let (adt, _subst) = self.ty.value.as_adt()?; | 2043 | let (adt, _subst) = self.ty.as_adt()?; |
2017 | Some(adt.into()) | 2044 | Some(adt.into()) |
2018 | } | 2045 | } |
2019 | 2046 | ||
2020 | pub fn as_dyn_trait(&self) -> Option<Trait> { | 2047 | pub fn as_dyn_trait(&self) -> Option<Trait> { |
2021 | self.ty.value.dyn_trait().map(Into::into) | 2048 | self.ty.dyn_trait().map(Into::into) |
2022 | } | 2049 | } |
2023 | 2050 | ||
2024 | pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> { | 2051 | pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> { |
2025 | self.ty.value.impl_trait_bounds(db).map(|it| { | 2052 | self.ty.impl_trait_bounds(db).map(|it| { |
2026 | it.into_iter() | 2053 | it.into_iter() |
2027 | .filter_map(|pred| match pred { | 2054 | .filter_map(|pred| match pred.skip_binders() { |
2028 | hir_ty::WhereClause::Implemented(trait_ref) => { | 2055 | hir_ty::WhereClause::Implemented(trait_ref) => { |
2029 | Some(Trait::from(trait_ref.hir_trait_id())) | 2056 | Some(Trait::from(trait_ref.hir_trait_id())) |
2030 | } | 2057 | } |
@@ -2035,14 +2062,11 @@ impl Type { | |||
2035 | } | 2062 | } |
2036 | 2063 | ||
2037 | pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> { | 2064 | pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> { |
2038 | self.ty.value.associated_type_parent_trait(db).map(Into::into) | 2065 | self.ty.associated_type_parent_trait(db).map(Into::into) |
2039 | } | 2066 | } |
2040 | 2067 | ||
2041 | fn derived(&self, ty: Ty) -> Type { | 2068 | fn derived(&self, ty: Ty) -> Type { |
2042 | Type { | 2069 | Type { krate: self.krate, env: self.env.clone(), ty } |
2043 | krate: self.krate, | ||
2044 | ty: InEnvironment { value: ty, environment: self.ty.environment.clone() }, | ||
2045 | } | ||
2046 | } | 2070 | } |
2047 | 2071 | ||
2048 | pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) { | 2072 | pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) { |
@@ -2063,14 +2087,17 @@ impl Type { | |||
2063 | fn walk_bounds( | 2087 | fn walk_bounds( |
2064 | db: &dyn HirDatabase, | 2088 | db: &dyn HirDatabase, |
2065 | type_: &Type, | 2089 | type_: &Type, |
2066 | bounds: &[WhereClause], | 2090 | bounds: &[QuantifiedWhereClause], |
2067 | cb: &mut impl FnMut(Type), | 2091 | cb: &mut impl FnMut(Type), |
2068 | ) { | 2092 | ) { |
2069 | for pred in bounds { | 2093 | for pred in bounds { |
2070 | match pred { | 2094 | match pred.skip_binders() { |
2071 | WhereClause::Implemented(trait_ref) => { | 2095 | WhereClause::Implemented(trait_ref) => { |
2072 | cb(type_.clone()); | 2096 | cb(type_.clone()); |
2073 | walk_substs(db, type_, &trait_ref.substitution, cb); | 2097 | // skip the self type. it's likely the type we just got the bounds from |
2098 | for ty in trait_ref.substitution.iter().skip(1) { | ||
2099 | walk_type(db, &type_.derived(ty.clone()), cb); | ||
2100 | } | ||
2074 | } | 2101 | } |
2075 | _ => (), | 2102 | _ => (), |
2076 | } | 2103 | } |
@@ -2078,7 +2105,7 @@ impl Type { | |||
2078 | } | 2105 | } |
2079 | 2106 | ||
2080 | fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { | 2107 | fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { |
2081 | let ty = type_.ty.value.strip_references(); | 2108 | let ty = type_.ty.strip_references(); |
2082 | match ty.interned(&Interner) { | 2109 | match ty.interned(&Interner) { |
2083 | TyKind::Adt(..) => { | 2110 | TyKind::Adt(..) => { |
2084 | cb(type_.derived(ty.clone())); | 2111 | cb(type_.derived(ty.clone())); |
@@ -2106,7 +2133,12 @@ impl Type { | |||
2106 | } | 2133 | } |
2107 | } | 2134 | } |
2108 | TyKind::Dyn(bounds) => { | 2135 | TyKind::Dyn(bounds) => { |
2109 | walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb); | 2136 | walk_bounds( |
2137 | db, | ||
2138 | &type_.derived(ty.clone()), | ||
2139 | bounds.bounds.skip_binders().interned(), | ||
2140 | cb, | ||
2141 | ); | ||
2110 | } | 2142 | } |
2111 | 2143 | ||
2112 | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) | TyKind::Array(ty) | TyKind::Slice(ty) => { | 2144 | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) | TyKind::Array(ty) | TyKind::Slice(ty) => { |
@@ -2201,6 +2233,7 @@ pub enum ScopeDef { | |||
2201 | ImplSelfType(Impl), | 2233 | ImplSelfType(Impl), |
2202 | AdtSelfType(Adt), | 2234 | AdtSelfType(Adt), |
2203 | Local(Local), | 2235 | Local(Local), |
2236 | Label(Label), | ||
2204 | Unknown, | 2237 | Unknown, |
2205 | } | 2238 | } |
2206 | 2239 | ||
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 15651bb22..1198e3f0b 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs | |||
@@ -839,6 +839,10 @@ impl<'a> SemanticsScope<'a> { | |||
839 | let parent = resolver.body_owner().unwrap(); | 839 | let parent = resolver.body_owner().unwrap(); |
840 | ScopeDef::Local(Local { parent, pat_id }) | 840 | ScopeDef::Local(Local { parent, pat_id }) |
841 | } | 841 | } |
842 | resolver::ScopeDef::Label(label_id) => { | ||
843 | let parent = resolver.body_owner().unwrap(); | ||
844 | ScopeDef::Label(Label { parent, label_id }) | ||
845 | } | ||
842 | }; | 846 | }; |
843 | f(name, def) | 847 | f(name, def) |
844 | }) | 848 | }) |
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index 2c10f46d8..52a2bce9b 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -638,7 +638,7 @@ fn collect_attrs( | |||
638 | owner: &dyn ast::AttrsOwner, | 638 | owner: &dyn ast::AttrsOwner, |
639 | ) -> impl Iterator<Item = Either<ast::Attr, ast::Comment>> { | 639 | ) -> impl Iterator<Item = Either<ast::Attr, ast::Comment>> { |
640 | let (inner_attrs, inner_docs) = inner_attributes(owner.syntax()) | 640 | let (inner_attrs, inner_docs) = inner_attributes(owner.syntax()) |
641 | .map_or((None, None), |(attrs, docs)| ((Some(attrs), Some(docs)))); | 641 | .map_or((None, None), |(attrs, docs)| (Some(attrs), Some(docs))); |
642 | 642 | ||
643 | let outer_attrs = owner.attrs().filter(|attr| attr.excl_token().is_none()); | 643 | let outer_attrs = owner.attrs().filter(|attr| attr.excl_token().is_none()); |
644 | let attrs = outer_attrs | 644 | let attrs = outer_attrs |
diff --git a/crates/hir_def/src/body/scope.rs b/crates/hir_def/src/body/scope.rs index 1bbb54fc6..bd7005ca6 100644 --- a/crates/hir_def/src/body/scope.rs +++ b/crates/hir_def/src/body/scope.rs | |||
@@ -8,7 +8,7 @@ use rustc_hash::FxHashMap; | |||
8 | use crate::{ | 8 | use crate::{ |
9 | body::Body, | 9 | body::Body, |
10 | db::DefDatabase, | 10 | db::DefDatabase, |
11 | expr::{Expr, ExprId, Pat, PatId, Statement}, | 11 | expr::{Expr, ExprId, LabelId, Pat, PatId, Statement}, |
12 | BlockId, DefWithBodyId, | 12 | BlockId, DefWithBodyId, |
13 | }; | 13 | }; |
14 | 14 | ||
@@ -40,6 +40,7 @@ impl ScopeEntry { | |||
40 | pub struct ScopeData { | 40 | pub struct ScopeData { |
41 | parent: Option<ScopeId>, | 41 | parent: Option<ScopeId>, |
42 | block: Option<BlockId>, | 42 | block: Option<BlockId>, |
43 | label: Option<(LabelId, Name)>, | ||
43 | entries: Vec<ScopeEntry>, | 44 | entries: Vec<ScopeEntry>, |
44 | } | 45 | } |
45 | 46 | ||
@@ -67,6 +68,11 @@ impl ExprScopes { | |||
67 | self.scopes[scope].block | 68 | self.scopes[scope].block |
68 | } | 69 | } |
69 | 70 | ||
71 | /// If `scope` refers to a labeled expression scope, returns the corresponding `Label`. | ||
72 | pub fn label(&self, scope: ScopeId) -> Option<(LabelId, Name)> { | ||
73 | self.scopes[scope].label.clone() | ||
74 | } | ||
75 | |||
70 | pub fn scope_chain(&self, scope: Option<ScopeId>) -> impl Iterator<Item = ScopeId> + '_ { | 76 | pub fn scope_chain(&self, scope: Option<ScopeId>) -> impl Iterator<Item = ScopeId> + '_ { |
71 | std::iter::successors(scope, move |&scope| self.scopes[scope].parent) | 77 | std::iter::successors(scope, move |&scope| self.scopes[scope].parent) |
72 | } | 78 | } |
@@ -85,15 +91,34 @@ impl ExprScopes { | |||
85 | } | 91 | } |
86 | 92 | ||
87 | fn root_scope(&mut self) -> ScopeId { | 93 | fn root_scope(&mut self) -> ScopeId { |
88 | self.scopes.alloc(ScopeData { parent: None, block: None, entries: vec![] }) | 94 | self.scopes.alloc(ScopeData { parent: None, block: None, label: None, entries: vec![] }) |
89 | } | 95 | } |
90 | 96 | ||
91 | fn new_scope(&mut self, parent: ScopeId) -> ScopeId { | 97 | fn new_scope(&mut self, parent: ScopeId) -> ScopeId { |
92 | self.scopes.alloc(ScopeData { parent: Some(parent), block: None, entries: vec![] }) | 98 | self.scopes.alloc(ScopeData { |
99 | parent: Some(parent), | ||
100 | block: None, | ||
101 | label: None, | ||
102 | entries: vec![], | ||
103 | }) | ||
93 | } | 104 | } |
94 | 105 | ||
95 | fn new_block_scope(&mut self, parent: ScopeId, block: BlockId) -> ScopeId { | 106 | fn new_labeled_scope(&mut self, parent: ScopeId, label: Option<(LabelId, Name)>) -> ScopeId { |
96 | self.scopes.alloc(ScopeData { parent: Some(parent), block: Some(block), entries: vec![] }) | 107 | self.scopes.alloc(ScopeData { parent: Some(parent), block: None, label, entries: vec![] }) |
108 | } | ||
109 | |||
110 | fn new_block_scope( | ||
111 | &mut self, | ||
112 | parent: ScopeId, | ||
113 | block: BlockId, | ||
114 | label: Option<(LabelId, Name)>, | ||
115 | ) -> ScopeId { | ||
116 | self.scopes.alloc(ScopeData { | ||
117 | parent: Some(parent), | ||
118 | block: Some(block), | ||
119 | label, | ||
120 | entries: vec![], | ||
121 | }) | ||
97 | } | 122 | } |
98 | 123 | ||
99 | fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) { | 124 | fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) { |
@@ -144,21 +169,33 @@ fn compute_block_scopes( | |||
144 | } | 169 | } |
145 | 170 | ||
146 | fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) { | 171 | fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) { |
172 | let make_label = | ||
173 | |label: &Option<_>| label.map(|label| (label, body.labels[label].name.clone())); | ||
174 | |||
147 | scopes.set_scope(expr, scope); | 175 | scopes.set_scope(expr, scope); |
148 | match &body[expr] { | 176 | match &body[expr] { |
149 | Expr::Block { statements, tail, id, .. } => { | 177 | Expr::Block { statements, tail, id, label } => { |
150 | let scope = scopes.new_block_scope(scope, *id); | 178 | let scope = scopes.new_block_scope(scope, *id, make_label(label)); |
151 | // Overwrite the old scope for the block expr, so that every block scope can be found | 179 | // Overwrite the old scope for the block expr, so that every block scope can be found |
152 | // via the block itself (important for blocks that only contain items, no expressions). | 180 | // via the block itself (important for blocks that only contain items, no expressions). |
153 | scopes.set_scope(expr, scope); | 181 | scopes.set_scope(expr, scope); |
154 | compute_block_scopes(&statements, *tail, body, scopes, scope); | 182 | compute_block_scopes(statements, *tail, body, scopes, scope); |
155 | } | 183 | } |
156 | Expr::For { iterable, pat, body: body_expr, .. } => { | 184 | Expr::For { iterable, pat, body: body_expr, label } => { |
157 | compute_expr_scopes(*iterable, body, scopes, scope); | 185 | compute_expr_scopes(*iterable, body, scopes, scope); |
158 | let scope = scopes.new_scope(scope); | 186 | let scope = scopes.new_labeled_scope(scope, make_label(label)); |
159 | scopes.add_bindings(body, scope, *pat); | 187 | scopes.add_bindings(body, scope, *pat); |
160 | compute_expr_scopes(*body_expr, body, scopes, scope); | 188 | compute_expr_scopes(*body_expr, body, scopes, scope); |
161 | } | 189 | } |
190 | Expr::While { condition, body: body_expr, label } => { | ||
191 | let scope = scopes.new_labeled_scope(scope, make_label(label)); | ||
192 | compute_expr_scopes(*condition, body, scopes, scope); | ||
193 | compute_expr_scopes(*body_expr, body, scopes, scope); | ||
194 | } | ||
195 | Expr::Loop { body: body_expr, label } => { | ||
196 | let scope = scopes.new_labeled_scope(scope, make_label(label)); | ||
197 | compute_expr_scopes(*body_expr, body, scopes, scope); | ||
198 | } | ||
162 | Expr::Lambda { args, body: body_expr, .. } => { | 199 | Expr::Lambda { args, body: body_expr, .. } => { |
163 | let scope = scopes.new_scope(scope); | 200 | let scope = scopes.new_scope(scope); |
164 | scopes.add_params_bindings(body, scope, &args); | 201 | scopes.add_params_bindings(body, scope, &args); |
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs index de08e2737..109d3552f 100644 --- a/crates/hir_def/src/find_path.rs +++ b/crates/hir_def/src/find_path.rs | |||
@@ -18,7 +18,8 @@ use crate::{ | |||
18 | /// *from where* you're referring to the item, hence the `from` parameter. | 18 | /// *from where* you're referring to the item, hence the `from` parameter. |
19 | pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> { | 19 | pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> { |
20 | let _p = profile::span("find_path"); | 20 | let _p = profile::span("find_path"); |
21 | find_path_inner(db, item, from, MAX_PATH_LEN, None) | 21 | let mut visited_modules = FxHashSet::default(); |
22 | find_path_inner(db, item, from, MAX_PATH_LEN, None, &mut visited_modules) | ||
22 | } | 23 | } |
23 | 24 | ||
24 | pub fn find_path_prefixed( | 25 | pub fn find_path_prefixed( |
@@ -28,7 +29,8 @@ pub fn find_path_prefixed( | |||
28 | prefix_kind: PrefixKind, | 29 | prefix_kind: PrefixKind, |
29 | ) -> Option<ModPath> { | 30 | ) -> Option<ModPath> { |
30 | let _p = profile::span("find_path_prefixed"); | 31 | let _p = profile::span("find_path_prefixed"); |
31 | find_path_inner(db, item, from, MAX_PATH_LEN, Some(prefix_kind)) | 32 | let mut visited_modules = FxHashSet::default(); |
33 | find_path_inner(db, item, from, MAX_PATH_LEN, Some(prefix_kind), &mut visited_modules) | ||
32 | } | 34 | } |
33 | 35 | ||
34 | const MAX_PATH_LEN: usize = 15; | 36 | const MAX_PATH_LEN: usize = 15; |
@@ -97,6 +99,7 @@ fn find_path_inner( | |||
97 | from: ModuleId, | 99 | from: ModuleId, |
98 | max_len: usize, | 100 | max_len: usize, |
99 | mut prefixed: Option<PrefixKind>, | 101 | mut prefixed: Option<PrefixKind>, |
102 | visited_modules: &mut FxHashSet<ModuleId>, | ||
100 | ) -> Option<ModPath> { | 103 | ) -> Option<ModPath> { |
101 | if max_len == 0 { | 104 | if max_len == 0 { |
102 | return None; | 105 | return None; |
@@ -176,15 +179,18 @@ fn find_path_inner( | |||
176 | if item.krate(db) == Some(from.krate) { | 179 | if item.krate(db) == Some(from.krate) { |
177 | // Item was defined in the same crate that wants to import it. It cannot be found in any | 180 | // Item was defined in the same crate that wants to import it. It cannot be found in any |
178 | // dependency in this case. | 181 | // dependency in this case. |
179 | 182 | for (module_id, name) in find_local_import_locations(db, item, from) { | |
180 | let local_imports = find_local_import_locations(db, item, from); | 183 | if !visited_modules.insert(module_id) { |
181 | for (module_id, name) in local_imports { | 184 | cov_mark::hit!(recursive_imports); |
185 | continue; | ||
186 | } | ||
182 | if let Some(mut path) = find_path_inner( | 187 | if let Some(mut path) = find_path_inner( |
183 | db, | 188 | db, |
184 | ItemInNs::Types(ModuleDefId::ModuleId(module_id)), | 189 | ItemInNs::Types(ModuleDefId::ModuleId(module_id)), |
185 | from, | 190 | from, |
186 | best_path_len - 1, | 191 | best_path_len - 1, |
187 | prefixed, | 192 | prefixed, |
193 | visited_modules, | ||
188 | ) { | 194 | ) { |
189 | path.push_segment(name); | 195 | path.push_segment(name); |
190 | 196 | ||
@@ -213,6 +219,7 @@ fn find_path_inner( | |||
213 | from, | 219 | from, |
214 | best_path_len - 1, | 220 | best_path_len - 1, |
215 | prefixed, | 221 | prefixed, |
222 | visited_modules, | ||
216 | )?; | 223 | )?; |
217 | cov_mark::hit!(partially_imported); | 224 | cov_mark::hit!(partially_imported); |
218 | path.push_segment(info.path.segments.last().unwrap().clone()); | 225 | path.push_segment(info.path.segments.last().unwrap().clone()); |
@@ -391,8 +398,15 @@ mod tests { | |||
391 | .take_types() | 398 | .take_types() |
392 | .unwrap(); | 399 | .unwrap(); |
393 | 400 | ||
394 | let found_path = | 401 | let mut visited_modules = FxHashSet::default(); |
395 | find_path_inner(&db, ItemInNs::Types(resolved), module, MAX_PATH_LEN, prefix_kind); | 402 | let found_path = find_path_inner( |
403 | &db, | ||
404 | ItemInNs::Types(resolved), | ||
405 | module, | ||
406 | MAX_PATH_LEN, | ||
407 | prefix_kind, | ||
408 | &mut visited_modules, | ||
409 | ); | ||
396 | assert_eq!(found_path, Some(mod_path), "{:?}", prefix_kind); | 410 | assert_eq!(found_path, Some(mod_path), "{:?}", prefix_kind); |
397 | } | 411 | } |
398 | 412 | ||
@@ -878,4 +892,32 @@ mod tests { | |||
878 | "self::module::CompleteMe", | 892 | "self::module::CompleteMe", |
879 | ) | 893 | ) |
880 | } | 894 | } |
895 | |||
896 | #[test] | ||
897 | fn recursive_pub_mod_reexport() { | ||
898 | cov_mark::check!(recursive_imports); | ||
899 | check_found_path( | ||
900 | r#" | ||
901 | fn main() { | ||
902 | let _ = 22_i32.as_name$0(); | ||
903 | } | ||
904 | |||
905 | pub mod name { | ||
906 | pub trait AsName { | ||
907 | fn as_name(&self) -> String; | ||
908 | } | ||
909 | impl AsName for i32 { | ||
910 | fn as_name(&self) -> String { | ||
911 | format!("Name: {}", self) | ||
912 | } | ||
913 | } | ||
914 | pub use crate::name; | ||
915 | } | ||
916 | "#, | ||
917 | "name::AsName", | ||
918 | "name::AsName", | ||
919 | "crate::name::AsName", | ||
920 | "self::name::AsName", | ||
921 | ); | ||
922 | } | ||
881 | } | 923 | } |
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index 0d3a0b54f..9e8e4e9ec 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs | |||
@@ -322,6 +322,23 @@ impl DefMap { | |||
322 | (res.resolved_def, res.segment_index) | 322 | (res.resolved_def, res.segment_index) |
323 | } | 323 | } |
324 | 324 | ||
325 | pub(crate) fn resolve_path_locally( | ||
326 | &self, | ||
327 | db: &dyn DefDatabase, | ||
328 | original_module: LocalModuleId, | ||
329 | path: &ModPath, | ||
330 | shadow: BuiltinShadowMode, | ||
331 | ) -> (PerNs, Option<usize>) { | ||
332 | let res = self.resolve_path_fp_with_macro_single( | ||
333 | db, | ||
334 | ResolveMode::Other, | ||
335 | original_module, | ||
336 | path, | ||
337 | shadow, | ||
338 | ); | ||
339 | (res.resolved_def, res.segment_index) | ||
340 | } | ||
341 | |||
325 | /// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module. | 342 | /// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module. |
326 | /// | 343 | /// |
327 | /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns | 344 | /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 46a3c60cd..d8fabe49b 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -91,7 +91,6 @@ pub(super) fn collect_defs( | |||
91 | resolved_imports: Vec::new(), | 91 | resolved_imports: Vec::new(), |
92 | 92 | ||
93 | unexpanded_macros: Vec::new(), | 93 | unexpanded_macros: Vec::new(), |
94 | unexpanded_attribute_macros: Vec::new(), | ||
95 | mod_dirs: FxHashMap::default(), | 94 | mod_dirs: FxHashMap::default(), |
96 | cfg_options, | 95 | cfg_options, |
97 | proc_macros, | 96 | proc_macros, |
@@ -202,15 +201,14 @@ struct ImportDirective { | |||
202 | #[derive(Clone, Debug, Eq, PartialEq)] | 201 | #[derive(Clone, Debug, Eq, PartialEq)] |
203 | struct MacroDirective { | 202 | struct MacroDirective { |
204 | module_id: LocalModuleId, | 203 | module_id: LocalModuleId, |
205 | ast_id: AstIdWithPath<ast::MacroCall>, | ||
206 | legacy: Option<MacroCallId>, | ||
207 | depth: usize, | 204 | depth: usize, |
205 | kind: MacroDirectiveKind, | ||
208 | } | 206 | } |
209 | 207 | ||
210 | #[derive(Clone, Debug, Eq, PartialEq)] | 208 | #[derive(Clone, Debug, Eq, PartialEq)] |
211 | struct DeriveDirective { | 209 | enum MacroDirectiveKind { |
212 | module_id: LocalModuleId, | 210 | FnLike { ast_id: AstIdWithPath<ast::MacroCall>, legacy: Option<MacroCallId> }, |
213 | ast_id: AstIdWithPath<ast::Item>, | 211 | Derive { ast_id: AstIdWithPath<ast::Item> }, |
214 | } | 212 | } |
215 | 213 | ||
216 | struct DefData<'a> { | 214 | struct DefData<'a> { |
@@ -228,7 +226,6 @@ struct DefCollector<'a> { | |||
228 | unresolved_imports: Vec<ImportDirective>, | 226 | unresolved_imports: Vec<ImportDirective>, |
229 | resolved_imports: Vec<ImportDirective>, | 227 | resolved_imports: Vec<ImportDirective>, |
230 | unexpanded_macros: Vec<MacroDirective>, | 228 | unexpanded_macros: Vec<MacroDirective>, |
231 | unexpanded_attribute_macros: Vec<DeriveDirective>, | ||
232 | mod_dirs: FxHashMap<LocalModuleId, ModDir>, | 229 | mod_dirs: FxHashMap<LocalModuleId, ModDir>, |
233 | cfg_options: &'a CfgOptions, | 230 | cfg_options: &'a CfgOptions, |
234 | /// List of procedural macros defined by this crate. This is read from the dynamic library | 231 | /// List of procedural macros defined by this crate. This is read from the dynamic library |
@@ -782,60 +779,58 @@ impl DefCollector<'_> { | |||
782 | 779 | ||
783 | fn resolve_macros(&mut self) -> ReachedFixedPoint { | 780 | fn resolve_macros(&mut self) -> ReachedFixedPoint { |
784 | let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new()); | 781 | let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new()); |
785 | let mut attribute_macros = | ||
786 | std::mem::replace(&mut self.unexpanded_attribute_macros, Vec::new()); | ||
787 | let mut resolved = Vec::new(); | 782 | let mut resolved = Vec::new(); |
788 | let mut res = ReachedFixedPoint::Yes; | 783 | let mut res = ReachedFixedPoint::Yes; |
789 | macros.retain(|directive| { | 784 | macros.retain(|directive| { |
790 | if let Some(call_id) = directive.legacy { | 785 | match &directive.kind { |
791 | res = ReachedFixedPoint::No; | 786 | MacroDirectiveKind::FnLike { ast_id, legacy } => { |
792 | resolved.push((directive.module_id, call_id, directive.depth)); | 787 | if let Some(call_id) = legacy { |
793 | return false; | 788 | res = ReachedFixedPoint::No; |
794 | } | 789 | resolved.push((directive.module_id, *call_id, directive.depth)); |
790 | return false; | ||
791 | } | ||
795 | 792 | ||
796 | match macro_call_as_call_id( | 793 | match macro_call_as_call_id( |
797 | &directive.ast_id, | 794 | ast_id, |
798 | self.db, | ||
799 | self.def_map.krate, | ||
800 | |path| { | ||
801 | let resolved_res = self.def_map.resolve_path_fp_with_macro( | ||
802 | self.db, | 795 | self.db, |
803 | ResolveMode::Other, | 796 | self.def_map.krate, |
804 | directive.module_id, | 797 | |path| { |
805 | &path, | 798 | let resolved_res = self.def_map.resolve_path_fp_with_macro( |
806 | BuiltinShadowMode::Module, | 799 | self.db, |
807 | ); | 800 | ResolveMode::Other, |
808 | resolved_res.resolved_def.take_macros() | 801 | directive.module_id, |
809 | }, | 802 | &path, |
810 | &mut |_err| (), | 803 | BuiltinShadowMode::Module, |
811 | ) { | 804 | ); |
812 | Ok(Ok(call_id)) => { | 805 | resolved_res.resolved_def.take_macros() |
813 | resolved.push((directive.module_id, call_id, directive.depth)); | 806 | }, |
814 | res = ReachedFixedPoint::No; | 807 | &mut |_err| (), |
815 | return false; | 808 | ) { |
809 | Ok(Ok(call_id)) => { | ||
810 | resolved.push((directive.module_id, call_id, directive.depth)); | ||
811 | res = ReachedFixedPoint::No; | ||
812 | return false; | ||
813 | } | ||
814 | Err(UnresolvedMacro) | Ok(Err(_)) => {} | ||
815 | } | ||
816 | } | 816 | } |
817 | Err(UnresolvedMacro) | Ok(Err(_)) => {} | 817 | MacroDirectiveKind::Derive { ast_id } => { |
818 | } | 818 | match derive_macro_as_call_id(ast_id, self.db, self.def_map.krate, |path| { |
819 | 819 | self.resolve_derive_macro(directive.module_id, &path) | |
820 | true | 820 | }) { |
821 | }); | 821 | Ok(call_id) => { |
822 | attribute_macros.retain(|directive| { | 822 | resolved.push((directive.module_id, call_id, 0)); |
823 | match derive_macro_as_call_id(&directive.ast_id, self.db, self.def_map.krate, |path| { | 823 | res = ReachedFixedPoint::No; |
824 | self.resolve_derive_macro(&directive, &path) | 824 | return false; |
825 | }) { | 825 | } |
826 | Ok(call_id) => { | 826 | Err(UnresolvedMacro) => (), |
827 | resolved.push((directive.module_id, call_id, 0)); | 827 | } |
828 | res = ReachedFixedPoint::No; | ||
829 | return false; | ||
830 | } | 828 | } |
831 | Err(UnresolvedMacro) => (), | ||
832 | } | 829 | } |
833 | 830 | ||
834 | true | 831 | true |
835 | }); | 832 | }); |
836 | |||
837 | self.unexpanded_macros = macros; | 833 | self.unexpanded_macros = macros; |
838 | self.unexpanded_attribute_macros = attribute_macros; | ||
839 | 834 | ||
840 | for (module_id, macro_call_id, depth) in resolved { | 835 | for (module_id, macro_call_id, depth) in resolved { |
841 | self.collect_macro_expansion(module_id, macro_call_id, depth); | 836 | self.collect_macro_expansion(module_id, macro_call_id, depth); |
@@ -844,15 +839,11 @@ impl DefCollector<'_> { | |||
844 | res | 839 | res |
845 | } | 840 | } |
846 | 841 | ||
847 | fn resolve_derive_macro( | 842 | fn resolve_derive_macro(&self, module: LocalModuleId, path: &ModPath) -> Option<MacroDefId> { |
848 | &self, | ||
849 | directive: &DeriveDirective, | ||
850 | path: &ModPath, | ||
851 | ) -> Option<MacroDefId> { | ||
852 | let resolved_res = self.def_map.resolve_path_fp_with_macro( | 843 | let resolved_res = self.def_map.resolve_path_fp_with_macro( |
853 | self.db, | 844 | self.db, |
854 | ResolveMode::Other, | 845 | ResolveMode::Other, |
855 | directive.module_id, | 846 | module, |
856 | &path, | 847 | &path, |
857 | BuiltinShadowMode::Module, | 848 | BuiltinShadowMode::Module, |
858 | ); | 849 | ); |
@@ -912,33 +903,35 @@ impl DefCollector<'_> { | |||
912 | // Emit diagnostics for all remaining unexpanded macros. | 903 | // Emit diagnostics for all remaining unexpanded macros. |
913 | 904 | ||
914 | for directive in &self.unexpanded_macros { | 905 | for directive in &self.unexpanded_macros { |
915 | let mut error = None; | 906 | match &directive.kind { |
916 | match macro_call_as_call_id( | 907 | MacroDirectiveKind::FnLike { ast_id, .. } => match macro_call_as_call_id( |
917 | &directive.ast_id, | 908 | ast_id, |
918 | self.db, | 909 | self.db, |
919 | self.def_map.krate, | 910 | self.def_map.krate, |
920 | |path| { | 911 | |path| { |
921 | let resolved_res = self.def_map.resolve_path_fp_with_macro( | 912 | let resolved_res = self.def_map.resolve_path_fp_with_macro( |
922 | self.db, | 913 | self.db, |
923 | ResolveMode::Other, | 914 | ResolveMode::Other, |
924 | directive.module_id, | 915 | directive.module_id, |
925 | &path, | 916 | &path, |
926 | BuiltinShadowMode::Module, | 917 | BuiltinShadowMode::Module, |
927 | ); | 918 | ); |
928 | resolved_res.resolved_def.take_macros() | 919 | resolved_res.resolved_def.take_macros() |
929 | }, | 920 | }, |
930 | &mut |e| { | 921 | &mut |_| (), |
931 | error.get_or_insert(e); | 922 | ) { |
923 | Ok(_) => (), | ||
924 | Err(UnresolvedMacro) => { | ||
925 | self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call( | ||
926 | directive.module_id, | ||
927 | ast_id.ast_id, | ||
928 | )); | ||
929 | } | ||
932 | }, | 930 | }, |
933 | ) { | 931 | MacroDirectiveKind::Derive { .. } => { |
934 | Ok(_) => (), | 932 | // FIXME: we might want to diagnose this too |
935 | Err(UnresolvedMacro) => { | ||
936 | self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call( | ||
937 | directive.module_id, | ||
938 | directive.ast_id.ast_id, | ||
939 | )); | ||
940 | } | 933 | } |
941 | }; | 934 | } |
942 | } | 935 | } |
943 | 936 | ||
944 | // Emit diagnostics for all remaining unresolved imports. | 937 | // Emit diagnostics for all remaining unresolved imports. |
@@ -1380,9 +1373,11 @@ impl ModCollector<'_, '_> { | |||
1380 | Some(derive_macros) => { | 1373 | Some(derive_macros) => { |
1381 | for path in derive_macros { | 1374 | for path in derive_macros { |
1382 | let ast_id = AstIdWithPath::new(self.file_id, ast_id, path); | 1375 | let ast_id = AstIdWithPath::new(self.file_id, ast_id, path); |
1383 | self.def_collector | 1376 | self.def_collector.unexpanded_macros.push(MacroDirective { |
1384 | .unexpanded_attribute_macros | 1377 | module_id: self.module_id, |
1385 | .push(DeriveDirective { module_id: self.module_id, ast_id }); | 1378 | depth: self.macro_depth + 1, |
1379 | kind: MacroDirectiveKind::Derive { ast_id }, | ||
1380 | }); | ||
1386 | } | 1381 | } |
1387 | } | 1382 | } |
1388 | None => { | 1383 | None => { |
@@ -1467,12 +1462,13 @@ impl ModCollector<'_, '_> { | |||
1467 | }, | 1462 | }, |
1468 | ) { | 1463 | ) { |
1469 | Ok(Ok(macro_call_id)) => { | 1464 | Ok(Ok(macro_call_id)) => { |
1470 | self.def_collector.unexpanded_macros.push(MacroDirective { | 1465 | // Legacy macros need to be expanded immediately, so that any macros they produce |
1471 | module_id: self.module_id, | 1466 | // are in scope. |
1472 | ast_id, | 1467 | self.def_collector.collect_macro_expansion( |
1473 | legacy: Some(macro_call_id), | 1468 | self.module_id, |
1474 | depth: self.macro_depth + 1, | 1469 | macro_call_id, |
1475 | }); | 1470 | self.macro_depth + 1, |
1471 | ); | ||
1476 | 1472 | ||
1477 | return; | 1473 | return; |
1478 | } | 1474 | } |
@@ -1496,9 +1492,8 @@ impl ModCollector<'_, '_> { | |||
1496 | 1492 | ||
1497 | self.def_collector.unexpanded_macros.push(MacroDirective { | 1493 | self.def_collector.unexpanded_macros.push(MacroDirective { |
1498 | module_id: self.module_id, | 1494 | module_id: self.module_id, |
1499 | ast_id, | ||
1500 | legacy: None, | ||
1501 | depth: self.macro_depth + 1, | 1495 | depth: self.macro_depth + 1, |
1496 | kind: MacroDirectiveKind::FnLike { ast_id, legacy: None }, | ||
1502 | }); | 1497 | }); |
1503 | } | 1498 | } |
1504 | 1499 | ||
@@ -1541,7 +1536,6 @@ mod tests { | |||
1541 | unresolved_imports: Vec::new(), | 1536 | unresolved_imports: Vec::new(), |
1542 | resolved_imports: Vec::new(), | 1537 | resolved_imports: Vec::new(), |
1543 | unexpanded_macros: Vec::new(), | 1538 | unexpanded_macros: Vec::new(), |
1544 | unexpanded_attribute_macros: Vec::new(), | ||
1545 | mod_dirs: FxHashMap::default(), | 1539 | mod_dirs: FxHashMap::default(), |
1546 | cfg_options: &CfgOptions::default(), | 1540 | cfg_options: &CfgOptions::default(), |
1547 | proc_macros: Default::default(), | 1541 | proc_macros: Default::default(), |
diff --git a/crates/hir_def/src/nameres/mod_resolution.rs b/crates/hir_def/src/nameres/mod_resolution.rs index d5de9899c..d9cec0e27 100644 --- a/crates/hir_def/src/nameres/mod_resolution.rs +++ b/crates/hir_def/src/nameres/mod_resolution.rs | |||
@@ -62,7 +62,7 @@ impl ModDir { | |||
62 | name: &Name, | 62 | name: &Name, |
63 | attr_path: Option<&SmolStr>, | 63 | attr_path: Option<&SmolStr>, |
64 | ) -> Result<(FileId, bool, ModDir), String> { | 64 | ) -> Result<(FileId, bool, ModDir), String> { |
65 | let file_id = file_id.original_file(db.upcast()); | 65 | let orig_file_id = file_id.original_file(db.upcast()); |
66 | 66 | ||
67 | let mut candidate_files = Vec::new(); | 67 | let mut candidate_files = Vec::new(); |
68 | match attr_path { | 68 | match attr_path { |
@@ -70,13 +70,18 @@ impl ModDir { | |||
70 | candidate_files.push(self.dir_path.join_attr(attr_path, self.root_non_dir_owner)) | 70 | candidate_files.push(self.dir_path.join_attr(attr_path, self.root_non_dir_owner)) |
71 | } | 71 | } |
72 | None => { | 72 | None => { |
73 | candidate_files.push(format!("{}{}.rs", self.dir_path.0, name)); | 73 | if file_id.is_include_macro(db.upcast()) { |
74 | candidate_files.push(format!("{}{}/mod.rs", self.dir_path.0, name)); | 74 | candidate_files.push(format!("{}.rs", name)); |
75 | candidate_files.push(format!("{}/mod.rs", name)); | ||
76 | } else { | ||
77 | candidate_files.push(format!("{}{}.rs", self.dir_path.0, name)); | ||
78 | candidate_files.push(format!("{}{}/mod.rs", self.dir_path.0, name)); | ||
79 | } | ||
75 | } | 80 | } |
76 | }; | 81 | }; |
77 | 82 | ||
78 | for candidate in candidate_files.iter() { | 83 | for candidate in candidate_files.iter() { |
79 | let path = AnchoredPath { anchor: file_id, path: candidate.as_str() }; | 84 | let path = AnchoredPath { anchor: orig_file_id, path: candidate.as_str() }; |
80 | if let Some(file_id) = db.resolve_path(path) { | 85 | if let Some(file_id) = db.resolve_path(path) { |
81 | let is_mod_rs = candidate.ends_with("/mod.rs"); | 86 | let is_mod_rs = candidate.ends_with("/mod.rs"); |
82 | 87 | ||
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs index db459b1ed..60471937c 100644 --- a/crates/hir_def/src/nameres/path_resolution.rs +++ b/crates/hir_def/src/nameres/path_resolution.rs | |||
@@ -156,7 +156,7 @@ impl DefMap { | |||
156 | } | 156 | } |
157 | } | 157 | } |
158 | 158 | ||
159 | fn resolve_path_fp_with_macro_single( | 159 | pub(super) fn resolve_path_fp_with_macro_single( |
160 | &self, | 160 | &self, |
161 | db: &dyn DefDatabase, | 161 | db: &dyn DefDatabase, |
162 | mode: ResolveMode, | 162 | mode: ResolveMode, |
diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs index d59d3c0db..6d3cb8d7a 100644 --- a/crates/hir_def/src/nameres/tests/macros.rs +++ b/crates/hir_def/src/nameres/tests/macros.rs | |||
@@ -713,6 +713,27 @@ b! { static = #[] ();} | |||
713 | } | 713 | } |
714 | 714 | ||
715 | #[test] | 715 | #[test] |
716 | fn macros_defining_macros() { | ||
717 | check( | ||
718 | r#" | ||
719 | macro_rules! item { | ||
720 | ($item:item) => { $item } | ||
721 | } | ||
722 | |||
723 | item! { | ||
724 | macro_rules! indirect_macro { () => { struct S {} } } | ||
725 | } | ||
726 | |||
727 | indirect_macro!(); | ||
728 | "#, | ||
729 | expect![[r#" | ||
730 | crate | ||
731 | S: t | ||
732 | "#]], | ||
733 | ); | ||
734 | } | ||
735 | |||
736 | #[test] | ||
716 | fn resolves_proc_macros() { | 737 | fn resolves_proc_macros() { |
717 | check( | 738 | check( |
718 | r" | 739 | r" |
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index 42736171e..a73585ee7 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs | |||
@@ -12,7 +12,7 @@ use crate::{ | |||
12 | body::scope::{ExprScopes, ScopeId}, | 12 | body::scope::{ExprScopes, ScopeId}, |
13 | builtin_type::BuiltinType, | 13 | builtin_type::BuiltinType, |
14 | db::DefDatabase, | 14 | db::DefDatabase, |
15 | expr::{ExprId, PatId}, | 15 | expr::{ExprId, LabelId, PatId}, |
16 | generics::GenericParams, | 16 | generics::GenericParams, |
17 | item_scope::{BuiltinShadowMode, BUILTIN_SCOPE}, | 17 | item_scope::{BuiltinShadowMode, BUILTIN_SCOPE}, |
18 | nameres::DefMap, | 18 | nameres::DefMap, |
@@ -409,6 +409,7 @@ pub enum ScopeDef { | |||
409 | AdtSelfType(AdtId), | 409 | AdtSelfType(AdtId), |
410 | GenericParam(GenericParamId), | 410 | GenericParam(GenericParamId), |
411 | Local(PatId), | 411 | Local(PatId), |
412 | Label(LabelId), | ||
412 | } | 413 | } |
413 | 414 | ||
414 | impl Scope { | 415 | impl Scope { |
@@ -470,6 +471,9 @@ impl Scope { | |||
470 | f(name![Self], ScopeDef::AdtSelfType(*i)); | 471 | f(name![Self], ScopeDef::AdtSelfType(*i)); |
471 | } | 472 | } |
472 | Scope::ExprScope(scope) => { | 473 | Scope::ExprScope(scope) => { |
474 | if let Some((label, name)) = scope.expr_scopes.label(scope.scope_id) { | ||
475 | f(name, ScopeDef::Label(label)) | ||
476 | } | ||
473 | scope.expr_scopes.entries(scope.scope_id).iter().for_each(|e| { | 477 | scope.expr_scopes.entries(scope.scope_id).iter().for_each(|e| { |
474 | f(e.name().clone(), ScopeDef::Local(e.pat())); | 478 | f(e.name().clone(), ScopeDef::Local(e.pat())); |
475 | }); | 479 | }); |
@@ -544,7 +548,7 @@ impl ModuleItemMap { | |||
544 | path: &ModPath, | 548 | path: &ModPath, |
545 | ) -> Option<ResolveValueResult> { | 549 | ) -> Option<ResolveValueResult> { |
546 | let (module_def, idx) = | 550 | let (module_def, idx) = |
547 | self.def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other); | 551 | self.def_map.resolve_path_locally(db, self.module_id, &path, BuiltinShadowMode::Other); |
548 | match idx { | 552 | match idx { |
549 | None => { | 553 | None => { |
550 | let value = to_value_ns(module_def)?; | 554 | let value = to_value_ns(module_def)?; |
@@ -574,7 +578,7 @@ impl ModuleItemMap { | |||
574 | path: &ModPath, | 578 | path: &ModPath, |
575 | ) -> Option<(TypeNs, Option<usize>)> { | 579 | ) -> Option<(TypeNs, Option<usize>)> { |
576 | let (module_def, idx) = | 580 | let (module_def, idx) = |
577 | self.def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other); | 581 | self.def_map.resolve_path_locally(db, self.module_id, &path, BuiltinShadowMode::Other); |
578 | let res = to_type_ns(module_def)?; | 582 | let res = to_type_ns(module_def)?; |
579 | Some((res, idx)) | 583 | Some((res, idx)) |
580 | } | 584 | } |
@@ -623,8 +627,18 @@ pub trait HasResolver: Copy { | |||
623 | 627 | ||
624 | impl HasResolver for ModuleId { | 628 | impl HasResolver for ModuleId { |
625 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { | 629 | fn resolver(self, db: &dyn DefDatabase) -> Resolver { |
626 | let def_map = self.def_map(db); | 630 | let mut def_map = self.def_map(db); |
627 | Resolver::default().push_module_scope(def_map, self.local_id) | 631 | let mut modules = Vec::new(); |
632 | modules.push((def_map.clone(), self.local_id)); | ||
633 | while let Some(parent) = def_map.parent() { | ||
634 | def_map = parent.def_map(db); | ||
635 | modules.push((def_map.clone(), parent.local_id)); | ||
636 | } | ||
637 | let mut resolver = Resolver::default(); | ||
638 | for (def_map, module) in modules.into_iter().rev() { | ||
639 | resolver = resolver.push_module_scope(def_map, module); | ||
640 | } | ||
641 | resolver | ||
628 | } | 642 | } |
629 | } | 643 | } |
630 | 644 | ||
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index 8529b43b6..4d52904b9 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs | |||
@@ -43,7 +43,7 @@ macro_rules! register_builtin { | |||
43 | db: &dyn AstDatabase, | 43 | db: &dyn AstDatabase, |
44 | arg_id: EagerMacroId, | 44 | arg_id: EagerMacroId, |
45 | tt: &tt::Subtree, | 45 | tt: &tt::Subtree, |
46 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 46 | ) -> ExpandResult<Option<ExpandedEager>> { |
47 | let expander = match *self { | 47 | let expander = match *self { |
48 | $( EagerExpander::$e_kind => $e_expand, )* | 48 | $( EagerExpander::$e_kind => $e_expand, )* |
49 | }; | 49 | }; |
@@ -61,6 +61,20 @@ macro_rules! register_builtin { | |||
61 | }; | 61 | }; |
62 | } | 62 | } |
63 | 63 | ||
64 | #[derive(Debug)] | ||
65 | pub struct ExpandedEager { | ||
66 | pub(crate) subtree: tt::Subtree, | ||
67 | pub(crate) fragment: FragmentKind, | ||
68 | /// The included file ID of the include macro. | ||
69 | pub(crate) included_file: Option<FileId>, | ||
70 | } | ||
71 | |||
72 | impl ExpandedEager { | ||
73 | fn new(subtree: tt::Subtree, fragment: FragmentKind) -> Self { | ||
74 | ExpandedEager { subtree, fragment, included_file: None } | ||
75 | } | ||
76 | } | ||
77 | |||
64 | pub fn find_builtin_macro( | 78 | pub fn find_builtin_macro( |
65 | ident: &name::Name, | 79 | ident: &name::Name, |
66 | krate: CrateId, | 80 | krate: CrateId, |
@@ -280,7 +294,7 @@ fn compile_error_expand( | |||
280 | _db: &dyn AstDatabase, | 294 | _db: &dyn AstDatabase, |
281 | _id: EagerMacroId, | 295 | _id: EagerMacroId, |
282 | tt: &tt::Subtree, | 296 | tt: &tt::Subtree, |
283 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 297 | ) -> ExpandResult<Option<ExpandedEager>> { |
284 | let err = match &*tt.token_trees { | 298 | let err = match &*tt.token_trees { |
285 | [tt::TokenTree::Leaf(tt::Leaf::Literal(it))] => { | 299 | [tt::TokenTree::Leaf(tt::Leaf::Literal(it))] => { |
286 | let text = it.text.as_str(); | 300 | let text = it.text.as_str(); |
@@ -294,14 +308,14 @@ fn compile_error_expand( | |||
294 | _ => mbe::ExpandError::BindingError("`compile_error!` argument must be a string".into()), | 308 | _ => mbe::ExpandError::BindingError("`compile_error!` argument must be a string".into()), |
295 | }; | 309 | }; |
296 | 310 | ||
297 | ExpandResult { value: Some((quote! {}, FragmentKind::Items)), err: Some(err) } | 311 | ExpandResult { value: Some(ExpandedEager::new(quote! {}, FragmentKind::Items)), err: Some(err) } |
298 | } | 312 | } |
299 | 313 | ||
300 | fn concat_expand( | 314 | fn concat_expand( |
301 | _db: &dyn AstDatabase, | 315 | _db: &dyn AstDatabase, |
302 | _arg_id: EagerMacroId, | 316 | _arg_id: EagerMacroId, |
303 | tt: &tt::Subtree, | 317 | tt: &tt::Subtree, |
304 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 318 | ) -> ExpandResult<Option<ExpandedEager>> { |
305 | let mut err = None; | 319 | let mut err = None; |
306 | let mut text = String::new(); | 320 | let mut text = String::new(); |
307 | for (i, t) in tt.token_trees.iter().enumerate() { | 321 | for (i, t) in tt.token_trees.iter().enumerate() { |
@@ -325,7 +339,7 @@ fn concat_expand( | |||
325 | } | 339 | } |
326 | } | 340 | } |
327 | } | 341 | } |
328 | ExpandResult { value: Some((quote!(#text), FragmentKind::Expr)), err } | 342 | ExpandResult { value: Some(ExpandedEager::new(quote!(#text), FragmentKind::Expr)), err } |
329 | } | 343 | } |
330 | 344 | ||
331 | fn relative_file( | 345 | fn relative_file( |
@@ -361,21 +375,27 @@ fn include_expand( | |||
361 | db: &dyn AstDatabase, | 375 | db: &dyn AstDatabase, |
362 | arg_id: EagerMacroId, | 376 | arg_id: EagerMacroId, |
363 | tt: &tt::Subtree, | 377 | tt: &tt::Subtree, |
364 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 378 | ) -> ExpandResult<Option<ExpandedEager>> { |
365 | let res = (|| { | 379 | let res = (|| { |
366 | let path = parse_string(tt)?; | 380 | let path = parse_string(tt)?; |
367 | let file_id = relative_file(db, arg_id.into(), &path, false)?; | 381 | let file_id = relative_file(db, arg_id.into(), &path, false)?; |
368 | 382 | ||
369 | Ok(parse_to_token_tree(&db.file_text(file_id)) | 383 | let subtree = parse_to_token_tree(&db.file_text(file_id)) |
370 | .ok_or_else(|| mbe::ExpandError::ConversionError)? | 384 | .ok_or_else(|| mbe::ExpandError::ConversionError)? |
371 | .0) | 385 | .0; |
386 | Ok((subtree, file_id)) | ||
372 | })(); | 387 | })(); |
373 | 388 | ||
374 | match res { | 389 | match res { |
375 | Ok(res) => { | 390 | Ok((subtree, file_id)) => { |
376 | // FIXME: | 391 | // FIXME: |
377 | // Handle include as expression | 392 | // Handle include as expression |
378 | ExpandResult::ok(Some((res, FragmentKind::Items))) | 393 | |
394 | ExpandResult::ok(Some(ExpandedEager { | ||
395 | subtree, | ||
396 | fragment: FragmentKind::Items, | ||
397 | included_file: Some(file_id), | ||
398 | })) | ||
379 | } | 399 | } |
380 | Err(e) => ExpandResult::only_err(e), | 400 | Err(e) => ExpandResult::only_err(e), |
381 | } | 401 | } |
@@ -385,7 +405,7 @@ fn include_bytes_expand( | |||
385 | _db: &dyn AstDatabase, | 405 | _db: &dyn AstDatabase, |
386 | _arg_id: EagerMacroId, | 406 | _arg_id: EagerMacroId, |
387 | tt: &tt::Subtree, | 407 | tt: &tt::Subtree, |
388 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 408 | ) -> ExpandResult<Option<ExpandedEager>> { |
389 | if let Err(e) = parse_string(tt) { | 409 | if let Err(e) = parse_string(tt) { |
390 | return ExpandResult::only_err(e); | 410 | return ExpandResult::only_err(e); |
391 | } | 411 | } |
@@ -398,14 +418,14 @@ fn include_bytes_expand( | |||
398 | id: tt::TokenId::unspecified(), | 418 | id: tt::TokenId::unspecified(), |
399 | }))], | 419 | }))], |
400 | }; | 420 | }; |
401 | ExpandResult::ok(Some((res, FragmentKind::Expr))) | 421 | ExpandResult::ok(Some(ExpandedEager::new(res, FragmentKind::Expr))) |
402 | } | 422 | } |
403 | 423 | ||
404 | fn include_str_expand( | 424 | fn include_str_expand( |
405 | db: &dyn AstDatabase, | 425 | db: &dyn AstDatabase, |
406 | arg_id: EagerMacroId, | 426 | arg_id: EagerMacroId, |
407 | tt: &tt::Subtree, | 427 | tt: &tt::Subtree, |
408 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 428 | ) -> ExpandResult<Option<ExpandedEager>> { |
409 | let path = match parse_string(tt) { | 429 | let path = match parse_string(tt) { |
410 | Ok(it) => it, | 430 | Ok(it) => it, |
411 | Err(e) => return ExpandResult::only_err(e), | 431 | Err(e) => return ExpandResult::only_err(e), |
@@ -418,14 +438,14 @@ fn include_str_expand( | |||
418 | let file_id = match relative_file(db, arg_id.into(), &path, true) { | 438 | let file_id = match relative_file(db, arg_id.into(), &path, true) { |
419 | Ok(file_id) => file_id, | 439 | Ok(file_id) => file_id, |
420 | Err(_) => { | 440 | Err(_) => { |
421 | return ExpandResult::ok(Some((quote!(""), FragmentKind::Expr))); | 441 | return ExpandResult::ok(Some(ExpandedEager::new(quote!(""), FragmentKind::Expr))); |
422 | } | 442 | } |
423 | }; | 443 | }; |
424 | 444 | ||
425 | let text = db.file_text(file_id); | 445 | let text = db.file_text(file_id); |
426 | let text = &*text; | 446 | let text = &*text; |
427 | 447 | ||
428 | ExpandResult::ok(Some((quote!(#text), FragmentKind::Expr))) | 448 | ExpandResult::ok(Some(ExpandedEager::new(quote!(#text), FragmentKind::Expr))) |
429 | } | 449 | } |
430 | 450 | ||
431 | fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> { | 451 | fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> { |
@@ -437,7 +457,7 @@ fn env_expand( | |||
437 | db: &dyn AstDatabase, | 457 | db: &dyn AstDatabase, |
438 | arg_id: EagerMacroId, | 458 | arg_id: EagerMacroId, |
439 | tt: &tt::Subtree, | 459 | tt: &tt::Subtree, |
440 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 460 | ) -> ExpandResult<Option<ExpandedEager>> { |
441 | let key = match parse_string(tt) { | 461 | let key = match parse_string(tt) { |
442 | Ok(it) => it, | 462 | Ok(it) => it, |
443 | Err(e) => return ExpandResult::only_err(e), | 463 | Err(e) => return ExpandResult::only_err(e), |
@@ -461,14 +481,14 @@ fn env_expand( | |||
461 | }); | 481 | }); |
462 | let expanded = quote! { #s }; | 482 | let expanded = quote! { #s }; |
463 | 483 | ||
464 | ExpandResult { value: Some((expanded, FragmentKind::Expr)), err } | 484 | ExpandResult { value: Some(ExpandedEager::new(expanded, FragmentKind::Expr)), err } |
465 | } | 485 | } |
466 | 486 | ||
467 | fn option_env_expand( | 487 | fn option_env_expand( |
468 | db: &dyn AstDatabase, | 488 | db: &dyn AstDatabase, |
469 | arg_id: EagerMacroId, | 489 | arg_id: EagerMacroId, |
470 | tt: &tt::Subtree, | 490 | tt: &tt::Subtree, |
471 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 491 | ) -> ExpandResult<Option<ExpandedEager>> { |
472 | let key = match parse_string(tt) { | 492 | let key = match parse_string(tt) { |
473 | Ok(it) => it, | 493 | Ok(it) => it, |
474 | Err(e) => return ExpandResult::only_err(e), | 494 | Err(e) => return ExpandResult::only_err(e), |
@@ -479,7 +499,7 @@ fn option_env_expand( | |||
479 | Some(s) => quote! { std::option::Some(#s) }, | 499 | Some(s) => quote! { std::option::Some(#s) }, |
480 | }; | 500 | }; |
481 | 501 | ||
482 | ExpandResult::ok(Some((expanded, FragmentKind::Expr))) | 502 | ExpandResult::ok(Some(ExpandedEager::new(expanded, FragmentKind::Expr))) |
483 | } | 503 | } |
484 | 504 | ||
485 | #[cfg(test)] | 505 | #[cfg(test)] |
@@ -553,16 +573,18 @@ mod tests { | |||
553 | subtree: Arc::new(parsed_args.clone()), | 573 | subtree: Arc::new(parsed_args.clone()), |
554 | krate, | 574 | krate, |
555 | call: call_id, | 575 | call: call_id, |
576 | included_file: None, | ||
556 | } | 577 | } |
557 | }); | 578 | }); |
558 | 579 | ||
559 | let (subtree, fragment) = expander.expand(&db, arg_id, &parsed_args).value.unwrap(); | 580 | let expanded = expander.expand(&db, arg_id, &parsed_args).value.unwrap(); |
560 | let eager = EagerCallLoc { | 581 | let eager = EagerCallLoc { |
561 | def, | 582 | def, |
562 | fragment, | 583 | fragment: expanded.fragment, |
563 | subtree: Arc::new(subtree), | 584 | subtree: Arc::new(expanded.subtree), |
564 | krate, | 585 | krate, |
565 | call: call_id, | 586 | call: call_id, |
587 | included_file: expanded.included_file, | ||
566 | }; | 588 | }; |
567 | 589 | ||
568 | let id: MacroCallId = db.intern_eager_expansion(eager).into(); | 590 | let id: MacroCallId = db.intern_eager_expansion(eager).into(); |
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs index 2748e25cf..fc73e435b 100644 --- a/crates/hir_expand/src/db.rs +++ b/crates/hir_expand/src/db.rs | |||
@@ -173,7 +173,7 @@ fn macro_arg_text(db: &dyn AstDatabase, id: MacroCallId) -> Option<GreenNode> { | |||
173 | }; | 173 | }; |
174 | let loc = db.lookup_intern_macro(id); | 174 | let loc = db.lookup_intern_macro(id); |
175 | let arg = loc.kind.arg(db)?; | 175 | let arg = loc.kind.arg(db)?; |
176 | Some(arg.green().to_owned()) | 176 | Some(arg.green()) |
177 | } | 177 | } |
178 | 178 | ||
179 | fn macro_arg(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> { | 179 | fn macro_arg(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> { |
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs index 04f374a29..9eedc8461 100644 --- a/crates/hir_expand/src/eager.rs +++ b/crates/hir_expand/src/eager.rs | |||
@@ -124,6 +124,7 @@ pub fn expand_eager_macro( | |||
124 | subtree: Arc::new(parsed_args.clone()), | 124 | subtree: Arc::new(parsed_args.clone()), |
125 | krate, | 125 | krate, |
126 | call: call_id, | 126 | call: call_id, |
127 | included_file: None, | ||
127 | } | 128 | } |
128 | }); | 129 | }); |
129 | let arg_file_id: MacroCallId = arg_id.into(); | 130 | let arg_file_id: MacroCallId = arg_id.into(); |
@@ -143,9 +144,15 @@ pub fn expand_eager_macro( | |||
143 | if let MacroDefKind::BuiltInEager(eager, _) = def.kind { | 144 | if let MacroDefKind::BuiltInEager(eager, _) = def.kind { |
144 | let res = eager.expand(db, arg_id, &subtree); | 145 | let res = eager.expand(db, arg_id, &subtree); |
145 | 146 | ||
146 | let (subtree, fragment) = diagnostic_sink.expand_result_option(res)?; | 147 | let expanded = diagnostic_sink.expand_result_option(res)?; |
147 | let eager = | 148 | let eager = EagerCallLoc { |
148 | EagerCallLoc { def, fragment, subtree: Arc::new(subtree), krate, call: call_id }; | 149 | def, |
150 | fragment: expanded.fragment, | ||
151 | subtree: Arc::new(expanded.subtree), | ||
152 | krate, | ||
153 | call: call_id, | ||
154 | included_file: expanded.included_file, | ||
155 | }; | ||
149 | 156 | ||
150 | Ok(db.intern_eager_expansion(eager)) | 157 | Ok(db.intern_eager_expansion(eager)) |
151 | } else { | 158 | } else { |
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs index f49fd4fda..b8045fda9 100644 --- a/crates/hir_expand/src/lib.rs +++ b/crates/hir_expand/src/lib.rs | |||
@@ -84,7 +84,11 @@ impl HirFileId { | |||
84 | } | 84 | } |
85 | MacroCallId::EagerMacro(id) => { | 85 | MacroCallId::EagerMacro(id) => { |
86 | let loc = db.lookup_intern_eager_expansion(id); | 86 | let loc = db.lookup_intern_eager_expansion(id); |
87 | loc.call.file_id | 87 | if let Some(included_file) = loc.included_file { |
88 | return included_file; | ||
89 | } else { | ||
90 | loc.call.file_id | ||
91 | } | ||
88 | } | 92 | } |
89 | }; | 93 | }; |
90 | file_id.original_file(db) | 94 | file_id.original_file(db) |
@@ -188,6 +192,21 @@ impl HirFileId { | |||
188 | } | 192 | } |
189 | } | 193 | } |
190 | } | 194 | } |
195 | |||
196 | /// Return whether this file is an include macro | ||
197 | pub fn is_include_macro(&self, db: &dyn db::AstDatabase) -> bool { | ||
198 | match self.0 { | ||
199 | HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id { | ||
200 | MacroCallId::EagerMacro(id) => { | ||
201 | let loc = db.lookup_intern_eager_expansion(id); | ||
202 | return loc.included_file.is_some(); | ||
203 | } | ||
204 | _ => {} | ||
205 | }, | ||
206 | _ => {} | ||
207 | } | ||
208 | false | ||
209 | } | ||
191 | } | 210 | } |
192 | 211 | ||
193 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 212 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -315,6 +334,8 @@ pub struct EagerCallLoc { | |||
315 | pub(crate) subtree: Arc<tt::Subtree>, | 334 | pub(crate) subtree: Arc<tt::Subtree>, |
316 | pub(crate) krate: CrateId, | 335 | pub(crate) krate: CrateId, |
317 | pub(crate) call: AstId<ast::MacroCall>, | 336 | pub(crate) call: AstId<ast::MacroCall>, |
337 | // The included file ID of the include macro. | ||
338 | pub(crate) included_file: Option<FileId>, | ||
318 | } | 339 | } |
319 | 340 | ||
320 | /// ExpansionInfo mainly describes how to map text range between src and expanded macro | 341 | /// ExpansionInfo mainly describes how to map text range between src and expanded macro |
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs index 43de9edd6..0aeea48d5 100644 --- a/crates/hir_expand/src/name.rs +++ b/crates/hir_expand/src/name.rs | |||
@@ -48,9 +48,8 @@ impl Name { | |||
48 | 48 | ||
49 | /// Resolve a name from the text of token. | 49 | /// Resolve a name from the text of token. |
50 | fn resolve(raw_text: &str) -> Name { | 50 | fn resolve(raw_text: &str) -> Name { |
51 | let raw_start = "r#"; | 51 | if let Some(text) = raw_text.strip_prefix("r#") { |
52 | if raw_text.starts_with(raw_start) { | 52 | Name::new_text(SmolStr::new(text)) |
53 | Name::new_text(SmolStr::new(&raw_text[raw_start.len()..])) | ||
54 | } else { | 53 | } else { |
55 | Name::new_text(raw_text.into()) | 54 | Name::new_text(raw_text.into()) |
56 | } | 55 | } |
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs index 23ab042c1..dc5fc759a 100644 --- a/crates/hir_ty/src/autoderef.rs +++ b/crates/hir_ty/src/autoderef.rs | |||
@@ -16,8 +16,8 @@ use crate::{ | |||
16 | to_assoc_type_id, to_chalk_trait_id, | 16 | to_assoc_type_id, to_chalk_trait_id, |
17 | traits::{InEnvironment, Solution}, | 17 | traits::{InEnvironment, Solution}, |
18 | utils::generics, | 18 | utils::generics, |
19 | AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, Interner, ProjectionTy, Substitution, | 19 | AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner, |
20 | TraitRef, Ty, TyKind, | 20 | ProjectionTy, Substitution, TraitRef, Ty, TyKind, |
21 | }; | 21 | }; |
22 | 22 | ||
23 | const AUTODEREF_RECURSION_LIMIT: usize = 10; | 23 | const AUTODEREF_RECURSION_LIMIT: usize = 10; |
@@ -27,9 +27,9 @@ pub fn autoderef<'a>( | |||
27 | krate: Option<CrateId>, | 27 | krate: Option<CrateId>, |
28 | ty: InEnvironment<Canonical<Ty>>, | 28 | ty: InEnvironment<Canonical<Ty>>, |
29 | ) -> impl Iterator<Item = Canonical<Ty>> + 'a { | 29 | ) -> impl Iterator<Item = Canonical<Ty>> + 'a { |
30 | let InEnvironment { value: ty, environment } = ty; | 30 | let InEnvironment { goal: ty, environment } = ty; |
31 | successors(Some(ty), move |ty| { | 31 | successors(Some(ty), move |ty| { |
32 | deref(db, krate?, InEnvironment { value: ty, environment: environment.clone() }) | 32 | deref(db, krate?, InEnvironment { goal: ty, environment: environment.clone() }) |
33 | }) | 33 | }) |
34 | .take(AUTODEREF_RECURSION_LIMIT) | 34 | .take(AUTODEREF_RECURSION_LIMIT) |
35 | } | 35 | } |
@@ -39,8 +39,8 @@ pub(crate) fn deref( | |||
39 | krate: CrateId, | 39 | krate: CrateId, |
40 | ty: InEnvironment<&Canonical<Ty>>, | 40 | ty: InEnvironment<&Canonical<Ty>>, |
41 | ) -> Option<Canonical<Ty>> { | 41 | ) -> Option<Canonical<Ty>> { |
42 | if let Some(derefed) = ty.value.value.builtin_deref() { | 42 | if let Some(derefed) = ty.goal.value.builtin_deref() { |
43 | Some(Canonical { value: derefed, kinds: ty.value.kinds.clone() }) | 43 | Some(Canonical { value: derefed, binders: ty.goal.binders.clone() }) |
44 | } else { | 44 | } else { |
45 | deref_by_trait(db, krate, ty) | 45 | deref_by_trait(db, krate, ty) |
46 | } | 46 | } |
@@ -67,15 +67,15 @@ fn deref_by_trait( | |||
67 | // FIXME make the Canonical / bound var handling nicer | 67 | // FIXME make the Canonical / bound var handling nicer |
68 | 68 | ||
69 | let parameters = | 69 | let parameters = |
70 | Substitution::build_for_generics(&generic_params).push(ty.value.value.clone()).build(); | 70 | Substitution::build_for_generics(&generic_params).push(ty.goal.value.clone()).build(); |
71 | 71 | ||
72 | // Check that the type implements Deref at all | 72 | // Check that the type implements Deref at all |
73 | let trait_ref = | 73 | let trait_ref = |
74 | TraitRef { trait_id: to_chalk_trait_id(deref_trait), substitution: parameters.clone() }; | 74 | TraitRef { trait_id: to_chalk_trait_id(deref_trait), substitution: parameters.clone() }; |
75 | let implements_goal = Canonical { | 75 | let implements_goal = Canonical { |
76 | kinds: ty.value.kinds.clone(), | 76 | binders: ty.goal.binders.clone(), |
77 | value: InEnvironment { | 77 | value: InEnvironment { |
78 | value: trait_ref.cast(&Interner), | 78 | goal: trait_ref.cast(&Interner), |
79 | environment: ty.environment.clone(), | 79 | environment: ty.environment.clone(), |
80 | }, | 80 | }, |
81 | }; | 81 | }; |
@@ -89,18 +89,27 @@ fn deref_by_trait( | |||
89 | associated_ty_id: to_assoc_type_id(target), | 89 | associated_ty_id: to_assoc_type_id(target), |
90 | substitution: parameters, | 90 | substitution: parameters, |
91 | }), | 91 | }), |
92 | ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len())) | 92 | ty: TyKind::BoundVar(BoundVar::new( |
93 | .intern(&Interner), | 93 | DebruijnIndex::INNERMOST, |
94 | ty.goal.binders.len(&Interner), | ||
95 | )) | ||
96 | .intern(&Interner), | ||
94 | }; | 97 | }; |
95 | 98 | ||
96 | let obligation = projection.cast(&Interner); | 99 | let obligation = projection.cast(&Interner); |
97 | 100 | ||
98 | let in_env = InEnvironment { value: obligation, environment: ty.environment }; | 101 | let in_env = InEnvironment { goal: obligation, environment: ty.environment }; |
99 | 102 | ||
100 | let canonical = Canonical::new( | 103 | let canonical = Canonical { |
101 | in_env, | 104 | value: in_env, |
102 | ty.value.kinds.iter().copied().chain(Some(chalk_ir::TyVariableKind::General)), | 105 | binders: CanonicalVarKinds::from_iter( |
103 | ); | 106 | &Interner, |
107 | ty.goal.binders.iter(&Interner).cloned().chain(Some(chalk_ir::WithKind::new( | ||
108 | chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), | ||
109 | chalk_ir::UniverseIndex::ROOT, | ||
110 | ))), | ||
111 | ), | ||
112 | }; | ||
104 | 113 | ||
105 | let solution = db.trait_solve(krate, canonical)?; | 114 | let solution = db.trait_solve(krate, canonical)?; |
106 | 115 | ||
@@ -121,21 +130,21 @@ fn deref_by_trait( | |||
121 | // assumptions will be broken. We would need to properly introduce | 130 | // assumptions will be broken. We would need to properly introduce |
122 | // new variables in that case | 131 | // new variables in that case |
123 | 132 | ||
124 | for i in 1..vars.0.kinds.len() { | 133 | for i in 1..vars.0.binders.len(&Interner) { |
125 | if vars.0.value[i - 1].interned(&Interner) | 134 | if vars.0.value[i - 1].interned(&Interner) |
126 | != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) | 135 | != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) |
127 | { | 136 | { |
128 | warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution); | 137 | warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution); |
129 | return None; | 138 | return None; |
130 | } | 139 | } |
131 | } | 140 | } |
132 | Some(Canonical { | 141 | Some(Canonical { |
133 | value: vars.0.value[vars.0.value.len() - 1].clone(), | 142 | value: vars.0.value[vars.0.value.len() - 1].clone(), |
134 | kinds: vars.0.kinds.clone(), | 143 | binders: vars.0.binders.clone(), |
135 | }) | 144 | }) |
136 | } | 145 | } |
137 | Solution::Ambig(_) => { | 146 | Solution::Ambig(_) => { |
138 | info!("Ambiguous solution for derefing {:?}: {:?}", ty.value, solution); | 147 | info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution); |
139 | None | 148 | None |
140 | } | 149 | } |
141 | } | 150 | } |
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs index 91a2e0b5b..58e4247c6 100644 --- a/crates/hir_ty/src/db.rs +++ b/crates/hir_ty/src/db.rs | |||
@@ -12,8 +12,8 @@ use la_arena::ArenaMap; | |||
12 | use crate::{ | 12 | use crate::{ |
13 | method_resolution::{InherentImpls, TraitImpls}, | 13 | method_resolution::{InherentImpls, TraitImpls}, |
14 | traits::chalk, | 14 | traits::chalk, |
15 | Binders, CallableDefId, FnDefId, ImplTraitId, InferenceResult, PolyFnSig, ReturnTypeImplTraits, | 15 | Binders, CallableDefId, FnDefId, ImplTraitId, InferenceResult, PolyFnSig, |
16 | TraitRef, Ty, TyDefId, ValueTyDefId, WhereClause, | 16 | QuantifiedWhereClause, ReturnTypeImplTraits, TraitRef, Ty, TyDefId, ValueTyDefId, |
17 | }; | 17 | }; |
18 | use hir_expand::name::Name; | 18 | use hir_expand::name::Name; |
19 | 19 | ||
@@ -57,10 +57,13 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { | |||
57 | 57 | ||
58 | #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] | 58 | #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] |
59 | #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)] | 59 | #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)] |
60 | fn generic_predicates_for_param(&self, param_id: TypeParamId) -> Arc<[Binders<WhereClause>]>; | 60 | fn generic_predicates_for_param( |
61 | &self, | ||
62 | param_id: TypeParamId, | ||
63 | ) -> Arc<[Binders<QuantifiedWhereClause>]>; | ||
61 | 64 | ||
62 | #[salsa::invoke(crate::lower::generic_predicates_query)] | 65 | #[salsa::invoke(crate::lower::generic_predicates_query)] |
63 | fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<WhereClause>]>; | 66 | fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<QuantifiedWhereClause>]>; |
64 | 67 | ||
65 | #[salsa::invoke(crate::lower::trait_environment_query)] | 68 | #[salsa::invoke(crate::lower::trait_environment_query)] |
66 | fn trait_environment(&self, def: GenericDefId) -> Arc<crate::TraitEnvironment>; | 69 | fn trait_environment(&self, def: GenericDefId) -> Arc<crate::TraitEnvironment>; |
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 3845009ae..6149067c7 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use std::{borrow::Cow, fmt}; | 3 | use std::fmt; |
4 | 4 | ||
5 | use arrayvec::ArrayVec; | 5 | use arrayvec::ArrayVec; |
6 | use chalk_ir::Mutability; | 6 | use chalk_ir::Mutability; |
@@ -20,7 +20,7 @@ use crate::{ | |||
20 | db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, | 20 | db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, |
21 | to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, | 21 | to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, |
22 | CallableDefId, CallableSig, DomainGoal, ImplTraitId, Interner, Lifetime, OpaqueTy, | 22 | CallableDefId, CallableSig, DomainGoal, ImplTraitId, Interner, Lifetime, OpaqueTy, |
23 | ProjectionTy, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause, | 23 | ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause, |
24 | }; | 24 | }; |
25 | 25 | ||
26 | pub struct HirFormatter<'a> { | 26 | pub struct HirFormatter<'a> { |
@@ -190,6 +190,7 @@ impl DisplayTarget { | |||
190 | pub enum DisplaySourceCodeError { | 190 | pub enum DisplaySourceCodeError { |
191 | PathNotFound, | 191 | PathNotFound, |
192 | UnknownType, | 192 | UnknownType, |
193 | Closure, | ||
193 | } | 194 | } |
194 | 195 | ||
195 | pub enum HirDisplayError { | 196 | pub enum HirDisplayError { |
@@ -328,9 +329,9 @@ impl HirDisplay for Ty { | |||
328 | 329 | ||
329 | // FIXME: all this just to decide whether to use parentheses... | 330 | // FIXME: all this just to decide whether to use parentheses... |
330 | let datas; | 331 | let datas; |
331 | let predicates = match t.interned(&Interner) { | 332 | let predicates: Vec<_> = match t.interned(&Interner) { |
332 | TyKind::Dyn(predicates) if predicates.len() > 1 => { | 333 | TyKind::Dyn(dyn_ty) if dyn_ty.bounds.skip_binders().interned().len() > 1 => { |
333 | Cow::Borrowed(predicates.as_ref()) | 334 | dyn_ty.bounds.skip_binders().interned().iter().cloned().collect() |
334 | } | 335 | } |
335 | &TyKind::Alias(AliasTy::Opaque(OpaqueTy { | 336 | &TyKind::Alias(AliasTy::Opaque(OpaqueTy { |
336 | opaque_ty_id, | 337 | opaque_ty_id, |
@@ -345,17 +346,21 @@ impl HirDisplay for Ty { | |||
345 | .as_ref() | 346 | .as_ref() |
346 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); | 347 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); |
347 | let bounds = data.subst(parameters); | 348 | let bounds = data.subst(parameters); |
348 | Cow::Owned(bounds.value) | 349 | bounds.value |
349 | } else { | 350 | } else { |
350 | Cow::Borrowed(&[][..]) | 351 | Vec::new() |
351 | } | 352 | } |
352 | } | 353 | } |
353 | _ => Cow::Borrowed(&[][..]), | 354 | _ => Vec::new(), |
354 | }; | 355 | }; |
355 | 356 | ||
356 | if let [WhereClause::Implemented(trait_ref), _] = predicates.as_ref() { | 357 | if let Some(WhereClause::Implemented(trait_ref)) = |
358 | predicates.get(0).map(|b| b.skip_binders()) | ||
359 | { | ||
357 | let trait_ = trait_ref.hir_trait_id(); | 360 | let trait_ = trait_ref.hir_trait_id(); |
358 | if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_) { | 361 | if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_) |
362 | && predicates.len() <= 2 | ||
363 | { | ||
359 | return write!(f, "{}", ty_display); | 364 | return write!(f, "{}", ty_display); |
360 | } | 365 | } |
361 | } | 366 | } |
@@ -539,6 +544,11 @@ impl HirDisplay for Ty { | |||
539 | } | 544 | } |
540 | } | 545 | } |
541 | TyKind::Closure(.., substs) => { | 546 | TyKind::Closure(.., substs) => { |
547 | if f.display_target.is_source_code() { | ||
548 | return Err(HirDisplayError::DisplaySourceCodeError( | ||
549 | DisplaySourceCodeError::Closure, | ||
550 | )); | ||
551 | } | ||
542 | let sig = substs[0].callable_sig(f.db); | 552 | let sig = substs[0].callable_sig(f.db); |
543 | if let Some(sig) = sig { | 553 | if let Some(sig) = sig { |
544 | if sig.params().is_empty() { | 554 | if sig.params().is_empty() { |
@@ -571,19 +581,32 @@ impl HirDisplay for Ty { | |||
571 | write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? | 581 | write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? |
572 | } | 582 | } |
573 | TypeParamProvenance::ArgumentImplTrait => { | 583 | TypeParamProvenance::ArgumentImplTrait => { |
574 | let bounds = f.db.generic_predicates_for_param(id); | ||
575 | let substs = Substitution::type_params_for_generics(f.db, &generics); | 584 | let substs = Substitution::type_params_for_generics(f.db, &generics); |
576 | write_bounds_like_dyn_trait_with_prefix( | 585 | let bounds = f |
577 | "impl", | 586 | .db |
578 | &bounds.iter().map(|b| b.clone().subst(&substs)).collect::<Vec<_>>(), | 587 | .generic_predicates(id.parent) |
579 | f, | 588 | .into_iter() |
580 | )?; | 589 | .map(|pred| pred.clone().subst(&substs)) |
590 | .filter(|wc| match &wc.skip_binders() { | ||
591 | WhereClause::Implemented(tr) => tr.self_type_parameter() == self, | ||
592 | WhereClause::AliasEq(AliasEq { | ||
593 | alias: AliasTy::Projection(proj), | ||
594 | ty: _, | ||
595 | }) => proj.self_type_parameter() == self, | ||
596 | _ => false, | ||
597 | }) | ||
598 | .collect::<Vec<_>>(); | ||
599 | write_bounds_like_dyn_trait_with_prefix("impl", &bounds, f)?; | ||
581 | } | 600 | } |
582 | } | 601 | } |
583 | } | 602 | } |
584 | TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, | 603 | TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, |
585 | TyKind::Dyn(predicates) => { | 604 | TyKind::Dyn(dyn_ty) => { |
586 | write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?; | 605 | write_bounds_like_dyn_trait_with_prefix( |
606 | "dyn", | ||
607 | dyn_ty.bounds.skip_binders().interned(), | ||
608 | f, | ||
609 | )?; | ||
587 | } | 610 | } |
588 | TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, | 611 | TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, |
589 | TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { | 612 | TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { |
@@ -652,7 +675,7 @@ fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = Trai | |||
652 | 675 | ||
653 | pub fn write_bounds_like_dyn_trait_with_prefix( | 676 | pub fn write_bounds_like_dyn_trait_with_prefix( |
654 | prefix: &str, | 677 | prefix: &str, |
655 | predicates: &[WhereClause], | 678 | predicates: &[QuantifiedWhereClause], |
656 | f: &mut HirFormatter, | 679 | f: &mut HirFormatter, |
657 | ) -> Result<(), HirDisplayError> { | 680 | ) -> Result<(), HirDisplayError> { |
658 | write!(f, "{}", prefix)?; | 681 | write!(f, "{}", prefix)?; |
@@ -665,7 +688,7 @@ pub fn write_bounds_like_dyn_trait_with_prefix( | |||
665 | } | 688 | } |
666 | 689 | ||
667 | fn write_bounds_like_dyn_trait( | 690 | fn write_bounds_like_dyn_trait( |
668 | predicates: &[WhereClause], | 691 | predicates: &[QuantifiedWhereClause], |
669 | f: &mut HirFormatter, | 692 | f: &mut HirFormatter, |
670 | ) -> Result<(), HirDisplayError> { | 693 | ) -> Result<(), HirDisplayError> { |
671 | // Note: This code is written to produce nice results (i.e. | 694 | // Note: This code is written to produce nice results (i.e. |
@@ -678,7 +701,7 @@ fn write_bounds_like_dyn_trait( | |||
678 | let mut angle_open = false; | 701 | let mut angle_open = false; |
679 | let mut is_fn_trait = false; | 702 | let mut is_fn_trait = false; |
680 | for p in predicates.iter() { | 703 | for p in predicates.iter() { |
681 | match p { | 704 | match p.skip_binders() { |
682 | WhereClause::Implemented(trait_ref) => { | 705 | WhereClause::Implemented(trait_ref) => { |
683 | let trait_ = trait_ref.hir_trait_id(); | 706 | let trait_ = trait_ref.hir_trait_id(); |
684 | if !is_fn_trait { | 707 | if !is_fn_trait { |
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index b9e434c78..8f9cf7480 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs | |||
@@ -331,7 +331,7 @@ impl<'a> InferenceContext<'a> { | |||
331 | fn resolve_obligations_as_possible(&mut self) { | 331 | fn resolve_obligations_as_possible(&mut self) { |
332 | let obligations = mem::replace(&mut self.obligations, Vec::new()); | 332 | let obligations = mem::replace(&mut self.obligations, Vec::new()); |
333 | for obligation in obligations { | 333 | for obligation in obligations { |
334 | let in_env = InEnvironment::new(self.trait_env.clone(), obligation.clone()); | 334 | let in_env = InEnvironment::new(self.trait_env.env.clone(), obligation.clone()); |
335 | let canonicalized = self.canonicalizer().canonicalize_obligation(in_env); | 335 | let canonicalized = self.canonicalizer().canonicalize_obligation(in_env); |
336 | let solution = | 336 | let solution = |
337 | self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); | 337 | self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); |
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index 07eb96573..9c62932b1 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs | |||
@@ -142,7 +142,7 @@ impl<'a> InferenceContext<'a> { | |||
142 | .build(); | 142 | .build(); |
143 | let trait_ref = | 143 | let trait_ref = |
144 | TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs }; | 144 | TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs }; |
145 | let goal = InEnvironment::new(self.trait_env.clone(), trait_ref.cast(&Interner)); | 145 | let goal = InEnvironment::new(self.trait_env.env.clone(), trait_ref.cast(&Interner)); |
146 | 146 | ||
147 | let canonicalizer = self.canonicalizer(); | 147 | let canonicalizer = self.canonicalizer(); |
148 | let canonicalized = canonicalizer.canonicalize_obligation(goal); | 148 | let canonicalized = canonicalizer.canonicalize_obligation(goal); |
@@ -170,8 +170,8 @@ impl<'a> InferenceContext<'a> { | |||
170 | self.db, | 170 | self.db, |
171 | self.resolver.krate(), | 171 | self.resolver.krate(), |
172 | InEnvironment { | 172 | InEnvironment { |
173 | value: canonicalized.value.clone(), | 173 | goal: canonicalized.value.clone(), |
174 | environment: self.trait_env.clone(), | 174 | environment: self.trait_env.env.clone(), |
175 | }, | 175 | }, |
176 | ) { | 176 | ) { |
177 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); | 177 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 46d713a7b..3f3187ea2 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -11,6 +11,7 @@ use hir_def::{ | |||
11 | AssocContainerId, FieldId, Lookup, | 11 | AssocContainerId, FieldId, Lookup, |
12 | }; | 12 | }; |
13 | use hir_expand::name::{name, Name}; | 13 | use hir_expand::name::{name, Name}; |
14 | use stdx::always; | ||
14 | use syntax::ast::RangeOp; | 15 | use syntax::ast::RangeOp; |
15 | 16 | ||
16 | use crate::{ | 17 | use crate::{ |
@@ -89,12 +90,12 @@ impl<'a> InferenceContext<'a> { | |||
89 | let substs = | 90 | let substs = |
90 | Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); | 91 | Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); |
91 | 92 | ||
92 | let trait_env = Arc::clone(&self.trait_env); | 93 | let trait_env = self.trait_env.env.clone(); |
93 | let implements_fn_trait: DomainGoal = | 94 | let implements_fn_trait: DomainGoal = |
94 | TraitRef { trait_id: to_chalk_trait_id(fn_once_trait), substitution: substs.clone() } | 95 | TraitRef { trait_id: to_chalk_trait_id(fn_once_trait), substitution: substs.clone() } |
95 | .cast(&Interner); | 96 | .cast(&Interner); |
96 | let goal = self.canonicalizer().canonicalize_obligation(InEnvironment { | 97 | let goal = self.canonicalizer().canonicalize_obligation(InEnvironment { |
97 | value: implements_fn_trait.clone(), | 98 | goal: implements_fn_trait.clone(), |
98 | environment: trait_env, | 99 | environment: trait_env, |
99 | }); | 100 | }); |
100 | if self.db.trait_solve(krate, goal.value).is_some() { | 101 | if self.db.trait_solve(krate, goal.value).is_some() { |
@@ -298,8 +299,8 @@ impl<'a> InferenceContext<'a> { | |||
298 | self.db, | 299 | self.db, |
299 | self.resolver.krate(), | 300 | self.resolver.krate(), |
300 | InEnvironment { | 301 | InEnvironment { |
301 | value: canonicalized.value.clone(), | 302 | goal: canonicalized.value.clone(), |
302 | environment: self.trait_env.clone(), | 303 | environment: self.trait_env.env.clone(), |
303 | }, | 304 | }, |
304 | ); | 305 | ); |
305 | let (param_tys, ret_ty): (Vec<Ty>, Ty) = derefs | 306 | let (param_tys, ret_ty): (Vec<Ty>, Ty) = derefs |
@@ -437,8 +438,8 @@ impl<'a> InferenceContext<'a> { | |||
437 | self.db, | 438 | self.db, |
438 | self.resolver.krate(), | 439 | self.resolver.krate(), |
439 | InEnvironment { | 440 | InEnvironment { |
440 | value: canonicalized.value.clone(), | 441 | goal: canonicalized.value.clone(), |
441 | environment: self.trait_env.clone(), | 442 | environment: self.trait_env.env.clone(), |
442 | }, | 443 | }, |
443 | ) | 444 | ) |
444 | .find_map(|derefed_ty| { | 445 | .find_map(|derefed_ty| { |
@@ -533,10 +534,10 @@ impl<'a> InferenceContext<'a> { | |||
533 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); | 534 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); |
534 | if let Some(box_) = self.resolve_boxed_box() { | 535 | if let Some(box_) = self.resolve_boxed_box() { |
535 | let mut sb = | 536 | let mut sb = |
536 | Substitution::builder(generics(self.db.upcast(), box_.into()).len()); | 537 | Substitution::build_for_generics(&generics(self.db.upcast(), box_.into())); |
537 | sb = sb.push(inner_ty); | 538 | sb = sb.push(inner_ty); |
538 | match self.db.generic_defaults(box_.into()).as_ref() { | 539 | match self.db.generic_defaults(box_.into()).get(1) { |
539 | [_, alloc_ty, ..] if !alloc_ty.value.is_unknown() => { | 540 | Some(alloc_ty) if !alloc_ty.value.is_unknown() && sb.remaining() > 0 => { |
540 | sb = sb.push(alloc_ty.value.clone()); | 541 | sb = sb.push(alloc_ty.value.clone()); |
541 | } | 542 | } |
542 | _ => (), | 543 | _ => (), |
@@ -557,8 +558,8 @@ impl<'a> InferenceContext<'a> { | |||
557 | self.db, | 558 | self.db, |
558 | krate, | 559 | krate, |
559 | InEnvironment { | 560 | InEnvironment { |
560 | value: &canonicalized.value, | 561 | goal: &canonicalized.value, |
561 | environment: self.trait_env.clone(), | 562 | environment: self.trait_env.env.clone(), |
562 | }, | 563 | }, |
563 | ) { | 564 | ) { |
564 | Some(derefed_ty) => { | 565 | Some(derefed_ty) => { |
@@ -957,7 +958,9 @@ impl<'a> InferenceContext<'a> { | |||
957 | let def: CallableDefId = from_chalk(self.db, *fn_def); | 958 | let def: CallableDefId = from_chalk(self.db, *fn_def); |
958 | let generic_predicates = self.db.generic_predicates(def.into()); | 959 | let generic_predicates = self.db.generic_predicates(def.into()); |
959 | for predicate in generic_predicates.iter() { | 960 | for predicate in generic_predicates.iter() { |
960 | let predicate = predicate.clone().subst(parameters); | 961 | let (predicate, binders) = |
962 | predicate.clone().subst(parameters).into_value_and_skipped_binders(); | ||
963 | always!(binders == 0); // quantified where clauses not yet handled | ||
961 | self.obligations.push(predicate.cast(&Interner)); | 964 | self.obligations.push(predicate.cast(&Interner)); |
962 | } | 965 | } |
963 | // add obligation for trait implementation, if this is a trait method | 966 | // add obligation for trait implementation, if this is a trait method |
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index befa0d69b..474363709 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs | |||
@@ -13,7 +13,9 @@ use hir_expand::name::Name; | |||
13 | 13 | ||
14 | use super::{BindingMode, Expectation, InferenceContext}; | 14 | use super::{BindingMode, Expectation, InferenceContext}; |
15 | use crate::{ | 15 | use crate::{ |
16 | lower::lower_to_chalk_mutability, utils::variant_data, Interner, Substitution, Ty, TyKind, | 16 | lower::lower_to_chalk_mutability, |
17 | utils::{generics, variant_data}, | ||
18 | Interner, Substitution, Ty, TyKind, | ||
17 | }; | 19 | }; |
18 | 20 | ||
19 | impl<'a> InferenceContext<'a> { | 21 | impl<'a> InferenceContext<'a> { |
@@ -38,7 +40,7 @@ impl<'a> InferenceContext<'a> { | |||
38 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); | 40 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); |
39 | let (pre, post) = match ellipsis { | 41 | let (pre, post) = match ellipsis { |
40 | Some(idx) => subpats.split_at(idx), | 42 | Some(idx) => subpats.split_at(idx), |
41 | None => (&subpats[..], &[][..]), | 43 | None => (subpats, &[][..]), |
42 | }; | 44 | }; |
43 | let post_idx_offset = field_tys.iter().count() - post.len(); | 45 | let post_idx_offset = field_tys.iter().count() - post.len(); |
44 | 46 | ||
@@ -233,13 +235,31 @@ impl<'a> InferenceContext<'a> { | |||
233 | Pat::Lit(expr) => self.infer_expr(*expr, &Expectation::has_type(expected.clone())), | 235 | Pat::Lit(expr) => self.infer_expr(*expr, &Expectation::has_type(expected.clone())), |
234 | Pat::Box { inner } => match self.resolve_boxed_box() { | 236 | Pat::Box { inner } => match self.resolve_boxed_box() { |
235 | Some(box_adt) => { | 237 | Some(box_adt) => { |
236 | let inner_expected = match expected.as_adt() { | 238 | let (inner_ty, alloc_ty) = match expected.as_adt() { |
237 | Some((adt, substs)) if adt == box_adt => substs.as_single().clone(), | 239 | Some((adt, subst)) if adt == box_adt => { |
238 | _ => self.result.standard_types.unknown.clone(), | 240 | (subst[0].clone(), subst.get(1).cloned()) |
241 | } | ||
242 | _ => (self.result.standard_types.unknown.clone(), None), | ||
239 | }; | 243 | }; |
240 | 244 | ||
241 | let inner_ty = self.infer_pat(*inner, &inner_expected, default_bm); | 245 | let inner_ty = self.infer_pat(*inner, &inner_ty, default_bm); |
242 | Ty::adt_ty(box_adt, Substitution::single(inner_ty)) | 246 | let mut sb = Substitution::build_for_generics(&generics( |
247 | self.db.upcast(), | ||
248 | box_adt.into(), | ||
249 | )); | ||
250 | sb = sb.push(inner_ty); | ||
251 | if sb.remaining() == 1 { | ||
252 | sb = sb.push(match alloc_ty { | ||
253 | Some(alloc_ty) if !alloc_ty.is_unknown() => alloc_ty, | ||
254 | _ => match self.db.generic_defaults(box_adt.into()).get(1) { | ||
255 | Some(alloc_ty) if !alloc_ty.value.is_unknown() => { | ||
256 | alloc_ty.value.clone() | ||
257 | } | ||
258 | _ => self.table.new_type_var(), | ||
259 | }, | ||
260 | }); | ||
261 | } | ||
262 | Ty::adt_ty(box_adt, sb.build()) | ||
243 | } | 263 | } |
244 | None => self.err_ty(), | 264 | None => self.err_ty(), |
245 | }, | 265 | }, |
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index 1fc03c8f4..75250a369 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs | |||
@@ -2,13 +2,13 @@ | |||
2 | 2 | ||
3 | use std::borrow::Cow; | 3 | use std::borrow::Cow; |
4 | 4 | ||
5 | use chalk_ir::{FloatTy, IntTy, TyVariableKind}; | 5 | use chalk_ir::{FloatTy, IntTy, TyVariableKind, UniverseIndex, VariableKind}; |
6 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; | 6 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; |
7 | 7 | ||
8 | use super::{DomainGoal, InferenceContext}; | 8 | use super::{DomainGoal, InferenceContext}; |
9 | use crate::{ | 9 | use crate::{ |
10 | AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, FnPointer, InEnvironment, InferenceVar, | 10 | AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, |
11 | Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause, | 11 | InEnvironment, InferenceVar, Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | impl<'a> InferenceContext<'a> { | 14 | impl<'a> InferenceContext<'a> { |
@@ -76,8 +76,17 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { | |||
76 | } | 76 | } |
77 | 77 | ||
78 | fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { | 78 | fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { |
79 | let kinds = self.free_vars.iter().map(|&(_, k)| k).collect(); | 79 | let kinds = self |
80 | Canonicalized { value: Canonical { value: result, kinds }, free_vars: self.free_vars } | 80 | .free_vars |
81 | .iter() | ||
82 | .map(|&(_, k)| chalk_ir::WithKind::new(VariableKind::Ty(k), UniverseIndex::ROOT)); | ||
83 | Canonicalized { | ||
84 | value: Canonical { | ||
85 | value: result, | ||
86 | binders: CanonicalVarKinds::from_iter(&Interner, kinds), | ||
87 | }, | ||
88 | free_vars: self.free_vars, | ||
89 | } | ||
81 | } | 90 | } |
82 | 91 | ||
83 | pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> { | 92 | pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> { |
@@ -89,15 +98,12 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { | |||
89 | mut self, | 98 | mut self, |
90 | obligation: InEnvironment<DomainGoal>, | 99 | obligation: InEnvironment<DomainGoal>, |
91 | ) -> Canonicalized<InEnvironment<DomainGoal>> { | 100 | ) -> Canonicalized<InEnvironment<DomainGoal>> { |
92 | let result = match obligation.value { | 101 | let result = match obligation.goal { |
93 | DomainGoal::Holds(wc) => { | 102 | DomainGoal::Holds(wc) => { |
94 | DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST)) | 103 | DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST)) |
95 | } | 104 | } |
96 | }; | 105 | }; |
97 | self.into_canonicalized(InEnvironment { | 106 | self.into_canonicalized(InEnvironment { goal: result, environment: obligation.environment }) |
98 | value: result, | ||
99 | environment: obligation.environment, | ||
100 | }) | ||
101 | } | 107 | } |
102 | } | 108 | } |
103 | 109 | ||
@@ -125,12 +131,19 @@ impl<T> Canonicalized<T> { | |||
125 | // the solution may contain new variables, which we need to convert to new inference vars | 131 | // the solution may contain new variables, which we need to convert to new inference vars |
126 | let new_vars = Substitution( | 132 | let new_vars = Substitution( |
127 | solution | 133 | solution |
128 | .kinds | 134 | .binders |
129 | .iter() | 135 | .iter(&Interner) |
130 | .map(|k| match k { | 136 | .map(|k| match k.kind { |
131 | TyVariableKind::General => ctx.table.new_type_var(), | 137 | VariableKind::Ty(TyVariableKind::General) => ctx.table.new_type_var(), |
132 | TyVariableKind::Integer => ctx.table.new_integer_var(), | 138 | VariableKind::Ty(TyVariableKind::Integer) => ctx.table.new_integer_var(), |
133 | TyVariableKind::Float => ctx.table.new_float_var(), | 139 | VariableKind::Ty(TyVariableKind::Float) => ctx.table.new_float_var(), |
140 | // HACK: Chalk can sometimes return new lifetime variables. We | ||
141 | // want to just skip them, but to not mess up the indices of | ||
142 | // other variables, we'll just create a new type variable in | ||
143 | // their place instead. This should not matter (we never see the | ||
144 | // actual *uses* of the lifetime variable). | ||
145 | VariableKind::Lifetime => ctx.table.new_type_var(), | ||
146 | _ => panic!("const variable in solution"), | ||
134 | }) | 147 | }) |
135 | .collect(), | 148 | .collect(), |
136 | ); | 149 | ); |
@@ -147,8 +160,8 @@ impl<T> Canonicalized<T> { | |||
147 | pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { | 160 | pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { |
148 | let mut table = InferenceTable::new(); | 161 | let mut table = InferenceTable::new(); |
149 | let vars = Substitution( | 162 | let vars = Substitution( |
150 | tys.kinds | 163 | tys.binders |
151 | .iter() | 164 | .iter(&Interner) |
152 | // we always use type vars here because we want everything to | 165 | // we always use type vars here because we want everything to |
153 | // fallback to Unknown in the end (kind of hacky, as below) | 166 | // fallback to Unknown in the end (kind of hacky, as below) |
154 | .map(|_| table.new_type_var()) | 167 | .map(|_| table.new_type_var()) |
@@ -170,7 +183,7 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { | |||
170 | } | 183 | } |
171 | } | 184 | } |
172 | Some( | 185 | Some( |
173 | Substitution::builder(tys.kinds.len()) | 186 | Substitution::builder(tys.binders.len(&Interner)) |
174 | .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) | 187 | .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) |
175 | .build(), | 188 | .build(), |
176 | ) | 189 | ) |
@@ -310,9 +323,18 @@ impl InferenceTable { | |||
310 | 323 | ||
311 | (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) if *p1 == *p2 => true, | 324 | (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) if *p1 == *p2 => true, |
312 | 325 | ||
313 | (TyKind::Dyn(dyn1), TyKind::Dyn(dyn2)) if dyn1.len() == dyn2.len() => { | 326 | (TyKind::Dyn(dyn1), TyKind::Dyn(dyn2)) |
314 | for (pred1, pred2) in dyn1.iter().zip(dyn2.iter()) { | 327 | if dyn1.bounds.skip_binders().interned().len() |
315 | if !self.unify_preds(pred1, pred2, depth + 1) { | 328 | == dyn2.bounds.skip_binders().interned().len() => |
329 | { | ||
330 | for (pred1, pred2) in dyn1 | ||
331 | .bounds | ||
332 | .skip_binders() | ||
333 | .interned() | ||
334 | .iter() | ||
335 | .zip(dyn2.bounds.skip_binders().interned().iter()) | ||
336 | { | ||
337 | if !self.unify_preds(pred1.skip_binders(), pred2.skip_binders(), depth + 1) { | ||
316 | return false; | 338 | return false; |
317 | } | 339 | } |
318 | } | 340 | } |
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index c46529879..69265286f 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -61,6 +61,8 @@ pub type ClosureId = chalk_ir::ClosureId<Interner>; | |||
61 | pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; | 61 | pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; |
62 | pub type PlaceholderIndex = chalk_ir::PlaceholderIndex; | 62 | pub type PlaceholderIndex = chalk_ir::PlaceholderIndex; |
63 | 63 | ||
64 | pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>; | ||
65 | |||
64 | pub type ChalkTraitId = chalk_ir::TraitId<Interner>; | 66 | pub type ChalkTraitId = chalk_ir::TraitId<Interner>; |
65 | 67 | ||
66 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 68 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
@@ -106,6 +108,10 @@ impl ProjectionTy { | |||
106 | } | 108 | } |
107 | } | 109 | } |
108 | 110 | ||
111 | pub fn self_type_parameter(&self) -> &Ty { | ||
112 | &self.substitution[0] | ||
113 | } | ||
114 | |||
109 | fn trait_(&self, db: &dyn HirDatabase) -> TraitId { | 115 | fn trait_(&self, db: &dyn HirDatabase) -> TraitId { |
110 | match from_assoc_type_id(self.associated_ty_id).lookup(db.upcast()).container { | 116 | match from_assoc_type_id(self.associated_ty_id).lookup(db.upcast()).container { |
111 | AssocContainerId::TraitId(it) => it, | 117 | AssocContainerId::TraitId(it) => it, |
@@ -128,6 +134,12 @@ impl TypeWalk for ProjectionTy { | |||
128 | } | 134 | } |
129 | } | 135 | } |
130 | 136 | ||
137 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
138 |