aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_assists/src/doc_tests/generated.rs27
-rw-r--r--crates/ra_assists/src/handlers/add_from_impl_for_enum.rs206
-rw-r--r--crates/ra_assists/src/handlers/add_function.rs788
-rw-r--r--crates/ra_assists/src/lib.rs4
-rw-r--r--crates/ra_hir/src/code_model.rs20
-rw-r--r--crates/ra_hir_def/src/body/lower.rs3
-rw-r--r--crates/ra_hir_def/src/type_ref.rs6
-rw-r--r--crates/ra_hir_ty/Cargo.toml6
-rw-r--r--crates/ra_hir_ty/src/autoderef.rs19
-rw-r--r--crates/ra_hir_ty/src/display.rs22
-rw-r--r--crates/ra_hir_ty/src/infer/unify.rs28
-rw-r--r--crates/ra_hir_ty/src/lib.rs103
-rw-r--r--crates/ra_hir_ty/src/lower.rs28
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs16
-rw-r--r--crates/ra_hir_ty/src/tests/coercion.rs8
-rw-r--r--crates/ra_hir_ty/src/tests/macros.rs31
-rw-r--r--crates/ra_hir_ty/src/tests/regression.rs2
-rw-r--r--crates/ra_hir_ty/src/tests/simple.rs28
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs12
-rw-r--r--crates/ra_hir_ty/src/traits.rs16
-rw-r--r--crates/ra_hir_ty/src/traits/builtin.rs53
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs153
-rw-r--r--crates/ra_hir_ty/src/utils.rs6
-rw-r--r--crates/ra_ide/src/completion/complete_dot.rs2
-rw-r--r--crates/ra_ide/src/completion/complete_path.rs24
-rw-r--r--crates/ra_ide/src/completion/complete_pattern.rs58
-rw-r--r--crates/ra_ide/src/completion/complete_scope.rs10
-rw-r--r--crates/ra_ide/src/completion/completion_context.rs31
-rw-r--r--crates/ra_ide/src/completion/presentation.rs235
-rw-r--r--crates/ra_parser/src/grammar/expressions.rs4
-rw-r--r--crates/ra_parser/src/grammar/patterns.rs25
-rw-r--r--crates/ra_parser/src/syntax_kind/generated.rs1
-rw-r--r--crates/ra_proc_macro/src/lib.rs3
-rw-r--r--crates/ra_proc_macro_srv/Cargo.toml21
-rw-r--r--crates/ra_proc_macro_srv/src/lib.rs21
-rw-r--r--crates/ra_proc_macro_srv/src/main.rs55
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs3
-rw-r--r--crates/ra_syntax/src/ast/generated.rs42
-rw-r--r--crates/ra_syntax/src/ast/make.rs28
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0129_marco_pat.txt21
-rw-r--r--crates/rust-analyzer/src/config.rs17
41 files changed, 1862 insertions, 324 deletions
diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs
index 0848ab6bc..64444ee3a 100644
--- a/crates/ra_assists/src/doc_tests/generated.rs
+++ b/crates/ra_assists/src/doc_tests/generated.rs
@@ -59,6 +59,33 @@ fn main() {
59} 59}
60 60
61#[test] 61#[test]
62fn doctest_add_function() {
63 check(
64 "add_function",
65 r#####"
66struct Baz;
67fn baz() -> Baz { Baz }
68fn foo() {
69 bar<|>("", baz());
70}
71
72"#####,
73 r#####"
74struct Baz;
75fn baz() -> Baz { Baz }
76fn foo() {
77 bar("", baz());
78}
79
80fn bar(arg: &str, baz: Baz) {
81 unimplemented!()
82}
83
84"#####,
85 )
86}
87
88#[test]
62fn doctest_add_hash() { 89fn doctest_add_hash() {
63 check( 90 check(
64 "add_hash", 91 "add_hash",
diff --git a/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs b/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs
new file mode 100644
index 000000000..864373aa5
--- /dev/null
+++ b/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs
@@ -0,0 +1,206 @@
1use ra_syntax::{
2 ast::{self, AstNode, NameOwner},
3 TextUnit,
4};
5use stdx::format_to;
6
7use crate::{Assist, AssistCtx, AssistId};
8use ra_ide_db::RootDatabase;
9
10// Assist add_from_impl_for_enum
11//
12// Adds a From impl for an enum variant with one tuple field
13//
14// ```
15// enum A { <|>One(u32) }
16// ```
17// ->
18// ```
19// enum A { One(u32) }
20//
21// impl From<u32> for A {
22// fn from(v: u32) -> Self {
23// A::One(v)
24// }
25// }
26// ```
27pub(crate) fn add_from_impl_for_enum(ctx: AssistCtx) -> Option<Assist> {
28 let variant = ctx.find_node_at_offset::<ast::EnumVariant>()?;
29 let variant_name = variant.name()?;
30 let enum_name = variant.parent_enum().name()?;
31 let field_list = match variant.kind() {
32 ast::StructKind::Tuple(field_list) => field_list,
33 _ => return None,
34 };
35 if field_list.fields().count() != 1 {
36 return None;
37 }
38 let field_type = field_list.fields().next()?.type_ref()?;
39 let path = match field_type {
40 ast::TypeRef::PathType(p) => p,
41 _ => return None,
42 };
43
44 if already_has_from_impl(ctx.sema, &variant) {
45 return None;
46 }
47
48 ctx.add_assist(
49 AssistId("add_from_impl_for_enum"),
50 "Add From impl for this enum variant",
51 |edit| {
52 let start_offset = variant.parent_enum().syntax().text_range().end();
53 let mut buf = String::new();
54 format_to!(
55 buf,
56 r#"
57
58impl From<{0}> for {1} {{
59 fn from(v: {0}) -> Self {{
60 {1}::{2}(v)
61 }}
62}}"#,
63 path.syntax(),
64 enum_name,
65 variant_name
66 );
67 edit.insert(start_offset, buf);
68 edit.set_cursor(start_offset + TextUnit::of_str("\n\n"));
69 },
70 )
71}
72
73fn already_has_from_impl(
74 sema: &'_ hir::Semantics<'_, RootDatabase>,
75 variant: &ast::EnumVariant,
76) -> bool {
77 let scope = sema.scope(&variant.syntax());
78
79 let from_path = ast::make::path_from_text("From");
80 let from_hir_path = match hir::Path::from_ast(from_path) {
81 Some(p) => p,
82 None => return false,
83 };
84 let from_trait = match scope.resolve_hir_path(&from_hir_path) {
85 Some(hir::PathResolution::Def(hir::ModuleDef::Trait(t))) => t,
86 _ => return false,
87 };
88
89 let e: hir::Enum = match sema.to_def(&variant.parent_enum()) {
90 Some(e) => e,
91 None => return false,
92 };
93 let e_ty = e.ty(sema.db);
94
95 let hir_enum_var: hir::EnumVariant = match sema.to_def(variant) {
96 Some(ev) => ev,
97 None => return false,
98 };
99 let var_ty = hir_enum_var.fields(sema.db)[0].signature_ty(sema.db);
100
101 e_ty.impls_trait(sema.db, from_trait, &[var_ty.clone()])
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107 use crate::helpers::{check_assist, check_assist_not_applicable};
108
109 #[test]
110 fn test_add_from_impl_for_enum() {
111 check_assist(
112 add_from_impl_for_enum,
113 "enum A { <|>One(u32) }",
114 r#"enum A { One(u32) }
115
116<|>impl From<u32> for A {
117 fn from(v: u32) -> Self {
118 A::One(v)
119 }
120}"#,
121 );
122 }
123
124 #[test]
125 fn test_add_from_impl_for_enum_complicated_path() {
126 check_assist(
127 add_from_impl_for_enum,
128 "enum A { <|>One(foo::bar::baz::Boo) }",
129 r#"enum A { One(foo::bar::baz::Boo) }
130
131<|>impl From<foo::bar::baz::Boo> for A {
132 fn from(v: foo::bar::baz::Boo) -> Self {
133 A::One(v)
134 }
135}"#,
136 );
137 }
138
139 #[test]
140 fn test_add_from_impl_no_element() {
141 check_assist_not_applicable(add_from_impl_for_enum, "enum A { <|>One }");
142 }
143
144 #[test]
145 fn test_add_from_impl_more_than_one_element_in_tuple() {
146 check_assist_not_applicable(add_from_impl_for_enum, "enum A { <|>One(u32, String) }");
147 }
148
149 #[test]
150 fn test_add_from_impl_struct_variant() {
151 check_assist_not_applicable(add_from_impl_for_enum, "enum A { <|>One { x: u32 } }");
152 }
153
154 #[test]
155 fn test_add_from_impl_already_exists() {
156 check_assist_not_applicable(
157 add_from_impl_for_enum,
158 r#"enum A { <|>One(u32), }
159
160impl From<u32> for A {
161 fn from(v: u32) -> Self {
162 A::One(v)
163 }
164}
165
166pub trait From<T> {
167 fn from(T) -> Self;
168}"#,
169 );
170 }
171
172 #[test]
173 fn test_add_from_impl_different_variant_impl_exists() {
174 check_assist(
175 add_from_impl_for_enum,
176 r#"enum A { <|>One(u32), Two(String), }
177
178impl From<String> for A {
179 fn from(v: String) -> Self {
180 A::Two(v)
181 }
182}
183
184pub trait From<T> {
185 fn from(T) -> Self;
186}"#,
187 r#"enum A { One(u32), Two(String), }
188
189<|>impl From<u32> for A {
190 fn from(v: u32) -> Self {
191 A::One(v)
192 }
193}
194
195impl From<String> for A {
196 fn from(v: String) -> Self {
197 A::Two(v)
198 }
199}
200
201pub trait From<T> {
202 fn from(T) -> Self;
203}"#,
204 );
205 }
206}
diff --git a/crates/ra_assists/src/handlers/add_function.rs b/crates/ra_assists/src/handlers/add_function.rs
new file mode 100644
index 000000000..488bae08f
--- /dev/null
+++ b/crates/ra_assists/src/handlers/add_function.rs
@@ -0,0 +1,788 @@
1use ra_syntax::{
2 ast::{self, AstNode},
3 SyntaxKind, SyntaxNode, TextUnit,
4};
5
6use crate::{Assist, AssistCtx, AssistId};
7use ast::{edit::IndentLevel, ArgListOwner, CallExpr, Expr};
8use hir::HirDisplay;
9use rustc_hash::{FxHashMap, FxHashSet};
10
11// Assist: add_function
12//
13// Adds a stub function with a signature matching the function under the cursor.
14//
15// ```
16// struct Baz;
17// fn baz() -> Baz { Baz }
18// fn foo() {
19// bar<|>("", baz());
20// }
21//
22// ```
23// ->
24// ```
25// struct Baz;
26// fn baz() -> Baz { Baz }
27// fn foo() {
28// bar("", baz());
29// }
30//
31// fn bar(arg: &str, baz: Baz) {
32// unimplemented!()
33// }
34//
35// ```
36pub(crate) fn add_function(ctx: AssistCtx) -> Option<Assist> {
37 let path_expr: ast::PathExpr = ctx.find_node_at_offset()?;
38 let call = path_expr.syntax().parent().and_then(ast::CallExpr::cast)?;
39 let path = path_expr.path()?;
40
41 if path.qualifier().is_some() {
42 return None;
43 }
44
45 if ctx.sema.resolve_path(&path).is_some() {
46 // The function call already resolves, no need to add a function
47 return None;
48 }
49
50 let function_builder = FunctionBuilder::from_call(&ctx, &call)?;
51
52 ctx.add_assist(AssistId("add_function"), "Add function", |edit| {
53 edit.target(call.syntax().text_range());
54
55 if let Some(function_template) = function_builder.render() {
56 edit.set_cursor(function_template.cursor_offset);
57 edit.insert(function_template.insert_offset, function_template.fn_def.to_string());
58 }
59 })
60}
61
62struct FunctionTemplate {
63 insert_offset: TextUnit,
64 cursor_offset: TextUnit,
65 fn_def: ast::SourceFile,
66}
67
68struct FunctionBuilder {
69 append_fn_at: SyntaxNode,
70 fn_name: ast::Name,
71 type_params: Option<ast::TypeParamList>,
72 params: ast::ParamList,
73}
74
75impl FunctionBuilder {
76 fn from_call(ctx: &AssistCtx, call: &ast::CallExpr) -> Option<Self> {
77 let append_fn_at = next_space_for_fn(&call)?;
78 let fn_name = fn_name(&call)?;
79 let (type_params, params) = fn_args(ctx, &call)?;
80 Some(Self { append_fn_at, fn_name, type_params, params })
81 }
82 fn render(self) -> Option<FunctionTemplate> {
83 let placeholder_expr = ast::make::expr_unimplemented();
84 let fn_body = ast::make::block_expr(vec![], Some(placeholder_expr));
85 let fn_def = ast::make::fn_def(self.fn_name, self.type_params, self.params, fn_body);
86 let fn_def = ast::make::add_newlines(2, fn_def);
87 let fn_def = IndentLevel::from_node(&self.append_fn_at).increase_indent(fn_def);
88 let insert_offset = self.append_fn_at.text_range().end();
89 let cursor_offset_from_fn_start = fn_def
90 .syntax()
91 .descendants()
92 .find_map(ast::MacroCall::cast)?
93 .syntax()
94 .text_range()
95 .start();
96 let cursor_offset = insert_offset + cursor_offset_from_fn_start;
97 Some(FunctionTemplate { insert_offset, cursor_offset, fn_def })
98 }
99}
100
101fn fn_name(call: &CallExpr) -> Option<ast::Name> {
102 let name = call.expr()?.syntax().to_string();
103 Some(ast::make::name(&name))
104}
105
106/// Computes the type variables and arguments required for the generated function
107fn fn_args(
108 ctx: &AssistCtx,
109 call: &CallExpr,
110) -> Option<(Option<ast::TypeParamList>, ast::ParamList)> {
111 let mut arg_names = Vec::new();
112 let mut arg_types = Vec::new();
113 for arg in call.arg_list()?.args() {
114 let arg_name = match fn_arg_name(&arg) {
115 Some(name) => name,
116 None => String::from("arg"),
117 };
118 arg_names.push(arg_name);
119 arg_types.push(match fn_arg_type(ctx, &arg) {
120 Some(ty) => ty,
121 None => String::from("()"),
122 });
123 }
124 deduplicate_arg_names(&mut arg_names);
125 let params = arg_names.into_iter().zip(arg_types).map(|(name, ty)| ast::make::param(name, ty));
126 Some((None, ast::make::param_list(params)))
127}
128
129/// Makes duplicate argument names unique by appending incrementing numbers.
130///
131/// ```
132/// let mut names: Vec<String> =
133/// vec!["foo".into(), "foo".into(), "bar".into(), "baz".into(), "bar".into()];
134/// deduplicate_arg_names(&mut names);
135/// let expected: Vec<String> =
136/// vec!["foo_1".into(), "foo_2".into(), "bar_1".into(), "baz".into(), "bar_2".into()];
137/// assert_eq!(names, expected);
138/// ```
139fn deduplicate_arg_names(arg_names: &mut Vec<String>) {
140 let arg_name_counts = arg_names.iter().fold(FxHashMap::default(), |mut m, name| {
141 *m.entry(name).or_insert(0) += 1;
142 m
143 });
144 let duplicate_arg_names: FxHashSet<String> = arg_name_counts
145 .into_iter()
146 .filter(|(_, count)| *count >= 2)
147 .map(|(name, _)| name.clone())
148 .collect();
149
150 let mut counter_per_name = FxHashMap::default();
151 for arg_name in arg_names.iter_mut() {
152 if duplicate_arg_names.contains(arg_name) {
153 let counter = counter_per_name.entry(arg_name.clone()).or_insert(1);
154 arg_name.push('_');
155 arg_name.push_str(&counter.to_string());
156 *counter += 1;
157 }
158 }
159}
160
161fn fn_arg_name(fn_arg: &Expr) -> Option<String> {
162 match fn_arg {
163 Expr::CastExpr(cast_expr) => fn_arg_name(&cast_expr.expr()?),
164 _ => Some(
165 fn_arg
166 .syntax()
167 .descendants()
168 .filter(|d| ast::NameRef::can_cast(d.kind()))
169 .last()?
170 .to_string(),
171 ),
172 }
173}
174
175fn fn_arg_type(ctx: &AssistCtx, fn_arg: &Expr) -> Option<String> {
176 let ty = ctx.sema.type_of_expr(fn_arg)?;
177 if ty.is_unknown() {
178 return None;
179 }
180 Some(ty.display(ctx.sema.db).to_string())
181}
182
183/// Returns the position inside the current mod or file
184/// directly after the current block
185/// We want to write the generated function directly after
186/// fns, impls or macro calls, but inside mods
187fn next_space_for_fn(expr: &CallExpr) -> Option<SyntaxNode> {
188 let mut ancestors = expr.syntax().ancestors().peekable();
189 let mut last_ancestor: Option<SyntaxNode> = None;
190 while let Some(next_ancestor) = ancestors.next() {
191 match next_ancestor.kind() {
192 SyntaxKind::SOURCE_FILE => {
193 break;
194 }
195 SyntaxKind::ITEM_LIST => {
196 if ancestors.peek().map(|a| a.kind()) == Some(SyntaxKind::MODULE) {
197 break;
198 }
199 }
200 _ => {}
201 }
202 last_ancestor = Some(next_ancestor);
203 }
204 last_ancestor
205}
206
207#[cfg(test)]
208mod tests {
209 use crate::helpers::{check_assist, check_assist_not_applicable};
210
211 use super::*;
212
213 #[test]
214 fn add_function_with_no_args() {
215 check_assist(
216 add_function,
217 r"
218fn foo() {
219 bar<|>();
220}
221",
222 r"
223fn foo() {
224 bar();
225}
226
227fn bar() {
228 <|>unimplemented!()
229}
230",
231 )
232 }
233
234 #[test]
235 fn add_function_from_method() {
236 // This ensures that the function is correctly generated
237 // in the next outer mod or file
238 check_assist(
239 add_function,
240 r"
241impl Foo {
242 fn foo() {
243 bar<|>();
244 }
245}
246",
247 r"
248impl Foo {
249 fn foo() {
250 bar();
251 }
252}
253
254fn bar() {
255 <|>unimplemented!()
256}
257",
258 )
259 }
260
261 #[test]
262 fn add_function_directly_after_current_block() {
263 // The new fn should not be created at the end of the file or module
264 check_assist(
265 add_function,
266 r"
267fn foo1() {
268 bar<|>();
269}
270
271fn foo2() {}
272",
273 r"
274fn foo1() {
275 bar();
276}
277
278fn bar() {
279 <|>unimplemented!()
280}
281
282fn foo2() {}
283",
284 )
285 }
286
287 #[test]
288 fn add_function_with_no_args_in_same_module() {
289 check_assist(
290 add_function,
291 r"
292mod baz {
293 fn foo() {
294 bar<|>();
295 }
296}
297",
298 r"
299mod baz {
300 fn foo() {
301 bar();
302 }
303
304 fn bar() {
305 <|>unimplemented!()
306 }
307}
308",
309 )
310 }
311
312 #[test]
313 fn add_function_with_function_call_arg() {
314 check_assist(
315 add_function,
316 r"
317struct Baz;
318fn baz() -> Baz { unimplemented!() }
319fn foo() {
320 bar<|>(baz());
321}
322",
323 r"
324struct Baz;
325fn baz() -> Baz { unimplemented!() }
326fn foo() {
327 bar(baz());
328}
329
330fn bar(baz: Baz) {
331 <|>unimplemented!()
332}
333",
334 );
335 }
336
337 #[test]
338 fn add_function_with_method_call_arg() {
339 check_assist(
340 add_function,
341 r"
342struct Baz;
343impl Baz {
344 fn foo(&self) -> Baz {
345 ba<|>r(self.baz())
346 }
347 fn baz(&self) -> Baz {
348 Baz
349 }
350}
351",
352 r"
353struct Baz;
354impl Baz {
355 fn foo(&self) -> Baz {
356 bar(self.baz())
357 }
358 fn baz(&self) -> Baz {
359 Baz
360 }
361}
362
363fn bar(baz: Baz) {
364 <|>unimplemented!()
365}
366",
367 )
368 }
369
370 #[test]
371 fn add_function_with_string_literal_arg() {
372 check_assist(
373 add_function,
374 r#"
375fn foo() {
376 <|>bar("bar")
377}
378"#,
379 r#"
380fn foo() {
381 bar("bar")
382}
383
384fn bar(arg: &str) {
385 <|>unimplemented!()
386}
387"#,
388 )
389 }
390
391 #[test]
392 fn add_function_with_char_literal_arg() {
393 check_assist(
394 add_function,
395 r#"
396fn foo() {
397 <|>bar('x')
398}
399"#,
400 r#"
401fn foo() {
402 bar('x')
403}
404
405fn bar(arg: char) {
406 <|>unimplemented!()
407}
408"#,
409 )
410 }
411
412 #[test]
413 fn add_function_with_int_literal_arg() {
414 check_assist(
415 add_function,
416 r"
417fn foo() {
418 <|>bar(42)
419}
420",
421 r"
422fn foo() {
423 bar(42)
424}
425
426fn bar(arg: i32) {
427 <|>unimplemented!()
428}
429",
430 )
431 }
432
433 #[test]
434 fn add_function_with_cast_int_literal_arg() {
435 check_assist(
436 add_function,
437 r"
438fn foo() {
439 <|>bar(42 as u8)
440}
441",
442 r"
443fn foo() {
444 bar(42 as u8)
445}
446
447fn bar(arg: u8) {
448 <|>unimplemented!()
449}
450",
451 )
452 }
453
454 #[test]
455 fn name_of_cast_variable_is_used() {
456 // Ensures that the name of the cast type isn't used
457 // in the generated function signature.
458 check_assist(
459 add_function,
460 r"
461fn foo() {
462 let x = 42;
463 bar<|>(x as u8)
464}
465",
466 r"
467fn foo() {
468 let x = 42;
469 bar(x as u8)
470}
471
472fn bar(x: u8) {
473 <|>unimplemented!()
474}
475",
476 )
477 }
478
479 #[test]
480 fn add_function_with_variable_arg() {
481 check_assist(
482 add_function,
483 r"
484fn foo() {
485 let worble = ();
486 <|>bar(worble)
487}
488",
489 r"
490fn foo() {
491 let worble = ();
492 bar(worble)
493}
494
495fn bar(worble: ()) {
496 <|>unimplemented!()
497}
498",
499 )
500 }
501
502 #[test]
503 fn add_function_with_impl_trait_arg() {
504 check_assist(
505 add_function,
506 r"
507trait Foo {}
508fn foo() -> impl Foo {
509 unimplemented!()
510}
511fn baz() {
512 <|>bar(foo())
513}
514",
515 r"
516trait Foo {}
517fn foo() -> impl Foo {
518 unimplemented!()
519}
520fn baz() {
521 bar(foo())
522}
523
524fn bar(foo: impl Foo) {
525 <|>unimplemented!()
526}
527",
528 )
529 }
530
531 #[test]
532 #[ignore]
533 // FIXME print paths properly to make this test pass
534 fn add_function_with_qualified_path_arg() {
535 check_assist(
536 add_function,
537 r"
538mod Baz {
539 pub struct Bof;
540 pub fn baz() -> Bof { Bof }
541}
542mod Foo {
543 fn foo() {
544 <|>bar(super::Baz::baz())
545 }
546}
547",
548 r"
549mod Baz {
550 pub struct Bof;
551 pub fn baz() -> Bof { Bof }
552}
553mod Foo {
554 fn foo() {
555 bar(super::Baz::baz())
556 }
557
558 fn bar(baz: super::Baz::Bof) {
559 <|>unimplemented!()
560 }
561}
562",
563 )
564 }
565
566 #[test]
567 #[ignore]
568 // FIXME fix printing the generics of a `Ty` to make this test pass
569 fn add_function_with_generic_arg() {
570 check_assist(
571 add_function,
572 r"
573fn foo<T>(t: T) {
574 <|>bar(t)
575}
576",
577 r"
578fn foo<T>(t: T) {
579 bar(t)
580}
581
582fn bar<T>(t: T) {
583 <|>unimplemented!()
584}
585",
586 )
587 }
588
589 #[test]
590 #[ignore]
591 // FIXME Fix function type printing to make this test pass
592 fn add_function_with_fn_arg() {
593 check_assist(
594 add_function,
595 r"
596struct Baz;
597impl Baz {
598 fn new() -> Self { Baz }
599}
600fn foo() {
601 <|>bar(Baz::new);
602}
603",
604 r"
605struct Baz;
606impl Baz {
607 fn new() -> Self { Baz }
608}
609fn foo() {
610 bar(Baz::new);
611}
612
613fn bar(arg: fn() -> Baz) {
614 <|>unimplemented!()
615}
616",
617 )
618 }
619
620 #[test]
621 #[ignore]
622 // FIXME Fix closure type printing to make this test pass
623 fn add_function_with_closure_arg() {
624 check_assist(
625 add_function,
626 r"
627fn foo() {
628 let closure = |x: i64| x - 1;
629 <|>bar(closure)
630}
631",
632 r"
633fn foo() {
634 let closure = |x: i64| x - 1;
635 bar(closure)
636}
637
638fn bar(closure: impl Fn(i64) -> i64) {
639 <|>unimplemented!()
640}
641",
642 )
643 }
644
645 #[test]
646 fn unresolveable_types_default_to_unit() {
647 check_assist(
648 add_function,
649 r"
650fn foo() {
651 <|>bar(baz)
652}
653",
654 r"
655fn foo() {
656 bar(baz)
657}
658
659fn bar(baz: ()) {
660 <|>unimplemented!()
661}
662",
663 )
664 }
665
666 #[test]
667 fn arg_names_dont_overlap() {
668 check_assist(
669 add_function,
670 r"
671struct Baz;
672fn baz() -> Baz { Baz }
673fn foo() {
674 <|>bar(baz(), baz())
675}
676",
677 r"
678struct Baz;
679fn baz() -> Baz { Baz }
680fn foo() {
681 bar(baz(), baz())
682}
683
684fn bar(baz_1: Baz, baz_2: Baz) {
685 <|>unimplemented!()
686}
687",
688 )
689 }
690
691 #[test]
692 fn arg_name_counters_start_at_1_per_name() {
693 check_assist(
694 add_function,
695 r#"
696struct Baz;
697fn baz() -> Baz { Baz }
698fn foo() {
699 <|>bar(baz(), baz(), "foo", "bar")
700}
701"#,
702 r#"
703struct Baz;
704fn baz() -> Baz { Baz }
705fn foo() {
706 bar(baz(), baz(), "foo", "bar")
707}
708
709fn bar(baz_1: Baz, baz_2: Baz, arg_1: &str, arg_2: &str) {
710 <|>unimplemented!()
711}
712"#,
713 )
714 }
715
716 #[test]
717 fn add_function_not_applicable_if_function_already_exists() {
718 check_assist_not_applicable(
719 add_function,
720 r"
721fn foo() {
722 bar<|>();
723}
724
725fn bar() {}
726",
727 )
728 }
729
730 #[test]
731 fn add_function_not_applicable_if_unresolved_variable_in_call_is_selected() {
732 check_assist_not_applicable(
733 // bar is resolved, but baz isn't.
734 // The assist is only active if the cursor is on an unresolved path,
735 // but the assist should only be offered if the path is a function call.
736 add_function,
737 r"
738fn foo() {
739 bar(b<|>az);
740}
741
742fn bar(baz: ()) {}
743",
744 )
745 }
746
747 #[test]
748 fn add_function_not_applicable_if_function_path_not_singleton() {
749 // In the future this assist could be extended to generate functions
750 // if the path is in the same crate (or even the same workspace).
751 // For the beginning, I think this is fine.
752 check_assist_not_applicable(
753 add_function,
754 r"
755fn foo() {
756 other_crate::bar<|>();
757}
758 ",
759 )
760 }
761
762 #[test]
763 #[ignore]
764 fn create_method_with_no_args() {
765 check_assist(
766 add_function,
767 r"
768struct Foo;
769impl Foo {
770 fn foo(&self) {
771 self.bar()<|>;
772 }
773}
774 ",
775 r"
776struct Foo;
777impl Foo {
778 fn foo(&self) {
779 self.bar();
780 }
781 fn bar(&self) {
782 unimplemented!();
783 }
784}
785 ",
786 )
787 }
788}
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs
index fa1f3dd26..fa3d3913f 100644
--- a/crates/ra_assists/src/lib.rs
+++ b/crates/ra_assists/src/lib.rs
@@ -96,6 +96,7 @@ mod handlers {
96 mod add_custom_impl; 96 mod add_custom_impl;
97 mod add_derive; 97 mod add_derive;
98 mod add_explicit_type; 98 mod add_explicit_type;
99 mod add_function;
99 mod add_impl; 100 mod add_impl;
100 mod add_missing_impl_members; 101 mod add_missing_impl_members;
101 mod add_new; 102 mod add_new;
@@ -122,12 +123,14 @@ mod handlers {
122 mod replace_qualified_name_with_use; 123 mod replace_qualified_name_with_use;
123 mod replace_unwrap_with_match; 124 mod replace_unwrap_with_match;
124 mod split_import; 125 mod split_import;
126 mod add_from_impl_for_enum;
125 127
126 pub(crate) fn all() -> &'static [AssistHandler] { 128 pub(crate) fn all() -> &'static [AssistHandler] {
127 &[ 129 &[
128 add_custom_impl::add_custom_impl, 130 add_custom_impl::add_custom_impl,
129 add_derive::add_derive, 131 add_derive::add_derive,
130 add_explicit_type::add_explicit_type, 132 add_explicit_type::add_explicit_type,
133 add_function::add_function,
131 add_impl::add_impl, 134 add_impl::add_impl,
132 add_missing_impl_members::add_missing_default_members, 135 add_missing_impl_members::add_missing_default_members,
133 add_missing_impl_members::add_missing_impl_members, 136 add_missing_impl_members::add_missing_impl_members,
@@ -159,6 +162,7 @@ mod handlers {
159 replace_qualified_name_with_use::replace_qualified_name_with_use, 162 replace_qualified_name_with_use::replace_qualified_name_with_use,
160 replace_unwrap_with_match::replace_unwrap_with_match, 163 replace_unwrap_with_match::replace_unwrap_with_match,
161 split_import::split_import, 164 split_import::split_import,
165 add_from_impl_for_enum::add_from_impl_for_enum,
162 ] 166 ]
163 } 167 }
164} 168}
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index cd2a8fc62..c6f3bdb8e 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -1084,6 +1084,26 @@ impl Type {
1084 ) 1084 )
1085 } 1085 }
1086 1086
1087 pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool {
1088 let trait_ref = hir_ty::TraitRef {
1089 trait_: trait_.id,
1090 substs: Substs::build_for_def(db, trait_.id)
1091 .push(self.ty.value.clone())
1092 .fill(args.iter().map(|t| t.ty.value.clone()))
1093 .build(),
1094 };
1095
1096 let goal = Canonical {
1097 value: hir_ty::InEnvironment::new(
1098 self.ty.environment.clone(),
1099 hir_ty::Obligation::Trait(trait_ref),
1100 ),
1101 num_vars: 0,
1102 };
1103
1104 db.trait_solve(self.krate, goal).is_some()
1105 }
1106
1087 // FIXME: this method is broken, as it doesn't take closures into account. 1107 // FIXME: this method is broken, as it doesn't take closures into account.
1088 pub fn as_callable(&self) -> Option<CallableDef> { 1108 pub fn as_callable(&self) -> Option<CallableDef> {
1089 Some(self.ty.value.as_callable()?.0) 1109 Some(self.ty.value.as_callable()?.0)
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index 28c570c76..8d4b8b0f0 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -672,8 +672,7 @@ impl ExprCollector<'_> {
672 } 672 }
673 673
674 // FIXME: implement 674 // FIXME: implement
675 ast::Pat::BoxPat(_) => Pat::Missing, 675 ast::Pat::BoxPat(_) | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing,
676 ast::Pat::RangePat(_) => Pat::Missing,
677 }; 676 };
678 let ptr = AstPtr::new(&pat); 677 let ptr = AstPtr::new(&pat);
679 self.alloc_pat(pattern, Either::Left(ptr)) 678 self.alloc_pat(pattern, Either::Left(ptr))
diff --git a/crates/ra_hir_def/src/type_ref.rs b/crates/ra_hir_def/src/type_ref.rs
index 102fdb13d..01cc392db 100644
--- a/crates/ra_hir_def/src/type_ref.rs
+++ b/crates/ra_hir_def/src/type_ref.rs
@@ -93,7 +93,11 @@ impl TypeRef {
93 } 93 }
94 ast::TypeRef::PlaceholderType(_inner) => TypeRef::Placeholder, 94 ast::TypeRef::PlaceholderType(_inner) => TypeRef::Placeholder,
95 ast::TypeRef::FnPointerType(inner) => { 95 ast::TypeRef::FnPointerType(inner) => {
96 let ret_ty = TypeRef::from_ast_opt(inner.ret_type().and_then(|rt| rt.type_ref())); 96 let ret_ty = inner
97 .ret_type()
98 .and_then(|rt| rt.type_ref())
99 .map(TypeRef::from_ast)
100 .unwrap_or_else(|| TypeRef::Tuple(Vec::new()));
97 let mut params = if let Some(pl) = inner.param_list() { 101 let mut params = if let Some(pl) = inner.param_list() {
98 pl.params().map(|p| p.ascribed_type()).map(TypeRef::from_ast_opt).collect() 102 pl.params().map(|p| p.ascribed_type()).map(TypeRef::from_ast_opt).collect()
99 } else { 103 } else {
diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml
index 5a58d70cf..45be08430 100644
--- a/crates/ra_hir_ty/Cargo.toml
+++ b/crates/ra_hir_ty/Cargo.toml
@@ -23,9 +23,9 @@ ra_prof = { path = "../ra_prof" }
23ra_syntax = { path = "../ra_syntax" } 23ra_syntax = { path = "../ra_syntax" }
24test_utils = { path = "../test_utils" } 24test_utils = { path = "../test_utils" }
25 25
26chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "177d71340acc7a7204a33115fc63075d86452179" } 26chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" }
27chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "177d71340acc7a7204a33115fc63075d86452179" } 27chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" }
28chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "177d71340acc7a7204a33115fc63075d86452179" } 28chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "039fc904a05f8cb3d0c682c9a57a63dda7a35356" }
29 29
30[dev-dependencies] 30[dev-dependencies]
31insta = "0.15.0" 31insta = "0.15.0"
diff --git a/crates/ra_hir_ty/src/autoderef.rs b/crates/ra_hir_ty/src/autoderef.rs
index 53e81e85d..d91c21e24 100644
--- a/crates/ra_hir_ty/src/autoderef.rs
+++ b/crates/ra_hir_ty/src/autoderef.rs
@@ -14,7 +14,7 @@ use crate::{
14 db::HirDatabase, 14 db::HirDatabase,
15 traits::{InEnvironment, Solution}, 15 traits::{InEnvironment, Solution},
16 utils::generics, 16 utils::generics,
17 Canonical, Substs, Ty, TypeWalk, 17 BoundVar, Canonical, DebruijnIndex, Substs, Ty,
18}; 18};
19 19
20const AUTODEREF_RECURSION_LIMIT: usize = 10; 20const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -61,14 +61,13 @@ fn deref_by_trait(
61 return None; 61 return None;
62 } 62 }
63 63
64 // FIXME make the Canonical handling nicer 64 // FIXME make the Canonical / bound var handling nicer
65 65
66 let parameters = Substs::build_for_generics(&generic_params) 66 let parameters =
67 .push(ty.value.value.clone().shift_bound_vars(1)) 67 Substs::build_for_generics(&generic_params).push(ty.value.value.clone()).build();
68 .build();
69 68
70 let projection = super::traits::ProjectionPredicate { 69 let projection = super::traits::ProjectionPredicate {
71 ty: Ty::Bound(0), 70 ty: Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.num_vars)),
72 projection_ty: super::ProjectionTy { associated_ty: target, parameters }, 71 projection_ty: super::ProjectionTy { associated_ty: target, parameters },
73 }; 72 };
74 73
@@ -93,12 +92,16 @@ fn deref_by_trait(
93 // we have `impl<T> Deref for Foo<T> { Target = T }`, that should be 92 // we have `impl<T> Deref for Foo<T> { Target = T }`, that should be
94 // the case. 93 // the case.
95 for i in 1..vars.0.num_vars { 94 for i in 1..vars.0.num_vars {
96 if vars.0.value[i] != Ty::Bound((i - 1) as u32) { 95 if vars.0.value[i - 1] != Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
96 {
97 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution); 97 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution);
98 return None; 98 return None;
99 } 99 }
100 } 100 }
101 Some(Canonical { value: vars.0.value[0].clone(), num_vars: vars.0.num_vars }) 101 Some(Canonical {
102 value: vars.0.value[vars.0.value.len() - 1].clone(),
103 num_vars: vars.0.num_vars,
104 })
102 } 105 }
103 Solution::Ambig(_) => { 106 Solution::Ambig(_) => {
104 info!("Ambiguous solution for derefing {:?}: {:?}", ty.value, solution); 107 info!("Ambiguous solution for derefing {:?}: {:?}", ty.value, solution);
diff --git a/crates/ra_hir_ty/src/display.rs b/crates/ra_hir_ty/src/display.rs
index 13ecd537a..0e9313aa1 100644
--- a/crates/ra_hir_ty/src/display.rs
+++ b/crates/ra_hir_ty/src/display.rs
@@ -155,7 +155,11 @@ impl HirDisplay for ApplicationTy {
155 let sig = FnSig::from_fn_ptr_substs(&self.parameters); 155 let sig = FnSig::from_fn_ptr_substs(&self.parameters);
156 write!(f, "fn(")?; 156 write!(f, "fn(")?;
157 f.write_joined(sig.params(), ", ")?; 157 f.write_joined(sig.params(), ", ")?;
158 write!(f, ") -> {}", sig.ret().display(f.db))?; 158 write!(f, ")")?;
159 let ret = sig.ret();
160 if *ret != Ty::unit() {
161 write!(f, " -> {}", ret.display(f.db))?;
162 }
159 } 163 }
160 TypeCtor::FnDef(def) => { 164 TypeCtor::FnDef(def) => {
161 let sig = f.db.callable_item_signature(def).subst(&self.parameters); 165 let sig = f.db.callable_item_signature(def).subst(&self.parameters);
@@ -180,7 +184,11 @@ impl HirDisplay for ApplicationTy {
180 } 184 }
181 write!(f, "(")?; 185 write!(f, "(")?;
182 f.write_joined(sig.params(), ", ")?; 186 f.write_joined(sig.params(), ", ")?;
183 write!(f, ") -> {}", sig.ret().display(f.db))?; 187 write!(f, ")")?;
188 let ret = sig.ret();
189 if *ret != Ty::unit() {
190 write!(f, " -> {}", ret.display(f.db))?;
191 }
184 } 192 }
185 TypeCtor::Adt(def_id) => { 193 TypeCtor::Adt(def_id) => {
186 let name = match def_id { 194 let name = match def_id {
@@ -242,16 +250,16 @@ impl HirDisplay for ApplicationTy {
242 let sig = self.parameters[0] 250 let sig = self.parameters[0]
243 .callable_sig(f.db) 251 .callable_sig(f.db)
244 .expect("first closure parameter should contain signature"); 252 .expect("first closure parameter should contain signature");
245 let return_type_hint = sig.ret().display(f.db);
246 if sig.params().is_empty() { 253 if sig.params().is_empty() {
247 write!(f, "|| -> {}", return_type_hint)?; 254 write!(f, "||")?;
248 } else if f.omit_verbose_types() { 255 } else if f.omit_verbose_types() {
249 write!(f, "|{}| -> {}", TYPE_HINT_TRUNCATION, return_type_hint)?; 256 write!(f, "|{}|", TYPE_HINT_TRUNCATION)?;
250 } else { 257 } else {
251 write!(f, "|")?; 258 write!(f, "|")?;
252 f.write_joined(sig.params(), ", ")?; 259 f.write_joined(sig.params(), ", ")?;
253 write!(f, "| -> {}", return_type_hint)?; 260 write!(f, "|")?;
254 }; 261 };
262 write!(f, " -> {}", sig.ret().display(f.db))?;
255 } 263 }
256 } 264 }
257 Ok(()) 265 Ok(())
@@ -303,7 +311,7 @@ impl HirDisplay for Ty {
303 } 311 }
304 } 312 }
305 } 313 }
306 Ty::Bound(idx) => write!(f, "?{}", idx)?, 314 Ty::Bound(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?,
307 Ty::Dyn(predicates) | Ty::Opaque(predicates) => { 315 Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
308 match self { 316 match self {
309 Ty::Dyn(_) => write!(f, "dyn ")?, 317 Ty::Dyn(_) => write!(f, "dyn ")?,
diff --git a/crates/ra_hir_ty/src/infer/unify.rs b/crates/ra_hir_ty/src/infer/unify.rs
index 0bf8fbd63..ac25f8a80 100644
--- a/crates/ra_hir_ty/src/infer/unify.rs
+++ b/crates/ra_hir_ty/src/infer/unify.rs
@@ -7,7 +7,9 @@ use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
7use test_utils::tested_by; 7use test_utils::tested_by;
8 8
9use super::{InferenceContext, Obligation}; 9use super::{InferenceContext, Obligation};
10use crate::{Canonical, InEnvironment, InferTy, Substs, Ty, TypeCtor, TypeWalk}; 10use crate::{
11 BoundVar, Canonical, DebruijnIndex, InEnvironment, InferTy, Substs, Ty, TypeCtor, TypeWalk,
12};
11 13
12impl<'a> InferenceContext<'a> { 14impl<'a> InferenceContext<'a> {
13 pub(super) fn canonicalizer<'b>(&'b mut self) -> Canonicalizer<'a, 'b> 15 pub(super) fn canonicalizer<'b>(&'b mut self) -> Canonicalizer<'a, 'b>
@@ -47,7 +49,7 @@ where
47 }) 49 })
48 } 50 }
49 51
50 fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: usize) -> T { 52 fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T {
51 t.fold_binders( 53 t.fold_binders(
52 &mut |ty, binders| match ty { 54 &mut |ty, binders| match ty {
53 Ty::Infer(tv) => { 55 Ty::Infer(tv) => {
@@ -72,7 +74,7 @@ where
72 InferTy::MaybeNeverTypeVar(_) => InferTy::MaybeNeverTypeVar(root), 74 InferTy::MaybeNeverTypeVar(_) => InferTy::MaybeNeverTypeVar(root),
73 }; 75 };
74 let position = self.add(free_var); 76 let position = self.add(free_var);
75 Ty::Bound((position + binders) as u32) 77 Ty::Bound(BoundVar::new(binders, position))
76 } 78 }
77 } 79 }
78 _ => ty, 80 _ => ty,
@@ -89,7 +91,7 @@ where
89 } 91 }
90 92
91 pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> { 93 pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> {
92 let result = self.do_canonicalize(ty, 0); 94 let result = self.do_canonicalize(ty, DebruijnIndex::INNERMOST);
93 self.into_canonicalized(result) 95 self.into_canonicalized(result)
94 } 96 }
95 97
@@ -98,8 +100,12 @@ where
98 obligation: InEnvironment<Obligation>, 100 obligation: InEnvironment<Obligation>,
99 ) -> Canonicalized<InEnvironment<Obligation>> { 101 ) -> Canonicalized<InEnvironment<Obligation>> {
100 let result = match obligation.value { 102 let result = match obligation.value {
101 Obligation::Trait(tr) => Obligation::Trait(self.do_canonicalize(tr, 0)), 103 Obligation::Trait(tr) => {
102 Obligation::Projection(pr) => Obligation::Projection(self.do_canonicalize(pr, 0)), 104 Obligation::Trait(self.do_canonicalize(tr, DebruijnIndex::INNERMOST))
105 }
106 Obligation::Projection(pr) => {
107 Obligation::Projection(self.do_canonicalize(pr, DebruijnIndex::INNERMOST))
108 }
103 }; 109 };
104 self.into_canonicalized(InEnvironment { 110 self.into_canonicalized(InEnvironment {
105 value: result, 111 value: result,
@@ -112,13 +118,13 @@ impl<T> Canonicalized<T> {
112 pub fn decanonicalize_ty(&self, mut ty: Ty) -> Ty { 118 pub fn decanonicalize_ty(&self, mut ty: Ty) -> Ty {
113 ty.walk_mut_binders( 119 ty.walk_mut_binders(
114 &mut |ty, binders| { 120 &mut |ty, binders| {
115 if let &mut Ty::Bound(idx) = ty { 121 if let &mut Ty::Bound(bound) = ty {
116 if idx as usize >= binders && (idx as usize - binders) < self.free_vars.len() { 122 if bound.debruijn >= binders {
117 *ty = Ty::Infer(self.free_vars[idx as usize - binders]); 123 *ty = Ty::Infer(self.free_vars[bound.index]);
118 } 124 }
119 } 125 }
120 }, 126 },
121 0, 127 DebruijnIndex::INNERMOST,
122 ); 128 );
123 ty 129 ty
124 } 130 }
@@ -150,7 +156,7 @@ pub fn unify(ty1: &Canonical<Ty>, ty2: &Canonical<Ty>) -> Option<Substs> {
150 // (kind of hacky) 156 // (kind of hacky)
151 for (i, var) in vars.iter().enumerate() { 157 for (i, var) in vars.iter().enumerate() {
152 if &*table.resolve_ty_shallow(var) == var { 158 if &*table.resolve_ty_shallow(var) == var {
153 table.unify(var, &Ty::Bound(i as u32)); 159 table.unify(var, &Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, i)));
154 } 160 }
155 } 161 }
156 Some( 162 Some(
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index 6c5469ecd..a9022dee7 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -64,6 +64,8 @@ pub use lower::{
64}; 64};
65pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; 65pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};
66 66
67pub use chalk_ir::{BoundVar, DebruijnIndex};
68
67/// A type constructor or type name: this might be something like the primitive 69/// A type constructor or type name: this might be something like the primitive
68/// type `bool`, a struct like `Vec`, or things like function pointers or 70/// type `bool`, a struct like `Vec`, or things like function pointers or
69/// tuples. 71/// tuples.
@@ -265,7 +267,11 @@ impl TypeWalk for ProjectionTy {
265 self.parameters.walk(f); 267 self.parameters.walk(f);
266 } 268 }
267 269
268 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { 270 fn walk_mut_binders(
271 &mut self,
272 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
273 binders: DebruijnIndex,
274 ) {
269 self.parameters.walk_mut_binders(f, binders); 275 self.parameters.walk_mut_binders(f, binders);
270 } 276 }
271} 277}
@@ -299,7 +305,7 @@ pub enum Ty {
299 /// parameters get turned into variables; during trait resolution, inference 305 /// parameters get turned into variables; during trait resolution, inference
300 /// variables get turned into bound variables and back; and in `Dyn` the 306 /// variables get turned into bound variables and back; and in `Dyn` the
301 /// `Self` type is represented with a bound variable as well. 307 /// `Self` type is represented with a bound variable as well.
302 Bound(u32), 308 Bound(BoundVar),
303 309
304 /// A type variable used during type checking. 310 /// A type variable used during type checking.
305 Infer(InferTy), 311 Infer(InferTy),
@@ -337,7 +343,11 @@ impl TypeWalk for Substs {
337 } 343 }
338 } 344 }
339 345
340 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { 346 fn walk_mut_binders(
347 &mut self,
348 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
349 binders: DebruijnIndex,
350 ) {
341 for t in make_mut_slice(&mut self.0) { 351 for t in make_mut_slice(&mut self.0) {
342 t.walk_mut_binders(f, binders); 352 t.walk_mut_binders(f, binders);
343 } 353 }
@@ -381,7 +391,13 @@ impl Substs {
381 391
382 /// Return Substs that replace each parameter by a bound variable. 392 /// Return Substs that replace each parameter by a bound variable.
383 pub(crate) fn bound_vars(generic_params: &Generics) -> Substs { 393 pub(crate) fn bound_vars(generic_params: &Generics) -> Substs {
384 Substs(generic_params.iter().enumerate().map(|(idx, _)| Ty::Bound(idx as u32)).collect()) 394 Substs(
395 generic_params
396 .iter()
397 .enumerate()
398 .map(|(idx, _)| Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, idx)))
399 .collect(),
400 )
385 } 401 }
386 402
387 pub fn build_for_def(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> SubstsBuilder { 403 pub fn build_for_def(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> SubstsBuilder {
@@ -425,8 +441,8 @@ impl SubstsBuilder {
425 self.param_count - self.vec.len() 441 self.param_count - self.vec.len()
426 } 442 }
427 443
428 pub fn fill_with_bound_vars(self, starting_from: u32) -> Self { 444 pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self {
429 self.fill((starting_from..).map(Ty::Bound)) 445 self.fill((starting_from..).map(|idx| Ty::Bound(BoundVar::new(debruijn, idx))))
430 } 446 }
431 447
432 pub fn fill_with_unknown(self) -> Self { 448 pub fn fill_with_unknown(self) -> Self {
@@ -507,7 +523,11 @@ impl TypeWalk for TraitRef {
507 self.substs.walk(f); 523 self.substs.walk(f);
508 } 524 }
509 525
510 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { 526 fn walk_mut_binders(
527 &mut self,
528 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
529 binders: DebruijnIndex,
530 ) {
511 self.substs.walk_mut_binders(f, binders); 531 self.substs.walk_mut_binders(f, binders);
512 } 532 }
513} 533}
@@ -558,7 +578,11 @@ impl TypeWalk for GenericPredicate {
558 } 578 }
559 } 579 }
560 580
561 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { 581 fn walk_mut_binders(
582 &mut self,
583 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
584 binders: DebruijnIndex,
585 ) {
562 match self { 586 match self {
563 GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders), 587 GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders),
564 GenericPredicate::Projection(projection_pred) => { 588 GenericPredicate::Projection(projection_pred) => {
@@ -616,7 +640,11 @@ impl TypeWalk for FnSig {
616 } 640 }
617 } 641 }
618 642
619 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { 643 fn walk_mut_binders(
644 &mut self,
645 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
646 binders: DebruijnIndex,
647 ) {
620 for t in make_mut_slice(&mut self.params_and_return) { 648 for t in make_mut_slice(&mut self.params_and_return) {
621 t.walk_mut_binders(f, binders); 649 t.walk_mut_binders(f, binders);
622 } 650 }
@@ -755,7 +783,7 @@ impl Ty {
755pub trait TypeWalk { 783pub trait TypeWalk {
756 fn walk(&self, f: &mut impl FnMut(&Ty)); 784 fn walk(&self, f: &mut impl FnMut(&Ty));
757 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { 785 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
758 self.walk_mut_binders(&mut |ty, _binders| f(ty), 0); 786 self.walk_mut_binders(&mut |ty, _binders| f(ty), DebruijnIndex::INNERMOST);
759 } 787 }
760 /// Walk the type, counting entered binders. 788 /// Walk the type, counting entered binders.
761 /// 789 ///
@@ -767,9 +795,17 @@ pub trait TypeWalk {
767 /// that. Currently, the only thing that introduces bound variables on our 795 /// that. Currently, the only thing that introduces bound variables on our
768 /// side are `Ty::Dyn` and `Ty::Opaque`, which each introduce a bound 796 /// side are `Ty::Dyn` and `Ty::Opaque`, which each introduce a bound
769 /// variable for the self type. 797 /// variable for the self type.
770 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize); 798 fn walk_mut_binders(
771 799 &mut self,
772 fn fold_binders(mut self, f: &mut impl FnMut(Ty, usize) -> Ty, binders: usize) -> Self 800 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
801 binders: DebruijnIndex,
802 );
803
804 fn fold_binders(
805 mut self,
806 f: &mut impl FnMut(Ty, DebruijnIndex) -> Ty,
807 binders: DebruijnIndex,
808 ) -> Self
773 where 809 where
774 Self: Sized, 810 Self: Sized,
775 { 811 {
@@ -795,40 +831,43 @@ pub trait TypeWalk {
795 } 831 }
796 832
797 /// Substitutes `Ty::Bound` vars with the given substitution. 833 /// Substitutes `Ty::Bound` vars with the given substitution.
798 fn subst_bound_vars(mut self, substs: &Substs) -> Self 834 fn subst_bound_vars(self, substs: &Substs) -> Self
835 where
836 Self: Sized,
837 {
838 self.subst_bound_vars_at_depth(substs, DebruijnIndex::INNERMOST)
839 }
840
841 /// Substitutes `Ty::Bound` vars with the given substitution.
842 fn subst_bound_vars_at_depth(mut self, substs: &Substs, depth: DebruijnIndex) -> Self
799 where 843 where
800 Self: Sized, 844 Self: Sized,
801 { 845 {
802 self.walk_mut_binders( 846 self.walk_mut_binders(
803 &mut |ty, binders| { 847 &mut |ty, binders| {
804 if let &mut Ty::Bound(idx) = ty { 848 if let &mut Ty::Bound(bound) = ty {
805 if idx as usize >= binders && (idx as usize - binders) < substs.len() { 849 if bound.debruijn >= binders {
806 *ty = substs.0[idx as usize - binders].clone(); 850 *ty = substs.0[bound.index].clone();
807 } else if idx as usize >= binders + substs.len() {
808 // shift free binders
809 *ty = Ty::Bound(idx - substs.len() as u32);
810 } 851 }
811 } 852 }
812 }, 853 },
813 0, 854 depth,
814 ); 855 );
815 self 856 self
816 } 857 }
817 858 // /// Shifts up debruijn indices of `Ty::Bound` vars by `n`.
818 /// Shifts up `Ty::Bound` vars by `n`. 859 fn shift_bound_vars(self, n: DebruijnIndex) -> Self
819 fn shift_bound_vars(self, n: i32) -> Self
820 where 860 where
821 Self: Sized, 861 Self: Sized,
822 { 862 {
823 self.fold_binders( 863 self.fold_binders(
824 &mut |ty, binders| match ty { 864 &mut |ty, binders| match ty {
825 Ty::Bound(idx) if idx as usize >= binders => { 865 Ty::Bound(bound) if bound.debruijn >= binders => {
826 assert!(idx as i32 >= -n); 866 Ty::Bound(bound.shifted_in_from(n))
827 Ty::Bound((idx as i32 + n) as u32)
828 } 867 }
829 ty => ty, 868 ty => ty,
830 }, 869 },
831 0, 870 DebruijnIndex::INNERMOST,
832 ) 871 )
833 } 872 }
834} 873}
@@ -856,7 +895,11 @@ impl TypeWalk for Ty {
856 f(self); 895 f(self);
857 } 896 }
858 897
859 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { 898 fn walk_mut_binders(
899 &mut self,
900 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
901 binders: DebruijnIndex,
902 ) {
860 match self { 903 match self {
861 Ty::Apply(a_ty) => { 904 Ty::Apply(a_ty) => {
862 a_ty.parameters.walk_mut_binders(f, binders); 905 a_ty.parameters.walk_mut_binders(f, binders);
@@ -866,7 +909,7 @@ impl TypeWalk for Ty {
866 } 909 }
867 Ty::Dyn(predicates) | Ty::Opaque(predicates) => { 910 Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
868 for p in make_mut_slice(predicates) { 911 for p in make_mut_slice(predicates) {
869 p.walk_mut_binders(f, binders + 1); 912 p.walk_mut_binders(f, binders.shifted_in());
870 } 913 }
871 } 914 }
872 Ty::Placeholder { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} 915 Ty::Placeholder { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index d7f250783..6c7bbc448 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -29,8 +29,8 @@ use crate::{
29 all_super_traits, associated_type_by_name_including_super_traits, generics, make_mut_slice, 29 all_super_traits, associated_type_by_name_including_super_traits, generics, make_mut_slice,
30 variant_data, 30 variant_data,
31 }, 31 },
32 Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs, 32 Binders, BoundVar, DebruijnIndex, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate,
33 TraitEnvironment, TraitRef, Ty, TypeCtor, 33 ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor,
34}; 34};
35 35
36#[derive(Debug)] 36#[derive(Debug)]
@@ -131,7 +131,7 @@ impl Ty {
131 Ty::apply(TypeCtor::FnPtr { num_args: sig.len() as u16 - 1 }, sig) 131 Ty::apply(TypeCtor::FnPtr { num_args: sig.len() as u16 - 1 }, sig)
132 } 132 }
133 TypeRef::DynTrait(bounds) => { 133 TypeRef::DynTrait(bounds) => {
134 let self_ty = Ty::Bound(0); 134 let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0));
135 let predicates = bounds 135 let predicates = bounds
136 .iter() 136 .iter()
137 .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone())) 137 .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone()))
@@ -141,7 +141,7 @@ impl Ty {
141 TypeRef::ImplTrait(bounds) => { 141 TypeRef::ImplTrait(bounds) => {
142 match ctx.impl_trait_mode { 142 match ctx.impl_trait_mode {
143 ImplTraitLoweringMode::Opaque => { 143 ImplTraitLoweringMode::Opaque => {
144 let self_ty = Ty::Bound(0); 144 let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0));
145 let predicates = bounds 145 let predicates = bounds
146 .iter() 146 .iter()
147 .flat_map(|b| { 147 .flat_map(|b| {
@@ -177,12 +177,10 @@ impl Ty {
177 } else { 177 } else {
178 (0, 0, 0, 0) 178 (0, 0, 0, 0)
179 }; 179 };
180 Ty::Bound( 180 Ty::Bound(BoundVar::new(
181 idx as u32 181 DebruijnIndex::INNERMOST,
182 + parent_params as u32 182 idx as usize + parent_params + self_params + list_params,
183 + self_params as u32 183 ))
184 + list_params as u32,
185 )
186 } 184 }
187 ImplTraitLoweringMode::Disallowed => { 185 ImplTraitLoweringMode::Disallowed => {
188 // FIXME: report error 186 // FIXME: report error
@@ -249,7 +247,11 @@ impl Ty {
249 let ty = match resolution { 247 let ty = match resolution {
250 TypeNs::TraitId(trait_) => { 248 TypeNs::TraitId(trait_) => {
251 // if this is a bare dyn Trait, we'll directly put the required ^0 for the self type in there 249 // if this is a bare dyn Trait, we'll directly put the required ^0 for the self type in there
252 let self_ty = if remaining_segments.len() == 0 { Some(Ty::Bound(0)) } else { None }; 250 let self_ty = if remaining_segments.len() == 0 {
251 Some(Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)))
252 } else {
253 None
254 };
253 let trait_ref = 255 let trait_ref =
254 TraitRef::from_resolved_path(ctx, trait_, resolved_segment, self_ty); 256 TraitRef::from_resolved_path(ctx, trait_, resolved_segment, self_ty);
255 let ty = if remaining_segments.len() == 1 { 257 let ty = if remaining_segments.len() == 1 {
@@ -289,7 +291,7 @@ impl Ty {
289 TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id), 291 TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id),
290 TypeParamLoweringMode::Variable => { 292 TypeParamLoweringMode::Variable => {
291 let idx = generics.param_idx(param_id).expect("matching generics"); 293 let idx = generics.param_idx(param_id).expect("matching generics");
292 Ty::Bound(idx) 294 Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, idx))
293 } 295 }
294 } 296 }
295 } 297 }
@@ -558,7 +560,7 @@ impl GenericPredicate {
558 TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id), 560 TypeParamLoweringMode::Placeholder => Ty::Placeholder(param_id),
559 TypeParamLoweringMode::Variable => { 561 TypeParamLoweringMode::Variable => {
560 let idx = generics.param_idx(param_id).expect("matching generics"); 562 let idx = generics.param_idx(param_id).expect("matching generics");
561 Ty::Bound(idx) 563 Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, idx))
562 } 564 }
563 } 565 }
564 } 566 }
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index 533c6ccfb..74a0bc7db 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -20,7 +20,8 @@ use crate::{
20 db::HirDatabase, 20 db::HirDatabase,
21 primitive::{FloatBitness, Uncertain}, 21 primitive::{FloatBitness, Uncertain},
22 utils::all_super_traits, 22 utils::all_super_traits,
23 ApplicationTy, Canonical, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, 23 ApplicationTy, Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty,
24 TypeCtor, TypeWalk,
24}; 25};
25 26
26/// This is used as a key for indexing impls. 27/// This is used as a key for indexing impls.
@@ -507,8 +508,9 @@ pub(crate) fn inherent_impl_substs(
507) -> Option<Substs> { 508) -> Option<Substs> {
508 // we create a var for each type parameter of the impl; we need to keep in 509 // we create a var for each type parameter of the impl; we need to keep in
509 // mind here that `self_ty` might have vars of its own 510 // mind here that `self_ty` might have vars of its own
510 let vars = 511 let vars = Substs::build_for_def(db, impl_id)
511 Substs::build_for_def(db, impl_id).fill_with_bound_vars(self_ty.num_vars as u32).build(); 512 .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.num_vars)
513 .build();
512 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); 514 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars);
513 let self_ty_with_vars = 515 let self_ty_with_vars =
514 Canonical { num_vars: vars.len() + self_ty.num_vars, value: self_ty_with_vars }; 516 Canonical { num_vars: vars.len() + self_ty.num_vars, value: self_ty_with_vars };
@@ -526,8 +528,8 @@ pub(crate) fn inherent_impl_substs(
526fn fallback_bound_vars(s: Substs, num_vars_to_keep: usize) -> Substs { 528fn fallback_bound_vars(s: Substs, num_vars_to_keep: usize) -> Substs {
527 s.fold_binders( 529 s.fold_binders(
528 &mut |ty, binders| { 530 &mut |ty, binders| {
529 if let Ty::Bound(idx) = &ty { 531 if let Ty::Bound(bound) = &ty {
530 if *idx >= binders as u32 { 532 if bound.index >= num_vars_to_keep && bound.debruijn >= binders {
531 Ty::Unknown 533 Ty::Unknown
532 } else { 534 } else {
533 ty 535 ty
@@ -536,7 +538,7 @@ fn fallback_bound_vars(s: Substs, num_vars_to_keep: usize) -> Substs {
536 ty 538 ty
537 } 539 }
538 }, 540 },
539 num_vars_to_keep, 541 DebruijnIndex::INNERMOST,
540 ) 542 )
541} 543}
542 544
@@ -586,7 +588,7 @@ fn generic_implements_goal(
586 let num_vars = self_ty.num_vars; 588 let num_vars = self_ty.num_vars;
587 let substs = super::Substs::build_for_def(db, trait_) 589 let substs = super::Substs::build_for_def(db, trait_)
588 .push(self_ty.value) 590 .push(self_ty.value)
589 .fill_with_bound_vars(num_vars as u32) 591 .fill_with_bound_vars(DebruijnIndex::INNERMOST, num_vars)
590 .build(); 592 .build();
591 let num_vars = substs.len() - 1 + self_ty.num_vars; 593 let num_vars = substs.len() - 1 + self_ty.num_vars;
592 let trait_ref = TraitRef { trait_, substs }; 594 let trait_ref = TraitRef { trait_, substs };
diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs
index 3e3d55c04..b2c971f02 100644
--- a/crates/ra_hir_ty/src/tests/coercion.rs
+++ b/crates/ra_hir_ty/src/tests/coercion.rs
@@ -407,16 +407,16 @@ fn test() {
407 [30; 31) 'x': &Foo 407 [30; 31) 'x': &Foo
408 [39; 41) '{}': () 408 [39; 41) '{}': ()
409 [52; 133) '{ ...oo); }': () 409 [52; 133) '{ ...oo); }': ()
410 [58; 71) 'takes_ref_foo': fn takes_ref_foo(&Foo) -> () 410 [58; 71) 'takes_ref_foo': fn takes_ref_foo(&Foo)
411 [58; 77) 'takes_...(&Foo)': () 411 [58; 77) 'takes_...(&Foo)': ()
412 [72; 76) '&Foo': &Foo 412 [72; 76) '&Foo': &Foo
413 [73; 76) 'Foo': Foo 413 [73; 76) 'Foo': Foo
414 [83; 96) 'takes_ref_foo': fn takes_ref_foo(&Foo) -> () 414 [83; 96) 'takes_ref_foo': fn takes_ref_foo(&Foo)
415 [83; 103) 'takes_...&&Foo)': () 415 [83; 103) 'takes_...&&Foo)': ()
416 [97; 102) '&&Foo': &&Foo 416 [97; 102) '&&Foo': &&Foo
417 [98; 102) '&Foo': &Foo 417 [98; 102) '&Foo': &Foo
418 [99; 102) 'Foo': Foo 418 [99; 102) 'Foo': Foo
419 [109; 122) 'takes_ref_foo': fn takes_ref_foo(&Foo) -> () 419 [109; 122) 'takes_ref_foo': fn takes_ref_foo(&Foo)
420 [109; 130) 'takes_...&&Foo)': () 420 [109; 130) 'takes_...&&Foo)': ()
421 [123; 129) '&&&Foo': &&&Foo 421 [123; 129) '&&&Foo': &&&Foo
422 [124; 129) '&&Foo': &&Foo 422 [124; 129) '&&Foo': &&Foo
@@ -484,7 +484,7 @@ fn test() {
484 [171; 178) 'loop {}': ! 484 [171; 178) 'loop {}': !
485 [176; 178) '{}': () 485 [176; 178) '{}': ()
486 [191; 236) '{ ... }); }': () 486 [191; 236) '{ ... }); }': ()
487 [197; 210) 'takes_ref_str': fn takes_ref_str(&str) -> () 487 [197; 210) 'takes_ref_str': fn takes_ref_str(&str)
488 [197; 233) 'takes_...g() })': () 488 [197; 233) 'takes_...g() })': ()
489 [211; 232) '&{ ret...ng() }': &String 489 [211; 232) '&{ ret...ng() }': &String
490 [212; 232) '{ retu...ng() }': String 490 [212; 232) '{ retu...ng() }': String
diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs
index eb97288f1..ff4599b71 100644
--- a/crates/ra_hir_ty/src/tests/macros.rs
+++ b/crates/ra_hir_ty/src/tests/macros.rs
@@ -1,8 +1,10 @@
1use super::{infer, type_at, type_at_pos};
2use crate::test_db::TestDB;
3use insta::assert_snapshot; 1use insta::assert_snapshot;
4use ra_db::fixture::WithFixture; 2use ra_db::fixture::WithFixture;
5 3
4use super::{infer, type_at, type_at_pos};
5
6use crate::test_db::TestDB;
7
6#[test] 8#[test]
7fn cfg_impl_def() { 9fn cfg_impl_def() {
8 let (db, pos) = TestDB::with_position( 10 let (db, pos) = TestDB::with_position(
@@ -658,3 +660,28 @@ fn test() {
658 ); 660 );
659 assert_eq!("S", type_at_pos(&db, pos)); 661 assert_eq!("S", type_at_pos(&db, pos));
660} 662}
663
664#[test]
665fn macro_in_arm() {
666 assert_snapshot!(
667 infer(r#"
668macro_rules! unit {
669 () => { () };
670}
671
672fn main() {
673 let x = match () {
674 unit!() => 92u32,
675 };
676}
677"#),
678 @r###"
679 [52; 111) '{ ... }; }': ()
680 [62; 63) 'x': u32
681 [66; 108) 'match ... }': u32
682 [72; 74) '()': ()
683 [85; 92) 'unit!()': ()
684 [96; 101) '92u32': u32
685 "###
686 );
687}
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs
index 2ee9b8f10..3402e0cb5 100644
--- a/crates/ra_hir_ty/src/tests/regression.rs
+++ b/crates/ra_hir_ty/src/tests/regression.rs
@@ -376,7 +376,7 @@ fn issue_2669() {
376 ), 376 ),
377 @r###" 377 @r###"
378 [147; 262) '{ ... }': () 378 [147; 262) '{ ... }': ()
379 [161; 164) 'end': fn end<{unknown}>() -> () 379 [161; 164) 'end': fn end<{unknown}>()
380 [161; 166) 'end()': () 380 [161; 166) 'end()': ()
381 [199; 252) '{ ... }': () 381 [199; 252) '{ ... }': ()
382 [221; 223) '_x': ! 382 [221; 223) '_x': !
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs
index a600b947d..c2f1ded2f 100644
--- a/crates/ra_hir_ty/src/tests/simple.rs
+++ b/crates/ra_hir_ty/src/tests/simple.rs
@@ -521,7 +521,7 @@ fn test() -> &mut &f64 {
521 [88; 89) 'a': u32 521 [88; 89) 'a': u32
522 [92; 108) 'unknow...nction': {unknown} 522 [92; 108) 'unknow...nction': {unknown}
523 [92; 110) 'unknow...tion()': u32 523 [92; 110) 'unknow...tion()': u32
524 [116; 125) 'takes_u32': fn takes_u32(u32) -> () 524 [116; 125) 'takes_u32': fn takes_u32(u32)
525 [116; 128) 'takes_u32(a)': () 525 [116; 128) 'takes_u32(a)': ()
526 [126; 127) 'a': u32 526 [126; 127) 'a': u32
527 [138; 139) 'b': i32 527 [138; 139) 'b': i32
@@ -1729,3 +1729,29 @@ fn foo() -> u32 {
1729 "### 1729 "###
1730 ); 1730 );
1731} 1731}
1732
1733#[test]
1734fn fn_pointer_return() {
1735 assert_snapshot!(
1736 infer(r#"
1737struct Vtable {
1738 method: fn(),
1739}
1740
1741fn main() {
1742 let vtable = Vtable { method: || {} };
1743 let m = vtable.method;
1744}
1745"#),
1746 @r###"
1747 [48; 121) '{ ...hod; }': ()
1748 [58; 64) 'vtable': Vtable
1749 [67; 91) 'Vtable...| {} }': Vtable
1750 [84; 89) '|| {}': || -> ()
1751 [87; 89) '{}': ()
1752 [101; 102) 'm': fn()
1753 [105; 111) 'vtable': Vtable
1754 [105; 118) 'vtable.method': fn()
1755 "###
1756 );
1757}
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index f009a708c..081aa943a 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -263,7 +263,7 @@ fn test() {
263 [119; 120) 'S': S<u32>(u32) -> S<u32> 263 [119; 120) 'S': S<u32>(u32) -> S<u32>
264 [119; 129) 'S(unknown)': S<u32> 264 [119; 129) 'S(unknown)': S<u32>
265 [121; 128) 'unknown': u32 265 [121; 128) 'unknown': u32
266 [135; 138) 'foo': fn foo<S<u32>>(S<u32>) -> () 266 [135; 138) 'foo': fn foo<S<u32>>(S<u32>)
267 [135; 141) 'foo(s)': () 267 [135; 141) 'foo(s)': ()
268 [139; 140) 's': S<u32> 268 [139; 140) 's': S<u32>
269 "### 269 "###
@@ -962,7 +962,7 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u32>) {
962 [224; 225) 'S': S<u16>(u16) -> S<u16> 962 [224; 225) 'S': S<u16>(u16) -> S<u16>
963 [224; 228) 'S(1)': S<u16> 963 [224; 228) 'S(1)': S<u16>
964 [226; 227) '1': u16 964 [226; 227) '1': u16
965 [234; 237) 'bar': fn bar(S<u16>) -> () 965 [234; 237) 'bar': fn bar(S<u16>)
966 [234; 240) 'bar(z)': () 966 [234; 240) 'bar(z)': ()
967 [238; 239) 'z': S<u16> 967 [238; 239) 'z': S<u16>
968 [246; 247) 'x': impl Trait<u64> 968 [246; 247) 'x': impl Trait<u64>
@@ -1108,8 +1108,8 @@ fn test() {
1108 [40; 47) 'loop {}': ! 1108 [40; 47) 'loop {}': !
1109 [45; 47) '{}': () 1109 [45; 47) '{}': ()
1110 [91; 124) '{ ...foo; }': () 1110 [91; 124) '{ ...foo; }': ()
1111 [101; 102) 'f': fn(S) -> () 1111 [101; 102) 'f': fn(S)
1112 [118; 121) 'foo': fn foo(S) -> () 1112 [118; 121) 'foo': fn foo(S)
1113 "### 1113 "###
1114 ); 1114 );
1115} 1115}
@@ -1962,7 +1962,7 @@ fn test() -> impl Trait<i32> {
1962 [229; 241) 'S(default())': S<u32> 1962 [229; 241) 'S(default())': S<u32>
1963 [231; 238) 'default': fn default<u32>() -> u32 1963 [231; 238) 'default': fn default<u32>() -> u32
1964 [231; 240) 'default()': u32 1964 [231; 240) 'default()': u32
1965 [247; 250) 'foo': fn foo(S<u32>) -> () 1965 [247; 250) 'foo': fn foo(S<u32>)
1966 [247; 254) 'foo(s1)': () 1966 [247; 254) 'foo(s1)': ()
1967 [251; 253) 's1': S<u32> 1967 [251; 253) 's1': S<u32>
1968 [264; 265) 'x': i32 1968 [264; 265) 'x': i32
@@ -2012,7 +2012,7 @@ fn main() {
2012 [147; 149) '_v': F 2012 [147; 149) '_v': F
2013 [192; 195) '{ }': () 2013 [192; 195) '{ }': ()
2014 [207; 238) '{ ... }); }': () 2014 [207; 238) '{ ... }); }': ()
2015 [213; 223) 'f::<(), _>': fn f<(), |&()| -> ()>(|&()| -> ()) -> () 2015 [213; 223) 'f::<(), _>': fn f<(), |&()| -> ()>(|&()| -> ())
2016 [213; 235) 'f::<()... z; })': () 2016 [213; 235) 'f::<()... z; })': ()
2017 [224; 234) '|z| { z; }': |&()| -> () 2017 [224; 234) '|z| { z; }': |&()| -> ()
2018 [225; 226) 'z': &() 2018 [225; 226) 'z': &()
diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs
index a1ca33c98..07854a062 100644
--- a/crates/ra_hir_ty/src/traits.rs
+++ b/crates/ra_hir_ty/src/traits.rs
@@ -7,7 +7,7 @@ use ra_db::{impl_intern_key, salsa, CrateId};
7use ra_prof::profile; 7use ra_prof::profile;
8use rustc_hash::FxHashSet; 8use rustc_hash::FxHashSet;
9 9
10use crate::db::HirDatabase; 10use crate::{db::HirDatabase, DebruijnIndex};
11 11
12use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; 12use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk};
13 13
@@ -128,7 +128,11 @@ impl TypeWalk for ProjectionPredicate {
128 self.ty.walk(f); 128 self.ty.walk(f);
129 } 129 }
130 130
131 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { 131 fn walk_mut_binders(
132 &mut self,
133 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
134 binders: DebruijnIndex,
135 ) {
132 self.projection_ty.walk_mut_binders(f, binders); 136 self.projection_ty.walk_mut_binders(f, binders);
133 self.ty.walk_mut_binders(f, binders); 137 self.ty.walk_mut_binders(f, binders);
134 } 138 }
@@ -144,7 +148,7 @@ pub(crate) fn trait_solve_query(
144 Obligation::Trait(it) => db.trait_data(it.trait_).name.to_string(), 148 Obligation::Trait(it) => db.trait_data(it.trait_).name.to_string(),
145 Obligation::Projection(_) => "projection".to_string(), 149 Obligation::Projection(_) => "projection".to_string(),
146 }); 150 });
147 log::debug!("trait_solve_query({})", goal.value.value.display(db)); 151 eprintln!("trait_solve_query({})", goal.value.value.display(db));
148 152
149 if let Obligation::Projection(pred) = &goal.value.value { 153 if let Obligation::Projection(pred) = &goal.value.value {
150 if let Ty::Bound(_) = &pred.projection_ty.parameters[0] { 154 if let Ty::Bound(_) = &pred.projection_ty.parameters[0] {
@@ -153,7 +157,7 @@ pub(crate) fn trait_solve_query(
153 } 157 }
154 } 158 }
155 159
156 let canonical = goal.to_chalk(db).cast(); 160 let canonical = goal.to_chalk(db).cast(&Interner);
157 161
158 // We currently don't deal with universes (I think / hope they're not yet 162 // We currently don't deal with universes (I think / hope they're not yet
159 // relevant for our use cases?) 163 // relevant for our use cases?)
@@ -194,8 +198,8 @@ fn solution_from_chalk(
194 let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<Interner>>| { 198 let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<Interner>>| {
195 let value = subst 199 let value = subst
196 .value 200 .value
197 .into_iter() 201 .iter(&Interner)
198 .map(|p| match p.ty() { 202 .map(|p| match p.ty(&Interner) {
199 Some(ty) => from_chalk(db, ty.clone()), 203 Some(ty) => from_chalk(db, ty.clone()),
200 None => unimplemented!(), 204 None => unimplemented!(),
201 }) 205 })
diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs
index 73e3c5c78..ccab246bf 100644
--- a/crates/ra_hir_ty/src/traits/builtin.rs
+++ b/crates/ra_hir_ty/src/traits/builtin.rs
@@ -8,7 +8,8 @@ use super::{AssocTyValue, Impl, UnsizeToSuperTraitObjectData};
8use crate::{ 8use crate::{
9 db::HirDatabase, 9 db::HirDatabase,
10 utils::{all_super_traits, generics}, 10 utils::{all_super_traits, generics},
11 ApplicationTy, Binders, GenericPredicate, Substs, TraitRef, Ty, TypeCtor, 11 ApplicationTy, Binders, BoundVar, DebruijnIndex, GenericPredicate, Substs, TraitRef, Ty,
12 TypeCtor, TypeWalk,
12}; 13};
13 14
14pub(super) struct BuiltinImplData { 15pub(super) struct BuiltinImplData {
@@ -164,11 +165,15 @@ fn closure_fn_trait_impl_datum(
164 165
165 let arg_ty = Ty::apply( 166 let arg_ty = Ty::apply(
166 TypeCtor::Tuple { cardinality: num_args }, 167 TypeCtor::Tuple { cardinality: num_args },
167 Substs::builder(num_args as usize).fill_with_bound_vars(0).build(), 168 Substs::builder(num_args as usize)
169 .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
170 .build(),
168 ); 171 );
169 let sig_ty = Ty::apply( 172 let sig_ty = Ty::apply(
170 TypeCtor::FnPtr { num_args }, 173 TypeCtor::FnPtr { num_args },
171 Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(), 174 Substs::builder(num_args as usize + 1)
175 .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
176 .build(),
172 ); 177 );
173 178
174 let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty); 179 let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty);
@@ -203,7 +208,7 @@ fn closure_fn_trait_output_assoc_ty_value(
203 } 208 }
204 }; 209 };
205 210
206 let output_ty = Ty::Bound(num_args.into()); 211 let output_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, num_args.into()));
207 212
208 let fn_once_trait = 213 let fn_once_trait =
209 get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist"); 214 get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist");
@@ -241,7 +246,7 @@ fn array_unsize_impl_datum(db: &dyn HirDatabase, krate: CrateId) -> BuiltinImplD
241 // the existence of the Unsize trait has been checked before 246 // the existence of the Unsize trait has been checked before
242 .expect("Unsize trait missing"); 247 .expect("Unsize trait missing");
243 248
244 let var = Ty::Bound(0); 249 let var = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0));
245 let substs = Substs::builder(2) 250 let substs = Substs::builder(2)
246 .push(Ty::apply_one(TypeCtor::Array, var.clone())) 251 .push(Ty::apply_one(TypeCtor::Array, var.clone()))
247 .push(Ty::apply_one(TypeCtor::Slice, var)) 252 .push(Ty::apply_one(TypeCtor::Slice, var))
@@ -270,19 +275,18 @@ fn trait_object_unsize_impl_datum(
270 // the existence of the Unsize trait has been checked before 275 // the existence of the Unsize trait has been checked before
271 .expect("Unsize trait missing"); 276 .expect("Unsize trait missing");
272 277
273 let self_ty = Ty::Bound(0); 278 let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0));
274 279
275 let target_substs = Substs::build_for_def(db, trait_) 280 let target_substs = Substs::build_for_def(db, trait_)
276 .push(Ty::Bound(0)) 281 .push(Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)))
277 // starting from ^2 because we want to start with ^1 outside of the 282 .fill_with_bound_vars(DebruijnIndex::ONE, 1)
278 // `dyn`, which is ^2 inside
279 .fill_with_bound_vars(2)
280 .build(); 283 .build();
281 let num_vars = target_substs.len(); 284 let num_vars = target_substs.len();
282 let target_trait_ref = TraitRef { trait_, substs: target_substs }; 285 let target_trait_ref = TraitRef { trait_, substs: target_substs };
283 let target_bounds = vec![GenericPredicate::Implemented(target_trait_ref)]; 286 let target_bounds = vec![GenericPredicate::Implemented(target_trait_ref)];
284 287
285 let self_substs = Substs::build_for_def(db, trait_).fill_with_bound_vars(0).build(); 288 let self_substs =
289 Substs::build_for_def(db, trait_).fill_with_bound_vars(DebruijnIndex::INNERMOST, 0).build();
286 let self_trait_ref = TraitRef { trait_, substs: self_substs }; 290 let self_trait_ref = TraitRef { trait_, substs: self_substs };
287 let where_clauses = vec![GenericPredicate::Implemented(self_trait_ref)]; 291 let where_clauses = vec![GenericPredicate::Implemented(self_trait_ref)];
288 292
@@ -305,24 +309,26 @@ fn super_trait_object_unsize_impl_datum(
305 // the existence of the Unsize trait has been checked before 309 // the existence of the Unsize trait has been checked before
306 .expect("Unsize trait missing"); 310 .expect("Unsize trait missing");
307 311
308 let self_substs = Substs::build_for_def(db, data.trait_).fill_with_bound_vars(0).build(); 312 let self_substs = Substs::build_for_def(db, data.trait_)
313 .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
314 .build();
315 let self_trait_ref = TraitRef { trait_: data.trait_, substs: self_substs.clone() };
309 316
310 let num_vars = self_substs.len() - 1; 317 let num_vars = self_substs.len() - 1;
311 318
312 let self_trait_ref = TraitRef { trait_: data.trait_, substs: self_substs.clone() };
313 let self_bounds = vec![GenericPredicate::Implemented(self_trait_ref.clone())];
314
315 // we need to go from our trait to the super trait, substituting type parameters 319 // we need to go from our trait to the super trait, substituting type parameters
316 let path = crate::utils::find_super_trait_path(db.upcast(), data.trait_, data.super_trait); 320 let path = crate::utils::find_super_trait_path(db.upcast(), data.trait_, data.super_trait);
317 321
318 let mut current_trait_ref = self_trait_ref; 322 let mut current_trait_ref = self_trait_ref.clone();
319 for t in path.into_iter().skip(1) { 323 for t in path.into_iter().skip(1) {
320 let bounds = db.generic_predicates(current_trait_ref.trait_.into()); 324 let bounds = db.generic_predicates(current_trait_ref.trait_.into());
321 let super_trait_ref = bounds 325 let super_trait_ref = bounds
322 .iter() 326 .iter()
323 .find_map(|b| match &b.value { 327 .find_map(|b| match &b.value {
324 GenericPredicate::Implemented(tr) 328 GenericPredicate::Implemented(tr)
325 if tr.trait_ == t && tr.substs[0] == Ty::Bound(0) => 329 if tr.trait_ == t
330 && tr.substs[0]
331 == Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)) =>
326 { 332 {
327 Some(Binders { value: tr, num_binders: b.num_binders }) 333 Some(Binders { value: tr, num_binders: b.num_binders })
328 } 334 }
@@ -332,7 +338,18 @@ fn super_trait_object_unsize_impl_datum(
332 current_trait_ref = super_trait_ref.cloned().subst(&current_trait_ref.substs); 338 current_trait_ref = super_trait_ref.cloned().subst(&current_trait_ref.substs);
333 } 339 }
334 340
335 let super_bounds = vec![GenericPredicate::Implemented(current_trait_ref)]; 341 // We need to renumber the variables a bit now: from ^0.0, ^0.1, ^0.2, ...
342 // to ^0.0, ^1.0, ^1.1. The reason for this is that the first variable comes
343 // from the dyn Trait binder, while the other variables come from the impl.
344 let new_substs = Substs::builder(num_vars + 1)
345 .push(Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)))
346 .fill_with_bound_vars(DebruijnIndex::ONE, 0)
347 .build();
348
349 let self_bounds =
350 vec![GenericPredicate::Implemented(self_trait_ref.subst_bound_vars(&new_substs))];
351 let super_bounds =
352 vec![GenericPredicate::Implemented(current_trait_ref.subst_bound_vars(&new_substs))];
336 353
337 let substs = Substs::builder(2) 354 let substs = Substs::builder(2)
338 .push(Ty::Dyn(self_bounds.into())) 355 .push(Ty::Dyn(self_bounds.into()))
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index 943d5f125..53ce362ea 100644
--- a/crates/ra_hir_ty/src/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -3,7 +3,10 @@ use std::{fmt, sync::Arc};
3 3
4use log::debug; 4use log::debug;
5 5
6use chalk_ir::{cast::Cast, Goal, GoalData, Parameter, PlaceholderIndex, TypeName, UniverseIndex}; 6use chalk_ir::{
7 cast::Cast, fold::shift::Shift, Goal, GoalData, Parameter, PlaceholderIndex, TypeName,
8 UniverseIndex,
9};
7 10
8use hir_def::{AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId}; 11use hir_def::{AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId};
9use ra_db::{ 12use ra_db::{
@@ -59,53 +62,126 @@ impl chalk_ir::interner::Interner for Interner {
59 None 62 None
60 } 63 }
61 64
65 fn debug_ty(_ty: &chalk_ir::Ty<Self>, _fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
66 None
67 }
68
69 fn debug_lifetime(
70 _lifetime: &chalk_ir::Lifetime<Self>,
71 _fmt: &mut fmt::Formatter<'_>,
72 ) -> Option<fmt::Result> {
73 None
74 }
75
76 fn debug_parameter(
77 _parameter: &Parameter<Self>,
78 _fmt: &mut fmt::Formatter<'_>,
79 ) -> Option<fmt::Result> {
80 None
81 }
82
83 fn debug_goal(_goal: &Goal<Self>, _fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
84 None
85 }
86
87 fn debug_goals(
88 _goals: &chalk_ir::Goals<Self>,
89 _fmt: &mut fmt::Formatter<'_>,
90 ) -> Option<fmt::Result> {
91 None
92 }
93
94 fn debug_program_clause_implication(
95 _pci: &chalk_ir::ProgramClauseImplication<Self>,
96 _fmt: &mut fmt::Formatter<'_>,
97 ) -> Option<fmt::Result> {
98 None
99 }
100
101 fn debug_application_ty(
102 _application_ty: &chalk_ir::ApplicationTy<Self>,
103 _fmt: &mut fmt::Formatter<'_>,
104 ) -> Option<fmt::Result> {
105 None
106 }
107
108 fn debug_substitution(
109 _substitution: &chalk_ir::Substitution<Self>,
110 _fmt: &mut fmt::Formatter<'_>,
111 ) -> Option<fmt::Result> {
112 None
113 }
114
115 fn debug_separator_trait_ref(
116 _separator_trait_ref: &chalk_ir::SeparatorTraitRef<Self>,
117 _fmt: &mut fmt::Formatter<'_>,
118 ) -> Option<fmt::Result> {
119 None
120 }
121
62 fn intern_ty(&self, ty: chalk_ir::TyData<Self>) -> Box<chalk_ir::TyData<Self>> { 122 fn intern_ty(&self, ty: chalk_ir::TyData<Self>) -> Box<chalk_ir::TyData<Self>> {
63 Box::new(ty) 123 Box::new(ty)
64 } 124 }
65 125
66 fn ty_data(ty: &Box<chalk_ir::TyData<Self>>) -> &chalk_ir::TyData<Self> { 126 fn ty_data<'a>(&self, ty: &'a Box<chalk_ir::TyData<Self>>) -> &'a chalk_ir::TyData<Self> {
67 ty 127 ty
68 } 128 }
69 129
70 fn intern_lifetime(lifetime: chalk_ir::LifetimeData<Self>) -> chalk_ir::LifetimeData<Self> { 130 fn intern_lifetime(
131 &self,
132 lifetime: chalk_ir::LifetimeData<Self>,
133 ) -> chalk_ir::LifetimeData<Self> {
71 lifetime 134 lifetime
72 } 135 }
73 136
74 fn lifetime_data(lifetime: &chalk_ir::LifetimeData<Self>) -> &chalk_ir::LifetimeData<Self> { 137 fn lifetime_data<'a>(
138 &self,
139 lifetime: &'a chalk_ir::LifetimeData<Self>,
140 ) -> &'a chalk_ir::LifetimeData<Self> {
75 lifetime 141 lifetime
76 } 142 }
77 143
78 fn intern_parameter(parameter: chalk_ir::ParameterData<Self>) -> chalk_ir::ParameterData<Self> { 144 fn intern_parameter(
145 &self,
146 parameter: chalk_ir::ParameterData<Self>,
147 ) -> chalk_ir::ParameterData<Self> {
79 parameter 148 parameter
80 } 149 }
81 150
82 fn parameter_data(parameter: &chalk_ir::ParameterData<Self>) -> &chalk_ir::ParameterData<Self> { 151 fn parameter_data<'a>(
152 &self,
153 parameter: &'a chalk_ir::ParameterData<Self>,
154 ) -> &'a chalk_ir::ParameterData<Self> {
83 parameter 155 parameter
84 } 156 }
85 157
86 fn intern_goal(goal: GoalData<Self>) -> Arc<GoalData<Self>> { 158 fn intern_goal(&self, goal: GoalData<Self>) -> Arc<GoalData<Self>> {
87 Arc::new(goal) 159 Arc::new(goal)
88 } 160 }
89 161
90 fn intern_goals(data: impl IntoIterator<Item = Goal<Self>>) -> Self::InternedGoals { 162 fn intern_goals(&self, data: impl IntoIterator<Item = Goal<Self>>) -> Self::InternedGoals {
91 data.into_iter().collect() 163 data.into_iter().collect()
92 } 164 }
93 165
94 fn goal_data(goal: &Arc<GoalData<Self>>) -> &GoalData<Self> { 166 fn goal_data<'a>(&self, goal: &'a Arc<GoalData<Self>>) -> &'a GoalData<Self> {
95 goal 167 goal
96 } 168 }
97 169
98 fn goals_data(goals: &Vec<Goal<Interner>>) -> &[Goal<Interner>] { 170 fn goals_data<'a>(&self, goals: &'a Vec<Goal<Interner>>) -> &'a [Goal<Interner>] {
99 goals 171 goals
100 } 172 }
101 173
102 fn intern_substitution<E>( 174 fn intern_substitution<E>(
175 &self,
103 data: impl IntoIterator<Item = Result<Parameter<Self>, E>>, 176 data: impl IntoIterator<Item = Result<Parameter<Self>, E>>,
104 ) -> Result<Vec<Parameter<Self>>, E> { 177 ) -> Result<Vec<Parameter<Self>>, E> {
105 data.into_iter().collect() 178 data.into_iter().collect()
106 } 179 }
107 180
108 fn substitution_data(substitution: &Vec<Parameter<Self>>) -> &[Parameter<Self>] { 181 fn substitution_data<'a>(
182 &self,
183 substitution: &'a Vec<Parameter<Self>>,
184 ) -> &'a [Parameter<Self>] {
109 substitution 185 substitution
110 } 186 }
111} 187}
@@ -145,12 +221,14 @@ impl ToChalk for Ty {
145 Ty::Apply(apply_ty) => { 221 Ty::Apply(apply_ty) => {
146 let name = apply_ty.ctor.to_chalk(db); 222 let name = apply_ty.ctor.to_chalk(db);
147 let substitution = apply_ty.parameters.to_chalk(db); 223 let substitution = apply_ty.parameters.to_chalk(db);
148 chalk_ir::ApplicationTy { name, substitution }.cast().intern(&Interner) 224 chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner)
149 } 225 }
150 Ty::Projection(proj_ty) => { 226 Ty::Projection(proj_ty) => {
151 let associated_ty_id = proj_ty.associated_ty.to_chalk(db); 227 let associated_ty_id = proj_ty.associated_ty.to_chalk(db);
152 let substitution = proj_ty.parameters.to_chalk(db); 228 let substitution = proj_ty.parameters.to_chalk(db);
153 chalk_ir::AliasTy { associated_ty_id, substitution }.cast().intern(&Interner) 229 chalk_ir::AliasTy { associated_ty_id, substitution }
230 .cast(&Interner)
231 .intern(&Interner)
154 } 232 }
155 Ty::Placeholder(id) => { 233 Ty::Placeholder(id) => {
156 let interned_id = db.intern_type_param_id(id); 234 let interned_id = db.intern_type_param_id(id);
@@ -160,7 +238,7 @@ impl ToChalk for Ty {
160 } 238 }
161 .to_ty::<Interner>(&Interner) 239 .to_ty::<Interner>(&Interner)
162 } 240 }
163 Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(&Interner), 241 Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx).intern(&Interner),
164 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), 242 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"),
165 Ty::Dyn(predicates) => { 243 Ty::Dyn(predicates) => {
166 let where_clauses = predicates 244 let where_clauses = predicates
@@ -173,14 +251,14 @@ impl ToChalk for Ty {
173 chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner) 251 chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner)
174 } 252 }
175 Ty::Opaque(_) | Ty::Unknown => { 253 Ty::Opaque(_) | Ty::Unknown => {
176 let substitution = chalk_ir::Substitution::empty(); 254 let substitution = chalk_ir::Substitution::empty(&Interner);
177 let name = TypeName::Error; 255 let name = TypeName::Error;
178 chalk_ir::ApplicationTy { name, substitution }.cast().intern(&Interner) 256 chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner)
179 } 257 }
180 } 258 }
181 } 259 }
182 fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self { 260 fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self {
183 match chalk.data().clone() { 261 match chalk.data(&Interner).clone() {
184 chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name { 262 chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name {
185 TypeName::Error => Ty::Unknown, 263 TypeName::Error => Ty::Unknown,
186 _ => { 264 _ => {
@@ -202,7 +280,7 @@ impl ToChalk for Ty {
202 Ty::Projection(ProjectionTy { associated_ty, parameters }) 280 Ty::Projection(ProjectionTy { associated_ty, parameters })
203 } 281 }
204 chalk_ir::TyData::Function(_) => unimplemented!(), 282 chalk_ir::TyData::Function(_) => unimplemented!(),
205 chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx as u32), 283 chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx),
206 chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown, 284 chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown,
207 chalk_ir::TyData::Dyn(where_clauses) => { 285 chalk_ir::TyData::Dyn(where_clauses) => {
208 assert_eq!(where_clauses.bounds.binders.len(), 1); 286 assert_eq!(where_clauses.bounds.binders.len(), 1);
@@ -218,13 +296,13 @@ impl ToChalk for Substs {
218 type Chalk = chalk_ir::Substitution<Interner>; 296 type Chalk = chalk_ir::Substitution<Interner>;
219 297
220 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Substitution<Interner> { 298 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Substitution<Interner> {
221 chalk_ir::Substitution::from(self.iter().map(|ty| ty.clone().to_chalk(db))) 299 chalk_ir::Substitution::from(&Interner, self.iter().map(|ty| ty.clone().to_chalk(db)))
222 } 300 }
223 301
224 fn from_chalk(db: &dyn HirDatabase, parameters: chalk_ir::Substitution<Interner>) -> Substs { 302 fn from_chalk(db: &dyn HirDatabase, parameters: chalk_ir::Substitution<Interner>) -> Substs {
225 let tys = parameters 303 let tys = parameters
226 .into_iter() 304 .iter(&Interner)
227 .map(|p| match p.ty() { 305 .map(|p| match p.ty(&Interner) {
228 Some(ty) => from_chalk(db, ty.clone()), 306 Some(ty) => from_chalk(db, ty.clone()),
229 None => unimplemented!(), 307 None => unimplemented!(),
230 }) 308 })
@@ -332,15 +410,15 @@ impl ToChalk for GenericPredicate {
332 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::QuantifiedWhereClause<Interner> { 410 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::QuantifiedWhereClause<Interner> {
333 match self { 411 match self {
334 GenericPredicate::Implemented(trait_ref) => { 412 GenericPredicate::Implemented(trait_ref) => {
335 make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0) 413 let chalk_trait_ref = trait_ref.to_chalk(db);
414 let chalk_trait_ref = chalk_trait_ref.shifted_in(&Interner);
415 make_binders(chalk_ir::WhereClause::Implemented(chalk_trait_ref), 0)
416 }
417 GenericPredicate::Projection(projection_pred) => {
418 let ty = projection_pred.ty.to_chalk(db).shifted_in(&Interner);
419 let alias = projection_pred.projection_ty.to_chalk(db).shifted_in(&Interner);
420 make_binders(chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq { alias, ty }), 0)
336 } 421 }
337 GenericPredicate::Projection(projection_pred) => make_binders(
338 chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq {
339 alias: projection_pred.projection_ty.to_chalk(db),
340 ty: projection_pred.ty.to_chalk(db),
341 }),
342 0,
343 ),
344 GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"), 422 GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"),
345 } 423 }
346 } 424 }
@@ -400,8 +478,8 @@ impl ToChalk for Obligation {
400 478
401 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> { 479 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> {
402 match self { 480 match self {
403 Obligation::Trait(tr) => tr.to_chalk(db).cast(), 481 Obligation::Trait(tr) => tr.to_chalk(db).cast(&Interner),
404 Obligation::Projection(pr) => pr.to_chalk(db).cast(), 482 Obligation::Projection(pr) => pr.to_chalk(db).cast(&Interner),
405 } 483 }
406 } 484 }
407 485
@@ -438,8 +516,8 @@ impl ToChalk for Arc<super::TraitEnvironment> {
438 continue; 516 continue;
439 } 517 }
440 let program_clause: chalk_ir::ProgramClause<Interner> = 518 let program_clause: chalk_ir::ProgramClause<Interner> =
441 pred.clone().to_chalk(db).cast(); 519 pred.clone().to_chalk(db).cast(&Interner);
442 clauses.push(program_clause.into_from_env_clause()); 520 clauses.push(program_clause.into_from_env_clause(&Interner));
443 } 521 }
444 chalk_ir::Environment::new().add_clauses(clauses) 522 chalk_ir::Environment::new().add_clauses(clauses)
445 } 523 }
@@ -504,7 +582,8 @@ impl ToChalk for builtin::BuiltinImplAssocTyValueData {
504 type Chalk = AssociatedTyValue; 582 type Chalk = AssociatedTyValue;
505 583
506 fn to_chalk(self, db: &dyn HirDatabase) -> AssociatedTyValue { 584 fn to_chalk(self, db: &dyn HirDatabase) -> AssociatedTyValue {
507 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: self.value.to_chalk(db) }; 585 let ty = self.value.to_chalk(db);
586 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty };
508 587
509 chalk_rust_ir::AssociatedTyValue { 588 chalk_rust_ir::AssociatedTyValue {
510 associated_ty_id: self.assoc_ty_id.to_chalk(db), 589 associated_ty_id: self.assoc_ty_id.to_chalk(db),
@@ -578,9 +657,9 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
578 .map(|impl_| impl_.to_chalk(self.db)) 657 .map(|impl_| impl_.to_chalk(self.db))
579 .collect(); 658 .collect();
580 659
581 let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref().clone()); 660 let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref(&Interner).clone());
582 let arg: Option<Ty> = 661 let arg: Option<Ty> =
583 parameters.get(1).map(|p| from_chalk(self.db, p.assert_ty_ref().clone())); 662 parameters.get(1).map(|p| from_chalk(self.db, p.assert_ty_ref(&Interner).clone()));
584 663
585 builtin::get_builtin_impls(self.db, self.krate, &ty, &arg, trait_, |i| { 664 builtin::get_builtin_impls(self.db, self.krate, &ty, &arg, trait_, |i| {
586 result.push(i.to_chalk(self.db)) 665 result.push(i.to_chalk(self.db))
@@ -663,11 +742,13 @@ pub(crate) fn trait_datum_query(
663 let associated_ty_ids = 742 let associated_ty_ids =
664 trait_data.associated_types().map(|type_alias| type_alias.to_chalk(db)).collect(); 743 trait_data.associated_types().map(|type_alias| type_alias.to_chalk(db)).collect();
665 let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses }; 744 let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses };
745 let well_known = None; // FIXME set this (depending on lang items)
666 let trait_datum = TraitDatum { 746 let trait_datum = TraitDatum {
667 id: trait_id, 747 id: trait_id,
668 binders: make_binders(trait_datum_bound, bound_vars.len()), 748 binders: make_binders(trait_datum_bound, bound_vars.len()),
669 flags, 749 flags,
670 associated_ty_ids, 750 associated_ty_ids,
751 well_known,
671 }; 752 };
672 Arc::new(trait_datum) 753 Arc::new(trait_datum)
673} 754}
diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs
index b40d4eb73..1e5022fa4 100644
--- a/crates/ra_hir_ty/src/utils.rs
+++ b/crates/ra_hir_ty/src/utils.rs
@@ -201,11 +201,11 @@ impl Generics {
201 (parent, self_params, list_params, impl_trait_params) 201 (parent, self_params, list_params, impl_trait_params)
202 } 202 }
203 203
204 pub(crate) fn param_idx(&self, param: TypeParamId) -> Option<u32> { 204 pub(crate) fn param_idx(&self, param: TypeParamId) -> Option<usize> {
205 Some(self.find_param(param)?.0) 205 Some(self.find_param(param)?.0)
206 } 206 }
207 207
208 fn find_param(&self, param: TypeParamId) -> Option<(u32, &TypeParamData)> { 208 fn find_param(&self, param: TypeParamId) -> Option<(usize, &TypeParamData)> {
209 if param.parent == self.def { 209 if param.parent == self.def {
210 let (idx, (_local_id, data)) = self 210 let (idx, (_local_id, data)) = self
211 .params 211 .params
@@ -215,7 +215,7 @@ impl Generics {
215 .find(|(_, (idx, _))| *idx == param.local_id) 215 .find(|(_, (idx, _))| *idx == param.local_id)
216 .unwrap(); 216 .unwrap();
217 let (_total, parent_len, _child) = self.len_split(); 217 let (_total, parent_len, _child) = self.len_split();
218 Some(((parent_len + idx) as u32, data)) 218 Some((parent_len + idx, data))
219 } else { 219 } else {
220 self.parent_generics.as_ref().and_then(|g| g.find_param(param)) 220 self.parent_generics.as_ref().and_then(|g| g.find_param(param))
221 } 221 }
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs
index 82ec16913..f433faef3 100644
--- a/crates/ra_ide/src/completion/complete_dot.rs
+++ b/crates/ra_ide/src/completion/complete_dot.rs
@@ -61,7 +61,7 @@ fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &T
61 && ctx.scope().module().map_or(true, |m| func.is_visible_from(ctx.db, m)) 61 && ctx.scope().module().map_or(true, |m| func.is_visible_from(ctx.db, m))
62 && seen_methods.insert(func.name(ctx.db)) 62 && seen_methods.insert(func.name(ctx.db))
63 { 63 {
64 acc.add_function(ctx, func); 64 acc.add_function(ctx, func, None);
65 } 65 }
66 None::<()> 66 None::<()>
67 }); 67 });
diff --git a/crates/ra_ide/src/completion/complete_path.rs b/crates/ra_ide/src/completion/complete_path.rs
index 3db17f15f..3ed2ae2b6 100644
--- a/crates/ra_ide/src/completion/complete_path.rs
+++ b/crates/ra_ide/src/completion/complete_path.rs
@@ -38,7 +38,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
38 hir::ModuleDef::Adt(_) | hir::ModuleDef::TypeAlias(_) => { 38 hir::ModuleDef::Adt(_) | hir::ModuleDef::TypeAlias(_) => {
39 if let hir::ModuleDef::Adt(Adt::Enum(e)) = def { 39 if let hir::ModuleDef::Adt(Adt::Enum(e)) = def {
40 for variant in e.variants(ctx.db) { 40 for variant in e.variants(ctx.db) {
41 acc.add_enum_variant(ctx, variant); 41 acc.add_enum_variant(ctx, variant, None);
42 } 42 }
43 } 43 }
44 let ty = match def { 44 let ty = match def {
@@ -58,7 +58,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
58 match item { 58 match item {
59 hir::AssocItem::Function(func) => { 59 hir::AssocItem::Function(func) => {
60 if !func.has_self_param(ctx.db) { 60 if !func.has_self_param(ctx.db) {
61 acc.add_function(ctx, func); 61 acc.add_function(ctx, func, None);
62 } 62 }
63 } 63 }
64 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), 64 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
@@ -87,7 +87,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
87 match item { 87 match item {
88 hir::AssocItem::Function(func) => { 88 hir::AssocItem::Function(func) => {
89 if !func.has_self_param(ctx.db) { 89 if !func.has_self_param(ctx.db) {
90 acc.add_function(ctx, func); 90 acc.add_function(ctx, func, None);
91 } 91 }
92 } 92 }
93 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), 93 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
@@ -355,15 +355,17 @@ mod tests {
355 @r###" 355 @r###"
356 [ 356 [
357 CompletionItem { 357 CompletionItem {
358 label: "Bar", 358 label: "Bar(…)",
359 source_range: [116; 116), 359 source_range: [116; 116),
360 delete: [116; 116), 360 delete: [116; 116),
361 insert: "Bar", 361 insert: "Bar($0)",
362 kind: EnumVariant, 362 kind: EnumVariant,
363 lookup: "Bar",
363 detail: "(i32)", 364 detail: "(i32)",
364 documentation: Documentation( 365 documentation: Documentation(
365 "Bar Variant with i32", 366 "Bar Variant with i32",
366 ), 367 ),
368 trigger_call_info: true,
367 }, 369 },
368 CompletionItem { 370 CompletionItem {
369 label: "Foo", 371 label: "Foo",
@@ -403,15 +405,17 @@ mod tests {
403 @r###" 405 @r###"
404 [ 406 [
405 CompletionItem { 407 CompletionItem {
406 label: "Bar", 408 label: "Bar(…)",
407 source_range: [180; 180), 409 source_range: [180; 180),
408 delete: [180; 180), 410 delete: [180; 180),
409 insert: "Bar", 411 insert: "Bar($0)",
410 kind: EnumVariant, 412 kind: EnumVariant,
413 lookup: "Bar",
411 detail: "(i32, u32)", 414 detail: "(i32, u32)",
412 documentation: Documentation( 415 documentation: Documentation(
413 "Bar Variant with i32 and u32", 416 "Bar Variant with i32 and u32",
414 ), 417 ),
418 trigger_call_info: true,
415 }, 419 },
416 CompletionItem { 420 CompletionItem {
417 label: "Foo", 421 label: "Foo",
@@ -425,15 +429,17 @@ mod tests {
425 ), 429 ),
426 }, 430 },
427 CompletionItem { 431 CompletionItem {
428 label: "S", 432 label: "S(…)",
429 source_range: [180; 180), 433 source_range: [180; 180),
430 delete: [180; 180), 434 delete: [180; 180),
431 insert: "S", 435 insert: "S($0)",
432 kind: EnumVariant, 436 kind: EnumVariant,
437 lookup: "S",
433 detail: "(S)", 438 detail: "(S)",
434 documentation: Documentation( 439 documentation: Documentation(
435 "", 440 "",
436 ), 441 ),
442 trigger_call_info: true,
437 }, 443 },
438 ] 444 ]
439 "### 445 "###
diff --git a/crates/ra_ide/src/completion/complete_pattern.rs b/crates/ra_ide/src/completion/complete_pattern.rs
index bc8fade6f..1b7d3122f 100644
--- a/crates/ra_ide/src/completion/complete_pattern.rs
+++ b/crates/ra_ide/src/completion/complete_pattern.rs
@@ -4,23 +4,25 @@ use crate::completion::{CompletionContext, Completions};
4 4
5/// Completes constats and paths in patterns. 5/// Completes constats and paths in patterns.
6pub(super) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { 6pub(super) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
7 if !ctx.is_pat_binding { 7 if !ctx.is_pat_binding_or_const {
8 return; 8 return;
9 } 9 }
10 // FIXME: ideally, we should look at the type we are matching against and 10 // FIXME: ideally, we should look at the type we are matching against and
11 // suggest variants + auto-imports 11 // suggest variants + auto-imports
12 ctx.scope().process_all_names(&mut |name, res| { 12 ctx.scope().process_all_names(&mut |name, res| {
13 let def = match &res { 13 match &res {
14 hir::ScopeDef::ModuleDef(def) => def, 14 hir::ScopeDef::ModuleDef(def) => match def {
15 hir::ModuleDef::Adt(hir::Adt::Enum(..))
16 | hir::ModuleDef::Adt(hir::Adt::Struct(..))
17 | hir::ModuleDef::EnumVariant(..)
18 | hir::ModuleDef::Const(..)
19 | hir::ModuleDef::Module(..) => (),
20 _ => return,
21 },
22 hir::ScopeDef::MacroDef(_) => (),
15 _ => return, 23 _ => return,
16 }; 24 };
17 match def { 25
18 hir::ModuleDef::Adt(hir::Adt::Enum(..))
19 | hir::ModuleDef::EnumVariant(..)
20 | hir::ModuleDef::Const(..)
21 | hir::ModuleDef::Module(..) => (),
22 _ => return,
23 }
24 acc.add_resolution(ctx, name.to_string(), &res) 26 acc.add_resolution(ctx, name.to_string(), &res)
25 }); 27 });
26} 28}
@@ -70,32 +72,12 @@ mod tests {
70 kind: Enum, 72 kind: Enum,
71 }, 73 },
72 CompletionItem { 74 CompletionItem {
73 label: "E",
74 source_range: [246; 246),
75 delete: [246; 246),
76 insert: "E",
77 kind: Enum,
78 },
79 CompletionItem {
80 label: "X", 75 label: "X",
81 source_range: [246; 246), 76 source_range: [246; 246),
82 delete: [246; 246), 77 delete: [246; 246),
83 insert: "X", 78 insert: "X",
84 kind: EnumVariant, 79 kind: EnumVariant,
85 }, 80 detail: "()",
86 CompletionItem {
87 label: "X",
88 source_range: [246; 246),
89 delete: [246; 246),
90 insert: "X",
91 kind: EnumVariant,
92 },
93 CompletionItem {
94 label: "Z",
95 source_range: [246; 246),
96 delete: [246; 246),
97 insert: "Z",
98 kind: Const,
99 }, 81 },
100 CompletionItem { 82 CompletionItem {
101 label: "Z", 83 label: "Z",
@@ -111,13 +93,6 @@ mod tests {
111 insert: "m", 93 insert: "m",
112 kind: Module, 94 kind: Module,
113 }, 95 },
114 CompletionItem {
115 label: "m",
116 source_range: [246; 246),
117 delete: [246; 246),
118 insert: "m",
119 kind: Module,
120 },
121 ] 96 ]
122 "###); 97 "###);
123 } 98 }
@@ -146,13 +121,6 @@ mod tests {
146 kind: Enum, 121 kind: Enum,
147 }, 122 },
148 CompletionItem { 123 CompletionItem {
149 label: "E",
150 source_range: [151; 151),
151 delete: [151; 151),
152 insert: "E",
153 kind: Enum,
154 },
155 CompletionItem {
156 label: "m!", 124 label: "m!",
157 source_range: [151; 151), 125 source_range: [151; 151),
158 delete: [151; 151), 126 delete: [151; 151),
diff --git a/crates/ra_ide/src/completion/complete_scope.rs b/crates/ra_ide/src/completion/complete_scope.rs
index 2ca552733..665597e4c 100644
--- a/crates/ra_ide/src/completion/complete_scope.rs
+++ b/crates/ra_ide/src/completion/complete_scope.rs
@@ -1,19 +1,13 @@
1//! Completion of names from the current scope, e.g. locals and imported items. 1//! Completion of names from the current scope, e.g. locals and imported items.
2 2
3use crate::completion::{CompletionContext, Completions}; 3use crate::completion::{CompletionContext, Completions};
4use hir::{ModuleDef, ScopeDef};
5 4
6pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { 5pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
7 if !ctx.is_trivial_path && !ctx.is_pat_binding_and_path { 6 if !(ctx.is_trivial_path && !ctx.is_pat_binding_or_const) {
8 return; 7 return;
9 } 8 }
10 9
11 ctx.scope().process_all_names(&mut |name, res| match (ctx.is_pat_binding_and_path, &res) { 10 ctx.scope().process_all_names(&mut |name, res| acc.add_resolution(ctx, name.to_string(), &res));
12 (true, ScopeDef::ModuleDef(ModuleDef::Function(..))) => (),
13 (true, ScopeDef::ModuleDef(ModuleDef::Static(..))) => (),
14 (true, ScopeDef::Local(..)) => (),
15 _ => acc.add_resolution(ctx, name.to_string(), &res),
16 });
17} 11}
18 12
19#[cfg(test)] 13#[cfg(test)]
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs
index fdc0da2c5..b8213d62f 100644
--- a/crates/ra_ide/src/completion/completion_context.rs
+++ b/crates/ra_ide/src/completion/completion_context.rs
@@ -35,10 +35,7 @@ pub(crate) struct CompletionContext<'a> {
35 pub(super) is_param: bool, 35 pub(super) is_param: bool,
36 /// If a name-binding or reference to a const in a pattern. 36 /// If a name-binding or reference to a const in a pattern.
37 /// Irrefutable patterns (like let) are excluded. 37 /// Irrefutable patterns (like let) are excluded.
38 pub(super) is_pat_binding: bool, 38 pub(super) is_pat_binding_or_const: bool,
39 // A bind battern which may also be part of a path.
40 // if let Some(En<|>) = Some(Enum::A)
41 pub(super) is_pat_binding_and_path: bool,
42 /// A single-indent path, like `foo`. `::foo` should not be considered a trivial path. 39 /// A single-indent path, like `foo`. `::foo` should not be considered a trivial path.
43 pub(super) is_trivial_path: bool, 40 pub(super) is_trivial_path: bool,
44 /// If not a trivial path, the prefix (qualifier). 41 /// If not a trivial path, the prefix (qualifier).
@@ -97,8 +94,7 @@ impl<'a> CompletionContext<'a> {
97 record_lit_pat: None, 94 record_lit_pat: None,
98 impl_def: None, 95 impl_def: None,
99 is_param: false, 96 is_param: false,
100 is_pat_binding: false, 97 is_pat_binding_or_const: false,
101 is_pat_binding_and_path: false,
102 is_trivial_path: false, 98 is_trivial_path: false,
103 path_prefix: None, 99 path_prefix: None,
104 after_if: false, 100 after_if: false,
@@ -190,18 +186,19 @@ impl<'a> CompletionContext<'a> {
190 // suggest declaration names, see `CompletionKind::Magic`. 186 // suggest declaration names, see `CompletionKind::Magic`.
191 if let Some(name) = find_node_at_offset::<ast::Name>(&file_with_fake_ident, offset) { 187 if let Some(name) = find_node_at_offset::<ast::Name>(&file_with_fake_ident, offset) {
192 if let Some(bind_pat) = name.syntax().ancestors().find_map(ast::BindPat::cast) { 188 if let Some(bind_pat) = name.syntax().ancestors().find_map(ast::BindPat::cast) {
193 let parent = bind_pat.syntax().parent(); 189 self.is_pat_binding_or_const = true;
194 if parent.clone().and_then(ast::MatchArm::cast).is_some() 190 if bind_pat.has_at() || bind_pat.is_ref() || bind_pat.is_mutable() {
195 || parent.clone().and_then(ast::Condition::cast).is_some() 191 self.is_pat_binding_or_const = false;
196 {
197 self.is_pat_binding = true;
198 } 192 }
199 193 if bind_pat.syntax().parent().and_then(ast::RecordFieldPatList::cast).is_some() {
200 if parent.and_then(ast::RecordFieldPatList::cast).is_none() 194 self.is_pat_binding_or_const = false;
201 && bind_pat.pat().is_none() 195 }
202 && !bind_pat.is_ref() 196 if let Some(let_stmt) = bind_pat.syntax().ancestors().find_map(ast::LetStmt::cast) {
203 { 197 if let Some(pat) = let_stmt.pat() {
204 self.is_pat_binding_and_path = true; 198 if bind_pat.syntax().text_range().is_subrange(&pat.syntax().text_range()) {
199 self.is_pat_binding_or_const = false;
200 }
201 }
205 } 202 }
206 } 203 }
207 if is_node::<ast::Param>(name.syntax()) { 204 if is_node::<ast::Param>(name.syntax()) {
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs
index 1c7c0924d..cdfd7bc32 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -7,7 +7,8 @@ use test_utils::tested_by;
7 7
8use crate::{ 8use crate::{
9 completion::{ 9 completion::{
10 CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, 10 completion_item::Builder, CompletionContext, CompletionItem, CompletionItemKind,
11 CompletionKind, Completions,
11 }, 12 },
12 display::{const_label, macro_label, type_label, FunctionSignature}, 13 display::{const_label, macro_label, type_label, FunctionSignature},
13 RootDatabase, 14 RootDatabase,
@@ -56,14 +57,16 @@ impl Completions {
56 let kind = match resolution { 57 let kind = match resolution {
57 ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::Module, 58 ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::Module,
58 ScopeDef::ModuleDef(Function(func)) => { 59 ScopeDef::ModuleDef(Function(func)) => {
59 return self.add_function_with_name(ctx, Some(local_name), *func); 60 return self.add_function(ctx, *func, Some(local_name));
60 } 61 }
61 ScopeDef::ModuleDef(Adt(hir::Adt::Struct(_))) => CompletionItemKind::Struct, 62 ScopeDef::ModuleDef(Adt(hir::Adt::Struct(_))) => CompletionItemKind::Struct,
62 // FIXME: add CompletionItemKind::Union 63 // FIXME: add CompletionItemKind::Union
63 ScopeDef::ModuleDef(Adt(hir::Adt::Union(_))) => CompletionItemKind::Struct, 64 ScopeDef::ModuleDef(Adt(hir::Adt::Union(_))) => CompletionItemKind::Struct,
64 ScopeDef::ModuleDef(Adt(hir::Adt::Enum(_))) => CompletionItemKind::Enum, 65 ScopeDef::ModuleDef(Adt(hir::Adt::Enum(_))) => CompletionItemKind::Enum,
65 66
66 ScopeDef::ModuleDef(EnumVariant(..)) => CompletionItemKind::EnumVariant, 67 ScopeDef::ModuleDef(EnumVariant(var)) => {
68 return self.add_enum_variant(ctx, *var, Some(local_name));
69 }
67 ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::Const, 70 ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::Const,
68 ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::Static, 71 ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::Static,
69 ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::Trait, 72 ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::Trait,
@@ -124,10 +127,6 @@ impl Completions {
124 completion_item.kind(kind).set_documentation(docs).add_to(self) 127 completion_item.kind(kind).set_documentation(docs).add_to(self)
125 } 128 }
126 129
127 pub(crate) fn add_function(&mut self, ctx: &CompletionContext, func: hir::Function) {
128 self.add_function_with_name(ctx, None, func)
129 }
130
131 fn guess_macro_braces(&self, macro_name: &str, docs: &str) -> &'static str { 130 fn guess_macro_braces(&self, macro_name: &str, docs: &str) -> &'static str {
132 let mut votes = [0, 0, 0]; 131 let mut votes = [0, 0, 0];
133 for (idx, s) in docs.match_indices(&macro_name) { 132 for (idx, s) in docs.match_indices(&macro_name) {
@@ -186,16 +185,15 @@ impl Completions {
186 self.add(builder); 185 self.add(builder);
187 } 186 }
188 187
189 fn add_function_with_name( 188 pub(crate) fn add_function(
190 &mut self, 189 &mut self,
191 ctx: &CompletionContext, 190 ctx: &CompletionContext,
192 name: Option<String>,
193 func: hir::Function, 191 func: hir::Function,
192 local_name: Option<String>,
194 ) { 193 ) {
195 let has_self_param = func.has_self_param(ctx.db); 194 let has_self_param = func.has_self_param(ctx.db);
196 let params = func.params(ctx.db);
197 195
198 let name = name.unwrap_or_else(|| func.name(ctx.db).to_string()); 196 let name = local_name.unwrap_or_else(|| func.name(ctx.db).to_string());
199 let ast_node = func.source(ctx.db).value; 197 let ast_node = func.source(ctx.db).value;
200 let function_signature = FunctionSignature::from(&ast_node); 198 let function_signature = FunctionSignature::from(&ast_node);
201 199
@@ -210,32 +208,14 @@ impl Completions {
210 .set_deprecated(is_deprecated(func, ctx.db)) 208 .set_deprecated(is_deprecated(func, ctx.db))
211 .detail(function_signature.to_string()); 209 .detail(function_signature.to_string());
212 210
213 // If not an import, add parenthesis automatically. 211 let params = function_signature
214 if ctx.use_item_syntax.is_none() && !ctx.is_call && ctx.config.add_call_parenthesis { 212 .parameter_names
215 tested_by!(inserts_parens_for_function_calls); 213 .iter()
216 214 .skip(if function_signature.has_self_param { 1 } else { 0 })
217 let (snippet, label) = if params.is_empty() || has_self_param && params.len() == 1 { 215 .cloned()
218 (format!("{}()$0", name), format!("{}()", name)) 216 .collect();
219 } else {
220 builder = builder.trigger_call_info();
221 let snippet = if ctx.config.add_call_argument_snippets {
222 let to_skip = if has_self_param { 1 } else { 0 };
223 let function_params_snippet = function_signature
224 .parameter_names
225 .iter()
226 .skip(to_skip)
227 .enumerate()
228 .map(|(index, param_name)| format!("${{{}:{}}}", index + 1, param_name))
229 .sep_by(", ");
230 format!("{}({})$0", name, function_params_snippet)
231 } else {
232 format!("{}($0)", name)
233 };
234 217
235 (snippet, format!("{}(…)", name)) 218 builder = builder.add_call_parens(ctx, name, Params::Named(params));
236 };
237 builder = builder.lookup_by(name).label(label).insert_snippet(snippet);
238 }
239 219
240 self.add(builder) 220 self.add(builder)
241 } 221 }
@@ -272,14 +252,20 @@ impl Completions {
272 .add_to(self); 252 .add_to(self);
273 } 253 }
274 254
275 pub(crate) fn add_enum_variant(&mut self, ctx: &CompletionContext, variant: hir::EnumVariant) { 255 pub(crate) fn add_enum_variant(
256 &mut self,
257 ctx: &CompletionContext,
258 variant: hir::EnumVariant,
259 local_name: Option<String>,
260 ) {
276 let is_deprecated = is_deprecated(variant, ctx.db); 261 let is_deprecated = is_deprecated(variant, ctx.db);
277 let name = variant.name(ctx.db); 262 let name = local_name.unwrap_or_else(|| variant.name(ctx.db).to_string());
278 let detail_types = variant 263 let detail_types = variant
279 .fields(ctx.db) 264 .fields(ctx.db)
280 .into_iter() 265 .into_iter()
281 .map(|field| (field.name(ctx.db), field.signature_ty(ctx.db))); 266 .map(|field| (field.name(ctx.db), field.signature_ty(ctx.db)));
282 let detail = match variant.kind(ctx.db) { 267 let variant_kind = variant.kind(ctx.db);
268 let detail = match variant_kind {
283 StructKind::Tuple | StructKind::Unit => detail_types 269 StructKind::Tuple | StructKind::Unit => detail_types
284 .map(|(_, t)| t.display(ctx.db).to_string()) 270 .map(|(_, t)| t.display(ctx.db).to_string())
285 .sep_by(", ") 271 .sep_by(", ")
@@ -291,12 +277,70 @@ impl Completions {
291 .surround_with("{ ", " }") 277 .surround_with("{ ", " }")
292 .to_string(), 278 .to_string(),
293 }; 279 };
294 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string()) 280 let mut res =
295 .kind(CompletionItemKind::EnumVariant) 281 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.clone())
296 .set_documentation(variant.docs(ctx.db)) 282 .kind(CompletionItemKind::EnumVariant)
297 .set_deprecated(is_deprecated) 283 .set_documentation(variant.docs(ctx.db))
298 .detail(detail) 284 .set_deprecated(is_deprecated)
299 .add_to(self); 285 .detail(detail);
286
287 if variant_kind == StructKind::Tuple {
288 let params = Params::Anonymous(variant.fields(ctx.db).len());
289 res = res.add_call_parens(ctx, name, params)
290 }
291
292 res.add_to(self);
293 }
294}
295
296enum Params {
297 Named(Vec<String>),
298 Anonymous(usize),
299}
300
301impl Params {
302 fn len(&self) -> usize {
303 match self {
304 Params::Named(xs) => xs.len(),
305 Params::Anonymous(len) => *len,
306 }
307 }
308
309 fn is_empty(&self) -> bool {
310 self.len() == 0
311 }
312}
313
314impl Builder {
315 fn add_call_parens(mut self, ctx: &CompletionContext, name: String, params: Params) -> Builder {
316 if !ctx.config.add_call_parenthesis {
317 return self;
318 }
319 if ctx.use_item_syntax.is_some() || ctx.is_call {
320 return self;
321 }
322 // If not an import, add parenthesis automatically.
323 tested_by!(inserts_parens_for_function_calls);
324
325 let (snippet, label) = if params.is_empty() {
326 (format!("{}()$0", name), format!("{}()", name))
327 } else {
328 self = self.trigger_call_info();
329 let snippet = match (ctx.config.add_call_argument_snippets, params) {
330 (true, Params::Named(params)) => {
331 let function_params_snippet = params
332 .iter()
333 .enumerate()
334 .map(|(index, param_name)| format!("${{{}:{}}}", index + 1, param_name))
335 .sep_by(", ");
336 format!("{}({})$0", name, function_params_snippet)
337 }
338 _ => format!("{}($0)", name),
339 };
340
341 (snippet, format!("{}(…)", name))
342 };
343 self.lookup_by(name).label(label).insert_snippet(snippet)
300 } 344 }
301} 345}
302 346
@@ -366,12 +410,14 @@ mod tests {
366 @r###" 410 @r###"
367 [ 411 [
368 CompletionItem { 412 CompletionItem {
369 label: "Foo", 413 label: "Foo(…)",
370 source_range: [115; 117), 414 source_range: [115; 117),
371 delete: [115; 117), 415 delete: [115; 117),
372 insert: "Foo", 416 insert: "Foo($0)",
373 kind: EnumVariant, 417 kind: EnumVariant,
418 lookup: "Foo",
374 detail: "(i32, i32)", 419 detail: "(i32, i32)",
420 trigger_call_info: true,
375 }, 421 },
376 ]"### 422 ]"###
377 ); 423 );
@@ -546,6 +592,101 @@ mod tests {
546 } 592 }
547 593
548 #[test] 594 #[test]
595 fn inserts_parens_for_tuple_enums() {
596 assert_debug_snapshot!(
597 do_reference_completion(
598 r"
599 enum Option<T> { Some(T), None }
600 use Option::*;
601 fn main() -> Option<i32> {
602 Som<|>
603 }
604 "
605 ),
606 @r###"
607 [
608 CompletionItem {
609 label: "None",
610 source_range: [144; 147),
611 delete: [144; 147),
612 insert: "None",
613 kind: EnumVariant,
614 detail: "()",
615 },
616 CompletionItem {
617 label: "Option",
618 source_range: [144; 147),
619 delete: [144; 147),
620 insert: "Option",
621 kind: Enum,
622 },
623 CompletionItem {
624 label: "Some(…)",
625 source_range: [144; 147),
626 delete: [144; 147),
627 insert: "Some($0)",
628 kind: EnumVariant,
629 lookup: "Some",
630 detail: "(T)",
631 trigger_call_info: true,
632 },
633 CompletionItem {
634 label: "main()",
635 source_range: [144; 147),
636 delete: [144; 147),
637 insert: "main()$0",
638 kind: Function,
639 lookup: "main",
640 detail: "fn main() -> Option<i32>",
641 },
642 ]
643 "###
644 );
645 assert_debug_snapshot!(
646 do_reference_completion(
647 r"
648 enum Option<T> { Some(T), None }
649 use Option::*;
650 fn main(value: Option<i32>) {
651 match value {
652 Som<|>
653 }
654 }
655 "
656 ),
657 @r###"
658 [
659 CompletionItem {
660 label: "None",
661 source_range: [185; 188),
662 delete: [185; 188),
663 insert: "None",
664 kind: EnumVariant,
665 detail: "()",
666 },
667 CompletionItem {
668 label: "Option",
669 source_range: [185; 188),
670 delete: [185; 188),
671 insert: "Option",
672 kind: Enum,
673 },
674 CompletionItem {
675 label: "Some(…)",
676 source_range: [185; 188),
677 delete: [185; 188),
678 insert: "Some($0)",
679 kind: EnumVariant,
680 lookup: "Some",
681 detail: "(T)",
682 trigger_call_info: true,
683 },
684 ]
685 "###
686 );
687 }
688
689 #[test]
549 fn arg_snippets_for_method_call() { 690 fn arg_snippets_for_method_call() {
550 assert_debug_snapshot!( 691 assert_debug_snapshot!(
551 do_reference_completion( 692 do_reference_completion(
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs
index 0c170ac5e..c486c0211 100644
--- a/crates/ra_parser/src/grammar/expressions.rs
+++ b/crates/ra_parser/src/grammar/expressions.rs
@@ -79,8 +79,6 @@ fn is_expr_stmt_attr_allowed(kind: SyntaxKind) -> bool {
79} 79}
80 80
81pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) { 81pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) {
82 // test block_items
83 // fn a() { fn b() {} }
84 let m = p.start(); 82 let m = p.start();
85 // test attr_on_expr_stmt 83 // test attr_on_expr_stmt
86 // fn foo() { 84 // fn foo() {
@@ -97,6 +95,8 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) {
97 return; 95 return;
98 } 96 }
99 97
98 // test block_items
99 // fn a() { fn b() {} }
100 let m = match items::maybe_item(p, m, items::ItemFlavor::Mod) { 100 let m = match items::maybe_item(p, m, items::ItemFlavor::Mod) {
101 Ok(()) => return, 101 Ok(()) => return,
102 Err(m) => m, 102 Err(m) => m,
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs
index 3afbaa82b..936d27575 100644
--- a/crates/ra_parser/src/grammar/patterns.rs
+++ b/crates/ra_parser/src/grammar/patterns.rs
@@ -70,15 +70,6 @@ fn pattern_single_r(p: &mut Parser, recovery_set: TokenSet) {
70 return; 70 return;
71 } 71 }
72 } 72 }
73 // test marco_pat
74 // fn main() {
75 // let m!(x) = 0;
76 // }
77 if lhs.kind() == PATH_PAT && p.at(T![!]) {
78 let m = lhs.undo_completion(p);
79 items::macro_call_after_excl(p);
80 m.complete(p, MACRO_CALL);
81 }
82 } 73 }
83} 74}
84 75
@@ -92,12 +83,12 @@ fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
92 IDENT => match p.nth(1) { 83 IDENT => match p.nth(1) {
93 // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro 84 // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro
94 // (T![x]). 85 // (T![x]).
95 T!['('] | T!['{'] | T![!] => path_pat(p), 86 T!['('] | T!['{'] | T![!] => path_or_macro_pat(p),
96 T![:] if p.nth_at(1, T![::]) => path_pat(p), 87 T![:] if p.nth_at(1, T![::]) => path_or_macro_pat(p),
97 _ => bind_pat(p, true), 88 _ => bind_pat(p, true),
98 }, 89 },
99 90
100 _ if paths::is_use_path_start(p) => path_pat(p), 91 _ if paths::is_use_path_start(p) => path_or_macro_pat(p),
101 _ if is_literal_pat_start(p) => literal_pat(p), 92 _ if is_literal_pat_start(p) => literal_pat(p),
102 93
103 T![.] if p.at(T![..]) => dot_dot_pat(p), 94 T![.] if p.at(T![..]) => dot_dot_pat(p),
@@ -146,7 +137,7 @@ fn literal_pat(p: &mut Parser) -> CompletedMarker {
146// let Bar { .. } = (); 137// let Bar { .. } = ();
147// let Bar(..) = (); 138// let Bar(..) = ();
148// } 139// }
149fn path_pat(p: &mut Parser) -> CompletedMarker { 140fn path_or_macro_pat(p: &mut Parser) -> CompletedMarker {
150 assert!(paths::is_use_path_start(p)); 141 assert!(paths::is_use_path_start(p));
151 let m = p.start(); 142 let m = p.start();
152 paths::expr_path(p); 143 paths::expr_path(p);
@@ -159,6 +150,14 @@ fn path_pat(p: &mut Parser) -> CompletedMarker {
159 record_field_pat_list(p); 150 record_field_pat_list(p);
160 RECORD_PAT 151 RECORD_PAT
161 } 152 }
153 // test marco_pat
154 // fn main() {
155 // let m!(x) = 0;
156 // }
157 T![!] => {
158 items::macro_call_after_excl(p);
159 return m.complete(p, MACRO_CALL).precede(p).complete(p, MACRO_PAT);
160 }
162 _ => PATH_PAT, 161 _ => PATH_PAT,
163 }; 162 };
164 m.complete(p, kind) 163 m.complete(p, kind)
diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs
index dfc30d727..4c16cf1cd 100644
--- a/crates/ra_parser/src/syntax_kind/generated.rs
+++ b/crates/ra_parser/src/syntax_kind/generated.rs
@@ -167,6 +167,7 @@ pub enum SyntaxKind {
167 SLICE_PAT, 167 SLICE_PAT,
168 RANGE_PAT, 168 RANGE_PAT,
169 LITERAL_PAT, 169 LITERAL_PAT,
170 MACRO_PAT,
170 TUPLE_EXPR, 171 TUPLE_EXPR,
171 ARRAY_EXPR, 172 ARRAY_EXPR,
172 PAREN_EXPR, 173 PAREN_EXPR,
diff --git a/crates/ra_proc_macro/src/lib.rs b/crates/ra_proc_macro/src/lib.rs
index 51fbb046a..63da9f1b4 100644
--- a/crates/ra_proc_macro/src/lib.rs
+++ b/crates/ra_proc_macro/src/lib.rs
@@ -11,13 +11,12 @@ pub mod msg;
11 11
12use process::{ProcMacroProcessSrv, ProcMacroProcessThread}; 12use process::{ProcMacroProcessSrv, ProcMacroProcessThread};
13use ra_tt::{SmolStr, Subtree}; 13use ra_tt::{SmolStr, Subtree};
14use rpc::ProcMacroKind;
15use std::{ 14use std::{
16 path::{Path, PathBuf}, 15 path::{Path, PathBuf},
17 sync::Arc, 16 sync::Arc,
18}; 17};
19 18
20pub use rpc::{ExpansionResult, ExpansionTask}; 19pub use rpc::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask, ProcMacroKind};
21 20
22#[derive(Debug, Clone)] 21#[derive(Debug, Clone)]
23pub struct ProcMacroProcessExpander { 22pub struct ProcMacroProcessExpander {
diff --git a/crates/ra_proc_macro_srv/Cargo.toml b/crates/ra_proc_macro_srv/Cargo.toml
new file mode 100644
index 000000000..315191cc5
--- /dev/null
+++ b/crates/ra_proc_macro_srv/Cargo.toml
@@ -0,0 +1,21 @@
1[package]
2edition = "2018"
3name = "ra_proc_macro_srv"
4version = "0.1.0"
5authors = ["rust-analyzer developers"]
6publish = false
7
8[lib]
9doctest = false
10
11[dependencies]
12ra_tt = { path = "../ra_tt" }
13ra_proc_macro = { path = "../ra_proc_macro" }
14
15serde_derive = "1.0.104"
16serde = "1.0.104"
17serde_json = "1.0.48"
18
19[dev-dependencies]
20cargo_metadata = "0.9.1"
21difference = "2.0.0"
diff --git a/crates/ra_proc_macro_srv/src/lib.rs b/crates/ra_proc_macro_srv/src/lib.rs
new file mode 100644
index 000000000..f77be1475
--- /dev/null
+++ b/crates/ra_proc_macro_srv/src/lib.rs
@@ -0,0 +1,21 @@
1//! RA Proc Macro Server
2//!
3//! This library is able to call compiled Rust custom derive dynamic libraries on arbitrary code.
4//! The general idea here is based on https://github.com/fedochet/rust-proc-macro-expander.
5//!
6//! But we change some several design for fitting RA needs:
7//!
8//! * We use `ra_tt` for proc-macro `TokenStream` server, it is easy to manipute and interact with
9//! RA then proc-macro2 token stream.
10//! * By **copying** the whole rustc `lib_proc_macro` code, we are able to build this with `stable`
11//! rustc rather than `unstable`. (Although in gerenal ABI compatibility is still an issue)
12
13use ra_proc_macro::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask};
14
15pub fn expand_task(_task: &ExpansionTask) -> Result<ExpansionResult, String> {
16 unimplemented!()
17}
18
19pub fn list_macros(_task: &ListMacrosTask) -> Result<ListMacrosResult, String> {
20 unimplemented!()
21}
diff --git a/crates/ra_proc_macro_srv/src/main.rs b/crates/ra_proc_macro_srv/src/main.rs
new file mode 100644
index 000000000..70743c1f4
--- /dev/null
+++ b/crates/ra_proc_macro_srv/src/main.rs
@@ -0,0 +1,55 @@
1//! Driver for proc macro server
2
3use ra_proc_macro::msg::{self, Message};
4use ra_proc_macro_srv::{expand_task, list_macros};
5
6use std::io;
7
8fn read_request() -> Result<Option<msg::Request>, io::Error> {
9 let stdin = io::stdin();
10 let mut stdin = stdin.lock();
11 msg::Request::read(&mut stdin)
12}
13
14fn write_response(res: Result<msg::Response, String>) -> Result<(), io::Error> {
15 let msg: msg::Response = match res {
16 Ok(res) => res,
17 Err(err) => msg::Response::Error(msg::ResponseError {
18 code: msg::ErrorCode::ExpansionError,
19 message: err,
20 }),
21 };
22
23 let stdout = io::stdout();
24 let mut stdout = stdout.lock();
25 msg.write(&mut stdout)
26}
27fn main() {
28 loop {
29 let req = match read_request() {
30 Err(err) => {
31 eprintln!("Read message error on ra_proc_macro_srv: {}", err.to_string());
32 continue;
33 }
34 Ok(None) => continue,
35 Ok(Some(req)) => req,
36 };
37
38 match req {
39 msg::Request::ListMacro(task) => {
40 if let Err(err) =
41 write_response(list_macros(&task).map(|it| msg::Response::ListMacro(it)))
42 {
43 eprintln!("Write message error on list macro: {}", err);
44 }
45 }
46 msg::Request::ExpansionMacro(task) => {
47 if let Err(err) =
48 write_response(expand_task(&task).map(|it| msg::Response::ExpansionMacro(it)))
49 {
50 eprintln!("Write message error on expansion macro: {}", err);
51 }
52 }
53 }
54 }
55}
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index 392731dac..bf7d137be 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -325,6 +325,9 @@ impl ast::BindPat {
325 pub fn is_ref(&self) -> bool { 325 pub fn is_ref(&self) -> bool {
326 self.syntax().children_with_tokens().any(|n| n.kind() == T![ref]) 326 self.syntax().children_with_tokens().any(|n| n.kind() == T![ref])
327 } 327 }
328 pub fn has_at(&self) -> bool {
329 self.syntax().children_with_tokens().any(|it| it.kind() == T![@])
330 }
328} 331}
329 332
330pub struct SlicePatComponents { 333pub struct SlicePatComponents {
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 7204ca5b1..0c339b987 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -2563,6 +2563,38 @@ impl LiteralPat {
2563 } 2563 }
2564} 2564}
2565#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2565#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2566pub struct MacroPat {
2567 pub(crate) syntax: SyntaxNode,
2568}
2569impl std::fmt::Display for MacroPat {
2570 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2571 std::fmt::Display::fmt(self.syntax(), f)
2572 }
2573}
2574impl AstNode for MacroPat {
2575 fn can_cast(kind: SyntaxKind) -> bool {
2576 match kind {
2577 MACRO_PAT => true,
2578 _ => false,
2579 }
2580 }
2581 fn cast(syntax: SyntaxNode) -> Option<Self> {
2582 if Self::can_cast(syntax.kind()) {
2583 Some(Self { syntax })
2584 } else {
2585 None
2586 }
2587 }
2588 fn syntax(&self) -> &SyntaxNode {
2589 &self.syntax
2590 }
2591}
2592impl MacroPat {
2593 pub fn macro_call(&self) -> Option<MacroCall> {
2594 AstChildren::new(&self.syntax).next()
2595 }
2596}
2597#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2566pub struct RecordPat { 2598pub struct RecordPat {
2567 pub(crate) syntax: SyntaxNode, 2599 pub(crate) syntax: SyntaxNode,
2568} 2600}
@@ -4600,6 +4632,7 @@ pub enum Pat {
4600 SlicePat(SlicePat), 4632 SlicePat(SlicePat),
4601 RangePat(RangePat), 4633 RangePat(RangePat),
4602 LiteralPat(LiteralPat), 4634 LiteralPat(LiteralPat),
4635 MacroPat(MacroPat),
4603} 4636}
4604impl From<OrPat> for Pat { 4637impl From<OrPat> for Pat {
4605 fn from(node: OrPat) -> Pat { 4638 fn from(node: OrPat) -> Pat {
@@ -4671,6 +4704,11 @@ impl From<LiteralPat> for Pat {
4671 Pat::LiteralPat(node) 4704 Pat::LiteralPat(node)
4672 } 4705 }
4673} 4706}
4707impl From<MacroPat> for Pat {
4708 fn from(node: MacroPat) -> Pat {
4709 Pat::MacroPat(node)
4710 }
4711}
4674impl std::fmt::Display for Pat { 4712impl std::fmt::Display for Pat {
4675 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 4713 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
4676 std::fmt::Display::fmt(self.syntax(), f) 4714 std::fmt::Display::fmt(self.syntax(), f)
@@ -4681,7 +4719,7 @@ impl AstNode for Pat {
4681 match kind { 4719 match kind {
4682 OR_PAT | PAREN_PAT | REF_PAT | BOX_PAT | BIND_PAT | PLACEHOLDER_PAT | DOT_DOT_PAT 4720 OR_PAT | PAREN_PAT | REF_PAT | BOX_PAT | BIND_PAT | PLACEHOLDER_PAT | DOT_DOT_PAT
4683 | PATH_PAT | RECORD_PAT | TUPLE_STRUCT_PAT | TUPLE_PAT | SLICE_PAT | RANGE_PAT 4721 | PATH_PAT | RECORD_PAT | TUPLE_STRUCT_PAT | TUPLE_PAT | SLICE_PAT | RANGE_PAT
4684 | LITERAL_PAT => true, 4722 | LITERAL_PAT | MACRO_PAT => true,
4685 _ => false, 4723 _ => false,
4686 } 4724 }
4687 } 4725 }
@@ -4701,6 +4739,7 @@ impl AstNode for Pat {
4701 SLICE_PAT => Pat::SlicePat(SlicePat { syntax }), 4739 SLICE_PAT => Pat::SlicePat(SlicePat { syntax }),
4702 RANGE_PAT => Pat::RangePat(RangePat { syntax }), 4740 RANGE_PAT => Pat::RangePat(RangePat { syntax }),
4703 LITERAL_PAT => Pat::LiteralPat(LiteralPat { syntax }), 4741 LITERAL_PAT => Pat::LiteralPat(LiteralPat { syntax }),
4742 MACRO_PAT => Pat::MacroPat(MacroPat { syntax }),
4704 _ => return None, 4743 _ => return None,
4705 }; 4744 };
4706 Some(res) 4745 Some(res)
@@ -4721,6 +4760,7 @@ impl AstNode for Pat {
4721 Pat::SlicePat(it) => &it.syntax, 4760 Pat::SlicePat(it) => &it.syntax,
4722 Pat::RangePat(it) => &it.syntax, 4761 Pat::RangePat(it) => &it.syntax,
4723 Pat::LiteralPat(it) => &it.syntax, 4762 Pat::LiteralPat(it) => &it.syntax,
4763 Pat::MacroPat(it) => &it.syntax,
4724 } 4764 }
4725 } 4765 }
4726} 4766}
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs
index 0c908573d..f39559e9e 100644
--- a/crates/ra_syntax/src/ast/make.rs
+++ b/crates/ra_syntax/src/ast/make.rs
@@ -22,7 +22,8 @@ pub fn path_unqualified(segment: ast::PathSegment) -> ast::Path {
22pub fn path_qualified(qual: ast::Path, segment: ast::PathSegment) -> ast::Path { 22pub fn path_qualified(qual: ast::Path, segment: ast::PathSegment) -> ast::Path {
23 path_from_text(&format!("{}::{}", qual, segment)) 23 path_from_text(&format!("{}::{}", qual, segment))
24} 24}
25fn path_from_text(text: &str) -> ast::Path { 25
26pub fn path_from_text(text: &str) -> ast::Path {
26 ast_from_text(text) 27 ast_from_text(text)
27} 28}
28 29
@@ -269,6 +270,31 @@ pub fn unreachable_macro_call() -> ast::MacroCall {
269 ast_from_text(&format!("unreachable!()")) 270 ast_from_text(&format!("unreachable!()"))
270} 271}
271 272
273pub fn param(name: String, ty: String) -> ast::Param {
274 ast_from_text(&format!("fn f({}: {}) {{ }}", name, ty))
275}
276
277pub fn param_list(pats: impl IntoIterator<Item = ast::Param>) -> ast::ParamList {
278 let args = pats.into_iter().join(", ");
279 ast_from_text(&format!("fn f({}) {{ }}", args))
280}
281
282pub fn fn_def(
283 fn_name: ast::Name,
284 type_params: Option<ast::TypeParamList>,
285 params: ast::ParamList,
286 body: ast::BlockExpr,
287) -> ast::FnDef {
288 let type_params =
289 if let Some(type_params) = type_params { format!("<{}>", type_params) } else { "".into() };
290 ast_from_text(&format!("fn {}{}{} {}", fn_name, type_params, params, body))
291}
292
293pub fn add_newlines(amount_of_newlines: usize, t: impl AstNode) -> ast::SourceFile {
294 let newlines = "\n".repeat(amount_of_newlines);
295 ast_from_text(&format!("{}{}", newlines, t.syntax()))
296}
297
272fn ast_from_text<N: AstNode>(text: &str) -> N { 298fn ast_from_text<N: AstNode>(text: &str) -> N {
273 let parse = SourceFile::parse(text); 299 let parse = SourceFile::parse(text);
274 let node = parse.tree().syntax().descendants().find_map(N::cast).unwrap(); 300 let node = parse.tree().syntax().descendants().find_map(N::cast).unwrap();
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0129_marco_pat.txt b/crates/ra_syntax/test_data/parser/inline/ok/0129_marco_pat.txt
index b05ccc0ed..36d8f4a5f 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0129_marco_pat.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0129_marco_pat.txt
@@ -15,16 +15,17 @@ SOURCE_FILE@[0; 33)
15 LET_STMT@[16; 30) 15 LET_STMT@[16; 30)
16 LET_KW@[16; 19) "let" 16 LET_KW@[16; 19) "let"
17 WHITESPACE@[19; 20) " " 17 WHITESPACE@[19; 20) " "
18 MACRO_CALL@[20; 25) 18 MACRO_PAT@[20; 25)
19 PATH@[20; 21) 19 MACRO_CALL@[20; 25)
20 PATH_SEGMENT@[20; 21) 20 PATH@[20; 21)
21 NAME_REF@[20; 21) 21 PATH_SEGMENT@[20; 21)
22 IDENT@[20; 21) "m" 22 NAME_REF@[20; 21)
23 EXCL@[21; 22) "!" 23 IDENT@[20; 21) "m"
24 TOKEN_TREE@[22; 25) 24 EXCL@[21; 22) "!"
25 L_PAREN@[22; 23) "(" 25 TOKEN_TREE@[22; 25)
26 IDENT@[23; 24) "x" 26 L_PAREN@[22; 23) "("
27 R_PAREN@[24; 25) ")" 27 IDENT@[23; 24) "x"
28 R_PAREN@[24; 25) ")"
28 WHITESPACE@[25; 26) " " 29 WHITESPACE@[25; 26) " "
29 EQ@[26; 27) "=" 30 EQ@[26; 27) "="
30 WHITESPACE@[27; 28) " " 31 WHITESPACE@[27; 28) " "
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 04f5bb473..b6a015790 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -120,12 +120,10 @@ impl Config {
120 set(value, "/withSysroot", &mut self.with_sysroot); 120 set(value, "/withSysroot", &mut self.with_sysroot);
121 set(value, "/featureFlags/lsp.diagnostics", &mut self.publish_diagnostics); 121 set(value, "/featureFlags/lsp.diagnostics", &mut self.publish_diagnostics);
122 set(value, "/lruCapacity", &mut self.lru_capacity); 122 set(value, "/lruCapacity", &mut self.lru_capacity);
123 if let Some(watcher) = get::<String>(value, "/files/watcher") { 123 self.files.watcher = match get(value, "/files/watcher") {
124 self.files.watcher = match watcher.as_str() { 124 Some("client") => FilesWatcher::Client,
125 "client" => FilesWatcher::Client, 125 Some("notify") | _ => FilesWatcher::Notify
126 "notify"| _ => FilesWatcher::Notify, 126 };
127 }
128 }
129 set(value, "/notifications/workspaceLoaded", &mut self.notifications.workspace_loaded); 127 set(value, "/notifications/workspaceLoaded", &mut self.notifications.workspace_loaded);
130 set(value, "/notifications/cargoTomlNotFound", &mut self.notifications.cargo_toml_not_found); 128 set(value, "/notifications/cargoTomlNotFound", &mut self.notifications.cargo_toml_not_found);
131 129
@@ -144,8 +142,9 @@ impl Config {
144 } else if let RustfmtConfig::Rustfmt { extra_args } = &mut self.rustfmt { 142 } else if let RustfmtConfig::Rustfmt { extra_args } = &mut self.rustfmt {
145 set(value, "/rustfmt/extraArgs", extra_args); 143 set(value, "/rustfmt/extraArgs", extra_args);
146 } 144 }
145
147 if let Some(false) = get(value, "/checkOnSave/enable") { 146 if let Some(false) = get(value, "/checkOnSave/enable") {
148 self.check = None 147 self.check = None;
149 } else { 148 } else {
150 if let Some(mut args) = get::<Vec<String>>(value, "/checkOnSave/overrideCommand") { 149 if let Some(mut args) = get::<Vec<String>>(value, "/checkOnSave/overrideCommand") {
151 if !args.is_empty() { 150 if !args.is_empty() {
@@ -153,7 +152,7 @@ impl Config {
153 self.check = Some(FlycheckConfig::CustomCommand { 152 self.check = Some(FlycheckConfig::CustomCommand {
154 command, 153 command,
155 args, 154 args,
156 }) 155 });
157 } 156 }
158 157
159 } else if let Some(FlycheckConfig::CargoCommand { command, extra_args, all_targets }) = &mut self.check 158 } else if let Some(FlycheckConfig::CargoCommand { command, extra_args, all_targets }) = &mut self.check
@@ -179,7 +178,7 @@ impl Config {
179 value.pointer(pointer).and_then(|it| T::deserialize(it).ok()) 178 value.pointer(pointer).and_then(|it| T::deserialize(it).ok())
180 } 179 }
181 180
182 fn set<'a, T: Deserialize<'a> + std::fmt::Debug>(value: &'a serde_json::Value, pointer: &str, slot: &mut T) { 181 fn set<'a, T: Deserialize<'a>>(value: &'a serde_json::Value, pointer: &str, slot: &mut T) {
183 if let Some(new_value) = get(value, pointer) { 182 if let Some(new_value) = get(value, pointer) {
184 *slot = new_value 183 *slot = new_value
185 } 184 }