aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-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
37 files changed, 927 insertions, 184 deletions
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