aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock29
-rw-r--r--crates/assists/src/assist_config.rs20
-rw-r--r--crates/assists/src/handlers/auto_import.rs7
-rw-r--r--crates/assists/src/handlers/extract_struct_from_enum_variant.rs6
-rw-r--r--crates/assists/src/handlers/replace_qualified_name_with_use.rs4
-rw-r--r--crates/assists/src/utils.rs3
-rw-r--r--crates/assists/src/utils/insert_use.rs2
-rw-r--r--crates/hir/src/code_model.rs7
-rw-r--r--crates/hir_def/src/body/lower.rs11
-rw-r--r--crates/hir_def/src/data.rs2
-rw-r--r--crates/hir_def/src/expr.rs7
-rw-r--r--crates/hir_def/src/item_tree.rs1
-rw-r--r--crates/hir_def/src/item_tree/lower.rs6
-rw-r--r--crates/hir_def/src/item_tree/tests.rs2
-rw-r--r--crates/hir_ty/Cargo.toml6
-rw-r--r--crates/hir_ty/src/display.rs37
-rw-r--r--crates/hir_ty/src/infer/expr.rs11
-rw-r--r--crates/hir_ty/src/infer/pat.rs14
-rw-r--r--crates/hir_ty/src/lib.rs45
-rw-r--r--crates/hir_ty/src/lower.rs10
-rw-r--r--crates/hir_ty/src/method_resolution.rs8
-rw-r--r--crates/hir_ty/src/tests/method_resolution.rs36
-rw-r--r--crates/hir_ty/src/tests/patterns.rs25
-rw-r--r--crates/hir_ty/src/tests/simple.rs45
-rw-r--r--crates/hir_ty/src/tests/traits.rs40
-rw-r--r--crates/hir_ty/src/traits/chalk.rs127
-rw-r--r--crates/hir_ty/src/traits/chalk/interner.rs1
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs69
-rw-r--r--crates/hir_ty/src/traits/chalk/tls.rs14
-rw-r--r--crates/ide/src/completion/complete_keyword.rs22
-rw-r--r--crates/ide/src/completion/complete_qualified_path.rs22
-rw-r--r--crates/ide/src/completion/complete_trait_impl.rs377
-rw-r--r--crates/ide/src/display.rs9
-rw-r--r--crates/ide/src/hover.rs64
-rw-r--r--crates/ide/src/lib.rs4
-rw-r--r--crates/project_model/src/project_json.rs8
-rw-r--r--crates/rust-analyzer/src/config.rs21
-rw-r--r--crates/rust-analyzer/src/reload.rs18
-rw-r--r--editors/code/package-lock.json6
-rw-r--r--editors/code/package.json21
-rw-r--r--editors/code/src/commands.ts2
-rw-r--r--xtask/src/release.rs3
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]]
164name = "chalk-derive" 164name = "chalk-derive"
165version = "0.25.0" 165version = "0.27.0"
166source = "registry+https://github.com/rust-lang/crates.io-index" 166source = "registry+https://github.com/rust-lang/crates.io-index"
167checksum = "624e14d3f029186e6ffd97081ffa082f98ddd5df20655b6f0e8efb83dd8ac8b4" 167checksum = "d5444ff2a211fe2a863e44d16a368c3d8a314d489de21b8eeb6879f14dd5d4a8"
168dependencies = [ 168dependencies = [
169 "proc-macro2", 169 "proc-macro2",
170 "quote", 170 "quote",
@@ -174,9 +174,9 @@ dependencies = [
174 174
175[[package]] 175[[package]]
176name = "chalk-ir" 176name = "chalk-ir"
177version = "0.25.0" 177version = "0.27.0"
178source = "registry+https://github.com/rust-lang/crates.io-index" 178source = "registry+https://github.com/rust-lang/crates.io-index"
179checksum = "118c68eccdda5604af50bbef84c94550f3854f76989cb03c36ffd36cc2ffe958" 179checksum = "e39c3db1dd4abfaa7658faaa62e5fe998a982a592b710bd971fad5b6adfcfdef"
180dependencies = [ 180dependencies = [
181 "chalk-derive", 181 "chalk-derive",
182 "lazy_static", 182 "lazy_static",
@@ -184,9 +184,9 @@ dependencies = [
184 184
185[[package]] 185[[package]]
186name = "chalk-recursive" 186name = "chalk-recursive"
187version = "0.25.0" 187version = "0.27.0"
188source = "registry+https://github.com/rust-lang/crates.io-index" 188source = "registry+https://github.com/rust-lang/crates.io-index"
189checksum = "5130de3065e3cdfd2ab6d7d70b02b917bafbc096f270c9a643c23da249053606" 189checksum = "3bfae328eff80ca54dcd0d731725bbb56136ac21c59261b68f1e5498e056b306"
190dependencies = [ 190dependencies = [
191 "chalk-derive", 191 "chalk-derive",
192 "chalk-ir", 192 "chalk-ir",
@@ -197,9 +197,9 @@ dependencies = [
197 197
198[[package]] 198[[package]]
199name = "chalk-solve" 199name = "chalk-solve"
200version = "0.25.0" 200version = "0.27.0"
201source = "registry+https://github.com/rust-lang/crates.io-index" 201source = "registry+https://github.com/rust-lang/crates.io-index"
202checksum = "45b235a1f568b28707f117b2d30eabbee9cbcfccaa0d6e9697300400c8ca0996" 202checksum = "a673abe3077adc25f8ee0894198aed494a5bb0ce50ee993900d0ee1a44e1948a"
203dependencies = [ 203dependencies = [
204 "chalk-derive", 204 "chalk-derive",
205 "chalk-ir", 205 "chalk-ir",
@@ -857,11 +857,12 @@ dependencies = [
857 857
858[[package]] 858[[package]]
859name = "miniz_oxide" 859name = "miniz_oxide"
860version = "0.4.1" 860version = "0.4.2"
861source = "registry+https://github.com/rust-lang/crates.io-index" 861source = "registry+https://github.com/rust-lang/crates.io-index"
862checksum = "4d7559a8a40d0f97e1edea3220f698f78b1c5ab67532e49f68fde3910323b722" 862checksum = "c60c0dfe32c10b43a144bad8fc83538c52f58302c92300ea7ec7bf7b38d5a7b9"
863dependencies = [ 863dependencies = [
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]]
1661name = "tracing-serde" 1662name = "tracing-serde"
1662version = "0.1.1" 1663version = "0.1.2"
1663source = "registry+https://github.com/rust-lang/crates.io-index" 1664source = "registry+https://github.com/rust-lang/crates.io-index"
1664checksum = "b6ccba2f8f16e0ed268fc765d9b7ff22e965e7185d32f8f1ec8294fe17d86e79" 1665checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b"
1665dependencies = [ 1666dependencies = [
1666 "serde", 1667 "serde",
1667 "tracing-core", 1668 "tracing-core",
@@ -1669,9 +1670,9 @@ dependencies = [
1669 1670
1670[[package]] 1671[[package]]
1671name = "tracing-subscriber" 1672name = "tracing-subscriber"
1672version = "0.2.11" 1673version = "0.2.12"
1673source = "registry+https://github.com/rust-lang/crates.io-index" 1674source = "registry+https://github.com/rust-lang/crates.io-index"
1674checksum = "abd165311cc4d7a555ad11cc77a37756df836182db0d81aac908c8184c584f40" 1675checksum = "82bb5079aa76438620837198db8a5c529fb9878c730bc2b28179b0241cf04c10"
1675dependencies = [ 1676dependencies = [
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
7use crate::AssistKind; 7use crate::{utils::MergeBehaviour, AssistKind};
8 8
9#[derive(Clone, Debug, PartialEq, Eq)] 9#[derive(Clone, Debug, PartialEq, Eq)]
10pub struct AssistConfig { 10pub 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
15impl AssistConfig { 16impl AssistConfig {
@@ -25,6 +26,21 @@ pub struct SnippetCap {
25 26
26impl Default for AssistConfig { 27impl 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)]
38pub struct InsertUseConfig {
39 pub merge: Option<MergeBehaviour>,
40}
41
42impl 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
17use crate::{ 17use 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
12use crate::{ 12use 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};
17use ast::make; 15use ast::make;
18use insert_use::ImportScope; 16use 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
2use test_utils::mark; 2use test_utils::mark;
3 3
4use crate::{ 4use crate::{
5 utils::{insert_use, ImportScope, MergeBehaviour}, 5 utils::{insert_use, ImportScope},
6 AssistContext, AssistId, AssistKind, Assists, 6 AssistContext, AssistId, AssistKind, Assists,
7}; 7};
8use ast::make; 8use 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
17use crate::assist_config::SnippetCap; 17use crate::assist_config::SnippetCap;
18 18
19pub(crate) use insert_use::{insert_use, ImportScope, MergeBehaviour}; 19pub use insert_use::MergeBehaviour;
20pub(crate) use insert_use::{insert_use, ImportScope};
20 21
21pub(crate) fn unwrap_trivial_block(block: ast::BlockExpr) -> ast::Expr { 22pub(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)]
348pub enum MergeBehaviour { 348pub 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
400impl Pat { 404impl 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"
17log = "0.4.8" 17log = "0.4.8"
18rustc-hash = "1.1.0" 18rustc-hash = "1.1.0"
19scoped-tls = "1" 19scoped-tls = "1"
20chalk-solve = { version = "0.25.0" } 20chalk-solve = { version = "0.27.0" }
21chalk-ir = { version = "0.25.0" } 21chalk-ir = { version = "0.27.0" }
22chalk-recursive = { version = "0.25.0" } 22chalk-recursive = { version = "0.27.0" }
23 23
24stdx = { path = "../stdx", version = "0.0.0" } 24stdx = { path = "../stdx", version = "0.0.0" }
25hir_def = { path = "../hir_def", version = "0.0.0" } 25hir_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
24use super::{ 24use 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)]
1066pub enum OpaqueTyId { 1106pub 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]
1056fn 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]
659fn 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() {
1889fn effects_smoke_test() { 1889fn 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]
89fn infer_async_block() {
90 check_types(
91 r#"
92//- /main.rs crate:main deps:core
93async 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
113enum Option<T> { None, Some(T) }
114
115//- /core.rs crate:core
116#[prelude_import] use future::*;
117mod future {
118 #[lang = "future_trait"]
119 trait Future {
120 type Output;
121 }
122}
123
124"#,
125 );
126}
127
128#[test]
89fn infer_try() { 129fn 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};
14use hir_expand::name::name;
14 15
15use super::ChalkContext; 16use super::ChalkContext;
16use crate::{ 17use 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};
23use mapping::{ 25use 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
27pub use self::interner::*; 30pub 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
13pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>; 13pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
14pub type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>; 14pub type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>;
15pub type ForeignDefId = chalk_ir::ForeignDefId<Interner>;
15pub type TraitId = chalk_ir::TraitId<Interner>; 16pub type TraitId = chalk_ir::TraitId<Interner>;
16pub type TraitDatum = chalk_solve::rust_ir::TraitDatum<Interner>; 17pub type TraitDatum = chalk_solve::rust_ir::TraitDatum<Interner>;
17pub type AdtId = chalk_ir::AdtId<Interner>; 18pub 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
491impl ToChalk for TypeAliasId { 507pub struct TypeAliasAsAssocType(pub TypeAliasId);
508
509impl 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
521pub struct TypeAliasAsForeignType(pub TypeAliasId);
522
523impl 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;
4use chalk_ir::{AliasTy, GenericArg, Goal, Goals, Lifetime, ProgramClauseImplication, TypeName}; 4use chalk_ir::{AliasTy, GenericArg, Goal, Goals, Lifetime, ProgramClauseImplication, TypeName};
5use itertools::Itertools; 5use itertools::Itertools;
6 6
7use super::{from_chalk, Interner}; 7use super::{from_chalk, Interner, TypeAliasAsAssocType};
8use crate::{db::HirDatabase, CallableDefId, TypeCtor}; 8use crate::{db::HirDatabase, CallableDefId, TypeCtor};
9use hir_def::{AdtId, AssocContainerId, DefWithBodyId, Lookup, TypeAliasId}; 9use 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
518use std::future::*;
519fn foo() {
520 let a = async {};
521 a.<|>
522}
523
524//- /std/lib.rs
525pub 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#"
738fn foo(
739 a: i32,
740 b: i32
741) {
742
743}
744
745fn 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)]
50enum ImplCompletionKind {
51 All,
52 Fn,
53 TypeAlias,
54 Const,
55}
56
49pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) { 57pub(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
107fn completion_match(ctx: &CompletionContext) -> Option<(SyntaxNode, Impl)> { 80fn 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
121fn add_function_impl( 131fn 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"
267trait Test { 277trait Test { fn test(); fn test2(); }
268 fn test(); 278struct T;
269 fn test2(); 279
280impl Test for T {
281 fn test() {
282 t<|>
283 }
284}
285",
286 expect![[""]],
287 );
288
289 check(
290 r"
291trait Test { fn test(); fn test2(); }
292struct T;
293
294impl Test for T {
295 fn test() {
296 fn t<|>
297 }
298}
299",
300 expect![[""]],
301 );
302
303 check(
304 r"
305trait Test { fn test(); fn test2(); }
306struct T;
307
308impl 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"
320trait Test { fn test(); fn test2(); }
271struct T; 321struct T;
272 322
273impl Test for T { 323impl Test for T {
274 fn test() { 324 fn test() {
325 foo.<|>
326 }
327}
328",
329 expect![[""]],
330 );
331
332 check(
333 r"
334trait Test { fn test(_: i32); fn test2(); }
335struct T;
336
337impl Test for T {
338 fn test(t<|>)
339}
340",
341 expect![[""]],
342 );
343
344 check(
345 r"
346trait Test { fn test(_: fn()); fn test2(); }
347struct T;
348
349impl 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"
361trait Test { const TEST: fn(); const TEST2: u32; type Test; fn test(); }
362struct T;
363
364impl Test for T {
365 const TEST: fn <|>
366}
367",
368 expect![[""]],
369 );
370
371 check(
372 r"
373trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); }
374struct T;
375
376impl Test for T {
377 const TEST: T<|>
378}
379",
380 expect![[""]],
381 );
382
383 check(
384 r"
385trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); }
386struct T;
387
388impl Test for T {
389 const TEST: u32 = f<|>
390}
391",
392 expect![[""]],
393 );
394
395 check(
396 r"
397trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); }
398struct T;
399
400impl Test for T {
401 const TEST: u32 = {
275 t<|> 402 t<|>
403 };
404}
405",
406 expect![[""]],
407 );
408
409 check(
410 r"
411trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); }
412struct T;
413
414impl Test for T {
415 const TEST: u32 = {
416 fn <|>
417 };
418}
419",
420 expect![[""]],
421 );
422
423 check(
424 r"
425trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); }
426struct T;
427
428impl 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"
442trait Test { type Test; type Test2; fn test(); }
443struct T;
444
445impl Test for T {
446 type Test = T<|>;
447}
448",
449 expect![[""]],
450 );
451
452 check(
453 r"
454trait Test { type Test; type Test2; fn test(); }
455struct T;
456
457impl 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#"
683trait Test {{
684 type Foo;
685 const CONST: u16;
686 fn bar();
687}}
688struct T;
689
690impl Test for T {{
691 {}
692 {}
693}}
694"#,
695 hint, next_sibling
696 ),
697 &format!(
698 r#"
699trait Test {{
700 type Foo;
701 const CONST: u16;
702 fn bar();
703}}
704struct T;
705
706impl 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#"
2653struct S;
2654fn foo() {
2655 let fo<|>o = async { S };
2656}
2657
2658#[prelude_import] use future::*;
2659mod 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
84pub use assists::{Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist}; 84pub use assists::{
85 utils::MergeBehaviour, Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist,
86};
85pub use base_db::{ 87pub 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)]
14pub struct ProjectJson { 14pub 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 @@
10use std::{ffi::OsString, path::PathBuf}; 10use std::{ffi::OsString, path::PathBuf};
11 11
12use flycheck::FlycheckConfig; 12use flycheck::FlycheckConfig;
13use ide::{AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig}; 13use ide::{
14 AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig,
15 MergeBehaviour,
16};
14use lsp_types::ClientCapabilities; 17use lsp_types::ClientCapabilities;
15use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest}; 18use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest};
16use rustc_hash::FxHashSet; 19use 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")]
384enum MergeBehaviourDef {
385 None,
386 Full,
387 Last,
388}
389
373macro_rules! config_data { 390macro_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
394config_data! { 411config_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 @@
2use std::{mem, sync::Arc}; 2use std::{mem, sync::Arc};
3 3
4use base_db::{CrateGraph, SourceRoot, VfsPath}; 4use base_db::{CrateGraph, SourceRoot, VfsPath};
5use flycheck::FlycheckHandle; 5use flycheck::{FlycheckConfig, FlycheckHandle};
6use ide::AnalysisChange; 6use ide::AnalysisChange;
7use project_model::{ProcMacroClient, ProjectWorkspace}; 7use project_model::{ProcMacroClient, ProjectWorkspace};
8use vfs::{file_set::FileSetConfig, AbsPath, AbsPathBuf, ChangeKind}; 8use 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
41https://github.com/sponsors/rust-analyzer[GitHub Sponsors].
41 42
42== New Features 43== New Features
43 44