diff options
-rw-r--r-- | Cargo.lock | 46 | ||||
-rw-r--r-- | crates/ra_assists/src/assists/add_derive.rs | 18 | ||||
-rw-r--r-- | crates/ra_assists/src/assists/add_explicit_type.rs | 16 | ||||
-rw-r--r-- | crates/ra_assists/src/assists/add_impl.rs | 19 | ||||
-rw-r--r-- | crates/ra_assists/src/assists/add_missing_impl_members.rs | 58 | ||||
-rw-r--r-- | crates/ra_assists/src/assists/apply_demorgan.rs | 26 | ||||
-rw-r--r-- | crates/ra_assists/src/doc_tests.rs | 6 | ||||
-rw-r--r-- | crates/ra_assists/src/doc_tests/generated.rs | 139 | ||||
-rw-r--r-- | crates/ra_hir/Cargo.toml | 6 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 110 | ||||
-rw-r--r-- | docs/user/assists.md | 137 | ||||
-rw-r--r-- | docs/user/features.md | 91 | ||||
-rw-r--r-- | xtask/src/codegen.rs | 13 | ||||
-rw-r--r-- | xtask/src/codegen/gen_assists_docs.rs | 10 |
15 files changed, 518 insertions, 183 deletions
diff --git a/Cargo.lock b/Cargo.lock index 382eb92e4..6f8a4431d 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -126,9 +126,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
126 | [[package]] | 126 | [[package]] |
127 | name = "chalk-engine" | 127 | name = "chalk-engine" |
128 | version = "0.9.0" | 128 | version = "0.9.0" |
129 | source = "git+https://github.com/rust-lang/chalk.git?rev=13303bb0067c6ed0572322080ae367ee38f9e7c9#13303bb0067c6ed0572322080ae367ee38f9e7c9" | 129 | source = "git+https://github.com/rust-lang/chalk.git?rev=1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae#1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae" |
130 | dependencies = [ | 130 | dependencies = [ |
131 | "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=13303bb0067c6ed0572322080ae367ee38f9e7c9)", | 131 | "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae)", |
132 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | 132 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", |
133 | "stacker 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", | 133 | "stacker 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", |
134 | ] | 134 | ] |
@@ -136,17 +136,17 @@ dependencies = [ | |||
136 | [[package]] | 136 | [[package]] |
137 | name = "chalk-ir" | 137 | name = "chalk-ir" |
138 | version = "0.1.0" | 138 | version = "0.1.0" |
139 | source = "git+https://github.com/rust-lang/chalk.git?rev=13303bb0067c6ed0572322080ae367ee38f9e7c9#13303bb0067c6ed0572322080ae367ee38f9e7c9" | 139 | source = "git+https://github.com/rust-lang/chalk.git?rev=1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae#1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae" |
140 | dependencies = [ | 140 | dependencies = [ |
141 | "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=13303bb0067c6ed0572322080ae367ee38f9e7c9)", | 141 | "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae)", |
142 | "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=13303bb0067c6ed0572322080ae367ee38f9e7c9)", | 142 | "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae)", |
143 | "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", | 143 | "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", |
144 | ] | 144 | ] |
145 | 145 | ||
146 | [[package]] | 146 | [[package]] |
147 | name = "chalk-macros" | 147 | name = "chalk-macros" |
148 | version = "0.1.1" | 148 | version = "0.1.1" |
149 | source = "git+https://github.com/rust-lang/chalk.git?rev=13303bb0067c6ed0572322080ae367ee38f9e7c9#13303bb0067c6ed0572322080ae367ee38f9e7c9" | 149 | source = "git+https://github.com/rust-lang/chalk.git?rev=1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae#1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae" |
150 | dependencies = [ | 150 | dependencies = [ |
151 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", | 151 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", |
152 | ] | 152 | ] |
@@ -154,22 +154,22 @@ dependencies = [ | |||
154 | [[package]] | 154 | [[package]] |
155 | name = "chalk-rust-ir" | 155 | name = "chalk-rust-ir" |
156 | version = "0.1.0" | 156 | version = "0.1.0" |
157 | source = "git+https://github.com/rust-lang/chalk.git?rev=13303bb0067c6ed0572322080ae367ee38f9e7c9#13303bb0067c6ed0572322080ae367ee38f9e7c9" | 157 | source = "git+https://github.com/rust-lang/chalk.git?rev=1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae#1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae" |
158 | dependencies = [ | 158 | dependencies = [ |
159 | "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=13303bb0067c6ed0572322080ae367ee38f9e7c9)", | 159 | "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae)", |
160 | "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=13303bb0067c6ed0572322080ae367ee38f9e7c9)", | 160 | "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae)", |
161 | "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=13303bb0067c6ed0572322080ae367ee38f9e7c9)", | 161 | "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae)", |
162 | ] | 162 | ] |
163 | 163 | ||
164 | [[package]] | 164 | [[package]] |
165 | name = "chalk-solve" | 165 | name = "chalk-solve" |
166 | version = "0.1.0" | 166 | version = "0.1.0" |
167 | source = "git+https://github.com/rust-lang/chalk.git?rev=13303bb0067c6ed0572322080ae367ee38f9e7c9#13303bb0067c6ed0572322080ae367ee38f9e7c9" | 167 | source = "git+https://github.com/rust-lang/chalk.git?rev=1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae#1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae" |
168 | dependencies = [ | 168 | dependencies = [ |
169 | "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=13303bb0067c6ed0572322080ae367ee38f9e7c9)", | 169 | "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae)", |
170 | "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=13303bb0067c6ed0572322080ae367ee38f9e7c9)", | 170 | "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae)", |
171 | "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=13303bb0067c6ed0572322080ae367ee38f9e7c9)", | 171 | "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae)", |
172 | "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=13303bb0067c6ed0572322080ae367ee38f9e7c9)", | 172 | "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae)", |
173 | "ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", | 173 | "ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", |
174 | "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", | 174 | "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", |
175 | "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", | 175 | "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -979,9 +979,9 @@ name = "ra_hir" | |||
979 | version = "0.1.0" | 979 | version = "0.1.0" |
980 | dependencies = [ | 980 | dependencies = [ |
981 | "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", | 981 | "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", |
982 | "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=13303bb0067c6ed0572322080ae367ee38f9e7c9)", | 982 | "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae)", |
983 | "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=13303bb0067c6ed0572322080ae367ee38f9e7c9)", | 983 | "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae)", |
984 | "chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=13303bb0067c6ed0572322080ae367ee38f9e7c9)", | 984 | "chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae)", |
985 | "ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", | 985 | "ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", |
986 | "insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", | 986 | "insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", |
987 | "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", | 987 | "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -1794,11 +1794,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
1794 | "checksum cargo_metadata 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8d2d1617e838936c0d2323a65cc151e03ae19a7678dd24f72bccf27119b90a5d" | 1794 | "checksum cargo_metadata 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8d2d1617e838936c0d2323a65cc151e03ae19a7678dd24f72bccf27119b90a5d" |
1795 | "checksum cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)" = "0213d356d3c4ea2c18c40b037c3be23cd639825c18f25ee670ac7813beeef99c" | 1795 | "checksum cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)" = "0213d356d3c4ea2c18c40b037c3be23cd639825c18f25ee670ac7813beeef99c" |
1796 | "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" | 1796 | "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" |
1797 | "checksum chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=13303bb0067c6ed0572322080ae367ee38f9e7c9)" = "<none>" | 1797 | "checksum chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae)" = "<none>" |
1798 | "checksum chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=13303bb0067c6ed0572322080ae367ee38f9e7c9)" = "<none>" | 1798 | "checksum chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae)" = "<none>" |
1799 | "checksum chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=13303bb0067c6ed0572322080ae367ee38f9e7c9)" = "<none>" | 1799 | "checksum chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae)" = "<none>" |
1800 | "checksum chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=13303bb0067c6ed0572322080ae367ee38f9e7c9)" = "<none>" | 1800 | "checksum chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae)" = "<none>" |
1801 | "checksum chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=13303bb0067c6ed0572322080ae367ee38f9e7c9)" = "<none>" | 1801 | "checksum chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae)" = "<none>" |
1802 | "checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68" | 1802 | "checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68" |
1803 | "checksum clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e" | 1803 | "checksum clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e" |
1804 | "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" | 1804 | "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" |
diff --git a/crates/ra_assists/src/assists/add_derive.rs b/crates/ra_assists/src/assists/add_derive.rs index 77ecc33c9..d3ba634c4 100644 --- a/crates/ra_assists/src/assists/add_derive.rs +++ b/crates/ra_assists/src/assists/add_derive.rs | |||
@@ -1,5 +1,3 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
3 | use hir::db::HirDatabase; | 1 | use hir::db::HirDatabase; |
4 | use ra_syntax::{ | 2 | use ra_syntax::{ |
5 | ast::{self, AstNode, AttrsOwner}, | 3 | ast::{self, AstNode, AttrsOwner}, |
@@ -9,6 +7,22 @@ use ra_syntax::{ | |||
9 | 7 | ||
10 | use crate::{Assist, AssistCtx, AssistId}; | 8 | use crate::{Assist, AssistCtx, AssistId}; |
11 | 9 | ||
10 | // Assist: add_derive | ||
11 | // Adds a new `#[derive()]` clause to a struct or enum. | ||
12 | // ``` | ||
13 | // struct Point { | ||
14 | // x: u32, | ||
15 | // y: u32,<|> | ||
16 | // } | ||
17 | // ``` | ||
18 | // -> | ||
19 | // ``` | ||
20 | // #[derive()] | ||
21 | // struct Point { | ||
22 | // x: u32, | ||
23 | // y: u32, | ||
24 | // } | ||
25 | // ``` | ||
12 | pub(crate) fn add_derive(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | 26 | pub(crate) fn add_derive(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { |
13 | let nominal = ctx.node_at_offset::<ast::NominalDef>()?; | 27 | let nominal = ctx.node_at_offset::<ast::NominalDef>()?; |
14 | let node_start = derive_insertion_offset(&nominal)?; | 28 | let node_start = derive_insertion_offset(&nominal)?; |
diff --git a/crates/ra_assists/src/assists/add_explicit_type.rs b/crates/ra_assists/src/assists/add_explicit_type.rs index 8c83dc987..33b7bea7f 100644 --- a/crates/ra_assists/src/assists/add_explicit_type.rs +++ b/crates/ra_assists/src/assists/add_explicit_type.rs | |||
@@ -1,5 +1,3 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
3 | use hir::{db::HirDatabase, HirDisplay, Ty}; | 1 | use hir::{db::HirDatabase, HirDisplay, Ty}; |
4 | use ra_syntax::{ | 2 | use ra_syntax::{ |
5 | ast::{self, AstNode, LetStmt, NameOwner}, | 3 | ast::{self, AstNode, LetStmt, NameOwner}, |
@@ -8,7 +6,19 @@ use ra_syntax::{ | |||
8 | 6 | ||
9 | use crate::{Assist, AssistCtx, AssistId}; | 7 | use crate::{Assist, AssistCtx, AssistId}; |
10 | 8 | ||
11 | /// Add explicit type assist. | 9 | // Assist: add_explicit_type |
10 | // Specify type for a let binding | ||
11 | // ``` | ||
12 | // fn main() { | ||
13 | // let x<|> = 92; | ||
14 | // } | ||
15 | // ``` | ||
16 | // -> | ||
17 | // ``` | ||
18 | // fn main() { | ||
19 | // let x: i32 = 92; | ||
20 | // } | ||
21 | // ``` | ||
12 | pub(crate) fn add_explicit_type(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | 22 | pub(crate) fn add_explicit_type(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { |
13 | let stmt = ctx.node_at_offset::<LetStmt>()?; | 23 | let stmt = ctx.node_at_offset::<LetStmt>()?; |
14 | let expr = stmt.initializer()?; | 24 | let expr = stmt.initializer()?; |
diff --git a/crates/ra_assists/src/assists/add_impl.rs b/crates/ra_assists/src/assists/add_impl.rs index 94801fbc9..40bc5c464 100644 --- a/crates/ra_assists/src/assists/add_impl.rs +++ b/crates/ra_assists/src/assists/add_impl.rs | |||
@@ -1,5 +1,3 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
3 | use format_buf::format; | 1 | use format_buf::format; |
4 | use hir::db::HirDatabase; | 2 | use hir::db::HirDatabase; |
5 | use join_to_string::join; | 3 | use join_to_string::join; |
@@ -10,6 +8,23 @@ use ra_syntax::{ | |||
10 | 8 | ||
11 | use crate::{Assist, AssistCtx, AssistId}; | 9 | use crate::{Assist, AssistCtx, AssistId}; |
12 | 10 | ||
11 | // Assist: add_impl | ||
12 | // Adds a new inherent impl for a type | ||
13 | // ``` | ||
14 | // struct Ctx<T: Clone> { | ||
15 | // data: T,<|> | ||
16 | // } | ||
17 | // ``` | ||
18 | // -> | ||
19 | // ``` | ||
20 | // struct Ctx<T: Clone> { | ||
21 | // data: T, | ||
22 | // } | ||
23 | // | ||
24 | // impl<T: Clone> Ctx<T> { | ||
25 | // | ||
26 | // } | ||
27 | // ``` | ||
13 | pub(crate) fn add_impl(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | 28 | pub(crate) fn add_impl(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { |
14 | let nominal = ctx.node_at_offset::<ast::NominalDef>()?; | 29 | let nominal = ctx.node_at_offset::<ast::NominalDef>()?; |
15 | let name = nominal.name()?; | 30 | let name = nominal.name()?; |
diff --git a/crates/ra_assists/src/assists/add_missing_impl_members.rs b/crates/ra_assists/src/assists/add_missing_impl_members.rs index 565b96fb5..36fa6f9ea 100644 --- a/crates/ra_assists/src/assists/add_missing_impl_members.rs +++ b/crates/ra_assists/src/assists/add_missing_impl_members.rs | |||
@@ -1,5 +1,3 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
3 | use hir::{db::HirDatabase, HasSource}; | 1 | use hir::{db::HirDatabase, HasSource}; |
4 | use ra_syntax::{ | 2 | use ra_syntax::{ |
5 | ast::{self, edit, make, AstNode, NameOwner}, | 3 | ast::{self, edit, make, AstNode, NameOwner}, |
@@ -14,6 +12,32 @@ enum AddMissingImplMembersMode { | |||
14 | NoDefaultMethods, | 12 | NoDefaultMethods, |
15 | } | 13 | } |
16 | 14 | ||
15 | // Assist: add_impl_missing_members | ||
16 | // Adds scaffold for required impl members | ||
17 | // ``` | ||
18 | // trait T { | ||
19 | // Type X; | ||
20 | // fn foo(&self); | ||
21 | // fn bar(&self) {} | ||
22 | // } | ||
23 | // | ||
24 | // impl T for () {<|> | ||
25 | // | ||
26 | // } | ||
27 | // ``` | ||
28 | // -> | ||
29 | // ``` | ||
30 | // trait T { | ||
31 | // Type X; | ||
32 | // fn foo(&self); | ||
33 | // fn bar(&self) {} | ||
34 | // } | ||
35 | // | ||
36 | // impl T for () { | ||
37 | // fn foo(&self) { unimplemented!() } | ||
38 | // | ||
39 | // } | ||
40 | // ``` | ||
17 | pub(crate) fn add_missing_impl_members(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | 41 | pub(crate) fn add_missing_impl_members(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { |
18 | add_missing_impl_members_inner( | 42 | add_missing_impl_members_inner( |
19 | ctx, | 43 | ctx, |
@@ -23,6 +47,36 @@ pub(crate) fn add_missing_impl_members(ctx: AssistCtx<impl HirDatabase>) -> Opti | |||
23 | ) | 47 | ) |
24 | } | 48 | } |
25 | 49 | ||
50 | // Assist: add_impl_default_members | ||
51 | // Adds scaffold for overriding default impl members | ||
52 | // ``` | ||
53 | // trait T { | ||
54 | // Type X; | ||
55 | // fn foo(&self); | ||
56 | // fn bar(&self) {} | ||
57 | // } | ||
58 | // | ||
59 | // impl T for () { | ||
60 | // Type X = (); | ||
61 | // fn foo(&self) {}<|> | ||
62 | // | ||
63 | // } | ||
64 | // ``` | ||
65 | // -> | ||
66 | // ``` | ||
67 | // trait T { | ||
68 | // Type X; | ||
69 | // fn foo(&self); | ||
70 | // fn bar(&self) {} | ||
71 | // } | ||
72 | // | ||
73 | // impl T for () { | ||
74 | // Type X = (); | ||
75 | // fn foo(&self) {} | ||
76 | // fn bar(&self) {} | ||
77 | // | ||
78 | // } | ||
79 | // ``` | ||
26 | pub(crate) fn add_missing_default_members(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | 80 | pub(crate) fn add_missing_default_members(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { |
27 | add_missing_impl_members_inner( | 81 | add_missing_impl_members_inner( |
28 | ctx, | 82 | ctx, |
diff --git a/crates/ra_assists/src/assists/apply_demorgan.rs b/crates/ra_assists/src/assists/apply_demorgan.rs index 5f2b0dd18..a072f63e7 100644 --- a/crates/ra_assists/src/assists/apply_demorgan.rs +++ b/crates/ra_assists/src/assists/apply_demorgan.rs | |||
@@ -1,18 +1,26 @@ | |||
1 | //! This contains the functions associated with the demorgan assist. | ||
2 | //! This assist transforms boolean expressions of the form `!a || !b` into | ||
3 | //! `!(a && b)`. | ||
4 | use hir::db::HirDatabase; | 1 | use hir::db::HirDatabase; |
5 | use ra_syntax::ast::{self, AstNode}; | 2 | use ra_syntax::ast::{self, AstNode}; |
6 | use ra_syntax::SyntaxNode; | 3 | use ra_syntax::SyntaxNode; |
7 | 4 | ||
8 | use crate::{Assist, AssistCtx, AssistId}; | 5 | use crate::{Assist, AssistCtx, AssistId}; |
9 | 6 | ||
10 | /// Assist for applying demorgan's law | 7 | // Assist: apply_demorgan |
11 | /// | 8 | // Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws). |
12 | /// This transforms expressions of the form `!l || !r` into `!(l && r)`. | 9 | // This transforms expressions of the form `!l || !r` into `!(l && r)`. |
13 | /// This also works with `&&`. This assist can only be applied with the cursor | 10 | // This also works with `&&`. This assist can only be applied with the cursor |
14 | /// on either `||` or `&&`, with both operands being a negation of some kind. | 11 | // on either `||` or `&&`, with both operands being a negation of some kind. |
15 | /// This means something of the form `!x` or `x != y`. | 12 | // This means something of the form `!x` or `x != y`. |
13 | // ``` | ||
14 | // fn main() { | ||
15 | // if x != 4 ||<|> !y {} | ||
16 | // } | ||
17 | // ``` | ||
18 | // -> | ||
19 | // ``` | ||
20 | // fn main() { | ||
21 | // if !(x == 4 && y) {} | ||
22 | // } | ||
23 | // ``` | ||
16 | pub(crate) fn apply_demorgan(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | 24 | pub(crate) fn apply_demorgan(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { |
17 | let expr = ctx.node_at_offset::<ast::BinExpr>()?; | 25 | let expr = ctx.node_at_offset::<ast::BinExpr>()?; |
18 | let op = expr.op_kind()?; | 26 | let op = expr.op_kind()?; |
diff --git a/crates/ra_assists/src/doc_tests.rs b/crates/ra_assists/src/doc_tests.rs index 88e901517..872bbdf17 100644 --- a/crates/ra_assists/src/doc_tests.rs +++ b/crates/ra_assists/src/doc_tests.rs | |||
@@ -15,8 +15,10 @@ fn check(assist_id: &str, before: &str, after: &str) { | |||
15 | let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); | 15 | let (db, _source_root, file_id) = MockDatabase::with_single_file(&before); |
16 | let frange = FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; | 16 | let frange = FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) }; |
17 | 17 | ||
18 | let (_assist_id, action) = | 18 | let (_assist_id, action) = crate::assists(&db, frange) |
19 | crate::assists(&db, frange).into_iter().find(|(id, _)| id.id.0 == assist_id).unwrap(); | 19 | .into_iter() |
20 | .find(|(id, _)| id.id.0 == assist_id) | ||
21 | .unwrap_or_else(|| panic!("Assist {:?} is not applicable", assist_id)); | ||
20 | 22 | ||
21 | let actual = action.edit.apply(&before); | 23 | let actual = action.edit.apply(&before); |
22 | assert_eq_text!(after, &actual); | 24 | assert_eq_text!(after, &actual); |
diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs index e5f6910f1..76d86b93d 100644 --- a/crates/ra_assists/src/doc_tests/generated.rs +++ b/crates/ra_assists/src/doc_tests/generated.rs | |||
@@ -3,6 +3,145 @@ | |||
3 | use super::check; | 3 | use super::check; |
4 | 4 | ||
5 | #[test] | 5 | #[test] |
6 | fn doctest_add_derive() { | ||
7 | check( | ||
8 | "add_derive", | ||
9 | r#####" | ||
10 | struct Point { | ||
11 | x: u32, | ||
12 | y: u32,<|> | ||
13 | } | ||
14 | "#####, | ||
15 | r#####" | ||
16 | #[derive()] | ||
17 | struct Point { | ||
18 | x: u32, | ||
19 | y: u32, | ||
20 | } | ||
21 | "#####, | ||
22 | ) | ||
23 | } | ||
24 | |||
25 | #[test] | ||
26 | fn doctest_add_explicit_type() { | ||
27 | check( | ||
28 | "add_explicit_type", | ||
29 | r#####" | ||
30 | fn main() { | ||
31 | let x<|> = 92; | ||
32 | } | ||
33 | "#####, | ||
34 | r#####" | ||
35 | fn main() { | ||
36 | let x: i32 = 92; | ||
37 | } | ||
38 | "#####, | ||
39 | ) | ||
40 | } | ||
41 | |||
42 | #[test] | ||
43 | fn doctest_add_impl() { | ||
44 | check( | ||
45 | "add_impl", | ||
46 | r#####" | ||
47 | struct Ctx<T: Clone> { | ||
48 | data: T,<|> | ||
49 | } | ||
50 | "#####, | ||
51 | r#####" | ||
52 | struct Ctx<T: Clone> { | ||
53 | data: T, | ||
54 | } | ||
55 | |||
56 | impl<T: Clone> Ctx<T> { | ||
57 | |||
58 | } | ||
59 | "#####, | ||
60 | ) | ||
61 | } | ||
62 | |||
63 | #[test] | ||
64 | fn doctest_add_impl_default_members() { | ||
65 | check( | ||
66 | "add_impl_default_members", | ||
67 | r#####" | ||
68 | trait T { | ||
69 | Type X; | ||
70 | fn foo(&self); | ||
71 | fn bar(&self) {} | ||
72 | } | ||
73 | |||
74 | impl T for () { | ||
75 | Type X = (); | ||
76 | fn foo(&self) {}<|> | ||
77 | |||
78 | } | ||
79 | "#####, | ||
80 | r#####" | ||
81 | trait T { | ||
82 | Type X; | ||
83 | fn foo(&self); | ||
84 | fn bar(&self) {} | ||
85 | } | ||
86 | |||
87 | impl T for () { | ||
88 | Type X = (); | ||
89 | fn foo(&self) {} | ||
90 | fn bar(&self) {} | ||
91 | |||
92 | } | ||
93 | "#####, | ||
94 | ) | ||
95 | } | ||
96 | |||
97 | #[test] | ||
98 | fn doctest_add_impl_missing_members() { | ||
99 | check( | ||
100 | "add_impl_missing_members", | ||
101 | r#####" | ||
102 | trait T { | ||
103 | Type X; | ||
104 | fn foo(&self); | ||
105 | fn bar(&self) {} | ||
106 | } | ||
107 | |||
108 | impl T for () {<|> | ||
109 | |||
110 | } | ||
111 | "#####, | ||
112 | r#####" | ||
113 | trait T { | ||
114 | Type X; | ||
115 | fn foo(&self); | ||
116 | fn bar(&self) {} | ||
117 | } | ||
118 | |||
119 | impl T for () { | ||
120 | fn foo(&self) { unimplemented!() } | ||
121 | |||
122 | } | ||
123 | "#####, | ||
124 | ) | ||
125 | } | ||
126 | |||
127 | #[test] | ||
128 | fn doctest_apply_demorgan() { | ||
129 | check( | ||
130 | "apply_demorgan", | ||
131 | r#####" | ||
132 | fn main() { | ||
133 | if x != 4 ||<|> !y {} | ||
134 | } | ||
135 | "#####, | ||
136 | r#####" | ||
137 | fn main() { | ||
138 | if !(x == 4 && y) {} | ||
139 | } | ||
140 | "#####, | ||
141 | ) | ||
142 | } | ||
143 | |||
144 | #[test] | ||
6 | fn doctest_convert_to_guarded_return() { | 145 | fn doctest_convert_to_guarded_return() { |
7 | check( | 146 | check( |
8 | "convert_to_guarded_return", | 147 | "convert_to_guarded_return", |
diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml index dce897d30..f05ec0b8a 100644 --- a/crates/ra_hir/Cargo.toml +++ b/crates/ra_hir/Cargo.toml | |||
@@ -22,9 +22,9 @@ tt = { path = "../ra_tt", package = "ra_tt" } | |||
22 | test_utils = { path = "../test_utils" } | 22 | test_utils = { path = "../test_utils" } |
23 | ra_prof = { path = "../ra_prof" } | 23 | ra_prof = { path = "../ra_prof" } |
24 | 24 | ||
25 | chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "13303bb0067c6ed0572322080ae367ee38f9e7c9" } | 25 | chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae" } |
26 | chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "13303bb0067c6ed0572322080ae367ee38f9e7c9" } | 26 | chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae" } |
27 | chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "13303bb0067c6ed0572322080ae367ee38f9e7c9" } | 27 | chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "1e5c1929364dfbb7c0c7ac0956b8250abe7c2cae" } |
28 | lalrpop-intern = "0.15.1" | 28 | lalrpop-intern = "0.15.1" |
29 | 29 | ||
30 | [dev-dependencies] | 30 | [dev-dependencies] |
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs index 0cb5c3798..4f1eab150 100644 --- a/crates/ra_hir/src/ty/traits.rs +++ b/crates/ra_hir/src/ty/traits.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! Trait solving using Chalk. | 1 | //! Trait solving using Chalk. |
2 | use std::sync::{Arc, Mutex}; | 2 | use std::sync::{Arc, Mutex}; |
3 | 3 | ||
4 | use chalk_ir::cast::Cast; | 4 | use chalk_ir::{cast::Cast, family::ChalkIr}; |
5 | use log::debug; | 5 | use log::debug; |
6 | use ra_db::salsa; | 6 | use ra_db::salsa; |
7 | use ra_prof::profile; | 7 | use ra_prof::profile; |
@@ -33,7 +33,7 @@ impl TraitSolver { | |||
33 | fn solve( | 33 | fn solve( |
34 | &self, | 34 | &self, |
35 | db: &impl HirDatabase, | 35 | db: &impl HirDatabase, |
36 | goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal>>, | 36 | goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal<ChalkIr>>>, |
37 | ) -> Option<chalk_solve::Solution> { | 37 | ) -> Option<chalk_solve::Solution> { |
38 | let context = ChalkContext { db, krate: self.krate }; | 38 | let context = ChalkContext { db, krate: self.krate }; |
39 | debug!("solve goal: {:?}", goal); | 39 | debug!("solve goal: {:?}", goal); |
@@ -196,7 +196,7 @@ pub(crate) fn trait_solve_query( | |||
196 | } | 196 | } |
197 | 197 | ||
198 | fn solution_from_chalk(db: &impl HirDatabase, solution: chalk_solve::Solution) -> Solution { | 198 | fn solution_from_chalk(db: &impl HirDatabase, solution: chalk_solve::Solution) -> Solution { |
199 | let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution>| { | 199 | let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<ChalkIr>>| { |
200 | let value = subst | 200 | let value = subst |
201 | .value | 201 | .value |
202 | .parameters | 202 | .parameters |
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 00aaf65d9..ad7c11a5a 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs | |||
@@ -4,8 +4,8 @@ use std::sync::Arc; | |||
4 | use log::debug; | 4 | use log::debug; |
5 | 5 | ||
6 | use chalk_ir::{ | 6 | use chalk_ir::{ |
7 | cast::Cast, Identifier, ImplId, Parameter, PlaceholderIndex, TypeId, TypeKindId, TypeName, | 7 | cast::Cast, family::ChalkIr, Identifier, ImplId, Parameter, PlaceholderIndex, TypeId, |
8 | UniverseIndex, | 8 | TypeKindId, TypeName, UniverseIndex, |
9 | }; | 9 | }; |
10 | use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum}; | 10 | use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum}; |
11 | 11 | ||
@@ -38,8 +38,8 @@ where | |||
38 | } | 38 | } |
39 | 39 | ||
40 | impl ToChalk for Ty { | 40 | impl ToChalk for Ty { |
41 | type Chalk = chalk_ir::Ty; | 41 | type Chalk = chalk_ir::Ty<ChalkIr>; |
42 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty { | 42 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty<ChalkIr> { |
43 | match self { | 43 | match self { |
44 | Ty::Apply(apply_ty) => { | 44 | Ty::Apply(apply_ty) => { |
45 | let name = match apply_ty.ctor { | 45 | let name = match apply_ty.ctor { |
@@ -62,21 +62,21 @@ impl ToChalk for Ty { | |||
62 | chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast() | 62 | chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast() |
63 | } | 63 | } |
64 | Ty::Param { idx, .. } => { | 64 | Ty::Param { idx, .. } => { |
65 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty() | 65 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty::<ChalkIr>() |
66 | } | 66 | } |
67 | Ty::Bound(idx) => chalk_ir::Ty::BoundVar(idx as usize), | 67 | Ty::Bound(idx) => chalk_ir::Ty::BoundVar(idx as usize), |
68 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), | 68 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), |
69 | // FIXME this is clearly incorrect, but probably not too incorrect | 69 | // FIXME this is clearly incorrect, but probably not too incorrect |
70 | // and I'm not sure what to actually do with Ty::Unknown | 70 | // and I'm not sure what to actually do with Ty::Unknown |
71 | // maybe an alternative would be `for<T> T`? (meaningless in rust, but expressible in chalk's Ty) | 71 | // maybe an alternative would be `for<T> T`? (meaningless in rust, but expressible in chalk's Ty) |
72 | // | 72 | // FIXME use Chalk's Dyn/Opaque once the bugs with that are fixed |
73 | // FIXME also dyn and impl Trait are currently handled like Unknown because Chalk doesn't have them yet | ||
74 | Ty::Unknown | Ty::Dyn(_) | Ty::Opaque(_) => { | 73 | Ty::Unknown | Ty::Dyn(_) | Ty::Opaque(_) => { |
75 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::max_value() }.to_ty() | 74 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::max_value() } |
75 | .to_ty::<ChalkIr>() | ||
76 | } | 76 | } |
77 | } | 77 | } |
78 | } | 78 | } |
79 | fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty) -> Self { | 79 | fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty<ChalkIr>) -> Self { |
80 | match chalk { | 80 | match chalk { |
81 | chalk_ir::Ty::Apply(apply_ty) => { | 81 | chalk_ir::Ty::Apply(apply_ty) => { |
82 | // FIXME this is kind of hacky due to the fact that | 82 | // FIXME this is kind of hacky due to the fact that |
@@ -108,18 +108,30 @@ impl ToChalk for Ty { | |||
108 | chalk_ir::Ty::ForAll(_) => unimplemented!(), | 108 | chalk_ir::Ty::ForAll(_) => unimplemented!(), |
109 | chalk_ir::Ty::BoundVar(idx) => Ty::Bound(idx as u32), | 109 | chalk_ir::Ty::BoundVar(idx) => Ty::Bound(idx as u32), |
110 | chalk_ir::Ty::InferenceVar(_iv) => Ty::Unknown, | 110 | chalk_ir::Ty::InferenceVar(_iv) => Ty::Unknown, |
111 | chalk_ir::Ty::Dyn(where_clauses) => { | ||
112 | assert_eq!(where_clauses.binders.len(), 1); | ||
113 | let predicates = | ||
114 | where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); | ||
115 | Ty::Dyn(predicates) | ||
116 | } | ||
117 | chalk_ir::Ty::Opaque(where_clauses) => { | ||
118 | assert_eq!(where_clauses.binders.len(), 1); | ||
119 | let predicates = | ||
120 | where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); | ||
121 | Ty::Opaque(predicates) | ||
122 | } | ||
111 | } | 123 | } |
112 | } | 124 | } |
113 | } | 125 | } |
114 | 126 | ||
115 | impl ToChalk for Substs { | 127 | impl ToChalk for Substs { |
116 | type Chalk = Vec<chalk_ir::Parameter>; | 128 | type Chalk = Vec<chalk_ir::Parameter<ChalkIr>>; |
117 | 129 | ||
118 | fn to_chalk(self, db: &impl HirDatabase) -> Vec<Parameter> { | 130 | fn to_chalk(self, db: &impl HirDatabase) -> Vec<Parameter<ChalkIr>> { |
119 | self.iter().map(|ty| ty.clone().to_chalk(db).cast()).collect() | 131 | self.iter().map(|ty| ty.clone().to_chalk(db).cast()).collect() |
120 | } | 132 | } |
121 | 133 | ||
122 | fn from_chalk(db: &impl HirDatabase, parameters: Vec<chalk_ir::Parameter>) -> Substs { | 134 | fn from_chalk(db: &impl HirDatabase, parameters: Vec<chalk_ir::Parameter<ChalkIr>>) -> Substs { |
123 | let tys = parameters | 135 | let tys = parameters |
124 | .into_iter() | 136 | .into_iter() |
125 | .map(|p| match p { | 137 | .map(|p| match p { |
@@ -132,15 +144,15 @@ impl ToChalk for Substs { | |||
132 | } | 144 | } |
133 | 145 | ||
134 | impl ToChalk for TraitRef { | 146 | impl ToChalk for TraitRef { |
135 | type Chalk = chalk_ir::TraitRef; | 147 | type Chalk = chalk_ir::TraitRef<ChalkIr>; |
136 | 148 | ||
137 | fn to_chalk(self: TraitRef, db: &impl HirDatabase) -> chalk_ir::TraitRef { | 149 | fn to_chalk(self: TraitRef, db: &impl HirDatabase) -> chalk_ir::TraitRef<ChalkIr> { |
138 | let trait_id = self.trait_.to_chalk(db); | 150 | let trait_id = self.trait_.to_chalk(db); |
139 | let parameters = self.substs.to_chalk(db); | 151 | let parameters = self.substs.to_chalk(db); |
140 | chalk_ir::TraitRef { trait_id, parameters } | 152 | chalk_ir::TraitRef { trait_id, parameters } |
141 | } | 153 | } |
142 | 154 | ||
143 | fn from_chalk(db: &impl HirDatabase, trait_ref: chalk_ir::TraitRef) -> Self { | 155 | fn from_chalk(db: &impl HirDatabase, trait_ref: chalk_ir::TraitRef<ChalkIr>) -> Self { |
144 | let trait_ = from_chalk(db, trait_ref.trait_id); | 156 | let trait_ = from_chalk(db, trait_ref.trait_id); |
145 | let substs = from_chalk(db, trait_ref.parameters); | 157 | let substs = from_chalk(db, trait_ref.parameters); |
146 | TraitRef { trait_, substs } | 158 | TraitRef { trait_, substs } |
@@ -196,9 +208,9 @@ impl ToChalk for TypeAlias { | |||
196 | } | 208 | } |
197 | 209 | ||
198 | impl ToChalk for GenericPredicate { | 210 | impl ToChalk for GenericPredicate { |
199 | type Chalk = chalk_ir::QuantifiedWhereClause; | 211 | type Chalk = chalk_ir::QuantifiedWhereClause<ChalkIr>; |
200 | 212 | ||
201 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::QuantifiedWhereClause { | 213 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::QuantifiedWhereClause<ChalkIr> { |
202 | match self { | 214 | match self { |
203 | GenericPredicate::Implemented(trait_ref) => { | 215 | GenericPredicate::Implemented(trait_ref) => { |
204 | make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0) | 216 | make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0) |
@@ -221,25 +233,40 @@ impl ToChalk for GenericPredicate { | |||
221 | } | 233 | } |
222 | 234 | ||
223 | fn from_chalk( | 235 | fn from_chalk( |
224 | _db: &impl HirDatabase, | 236 | db: &impl HirDatabase, |
225 | _where_clause: chalk_ir::QuantifiedWhereClause, | 237 | where_clause: chalk_ir::QuantifiedWhereClause<ChalkIr>, |
226 | ) -> GenericPredicate { | 238 | ) -> GenericPredicate { |
227 | // This should never need to be called | 239 | match where_clause.value { |
228 | unimplemented!() | 240 | chalk_ir::WhereClause::Implemented(tr) => { |
241 | if tr.trait_id == UNKNOWN_TRAIT { | ||
242 | // FIXME we need an Error enum on the Chalk side to avoid this | ||
243 | return GenericPredicate::Error; | ||
244 | } | ||
245 | GenericPredicate::Implemented(from_chalk(db, tr)) | ||
246 | } | ||
247 | chalk_ir::WhereClause::ProjectionEq(projection_eq) => { | ||
248 | let projection_ty = from_chalk(db, projection_eq.projection); | ||
249 | let ty = from_chalk(db, projection_eq.ty); | ||
250 | GenericPredicate::Projection(super::ProjectionPredicate { projection_ty, ty }) | ||
251 | } | ||
252 | } | ||
229 | } | 253 | } |
230 | } | 254 | } |
231 | 255 | ||
232 | impl ToChalk for ProjectionTy { | 256 | impl ToChalk for ProjectionTy { |
233 | type Chalk = chalk_ir::ProjectionTy; | 257 | type Chalk = chalk_ir::ProjectionTy<ChalkIr>; |
234 | 258 | ||
235 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ProjectionTy { | 259 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ProjectionTy<ChalkIr> { |
236 | chalk_ir::ProjectionTy { | 260 | chalk_ir::ProjectionTy { |
237 | associated_ty_id: self.associated_ty.to_chalk(db), | 261 | associated_ty_id: self.associated_ty.to_chalk(db), |
238 | parameters: self.parameters.to_chalk(db), | 262 | parameters: self.parameters.to_chalk(db), |
239 | } | 263 | } |
240 | } | 264 | } |
241 | 265 | ||
242 | fn from_chalk(db: &impl HirDatabase, projection_ty: chalk_ir::ProjectionTy) -> ProjectionTy { | 266 | fn from_chalk( |
267 | db: &impl HirDatabase, | ||
268 | projection_ty: chalk_ir::ProjectionTy<ChalkIr>, | ||
269 | ) -> ProjectionTy { | ||
243 | ProjectionTy { | 270 | ProjectionTy { |
244 | associated_ty: from_chalk(db, projection_ty.associated_ty_id), | 271 | associated_ty: from_chalk(db, projection_ty.associated_ty_id), |
245 | parameters: from_chalk(db, projection_ty.parameters), | 272 | parameters: from_chalk(db, projection_ty.parameters), |
@@ -248,31 +275,31 @@ impl ToChalk for ProjectionTy { | |||
248 | } | 275 | } |
249 | 276 | ||
250 | impl ToChalk for super::ProjectionPredicate { | 277 | impl ToChalk for super::ProjectionPredicate { |
251 | type Chalk = chalk_ir::Normalize; | 278 | type Chalk = chalk_ir::Normalize<ChalkIr>; |
252 | 279 | ||
253 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Normalize { | 280 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Normalize<ChalkIr> { |
254 | chalk_ir::Normalize { | 281 | chalk_ir::Normalize { |
255 | projection: self.projection_ty.to_chalk(db), | 282 | projection: self.projection_ty.to_chalk(db), |
256 | ty: self.ty.to_chalk(db), | 283 | ty: self.ty.to_chalk(db), |
257 | } | 284 | } |
258 | } | 285 | } |
259 | 286 | ||
260 | fn from_chalk(_db: &impl HirDatabase, _normalize: chalk_ir::Normalize) -> Self { | 287 | fn from_chalk(_db: &impl HirDatabase, _normalize: chalk_ir::Normalize<ChalkIr>) -> Self { |
261 | unimplemented!() | 288 | unimplemented!() |
262 | } | 289 | } |
263 | } | 290 | } |
264 | 291 | ||
265 | impl ToChalk for Obligation { | 292 | impl ToChalk for Obligation { |
266 | type Chalk = chalk_ir::DomainGoal; | 293 | type Chalk = chalk_ir::DomainGoal<ChalkIr>; |
267 | 294 | ||
268 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::DomainGoal { | 295 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::DomainGoal<ChalkIr> { |
269 | match self { | 296 | match self { |
270 | Obligation::Trait(tr) => tr.to_chalk(db).cast(), | 297 | Obligation::Trait(tr) => tr.to_chalk(db).cast(), |
271 | Obligation::Projection(pr) => pr.to_chalk(db).cast(), | 298 | Obligation::Projection(pr) => pr.to_chalk(db).cast(), |
272 | } | 299 | } |
273 | } | 300 | } |
274 | 301 | ||
275 | fn from_chalk(_db: &impl HirDatabase, _goal: chalk_ir::DomainGoal) -> Self { | 302 | fn from_chalk(_db: &impl HirDatabase, _goal: chalk_ir::DomainGoal<ChalkIr>) -> Self { |
276 | unimplemented!() | 303 | unimplemented!() |
277 | } | 304 | } |
278 | } | 305 | } |
@@ -296,16 +323,16 @@ where | |||
296 | } | 323 | } |
297 | 324 | ||
298 | impl ToChalk for Arc<super::TraitEnvironment> { | 325 | impl ToChalk for Arc<super::TraitEnvironment> { |
299 | type Chalk = Arc<chalk_ir::Environment>; | 326 | type Chalk = Arc<chalk_ir::Environment<ChalkIr>>; |
300 | 327 | ||
301 | fn to_chalk(self, db: &impl HirDatabase) -> Arc<chalk_ir::Environment> { | 328 | fn to_chalk(self, db: &impl HirDatabase) -> Arc<chalk_ir::Environment<ChalkIr>> { |
302 | let mut clauses = Vec::new(); | 329 | let mut clauses = Vec::new(); |
303 | for pred in &self.predicates { | 330 | for pred in &self.predicates { |
304 | if pred.is_error() { | 331 | if pred.is_error() { |
305 | // for env, we just ignore errors | 332 | // for env, we just ignore errors |
306 | continue; | 333 | continue; |
307 | } | 334 | } |
308 | let program_clause: chalk_ir::ProgramClause = pred.clone().to_chalk(db).cast(); | 335 | let program_clause: chalk_ir::ProgramClause<ChalkIr> = pred.clone().to_chalk(db).cast(); |
309 | clauses.push(program_clause.into_from_env_clause()); | 336 | clauses.push(program_clause.into_from_env_clause()); |
310 | } | 337 | } |
311 | chalk_ir::Environment::new().add_clauses(clauses) | 338 | chalk_ir::Environment::new().add_clauses(clauses) |
@@ -313,13 +340,16 @@ impl ToChalk for Arc<super::TraitEnvironment> { | |||
313 | 340 | ||
314 | fn from_chalk( | 341 | fn from_chalk( |
315 | _db: &impl HirDatabase, | 342 | _db: &impl HirDatabase, |
316 | _env: Arc<chalk_ir::Environment>, | 343 | _env: Arc<chalk_ir::Environment<ChalkIr>>, |
317 | ) -> Arc<super::TraitEnvironment> { | 344 | ) -> Arc<super::TraitEnvironment> { |
318 | unimplemented!() | 345 | unimplemented!() |
319 | } | 346 | } |
320 | } | 347 | } |
321 | 348 | ||
322 | impl<T: ToChalk> ToChalk for super::InEnvironment<T> { | 349 | impl<T: ToChalk> ToChalk for super::InEnvironment<T> |
350 | where | ||
351 | T::Chalk: chalk_ir::family::HasTypeFamily<TypeFamily = ChalkIr>, | ||
352 | { | ||
323 | type Chalk = chalk_ir::InEnvironment<T::Chalk>; | 353 | type Chalk = chalk_ir::InEnvironment<T::Chalk>; |
324 | 354 | ||
325 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> { | 355 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> { |
@@ -351,7 +381,7 @@ fn convert_where_clauses( | |||
351 | db: &impl HirDatabase, | 381 | db: &impl HirDatabase, |
352 | def: GenericDef, | 382 | def: GenericDef, |
353 | substs: &Substs, | 383 | substs: &Substs, |
354 | ) -> Vec<chalk_ir::QuantifiedWhereClause> { | 384 | ) -> Vec<chalk_ir::QuantifiedWhereClause<ChalkIr>> { |
355 | let generic_predicates = db.generic_predicates(def); | 385 | let generic_predicates = db.generic_predicates(def); |
356 | let mut result = Vec::with_capacity(generic_predicates.len()); | 386 | let mut result = Vec::with_capacity(generic_predicates.len()); |
357 | for pred in generic_predicates.iter() { | 387 | for pred in generic_predicates.iter() { |
@@ -384,7 +414,7 @@ where | |||
384 | fn impls_for_trait( | 414 | fn impls_for_trait( |
385 | &self, | 415 | &self, |
386 | trait_id: chalk_ir::TraitId, | 416 | trait_id: chalk_ir::TraitId, |
387 | parameters: &[Parameter], | 417 | parameters: &[Parameter<ChalkIr>], |
388 | ) -> Vec<ImplId> { | 418 | ) -> Vec<ImplId> { |
389 | debug!("impls_for_trait {:?}", trait_id); | 419 | debug!("impls_for_trait {:?}", trait_id); |
390 | if trait_id == UNKNOWN_TRAIT { | 420 | if trait_id == UNKNOWN_TRAIT { |
@@ -430,13 +460,13 @@ where | |||
430 | } | 460 | } |
431 | fn split_projection<'p>( | 461 | fn split_projection<'p>( |
432 | &self, | 462 | &self, |
433 | projection: &'p chalk_ir::ProjectionTy, | 463 | projection: &'p chalk_ir::ProjectionTy<ChalkIr>, |
434 | ) -> (Arc<AssociatedTyDatum>, &'p [Parameter], &'p [Parameter]) { | 464 | ) -> (Arc<AssociatedTyDatum>, &'p [Parameter<ChalkIr>], &'p [Parameter<ChalkIr>]) { |
435 | debug!("split_projection {:?}", projection); | 465 | debug!("split_projection {:?}", projection); |
436 | // we don't support GATs, so I think this should always be correct currently | 466 | // we don't support GATs, so I think this should always be correct currently |
437 | (self.db.associated_ty_data(projection.associated_ty_id), &projection.parameters, &[]) | 467 | (self.db.associated_ty_data(projection.associated_ty_id), &projection.parameters, &[]) |
438 | } | 468 | } |
439 | fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause> { | 469 | fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<ChalkIr>> { |
440 | vec![] | 470 | vec![] |
441 | } | 471 | } |
442 | fn local_impls_to_coherence_check( | 472 | fn local_impls_to_coherence_check( |
diff --git a/docs/user/assists.md b/docs/user/assists.md index cb4b0b9fb..eeb486832 100644 --- a/docs/user/assists.md +++ b/docs/user/assists.md | |||
@@ -1,5 +1,142 @@ | |||
1 | # Assists | 1 | # Assists |
2 | 2 | ||
3 | ## `add_derive` | ||
4 | |||
5 | Adds a new `#[derive()]` clause to a struct or enum. | ||
6 | |||
7 | ```rust | ||
8 | // BEFORE | ||
9 | struct Point { | ||
10 | x: u32, | ||
11 | y: u32,<|> | ||
12 | } | ||
13 | |||
14 | // AFTER | ||
15 | #[derive()] | ||
16 | struct Point { | ||
17 | x: u32, | ||
18 | y: u32, | ||
19 | } | ||
20 | ``` | ||
21 | |||
22 | ## `add_explicit_type` | ||
23 | |||
24 | Specify type for a let binding | ||
25 | |||
26 | ```rust | ||
27 | // BEFORE | ||
28 | fn main() { | ||
29 | let x<|> = 92; | ||
30 | } | ||
31 | |||
32 | // AFTER | ||
33 | fn main() { | ||
34 | let x: i32 = 92; | ||
35 | } | ||
36 | ``` | ||
37 | |||
38 | ## `add_impl` | ||
39 | |||
40 | Adds a new inherent impl for a type | ||
41 | |||
42 | ```rust | ||
43 | // BEFORE | ||
44 | struct Ctx<T: Clone> { | ||
45 | data: T,<|> | ||
46 | } | ||
47 | |||
48 | // AFTER | ||
49 | struct Ctx<T: Clone> { | ||
50 | data: T, | ||
51 | } | ||
52 | |||
53 | impl<T: Clone> Ctx<T> { | ||
54 | |||
55 | } | ||
56 | ``` | ||
57 | |||
58 | ## `add_impl_default_members` | ||
59 | |||
60 | Adds scaffold for overriding default impl members | ||
61 | |||
62 | ```rust | ||
63 | // BEFORE | ||
64 | trait T { | ||
65 | Type X; | ||
66 | fn foo(&self); | ||
67 | fn bar(&self) {} | ||
68 | } | ||
69 | |||
70 | impl T for () { | ||
71 | Type X = (); | ||
72 | fn foo(&self) {}<|> | ||
73 | |||
74 | } | ||
75 | |||
76 | // AFTER | ||
77 | trait T { | ||
78 | Type X; | ||
79 | fn foo(&self); | ||
80 | fn bar(&self) {} | ||
81 | } | ||
82 | |||
83 | impl T for () { | ||
84 | Type X = (); | ||
85 | fn foo(&self) {} | ||
86 | fn bar(&self) {} | ||
87 | |||
88 | } | ||
89 | ``` | ||
90 | |||
91 | ## `add_impl_missing_members` | ||
92 | |||
93 | Adds scaffold for required impl members | ||
94 | |||
95 | ```rust | ||
96 | // BEFORE | ||
97 | trait T { | ||
98 | Type X; | ||
99 | fn foo(&self); | ||
100 | fn bar(&self) {} | ||
101 | } | ||
102 | |||
103 | impl T for () {<|> | ||
104 | |||
105 | } | ||
106 | |||
107 | // AFTER | ||
108 | trait T { | ||
109 | Type X; | ||
110 | fn foo(&self); | ||
111 | fn bar(&self) {} | ||
112 | } | ||
113 | |||
114 | impl T for () { | ||
115 | fn foo(&self) { unimplemented!() } | ||
116 | |||
117 | } | ||
118 | ``` | ||
119 | |||
120 | ## `apply_demorgan` | ||
121 | |||
122 | Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws). | ||
123 | This transforms expressions of the form `!l || !r` into `!(l && r)`. | ||
124 | This also works with `&&`. This assist can only be applied with the cursor | ||
125 | on either `||` or `&&`, with both operands being a negation of some kind. | ||
126 | This means something of the form `!x` or `x != y`. | ||
127 | |||
128 | ```rust | ||
129 | // BEFORE | ||
130 | fn main() { | ||
131 | if x != 4 ||<|> !y {} | ||
132 | } | ||
133 | |||
134 | // AFTER | ||
135 | fn main() { | ||
136 | if !(x == 4 && y) {} | ||
137 | } | ||
138 | ``` | ||
139 | |||
3 | ## `convert_to_guarded_return` | 140 | ## `convert_to_guarded_return` |
4 | 141 | ||
5 | Replace a large conditional with a guarded return. | 142 | Replace a large conditional with a guarded return. |
diff --git a/docs/user/features.md b/docs/user/features.md index a94b65ad4..acf092cec 100644 --- a/docs/user/features.md +++ b/docs/user/features.md | |||
@@ -104,84 +104,6 @@ the VS Code side to be able to position cursor. `<|>` signifies cursor | |||
104 | 104 | ||
105 | See [assists.md](./assists.md) | 105 | See [assists.md](./assists.md) |
106 | 106 | ||
107 | - Add `#[derive]` | ||
108 | |||
109 | ```rust | ||
110 | // before: | ||
111 | struct Foo { | ||
112 | <|>x: i32 | ||
113 | } | ||
114 | // after: | ||
115 | #[derive(<|>)] | ||
116 | struct Foo { | ||
117 | x: i32 | ||
118 | } | ||
119 | ``` | ||
120 | |||
121 | - Add `impl` | ||
122 | |||
123 | ```rust | ||
124 | // before: | ||
125 | struct Foo<'a, T: Debug> { | ||
126 | <|>t: T | ||
127 | } | ||
128 | // after: | ||
129 | struct Foo<'a, T: Debug> { | ||
130 | t: T | ||
131 | } | ||
132 | |||
133 | impl<'a, T: Debug> Foo<'a, T> { | ||
134 | <|> | ||
135 | } | ||
136 | ``` | ||
137 | |||
138 | - Add missing `impl` members | ||
139 | |||
140 | ```rust | ||
141 | // before: | ||
142 | trait Foo { | ||
143 | fn foo(&self); | ||
144 | fn bar(&self); | ||
145 | fn baz(&self); | ||
146 | } | ||
147 | |||
148 | struct S; | ||
149 | |||
150 | impl Foo for S { | ||
151 | fn bar(&self) {} | ||
152 | <|> | ||
153 | } | ||
154 | |||
155 | // after: | ||
156 | trait Foo { | ||
157 | fn foo(&self); | ||
158 | fn bar(&self); | ||
159 | fn baz(&self); | ||
160 | } | ||
161 | |||
162 | struct S; | ||
163 | |||
164 | impl Foo for S { | ||
165 | fn bar(&self) {} | ||
166 | fn foo(&self) { unimplemented!() } | ||
167 | fn baz(&self) { unimplemented!() }<|> | ||
168 | } | ||
169 | ``` | ||
170 | |||
171 | - Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws) | ||
172 | |||
173 | ```rust | ||
174 | // before: | ||
175 | fn example(x: bool) -> bool { | ||
176 | !x || !x | ||
177 | } | ||
178 | |||
179 | // after: | ||
180 | fn example(x: bool) -> bool { | ||
181 | !(x && x) | ||
182 | } | ||
183 | ``` | ||
184 | |||
185 | - Import path | 107 | - Import path |
186 | 108 | ||
187 | ```rust | 109 | ```rust |
@@ -391,19 +313,6 @@ fn foo() { | |||
391 | } | 313 | } |
392 | ``` | 314 | ``` |
393 | 315 | ||
394 | - Add explicit type | ||
395 | |||
396 | ```rust | ||
397 | // before: | ||
398 | fn foo() { | ||
399 | let t<|> = (&2, Some(1)); | ||
400 | } | ||
401 | // after: | ||
402 | fn foo() { | ||
403 | let t<|>: (&i32, Option<i32>) = (&2, Some(1)); | ||
404 | } | ||
405 | ``` | ||
406 | |||
407 | - Move guard expression to match arm body | 316 | - Move guard expression to match arm body |
408 | ```rust | 317 | ```rust |
409 | // before: | 318 | // before: |
diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs index 44729cd57..4ec8ab75a 100644 --- a/xtask/src/codegen.rs +++ b/xtask/src/codegen.rs | |||
@@ -74,6 +74,14 @@ fn reformat(text: impl std::fmt::Display) -> Result<String> { | |||
74 | } | 74 | } |
75 | 75 | ||
76 | fn extract_comment_blocks(text: &str) -> Vec<Vec<String>> { | 76 | fn extract_comment_blocks(text: &str) -> Vec<Vec<String>> { |
77 | do_extract_comment_blocks(text, false) | ||
78 | } | ||
79 | |||
80 | fn extract_comment_blocks_with_empty_lines(text: &str) -> Vec<Vec<String>> { | ||
81 | do_extract_comment_blocks(text, true) | ||
82 | } | ||
83 | |||
84 | fn do_extract_comment_blocks(text: &str, allow_blocks_with_empty_lins: bool) -> Vec<Vec<String>> { | ||
77 | let mut res = Vec::new(); | 85 | let mut res = Vec::new(); |
78 | 86 | ||
79 | let prefix = "// "; | 87 | let prefix = "// "; |
@@ -81,6 +89,11 @@ fn extract_comment_blocks(text: &str) -> Vec<Vec<String>> { | |||
81 | 89 | ||
82 | let mut block = vec![]; | 90 | let mut block = vec![]; |
83 | for line in lines { | 91 | for line in lines { |
92 | if line == "//" && allow_blocks_with_empty_lins { | ||
93 | block.push(String::new()); | ||
94 | continue; | ||
95 | } | ||
96 | |||
84 | let is_comment = line.starts_with(prefix); | 97 | let is_comment = line.starts_with(prefix); |
85 | if is_comment { | 98 | if is_comment { |
86 | block.push(line[prefix.len()..].to_string()); | 99 | block.push(line[prefix.len()..].to_string()); |
diff --git a/xtask/src/codegen/gen_assists_docs.rs b/xtask/src/codegen/gen_assists_docs.rs index 654ae09d6..e313820d1 100644 --- a/xtask/src/codegen/gen_assists_docs.rs +++ b/xtask/src/codegen/gen_assists_docs.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use std::{fs, path::Path}; | 1 | use std::{fs, path::Path}; |
2 | 2 | ||
3 | use crate::{ | 3 | use crate::{ |
4 | codegen::{self, extract_comment_blocks, Mode}, | 4 | codegen::{self, extract_comment_blocks_with_empty_lines, Mode}, |
5 | project_root, Result, | 5 | project_root, Result, |
6 | }; | 6 | }; |
7 | 7 | ||
@@ -34,7 +34,7 @@ fn collect_assists() -> Result<Vec<Assist>> { | |||
34 | 34 | ||
35 | fn collect_file(acc: &mut Vec<Assist>, path: &Path) -> Result<()> { | 35 | fn collect_file(acc: &mut Vec<Assist>, path: &Path) -> Result<()> { |
36 | let text = fs::read_to_string(path)?; | 36 | let text = fs::read_to_string(path)?; |
37 | let comment_blocks = extract_comment_blocks(&text); | 37 | let comment_blocks = extract_comment_blocks_with_empty_lines(&text); |
38 | 38 | ||
39 | for block in comment_blocks { | 39 | for block in comment_blocks { |
40 | // FIXME: doesn't support blank lines yet, need to tweak | 40 | // FIXME: doesn't support blank lines yet, need to tweak |
@@ -45,7 +45,11 @@ fn collect_assists() -> Result<Vec<Assist>> { | |||
45 | continue; | 45 | continue; |
46 | } | 46 | } |
47 | let id = first_line["Assist: ".len()..].to_string(); | 47 | let id = first_line["Assist: ".len()..].to_string(); |
48 | assert!(id.chars().all(|it| it.is_ascii_lowercase() || it == '_')); | 48 | assert!( |
49 | id.chars().all(|it| it.is_ascii_lowercase() || it == '_'), | ||
50 | "invalid assist id: {:?}", | ||
51 | id | ||
52 | ); | ||
49 | 53 | ||
50 | let doc = take_until(lines.by_ref(), "```"); | 54 | let doc = take_until(lines.by_ref(), "```"); |
51 | let before = take_until(lines.by_ref(), "```"); | 55 | let before = take_until(lines.by_ref(), "```"); |