diff options
42 files changed, 968 insertions, 204 deletions
diff --git a/Cargo.lock b/Cargo.lock index f5b1a4747..72ec68624 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -162,9 +162,9 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" | |||
162 | 162 | ||
163 | [[package]] | 163 | [[package]] |
164 | name = "chalk-derive" | 164 | name = "chalk-derive" |
165 | version = "0.25.0" | 165 | version = "0.27.0" |
166 | source = "registry+https://github.com/rust-lang/crates.io-index" | 166 | source = "registry+https://github.com/rust-lang/crates.io-index" |
167 | checksum = "624e14d3f029186e6ffd97081ffa082f98ddd5df20655b6f0e8efb83dd8ac8b4" | 167 | checksum = "d5444ff2a211fe2a863e44d16a368c3d8a314d489de21b8eeb6879f14dd5d4a8" |
168 | dependencies = [ | 168 | dependencies = [ |
169 | "proc-macro2", | 169 | "proc-macro2", |
170 | "quote", | 170 | "quote", |
@@ -174,9 +174,9 @@ dependencies = [ | |||
174 | 174 | ||
175 | [[package]] | 175 | [[package]] |
176 | name = "chalk-ir" | 176 | name = "chalk-ir" |
177 | version = "0.25.0" | 177 | version = "0.27.0" |
178 | source = "registry+https://github.com/rust-lang/crates.io-index" | 178 | source = "registry+https://github.com/rust-lang/crates.io-index" |
179 | checksum = "118c68eccdda5604af50bbef84c94550f3854f76989cb03c36ffd36cc2ffe958" | 179 | checksum = "e39c3db1dd4abfaa7658faaa62e5fe998a982a592b710bd971fad5b6adfcfdef" |
180 | dependencies = [ | 180 | dependencies = [ |
181 | "chalk-derive", | 181 | "chalk-derive", |
182 | "lazy_static", | 182 | "lazy_static", |
@@ -184,9 +184,9 @@ dependencies = [ | |||
184 | 184 | ||
185 | [[package]] | 185 | [[package]] |
186 | name = "chalk-recursive" | 186 | name = "chalk-recursive" |
187 | version = "0.25.0" | 187 | version = "0.27.0" |
188 | source = "registry+https://github.com/rust-lang/crates.io-index" | 188 | source = "registry+https://github.com/rust-lang/crates.io-index" |
189 | checksum = "5130de3065e3cdfd2ab6d7d70b02b917bafbc096f270c9a643c23da249053606" | 189 | checksum = "3bfae328eff80ca54dcd0d731725bbb56136ac21c59261b68f1e5498e056b306" |
190 | dependencies = [ | 190 | dependencies = [ |
191 | "chalk-derive", | 191 | "chalk-derive", |
192 | "chalk-ir", | 192 | "chalk-ir", |
@@ -197,9 +197,9 @@ dependencies = [ | |||
197 | 197 | ||
198 | [[package]] | 198 | [[package]] |
199 | name = "chalk-solve" | 199 | name = "chalk-solve" |
200 | version = "0.25.0" | 200 | version = "0.27.0" |
201 | source = "registry+https://github.com/rust-lang/crates.io-index" | 201 | source = "registry+https://github.com/rust-lang/crates.io-index" |
202 | checksum = "45b235a1f568b28707f117b2d30eabbee9cbcfccaa0d6e9697300400c8ca0996" | 202 | checksum = "a673abe3077adc25f8ee0894198aed494a5bb0ce50ee993900d0ee1a44e1948a" |
203 | dependencies = [ | 203 | dependencies = [ |
204 | "chalk-derive", | 204 | "chalk-derive", |
205 | "chalk-ir", | 205 | "chalk-ir", |
@@ -857,11 +857,12 @@ dependencies = [ | |||
857 | 857 | ||
858 | [[package]] | 858 | [[package]] |
859 | name = "miniz_oxide" | 859 | name = "miniz_oxide" |
860 | version = "0.4.1" | 860 | version = "0.4.2" |
861 | source = "registry+https://github.com/rust-lang/crates.io-index" | 861 | source = "registry+https://github.com/rust-lang/crates.io-index" |
862 | checksum = "4d7559a8a40d0f97e1edea3220f698f78b1c5ab67532e49f68fde3910323b722" | 862 | checksum = "c60c0dfe32c10b43a144bad8fc83538c52f58302c92300ea7ec7bf7b38d5a7b9" |
863 | dependencies = [ | 863 | dependencies = [ |
864 | "adler", | 864 | "adler", |
865 | "autocfg", | ||
865 | ] | 866 | ] |
866 | 867 | ||
867 | [[package]] | 868 | [[package]] |
@@ -1659,9 +1660,9 @@ dependencies = [ | |||
1659 | 1660 | ||
1660 | [[package]] | 1661 | [[package]] |
1661 | name = "tracing-serde" | 1662 | name = "tracing-serde" |
1662 | version = "0.1.1" | 1663 | version = "0.1.2" |
1663 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1664 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1664 | checksum = "b6ccba2f8f16e0ed268fc765d9b7ff22e965e7185d32f8f1ec8294fe17d86e79" | 1665 | checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b" |
1665 | dependencies = [ | 1666 | dependencies = [ |
1666 | "serde", | 1667 | "serde", |
1667 | "tracing-core", | 1668 | "tracing-core", |
@@ -1669,9 +1670,9 @@ dependencies = [ | |||
1669 | 1670 | ||
1670 | [[package]] | 1671 | [[package]] |
1671 | name = "tracing-subscriber" | 1672 | name = "tracing-subscriber" |
1672 | version = "0.2.11" | 1673 | version = "0.2.12" |
1673 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1674 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1674 | checksum = "abd165311cc4d7a555ad11cc77a37756df836182db0d81aac908c8184c584f40" | 1675 | checksum = "82bb5079aa76438620837198db8a5c529fb9878c730bc2b28179b0241cf04c10" |
1675 | dependencies = [ | 1676 | dependencies = [ |
1676 | "ansi_term", | 1677 | "ansi_term", |
1677 | "chrono", | 1678 | "chrono", |
diff --git a/crates/assists/src/assist_config.rs b/crates/assists/src/assist_config.rs index cda2abfb9..adf02edab 100644 --- a/crates/assists/src/assist_config.rs +++ b/crates/assists/src/assist_config.rs | |||
@@ -4,12 +4,13 @@ | |||
4 | //! module, and we use to statically check that we only produce snippet | 4 | //! module, and we use to statically check that we only produce snippet |
5 | //! assists if we are allowed to. | 5 | //! assists if we are allowed to. |
6 | 6 | ||
7 | use crate::AssistKind; | 7 | use crate::{utils::MergeBehaviour, AssistKind}; |
8 | 8 | ||
9 | #[derive(Clone, Debug, PartialEq, Eq)] | 9 | #[derive(Clone, Debug, PartialEq, Eq)] |
10 | pub struct AssistConfig { | 10 | pub struct AssistConfig { |
11 | pub snippet_cap: Option<SnippetCap>, | 11 | pub snippet_cap: Option<SnippetCap>, |
12 | pub allowed: Option<Vec<AssistKind>>, | 12 | pub allowed: Option<Vec<AssistKind>>, |
13 | pub insert_use: InsertUseConfig, | ||
13 | } | 14 | } |
14 | 15 | ||
15 | impl AssistConfig { | 16 | impl AssistConfig { |
@@ -25,6 +26,21 @@ pub struct SnippetCap { | |||
25 | 26 | ||
26 | impl Default for AssistConfig { | 27 | impl Default for AssistConfig { |
27 | fn default() -> Self { | 28 | fn default() -> Self { |
28 | AssistConfig { snippet_cap: Some(SnippetCap { _private: () }), allowed: None } | 29 | AssistConfig { |
30 | snippet_cap: Some(SnippetCap { _private: () }), | ||
31 | allowed: None, | ||
32 | insert_use: InsertUseConfig::default(), | ||
33 | } | ||
34 | } | ||
35 | } | ||
36 | |||
37 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] | ||
38 | pub struct InsertUseConfig { | ||
39 | pub merge: Option<MergeBehaviour>, | ||
40 | } | ||
41 | |||
42 | impl Default for InsertUseConfig { | ||
43 | fn default() -> Self { | ||
44 | InsertUseConfig { merge: Some(MergeBehaviour::Full) } | ||
29 | } | 45 | } |
30 | } | 46 | } |
diff --git a/crates/assists/src/handlers/auto_import.rs b/crates/assists/src/handlers/auto_import.rs index 66e819154..b5eb2c722 100644 --- a/crates/assists/src/handlers/auto_import.rs +++ b/crates/assists/src/handlers/auto_import.rs | |||
@@ -14,10 +14,7 @@ use syntax::{ | |||
14 | SyntaxNode, | 14 | SyntaxNode, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | use crate::{ | 17 | use crate::{utils::insert_use, AssistContext, AssistId, AssistKind, Assists, GroupLabel}; |
18 | utils::{insert_use, MergeBehaviour}, | ||
19 | AssistContext, AssistId, AssistKind, Assists, GroupLabel, | ||
20 | }; | ||
21 | 18 | ||
22 | // Assist: auto_import | 19 | // Assist: auto_import |
23 | // | 20 | // |
@@ -60,7 +57,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> | |||
60 | let new_syntax = insert_use( | 57 | let new_syntax = insert_use( |
61 | &scope, | 58 | &scope, |
62 | make::path_from_text(&import.to_string()), | 59 | make::path_from_text(&import.to_string()), |
63 | Some(MergeBehaviour::Full), | 60 | ctx.config.insert_use.merge, |
64 | ); | 61 | ); |
65 | builder.replace(syntax.text_range(), new_syntax.to_string()) | 62 | builder.replace(syntax.text_range(), new_syntax.to_string()) |
66 | }, | 63 | }, |
diff --git a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs index 80c62d8bb..3ea50f375 100644 --- a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs +++ b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs | |||
@@ -10,9 +10,7 @@ use syntax::{ | |||
10 | }; | 10 | }; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | assist_context::AssistBuilder, | 13 | assist_context::AssistBuilder, utils::insert_use, AssistContext, AssistId, AssistKind, Assists, |
14 | utils::{insert_use, MergeBehaviour}, | ||
15 | AssistContext, AssistId, AssistKind, Assists, | ||
16 | }; | 14 | }; |
17 | use ast::make; | 15 | use ast::make; |
18 | use insert_use::ImportScope; | 16 | use insert_use::ImportScope; |
@@ -117,7 +115,7 @@ fn insert_import( | |||
117 | let new_syntax = insert_use( | 115 | let new_syntax = insert_use( |
118 | &scope, | 116 | &scope, |
119 | make::path_from_text(&mod_path.to_string()), | 117 | make::path_from_text(&mod_path.to_string()), |
120 | Some(MergeBehaviour::Full), | 118 | ctx.config.insert_use.merge, |
121 | ); | 119 | ); |
122 | // FIXME: this will currently panic as multiple imports will have overlapping text ranges | 120 | // FIXME: this will currently panic as multiple imports will have overlapping text ranges |
123 | builder.replace(syntax.text_range(), new_syntax.to_string()) | 121 | builder.replace(syntax.text_range(), new_syntax.to_string()) |
diff --git a/crates/assists/src/handlers/replace_qualified_name_with_use.rs b/crates/assists/src/handlers/replace_qualified_name_with_use.rs index 093c3b101..8ac907707 100644 --- a/crates/assists/src/handlers/replace_qualified_name_with_use.rs +++ b/crates/assists/src/handlers/replace_qualified_name_with_use.rs | |||
@@ -2,7 +2,7 @@ use syntax::{algo::SyntaxRewriter, ast, match_ast, AstNode, SyntaxNode, TextRang | |||
2 | use test_utils::mark; | 2 | use test_utils::mark; |
3 | 3 | ||
4 | use crate::{ | 4 | use crate::{ |
5 | utils::{insert_use, ImportScope, MergeBehaviour}, | 5 | utils::{insert_use, ImportScope}, |
6 | AssistContext, AssistId, AssistKind, Assists, | 6 | AssistContext, AssistId, AssistKind, Assists, |
7 | }; | 7 | }; |
8 | use ast::make; | 8 | use ast::make; |
@@ -60,7 +60,7 @@ pub(crate) fn replace_qualified_name_with_use( | |||
60 | let new_syntax = insert_use( | 60 | let new_syntax = insert_use( |
61 | import_scope, | 61 | import_scope, |
62 | make::path_from_text(path_to_import), | 62 | make::path_from_text(path_to_import), |
63 | Some(MergeBehaviour::Full), | 63 | ctx.config.insert_use.merge, |
64 | ); | 64 | ); |
65 | builder.replace(syntax.text_range(), new_syntax.to_string()) | 65 | builder.replace(syntax.text_range(), new_syntax.to_string()) |
66 | } | 66 | } |
diff --git a/crates/assists/src/utils.rs b/crates/assists/src/utils.rs index 7559ddd63..b0511ceb6 100644 --- a/crates/assists/src/utils.rs +++ b/crates/assists/src/utils.rs | |||
@@ -16,7 +16,8 @@ use syntax::{ | |||
16 | 16 | ||
17 | use crate::assist_config::SnippetCap; | 17 | use crate::assist_config::SnippetCap; |
18 | 18 | ||
19 | pub(crate) use insert_use::{insert_use, ImportScope, MergeBehaviour}; | 19 | pub use insert_use::MergeBehaviour; |
20 | pub(crate) use insert_use::{insert_use, ImportScope}; | ||
20 | 21 | ||
21 | pub(crate) fn unwrap_trivial_block(block: ast::BlockExpr) -> ast::Expr { | 22 | pub(crate) fn unwrap_trivial_block(block: ast::BlockExpr) -> ast::Expr { |
22 | extract_trivial_expression(&block) | 23 | extract_trivial_expression(&block) |
diff --git a/crates/assists/src/utils/insert_use.rs b/crates/assists/src/utils/insert_use.rs index 97ac6b832..09f4a2224 100644 --- a/crates/assists/src/utils/insert_use.rs +++ b/crates/assists/src/utils/insert_use.rs | |||
@@ -344,7 +344,7 @@ fn path_cmp_opt(a: Option<ast::Path>, b: Option<ast::Path>) -> Ordering { | |||
344 | } | 344 | } |
345 | 345 | ||
346 | /// What type of merges are allowed. | 346 | /// What type of merges are allowed. |
347 | #[derive(Copy, Clone, PartialEq, Eq)] | 347 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
348 | pub enum MergeBehaviour { | 348 | pub enum MergeBehaviour { |
349 | /// Merge everything together creating deeply nested imports. | 349 | /// Merge everything together creating deeply nested imports. |
350 | Full, | 350 | Full, |
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index c2fc819e7..7a9747fc7 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs | |||
@@ -1283,6 +1283,8 @@ impl Type { | |||
1283 | /// Checks that particular type `ty` implements `std::future::Future`. | 1283 | /// Checks that particular type `ty` implements `std::future::Future`. |
1284 | /// This function is used in `.await` syntax completion. | 1284 | /// This function is used in `.await` syntax completion. |
1285 | pub fn impls_future(&self, db: &dyn HirDatabase) -> bool { | 1285 | pub fn impls_future(&self, db: &dyn HirDatabase) -> bool { |
1286 | // No special case for the type of async block, since Chalk can figure it out. | ||
1287 | |||
1286 | let krate = self.krate; | 1288 | let krate = self.krate; |
1287 | 1289 | ||
1288 | let std_future_trait = | 1290 | let std_future_trait = |
@@ -1600,6 +1602,11 @@ impl Type { | |||
1600 | cb(type_.derived(ty.clone())); | 1602 | cb(type_.derived(ty.clone())); |
1601 | } | 1603 | } |
1602 | } | 1604 | } |
1605 | TypeCtor::OpaqueType(..) => { | ||
1606 | if let Some(bounds) = ty.impl_trait_bounds(db) { | ||
1607 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); | ||
1608 | } | ||
1609 | } | ||
1603 | _ => (), | 1610 | _ => (), |
1604 | } | 1611 | } |
1605 | 1612 | ||
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 30ac12a12..2d91bb21f 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -239,7 +239,10 @@ impl ExprCollector<'_> { | |||
239 | None => self.missing_expr(), | 239 | None => self.missing_expr(), |
240 | }, | 240 | }, |
241 | // FIXME: we need to record these effects somewhere... | 241 | // FIXME: we need to record these effects somewhere... |
242 | ast::Effect::Async(_) => self.collect_block_opt(e.block_expr()), | 242 | ast::Effect::Async(_) => { |
243 | let body = self.collect_block_opt(e.block_expr()); | ||
244 | self.alloc_expr(Expr::Async { body }, syntax_ptr) | ||
245 | } | ||
243 | }, | 246 | }, |
244 | ast::Expr::BlockExpr(e) => self.collect_block(e), | 247 | ast::Expr::BlockExpr(e) => self.collect_block(e), |
245 | ast::Expr::LoopExpr(e) => { | 248 | ast::Expr::LoopExpr(e) => { |
@@ -835,8 +838,12 @@ impl ExprCollector<'_> { | |||
835 | 838 | ||
836 | Pat::Missing | 839 | Pat::Missing |
837 | } | 840 | } |
841 | ast::Pat::BoxPat(boxpat) => { | ||
842 | let inner = self.collect_pat_opt(boxpat.pat()); | ||
843 | Pat::Box { inner } | ||
844 | } | ||
838 | // FIXME: implement | 845 | // FIXME: implement |
839 | ast::Pat::BoxPat(_) | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing, | 846 | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing, |
840 | }; | 847 | }; |
841 | let ptr = AstPtr::new(&pat); | 848 | let ptr = AstPtr::new(&pat); |
842 | self.alloc_pat(pattern, Either::Left(ptr)) | 849 | self.alloc_pat(pattern, Either::Left(ptr)) |
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index 9a8eb4ede..6190906da 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs | |||
@@ -54,6 +54,7 @@ pub struct TypeAliasData { | |||
54 | pub name: Name, | 54 | pub name: Name, |
55 | pub type_ref: Option<TypeRef>, | 55 | pub type_ref: Option<TypeRef>, |
56 | pub visibility: RawVisibility, | 56 | pub visibility: RawVisibility, |
57 | pub is_extern: bool, | ||
57 | /// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl). | 58 | /// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl). |
58 | pub bounds: Vec<TypeBound>, | 59 | pub bounds: Vec<TypeBound>, |
59 | } | 60 | } |
@@ -71,6 +72,7 @@ impl TypeAliasData { | |||
71 | name: typ.name.clone(), | 72 | name: typ.name.clone(), |
72 | type_ref: typ.type_ref.clone(), | 73 | type_ref: typ.type_ref.clone(), |
73 | visibility: item_tree[typ.visibility].clone(), | 74 | visibility: item_tree[typ.visibility].clone(), |
75 | is_extern: typ.is_extern, | ||
74 | bounds: typ.bounds.to_vec(), | 76 | bounds: typ.bounds.to_vec(), |
75 | }) | 77 | }) |
76 | } | 78 | } |
diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs index c94b3a36f..e5d740a36 100644 --- a/crates/hir_def/src/expr.rs +++ b/crates/hir_def/src/expr.rs | |||
@@ -111,6 +111,9 @@ pub enum Expr { | |||
111 | TryBlock { | 111 | TryBlock { |
112 | body: ExprId, | 112 | body: ExprId, |
113 | }, | 113 | }, |
114 | Async { | ||
115 | body: ExprId, | ||
116 | }, | ||
114 | Cast { | 117 | Cast { |
115 | expr: ExprId, | 118 | expr: ExprId, |
116 | type_ref: TypeRef, | 119 | type_ref: TypeRef, |
@@ -250,7 +253,7 @@ impl Expr { | |||
250 | f(*expr); | 253 | f(*expr); |
251 | } | 254 | } |
252 | } | 255 | } |
253 | Expr::TryBlock { body } | Expr::Unsafe { body } => f(*body), | 256 | Expr::TryBlock { body } | Expr::Unsafe { body } | Expr::Async { body } => f(*body), |
254 | Expr::Loop { body, .. } => f(*body), | 257 | Expr::Loop { body, .. } => f(*body), |
255 | Expr::While { condition, body, .. } => { | 258 | Expr::While { condition, body, .. } => { |
256 | f(*condition); | 259 | f(*condition); |
@@ -395,6 +398,7 @@ pub enum Pat { | |||
395 | Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> }, | 398 | Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> }, |
396 | TupleStruct { path: Option<Path>, args: Vec<PatId>, ellipsis: Option<usize> }, | 399 | TupleStruct { path: Option<Path>, args: Vec<PatId>, ellipsis: Option<usize> }, |
397 | Ref { pat: PatId, mutability: Mutability }, | 400 | Ref { pat: PatId, mutability: Mutability }, |
401 | Box { inner: PatId }, | ||
398 | } | 402 | } |
399 | 403 | ||
400 | impl Pat { | 404 | impl Pat { |
@@ -415,6 +419,7 @@ impl Pat { | |||
415 | Pat::Record { args, .. } => { | 419 | Pat::Record { args, .. } => { |
416 | args.iter().map(|f| f.pat).for_each(f); | 420 | args.iter().map(|f| f.pat).for_each(f); |
417 | } | 421 | } |
422 | Pat::Box { inner } => f(*inner), | ||
418 | } | 423 | } |
419 | } | 424 | } |
420 | } | 425 | } |
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index e14722cae..52abb8e7f 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -592,6 +592,7 @@ pub struct TypeAlias { | |||
592 | pub bounds: Box<[TypeBound]>, | 592 | pub bounds: Box<[TypeBound]>, |
593 | pub generic_params: GenericParamsId, | 593 | pub generic_params: GenericParamsId, |
594 | pub type_ref: Option<TypeRef>, | 594 | pub type_ref: Option<TypeRef>, |
595 | pub is_extern: bool, | ||
595 | pub ast_id: FileAstId<ast::TypeAlias>, | 596 | pub ast_id: FileAstId<ast::TypeAlias>, |
596 | } | 597 | } |
597 | 598 | ||
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 6a503d785..d93377c3b 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -364,6 +364,7 @@ impl Ctx { | |||
364 | generic_params, | 364 | generic_params, |
365 | type_ref, | 365 | type_ref, |
366 | ast_id, | 366 | ast_id, |
367 | is_extern: false, | ||
367 | }; | 368 | }; |
368 | Some(id(self.data().type_aliases.alloc(res))) | 369 | Some(id(self.data().type_aliases.alloc(res))) |
369 | } | 370 | } |
@@ -558,8 +559,9 @@ impl Ctx { | |||
558 | statik.into() | 559 | statik.into() |
559 | } | 560 | } |
560 | ast::ExternItem::TypeAlias(ty) => { | 561 | ast::ExternItem::TypeAlias(ty) => { |
561 | let id = self.lower_type_alias(&ty)?; | 562 | let foreign_ty = self.lower_type_alias(&ty)?; |
562 | id.into() | 563 | self.data().type_aliases[foreign_ty.index].is_extern = true; |
564 | foreign_ty.into() | ||
563 | } | 565 | } |
564 | ast::ExternItem::MacroCall(_) => return None, | 566 | ast::ExternItem::MacroCall(_) => return None, |
565 | }; | 567 | }; |
diff --git a/crates/hir_def/src/item_tree/tests.rs b/crates/hir_def/src/item_tree/tests.rs index 620e697d4..eed3d0d6f 100644 --- a/crates/hir_def/src/item_tree/tests.rs +++ b/crates/hir_def/src/item_tree/tests.rs | |||
@@ -236,7 +236,7 @@ fn smoke() { | |||
236 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("on_trait"))] }, input: None }]) }] | 236 | #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("on_trait"))] }, input: None }]) }] |
237 | Trait { name: Name(Text("Tr")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(0), auto: false, items: [TypeAlias(Idx::<TypeAlias>(0)), Const(Idx::<Const>(0)), Function(Idx::<Function>(0)), Function(Idx::<Function>(1))], ast_id: FileAstId::<syntax::ast::generated::nodes::Trait>(2) } | 237 | Trait { name: Name(Text("Tr")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(0), auto: false, items: [TypeAlias(Idx::<TypeAlias>(0)), Const(Idx::<Const>(0)), Function(Idx::<Function>(0)), Function(Idx::<Function>(1))], ast_id: FileAstId::<syntax::ast::generated::nodes::Trait>(2) } |
238 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_ty"))] }, input: None }]) }] | 238 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_ty"))] }, input: None }]) }] |
239 | > TypeAlias { name: Name(Text("AssocTy")), visibility: RawVisibilityId("pub(self)"), bounds: [Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Tr"))] }, generic_args: [Some(GenericArgs { args: [Type(Tuple([]))], has_self_type: false, bindings: [] })] })], generic_params: GenericParamsId(4294967295), type_ref: None, ast_id: FileAstId::<syntax::ast::generated::nodes::TypeAlias>(8) } | 239 | > TypeAlias { name: Name(Text("AssocTy")), visibility: RawVisibilityId("pub(self)"), bounds: [Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Tr"))] }, generic_args: [Some(GenericArgs { args: [Type(Tuple([]))], has_self_type: false, bindings: [] })] })], generic_params: GenericParamsId(4294967295), type_ref: None, is_extern: false, ast_id: FileAstId::<syntax::ast::generated::nodes::TypeAlias>(8) } |
240 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_const"))] }, input: None }]) }] | 240 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_const"))] }, input: None }]) }] |
241 | > Const { name: Some(Name(Text("CONST"))), visibility: RawVisibilityId("pub(self)"), type_ref: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("u8"))] }, generic_args: [None] }), ast_id: FileAstId::<syntax::ast::generated::nodes::Const>(9) } | 241 | > Const { name: Some(Name(Text("CONST"))), visibility: RawVisibilityId("pub(self)"), type_ref: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("u8"))] }, generic_args: [None] }), ast_id: FileAstId::<syntax::ast::generated::nodes::Const>(9) } |
242 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_method"))] }, input: None }]) }] | 242 | > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_method"))] }, input: None }]) }] |
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml index 7d02aaf95..bc86df2b1 100644 --- a/crates/hir_ty/Cargo.toml +++ b/crates/hir_ty/Cargo.toml | |||
@@ -17,9 +17,9 @@ ena = "0.14.0" | |||
17 | log = "0.4.8" | 17 | log = "0.4.8" |
18 | rustc-hash = "1.1.0" | 18 | rustc-hash = "1.1.0" |
19 | scoped-tls = "1" | 19 | scoped-tls = "1" |
20 | chalk-solve = { version = "0.25.0" } | 20 | chalk-solve = { version = "0.27.0" } |
21 | chalk-ir = { version = "0.25.0" } | 21 | chalk-ir = { version = "0.27.0" } |
22 | chalk-recursive = { version = "0.25.0" } | 22 | chalk-recursive = { version = "0.27.0" } |
23 | 23 | ||
24 | stdx = { path = "../stdx", version = "0.0.0" } | 24 | stdx = { path = "../stdx", version = "0.0.0" } |
25 | hir_def = { path = "../hir_def", version = "0.0.0" } | 25 | hir_def = { path = "../hir_def", version = "0.0.0" } |
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 64b68014d..f389c5a4b 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -380,20 +380,34 @@ impl HirDisplay for ApplicationTy { | |||
380 | write!(f, ">")?; | 380 | write!(f, ">")?; |
381 | } | 381 | } |
382 | } | 382 | } |
383 | TypeCtor::ForeignType(type_alias) => { | ||
384 | let type_alias = f.db.type_alias_data(type_alias); | ||
385 | write!(f, "{}", type_alias.name)?; | ||
386 | if self.parameters.len() > 0 { | ||
387 | write!(f, "<")?; | ||
388 | f.write_joined(&*self.parameters.0, ", ")?; | ||
389 | write!(f, ">")?; | ||
390 | } | ||
391 | } | ||
383 | TypeCtor::OpaqueType(opaque_ty_id) => { | 392 | TypeCtor::OpaqueType(opaque_ty_id) => { |
384 | let bounds = match opaque_ty_id { | 393 | match opaque_ty_id { |
385 | OpaqueTyId::ReturnTypeImplTrait(func, idx) => { | 394 | OpaqueTyId::ReturnTypeImplTrait(func, idx) => { |
386 | let datas = | 395 | let datas = |
387 | f.db.return_type_impl_traits(func).expect("impl trait id without data"); | 396 | f.db.return_type_impl_traits(func).expect("impl trait id without data"); |
388 | let data = (*datas) | 397 | let data = (*datas) |
389 | .as_ref() | 398 | .as_ref() |
390 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); | 399 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); |
391 | data.subst(&self.parameters) | 400 | let bounds = data.subst(&self.parameters); |
401 | write!(f, "impl ")?; | ||
402 | write_bounds_like_dyn_trait(&bounds.value, f)?; | ||
403 | // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution | ||
392 | } | 404 | } |
393 | }; | 405 | OpaqueTyId::AsyncBlockTypeImplTrait(..) => { |
394 | write!(f, "impl ")?; | 406 | write!(f, "impl Future<Output = ")?; |
395 | write_bounds_like_dyn_trait(&bounds.value, f)?; | 407 | self.parameters[0].hir_fmt(f)?; |
396 | // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution | 408 | write!(f, ">")?; |
409 | } | ||
410 | } | ||
397 | } | 411 | } |
398 | TypeCtor::Closure { .. } => { | 412 | TypeCtor::Closure { .. } => { |
399 | let sig = self.parameters[0].callable_sig(f.db); | 413 | let sig = self.parameters[0].callable_sig(f.db); |
@@ -474,18 +488,21 @@ impl HirDisplay for Ty { | |||
474 | write_bounds_like_dyn_trait(predicates, f)?; | 488 | write_bounds_like_dyn_trait(predicates, f)?; |
475 | } | 489 | } |
476 | Ty::Opaque(opaque_ty) => { | 490 | Ty::Opaque(opaque_ty) => { |
477 | let bounds = match opaque_ty.opaque_ty_id { | 491 | match opaque_ty.opaque_ty_id { |
478 | OpaqueTyId::ReturnTypeImplTrait(func, idx) => { | 492 | OpaqueTyId::ReturnTypeImplTrait(func, idx) => { |
479 | let datas = | 493 | let datas = |
480 | f.db.return_type_impl_traits(func).expect("impl trait id without data"); | 494 | f.db.return_type_impl_traits(func).expect("impl trait id without data"); |
481 | let data = (*datas) | 495 | let data = (*datas) |
482 | .as_ref() | 496 | .as_ref() |
483 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); | 497 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); |
484 | data.subst(&opaque_ty.parameters) | 498 | let bounds = data.subst(&opaque_ty.parameters); |
499 | write!(f, "impl ")?; | ||
500 | write_bounds_like_dyn_trait(&bounds.value, f)?; | ||
501 | } | ||
502 | OpaqueTyId::AsyncBlockTypeImplTrait(..) => { | ||
503 | write!(f, "{{async block}}")?; | ||
485 | } | 504 | } |
486 | }; | 505 | }; |
487 | write!(f, "impl ")?; | ||
488 | write_bounds_like_dyn_trait(&bounds.value, f)?; | ||
489 | } | 506 | } |
490 | Ty::Unknown => write!(f, "{{unknown}}")?, | 507 | Ty::Unknown => write!(f, "{{unknown}}")?, |
491 | Ty::Infer(..) => write!(f, "_")?, | 508 | Ty::Infer(..) => write!(f, "_")?, |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index a2f849d02..0a141b9cb 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -17,8 +17,8 @@ use crate::{ | |||
17 | autoderef, method_resolution, op, | 17 | autoderef, method_resolution, op, |
18 | traits::{FnTrait, InEnvironment}, | 18 | traits::{FnTrait, InEnvironment}, |
19 | utils::{generics, variant_data, Generics}, | 19 | utils::{generics, variant_data, Generics}, |
20 | ApplicationTy, Binders, CallableDefId, InferTy, IntTy, Mutability, Obligation, Rawness, Substs, | 20 | ApplicationTy, Binders, CallableDefId, InferTy, IntTy, Mutability, Obligation, OpaqueTyId, |
21 | TraitRef, Ty, TypeCtor, | 21 | Rawness, Substs, TraitRef, Ty, TypeCtor, |
22 | }; | 22 | }; |
23 | 23 | ||
24 | use super::{ | 24 | use super::{ |
@@ -146,6 +146,13 @@ impl<'a> InferenceContext<'a> { | |||
146 | // FIXME should be std::result::Result<{inner}, _> | 146 | // FIXME should be std::result::Result<{inner}, _> |
147 | Ty::Unknown | 147 | Ty::Unknown |
148 | } | 148 | } |
149 | Expr::Async { body } => { | ||
150 | // Use the first type parameter as the output type of future. | ||
151 | // existenail type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType> | ||
152 | let inner_ty = self.infer_expr(*body, &Expectation::none()); | ||
153 | let opaque_ty_id = OpaqueTyId::AsyncBlockTypeImplTrait(self.owner, *body); | ||
154 | Ty::apply_one(TypeCtor::OpaqueType(opaque_ty_id), inner_ty) | ||
155 | } | ||
149 | Expr::Loop { body, label } => { | 156 | Expr::Loop { body, label } => { |
150 | self.breakables.push(BreakableContext { | 157 | self.breakables.push(BreakableContext { |
151 | may_break: false, | 158 | may_break: false, |
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index dde38bc39..cde2ab82b 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs | |||
@@ -209,6 +209,18 @@ impl<'a> InferenceContext<'a> { | |||
209 | end_ty | 209 | end_ty |
210 | } | 210 | } |
211 | Pat::Lit(expr) => self.infer_expr(*expr, &Expectation::has_type(expected.clone())), | 211 | Pat::Lit(expr) => self.infer_expr(*expr, &Expectation::has_type(expected.clone())), |
212 | Pat::Box { inner } => match self.resolve_boxed_box() { | ||
213 | Some(box_adt) => { | ||
214 | let inner_expected = match expected.as_adt() { | ||
215 | Some((adt, substs)) if adt == box_adt => substs.as_single(), | ||
216 | _ => &Ty::Unknown, | ||
217 | }; | ||
218 | |||
219 | let inner_ty = self.infer_pat(*inner, inner_expected, default_bm); | ||
220 | Ty::apply_one(TypeCtor::Adt(box_adt), inner_ty) | ||
221 | } | ||
222 | None => Ty::Unknown, | ||
223 | }, | ||
212 | Pat::Missing => Ty::Unknown, | 224 | Pat::Missing => Ty::Unknown, |
213 | }; | 225 | }; |
214 | // use a new type variable if we got Ty::Unknown here | 226 | // use a new type variable if we got Ty::Unknown here |
@@ -236,6 +248,6 @@ fn is_non_ref_pat(body: &hir_def::body::Body, pat: PatId) -> bool { | |||
236 | Expr::Literal(Literal::String(..)) => false, | 248 | Expr::Literal(Literal::String(..)) => false, |
237 | _ => true, | 249 | _ => true, |
238 | }, | 250 | }, |
239 | Pat::Wild | Pat::Bind { .. } | Pat::Ref { .. } | Pat::Missing => false, | 251 | Pat::Wild | Pat::Bind { .. } | Pat::Ref { .. } | Pat::Box { .. } | Pat::Missing => false, |
240 | } | 252 | } |
241 | } | 253 | } |
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 1e748476a..768d95eff 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -129,10 +129,14 @@ pub enum TypeCtor { | |||
129 | 129 | ||
130 | /// This represents a placeholder for an opaque type in situations where we | 130 | /// This represents a placeholder for an opaque type in situations where we |
131 | /// don't know the hidden type (i.e. currently almost always). This is | 131 | /// don't know the hidden type (i.e. currently almost always). This is |
132 | /// analogous to the `AssociatedType` type constructor. As with that one, | 132 | /// analogous to the `AssociatedType` type constructor. |
133 | /// these are only produced by Chalk. | 133 | /// It is also used as the type of async block, with one type parameter |
134 | /// representing the Future::Output type. | ||
134 | OpaqueType(OpaqueTyId), | 135 | OpaqueType(OpaqueTyId), |
135 | 136 | ||
137 | /// Represents a foreign type declared in external blocks. | ||
138 | ForeignType(TypeAliasId), | ||
139 | |||
136 | /// The type of a specific closure. | 140 | /// The type of a specific closure. |
137 | /// | 141 | /// |
138 | /// The closure signature is stored in a `FnPtr` type in the first type | 142 | /// The closure signature is stored in a `FnPtr` type in the first type |
@@ -167,12 +171,18 @@ impl TypeCtor { | |||
167 | let generic_params = generics(db.upcast(), type_alias.into()); | 171 | let generic_params = generics(db.upcast(), type_alias.into()); |
168 | generic_params.len() | 172 | generic_params.len() |
169 | } | 173 | } |
174 | TypeCtor::ForeignType(type_alias) => { | ||
175 | let generic_params = generics(db.upcast(), type_alias.into()); | ||
176 | generic_params.len() | ||
177 | } | ||
170 | TypeCtor::OpaqueType(opaque_ty_id) => { | 178 | TypeCtor::OpaqueType(opaque_ty_id) => { |
171 | match opaque_ty_id { | 179 | match opaque_ty_id { |
172 | OpaqueTyId::ReturnTypeImplTrait(func, _) => { | 180 | OpaqueTyId::ReturnTypeImplTrait(func, _) => { |
173 | let generic_params = generics(db.upcast(), func.into()); | 181 | let generic_params = generics(db.upcast(), func.into()); |
174 | generic_params.len() | 182 | generic_params.len() |
175 | } | 183 | } |
184 | // 1 param representing Future::Output type. | ||
185 | OpaqueTyId::AsyncBlockTypeImplTrait(..) => 1, | ||
176 | } | 186 | } |
177 | } | 187 | } |
178 | TypeCtor::FnPtr { num_args, is_varargs: _ } => num_args as usize + 1, | 188 | TypeCtor::FnPtr { num_args, is_varargs: _ } => num_args as usize + 1, |
@@ -201,10 +211,14 @@ impl TypeCtor { | |||
201 | TypeCtor::AssociatedType(type_alias) => { | 211 | TypeCtor::AssociatedType(type_alias) => { |
202 | Some(type_alias.lookup(db.upcast()).module(db.upcast()).krate) | 212 | Some(type_alias.lookup(db.upcast()).module(db.upcast()).krate) |
203 | } | 213 | } |
214 | TypeCtor::ForeignType(type_alias) => { | ||
215 | Some(type_alias.lookup(db.upcast()).module(db.upcast()).krate) | ||
216 | } | ||
204 | TypeCtor::OpaqueType(opaque_ty_id) => match opaque_ty_id { | 217 | TypeCtor::OpaqueType(opaque_ty_id) => match opaque_ty_id { |
205 | OpaqueTyId::ReturnTypeImplTrait(func, _) => { | 218 | OpaqueTyId::ReturnTypeImplTrait(func, _) => { |
206 | Some(func.lookup(db.upcast()).module(db.upcast()).krate) | 219 | Some(func.lookup(db.upcast()).module(db.upcast()).krate) |
207 | } | 220 | } |
221 | OpaqueTyId::AsyncBlockTypeImplTrait(def, _) => Some(def.module(db.upcast()).krate), | ||
208 | }, | 222 | }, |
209 | } | 223 | } |
210 | } | 224 | } |
@@ -227,6 +241,7 @@ impl TypeCtor { | |||
227 | TypeCtor::Adt(adt) => Some(adt.into()), | 241 | TypeCtor::Adt(adt) => Some(adt.into()), |
228 | TypeCtor::FnDef(callable) => Some(callable.into()), | 242 | TypeCtor::FnDef(callable) => Some(callable.into()), |
229 | TypeCtor::AssociatedType(type_alias) => Some(type_alias.into()), | 243 | TypeCtor::AssociatedType(type_alias) => Some(type_alias.into()), |
244 | TypeCtor::ForeignType(type_alias) => Some(type_alias.into()), | ||
230 | TypeCtor::OpaqueType(_impl_trait_id) => None, | 245 | TypeCtor::OpaqueType(_impl_trait_id) => None, |
231 | } | 246 | } |
232 | } | 247 | } |
@@ -843,6 +858,29 @@ impl Ty { | |||
843 | 858 | ||
844 | pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredicate>> { | 859 | pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredicate>> { |
845 | match self { | 860 | match self { |
861 | Ty::Apply(ApplicationTy { ctor: TypeCtor::OpaqueType(opaque_ty_id), .. }) => { | ||
862 | match opaque_ty_id { | ||
863 | OpaqueTyId::AsyncBlockTypeImplTrait(def, _expr) => { | ||
864 | let krate = def.module(db.upcast()).krate; | ||
865 | if let Some(future_trait) = db | ||
866 | .lang_item(krate, "future_trait".into()) | ||
867 | .and_then(|item| item.as_trait()) | ||
868 | { | ||
869 | // This is only used by type walking. | ||
870 | // Parameters will be walked outside, and projection predicate is not used. | ||
871 | // So just provide the Future trait. | ||
872 | let impl_bound = GenericPredicate::Implemented(TraitRef { | ||
873 | trait_: future_trait, | ||
874 | substs: Substs::empty(), | ||
875 | }); | ||
876 | Some(vec![impl_bound]) | ||
877 | } else { | ||
878 | None | ||
879 | } | ||
880 | } | ||
881 | OpaqueTyId::ReturnTypeImplTrait(..) => None, | ||
882 | } | ||
883 | } | ||
846 | Ty::Opaque(opaque_ty) => { | 884 | Ty::Opaque(opaque_ty) => { |
847 | let predicates = match opaque_ty.opaque_ty_id { | 885 | let predicates = match opaque_ty.opaque_ty_id { |
848 | OpaqueTyId::ReturnTypeImplTrait(func, idx) => { | 886 | OpaqueTyId::ReturnTypeImplTrait(func, idx) => { |
@@ -853,6 +891,8 @@ impl Ty { | |||
853 | data.subst(&opaque_ty.parameters) | 891 | data.subst(&opaque_ty.parameters) |
854 | }) | 892 | }) |
855 | } | 893 | } |
894 | // It always has an parameter for Future::Output type. | ||
895 | OpaqueTyId::AsyncBlockTypeImplTrait(..) => unreachable!(), | ||
856 | }; | 896 | }; |
857 | 897 | ||
858 | predicates.map(|it| it.value) | 898 | predicates.map(|it| it.value) |
@@ -1065,6 +1105,7 @@ impl<T: TypeWalk> TypeWalk for Vec<T> { | |||
1065 | #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] | 1105 | #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] |
1066 | pub enum OpaqueTyId { | 1106 | pub enum OpaqueTyId { |
1067 | ReturnTypeImplTrait(hir_def::FunctionId, u16), | 1107 | ReturnTypeImplTrait(hir_def::FunctionId, u16), |
1108 | AsyncBlockTypeImplTrait(hir_def::DefWithBodyId, ExprId), | ||
1068 | } | 1109 | } |
1069 | 1110 | ||
1070 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 1111 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index cd574e983..708e2af0f 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -1101,10 +1101,14 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> { | |||
1101 | let resolver = t.resolver(db.upcast()); | 1101 | let resolver = t.resolver(db.upcast()); |
1102 | let ctx = | 1102 | let ctx = |
1103 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | 1103 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); |
1104 | let type_ref = &db.type_alias_data(t).type_ref; | ||
1105 | let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); | 1104 | let substs = Substs::bound_vars(&generics, DebruijnIndex::INNERMOST); |
1106 | let inner = Ty::from_hir(&ctx, type_ref.as_ref().unwrap_or(&TypeRef::Error)); | 1105 | if db.type_alias_data(t).is_extern { |
1107 | Binders::new(substs.len(), inner) | 1106 | Binders::new(substs.len(), Ty::apply(TypeCtor::ForeignType(t), substs)) |
1107 | } else { | ||
1108 | let type_ref = &db.type_alias_data(t).type_ref; | ||
1109 | let inner = Ty::from_hir(&ctx, type_ref.as_ref().unwrap_or(&TypeRef::Error)); | ||
1110 | Binders::new(substs.len(), inner) | ||
1111 | } | ||
1108 | } | 1112 | } |
1109 | 1113 | ||
1110 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 1114 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index ec59145c7..8961df404 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs | |||
@@ -250,6 +250,14 @@ impl Ty { | |||
250 | TypeCtor::Adt(def_id) => { | 250 | TypeCtor::Adt(def_id) => { |
251 | return Some(std::iter::once(def_id.module(db.upcast()).krate).collect()) | 251 | return Some(std::iter::once(def_id.module(db.upcast()).krate).collect()) |
252 | } | 252 | } |
253 | TypeCtor::ForeignType(type_alias_id) => { | ||
254 | return Some( | ||
255 | std::iter::once( | ||
256 | type_alias_id.lookup(db.upcast()).module(db.upcast()).krate, | ||
257 | ) | ||
258 | .collect(), | ||
259 | ) | ||
260 | } | ||
253 | TypeCtor::Bool => lang_item_crate!("bool"), | 261 | TypeCtor::Bool => lang_item_crate!("bool"), |
254 | TypeCtor::Char => lang_item_crate!("char"), | 262 | TypeCtor::Char => lang_item_crate!("char"), |
255 | TypeCtor::Float(f) => match f.bitness { | 263 | TypeCtor::Float(f) => match f.bitness { |
diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs index 23b2601e6..0f17ff151 100644 --- a/crates/hir_ty/src/tests/method_resolution.rs +++ b/crates/hir_ty/src/tests/method_resolution.rs | |||
@@ -1051,3 +1051,39 @@ fn dyn_trait_super_trait_not_in_scope() { | |||
1051 | "#]], | 1051 | "#]], |
1052 | ); | 1052 | ); |
1053 | } | 1053 | } |
1054 | |||
1055 | #[test] | ||
1056 | fn method_resolution_foreign_opaque_type() { | ||
1057 | check_infer( | ||
1058 | r#" | ||
1059 | extern "C" { | ||
1060 | type S; | ||
1061 | fn f() -> &'static S; | ||
1062 | } | ||
1063 | |||
1064 | impl S { | ||
1065 | fn foo(&self) -> bool { | ||
1066 | true | ||
1067 | } | ||
1068 | } | ||
1069 | |||
1070 | fn test() { | ||
1071 | let s = unsafe { f() }; | ||
1072 | s.foo(); | ||
1073 | } | ||
1074 | "#, | ||
1075 | expect![[r#" | ||
1076 | 75..79 'self': &S | ||
1077 | 89..109 '{ ... }': bool | ||
1078 | 99..103 'true': bool | ||
1079 | 123..167 '{ ...o(); }': () | ||
1080 | 133..134 's': &S | ||
1081 | 137..151 'unsafe { f() }': &S | ||
1082 | 144..151 '{ f() }': &S | ||
1083 | 146..147 'f': fn f() -> &S | ||
1084 | 146..149 'f()': &S | ||
1085 | 157..158 's': &S | ||
1086 | 157..164 's.foo()': bool | ||
1087 | "#]], | ||
1088 | ); | ||
1089 | } | ||
diff --git a/crates/hir_ty/src/tests/patterns.rs b/crates/hir_ty/src/tests/patterns.rs index aeb191c79..6a965ac4f 100644 --- a/crates/hir_ty/src/tests/patterns.rs +++ b/crates/hir_ty/src/tests/patterns.rs | |||
@@ -654,3 +654,28 @@ fn slice_tail_pattern() { | |||
654 | "#]], | 654 | "#]], |
655 | ); | 655 | ); |
656 | } | 656 | } |
657 | |||
658 | #[test] | ||
659 | fn box_pattern() { | ||
660 | check_infer( | ||
661 | r#" | ||
662 | #[lang = "owned_box"] | ||
663 | pub struct Box<T>(T); | ||
664 | |||
665 | fn foo(params: Box<i32>) { | ||
666 | match params { | ||
667 | box integer => {} | ||
668 | } | ||
669 | } | ||
670 | "#, | ||
671 | expect![[r#" | ||
672 | 52..58 'params': Box<i32> | ||
673 | 70..124 '{ ... } }': () | ||
674 | 76..122 'match ... }': () | ||
675 | 82..88 'params': Box<i32> | ||
676 | 99..110 'box integer': Box<i32> | ||
677 | 103..110 'integer': i32 | ||
678 | 114..116 '{}': () | ||
679 | "#]], | ||
680 | ); | ||
681 | } | ||
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs index 48db23a34..5b07948f3 100644 --- a/crates/hir_ty/src/tests/simple.rs +++ b/crates/hir_ty/src/tests/simple.rs | |||
@@ -1889,31 +1889,40 @@ fn fn_pointer_return() { | |||
1889 | fn effects_smoke_test() { | 1889 | fn effects_smoke_test() { |
1890 | check_infer( | 1890 | check_infer( |
1891 | r#" | 1891 | r#" |
1892 | fn main() { | 1892 | async fn main() { |
1893 | let x = unsafe { 92 }; | 1893 | let x = unsafe { 92 }; |
1894 | let y = async { async { () }.await }; | 1894 | let y = async { async { () }.await }; |
1895 | let z = try { () }; | 1895 | let z = try { () }; |
1896 | let t = 'a: { 92 }; | 1896 | let t = 'a: { 92 }; |
1897 | } | 1897 | } |
1898 | |||
1899 | #[prelude_import] use future::*; | ||
1900 | |||
1901 | mod future { | ||
1902 | #[lang = "future_trait"] | ||
1903 | pub trait Future { type Output; } | ||
1904 | } | ||
1898 | "#, | 1905 | "#, |
1899 | expect![[r#" | 1906 | expect![[r#" |
1900 | 10..130 '{ ...2 }; }': () | 1907 | 16..136 '{ ...2 }; }': () |
1901 | 20..21 'x': i32 | 1908 | 26..27 'x': i32 |
1902 | 24..37 'unsafe { 92 }': i32 | 1909 | 30..43 'unsafe { 92 }': i32 |
1903 | 31..37 '{ 92 }': i32 | 1910 | 37..43 '{ 92 }': i32 |
1904 | 33..35 '92': i32 | 1911 | 39..41 '92': i32 |
1905 | 47..48 'y': {unknown} | 1912 | 53..54 'y': impl Future<Output = ()> |
1906 | 57..79 '{ asyn...wait }': {unknown} | 1913 | 57..85 'async ...wait }': impl Future<Output = ()> |
1907 | 59..77 'async ....await': {unknown} | 1914 | 63..85 '{ asyn...wait }': () |
1908 | 65..71 '{ () }': () | 1915 | 65..77 'async { () }': impl Future<Output = ()> |
1909 | 67..69 '()': () | 1916 | 65..83 'async ....await': () |
1910 | 89..90 'z': {unknown} | 1917 | 71..77 '{ () }': () |
1911 | 93..103 'try { () }': {unknown} | 1918 | 73..75 '()': () |
1912 | 97..103 '{ () }': () | 1919 | 95..96 'z': {unknown} |
1913 | 99..101 '()': () | 1920 | 99..109 'try { () }': {unknown} |
1914 | 113..114 't': i32 | 1921 | 103..109 '{ () }': () |
1915 | 121..127 '{ 92 }': i32 | 1922 | 105..107 '()': () |
1916 | 123..125 '92': i32 | 1923 | 119..120 't': i32 |
1924 | 127..133 '{ 92 }': i32 | ||
1925 | 129..131 '92': i32 | ||
1917 | "#]], | 1926 | "#]], |
1918 | ) | 1927 | ) |
1919 | } | 1928 | } |
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index 1f1056962..41d097519 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs | |||
@@ -86,6 +86,46 @@ mod future { | |||
86 | } | 86 | } |
87 | 87 | ||
88 | #[test] | 88 | #[test] |
89 | fn infer_async_block() { | ||
90 | check_types( | ||
91 | r#" | ||
92 | //- /main.rs crate:main deps:core | ||
93 | async fn test() { | ||
94 | let a = async { 42 }; | ||
95 | a; | ||
96 | // ^ impl Future<Output = i32> | ||
97 | let x = a.await; | ||
98 | x; | ||
99 | // ^ i32 | ||
100 | let b = async {}.await; | ||
101 | b; | ||
102 | // ^ () | ||
103 | let c = async { | ||
104 | let y = Option::None; | ||
105 | y | ||
106 | // ^ Option<u64> | ||
107 | }; | ||
108 | let _: Option<u64> = c.await; | ||
109 | c; | ||
110 | // ^ impl Future<Output = Option<u64>> | ||
111 | } | ||
112 | |||
113 | enum Option<T> { None, Some(T) } | ||
114 | |||
115 | //- /core.rs crate:core | ||
116 | #[prelude_import] use future::*; | ||
117 | mod future { | ||
118 | #[lang = "future_trait"] | ||
119 | trait Future { | ||
120 | type Output; | ||
121 | } | ||
122 | } | ||
123 | |||
124 | "#, | ||
125 | ); | ||
126 | } | ||
127 | |||
128 | #[test] | ||
89 | fn infer_try() { | 129 | fn infer_try() { |
90 | check_types( | 130 | check_types( |
91 | r#" | 131 | r#" |
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index 01b5717a3..27f0ed628 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs | |||
@@ -11,6 +11,7 @@ use hir_def::{ | |||
11 | lang_item::{lang_attr, LangItemTarget}, | 11 | lang_item::{lang_attr, LangItemTarget}, |
12 | AssocContainerId, AssocItemId, HasModule, Lookup, TypeAliasId, | 12 | AssocContainerId, AssocItemId, HasModule, Lookup, TypeAliasId, |
13 | }; | 13 | }; |
14 | use hir_expand::name::name; | ||
14 | 15 | ||
15 | use super::ChalkContext; | 16 | use super::ChalkContext; |
16 | use crate::{ | 17 | use crate::{ |
@@ -18,10 +19,12 @@ use crate::{ | |||
18 | display::HirDisplay, | 19 | display::HirDisplay, |
19 | method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, | 20 | method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, |
20 | utils::generics, | 21 | utils::generics, |
21 | CallableDefId, DebruijnIndex, FnSig, GenericPredicate, Substs, Ty, TypeCtor, | 22 | BoundVar, CallableDefId, DebruijnIndex, FnSig, GenericPredicate, ProjectionPredicate, |
23 | ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | ||
22 | }; | 24 | }; |
23 | use mapping::{ | 25 | use mapping::{ |
24 | convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue, | 26 | convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsAssocType, |
27 | TypeAliasAsValue, | ||
25 | }; | 28 | }; |
26 | 29 | ||
27 | pub use self::interner::*; | 30 | pub use self::interner::*; |
@@ -166,27 +169,88 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
166 | fn opaque_ty_data(&self, id: chalk_ir::OpaqueTyId<Interner>) -> Arc<OpaqueTyDatum> { | 169 | fn opaque_ty_data(&self, id: chalk_ir::OpaqueTyId<Interner>) -> Arc<OpaqueTyDatum> { |
167 | let interned_id = crate::db::InternedOpaqueTyId::from(id); | 170 | let interned_id = crate::db::InternedOpaqueTyId::from(id); |
168 | let full_id = self.db.lookup_intern_impl_trait_id(interned_id); | 171 | let full_id = self.db.lookup_intern_impl_trait_id(interned_id); |
169 | let (func, idx) = match full_id { | 172 | let bound = match full_id { |
170 | crate::OpaqueTyId::ReturnTypeImplTrait(func, idx) => (func, idx), | 173 | crate::OpaqueTyId::ReturnTypeImplTrait(func, idx) => { |
171 | }; | 174 | let datas = self |
172 | let datas = | 175 | .db |
173 | self.db.return_type_impl_traits(func).expect("impl trait id without impl traits"); | 176 | .return_type_impl_traits(func) |
174 | let data = &datas.value.impl_traits[idx as usize]; | 177 | .expect("impl trait id without impl traits"); |
175 | let bound = OpaqueTyDatumBound { | 178 | let data = &datas.value.impl_traits[idx as usize]; |
176 | bounds: make_binders( | 179 | let bound = OpaqueTyDatumBound { |
177 | data.bounds | 180 | bounds: make_binders( |
178 | .value | 181 | data.bounds |
179 | .iter() | 182 | .value |
180 | .cloned() | 183 | .iter() |
181 | .filter(|b| !b.is_error()) | 184 | .cloned() |
182 | .map(|b| b.to_chalk(self.db)) | 185 | .filter(|b| !b.is_error()) |
183 | .collect(), | 186 | .map(|b| b.to_chalk(self.db)) |
184 | 1, | 187 | .collect(), |
185 | ), | 188 | 1, |
186 | where_clauses: make_binders(vec![], 0), | 189 | ), |
190 | where_clauses: make_binders(vec![], 0), | ||
191 | }; | ||
192 | let num_vars = datas.num_binders; | ||
193 | make_binders(bound, num_vars) | ||
194 | } | ||
195 | crate::OpaqueTyId::AsyncBlockTypeImplTrait(..) => { | ||
196 | if let Some((future_trait, future_output)) = self | ||
197 | .db | ||
198 | .lang_item(self.krate, "future_trait".into()) | ||
199 | .and_then(|item| item.as_trait()) | ||
200 | .and_then(|trait_| { | ||
201 | let alias = | ||
202 | self.db.trait_data(trait_).associated_type_by_name(&name![Output])?; | ||
203 | Some((trait_, alias)) | ||
204 | }) | ||
205 | { | ||
206 | // Making up `AsyncBlock<T>: Future<Output = T>` | ||
207 | // | ||
208 | // |--------------------OpaqueTyDatum-------------------| | ||
209 | // |-------------OpaqueTyDatumBound--------------| | ||
210 | // for<T> <Self> [Future<Self>, Future::Output<Self> = T] | ||
211 | // ^1 ^0 ^0 ^0 ^1 | ||
212 | let impl_bound = GenericPredicate::Implemented(TraitRef { | ||
213 | trait_: future_trait, | ||
214 | // Self type as the first parameter. | ||
215 | substs: Substs::single(Ty::Bound(BoundVar { | ||
216 | debruijn: DebruijnIndex::INNERMOST, | ||
217 | index: 0, | ||
218 | })), | ||
219 | }); | ||
220 | let proj_bound = GenericPredicate::Projection(ProjectionPredicate { | ||
221 | // The parameter of the opaque type. | ||
222 | ty: Ty::Bound(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 }), | ||
223 | projection_ty: ProjectionTy { | ||
224 | associated_ty: future_output, | ||
225 | // Self type as the first parameter. | ||
226 | parameters: Substs::single(Ty::Bound(BoundVar::new( | ||
227 | DebruijnIndex::INNERMOST, | ||
228 | 0, | ||
229 | ))), | ||
230 | }, | ||
231 | }); | ||
232 | let bound = OpaqueTyDatumBound { | ||
233 | bounds: make_binders( | ||
234 | vec![impl_bound.to_chalk(self.db), proj_bound.to_chalk(self.db)], | ||
235 | 1, | ||
236 | ), | ||
237 | where_clauses: make_binders(vec![], 0), | ||
238 | }; | ||
239 | // The opaque type has 1 parameter. | ||
240 | make_binders(bound, 1) | ||
241 | } else { | ||
242 | // If failed to find `Future::Output`, return empty bounds as fallback. | ||
243 | let bound = OpaqueTyDatumBound { | ||
244 | bounds: make_binders(vec![], 0), | ||
245 | where_clauses: make_binders(vec![], 0), | ||
246 | }; | ||
247 | // The opaque type has 1 parameter. | ||
248 | make_binders(bound, 1) | ||
249 | } | ||
250 | } | ||
187 | }; | 251 | }; |
188 | let num_vars = datas.num_binders; | 252 | |
189 | Arc::new(OpaqueTyDatum { opaque_ty_id: id, bound: make_binders(bound, num_vars) }) | 253 | Arc::new(OpaqueTyDatum { opaque_ty_id: id, bound }) |
190 | } | 254 | } |
191 | 255 | ||
192 | fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<Interner>) -> chalk_ir::Ty<Interner> { | 256 | fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<Interner>) -> chalk_ir::Ty<Interner> { |
@@ -277,7 +341,7 @@ pub(crate) fn associated_ty_data_query( | |||
277 | id: AssocTypeId, | 341 | id: AssocTypeId, |
278 | ) -> Arc<AssociatedTyDatum> { | 342 | ) -> Arc<AssociatedTyDatum> { |
279 | debug!("associated_ty_data {:?}", id); | 343 | debug!("associated_ty_data {:?}", id); |
280 | let type_alias: TypeAliasId = from_chalk(db, id); | 344 | let type_alias: TypeAliasId = from_chalk::<TypeAliasAsAssocType, _>(db, id).0; |
281 | let trait_ = match type_alias.lookup(db.upcast()).container { | 345 | let trait_ = match type_alias.lookup(db.upcast()).container { |
282 | AssocContainerId::TraitId(t) => t, | 346 | AssocContainerId::TraitId(t) => t, |
283 | _ => panic!("associated type not in trait"), | 347 | _ => panic!("associated type not in trait"), |
@@ -331,8 +395,10 @@ pub(crate) fn trait_datum_query( | |||
331 | fundamental: false, | 395 | fundamental: false, |
332 | }; | 396 | }; |
333 | let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars); | 397 | let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars); |
334 | let associated_ty_ids = | 398 | let associated_ty_ids = trait_data |
335 | trait_data.associated_types().map(|type_alias| type_alias.to_chalk(db)).collect(); | 399 | .associated_types() |
400 | .map(|type_alias| TypeAliasAsAssocType(type_alias).to_chalk(db)) | ||
401 | .collect(); | ||
336 | let trait_datum_bound = rust_ir::TraitDatumBound { where_clauses }; | 402 | let trait_datum_bound = rust_ir::TraitDatumBound { where_clauses }; |
337 | let well_known = | 403 | let well_known = |
338 | lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name)); | 404 | lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name)); |
@@ -370,6 +436,7 @@ fn lang_attr_from_well_known_trait(attr: WellKnownTrait) -> &'static str { | |||
370 | WellKnownTrait::FnMut => "fn_mut", | 436 | WellKnownTrait::FnMut => "fn_mut", |
371 | WellKnownTrait::Fn => "fn", | 437 | WellKnownTrait::Fn => "fn", |
372 | WellKnownTrait::Unsize => "unsize", | 438 | WellKnownTrait::Unsize => "unsize", |
439 | WellKnownTrait::Unpin => "unpin", | ||
373 | } | 440 | } |
374 | } | 441 | } |
375 | 442 | ||
@@ -513,7 +580,7 @@ fn type_alias_associated_ty_value( | |||
513 | let value_bound = rust_ir::AssociatedTyValueBound { ty: ty.value.to_chalk(db) }; | 580 | let value_bound = rust_ir::AssociatedTyValueBound { ty: ty.value.to_chalk(db) }; |
514 | let value = rust_ir::AssociatedTyValue { | 581 | let value = rust_ir::AssociatedTyValue { |
515 | impl_id: impl_id.to_chalk(db), | 582 | impl_id: impl_id.to_chalk(db), |
516 | associated_ty_id: assoc_ty.to_chalk(db), | 583 | associated_ty_id: TypeAliasAsAssocType(assoc_ty).to_chalk(db), |
517 | value: make_binders(value_bound, ty.num_binders), | 584 | value: make_binders(value_bound, ty.num_binders), |
518 | }; | 585 | }; |
519 | Arc::new(value) | 586 | Arc::new(value) |
@@ -548,9 +615,11 @@ pub(crate) fn fn_def_datum_query( | |||
548 | }; | 615 | }; |
549 | let datum = FnDefDatum { | 616 | let datum = FnDefDatum { |
550 | id: fn_def_id, | 617 | id: fn_def_id, |
551 | abi: (), | 618 | sig: chalk_ir::FnSig { |
552 | safety: chalk_ir::Safety::Safe, | 619 | abi: (), |
553 | variadic: sig.value.is_varargs, | 620 | safety: chalk_ir::Safety::Safe, |
621 | variadic: sig.value.is_varargs, | ||
622 | }, | ||
554 | binders: make_binders(bound, sig.num_binders), | 623 | binders: make_binders(bound, sig.num_binders), |
555 | }; | 624 | }; |
556 | Arc::new(datum) | 625 | Arc::new(datum) |
diff --git a/crates/hir_ty/src/traits/chalk/interner.rs b/crates/hir_ty/src/traits/chalk/interner.rs index eb35db3ff..f9304b7d0 100644 --- a/crates/hir_ty/src/traits/chalk/interner.rs +++ b/crates/hir_ty/src/traits/chalk/interner.rs | |||
@@ -12,6 +12,7 @@ pub struct Interner; | |||
12 | 12 | ||
13 | pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>; | 13 | pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>; |
14 | pub type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>; | 14 | pub type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>; |
15 | pub type ForeignDefId = chalk_ir::ForeignDefId<Interner>; | ||
15 | pub type TraitId = chalk_ir::TraitId<Interner>; | 16 | pub type TraitId = chalk_ir::TraitId<Interner>; |
16 | pub type TraitDatum = chalk_solve::rust_ir::TraitDatum<Interner>; | 17 | pub type TraitDatum = chalk_solve::rust_ir::TraitDatum<Interner>; |
17 | pub type AdtId = chalk_ir::AdtId<Interner>; | 18 | pub type AdtId = chalk_ir::AdtId<Interner>; |
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs index d6bacba1d..d42f4bba9 100644 --- a/crates/hir_ty/src/traits/chalk/mapping.rs +++ b/crates/hir_ty/src/traits/chalk/mapping.rs | |||
@@ -34,9 +34,11 @@ impl ToChalk for Ty { | |||
34 | let substitution = apply_ty.parameters.to_chalk(db).shifted_in(&Interner); | 34 | let substitution = apply_ty.parameters.to_chalk(db).shifted_in(&Interner); |
35 | chalk_ir::TyData::Function(chalk_ir::FnPointer { | 35 | chalk_ir::TyData::Function(chalk_ir::FnPointer { |
36 | num_binders: 0, | 36 | num_binders: 0, |
37 | abi: (), | 37 | sig: chalk_ir::FnSig { |
38 | safety: chalk_ir::Safety::Safe, | 38 | abi: (), |
39 | variadic: is_varargs, | 39 | safety: chalk_ir::Safety::Safe, |
40 | variadic: is_varargs, | ||
41 | }, | ||
40 | substitution, | 42 | substitution, |
41 | }) | 43 | }) |
42 | .intern(&Interner) | 44 | .intern(&Interner) |
@@ -48,7 +50,7 @@ impl ToChalk for Ty { | |||
48 | } | 50 | } |
49 | }, | 51 | }, |
50 | Ty::Projection(proj_ty) => { | 52 | Ty::Projection(proj_ty) => { |
51 | let associated_ty_id = proj_ty.associated_ty.to_chalk(db); | 53 | let associated_ty_id = TypeAliasAsAssocType(proj_ty.associated_ty).to_chalk(db); |
52 | let substitution = proj_ty.parameters.to_chalk(db); | 54 | let substitution = proj_ty.parameters.to_chalk(db); |
53 | chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy { | 55 | chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy { |
54 | associated_ty_id, | 56 | associated_ty_id, |
@@ -114,7 +116,8 @@ impl ToChalk for Ty { | |||
114 | Ty::Placeholder(db.lookup_intern_type_param_id(interned_id)) | 116 | Ty::Placeholder(db.lookup_intern_type_param_id(interned_id)) |
115 | } | 117 | } |
116 | chalk_ir::TyData::Alias(chalk_ir::AliasTy::Projection(proj)) => { | 118 | chalk_ir::TyData::Alias(chalk_ir::AliasTy::Projection(proj)) => { |
117 | let associated_ty = from_chalk(db, proj.associated_ty_id); | 119 | let associated_ty = |
120 | from_chalk::<TypeAliasAsAssocType, _>(db, proj.associated_ty_id).0; | ||
118 | let parameters = from_chalk(db, proj.substitution); | 121 | let parameters = from_chalk(db, proj.substitution); |
119 | Ty::Projection(ProjectionTy { associated_ty, parameters }) | 122 | Ty::Projection(ProjectionTy { associated_ty, parameters }) |
120 | } | 123 | } |
@@ -125,7 +128,7 @@ impl ToChalk for Ty { | |||
125 | } | 128 | } |
126 | chalk_ir::TyData::Function(chalk_ir::FnPointer { | 129 | chalk_ir::TyData::Function(chalk_ir::FnPointer { |
127 | num_binders, | 130 | num_binders, |
128 | variadic, | 131 | sig: chalk_ir::FnSig { variadic, .. }, |
129 | substitution, | 132 | substitution, |
130 | .. | 133 | .. |
131 | }) => { | 134 | }) => { |
@@ -290,8 +293,9 @@ impl ToChalk for TypeCtor { | |||
290 | fn to_chalk(self, db: &dyn HirDatabase) -> TypeName<Interner> { | 293 | fn to_chalk(self, db: &dyn HirDatabase) -> TypeName<Interner> { |
291 | match self { | 294 | match self { |
292 | TypeCtor::AssociatedType(type_alias) => { | 295 | TypeCtor::AssociatedType(type_alias) => { |
293 | let type_id = type_alias.to_chalk(db); | 296 | let assoc_type = TypeAliasAsAssocType(type_alias); |
294 | TypeName::AssociatedType(type_id) | 297 | let assoc_type_id = assoc_type.to_chalk(db); |
298 | TypeName::AssociatedType(assoc_type_id) | ||
295 | } | 299 | } |
296 | 300 | ||
297 | TypeCtor::OpaqueType(impl_trait_id) => { | 301 | TypeCtor::OpaqueType(impl_trait_id) => { |
@@ -299,6 +303,12 @@ impl ToChalk for TypeCtor { | |||
299 | TypeName::OpaqueType(id) | 303 | TypeName::OpaqueType(id) |
300 | } | 304 | } |
301 | 305 | ||
306 | TypeCtor::ForeignType(type_alias) => { | ||
307 | let foreign_type = TypeAliasAsForeignType(type_alias); | ||
308 | let foreign_type_id = foreign_type.to_chalk(db); | ||
309 | TypeName::Foreign(foreign_type_id) | ||
310 | } | ||
311 | |||
302 | TypeCtor::Bool => TypeName::Scalar(Scalar::Bool), | 312 | TypeCtor::Bool => TypeName::Scalar(Scalar::Bool), |
303 | TypeCtor::Char => TypeName::Scalar(Scalar::Char), | 313 | TypeCtor::Char => TypeName::Scalar(Scalar::Char), |
304 | TypeCtor::Int(int_ty) => TypeName::Scalar(int_ty_to_chalk(int_ty)), | 314 | TypeCtor::Int(int_ty) => TypeName::Scalar(int_ty_to_chalk(int_ty)), |
@@ -339,7 +349,9 @@ impl ToChalk for TypeCtor { | |||
339 | fn from_chalk(db: &dyn HirDatabase, type_name: TypeName<Interner>) -> TypeCtor { | 349 | fn from_chalk(db: &dyn HirDatabase, type_name: TypeName<Interner>) -> TypeCtor { |
340 | match type_name { | 350 | match type_name { |
341 | TypeName::Adt(struct_id) => TypeCtor::Adt(struct_id.0), | 351 | TypeName::Adt(struct_id) => TypeCtor::Adt(struct_id.0), |
342 | TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)), | 352 | TypeName::AssociatedType(type_id) => { |
353 | TypeCtor::AssociatedType(from_chalk::<TypeAliasAsAssocType, _>(db, type_id).0) | ||
354 | } | ||
343 | TypeName::OpaqueType(opaque_type_id) => { | 355 | TypeName::OpaqueType(opaque_type_id) => { |
344 | TypeCtor::OpaqueType(from_chalk(db, opaque_type_id)) | 356 | TypeCtor::OpaqueType(from_chalk(db, opaque_type_id)) |
345 | } | 357 | } |
@@ -379,6 +391,10 @@ impl ToChalk for TypeCtor { | |||
379 | TypeCtor::Closure { def, expr } | 391 | TypeCtor::Closure { def, expr } |
380 | } | 392 | } |
381 | 393 | ||
394 | TypeName::Foreign(foreign_def_id) => { | ||
395 | TypeCtor::ForeignType(from_chalk::<TypeAliasAsForeignType, _>(db, foreign_def_id).0) | ||
396 | } | ||
397 | |||
382 | TypeName::Error => { | 398 | TypeName::Error => { |
383 | // this should not be reached, since we don't represent TypeName::Error with TypeCtor | 399 | // this should not be reached, since we don't represent TypeName::Error with TypeCtor |
384 | unreachable!() | 400 | unreachable!() |
@@ -488,15 +504,31 @@ impl ToChalk for CallableDefId { | |||
488 | } | 504 | } |
489 | } | 505 | } |
490 | 506 | ||
491 | impl ToChalk for TypeAliasId { | 507 | pub struct TypeAliasAsAssocType(pub TypeAliasId); |
508 | |||
509 | impl ToChalk for TypeAliasAsAssocType { | ||
492 | type Chalk = AssocTypeId; | 510 | type Chalk = AssocTypeId; |
493 | 511 | ||
494 | fn to_chalk(self, _db: &dyn HirDatabase) -> AssocTypeId { | 512 | fn to_chalk(self, _db: &dyn HirDatabase) -> AssocTypeId { |
495 | chalk_ir::AssocTypeId(self.as_intern_id()) | 513 | chalk_ir::AssocTypeId(self.0.as_intern_id()) |
514 | } | ||
515 | |||
516 | fn from_chalk(_db: &dyn HirDatabase, assoc_type_id: AssocTypeId) -> TypeAliasAsAssocType { | ||
517 | TypeAliasAsAssocType(InternKey::from_intern_id(assoc_type_id.0)) | ||
518 | } | ||
519 | } | ||
520 | |||
521 | pub struct TypeAliasAsForeignType(pub TypeAliasId); | ||
522 | |||
523 | impl ToChalk for TypeAliasAsForeignType { | ||
524 | type Chalk = ForeignDefId; | ||
525 | |||
526 | fn to_chalk(self, _db: &dyn HirDatabase) -> ForeignDefId { | ||
527 | chalk_ir::ForeignDefId(self.0.as_intern_id()) | ||
496 | } | 528 | } |
497 | 529 | ||
498 | fn from_chalk(_db: &dyn HirDatabase, type_alias_id: AssocTypeId) -> TypeAliasId { | 530 | fn from_chalk(_db: &dyn HirDatabase, foreign_def_id: ForeignDefId) -> TypeAliasAsForeignType { |
499 | InternKey::from_intern_id(type_alias_id.0) | 531 | TypeAliasAsForeignType(InternKey::from_intern_id(foreign_def_id.0)) |
500 | } | 532 | } |
501 | } | 533 | } |
502 | 534 | ||
@@ -580,7 +612,7 @@ impl ToChalk for ProjectionTy { | |||
580 | 612 | ||
581 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::ProjectionTy<Interner> { | 613 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::ProjectionTy<Interner> { |
582 | chalk_ir::ProjectionTy { | 614 | chalk_ir::ProjectionTy { |
583 | associated_ty_id: self.associated_ty.to_chalk(db), | 615 | associated_ty_id: TypeAliasAsAssocType(self.associated_ty).to_chalk(db), |
584 | substitution: self.parameters.to_chalk(db), | 616 | substitution: self.parameters.to_chalk(db), |
585 | } | 617 | } |
586 | } | 618 | } |
@@ -590,7 +622,11 @@ impl ToChalk for ProjectionTy { | |||
590 | projection_ty: chalk_ir::ProjectionTy<Interner>, | 622 | projection_ty: chalk_ir::ProjectionTy<Interner>, |
591 | ) -> ProjectionTy { | 623 | ) -> ProjectionTy { |
592 | ProjectionTy { | 624 | ProjectionTy { |
593 | associated_ty: from_chalk(db, projection_ty.associated_ty_id), | 625 | associated_ty: from_chalk::<TypeAliasAsAssocType, _>( |
626 | db, | ||
627 | projection_ty.associated_ty_id, | ||
628 | ) | ||
629 | .0, | ||
594 | parameters: from_chalk(db, projection_ty.substitution), | 630 | parameters: from_chalk(db, projection_ty.substitution), |
595 | } | 631 | } |
596 | } | 632 | } |
@@ -789,7 +825,8 @@ pub(super) fn generic_predicate_to_inline_bound( | |||
789 | let alias_eq_bound = rust_ir::AliasEqBound { | 825 | let alias_eq_bound = rust_ir::AliasEqBound { |
790 | value: proj.ty.clone().to_chalk(db), | 826 | value: proj.ty.clone().to_chalk(db), |
791 | trait_bound: rust_ir::TraitBound { trait_id: trait_.to_chalk(db), args_no_self }, | 827 | trait_bound: rust_ir::TraitBound { trait_id: trait_.to_chalk(db), args_no_self }, |
792 | associated_ty_id: proj.projection_ty.associated_ty.to_chalk(db), | 828 | associated_ty_id: TypeAliasAsAssocType(proj.projection_ty.associated_ty) |
829 | .to_chalk(db), | ||
793 | parameters: Vec::new(), // FIXME we don't support generic associated types yet | 830 | parameters: Vec::new(), // FIXME we don't support generic associated types yet |
794 | }; | 831 | }; |
795 | Some(rust_ir::InlineBound::AliasEqBound(alias_eq_bound)) | 832 | Some(rust_ir::InlineBound::AliasEqBound(alias_eq_bound)) |
diff --git a/crates/hir_ty/src/traits/chalk/tls.rs b/crates/hir_ty/src/traits/chalk/tls.rs index db915625c..b4568cff6 100644 --- a/crates/hir_ty/src/traits/chalk/tls.rs +++ b/crates/hir_ty/src/traits/chalk/tls.rs | |||
@@ -4,7 +4,7 @@ use std::fmt; | |||
4 | use chalk_ir::{AliasTy, GenericArg, Goal, Goals, Lifetime, ProgramClauseImplication, TypeName}; | 4 | use chalk_ir::{AliasTy, GenericArg, Goal, Goals, Lifetime, ProgramClauseImplication, TypeName}; |
5 | use itertools::Itertools; | 5 | use itertools::Itertools; |
6 | 6 | ||
7 | use super::{from_chalk, Interner}; | 7 | use super::{from_chalk, Interner, TypeAliasAsAssocType}; |
8 | use crate::{db::HirDatabase, CallableDefId, TypeCtor}; | 8 | use crate::{db::HirDatabase, CallableDefId, TypeCtor}; |
9 | use hir_def::{AdtId, AssocContainerId, DefWithBodyId, Lookup, TypeAliasId}; | 9 | use hir_def::{AdtId, AssocContainerId, DefWithBodyId, Lookup, TypeAliasId}; |
10 | 10 | ||
@@ -73,7 +73,14 @@ impl DebugContext<'_> { | |||
73 | crate::OpaqueTyId::ReturnTypeImplTrait(func, idx) => { | 73 | crate::OpaqueTyId::ReturnTypeImplTrait(func, idx) => { |
74 | write!(f, "{{impl trait {} of {:?}}}", idx, func)?; | 74 | write!(f, "{{impl trait {} of {:?}}}", idx, func)?; |
75 | } | 75 | } |
76 | crate::OpaqueTyId::AsyncBlockTypeImplTrait(def, idx) => { | ||
77 | write!(f, "{{impl trait of async block {} of {:?}}}", idx.into_raw(), def)?; | ||
78 | } | ||
76 | }, | 79 | }, |
80 | TypeCtor::ForeignType(type_alias) => { | ||
81 | let name = self.0.type_alias_data(type_alias).name.clone(); | ||
82 | write!(f, "{}", name)?; | ||
83 | } | ||
77 | TypeCtor::Closure { def, expr } => { | 84 | TypeCtor::Closure { def, expr } => { |
78 | write!(f, "{{closure {:?} in ", expr.into_raw())?; | 85 | write!(f, "{{closure {:?} in ", expr.into_raw())?; |
79 | match def { | 86 | match def { |
@@ -116,7 +123,7 @@ impl DebugContext<'_> { | |||
116 | id: super::AssocTypeId, | 123 | id: super::AssocTypeId, |
117 | fmt: &mut fmt::Formatter<'_>, | 124 | fmt: &mut fmt::Formatter<'_>, |
118 | ) -> Result<(), fmt::Error> { | 125 | ) -> Result<(), fmt::Error> { |
119 | let type_alias: TypeAliasId = from_chalk(self.0, id); | 126 | let type_alias: TypeAliasId = from_chalk::<TypeAliasAsAssocType, _>(self.0, id).0; |
120 | let type_alias_data = self.0.type_alias_data(type_alias); | 127 | let type_alias_data = self.0.type_alias_data(type_alias); |
121 | let trait_ = match type_alias.lookup(self.0.upcast()).container { | 128 | let trait_ = match type_alias.lookup(self.0.upcast()).container { |
122 | AssocContainerId::TraitId(t) => t, | 129 | AssocContainerId::TraitId(t) => t, |
@@ -150,7 +157,8 @@ impl DebugContext<'_> { | |||
150 | projection_ty: &chalk_ir::ProjectionTy<Interner>, | 157 | projection_ty: &chalk_ir::ProjectionTy<Interner>, |
151 | fmt: &mut fmt::Formatter<'_>, | 158 | fmt: &mut fmt::Formatter<'_>, |
152 | ) -> Result<(), fmt::Error> { | 159 | ) -> Result<(), fmt::Error> { |
153 | let type_alias: TypeAliasId = from_chalk(self.0, projection_ty.associated_ty_id); | 160 | let type_alias: TypeAliasId = |
161 | from_chalk::<TypeAliasAsAssocType, _>(self.0, projection_ty.associated_ty_id).0; | ||
154 | let type_alias_data = self.0.type_alias_data(type_alias); | 162 | let type_alias_data = self.0.type_alias_data(type_alias); |
155 | let trait_ = match type_alias.lookup(self.0.upcast()).container { | 163 | let trait_ = match type_alias.lookup(self.0.upcast()).container { |
156 | AssocContainerId::TraitId(t) => t, | 164 | AssocContainerId::TraitId(t) => t, |
diff --git a/crates/ide/src/completion/complete_keyword.rs b/crates/ide/src/completion/complete_keyword.rs index 53ba76e0e..5645b41fa 100644 --- a/crates/ide/src/completion/complete_keyword.rs +++ b/crates/ide/src/completion/complete_keyword.rs | |||
@@ -510,6 +510,28 @@ pub mod future { | |||
510 | expect![[r#" | 510 | expect![[r#" |
511 | kw await expr.await | 511 | kw await expr.await |
512 | "#]], | 512 | "#]], |
513 | ); | ||
514 | |||
515 | check( | ||
516 | r#" | ||
517 | //- /main.rs | ||
518 | use std::future::*; | ||
519 | fn foo() { | ||
520 | let a = async {}; | ||
521 | a.<|> | ||
522 | } | ||
523 | |||
524 | //- /std/lib.rs | ||
525 | pub mod future { | ||
526 | #[lang = "future_trait"] | ||
527 | pub trait Future { | ||
528 | type Output; | ||
529 | } | ||
530 | } | ||
531 | "#, | ||
532 | expect![[r#" | ||
533 | kw await expr.await | ||
534 | "#]], | ||
513 | ) | 535 | ) |
514 | } | 536 | } |
515 | 537 | ||
diff --git a/crates/ide/src/completion/complete_qualified_path.rs b/crates/ide/src/completion/complete_qualified_path.rs index 79de50792..00e89f0fd 100644 --- a/crates/ide/src/completion/complete_qualified_path.rs +++ b/crates/ide/src/completion/complete_qualified_path.rs | |||
@@ -730,4 +730,26 @@ fn f() {} | |||
730 | expect![[""]], | 730 | expect![[""]], |
731 | ); | 731 | ); |
732 | } | 732 | } |
733 | |||
734 | #[test] | ||
735 | fn completes_function() { | ||
736 | check( | ||
737 | r#" | ||
738 | fn foo( | ||
739 | a: i32, | ||
740 | b: i32 | ||
741 | ) { | ||
742 | |||
743 | } | ||
744 | |||
745 | fn main() { | ||
746 | fo<|> | ||
747 | } | ||
748 | "#, | ||
749 | expect![[r#" | ||
750 | fn foo(…) fn foo(a: i32, b: i32) | ||
751 | fn main() fn main() | ||
752 | "#]], | ||
753 | ); | ||
754 | } | ||
733 | } | 755 | } |
diff --git a/crates/ide/src/completion/complete_trait_impl.rs b/crates/ide/src/completion/complete_trait_impl.rs index 26f268bd1..ff115df92 100644 --- a/crates/ide/src/completion/complete_trait_impl.rs +++ b/crates/ide/src/completion/complete_trait_impl.rs | |||
@@ -46,76 +46,86 @@ use crate::{ | |||
46 | display::function_declaration, | 46 | display::function_declaration, |
47 | }; | 47 | }; |
48 | 48 | ||
49 | #[derive(Debug, PartialEq, Eq)] | ||
50 | enum ImplCompletionKind { | ||
51 | All, | ||
52 | Fn, | ||
53 | TypeAlias, | ||
54 | Const, | ||
55 | } | ||
56 | |||
49 | pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) { | 57 | pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) { |
50 | if let Some((trigger, impl_def)) = completion_match(ctx) { | 58 | if let Some((kind, trigger, impl_def)) = completion_match(ctx) { |
51 | match trigger.kind() { | 59 | get_missing_assoc_items(&ctx.sema, &impl_def).into_iter().for_each(|item| match item { |
52 | SyntaxKind::NAME_REF => get_missing_assoc_items(&ctx.sema, &impl_def) | 60 | hir::AssocItem::Function(fn_item) |
53 | .into_iter() | 61 | if kind == ImplCompletionKind::All || kind == ImplCompletionKind::Fn => |
54 | .for_each(|item| match item { | 62 | { |
55 | hir::AssocItem::Function(fn_item) => { | 63 | add_function_impl(&trigger, acc, ctx, fn_item) |
56 | add_function_impl(&trigger, acc, ctx, fn_item) | ||
57 | } | ||
58 | hir::AssocItem::TypeAlias(type_item) => { | ||
59 | add_type_alias_impl(&trigger, acc, ctx, type_item) | ||
60 | } | ||
61 | hir::AssocItem::Const(const_item) => { | ||
62 | add_const_impl(&trigger, acc, ctx, const_item) | ||
63 | } | ||
64 | }), | ||
65 | |||
66 | SyntaxKind::FN => { | ||
67 | for missing_fn in get_missing_assoc_items(&ctx.sema, &impl_def) | ||
68 | .into_iter() | ||
69 | .filter_map(|item| match item { | ||
70 | hir::AssocItem::Function(fn_item) => Some(fn_item), | ||
71 | _ => None, | ||
72 | }) | ||
73 | { | ||
74 | add_function_impl(&trigger, acc, ctx, missing_fn); | ||
75 | } | ||
76 | } | 64 | } |
77 | 65 | hir::AssocItem::TypeAlias(type_item) | |
78 | SyntaxKind::TYPE_ALIAS => { | 66 | if kind == ImplCompletionKind::All || kind == ImplCompletionKind::TypeAlias => |
79 | for missing_fn in get_missing_assoc_items(&ctx.sema, &impl_def) | 67 | { |
80 | .into_iter() | 68 | add_type_alias_impl(&trigger, acc, ctx, type_item) |
81 | .filter_map(|item| match item { | ||
82 | hir::AssocItem::TypeAlias(type_item) => Some(type_item), | ||
83 | _ => None, | ||
84 | }) | ||
85 | { | ||
86 | add_type_alias_impl(&trigger, acc, ctx, missing_fn); | ||
87 | } | ||
88 | } | 69 | } |
89 | 70 | hir::AssocItem::Const(const_item) | |
90 | SyntaxKind::CONST => { | 71 | if kind == ImplCompletionKind::All || kind == ImplCompletionKind::Const => |
91 | for missing_fn in get_missing_assoc_items(&ctx.sema, &impl_def) | 72 | { |
92 | .into_iter() | 73 | add_const_impl(&trigger, acc, ctx, const_item) |
93 | .filter_map(|item| match item { | ||
94 | hir::AssocItem::Const(const_item) => Some(const_item), | ||
95 | _ => None, | ||
96 | }) | ||
97 | { | ||
98 | add_const_impl(&trigger, acc, ctx, missing_fn); | ||
99 | } | ||
100 | } | 74 | } |
101 | |||
102 | _ => {} | 75 | _ => {} |
103 | } | 76 | }); |
104 | } | 77 | } |
105 | } | 78 | } |
106 | 79 | ||
107 | fn completion_match(ctx: &CompletionContext) -> Option<(SyntaxNode, Impl)> { | 80 | fn completion_match(ctx: &CompletionContext) -> Option<(ImplCompletionKind, SyntaxNode, Impl)> { |
108 | let (trigger, impl_def_offset) = ctx.token.ancestors().find_map(|p| match p.kind() { | 81 | let mut token = ctx.token.clone(); |
109 | SyntaxKind::FN | SyntaxKind::TYPE_ALIAS | SyntaxKind::CONST | SyntaxKind::BLOCK_EXPR => { | 82 | // For keywork without name like `impl .. { fn <|> }`, the current position is inside |
110 | Some((p, 2)) | 83 | // the whitespace token, which is outside `FN` syntax node. |
111 | } | 84 | // We need to follow the previous token in this case. |
112 | SyntaxKind::NAME_REF => Some((p, 5)), | 85 | if token.kind() == SyntaxKind::WHITESPACE { |
113 | _ => None, | 86 | token = token.prev_token()?; |
114 | })?; | 87 | } |
115 | let impl_def = (0..impl_def_offset - 1) | 88 | |
116 | .try_fold(trigger.parent()?, |t, _| t.parent()) | 89 | let impl_item_offset = match token.kind() { |
117 | .and_then(ast::Impl::cast)?; | 90 | // `impl .. { const <|> }` |
118 | Some((trigger, impl_def)) | 91 | // ERROR 0 |
92 | // CONST_KW <- * | ||
93 | SyntaxKind::CONST_KW => 0, | ||
94 | // `impl .. { fn/type <|> }` | ||
95 | // FN/TYPE_ALIAS 0 | ||
96 | // FN_KW <- * | ||
97 | SyntaxKind::FN_KW | SyntaxKind::TYPE_KW => 0, | ||
98 | // `impl .. { fn/type/const foo<|> }` | ||
99 | // FN/TYPE_ALIAS/CONST 1 | ||
100 | // NAME 0 | ||
101 | // IDENT <- * | ||
102 | SyntaxKind::IDENT if token.parent().kind() == SyntaxKind::NAME => 1, | ||
103 | // `impl .. { foo<|> }` | ||
104 | // MACRO_CALL 3 | ||
105 | // PATH 2 | ||
106 | // PATH_SEGMENT 1 | ||
107 | // NAME_REF 0 | ||
108 | // IDENT <- * | ||
109 | SyntaxKind::IDENT if token.parent().kind() == SyntaxKind::NAME_REF => 3, | ||
110 | _ => return None, | ||
111 | }; | ||
112 | |||
113 | let impl_item = token.ancestors().nth(impl_item_offset)?; | ||
114 | // Must directly belong to an impl block. | ||
115 | // IMPL | ||
116 | // ASSOC_ITEM_LIST | ||
117 | // <item> | ||
118 | let impl_def = ast::Impl::cast(impl_item.parent()?.parent()?)?; | ||
119 | let kind = match impl_item.kind() { | ||
120 | // `impl ... { const <|> fn/type/const }` | ||
121 | _ if token.kind() == SyntaxKind::CONST_KW => ImplCompletionKind::Const, | ||
122 | SyntaxKind::CONST | SyntaxKind::ERROR => ImplCompletionKind::Const, | ||
123 | SyntaxKind::TYPE_ALIAS => ImplCompletionKind::TypeAlias, | ||
124 | SyntaxKind::FN => ImplCompletionKind::Fn, | ||
125 | SyntaxKind::MACRO_CALL => ImplCompletionKind::All, | ||
126 | _ => return None, | ||
127 | }; | ||
128 | Some((kind, impl_item, impl_def)) | ||
119 | } | 129 | } |
120 | 130 | ||
121 | fn add_function_impl( | 131 | fn add_function_impl( |
@@ -261,19 +271,191 @@ ta type TestType = \n\ | |||
261 | } | 271 | } |
262 | 272 | ||
263 | #[test] | 273 | #[test] |
264 | fn no_nested_fn_completions() { | 274 | fn no_completion_inside_fn() { |
265 | check( | 275 | check( |
266 | r" | 276 | r" |
267 | trait Test { | 277 | trait Test { fn test(); fn test2(); } |
268 | fn test(); | 278 | struct T; |
269 | fn test2(); | 279 | |
280 | impl Test for T { | ||
281 | fn test() { | ||
282 | t<|> | ||
283 | } | ||
284 | } | ||
285 | ", | ||
286 | expect![[""]], | ||
287 | ); | ||
288 | |||
289 | check( | ||
290 | r" | ||
291 | trait Test { fn test(); fn test2(); } | ||
292 | struct T; | ||
293 | |||
294 | impl Test for T { | ||
295 | fn test() { | ||
296 | fn t<|> | ||
297 | } | ||
298 | } | ||
299 | ", | ||
300 | expect![[""]], | ||
301 | ); | ||
302 | |||
303 | check( | ||
304 | r" | ||
305 | trait Test { fn test(); fn test2(); } | ||
306 | struct T; | ||
307 | |||
308 | impl Test for T { | ||
309 | fn test() { | ||
310 | fn <|> | ||
311 | } | ||
270 | } | 312 | } |
313 | ", | ||
314 | expect![[""]], | ||
315 | ); | ||
316 | |||
317 | // https://github.com/rust-analyzer/rust-analyzer/pull/5976#issuecomment-692332191 | ||
318 | check( | ||
319 | r" | ||
320 | trait Test { fn test(); fn test2(); } | ||
271 | struct T; | 321 | struct T; |
272 | 322 | ||
273 | impl Test for T { | 323 | impl Test for T { |
274 | fn test() { | 324 | fn test() { |
325 | foo.<|> | ||
326 | } | ||
327 | } | ||
328 | ", | ||
329 | expect![[""]], | ||
330 | ); | ||
331 | |||
332 | check( | ||
333 | r" | ||
334 | trait Test { fn test(_: i32); fn test2(); } | ||
335 | struct T; | ||
336 | |||
337 | impl Test for T { | ||
338 | fn test(t<|>) | ||
339 | } | ||
340 | ", | ||
341 | expect![[""]], | ||
342 | ); | ||
343 | |||
344 | check( | ||
345 | r" | ||
346 | trait Test { fn test(_: fn()); fn test2(); } | ||
347 | struct T; | ||
348 | |||
349 | impl Test for T { | ||
350 | fn test(f: fn <|>) | ||
351 | } | ||
352 | ", | ||
353 | expect![[""]], | ||
354 | ); | ||
355 | } | ||
356 | |||
357 | #[test] | ||
358 | fn no_completion_inside_const() { | ||
359 | check( | ||
360 | r" | ||
361 | trait Test { const TEST: fn(); const TEST2: u32; type Test; fn test(); } | ||
362 | struct T; | ||
363 | |||
364 | impl Test for T { | ||
365 | const TEST: fn <|> | ||
366 | } | ||
367 | ", | ||
368 | expect![[""]], | ||
369 | ); | ||
370 | |||
371 | check( | ||
372 | r" | ||
373 | trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); } | ||
374 | struct T; | ||
375 | |||
376 | impl Test for T { | ||
377 | const TEST: T<|> | ||
378 | } | ||
379 | ", | ||
380 | expect![[""]], | ||
381 | ); | ||
382 | |||
383 | check( | ||
384 | r" | ||
385 | trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); } | ||
386 | struct T; | ||
387 | |||
388 | impl Test for T { | ||
389 | const TEST: u32 = f<|> | ||
390 | } | ||
391 | ", | ||
392 | expect![[""]], | ||
393 | ); | ||
394 | |||
395 | check( | ||
396 | r" | ||
397 | trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); } | ||
398 | struct T; | ||
399 | |||
400 | impl Test for T { | ||
401 | const TEST: u32 = { | ||
275 | t<|> | 402 | t<|> |
403 | }; | ||
404 | } | ||
405 | ", | ||
406 | expect![[""]], | ||
407 | ); | ||
408 | |||
409 | check( | ||
410 | r" | ||
411 | trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); } | ||
412 | struct T; | ||
413 | |||
414 | impl Test for T { | ||
415 | const TEST: u32 = { | ||
416 | fn <|> | ||
417 | }; | ||
418 | } | ||
419 | ", | ||
420 | expect![[""]], | ||
421 | ); | ||
422 | |||
423 | check( | ||
424 | r" | ||
425 | trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); } | ||
426 | struct T; | ||
427 | |||
428 | impl Test for T { | ||
429 | const TEST: u32 = { | ||
430 | fn t<|> | ||
431 | }; | ||
432 | } | ||
433 | ", | ||
434 | expect![[""]], | ||
435 | ); | ||
276 | } | 436 | } |
437 | |||
438 | #[test] | ||
439 | fn no_completion_inside_type() { | ||
440 | check( | ||
441 | r" | ||
442 | trait Test { type Test; type Test2; fn test(); } | ||
443 | struct T; | ||
444 | |||
445 | impl Test for T { | ||
446 | type Test = T<|>; | ||
447 | } | ||
448 | ", | ||
449 | expect![[""]], | ||
450 | ); | ||
451 | |||
452 | check( | ||
453 | r" | ||
454 | trait Test { type Test; type Test2; fn test(); } | ||
455 | struct T; | ||
456 | |||
457 | impl Test for T { | ||
458 | type Test = fn <|>; | ||
277 | } | 459 | } |
278 | ", | 460 | ", |
279 | expect![[""]], | 461 | expect![[""]], |
@@ -485,4 +667,67 @@ impl Test for () { | |||
485 | ", | 667 | ", |
486 | ); | 668 | ); |
487 | } | 669 | } |
670 | |||
671 | #[test] | ||
672 | fn complete_without_name() { | ||
673 | let test = |completion: &str, hint: &str, completed: &str, next_sibling: &str| { | ||
674 | println!( | ||
675 | "completion='{}', hint='{}', next_sibling='{}'", | ||
676 | completion, hint, next_sibling | ||
677 | ); | ||
678 | |||
679 | check_edit( | ||
680 | completion, | ||
681 | &format!( | ||
682 | r#" | ||
683 | trait Test {{ | ||
684 | type Foo; | ||
685 | const CONST: u16; | ||
686 | fn bar(); | ||
687 | }} | ||
688 | struct T; | ||
689 | |||
690 | impl Test for T {{ | ||
691 | {} | ||
692 | {} | ||
693 | }} | ||
694 | "#, | ||
695 | hint, next_sibling | ||
696 | ), | ||
697 | &format!( | ||
698 | r#" | ||
699 | trait Test {{ | ||
700 | type Foo; | ||
701 | const CONST: u16; | ||
702 | fn bar(); | ||
703 | }} | ||
704 | struct T; | ||
705 | |||
706 | impl Test for T {{ | ||
707 | {} | ||
708 | {} | ||
709 | }} | ||
710 | "#, | ||
711 | completed, next_sibling | ||
712 | ), | ||
713 | ) | ||
714 | }; | ||
715 | |||
716 | // Enumerate some possible next siblings. | ||
717 | for next_sibling in &[ | ||
718 | "", | ||
719 | "fn other_fn() {}", // `const <|> fn` -> `const fn` | ||
720 | "type OtherType = i32;", | ||
721 | "const OTHER_CONST: i32 = 0;", | ||
722 | "async fn other_fn() {}", | ||
723 | "unsafe fn other_fn() {}", | ||
724 | "default fn other_fn() {}", | ||
725 | "default type OtherType = i32;", | ||
726 | "default const OTHER_CONST: i32 = 0;", | ||
727 | ] { | ||
728 | test("bar", "fn <|>", "fn bar() {\n $0\n}", next_sibling); | ||
729 | test("Foo", "type <|>", "type Foo = ", next_sibling); | ||
730 | test("CONST", "const <|>", "const CONST: u16 = ", next_sibling); | ||
731 | } | ||
732 | } | ||
488 | } | 733 | } |
diff --git a/crates/ide/src/display.rs b/crates/ide/src/display.rs index 41b5bdc49..2484dbbf1 100644 --- a/crates/ide/src/display.rs +++ b/crates/ide/src/display.rs | |||
@@ -41,7 +41,14 @@ pub(crate) fn function_declaration(node: &ast::Fn) -> String { | |||
41 | format_to!(buf, "{}", type_params); | 41 | format_to!(buf, "{}", type_params); |
42 | } | 42 | } |
43 | if let Some(param_list) = node.param_list() { | 43 | if let Some(param_list) = node.param_list() { |
44 | format_to!(buf, "{}", param_list); | 44 | let params: Vec<String> = param_list |
45 | .self_param() | ||
46 | .into_iter() | ||
47 | .map(|self_param| self_param.to_string()) | ||
48 | .chain(param_list.params().map(|param| param.to_string())) | ||
49 | .collect(); | ||
50 | // Useful to inline parameters | ||
51 | format_to!(buf, "({})", params.join(", ")); | ||
45 | } | 52 | } |
46 | if let Some(ret_type) = node.ret_type() { | 53 | if let Some(ret_type) = node.ret_type() { |
47 | if ret_type.ty().is_some() { | 54 | if ret_type.ty().is_some() { |
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index efec0184e..37171cbef 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs | |||
@@ -2647,6 +2647,70 @@ fn foo(ar<|>g: &impl Foo + Bar<S>) {} | |||
2647 | } | 2647 | } |
2648 | 2648 | ||
2649 | #[test] | 2649 | #[test] |
2650 | fn test_hover_async_block_impl_trait_has_goto_type_action() { | ||
2651 | check_actions( | ||
2652 | r#" | ||
2653 | struct S; | ||
2654 | fn foo() { | ||
2655 | let fo<|>o = async { S }; | ||
2656 | } | ||
2657 | |||
2658 | #[prelude_import] use future::*; | ||
2659 | mod future { | ||
2660 | #[lang = "future_trait"] | ||
2661 | pub trait Future { type Output; } | ||
2662 | } | ||
2663 | "#, | ||
2664 | expect![[r#" | ||
2665 | [ | ||
2666 | GoToType( | ||
2667 | [ | ||
2668 | HoverGotoTypeData { | ||
2669 | mod_path: "test::future::Future", | ||
2670 | nav: NavigationTarget { | ||
2671 | file_id: FileId( | ||
2672 | 1, | ||
2673 | ), | ||
2674 | full_range: 101..163, | ||
2675 | focus_range: Some( | ||
2676 | 140..146, | ||
2677 | ), | ||
2678 | name: "Future", | ||
2679 | kind: TRAIT, | ||
2680 | container_name: None, | ||
2681 | description: Some( | ||
2682 | "pub trait Future", | ||
2683 | ), | ||
2684 | docs: None, | ||
2685 | }, | ||
2686 | }, | ||
2687 | HoverGotoTypeData { | ||
2688 | mod_path: "test::S", | ||
2689 | nav: NavigationTarget { | ||
2690 | file_id: FileId( | ||
2691 | 1, | ||
2692 | ), | ||
2693 | full_range: 0..9, | ||
2694 | focus_range: Some( | ||
2695 | 7..8, | ||
2696 | ), | ||
2697 | name: "S", | ||
2698 | kind: STRUCT, | ||
2699 | container_name: None, | ||
2700 | description: Some( | ||
2701 | "struct S", | ||
2702 | ), | ||
2703 | docs: None, | ||
2704 | }, | ||
2705 | }, | ||
2706 | ], | ||
2707 | ), | ||
2708 | ] | ||
2709 | "#]], | ||
2710 | ); | ||
2711 | } | ||
2712 | |||
2713 | #[test] | ||
2650 | fn test_hover_arg_generic_impl_trait_has_goto_type_action() { | 2714 | fn test_hover_arg_generic_impl_trait_has_goto_type_action() { |
2651 | check_actions( | 2715 | check_actions( |
2652 | r#" | 2716 | r#" |
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 570790384..3b97e087f 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs | |||
@@ -81,7 +81,9 @@ pub use crate::{ | |||
81 | }, | 81 | }, |
82 | }; | 82 | }; |
83 | 83 | ||
84 | pub use assists::{Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist}; | 84 | pub use assists::{ |
85 | utils::MergeBehaviour, Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist, | ||
86 | }; | ||
85 | pub use base_db::{ | 87 | pub use base_db::{ |
86 | Canceled, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRoot, | 88 | Canceled, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRoot, |
87 | SourceRootId, | 89 | SourceRootId, |
diff --git a/crates/project_model/src/project_json.rs b/crates/project_model/src/project_json.rs index 979e90058..545f254aa 100644 --- a/crates/project_model/src/project_json.rs +++ b/crates/project_model/src/project_json.rs | |||
@@ -13,6 +13,7 @@ use crate::cfg_flag::CfgFlag; | |||
13 | #[derive(Clone, Debug, Eq, PartialEq)] | 13 | #[derive(Clone, Debug, Eq, PartialEq)] |
14 | pub struct ProjectJson { | 14 | pub struct ProjectJson { |
15 | pub(crate) sysroot_src: Option<AbsPathBuf>, | 15 | pub(crate) sysroot_src: Option<AbsPathBuf>, |
16 | project_root: Option<AbsPathBuf>, | ||
16 | crates: Vec<Crate>, | 17 | crates: Vec<Crate>, |
17 | } | 18 | } |
18 | 19 | ||
@@ -36,6 +37,7 @@ impl ProjectJson { | |||
36 | pub fn new(base: &AbsPath, data: ProjectJsonData) -> ProjectJson { | 37 | pub fn new(base: &AbsPath, data: ProjectJsonData) -> ProjectJson { |
37 | ProjectJson { | 38 | ProjectJson { |
38 | sysroot_src: data.sysroot_src.map(|it| base.join(it)), | 39 | sysroot_src: data.sysroot_src.map(|it| base.join(it)), |
40 | project_root: base.parent().map(AbsPath::to_path_buf), | ||
39 | crates: data | 41 | crates: data |
40 | .crates | 42 | .crates |
41 | .into_iter() | 43 | .into_iter() |
@@ -89,6 +91,12 @@ impl ProjectJson { | |||
89 | pub fn crates(&self) -> impl Iterator<Item = (CrateId, &Crate)> + '_ { | 91 | pub fn crates(&self) -> impl Iterator<Item = (CrateId, &Crate)> + '_ { |
90 | self.crates.iter().enumerate().map(|(idx, krate)| (CrateId(idx as u32), krate)) | 92 | self.crates.iter().enumerate().map(|(idx, krate)| (CrateId(idx as u32), krate)) |
91 | } | 93 | } |
94 | pub fn path(&self) -> Option<&AbsPath> { | ||
95 | match &self.project_root { | ||
96 | Some(p) => Some(p.as_path()), | ||
97 | None => None, | ||
98 | } | ||
99 | } | ||
92 | } | 100 | } |
93 | 101 | ||
94 | #[derive(Deserialize)] | 102 | #[derive(Deserialize)] |
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 187273bbc..1a74286f5 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -10,7 +10,10 @@ | |||
10 | use std::{ffi::OsString, path::PathBuf}; | 10 | use std::{ffi::OsString, path::PathBuf}; |
11 | 11 | ||
12 | use flycheck::FlycheckConfig; | 12 | use flycheck::FlycheckConfig; |
13 | use ide::{AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig}; | 13 | use ide::{ |
14 | AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig, | ||
15 | MergeBehaviour, | ||
16 | }; | ||
14 | use lsp_types::ClientCapabilities; | 17 | use lsp_types::ClientCapabilities; |
15 | use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest}; | 18 | use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest}; |
16 | use rustc_hash::FxHashSet; | 19 | use rustc_hash::FxHashSet; |
@@ -263,6 +266,12 @@ impl Config { | |||
263 | self.completion.add_call_parenthesis = data.completion_addCallParenthesis; | 266 | self.completion.add_call_parenthesis = data.completion_addCallParenthesis; |
264 | self.completion.add_call_argument_snippets = data.completion_addCallArgumentSnippets; | 267 | self.completion.add_call_argument_snippets = data.completion_addCallArgumentSnippets; |
265 | 268 | ||
269 | self.assist.insert_use.merge = match data.assist_importMergeBehaviour { | ||
270 | MergeBehaviourDef::None => None, | ||
271 | MergeBehaviourDef::Full => Some(MergeBehaviour::Full), | ||
272 | MergeBehaviourDef::Last => Some(MergeBehaviour::Last), | ||
273 | }; | ||
274 | |||
266 | self.call_info_full = data.callInfo_full; | 275 | self.call_info_full = data.callInfo_full; |
267 | 276 | ||
268 | self.lens = LensConfig { | 277 | self.lens = LensConfig { |
@@ -370,6 +379,14 @@ enum ManifestOrProjectJson { | |||
370 | ProjectJson(ProjectJsonData), | 379 | ProjectJson(ProjectJsonData), |
371 | } | 380 | } |
372 | 381 | ||
382 | #[derive(Deserialize)] | ||
383 | #[serde(rename_all = "lowercase")] | ||
384 | enum MergeBehaviourDef { | ||
385 | None, | ||
386 | Full, | ||
387 | Last, | ||
388 | } | ||
389 | |||
373 | macro_rules! config_data { | 390 | macro_rules! config_data { |
374 | (struct $name:ident { $($field:ident: $ty:ty = $default:expr,)*}) => { | 391 | (struct $name:ident { $($field:ident: $ty:ty = $default:expr,)*}) => { |
375 | #[allow(non_snake_case)] | 392 | #[allow(non_snake_case)] |
@@ -393,6 +410,8 @@ macro_rules! config_data { | |||
393 | 410 | ||
394 | config_data! { | 411 | config_data! { |
395 | struct ConfigData { | 412 | struct ConfigData { |
413 | assist_importMergeBehaviour: MergeBehaviourDef = MergeBehaviourDef::None, | ||
414 | |||
396 | callInfo_full: bool = true, | 415 | callInfo_full: bool = true, |
397 | 416 | ||
398 | cargo_autoreload: bool = true, | 417 | cargo_autoreload: bool = true, |
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index bab6f8a71..b819618cb 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs | |||
@@ -2,7 +2,7 @@ | |||
2 | use std::{mem, sync::Arc}; | 2 | use std::{mem, sync::Arc}; |
3 | 3 | ||
4 | use base_db::{CrateGraph, SourceRoot, VfsPath}; | 4 | use base_db::{CrateGraph, SourceRoot, VfsPath}; |
5 | use flycheck::FlycheckHandle; | 5 | use flycheck::{FlycheckConfig, FlycheckHandle}; |
6 | use ide::AnalysisChange; | 6 | use ide::AnalysisChange; |
7 | use project_model::{ProcMacroClient, ProjectWorkspace}; | 7 | use project_model::{ProcMacroClient, ProjectWorkspace}; |
8 | use vfs::{file_set::FileSetConfig, AbsPath, AbsPathBuf, ChangeKind}; | 8 | use vfs::{file_set::FileSetConfig, AbsPath, AbsPathBuf, ChangeKind}; |
@@ -244,13 +244,17 @@ impl GlobalState { | |||
244 | .iter() | 244 | .iter() |
245 | // FIXME: Figure out the multi-workspace situation | 245 | // FIXME: Figure out the multi-workspace situation |
246 | .find_map(|w| match w { | 246 | .find_map(|w| match w { |
247 | ProjectWorkspace::Cargo { cargo, sysroot: _ } => Some(cargo), | 247 | ProjectWorkspace::Cargo { cargo, sysroot: _ } => Some(cargo.workspace_root()), |
248 | ProjectWorkspace::Json { .. } => None, | 248 | ProjectWorkspace::Json { project, .. } => { |
249 | }) | 249 | // Enable flychecks for json projects if a custom flycheck command was supplied |
250 | .map(move |cargo| { | 250 | // in the workspace configuration. |
251 | let cargo_project_root = cargo.workspace_root().to_path_buf(); | 251 | match config { |
252 | FlycheckHandle::spawn(sender, config, cargo_project_root.into()) | 252 | FlycheckConfig::CustomCommand { .. } => project.path(), |
253 | _ => None, | ||
254 | } | ||
255 | } | ||
253 | }) | 256 | }) |
257 | .map(move |root| FlycheckHandle::spawn(sender, config, root.to_path_buf().into())) | ||
254 | } | 258 | } |
255 | } | 259 | } |
256 | 260 | ||
diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json index 63ba4bdf1..33d60d4dd 100644 --- a/editors/code/package-lock.json +++ b/editors/code/package-lock.json | |||
@@ -1761,9 +1761,9 @@ | |||
1761 | "dev": true | 1761 | "dev": true |
1762 | }, | 1762 | }, |
1763 | "node-fetch": { | 1763 | "node-fetch": { |
1764 | "version": "2.6.0", | 1764 | "version": "2.6.1", |
1765 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", | 1765 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", |
1766 | "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" | 1766 | "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" |
1767 | }, | 1767 | }, |
1768 | "normalize-path": { | 1768 | "normalize-path": { |
1769 | "version": "3.0.0", | 1769 | "version": "3.0.0", |
diff --git a/editors/code/package.json b/editors/code/package.json index 6fc4464df..c57fbdda2 100644 --- a/editors/code/package.json +++ b/editors/code/package.json | |||
@@ -35,7 +35,7 @@ | |||
35 | "test": "node ./out/tests/runTests.js" | 35 | "test": "node ./out/tests/runTests.js" |
36 | }, | 36 | }, |
37 | "dependencies": { | 37 | "dependencies": { |
38 | "node-fetch": "^2.6.0", | 38 | "node-fetch": "^2.6.1", |
39 | "vscode-languageclient": "7.0.0-next.9" | 39 | "vscode-languageclient": "7.0.0-next.9" |
40 | }, | 40 | }, |
41 | "devDependencies": { | 41 | "devDependencies": { |
@@ -626,6 +626,21 @@ | |||
626 | }, | 626 | }, |
627 | "description": "List of warnings that should be displayed with hint severity.\nThe warnings will be indicated by faded text or three dots in code and will not show up in the problems panel.", | 627 | "description": "List of warnings that should be displayed with hint severity.\nThe warnings will be indicated by faded text or three dots in code and will not show up in the problems panel.", |
628 | "default": [] | 628 | "default": [] |
629 | }, | ||
630 | "rust-analyzer.assist.importMergeBehaviour": { | ||
631 | "type": "string", | ||
632 | "enum": [ | ||
633 | "none", | ||
634 | "full", | ||
635 | "last" | ||
636 | ], | ||
637 | "enumDescriptions": [ | ||
638 | "No merging", | ||
639 | "Merge all layers of the import trees", | ||
640 | "Only merge the last layer of the import trees" | ||
641 | ], | ||
642 | "default": "full", | ||
643 | "description": "The strategy to use when inserting new imports or merging imports." | ||
629 | } | 644 | } |
630 | } | 645 | } |
631 | }, | 646 | }, |
@@ -864,6 +879,10 @@ | |||
864 | { | 879 | { |
865 | "id": "unsafe", | 880 | "id": "unsafe", |
866 | "description": "Style for unsafe operations" | 881 | "description": "Style for unsafe operations" |
882 | }, | ||
883 | { | ||
884 | "id": "consuming", | ||
885 | "description": "Style for non-Copy lvalues consumed by method/function call" | ||
867 | } | 886 | } |
868 | ], | 887 | ], |
869 | "semanticTokenScopes": [ | 888 | "semanticTokenScopes": [ |
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts index 69f2836ad..4321de244 100644 --- a/editors/code/src/commands.ts +++ b/editors/code/src/commands.ts | |||
@@ -195,7 +195,7 @@ export function ssr(ctx: Ctx): Cmd { | |||
195 | 195 | ||
196 | const options: vscode.InputBoxOptions = { | 196 | const options: vscode.InputBoxOptions = { |
197 | value: "() ==>> ()", | 197 | value: "() ==>> ()", |
198 | prompt: "Enter request, for example 'Foo($a) ==> Foo::new($a)' ", | 198 | prompt: "Enter request, for example 'Foo($a) ==>> Foo::new($a)' ", |
199 | validateInput: async (x: string) => { | 199 | validateInput: async (x: string) => { |
200 | try { | 200 | try { |
201 | await client.sendRequest(ra.ssr, { | 201 | await client.sendRequest(ra.ssr, { |
diff --git a/xtask/src/release.rs b/xtask/src/release.rs index 7fa0966aa..3aab29801 100644 --- a/xtask/src/release.rs +++ b/xtask/src/release.rs | |||
@@ -37,7 +37,8 @@ Release: release:{}[] | |||
37 | 37 | ||
38 | == Sponsors | 38 | == Sponsors |
39 | 39 | ||
40 | **Become a sponsor:** https://opencollective.com/rust-analyzer/[opencollective.com/rust-analyzer] | 40 | **Become a sponsor:** On https://opencollective.com/rust-analyzer/[OpenCollective] or |
41 | https://github.com/sponsors/rust-analyzer[GitHub Sponsors]. | ||
41 | 42 | ||
42 | == New Features | 43 | == New Features |
43 | 44 | ||