aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock47
-rw-r--r--crates/assists/src/handlers/replace_qualified_name_with_use.rs2
-rw-r--r--crates/completion/src/completions/postfix.rs35
-rw-r--r--crates/completion/src/completions/qualified_path.rs40
-rw-r--r--crates/completion/src/completions/trait_impl.rs2
-rw-r--r--crates/completion/src/render/builder_ext.rs5
-rw-r--r--crates/completion/src/render/function.rs69
-rw-r--r--crates/hir/src/code_model.rs12
-rw-r--r--crates/hir_def/src/body.rs73
-rw-r--r--crates/hir_def/src/body/diagnostics.rs10
-rw-r--r--crates/hir_def/src/body/lower.rs31
-rw-r--r--crates/hir_def/src/data.rs2
-rw-r--r--crates/hir_expand/src/builtin_macro.rs129
-rw-r--r--crates/hir_expand/src/db.rs2
-rw-r--r--crates/hir_expand/src/eager.rs2
-rw-r--r--crates/ide/src/references/rename.rs2
-rw-r--r--crates/ide_db/src/helpers/insert_use.rs11
-rw-r--r--crates/rust-analyzer/Cargo.toml2
-rw-r--r--crates/rust-analyzer/src/semantic_tokens.rs2
-rw-r--r--crates/syntax/Cargo.toml2
20 files changed, 324 insertions, 156 deletions
diff --git a/Cargo.lock b/Cargo.lock
index f50e9edd6..d8838cf2b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -300,7 +300,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
300checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" 300checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"
301dependencies = [ 301dependencies = [
302 "cfg-if 1.0.0", 302 "cfg-if 1.0.0",
303 "crossbeam-utils 0.8.0", 303 "crossbeam-utils 0.8.1",
304] 304]
305 305
306[[package]] 306[[package]]
@@ -311,18 +311,18 @@ checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
311dependencies = [ 311dependencies = [
312 "cfg-if 1.0.0", 312 "cfg-if 1.0.0",
313 "crossbeam-epoch", 313 "crossbeam-epoch",
314 "crossbeam-utils 0.8.0", 314 "crossbeam-utils 0.8.1",
315] 315]
316 316
317[[package]] 317[[package]]
318name = "crossbeam-epoch" 318name = "crossbeam-epoch"
319version = "0.9.0" 319version = "0.9.1"
320source = "registry+https://github.com/rust-lang/crates.io-index" 320source = "registry+https://github.com/rust-lang/crates.io-index"
321checksum = "ec0f606a85340376eef0d6d8fec399e6d4a544d648386c6645eb6d0653b27d9f" 321checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d"
322dependencies = [ 322dependencies = [
323 "cfg-if 1.0.0", 323 "cfg-if 1.0.0",
324 "const_fn", 324 "const_fn",
325 "crossbeam-utils 0.8.0", 325 "crossbeam-utils 0.8.1",
326 "lazy_static", 326 "lazy_static",
327 "memoffset", 327 "memoffset",
328 "scopeguard", 328 "scopeguard",
@@ -341,13 +341,12 @@ dependencies = [
341 341
342[[package]] 342[[package]]
343name = "crossbeam-utils" 343name = "crossbeam-utils"
344version = "0.8.0" 344version = "0.8.1"
345source = "registry+https://github.com/rust-lang/crates.io-index" 345source = "registry+https://github.com/rust-lang/crates.io-index"
346checksum = "ec91540d98355f690a86367e566ecad2e9e579f230230eb7c21398372be73ea5" 346checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
347dependencies = [ 347dependencies = [
348 "autocfg", 348 "autocfg",
349 "cfg-if 1.0.0", 349 "cfg-if 1.0.0",
350 "const_fn",
351 "lazy_static", 350 "lazy_static",
352] 351]
353 352
@@ -865,9 +864,9 @@ dependencies = [
865 864
866[[package]] 865[[package]]
867name = "lsp-types" 866name = "lsp-types"
868version = "0.84.0" 867version = "0.85.0"
869source = "registry+https://github.com/rust-lang/crates.io-index" 868source = "registry+https://github.com/rust-lang/crates.io-index"
870checksum = "3b95be71fe205e44de754185bcf86447b65813ce1ceb298f8d3793ade5fff08d" 869checksum = "857650f3e83fb62f89d15410414e0ed7d0735445020da398d37f65d20a5423b9"
871dependencies = [ 870dependencies = [
872 "base64", 871 "base64",
873 "bitflags", 872 "bitflags",
@@ -929,9 +928,9 @@ dependencies = [
929 928
930[[package]] 929[[package]]
931name = "memoffset" 930name = "memoffset"
932version = "0.5.6" 931version = "0.6.1"
933source = "registry+https://github.com/rust-lang/crates.io-index" 932source = "registry+https://github.com/rust-lang/crates.io-index"
934checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" 933checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87"
935dependencies = [ 934dependencies = [
936 "autocfg", 935 "autocfg",
937] 936]
@@ -988,9 +987,9 @@ dependencies = [
988 987
989[[package]] 988[[package]]
990name = "miow" 989name = "miow"
991version = "0.2.1" 990version = "0.2.2"
992source = "registry+https://github.com/rust-lang/crates.io-index" 991source = "registry+https://github.com/rust-lang/crates.io-index"
993checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" 992checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d"
994dependencies = [ 993dependencies = [
995 "kernel32-sys", 994 "kernel32-sys",
996 "net2", 995 "net2",
@@ -1000,9 +999,9 @@ dependencies = [
1000 999
1001[[package]] 1000[[package]]
1002name = "net2" 1001name = "net2"
1003version = "0.2.35" 1002version = "0.2.36"
1004source = "registry+https://github.com/rust-lang/crates.io-index" 1003source = "registry+https://github.com/rust-lang/crates.io-index"
1005checksum = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853" 1004checksum = "d7cf75f38f16cb05ea017784dc6dbfd354f76c223dba37701734c4f5a9337d02"
1006dependencies = [ 1005dependencies = [
1007 "cfg-if 0.1.10", 1006 "cfg-if 0.1.10",
1008 "libc", 1007 "libc",
@@ -1298,7 +1297,7 @@ checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a"
1298dependencies = [ 1297dependencies = [
1299 "crossbeam-channel 0.5.0", 1298 "crossbeam-channel 0.5.0",
1300 "crossbeam-deque", 1299 "crossbeam-deque",
1301 "crossbeam-utils 0.8.0", 1300 "crossbeam-utils 0.8.1",
1302 "lazy_static", 1301 "lazy_static",
1303 "num_cpus", 1302 "num_cpus",
1304] 1303]
@@ -1396,9 +1395,9 @@ dependencies = [
1396 1395
1397[[package]] 1396[[package]]
1398name = "rustc-ap-rustc_lexer" 1397name = "rustc-ap-rustc_lexer"
1399version = "688.0.0" 1398version = "691.0.0"
1400source = "registry+https://github.com/rust-lang/crates.io-index" 1399source = "registry+https://github.com/rust-lang/crates.io-index"
1401checksum = "ebbdcc99bd015349093fcbae4780fda21416fec5d8843acfb3d1733e130cd4db" 1400checksum = "44bc89d9ca7a78fb82e103b389362c55f03800745f8ba14e068b805cfaf783ec"
1402dependencies = [ 1401dependencies = [
1403 "unicode-xid", 1402 "unicode-xid",
1404] 1403]
@@ -1436,7 +1435,7 @@ version = "0.16.0"
1436source = "registry+https://github.com/rust-lang/crates.io-index" 1435source = "registry+https://github.com/rust-lang/crates.io-index"
1437checksum = "d8fadca2ab5de17acf66d744f4888049ca8f1bb9b8a1ab8afd9d032cc959c5dc" 1436checksum = "d8fadca2ab5de17acf66d744f4888049ca8f1bb9b8a1ab8afd9d032cc959c5dc"
1438dependencies = [ 1437dependencies = [
1439 "crossbeam-utils 0.8.0", 1438 "crossbeam-utils 0.8.1",
1440 "indexmap", 1439 "indexmap",
1441 "lock_api", 1440 "lock_api",
1442 "log", 1441 "log",
@@ -1627,9 +1626,9 @@ version = "0.0.0"
1627 1626
1628[[package]] 1627[[package]]
1629name = "syn" 1628name = "syn"
1630version = "1.0.51" 1629version = "1.0.53"
1631source = "registry+https://github.com/rust-lang/crates.io-index" 1630source = "registry+https://github.com/rust-lang/crates.io-index"
1632checksum = "3b4f34193997d92804d359ed09953e25d5138df6bcc055a71bf68ee89fdf9223" 1631checksum = "8833e20724c24de12bbaba5ad230ea61c3eafb05b881c7c9d3cfe8638b187e68"
1633dependencies = [ 1632dependencies = [
1634 "proc-macro2", 1633 "proc-macro2",
1635 "quote", 1634 "quote",
@@ -1899,9 +1898,9 @@ dependencies = [
1899 1898
1900[[package]] 1899[[package]]
1901name = "unicode-segmentation" 1900name = "unicode-segmentation"
1902version = "1.7.0" 1901version = "1.7.1"
1903source = "registry+https://github.com/rust-lang/crates.io-index" 1902source = "registry+https://github.com/rust-lang/crates.io-index"
1904checksum = "db8716a166f290ff49dabc18b44aa407cb7c6dbe1aa0971b44b8a24b0ca35aae" 1903checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
1905 1904
1906[[package]] 1905[[package]]
1907name = "unicode-xid" 1906name = "unicode-xid"
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 8bdf9eea5..8193e45a8 100644
--- a/crates/assists/src/handlers/replace_qualified_name_with_use.rs
+++ b/crates/assists/src/handlers/replace_qualified_name_with_use.rs
@@ -407,7 +407,7 @@ impl std::fmt::Display<|> for Foo {
407} 407}
408", 408",
409 r" 409 r"
410use std::fmt::{nested::Debug, Display}; 410use std::fmt::{Display, nested::Debug};
411 411
412impl Display for Foo { 412impl Display for Foo {
413} 413}
diff --git a/crates/completion/src/completions/postfix.rs b/crates/completion/src/completions/postfix.rs
index 1785794cc..c8ba63cd3 100644
--- a/crates/completion/src/completions/postfix.rs
+++ b/crates/completion/src/completions/postfix.rs
@@ -5,7 +5,7 @@ mod format_like;
5use ide_db::ty_filter::TryEnum; 5use ide_db::ty_filter::TryEnum;
6use syntax::{ 6use syntax::{
7 ast::{self, AstNode, AstToken}, 7 ast::{self, AstNode, AstToken},
8 SyntaxKind::BLOCK_EXPR, 8 SyntaxKind::{BLOCK_EXPR, EXPR_STMT},
9 TextRange, TextSize, 9 TextRange, TextSize,
10}; 10};
11use text_edit::TextEdit; 11use text_edit::TextEdit;
@@ -221,9 +221,8 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
221 ) 221 )
222 .add_to(acc); 222 .add_to(acc);
223 223
224 let parent_node = dot_receiver.syntax().parent().and_then(|p| p.parent()); 224 if let Some(parent) = dot_receiver.syntax().parent().and_then(|p| p.parent()) {
225 if let Some(parent) = parent_node { 225 if matches!(parent.kind(), BLOCK_EXPR | EXPR_STMT) {
226 if parent.kind() == BLOCK_EXPR {
227 postfix_snippet( 226 postfix_snippet(
228 ctx, 227 ctx,
229 cap, 228 cap,
@@ -390,6 +389,34 @@ fn main() {
390 } 389 }
391 390
392 #[test] 391 #[test]
392 fn let_middle_block() {
393 check(
394 r#"
395fn main() {
396 baz.l<|>
397 res
398}
399"#,
400 expect![[r#"
401 sn box Box::new(expr)
402 sn call function(expr)
403 sn dbg dbg!(expr)
404 sn dbgr dbg!(&expr)
405 sn if if expr {}
406 sn let let
407 sn letm let mut
408 sn match match expr {}
409 sn not !expr
410 sn ok Ok(expr)
411 sn ref &expr
412 sn refm &mut expr
413 sn some Some(expr)
414 sn while while expr {}
415 "#]],
416 );
417 }
418
419 #[test]
393 fn option_iflet() { 420 fn option_iflet() {
394 check_edit( 421 check_edit(
395 "ifl", 422 "ifl",
diff --git a/crates/completion/src/completions/qualified_path.rs b/crates/completion/src/completions/qualified_path.rs
index d9387054d..bc23bea3f 100644
--- a/crates/completion/src/completions/qualified_path.rs
+++ b/crates/completion/src/completions/qualified_path.rs
@@ -353,10 +353,10 @@ impl S {
353fn foo() { let _ = S::<|> } 353fn foo() { let _ = S::<|> }
354"#, 354"#,
355 expect![[r#" 355 expect![[r#"
356 ct C const C: i32 = 42; 356 ct C const C: i32 = 42;
357 ta T type T = i32; 357 ta T type T = i32;
358 fn a() fn a() 358 fn a() fn a()
359 me b() fn b(&self) 359 me b(…) fn b(&self)
360 "#]], 360 "#]],
361 ); 361 );
362 } 362 }
@@ -503,14 +503,14 @@ trait Sub: Super {
503fn foo<T: Sub>() { T::<|> } 503fn foo<T: Sub>() { T::<|> }
504"#, 504"#,
505 expect![[r#" 505 expect![[r#"
506 ct C2 const C2: (); 506 ct C2 const C2: ();
507 ct CONST const CONST: u8; 507 ct CONST const CONST: u8;
508 ta SubTy type SubTy; 508 ta SubTy type SubTy;
509 ta Ty type Ty; 509 ta Ty type Ty;
510 fn func() fn func() 510 fn func() fn func()
511 me method() fn method(&self) 511 me method(…) fn method(&self)
512 fn subfunc() fn subfunc() 512 fn subfunc() fn subfunc()
513 me submethod() fn submethod(&self) 513 me submethod(…) fn submethod(&self)
514 "#]], 514 "#]],
515 ); 515 );
516 } 516 }
@@ -543,14 +543,14 @@ impl<T> Sub for Wrap<T> {
543} 543}
544"#, 544"#,
545 expect![[r#" 545 expect![[r#"
546 ct C2 const C2: () = (); 546 ct C2 const C2: () = ();
547 ct CONST const CONST: u8 = 0; 547 ct CONST const CONST: u8 = 0;
548 ta SubTy type SubTy; 548 ta SubTy type SubTy;
549 ta Ty type Ty; 549 ta Ty type Ty;
550 fn func() fn func() 550 fn func() fn func()
551 me method() fn method(&self) 551 me method(…) fn method(&self)
552 fn subfunc() fn subfunc() 552 fn subfunc() fn subfunc()
553 me submethod() fn submethod(&self) 553 me submethod(…) fn submethod(&self)
554 "#]], 554 "#]],
555 ); 555 );
556 } 556 }
diff --git a/crates/completion/src/completions/trait_impl.rs b/crates/completion/src/completions/trait_impl.rs
index a14be9c73..e2fe44aff 100644
--- a/crates/completion/src/completions/trait_impl.rs
+++ b/crates/completion/src/completions/trait_impl.rs
@@ -139,7 +139,7 @@ fn add_function_impl(
139) { 139) {
140 let fn_name = func.name(ctx.db).to_string(); 140 let fn_name = func.name(ctx.db).to_string();
141 141
142 let label = if func.params(ctx.db).is_empty() { 142 let label = if func.assoc_fn_params(ctx.db).is_empty() {
143 format!("fn {}()", fn_name) 143 format!("fn {}()", fn_name)
144 } else { 144 } else {
145 format!("fn {}(..)", fn_name) 145 format!("fn {}(..)", fn_name)
diff --git a/crates/completion/src/render/builder_ext.rs b/crates/completion/src/render/builder_ext.rs
index 37b0d0459..ce8718bd5 100644
--- a/crates/completion/src/render/builder_ext.rs
+++ b/crates/completion/src/render/builder_ext.rs
@@ -5,6 +5,7 @@ use test_utils::mark;
5 5
6use crate::{item::Builder, CompletionContext}; 6use crate::{item::Builder, CompletionContext};
7 7
8#[derive(Debug)]
8pub(super) enum Params { 9pub(super) enum Params {
9 Named(Vec<String>), 10 Named(Vec<String>),
10 Anonymous(usize), 11 Anonymous(usize),
@@ -24,7 +25,7 @@ impl Params {
24} 25}
25 26
26impl Builder { 27impl Builder {
27 pub(super) fn should_add_parems(&self, ctx: &CompletionContext) -> bool { 28 fn should_add_parens(&self, ctx: &CompletionContext) -> bool {
28 if !ctx.config.add_call_parenthesis { 29 if !ctx.config.add_call_parenthesis {
29 return false; 30 return false;
30 } 31 }
@@ -58,7 +59,7 @@ impl Builder {
58 name: String, 59 name: String,
59 params: Params, 60 params: Params,
60 ) -> Builder { 61 ) -> Builder {
61 if !self.should_add_parems(ctx) { 62 if !self.should_add_parens(ctx) {
62 return self; 63 return self;
63 } 64 }
64 65
diff --git a/crates/completion/src/render/function.rs b/crates/completion/src/render/function.rs
index 542383d7e..00e3eb203 100644
--- a/crates/completion/src/render/function.rs
+++ b/crates/completion/src/render/function.rs
@@ -2,6 +2,7 @@
2 2
3use hir::{HasSource, Type}; 3use hir::{HasSource, Type};
4use syntax::{ast::Fn, display::function_declaration}; 4use syntax::{ast::Fn, display::function_declaration};
5use test_utils::mark;
5 6
6use crate::{ 7use crate::{
7 item::{CompletionItem, CompletionItemKind, CompletionKind, ImportToAdd}, 8 item::{CompletionItem, CompletionItemKind, CompletionKind, ImportToAdd},
@@ -22,7 +23,7 @@ pub(crate) fn render_fn<'a>(
22struct FunctionRender<'a> { 23struct FunctionRender<'a> {
23 ctx: RenderContext<'a>, 24 ctx: RenderContext<'a>,
24 name: String, 25 name: String,
25 fn_: hir::Function, 26 func: hir::Function,
26 ast_node: Fn, 27 ast_node: Fn,
27} 28}
28 29
@@ -35,15 +36,15 @@ impl<'a> FunctionRender<'a> {
35 let name = local_name.unwrap_or_else(|| fn_.name(ctx.db()).to_string()); 36 let name = local_name.unwrap_or_else(|| fn_.name(ctx.db()).to_string());
36 let ast_node = fn_.source(ctx.db()).value; 37 let ast_node = fn_.source(ctx.db()).value;
37 38
38 FunctionRender { ctx, name, fn_, ast_node } 39 FunctionRender { ctx, name, func: fn_, ast_node }
39 } 40 }
40 41
41 fn render(self, import_to_add: Option<ImportToAdd>) -> CompletionItem { 42 fn render(self, import_to_add: Option<ImportToAdd>) -> CompletionItem {
42 let params = self.params(); 43 let params = self.params();
43 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), self.name.clone()) 44 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), self.name.clone())
44 .kind(self.kind()) 45 .kind(self.kind())
45 .set_documentation(self.ctx.docs(self.fn_)) 46 .set_documentation(self.ctx.docs(self.func))
46 .set_deprecated(self.ctx.is_deprecated(self.fn_)) 47 .set_deprecated(self.ctx.is_deprecated(self.func))
47 .detail(self.detail()) 48 .detail(self.detail())
48 .add_call_parens(self.ctx.completion, self.name, params) 49 .add_call_parens(self.ctx.completion, self.name, params)
49 .add_import(import_to_add) 50 .add_import(import_to_add)
@@ -67,27 +68,39 @@ impl<'a> FunctionRender<'a> {
67 } 68 }
68 69
69 fn params(&self) -> Params { 70 fn params(&self) -> Params {
70 let params_ty = self.fn_.params(self.ctx.db()); 71 let ast_params = match self.ast_node.param_list() {
71 let params = self 72 Some(it) => it,
72 .ast_node 73 None => return Params::Named(Vec::new()),
73 .param_list() 74 };
75
76 let mut params_pats = Vec::new();
77 let params_ty = if self.ctx.completion.dot_receiver.is_some() {
78 self.func.method_params(self.ctx.db()).unwrap_or_default()
79 } else {
80 if let Some(s) = ast_params.self_param() {
81 mark::hit!(parens_for_method_call_as_assoc_fn);
82 params_pats.push(Some(s.to_string()));
83 }
84 self.func.assoc_fn_params(self.ctx.db())
85 };
86 params_pats
87 .extend(ast_params.params().into_iter().map(|it| it.pat().map(|it| it.to_string())));
88
89 let params = params_pats
74 .into_iter() 90 .into_iter()
75 .flat_map(|it| it.params())
76 .zip(params_ty) 91 .zip(params_ty)
77 .flat_map(|(it, param_ty)| { 92 .flat_map(|(pat, param_ty)| {
78 if let Some(pat) = it.pat() { 93 let pat = pat?;
79 let name = pat.to_string(); 94 let name = pat.to_string();
80 let arg = name.trim_start_matches("mut ").trim_start_matches('_'); 95 let arg = name.trim_start_matches("mut ").trim_start_matches('_');
81 return Some(self.add_arg(arg, param_ty.ty())); 96 Some(self.add_arg(arg, param_ty.ty()))
82 }
83 None
84 }) 97 })
85 .collect(); 98 .collect();
86 Params::Named(params) 99 Params::Named(params)
87 } 100 }
88 101
89 fn kind(&self) -> CompletionItemKind { 102 fn kind(&self) -> CompletionItemKind {
90 if self.fn_.self_param(self.ctx.db()).is_some() { 103 if self.func.self_param(self.ctx.db()).is_some() {
91 CompletionItemKind::Method 104 CompletionItemKind::Method
92 } else { 105 } else {
93 CompletionItemKind::Function 106 CompletionItemKind::Function
@@ -173,6 +186,28 @@ fn bar(s: &S) {
173 } 186 }
174 187
175 #[test] 188 #[test]
189 fn parens_for_method_call_as_assoc_fn() {
190 mark::check!(parens_for_method_call_as_assoc_fn);
191 check_edit(
192 "foo",
193 r#"
194struct S;
195impl S {
196 fn foo(&self) {}
197}
198fn main() { S::f<|> }
199"#,
200 r#"
201struct S;
202impl S {
203 fn foo(&self) {}
204}
205fn main() { S::foo(${1:&self})$0 }
206"#,
207 );
208 }
209
210 #[test]
176 fn suppress_arg_snippets() { 211 fn suppress_arg_snippets() {
177 mark::check!(suppress_arg_snippets); 212 mark::check!(suppress_arg_snippets);
178 check_edit_with_config( 213 check_edit_with_config(
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index f06b5cd9f..4500050f1 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -744,14 +744,13 @@ impl Function {
744 Some(SelfParam { func: self.id }) 744 Some(SelfParam { func: self.id })
745 } 745 }
746 746
747 pub fn params(self, db: &dyn HirDatabase) -> Vec<Param> { 747 pub fn assoc_fn_params(self, db: &dyn HirDatabase) -> Vec<Param> {
748 let resolver = self.id.resolver(db.upcast()); 748 let resolver = self.id.resolver(db.upcast());
749 let ctx = hir_ty::TyLoweringContext::new(db, &resolver); 749 let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
750 let environment = TraitEnvironment::lower(db, &resolver); 750 let environment = TraitEnvironment::lower(db, &resolver);
751 db.function_data(self.id) 751 db.function_data(self.id)
752 .params 752 .params
753 .iter() 753 .iter()
754 .skip(if self.self_param(db).is_some() { 1 } else { 0 })
755 .map(|type_ref| { 754 .map(|type_ref| {
756 let ty = Type { 755 let ty = Type {
757 krate: self.id.lookup(db.upcast()).container.module(db.upcast()).krate, 756 krate: self.id.lookup(db.upcast()).container.module(db.upcast()).krate,
@@ -764,6 +763,14 @@ impl Function {
764 }) 763 })
765 .collect() 764 .collect()
766 } 765 }
766 pub fn method_params(self, db: &dyn HirDatabase) -> Option<Vec<Param>> {
767 if self.self_param(db).is_none() {
768 return None;
769 }
770 let mut res = self.assoc_fn_params(db);
771 res.remove(0);
772 Some(res)
773 }
767 774
768 pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool { 775 pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
769 db.function_data(self.id).is_unsafe 776 db.function_data(self.id).is_unsafe
@@ -799,6 +806,7 @@ impl From<Mutability> for Access {
799 } 806 }
800} 807}
801 808
809#[derive(Debug)]
802pub struct Param { 810pub struct Param {
803 ty: Type, 811 ty: Type,
804} 812}
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs
index d10b1af01..33eb5e78c 100644
--- a/crates/hir_def/src/body.rs
+++ b/crates/hir_def/src/body.rs
@@ -14,8 +14,8 @@ use cfg::CfgOptions;
14use drop_bomb::DropBomb; 14use drop_bomb::DropBomb;
15use either::Either; 15use either::Either;
16use hir_expand::{ 16use hir_expand::{
17 ast_id_map::AstIdMap, diagnostics::DiagnosticSink, hygiene::Hygiene, AstId, HirFileId, InFile, 17 ast_id_map::AstIdMap, diagnostics::DiagnosticSink, hygiene::Hygiene, AstId, ExpandResult,
18 MacroDefId, 18 HirFileId, InFile, MacroDefId,
19}; 19};
20use rustc_hash::FxHashMap; 20use rustc_hash::FxHashMap;
21use syntax::{ast, AstNode, AstPtr}; 21use syntax::{ast, AstNode, AstPtr};
@@ -102,11 +102,11 @@ impl Expander {
102 db: &dyn DefDatabase, 102 db: &dyn DefDatabase,
103 local_scope: Option<&ItemScope>, 103 local_scope: Option<&ItemScope>,
104 macro_call: ast::MacroCall, 104 macro_call: ast::MacroCall,
105 ) -> Option<(Mark, T)> { 105 ) -> ExpandResult<Option<(Mark, T)>> {
106 self.recursion_limit += 1; 106 self.recursion_limit += 1;
107 if self.recursion_limit > EXPANSION_RECURSION_LIMIT { 107 if self.recursion_limit > EXPANSION_RECURSION_LIMIT {
108 mark::hit!(your_stack_belongs_to_me); 108 mark::hit!(your_stack_belongs_to_me);
109 return None; 109 return ExpandResult::str_err("reached recursion limit during macro expansion".into());
110 } 110 }
111 111
112 let macro_call = InFile::new(self.current_file_id, &macro_call); 112 let macro_call = InFile::new(self.current_file_id, &macro_call);
@@ -120,28 +120,55 @@ impl Expander {
120 self.resolve_path_as_macro(db, &path) 120 self.resolve_path_as_macro(db, &path)
121 }; 121 };
122 122
123 if let Some(call_id) = macro_call.as_call_id(db, self.crate_def_map.krate, resolver) { 123 let call_id = match macro_call.as_call_id(db, self.crate_def_map.krate, resolver) {
124 let file_id = call_id.as_file(); 124 Some(it) => it,
125 if let Some(node) = db.parse_or_expand(file_id) { 125 None => {
126 if let Some(expr) = T::cast(node) { 126 // FIXME: this can mean other things too, but `as_call_id` doesn't provide enough
127 log::debug!("macro expansion {:#?}", expr.syntax()); 127 // info.
128 128 return ExpandResult::only_err(mbe::ExpandError::Other(
129 let mark = Mark { 129 "failed to parse or resolve macro invocation".into(),
130 file_id: self.current_file_id, 130 ));
131 ast_id_map: mem::take(&mut self.ast_id_map), 131 }
132 bomb: DropBomb::new("expansion mark dropped"), 132 };
133 }; 133
134 self.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id); 134 let err = db.macro_expand_error(call_id);
135 self.current_file_id = file_id; 135
136 self.ast_id_map = db.ast_id_map(file_id); 136 let file_id = call_id.as_file();
137 return Some((mark, expr)); 137
138 let raw_node = match db.parse_or_expand(file_id) {
139 Some(it) => it,
140 None => {
141 // Only `None` if the macro expansion produced no usable AST.
142 if err.is_none() {
143 log::warn!("no error despite `parse_or_expand` failing");
138 } 144 }
145
146 return ExpandResult::only_err(err.unwrap_or_else(|| {
147 mbe::ExpandError::Other("failed to parse macro invocation".into())
148 }));
139 } 149 }
140 } 150 };
151
152 let node = match T::cast(raw_node) {
153 Some(it) => it,
154 None => {
155 // This can happen without being an error, so only forward previous errors.
156 return ExpandResult { value: None, err };
157 }
158 };
159
160 log::debug!("macro expansion {:#?}", node.syntax());
161
162 let mark = Mark {
163 file_id: self.current_file_id,
164 ast_id_map: mem::take(&mut self.ast_id_map),
165 bomb: DropBomb::new("expansion mark dropped"),
166 };
167 self.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id);
168 self.current_file_id = file_id;
169 self.ast_id_map = db.ast_id_map(file_id);
141 170
142 // FIXME: Instead of just dropping the error from expansion 171 ExpandResult { value: Some((mark, node)), err }
143 // report it
144 None
145 } 172 }
146 173
147 pub(crate) fn exit(&mut self, db: &dyn DefDatabase, mut mark: Mark) { 174 pub(crate) fn exit(&mut self, db: &dyn DefDatabase, mut mark: Mark) {
diff --git a/crates/hir_def/src/body/diagnostics.rs b/crates/hir_def/src/body/diagnostics.rs
index e57bdc133..1de7d30e2 100644
--- a/crates/hir_def/src/body/diagnostics.rs
+++ b/crates/hir_def/src/body/diagnostics.rs
@@ -2,11 +2,13 @@
2 2
3use hir_expand::diagnostics::DiagnosticSink; 3use hir_expand::diagnostics::DiagnosticSink;
4 4
5use crate::diagnostics::InactiveCode; 5use crate::diagnostics::{InactiveCode, MacroError, UnresolvedProcMacro};
6 6
7#[derive(Debug, Eq, PartialEq)] 7#[derive(Debug, Eq, PartialEq)]
8pub(crate) enum BodyDiagnostic { 8pub(crate) enum BodyDiagnostic {
9 InactiveCode(InactiveCode), 9 InactiveCode(InactiveCode),
10 MacroError(MacroError),
11 UnresolvedProcMacro(UnresolvedProcMacro),
10} 12}
11 13
12impl BodyDiagnostic { 14impl BodyDiagnostic {
@@ -15,6 +17,12 @@ impl BodyDiagnostic {
15 BodyDiagnostic::InactiveCode(diag) => { 17 BodyDiagnostic::InactiveCode(diag) => {
16 sink.push(diag.clone()); 18 sink.push(diag.clone());
17 } 19 }
20 BodyDiagnostic::MacroError(diag) => {
21 sink.push(diag.clone());
22 }
23 BodyDiagnostic::UnresolvedProcMacro(diag) => {
24 sink.push(diag.clone());
25 }
18 } 26 }
19 } 27 }
20} 28}
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index cd7958746..2c41c0005 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -8,7 +8,7 @@ use either::Either;
8use hir_expand::{ 8use hir_expand::{
9 hygiene::Hygiene, 9 hygiene::Hygiene,
10 name::{name, AsName, Name}, 10 name::{name, AsName, Name},
11 HirFileId, MacroDefId, MacroDefKind, 11 ExpandError, HirFileId, MacroDefId, MacroDefKind,
12}; 12};
13use rustc_hash::FxHashMap; 13use rustc_hash::FxHashMap;
14use syntax::{ 14use syntax::{
@@ -25,7 +25,7 @@ use crate::{
25 body::{Body, BodySourceMap, Expander, PatPtr, SyntheticSyntax}, 25 body::{Body, BodySourceMap, Expander, PatPtr, SyntheticSyntax},
26 builtin_type::{BuiltinFloat, BuiltinInt}, 26 builtin_type::{BuiltinFloat, BuiltinInt},
27 db::DefDatabase, 27 db::DefDatabase,
28 diagnostics::InactiveCode, 28 diagnostics::{InactiveCode, MacroError, UnresolvedProcMacro},
29 expr::{ 29 expr::{
30 dummy_expr_id, ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, 30 dummy_expr_id, ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal,
31 LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, 31 LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
@@ -561,7 +561,32 @@ impl ExprCollector<'_> {
561 self.alloc_expr(Expr::Missing, syntax_ptr) 561 self.alloc_expr(Expr::Missing, syntax_ptr)
562 } else { 562 } else {
563 let macro_call = self.expander.to_source(AstPtr::new(&e)); 563 let macro_call = self.expander.to_source(AstPtr::new(&e));
564 match self.expander.enter_expand(self.db, Some(&self.body.item_scope), e) { 564 let res = self.expander.enter_expand(self.db, Some(&self.body.item_scope), e);
565
566 match res.err {
567 Some(ExpandError::UnresolvedProcMacro) => {
568 self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedProcMacro(
569 UnresolvedProcMacro {
570 file: self.expander.current_file_id,
571 node: syntax_ptr.clone().into(),
572 precise_location: None,
573 macro_name: None,
574 },
575 ));
576 }
577 Some(err) => {
578 self.source_map.diagnostics.push(BodyDiagnostic::MacroError(
579 MacroError {
580 file: self.expander.current_file_id,
581 node: syntax_ptr.clone().into(),
582 message: err.to_string(),
583 },
584 ));
585 }
586 None => {}
587 }
588
589 match res.value {
565 Some((mark, expansion)) => { 590 Some((mark, expansion)) => {
566 self.source_map 591 self.source_map
567 .expansions 592 .expansions
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs
index ff1ef0df6..146045938 100644
--- a/crates/hir_def/src/data.rs
+++ b/crates/hir_def/src/data.rs
@@ -257,7 +257,7 @@ fn collect_items(
257 let root = db.parse_or_expand(file_id).unwrap(); 257 let root = db.parse_or_expand(file_id).unwrap();
258 let call = ast_id_map.get(call.ast_id).to_node(&root); 258 let call = ast_id_map.get(call.ast_id).to_node(&root);
259 259
260 if let Some((mark, mac)) = expander.enter_expand(db, None, call) { 260 if let Some((mark, mac)) = expander.enter_expand(db, None, call).value {
261 let src: InFile<ast::MacroItems> = expander.to_source(mac); 261 let src: InFile<ast::MacroItems> = expander.to_source(mac);
262 let item_tree = db.item_tree(src.file_id); 262 let item_tree = db.item_tree(src.file_id);
263 let iter = 263 let iter =
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index aebbfc4df..7f4db106d 100644
--- a/crates/hir_expand/src/builtin_macro.rs
+++ b/crates/hir_expand/src/builtin_macro.rs
@@ -6,7 +6,7 @@ use crate::{
6 6
7use base_db::FileId; 7use base_db::FileId;
8use either::Either; 8use either::Either;
9use mbe::parse_to_token_tree; 9use mbe::{parse_to_token_tree, ExpandResult};
10use parser::FragmentKind; 10use parser::FragmentKind;
11use syntax::ast::{self, AstToken}; 11use syntax::ast::{self, AstToken};
12 12
@@ -28,7 +28,7 @@ macro_rules! register_builtin {
28 db: &dyn AstDatabase, 28 db: &dyn AstDatabase,
29 id: LazyMacroId, 29 id: LazyMacroId,
30 tt: &tt::Subtree, 30 tt: &tt::Subtree,
31 ) -> Result<tt::Subtree, mbe::ExpandError> { 31 ) -> ExpandResult<tt::Subtree> {
32 let expander = match *self { 32 let expander = match *self {
33 $( BuiltinFnLikeExpander::$kind => $expand, )* 33 $( BuiltinFnLikeExpander::$kind => $expand, )*
34 }; 34 };
@@ -42,7 +42,7 @@ macro_rules! register_builtin {
42 db: &dyn AstDatabase, 42 db: &dyn AstDatabase,
43 arg_id: EagerMacroId, 43 arg_id: EagerMacroId,
44 tt: &tt::Subtree, 44 tt: &tt::Subtree,
45 ) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { 45 ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
46 let expander = match *self { 46 let expander = match *self {
47 $( EagerExpander::$e_kind => $e_expand, )* 47 $( EagerExpander::$e_kind => $e_expand, )*
48 }; 48 };
@@ -109,25 +109,28 @@ fn line_expand(
109 _db: &dyn AstDatabase, 109 _db: &dyn AstDatabase,
110 _id: LazyMacroId, 110 _id: LazyMacroId,
111 _tt: &tt::Subtree, 111 _tt: &tt::Subtree,
112) -> Result<tt::Subtree, mbe::ExpandError> { 112) -> ExpandResult<tt::Subtree> {
113 // dummy implementation for type-checking purposes 113 // dummy implementation for type-checking purposes
114 let line_num = 0; 114 let line_num = 0;
115 let expanded = quote! { 115 let expanded = quote! {
116 #line_num 116 #line_num
117 }; 117 };
118 118
119 Ok(expanded) 119 ExpandResult::ok(expanded)
120} 120}
121 121
122fn stringify_expand( 122fn stringify_expand(
123 db: &dyn AstDatabase, 123 db: &dyn AstDatabase,
124 id: LazyMacroId, 124 id: LazyMacroId,
125 _tt: &tt::Subtree, 125 _tt: &tt::Subtree,
126) -> Result<tt::Subtree, mbe::ExpandError> { 126) -> ExpandResult<tt::Subtree> {
127 let loc = db.lookup_intern_macro(id); 127 let loc = db.lookup_intern_macro(id);
128 128
129 let macro_content = { 129 let macro_content = {
130 let arg = loc.kind.arg(db).ok_or_else(|| mbe::ExpandError::UnexpectedToken)?; 130 let arg = match loc.kind.arg(db) {
131 Some(arg) => arg,
132 None => return ExpandResult::only_err(mbe::ExpandError::UnexpectedToken),
133 };
131 let macro_args = arg; 134 let macro_args = arg;
132 let text = macro_args.text(); 135 let text = macro_args.text();
133 let without_parens = TextSize::of('(')..text.len() - TextSize::of(')'); 136 let without_parens = TextSize::of('(')..text.len() - TextSize::of(')');
@@ -138,28 +141,28 @@ fn stringify_expand(
138 #macro_content 141 #macro_content
139 }; 142 };
140 143
141 Ok(expanded) 144 ExpandResult::ok(expanded)
142} 145}
143 146
144fn column_expand( 147fn column_expand(
145 _db: &dyn AstDatabase, 148 _db: &dyn AstDatabase,
146 _id: LazyMacroId, 149 _id: LazyMacroId,
147 _tt: &tt::Subtree, 150 _tt: &tt::Subtree,
148) -> Result<tt::Subtree, mbe::ExpandError> { 151) -> ExpandResult<tt::Subtree> {
149 // dummy implementation for type-checking purposes 152 // dummy implementation for type-checking purposes
150 let col_num = 0; 153 let col_num = 0;
151 let expanded = quote! { 154 let expanded = quote! {
152 #col_num 155 #col_num
153 }; 156 };
154 157
155 Ok(expanded) 158 ExpandResult::ok(expanded)
156} 159}
157 160
158fn assert_expand( 161fn assert_expand(
159 _db: &dyn AstDatabase, 162 _db: &dyn AstDatabase,
160 _id: LazyMacroId, 163 _id: LazyMacroId,
161 tt: &tt::Subtree, 164 tt: &tt::Subtree,
162) -> Result<tt::Subtree, mbe::ExpandError> { 165) -> ExpandResult<tt::Subtree> {
163 // A hacky implementation for goto def and hover 166 // A hacky implementation for goto def and hover
164 // We expand `assert!(cond, arg1, arg2)` to 167 // We expand `assert!(cond, arg1, arg2)` to
165 // ``` 168 // ```
@@ -191,14 +194,14 @@ fn assert_expand(
191 let expanded = quote! { 194 let expanded = quote! {
192 { { (##arg_tts); } } 195 { { (##arg_tts); } }
193 }; 196 };
194 Ok(expanded) 197 ExpandResult::ok(expanded)
195} 198}
196 199
197fn file_expand( 200fn file_expand(
198 _db: &dyn AstDatabase, 201 _db: &dyn AstDatabase,
199 _id: LazyMacroId, 202 _id: LazyMacroId,
200 _tt: &tt::Subtree, 203 _tt: &tt::Subtree,
201) -> Result<tt::Subtree, mbe::ExpandError> { 204) -> ExpandResult<tt::Subtree> {
202 // FIXME: RA purposefully lacks knowledge of absolute file names 205 // FIXME: RA purposefully lacks knowledge of absolute file names
203 // so just return "". 206 // so just return "".
204 let file_name = ""; 207 let file_name = "";
@@ -207,31 +210,33 @@ fn file_expand(
207 #file_name 210 #file_name
208 }; 211 };
209 212
210 Ok(expanded) 213 ExpandResult::ok(expanded)
211} 214}
212 215
213fn compile_error_expand( 216fn compile_error_expand(
214 _db: &dyn AstDatabase, 217 _db: &dyn AstDatabase,
215 _id: LazyMacroId, 218 _id: LazyMacroId,
216 tt: &tt::Subtree, 219 tt: &tt::Subtree,
217) -> Result<tt::Subtree, mbe::ExpandError> { 220) -> ExpandResult<tt::Subtree> {
218 if tt.count() == 1 { 221 if tt.count() == 1 {
219 if let tt::TokenTree::Leaf(tt::Leaf::Literal(it)) = &tt.token_trees[0] { 222 if let tt::TokenTree::Leaf(tt::Leaf::Literal(it)) = &tt.token_trees[0] {
220 let s = it.text.as_str(); 223 let s = it.text.as_str();
221 if s.contains('"') { 224 if s.contains('"') {
222 return Ok(quote! { loop { #it }}); 225 return ExpandResult::ok(quote! { loop { #it }});
223 } 226 }
224 }; 227 };
225 } 228 }
226 229
227 Err(mbe::ExpandError::BindingError("Must be a string".into())) 230 ExpandResult::only_err(mbe::ExpandError::BindingError(
231 "`compile_error!` argument be a string".into(),
232 ))
228} 233}
229 234
230fn format_args_expand( 235fn format_args_expand(
231 _db: &dyn AstDatabase, 236 _db: &dyn AstDatabase,
232 _id: LazyMacroId, 237 _id: LazyMacroId,
233 tt: &tt::Subtree, 238 tt: &tt::Subtree,
234) -> Result<tt::Subtree, mbe::ExpandError> { 239) -> ExpandResult<tt::Subtree> {
235 // We expand `format_args!("", a1, a2)` to 240 // We expand `format_args!("", a1, a2)` to
236 // ``` 241 // ```
237 // std::fmt::Arguments::new_v1(&[], &[ 242 // std::fmt::Arguments::new_v1(&[], &[
@@ -257,7 +262,7 @@ fn format_args_expand(
257 args.push(current); 262 args.push(current);
258 } 263 }
259 if args.is_empty() { 264 if args.is_empty() {
260 return Err(mbe::ExpandError::NoMatchingRule); 265 return ExpandResult::only_err(mbe::ExpandError::NoMatchingRule);
261 } 266 }
262 let _format_string = args.remove(0); 267 let _format_string = args.remove(0);
263 let arg_tts = args.into_iter().flat_map(|arg| { 268 let arg_tts = args.into_iter().flat_map(|arg| {
@@ -266,7 +271,7 @@ fn format_args_expand(
266 let expanded = quote! { 271 let expanded = quote! {
267 std::fmt::Arguments::new_v1(&[], &[##arg_tts]) 272 std::fmt::Arguments::new_v1(&[], &[##arg_tts])
268 }; 273 };
269 Ok(expanded) 274 ExpandResult::ok(expanded)
270} 275}
271 276
272fn unquote_str(lit: &tt::Literal) -> Option<String> { 277fn unquote_str(lit: &tt::Literal) -> Option<String> {
@@ -279,19 +284,24 @@ fn concat_expand(
279 _db: &dyn AstDatabase, 284 _db: &dyn AstDatabase,
280 _arg_id: EagerMacroId, 285 _arg_id: EagerMacroId,
281 tt: &tt::Subtree, 286 tt: &tt::Subtree,
282) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { 287) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
283 let mut text = String::new(); 288 let mut text = String::new();
284 for (i, t) in tt.token_trees.iter().enumerate() { 289 for (i, t) in tt.token_trees.iter().enumerate() {
285 match t { 290 match t {
286 tt::TokenTree::Leaf(tt::Leaf::Literal(it)) if i % 2 == 0 => { 291 tt::TokenTree::Leaf(tt::Leaf::Literal(it)) if i % 2 == 0 => {
287 text += &unquote_str(&it).ok_or_else(|| mbe::ExpandError::ConversionError)?; 292 text += &match unquote_str(&it) {
293 Some(s) => s,
294 None => {
295 return ExpandResult::only_err(mbe::ExpandError::ConversionError);
296 }
297 };
288 } 298 }
289 tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (), 299 tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
290 _ => return Err(mbe::ExpandError::UnexpectedToken), 300 _ => return ExpandResult::only_err(mbe::ExpandError::UnexpectedToken),
291 } 301 }
292 } 302 }
293 303
294 Ok((quote!(#text), FragmentKind::Expr)) 304 ExpandResult::ok(Some((quote!(#text), FragmentKind::Expr)))
295} 305}
296 306
297fn relative_file( 307fn relative_file(
@@ -324,26 +334,35 @@ fn include_expand(
324 db: &dyn AstDatabase, 334 db: &dyn AstDatabase,
325 arg_id: EagerMacroId, 335 arg_id: EagerMacroId,
326 tt: &tt::Subtree, 336 tt: &tt::Subtree,
327) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { 337) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
328 let path = parse_string(tt)?; 338 let res = (|| {
329 let file_id = relative_file(db, arg_id.into(), &path, false) 339 let path = parse_string(tt)?;
330 .ok_or_else(|| mbe::ExpandError::ConversionError)?; 340 let file_id = relative_file(db, arg_id.into(), &path, false)
331 341 .ok_or_else(|| mbe::ExpandError::ConversionError)?;
332 // FIXME: 342
333 // Handle include as expression 343 Ok(parse_to_token_tree(&db.file_text(file_id))
334 let res = parse_to_token_tree(&db.file_text(file_id)) 344 .ok_or_else(|| mbe::ExpandError::ConversionError)?
335 .ok_or_else(|| mbe::ExpandError::ConversionError)? 345 .0)
336 .0; 346 })();
337 347
338 Ok((res, FragmentKind::Items)) 348 match res {
349 Ok(res) => {
350 // FIXME:
351 // Handle include as expression
352 ExpandResult::ok(Some((res, FragmentKind::Items)))
353 }
354 Err(e) => ExpandResult::only_err(e),
355 }
339} 356}
340 357
341fn include_bytes_expand( 358fn include_bytes_expand(
342 _db: &dyn AstDatabase, 359 _db: &dyn AstDatabase,
343 _arg_id: EagerMacroId, 360 _arg_id: EagerMacroId,
344 tt: &tt::Subtree, 361 tt: &tt::Subtree,
345) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { 362) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
346 let _path = parse_string(tt)?; 363 if let Err(e) = parse_string(tt) {
364 return ExpandResult::only_err(e);
365 }
347 366
348 // FIXME: actually read the file here if the user asked for macro expansion 367 // FIXME: actually read the file here if the user asked for macro expansion
349 let res = tt::Subtree { 368 let res = tt::Subtree {
@@ -353,15 +372,18 @@ fn include_bytes_expand(
353 id: tt::TokenId::unspecified(), 372 id: tt::TokenId::unspecified(),
354 }))], 373 }))],
355 }; 374 };
356 Ok((res, FragmentKind::Expr)) 375 ExpandResult::ok(Some((res, FragmentKind::Expr)))
357} 376}
358 377
359fn include_str_expand( 378fn include_str_expand(
360 db: &dyn AstDatabase, 379 db: &dyn AstDatabase,
361 arg_id: EagerMacroId, 380 arg_id: EagerMacroId,
362 tt: &tt::Subtree, 381 tt: &tt::Subtree,
363) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { 382) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
364 let path = parse_string(tt)?; 383 let path = match parse_string(tt) {
384 Ok(it) => it,
385 Err(e) => return ExpandResult::only_err(e),
386 };
365 387
366 // FIXME: we're not able to read excluded files (which is most of them because 388 // FIXME: we're not able to read excluded files (which is most of them because
367 // it's unusual to `include_str!` a Rust file), but we can return an empty string. 389 // it's unusual to `include_str!` a Rust file), but we can return an empty string.
@@ -370,14 +392,14 @@ fn include_str_expand(
370 let file_id = match relative_file(db, arg_id.into(), &path, true) { 392 let file_id = match relative_file(db, arg_id.into(), &path, true) {
371 Some(file_id) => file_id, 393 Some(file_id) => file_id,
372 None => { 394 None => {
373 return Ok((quote!(""), FragmentKind::Expr)); 395 return ExpandResult::ok(Some((quote!(""), FragmentKind::Expr)));
374 } 396 }
375 }; 397 };
376 398
377 let text = db.file_text(file_id); 399 let text = db.file_text(file_id);
378 let text = &*text; 400 let text = &*text;
379 401
380 Ok((quote!(#text), FragmentKind::Expr)) 402 ExpandResult::ok(Some((quote!(#text), FragmentKind::Expr)))
381} 403}
382 404
383fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> { 405fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> {
@@ -389,8 +411,11 @@ fn env_expand(
389 db: &dyn AstDatabase, 411 db: &dyn AstDatabase,
390 arg_id: EagerMacroId, 412 arg_id: EagerMacroId,
391 tt: &tt::Subtree, 413 tt: &tt::Subtree,
392) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { 414) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
393 let key = parse_string(tt)?; 415 let key = match parse_string(tt) {
416 Ok(it) => it,
417 Err(e) => return ExpandResult::only_err(e),
418 };
394 419
395 // FIXME: 420 // FIXME:
396 // If the environment variable is not defined int rustc, then a compilation error will be emitted. 421 // If the environment variable is not defined int rustc, then a compilation error will be emitted.
@@ -402,21 +427,25 @@ fn env_expand(
402 let s = get_env_inner(db, arg_id, &key).unwrap_or_else(|| "__RA_UNIMPLEMENTED__".to_string()); 427 let s = get_env_inner(db, arg_id, &key).unwrap_or_else(|| "__RA_UNIMPLEMENTED__".to_string());
403 let expanded = quote! { #s }; 428 let expanded = quote! { #s };
404 429
405 Ok((expanded, FragmentKind::Expr)) 430 ExpandResult::ok(Some((expanded, FragmentKind::Expr)))
406} 431}
407 432
408fn option_env_expand( 433fn option_env_expand(
409 db: &dyn AstDatabase, 434 db: &dyn AstDatabase,
410 arg_id: EagerMacroId, 435 arg_id: EagerMacroId,
411 tt: &tt::Subtree, 436 tt: &tt::Subtree,
412) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { 437) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
413 let key = parse_string(tt)?; 438 let key = match parse_string(tt) {
439 Ok(it) => it,
440 Err(e) => return ExpandResult::only_err(e),
441 };
442
414 let expanded = match get_env_inner(db, arg_id, &key) { 443 let expanded = match get_env_inner(db, arg_id, &key) {
415 None => quote! { std::option::Option::None::<&str> }, 444 None => quote! { std::option::Option::None::<&str> },
416 Some(s) => quote! { std::option::Some(#s) }, 445 Some(s) => quote! { std::option::Some(#s) },
417 }; 446 };
418 447
419 Ok((expanded, FragmentKind::Expr)) 448 ExpandResult::ok(Some((expanded, FragmentKind::Expr)))
420} 449}
421 450
422#[cfg(test)] 451#[cfg(test)]
@@ -485,7 +514,7 @@ mod tests {
485 } 514 }
486 }); 515 });
487 516
488 let (subtree, fragment) = expander.expand(&db, arg_id, &parsed_args).unwrap(); 517 let (subtree, fragment) = expander.expand(&db, arg_id, &parsed_args).value.unwrap();
489 let eager = EagerCallLoc { 518 let eager = EagerCallLoc {
490 def, 519 def,
491 fragment, 520 fragment,
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index ff50bfd82..4fd0ba290 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -30,8 +30,8 @@ impl TokenExpander {
30 ) -> mbe::ExpandResult<tt::Subtree> { 30 ) -> mbe::ExpandResult<tt::Subtree> {
31 match self { 31 match self {
32 TokenExpander::MacroRules(it) => it.expand(tt), 32 TokenExpander::MacroRules(it) => it.expand(tt),
33 TokenExpander::Builtin(it) => it.expand(db, id, tt),
33 // FIXME switch these to ExpandResult as well 34 // FIXME switch these to ExpandResult as well
34 TokenExpander::Builtin(it) => it.expand(db, id, tt).into(),
35 TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(), 35 TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(),
36 TokenExpander::ProcMacro(_) => { 36 TokenExpander::ProcMacro(_) => {
37 // We store the result in salsa db to prevent non-determinisc behavior in 37 // We store the result in salsa db to prevent non-determinisc behavior in
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs
index 2f37d7189..ab6b4477c 100644
--- a/crates/hir_expand/src/eager.rs
+++ b/crates/hir_expand/src/eager.rs
@@ -65,7 +65,7 @@ pub fn expand_eager_macro(
65 let subtree = to_subtree(&result)?; 65 let subtree = to_subtree(&result)?;
66 66
67 if let MacroDefKind::BuiltInEager(eager) = def.kind { 67 if let MacroDefKind::BuiltInEager(eager) = def.kind {
68 let (subtree, fragment) = eager.expand(db, arg_id, &subtree).ok()?; 68 let (subtree, fragment) = eager.expand(db, arg_id, &subtree).value?;
69 let eager = EagerCallLoc { 69 let eager = EagerCallLoc {
70 def, 70 def,
71 fragment, 71 fragment,
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs
index 731457696..64fe8bd65 100644
--- a/crates/ide/src/references/rename.rs
+++ b/crates/ide/src/references/rename.rs
@@ -241,7 +241,7 @@ fn rename_to_self(
241 return Err(RenameError("Method already has a self parameter".to_string())); 241 return Err(RenameError("Method already has a self parameter".to_string()));
242 } 242 }
243 243
244 let params = fn_def.params(sema.db); 244 let params = fn_def.assoc_fn_params(sema.db);
245 let first_param = 245 let first_param =
246 params.first().ok_or_else(|| RenameError("Method has no parameters".into()))?; 246 params.first().ok_or_else(|| RenameError("Method has no parameters".into()))?;
247 let first_param_ty = first_param.ty(); 247 let first_param_ty = first_param.ty();
diff --git a/crates/ide_db/src/helpers/insert_use.rs b/crates/ide_db/src/helpers/insert_use.rs
index 67e800fad..08d246c16 100644
--- a/crates/ide_db/src/helpers/insert_use.rs
+++ b/crates/ide_db/src/helpers/insert_use.rs
@@ -384,7 +384,7 @@ fn path_cmp_for_sort(a: Option<ast::Path>, b: Option<ast::Path>) -> Ordering {
384 384
385/// Path comparison func for binary searching for merging. 385/// Path comparison func for binary searching for merging.
386fn path_cmp_bin_search(lhs: Option<ast::Path>, rhs: Option<ast::Path>) -> Ordering { 386fn path_cmp_bin_search(lhs: Option<ast::Path>, rhs: Option<ast::Path>) -> Ordering {
387 match (lhs.and_then(|path| path.segment()), rhs.and_then(|path| path.segment())) { 387 match (lhs.as_ref().and_then(first_segment), rhs.as_ref().and_then(first_segment)) {
388 (None, None) => Ordering::Equal, 388 (None, None) => Ordering::Equal,
389 (None, Some(_)) => Ordering::Less, 389 (None, Some(_)) => Ordering::Less,
390 (Some(_), None) => Ordering::Greater, 390 (Some(_), None) => Ordering::Greater,
@@ -1082,6 +1082,15 @@ use std::io;",
1082 } 1082 }
1083 1083
1084 #[test] 1084 #[test]
1085 fn merge_nested_considers_first_segments() {
1086 check_full(
1087 "hir_ty::display::write_bounds_like_dyn_trait",
1088 r"use hir_ty::{autoderef, display::{HirDisplayError, HirFormatter}, method_resolution};",
1089 r"use hir_ty::{autoderef, display::{HirDisplayError, HirFormatter, write_bounds_like_dyn_trait}, method_resolution};",
1090 );
1091 }
1092
1093 #[test]
1085 fn skip_merge_last_too_long() { 1094 fn skip_merge_last_too_long() {
1086 check_last( 1095 check_last(
1087 "foo::bar", 1096 "foo::bar",
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index 08559b53a..0a055b039 100644
--- a/crates/rust-analyzer/Cargo.toml
+++ b/crates/rust-analyzer/Cargo.toml
@@ -21,7 +21,7 @@ env_logger = { version = "0.8.1", default-features = false }
21itertools = "0.9.0" 21itertools = "0.9.0"
22jod-thread = "0.1.0" 22jod-thread = "0.1.0"
23log = "0.4.8" 23log = "0.4.8"
24lsp-types = { version = "0.84.0", features = ["proposed"] } 24lsp-types = { version = "0.85.0", features = ["proposed"] }
25parking_lot = "0.11.0" 25parking_lot = "0.11.0"
26pico-args = "0.3.1" 26pico-args = "0.3.1"
27oorandom = "11.1.2" 27oorandom = "11.1.2"
diff --git a/crates/rust-analyzer/src/semantic_tokens.rs b/crates/rust-analyzer/src/semantic_tokens.rs
index e7991fd28..1daad1c98 100644
--- a/crates/rust-analyzer/src/semantic_tokens.rs
+++ b/crates/rust-analyzer/src/semantic_tokens.rs
@@ -27,7 +27,7 @@ macro_rules! define_semantic_token_types {
27 SemanticTokenType::ENUM_MEMBER, 27 SemanticTokenType::ENUM_MEMBER,
28 SemanticTokenType::TYPE_PARAMETER, 28 SemanticTokenType::TYPE_PARAMETER,
29 SemanticTokenType::FUNCTION, 29 SemanticTokenType::FUNCTION,
30 SemanticTokenType::MEMBER, 30 SemanticTokenType::METHOD,
31 SemanticTokenType::PROPERTY, 31 SemanticTokenType::PROPERTY,
32 SemanticTokenType::MACRO, 32 SemanticTokenType::MACRO,
33 SemanticTokenType::VARIABLE, 33 SemanticTokenType::VARIABLE,
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml
index ce62babc3..c6a6f11e1 100644
--- a/crates/syntax/Cargo.toml
+++ b/crates/syntax/Cargo.toml
@@ -13,7 +13,7 @@ doctest = false
13[dependencies] 13[dependencies]
14itertools = "0.9.0" 14itertools = "0.9.0"
15rowan = "0.10.0" 15rowan = "0.10.0"
16rustc_lexer = { version = "688.0.0", package = "rustc-ap-rustc_lexer" } 16rustc_lexer = { version = "691.0.0", package = "rustc-ap-rustc_lexer" }
17rustc-hash = "1.1.0" 17rustc-hash = "1.1.0"
18arrayvec = "0.5.1" 18arrayvec = "0.5.1"
19once_cell = "1.3.1" 19once_cell = "1.3.1"