aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock178
-rw-r--r--crates/ra_hir_ty/Cargo.toml4
-rw-r--r--crates/ra_hir_ty/src/tests/coercion.rs42
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs8
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs86
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/interner.rs1
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/mapping.rs9
-rw-r--r--crates/ra_ide/src/completion/complete_keyword.rs14
-rw-r--r--crates/ra_ide/src/completion/test_utils.rs23
-rw-r--r--crates/ra_ssr/src/lib.rs18
-rw-r--r--crates/ra_ssr/src/matching.rs4
-rw-r--r--crates/ra_ssr/src/tests.rs61
12 files changed, 372 insertions, 76 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c040bfb95..a70c22a94 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -25,6 +25,15 @@ dependencies = [
25] 25]
26 26
27[[package]] 27[[package]]
28name = "ansi_term"
29version = "0.11.0"
30source = "registry+https://github.com/rust-lang/crates.io-index"
31checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
32dependencies = [
33 "winapi 0.3.8",
34]
35
36[[package]]
28name = "anyhow" 37name = "anyhow"
29version = "1.0.31" 38version = "1.0.31"
30source = "registry+https://github.com/rust-lang/crates.io-index" 39source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -95,6 +104,12 @@ dependencies = [
95] 104]
96 105
97[[package]] 106[[package]]
107name = "byteorder"
108version = "1.3.4"
109source = "registry+https://github.com/rust-lang/crates.io-index"
110checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
111
112[[package]]
98name = "cargo_metadata" 113name = "cargo_metadata"
99version = "0.10.0" 114version = "0.10.0"
100source = "registry+https://github.com/rust-lang/crates.io-index" 115source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -120,9 +135,8 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
120 135
121[[package]] 136[[package]]
122name = "chalk-derive" 137name = "chalk-derive"
123version = "0.11.0" 138version = "0.15.0-dev.0"
124source = "registry+https://github.com/rust-lang/crates.io-index" 139source = "git+https://github.com/rust-lang/chalk#57037a53f7decc965d25972606c3ea930e9cb39f"
125checksum = "5b9bd01eab87277d973183a1d2e56bace1c11f8242c52c20636fb7dddf343ac9"
126dependencies = [ 140dependencies = [
127 "proc-macro2", 141 "proc-macro2",
128 "quote", 142 "quote",
@@ -132,20 +146,19 @@ dependencies = [
132 146
133[[package]] 147[[package]]
134name = "chalk-engine" 148name = "chalk-engine"
135version = "0.11.0" 149version = "0.15.0-dev.0"
136source = "registry+https://github.com/rust-lang/crates.io-index" 150source = "git+https://github.com/rust-lang/chalk#57037a53f7decc965d25972606c3ea930e9cb39f"
137checksum = "6c7a637c3d17ed555aef16e16952a5d1e127bd55178cc30be22afeb92da90c7d"
138dependencies = [ 151dependencies = [
139 "chalk-derive", 152 "chalk-derive",
140 "chalk-ir", 153 "chalk-ir",
141 "rustc-hash", 154 "rustc-hash",
155 "tracing",
142] 156]
143 157
144[[package]] 158[[package]]
145name = "chalk-ir" 159name = "chalk-ir"
146version = "0.11.0" 160version = "0.15.0-dev.0"
147source = "registry+https://github.com/rust-lang/crates.io-index" 161source = "git+https://github.com/rust-lang/chalk#57037a53f7decc965d25972606c3ea930e9cb39f"
148checksum = "595e5735ded16c3f3dc348f7b15bbb2521a0080b1863cac38ad5271589944670"
149dependencies = [ 162dependencies = [
150 "chalk-derive", 163 "chalk-derive",
151 "lazy_static", 164 "lazy_static",
@@ -153,9 +166,8 @@ dependencies = [
153 166
154[[package]] 167[[package]]
155name = "chalk-solve" 168name = "chalk-solve"
156version = "0.11.0" 169version = "0.15.0-dev.0"
157source = "registry+https://github.com/rust-lang/crates.io-index" 170source = "git+https://github.com/rust-lang/chalk#57037a53f7decc965d25972606c3ea930e9cb39f"
158checksum = "5d9d938139db425867a30cc0cfec0269406d8238d0571d829041eaa7a8455d11"
159dependencies = [ 171dependencies = [
160 "chalk-derive", 172 "chalk-derive",
161 "chalk-engine", 173 "chalk-engine",
@@ -164,6 +176,19 @@ dependencies = [
164 "itertools", 176 "itertools",
165 "petgraph", 177 "petgraph",
166 "rustc-hash", 178 "rustc-hash",
179 "tracing",
180 "tracing-subscriber",
181]
182
183[[package]]
184name = "chrono"
185version = "0.4.11"
186source = "registry+https://github.com/rust-lang/crates.io-index"
187checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2"
188dependencies = [
189 "num-integer",
190 "num-traits",
191 "time",
167] 192]
168 193
169[[package]] 194[[package]]
@@ -683,6 +708,15 @@ dependencies = [
683] 708]
684 709
685[[package]] 710[[package]]
711name = "matchers"
712version = "0.0.1"
713source = "registry+https://github.com/rust-lang/crates.io-index"
714checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1"
715dependencies = [
716 "regex-automata",
717]
718
719[[package]]
686name = "matches" 720name = "matches"
687version = "0.1.8" 721version = "0.1.8"
688source = "registry+https://github.com/rust-lang/crates.io-index" 722source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -803,6 +837,25 @@ dependencies = [
803] 837]
804 838
805[[package]] 839[[package]]
840name = "num-integer"
841version = "0.1.43"
842source = "registry+https://github.com/rust-lang/crates.io-index"
843checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b"
844dependencies = [
845 "autocfg",
846 "num-traits",
847]
848
849[[package]]
850name = "num-traits"
851version = "0.2.12"
852source = "registry+https://github.com/rust-lang/crates.io-index"
853checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
854dependencies = [
855 "autocfg",
856]
857
858[[package]]
806name = "num_cpus" 859name = "num_cpus"
807version = "1.13.0" 860version = "1.13.0"
808source = "registry+https://github.com/rust-lang/crates.io-index" 861source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1342,6 +1395,16 @@ dependencies = [
1342] 1395]
1343 1396
1344[[package]] 1397[[package]]
1398name = "regex-automata"
1399version = "0.1.9"
1400source = "registry+https://github.com/rust-lang/crates.io-index"
1401checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4"
1402dependencies = [
1403 "byteorder",
1404 "regex-syntax",
1405]
1406
1407[[package]]
1345name = "regex-syntax" 1408name = "regex-syntax"
1346version = "0.6.18" 1409version = "0.6.18"
1347source = "registry+https://github.com/rust-lang/crates.io-index" 1410source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1585,6 +1648,15 @@ dependencies = [
1585] 1648]
1586 1649
1587[[package]] 1650[[package]]
1651name = "sharded-slab"
1652version = "0.0.9"
1653source = "registry+https://github.com/rust-lang/crates.io-index"
1654checksum = "06d5a3f5166fb5b42a5439f2eee8b9de149e235961e3eb21c5808fc3ea17ff3e"
1655dependencies = [
1656 "lazy_static",
1657]
1658
1659[[package]]
1588name = "slab" 1660name = "slab"
1589version = "0.4.2" 1661version = "0.4.2"
1590source = "registry+https://github.com/rust-lang/crates.io-index" 1662source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1713,12 +1785,94 @@ dependencies = [
1713] 1785]
1714 1786
1715[[package]] 1787[[package]]
1788name = "time"
1789version = "0.1.43"
1790source = "registry+https://github.com/rust-lang/crates.io-index"
1791checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
1792dependencies = [
1793 "libc",
1794 "winapi 0.3.8",
1795]
1796
1797[[package]]
1716name = "tinyvec" 1798name = "tinyvec"
1717version = "0.3.3" 1799version = "0.3.3"
1718source = "registry+https://github.com/rust-lang/crates.io-index" 1800source = "registry+https://github.com/rust-lang/crates.io-index"
1719checksum = "53953d2d3a5ad81d9f844a32f14ebb121f50b650cd59d0ee2a07cf13c617efed" 1801checksum = "53953d2d3a5ad81d9f844a32f14ebb121f50b650cd59d0ee2a07cf13c617efed"
1720 1802
1721[[package]] 1803[[package]]
1804name = "tracing"
1805version = "0.1.15"
1806source = "registry+https://github.com/rust-lang/crates.io-index"
1807checksum = "a41f40ed0e162c911ac6fcb53ecdc8134c46905fdbbae8c50add462a538b495f"
1808dependencies = [
1809 "cfg-if",
1810 "tracing-attributes",
1811 "tracing-core",
1812]
1813
1814[[package]]
1815name = "tracing-attributes"
1816version = "0.1.8"
1817source = "registry+https://github.com/rust-lang/crates.io-index"
1818checksum = "99bbad0de3fd923c9c3232ead88510b783e5a4d16a6154adffa3d53308de984c"
1819dependencies = [
1820 "proc-macro2",
1821 "quote",
1822 "syn",
1823]
1824
1825[[package]]
1826name = "tracing-core"
1827version = "0.1.10"
1828source = "registry+https://github.com/rust-lang/crates.io-index"
1829checksum = "0aa83a9a47081cd522c09c81b31aec2c9273424976f922ad61c053b58350b715"
1830dependencies = [
1831 "lazy_static",
1832]
1833
1834[[package]]
1835name = "tracing-log"
1836version = "0.1.1"
1837source = "registry+https://github.com/rust-lang/crates.io-index"
1838checksum = "5e0f8c7178e13481ff6765bd169b33e8d554c5d2bbede5e32c356194be02b9b9"
1839dependencies = [
1840 "lazy_static",
1841 "log",
1842 "tracing-core",
1843]
1844
1845[[package]]
1846name = "tracing-serde"
1847version = "0.1.1"
1848source = "registry+https://github.com/rust-lang/crates.io-index"
1849checksum = "b6ccba2f8f16e0ed268fc765d9b7ff22e965e7185d32f8f1ec8294fe17d86e79"
1850dependencies = [
1851 "serde",
1852 "tracing-core",
1853]
1854
1855[[package]]
1856name = "tracing-subscriber"
1857version = "0.2.6"
1858source = "registry+https://github.com/rust-lang/crates.io-index"
1859checksum = "04a11b459109e38ff6e1b580bafef4142a11d44889f5d07424cbce2fd2a2a119"
1860dependencies = [
1861 "ansi_term",
1862 "chrono",
1863 "lazy_static",
1864 "matchers",
1865 "regex",
1866 "serde",
1867 "serde_json",
1868 "sharded-slab",
1869 "smallvec",
1870 "tracing-core",
1871 "tracing-log",
1872 "tracing-serde",
1873]
1874
1875[[package]]
1722name = "unicode-bidi" 1876name = "unicode-bidi"
1723version = "0.3.4" 1877version = "0.3.4"
1724source = "registry+https://github.com/rust-lang/crates.io-index" 1878source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml
index 112fcd07e..407322dc1 100644
--- a/crates/ra_hir_ty/Cargo.toml
+++ b/crates/ra_hir_ty/Cargo.toml
@@ -27,8 +27,8 @@ test_utils = { path = "../test_utils" }
27 27
28scoped-tls = "1" 28scoped-tls = "1"
29 29
30chalk-solve = "0.11" 30chalk-solve = { version = "0.15.0-dev.0", git = "https://github.com/rust-lang/chalk" }
31chalk-ir = "0.11" 31chalk-ir = { version = "0.15.0-dev.0", git = "https://github.com/rust-lang/chalk" }
32 32
33[dev-dependencies] 33[dev-dependencies]
34insta = "0.16.0" 34insta = "0.16.0"
diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs
index a2601c68a..5a1c6ccc3 100644
--- a/crates/ra_hir_ty/src/tests/coercion.rs
+++ b/crates/ra_hir_ty/src/tests/coercion.rs
@@ -664,6 +664,8 @@ fn test() {
664fn coerce_unsize_trait_object() { 664fn coerce_unsize_trait_object() {
665 assert_snapshot!( 665 assert_snapshot!(
666 infer_with_mismatches(r#" 666 infer_with_mismatches(r#"
667#[lang = "sized"]
668pub trait Sized {}
667#[lang = "unsize"] 669#[lang = "unsize"]
668pub trait Unsize<T> {} 670pub trait Unsize<T> {}
669#[lang = "coerce_unsized"] 671#[lang = "coerce_unsized"]
@@ -689,19 +691,19 @@ fn test() {
689} 691}
690"#, true), 692"#, true),
691 @r###" 693 @r###"
692 387..572 '{ ...bj2; }': () 694 424..609 '{ ...bj2; }': ()
693 397..400 'obj': &dyn Baz<i8, i16> 695 434..437 'obj': &dyn Baz<i8, i16>
694 422..424 '&S': &S<i8, i16> 696 459..461 '&S': &S<i8, i16>
695 423..424 'S': S<i8, i16> 697 460..461 'S': S<i8, i16>
696 434..437 'obj': &dyn Bar<usize, i8, i16> 698 471..474 'obj': &dyn Bar<usize, i8, i16>
697 459..462 'obj': &dyn Baz<i8, i16> 699 496..499 'obj': &dyn Baz<i8, i16>
698 472..475 'obj': &dyn Foo<i8, usize> 700 509..512 'obj': &dyn Foo<i8, usize>
699 494..497 'obj': &dyn Bar<usize, i8, i16> 701 531..534 'obj': &dyn Bar<usize, i8, i16>
700 507..511 'obj2': &dyn Baz<i8, i16> 702 544..548 'obj2': &dyn Baz<i8, i16>
701 533..535 '&S': &S<i8, i16> 703 570..572 '&S': &S<i8, i16>
702 534..535 'S': S<i8, i16> 704 571..572 'S': S<i8, i16>
703 545..546 '_': &dyn Foo<i8, usize> 705 582..583 '_': &dyn Foo<i8, usize>
704 565..569 'obj2': &dyn Baz<i8, i16> 706 602..606 'obj2': &dyn Baz<i8, i16>
705 "### 707 "###
706 ); 708 );
707} 709}
@@ -710,6 +712,8 @@ fn test() {
710fn coerce_unsize_super_trait_cycle() { 712fn coerce_unsize_super_trait_cycle() {
711 assert_snapshot!( 713 assert_snapshot!(
712 infer_with_mismatches(r#" 714 infer_with_mismatches(r#"
715#[lang = "sized"]
716pub trait Sized {}
713#[lang = "unsize"] 717#[lang = "unsize"]
714pub trait Unsize<T> {} 718pub trait Unsize<T> {}
715#[lang = "coerce_unsized"] 719#[lang = "coerce_unsized"]
@@ -734,12 +738,12 @@ fn test() {
734} 738}
735"#, true), 739"#, true),
736 @r###" 740 @r###"
737 291..347 '{ ...obj; }': () 741 328..384 '{ ...obj; }': ()
738 301..304 'obj': &dyn D 742 338..341 'obj': &dyn D
739 315..317 '&S': &S 743 352..354 '&S': &S
740 316..317 'S': S 744 353..354 'S': S
741 327..330 'obj': &dyn A 745 364..367 'obj': &dyn A
742 341..344 'obj': &dyn D 746 378..381 'obj': &dyn D
743 "### 747 "###
744 ); 748 );
745} 749}
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index 646e1715c..71c0c2d27 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -1753,11 +1753,11 @@ fn test() {
1753 384..500 '{ ...(f); }': () 1753 384..500 '{ ...(f); }': ()
1754 394..397 'bar': Bar<fn(u8) -> u32> 1754 394..397 'bar': Bar<fn(u8) -> u32>
1755 423..426 'bar': Bar<fn(u8) -> u32> 1755 423..426 'bar': Bar<fn(u8) -> u32>
1756 423..432 'bar.foo()': {unknown} 1756 423..432 'bar.foo()': (u8, u32)
1757 443..446 'opt': Opt<u8> 1757 443..446 'opt': Opt<u8>
1758 465..466 'f': fn(u8) -> u32 1758 465..466 'f': fn(u8) -> u32
1759 487..490 'opt': Opt<u8> 1759 487..490 'opt': Opt<u8>
1760 487..497 'opt.map(f)': Opt<FnOnce::Output<fn(u8) -> u32, (u8,)>> 1760 487..497 'opt.map(f)': Opt<u32>
1761 495..496 'f': fn(u8) -> u32 1761 495..496 'f': fn(u8) -> u32
1762 "### 1762 "###
1763 ); 1763 );
@@ -1830,9 +1830,9 @@ fn test() {
1830 634..643 'Lazy::new': fn new<Foo, fn() -> Foo>(fn() -> Foo) -> Lazy<Foo, fn() -> Foo> 1830 634..643 'Lazy::new': fn new<Foo, fn() -> Foo>(fn() -> Foo) -> Lazy<Foo, fn() -> Foo>
1831 634..660 'Lazy::...n_ptr)': Lazy<Foo, fn() -> Foo> 1831 634..660 'Lazy::...n_ptr)': Lazy<Foo, fn() -> Foo>
1832 644..659 'make_foo_fn_ptr': fn() -> Foo 1832 644..659 'make_foo_fn_ptr': fn() -> Foo
1833 670..672 'r2': {unknown} 1833 670..672 'r2': usize
1834 675..680 'lazy2': Lazy<Foo, fn() -> Foo> 1834 675..680 'lazy2': Lazy<Foo, fn() -> Foo>
1835 675..686 'lazy2.foo()': {unknown} 1835 675..686 'lazy2.foo()': usize
1836 549..551 '{}': () 1836 549..551 '{}': ()
1837 "### 1837 "###
1838 ); 1838 );
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index 2f35d6d49..8ef4941c0 100644
--- a/crates/ra_hir_ty/src/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -48,6 +48,9 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
48 fn adt_datum(&self, struct_id: AdtId) -> Arc<StructDatum> { 48 fn adt_datum(&self, struct_id: AdtId) -> Arc<StructDatum> {
49 self.db.struct_datum(self.krate, struct_id) 49 self.db.struct_datum(self.krate, struct_id)
50 } 50 }
51 fn adt_repr(&self, _struct_id: AdtId) -> rust_ir::AdtRepr {
52 unreachable!()
53 }
51 fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> { 54 fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> {
52 self.db.impl_datum(self.krate, impl_id) 55 self.db.impl_datum(self.krate, impl_id)
53 } 56 }
@@ -128,8 +131,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
128 well_known_trait: rust_ir::WellKnownTrait, 131 well_known_trait: rust_ir::WellKnownTrait,
129 ) -> Option<chalk_ir::TraitId<Interner>> { 132 ) -> Option<chalk_ir::TraitId<Interner>> {
130 let lang_attr = lang_attr_from_well_known_trait(well_known_trait); 133 let lang_attr = lang_attr_from_well_known_trait(well_known_trait);
131 let lang_items = self.db.crate_lang_items(self.krate); 134 let trait_ = match self.db.lang_item(self.krate, lang_attr.into()) {
132 let trait_ = match lang_items.target(lang_attr) {
133 Some(LangItemTarget::TraitId(trait_)) => trait_, 135 Some(LangItemTarget::TraitId(trait_)) => trait_,
134 _ => return None, 136 _ => return None,
135 }; 137 };
@@ -186,6 +188,39 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
186 // FIXME: implement actual object safety 188 // FIXME: implement actual object safety
187 true 189 true
188 } 190 }
191
192 fn closure_kind(
193 &self,
194 _closure_id: chalk_ir::ClosureId<Interner>,
195 _substs: &chalk_ir::Substitution<Interner>,
196 ) -> rust_ir::ClosureKind {
197 // FIXME: implement closure support
198 unimplemented!()
199 }
200 fn closure_inputs_and_output(
201 &self,
202 _closure_id: chalk_ir::ClosureId<Interner>,
203 _substs: &chalk_ir::Substitution<Interner>,
204 ) -> chalk_ir::Binders<rust_ir::FnDefInputsAndOutputDatum<Interner>> {
205 // FIXME: implement closure support
206 unimplemented!()
207 }
208 fn closure_upvars(
209 &self,
210 _closure_id: chalk_ir::ClosureId<Interner>,
211 _substs: &chalk_ir::Substitution<Interner>,
212 ) -> chalk_ir::Binders<chalk_ir::Ty<Interner>> {
213 // FIXME: implement closure support
214 unimplemented!()
215 }
216 fn closure_fn_substitution(
217 &self,
218 _closure_id: chalk_ir::ClosureId<Interner>,
219 _substs: &chalk_ir::Substitution<Interner>,
220 ) -> chalk_ir::Substitution<Interner> {
221 // FIXME: implement closure support
222 unimplemented!()
223 }
189} 224}
190 225
191pub(crate) fn program_clauses_for_chalk_env_query( 226pub(crate) fn program_clauses_for_chalk_env_query(
@@ -250,7 +285,7 @@ pub(crate) fn trait_datum_query(
250 upstream: trait_.lookup(db.upcast()).container.module(db.upcast()).krate != krate, 285 upstream: trait_.lookup(db.upcast()).container.module(db.upcast()).krate != krate,
251 non_enumerable: true, 286 non_enumerable: true,
252 coinductive: false, // only relevant for Chalk testing 287 coinductive: false, // only relevant for Chalk testing
253 // FIXME set these flags correctly 288 // FIXME: set these flags correctly
254 marker: false, 289 marker: false,
255 fundamental: false, 290 fundamental: false,
256 }; 291 };
@@ -272,20 +307,28 @@ pub(crate) fn trait_datum_query(
272 307
273fn well_known_trait_from_lang_attr(name: &str) -> Option<WellKnownTrait> { 308fn well_known_trait_from_lang_attr(name: &str) -> Option<WellKnownTrait> {
274 Some(match name { 309 Some(match name {
275 "sized" => WellKnownTrait::SizedTrait, 310 "sized" => WellKnownTrait::Sized,
276 "copy" => WellKnownTrait::CopyTrait, 311 "copy" => WellKnownTrait::Copy,
277 "clone" => WellKnownTrait::CloneTrait, 312 "clone" => WellKnownTrait::Clone,
278 "drop" => WellKnownTrait::DropTrait, 313 "drop" => WellKnownTrait::Drop,
314 "fn_once" => WellKnownTrait::FnOnce,
315 "fn_mut" => WellKnownTrait::FnMut,
316 "fn" => WellKnownTrait::Fn,
317 "unsize" => WellKnownTrait::Unsize,
279 _ => return None, 318 _ => return None,
280 }) 319 })
281} 320}
282 321
283fn lang_attr_from_well_known_trait(attr: WellKnownTrait) -> &'static str { 322fn lang_attr_from_well_known_trait(attr: WellKnownTrait) -> &'static str {
284 match attr { 323 match attr {
285 WellKnownTrait::SizedTrait => "sized", 324 WellKnownTrait::Sized => "sized",
286 WellKnownTrait::CopyTrait => "copy", 325 WellKnownTrait::Copy => "copy",
287 WellKnownTrait::CloneTrait => "clone", 326 WellKnownTrait::Clone => "clone",
288 WellKnownTrait::DropTrait => "drop", 327 WellKnownTrait::Drop => "drop",
328 WellKnownTrait::FnOnce => "fn_once",
329 WellKnownTrait::FnMut => "fn_mut",
330 WellKnownTrait::Fn => "fn",
331 WellKnownTrait::Unsize => "unsize",
289 } 332 }
290} 333}
291 334
@@ -309,8 +352,9 @@ pub(crate) fn struct_datum_query(
309 .unwrap_or_else(Vec::new); 352 .unwrap_or_else(Vec::new);
310 let flags = rust_ir::AdtFlags { 353 let flags = rust_ir::AdtFlags {
311 upstream, 354 upstream,
312 // FIXME set fundamental flag correctly 355 // FIXME set fundamental and phantom_data flags correctly
313 fundamental: false, 356 fundamental: false,
357 phantom_data: false,
314 }; 358 };
315 let struct_datum_bound = rust_ir::AdtDatumBound { 359 let struct_datum_bound = rust_ir::AdtDatumBound {
316 fields: Vec::new(), // FIXME add fields (only relevant for auto traits) 360 fields: Vec::new(), // FIXME add fields (only relevant for auto traits)
@@ -448,11 +492,23 @@ pub(crate) fn fn_def_datum_query(
448 let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars); 492 let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars);
449 let bound = rust_ir::FnDefDatumBound { 493 let bound = rust_ir::FnDefDatumBound {
450 // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway 494 // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway
451 argument_types: sig.value.params().iter().map(|ty| ty.clone().to_chalk(db)).collect(), 495 inputs_and_output: make_binders(
452 return_type: sig.value.ret().clone().to_chalk(db), 496 rust_ir::FnDefInputsAndOutputDatum {
497 argument_types: sig
498 .value
499 .params()
500 .iter()
501 .map(|ty| ty.clone().to_chalk(db))
502 .collect(),
503 return_type: sig.value.ret().clone().to_chalk(db),
504 }
505 .shifted_in(&Interner),
506 0,
507 ),
453 where_clauses, 508 where_clauses,
454 }; 509 };
455 let datum = FnDefDatum { id: fn_def_id, binders: make_binders(bound, sig.num_binders) }; 510 let datum =
511 FnDefDatum { id: fn_def_id, binders: make_binders(bound, sig.num_binders), abi: () };
456 Arc::new(datum) 512 Arc::new(datum)
457} 513}
458 514
diff --git a/crates/ra_hir_ty/src/traits/chalk/interner.rs b/crates/ra_hir_ty/src/traits/chalk/interner.rs
index 56aab640c..15426b022 100644
--- a/crates/ra_hir_ty/src/traits/chalk/interner.rs
+++ b/crates/ra_hir_ty/src/traits/chalk/interner.rs
@@ -42,6 +42,7 @@ impl chalk_ir::interner::Interner for Interner {
42 type DefId = InternId; 42 type DefId = InternId;
43 type InternedAdtId = crate::TypeCtorId; 43 type InternedAdtId = crate::TypeCtorId;
44 type Identifier = TypeAliasId; 44 type Identifier = TypeAliasId;
45 type FnAbi = ();
45 46
46 fn debug_adt_id(type_kind_id: AdtId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { 47 fn debug_adt_id(type_kind_id: AdtId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
47 tls::with_current_program(|prog| Some(prog?.debug_struct_id(type_kind_id, fmt))) 48 tls::with_current_program(|prog| Some(prog?.debug_struct_id(type_kind_id, fmt)))
diff --git a/crates/ra_hir_ty/src/traits/chalk/mapping.rs b/crates/ra_hir_ty/src/traits/chalk/mapping.rs
index 18e5c9c16..ac82ea831 100644
--- a/crates/ra_hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/ra_hir_ty/src/traits/chalk/mapping.rs
@@ -65,7 +65,10 @@ impl ToChalk for Ty {
65 &Interner, 65 &Interner,
66 predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)), 66 predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)),
67 ); 67 );
68 let bounded_ty = chalk_ir::DynTy { bounds: make_binders(where_clauses, 1) }; 68 let bounded_ty = chalk_ir::DynTy {
69 bounds: make_binders(where_clauses, 1),
70 lifetime: LIFETIME_PLACEHOLDER.to_lifetime(&Interner),
71 };
69 chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner) 72 chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner)
70 } 73 }
71 Ty::Opaque(opaque_ty) => { 74 Ty::Opaque(opaque_ty) => {
@@ -319,6 +322,10 @@ impl ToChalk for TypeCtor {
319 // this should not be reached, since we don't represent TypeName::Error with TypeCtor 322 // this should not be reached, since we don't represent TypeName::Error with TypeCtor
320 unreachable!() 323 unreachable!()
321 } 324 }
325 TypeName::Closure(_) => {
326 // FIXME: implement closure support
327 unreachable!()
328 }
322 } 329 }
323 } 330 }
324} 331}
diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs
index b2f621a11..3b174f916 100644
--- a/crates/ra_ide/src/completion/complete_keyword.rs
+++ b/crates/ra_ide/src/completion/complete_keyword.rs
@@ -11,14 +11,14 @@ pub(super) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionC
11 let source_range = ctx.source_range(); 11 let source_range = ctx.source_range();
12 match (ctx.use_item_syntax.as_ref(), ctx.path_prefix.as_ref()) { 12 match (ctx.use_item_syntax.as_ref(), ctx.path_prefix.as_ref()) {
13 (Some(_), None) => { 13 (Some(_), None) => {
14 CompletionItem::new(CompletionKind::Keyword, source_range, "crate") 14 CompletionItem::new(CompletionKind::Keyword, source_range, "crate::")
15 .kind(CompletionItemKind::Keyword) 15 .kind(CompletionItemKind::Keyword)
16 .insert_text("crate::") 16 .insert_text("crate::")
17 .add_to(acc); 17 .add_to(acc);
18 CompletionItem::new(CompletionKind::Keyword, source_range, "self") 18 CompletionItem::new(CompletionKind::Keyword, source_range, "self")
19 .kind(CompletionItemKind::Keyword) 19 .kind(CompletionItemKind::Keyword)
20 .add_to(acc); 20 .add_to(acc);
21 CompletionItem::new(CompletionKind::Keyword, source_range, "super") 21 CompletionItem::new(CompletionKind::Keyword, source_range, "super::")
22 .kind(CompletionItemKind::Keyword) 22 .kind(CompletionItemKind::Keyword)
23 .insert_text("super::") 23 .insert_text("super::")
24 .add_to(acc); 24 .add_to(acc);
@@ -27,7 +27,7 @@ pub(super) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionC
27 CompletionItem::new(CompletionKind::Keyword, source_range, "self") 27 CompletionItem::new(CompletionKind::Keyword, source_range, "self")
28 .kind(CompletionItemKind::Keyword) 28 .kind(CompletionItemKind::Keyword)
29 .add_to(acc); 29 .add_to(acc);
30 CompletionItem::new(CompletionKind::Keyword, source_range, "super") 30 CompletionItem::new(CompletionKind::Keyword, source_range, "super::")
31 .kind(CompletionItemKind::Keyword) 31 .kind(CompletionItemKind::Keyword)
32 .insert_text("super::") 32 .insert_text("super::")
33 .add_to(acc); 33 .add_to(acc);
@@ -182,9 +182,9 @@ mod tests {
182 assert_snapshot!( 182 assert_snapshot!(
183 get_keyword_completions(r"use <|>"), 183 get_keyword_completions(r"use <|>"),
184 @r###" 184 @r###"
185 kw crate 185 kw crate::
186 kw self 186 kw self
187 kw super 187 kw super::
188 "### 188 "###
189 ); 189 );
190 190
@@ -192,7 +192,7 @@ mod tests {
192 get_keyword_completions(r"use a::<|>"), 192 get_keyword_completions(r"use a::<|>"),
193 @r###" 193 @r###"
194 kw self 194 kw self
195 kw super 195 kw super::
196 "### 196 "###
197 ); 197 );
198 198
@@ -200,7 +200,7 @@ mod tests {
200 get_keyword_completions(r"use a::{b, <|>}"), 200 get_keyword_completions(r"use a::{b, <|>}"),
201 @r###" 201 @r###"
202 kw self 202 kw self
203 kw super 203 kw super::
204 "### 204 "###
205 ); 205 );
206 } 206 }
diff --git a/crates/ra_ide/src/completion/test_utils.rs b/crates/ra_ide/src/completion/test_utils.rs
index a1b7c1193..5c01654cc 100644
--- a/crates/ra_ide/src/completion/test_utils.rs
+++ b/crates/ra_ide/src/completion/test_utils.rs
@@ -1,21 +1,18 @@
1//! Runs completion for testing purposes. 1//! Runs completion for testing purposes.
2 2
3use hir::Semantics;
4use ra_syntax::{AstNode, NodeOrToken, SyntaxElement};
5
3use crate::{ 6use crate::{
4 completion::{completion_item::CompletionKind, CompletionConfig}, 7 completion::{completion_item::CompletionKind, CompletionConfig},
5 mock_analysis::analysis_and_position, 8 mock_analysis::analysis_and_position,
6 CompletionItem, 9 CompletionItem,
7}; 10};
8use hir::Semantics;
9use ra_syntax::{AstNode, NodeOrToken, SyntaxElement};
10 11
11pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> { 12pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> {
12 do_completion_with_options(code, kind, &CompletionConfig::default()) 13 do_completion_with_options(code, kind, &CompletionConfig::default())
13} 14}
14 15
15pub(crate) fn completion_list(code: &str, kind: CompletionKind) -> String {
16 completion_list_with_options(code, kind, &CompletionConfig::default())
17}
18
19pub(crate) fn do_completion_with_options( 16pub(crate) fn do_completion_with_options(
20 code: &str, 17 code: &str,
21 kind: CompletionKind, 18 kind: CompletionKind,
@@ -29,13 +26,8 @@ pub(crate) fn do_completion_with_options(
29 kind_completions 26 kind_completions
30} 27}
31 28
32fn get_all_completion_items(code: &str, options: &CompletionConfig) -> Vec<CompletionItem> { 29pub(crate) fn completion_list(code: &str, kind: CompletionKind) -> String {
33 let (analysis, position) = if code.contains("//-") { 30 completion_list_with_options(code, kind, &CompletionConfig::default())
34 analysis_and_position(code)
35 } else {
36 analysis_and_position(code)
37 };
38 analysis.completions(options, position).unwrap().unwrap().into()
39} 31}
40 32
41pub(crate) fn completion_list_with_options( 33pub(crate) fn completion_list_with_options(
@@ -65,3 +57,8 @@ pub(crate) fn check_pattern_is_applicable(code: &str, check: fn(SyntaxElement) -
65 }) 57 })
66 .unwrap(); 58 .unwrap();
67} 59}
60
61fn get_all_completion_items(code: &str, options: &CompletionConfig) -> Vec<CompletionItem> {
62 let (analysis, position) = analysis_and_position(code);
63 analysis.completions(options, position).unwrap().unwrap().into()
64}
diff --git a/crates/ra_ssr/src/lib.rs b/crates/ra_ssr/src/lib.rs
index da26ee669..8f149e3db 100644
--- a/crates/ra_ssr/src/lib.rs
+++ b/crates/ra_ssr/src/lib.rs
@@ -12,7 +12,7 @@ mod tests;
12use crate::matching::Match; 12use crate::matching::Match;
13use hir::Semantics; 13use hir::Semantics;
14use ra_db::{FileId, FileRange}; 14use ra_db::{FileId, FileRange};
15use ra_syntax::{AstNode, SmolStr, SyntaxNode}; 15use ra_syntax::{ast, AstNode, SmolStr, SyntaxNode};
16use ra_text_edit::TextEdit; 16use ra_text_edit::TextEdit;
17use rustc_hash::FxHashMap; 17use rustc_hash::FxHashMap;
18 18
@@ -107,6 +107,22 @@ impl<'db> MatchFinder<'db> {
107 return; 107 return;
108 } 108 }
109 } 109 }
110 // If we've got a macro call, we already tried matching it pre-expansion, which is the only
111 // way to match the whole macro, now try expanding it and matching the expansion.
112 if let Some(macro_call) = ast::MacroCall::cast(code.clone()) {
113 if let Some(expanded) = self.sema.expand(&macro_call) {
114 if let Some(tt) = macro_call.token_tree() {
115 // When matching within a macro expansion, we only want to allow matches of
116 // nodes that originated entirely from within the token tree of the macro call.
117 // i.e. we don't want to match something that came from the macro itself.
118 self.find_matches(
119 &expanded,
120 &Some(self.sema.original_range(tt.syntax())),
121 matches_out,
122 );
123 }
124 }
125 }
110 for child in code.children() { 126 for child in code.children() {
111 self.find_matches(&child, restrict_range, matches_out); 127 self.find_matches(&child, restrict_range, matches_out);
112 } 128 }
diff --git a/crates/ra_ssr/src/matching.rs b/crates/ra_ssr/src/matching.rs
index bdaba9f1b..85420ed3c 100644
--- a/crates/ra_ssr/src/matching.rs
+++ b/crates/ra_ssr/src/matching.rs
@@ -343,7 +343,9 @@ impl<'db, 'sema> MatchState<'db, 'sema> {
343 } 343 }
344 344
345 /// Outside of token trees, a placeholder can only match a single AST node, whereas in a token 345 /// Outside of token trees, a placeholder can only match a single AST node, whereas in a token
346 /// tree it can match a sequence of tokens. 346 /// tree it can match a sequence of tokens. Note, that this code will only be used when the
347 /// pattern matches the macro invocation. For matches within the macro call, we'll already have
348 /// expanded the macro.
347 fn attempt_match_token_tree( 349 fn attempt_match_token_tree(
348 &mut self, 350 &mut self,
349 match_inputs: &MatchInputs, 351 match_inputs: &MatchInputs,
diff --git a/crates/ra_ssr/src/tests.rs b/crates/ra_ssr/src/tests.rs
index 3ee1e74e9..7a3141be8 100644
--- a/crates/ra_ssr/src/tests.rs
+++ b/crates/ra_ssr/src/tests.rs
@@ -209,6 +209,11 @@ fn assert_ssr_transform(rule: &str, input: &str, result: &str) {
209 assert_ssr_transforms(&[rule], input, result); 209 assert_ssr_transforms(&[rule], input, result);
210} 210}
211 211
212fn normalize_code(code: &str) -> String {
213 let (db, file_id) = single_file(code);
214 db.file_text(file_id).to_string()
215}
216
212fn assert_ssr_transforms(rules: &[&str], input: &str, result: &str) { 217fn assert_ssr_transforms(rules: &[&str], input: &str, result: &str) {
213 let (db, file_id) = single_file(input); 218 let (db, file_id) = single_file(input);
214 let mut match_finder = MatchFinder::new(&db); 219 let mut match_finder = MatchFinder::new(&db);
@@ -217,8 +222,13 @@ fn assert_ssr_transforms(rules: &[&str], input: &str, result: &str) {
217 match_finder.add_rule(rule); 222 match_finder.add_rule(rule);
218 } 223 }
219 if let Some(edits) = match_finder.edits_for_file(file_id) { 224 if let Some(edits) = match_finder.edits_for_file(file_id) {
220 let mut after = input.to_string(); 225 // Note, db.file_text is not necessarily the same as `input`, since fixture parsing alters
226 // stuff.
227 let mut after = db.file_text(file_id).to_string();
221 edits.apply(&mut after); 228 edits.apply(&mut after);
229 // Likewise, we need to make sure that whatever transformations fixture parsing applies,
230 // also get appplied to our expected result.
231 let result = normalize_code(result);
222 assert_eq!(after, result); 232 assert_eq!(after, result);
223 } else { 233 } else {
224 panic!("No edits were made"); 234 panic!("No edits were made");
@@ -355,6 +365,18 @@ fn match_nested_method_calls() {
355 ); 365 );
356} 366}
357 367
368// Make sure that our node matching semantics don't differ within macro calls.
369#[test]
370fn match_nested_method_calls_with_macro_call() {
371 assert_matches(
372 "$a.z().z().z()",
373 r#"
374 macro_rules! m1 { ($a:expr) => {$a}; }
375 fn f() {m1!(h().i().j().z().z().z().d().e())}"#,
376 &["h().i().j().z().z().z()"],
377 );
378}
379
358#[test] 380#[test]
359fn match_complex_expr() { 381fn match_complex_expr() {
360 let code = "fn f() -> i32 {foo(bar(40, 2), 42)}"; 382 let code = "fn f() -> i32 {foo(bar(40, 2), 42)}";
@@ -547,3 +569,40 @@ fn multiple_rules() {
547 "fn f() -> i32 {add_one(add(3, 2))}", 569 "fn f() -> i32 {add_one(add(3, 2))}",
548 ) 570 )
549} 571}
572
573#[test]
574fn match_within_macro_invocation() {
575 let code = r#"
576 macro_rules! foo {
577 ($a:stmt; $b:expr) => {
578 $b
579 };
580 }
581 struct A {}
582 impl A {
583 fn bar() {}
584 }
585 fn f1() {
586 let aaa = A {};
587 foo!(macro_ignores_this(); aaa.bar());
588 }
589 "#;
590 assert_matches("$a.bar()", code, &["aaa.bar()"]);
591}
592
593#[test]
594fn replace_within_macro_expansion() {
595 assert_ssr_transform(
596 "$a.foo() ==>> bar($a)",
597 r#"
598 macro_rules! macro1 {
599 ($a:expr) => {$a}
600 }
601 fn f() {macro1!(5.x().foo().o2())}"#,
602 r#"
603 macro_rules! macro1 {
604 ($a:expr) => {$a}
605 }
606 fn f() {macro1!(bar(5.x()).o2())}"#,
607 )
608}