aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--crates/ra_hir_ty/src/infer.rs27
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs1
-rw-r--r--crates/ra_hir_ty/src/marks.rs1
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs65
-rw-r--r--crates/ra_parser/src/grammar/expressions/atom.rs7
-rw-r--r--crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.rs5
-rw-r--r--crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.txt83
-rw-r--r--editors/code/package.json4
-rw-r--r--editors/code/src/config.ts4
10 files changed, 190 insertions, 9 deletions
diff --git a/README.md b/README.md
index 979e4ef88..deaa147ba 100644
--- a/README.md
+++ b/README.md
@@ -58,7 +58,7 @@ https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frls-2.2E0
58## Quick Links 58## Quick Links
59 59
60* API docs: https://rust-analyzer.github.io/rust-analyzer/ra_ide/ 60* API docs: https://rust-analyzer.github.io/rust-analyzer/ra_ide/
61 61* Website: https://rust-analyzer.github.io/
62 62
63## License 63## License
64 64
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index af42854cc..98ba05fc2 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -32,6 +32,7 @@ use hir_def::{
32use hir_expand::{diagnostics::DiagnosticSink, name::name}; 32use hir_expand::{diagnostics::DiagnosticSink, name::name};
33use ra_arena::map::ArenaMap; 33use ra_arena::map::ArenaMap;
34use ra_prof::profile; 34use ra_prof::profile;
35use test_utils::tested_by;
35 36
36use super::{ 37use super::{
37 primitive::{FloatTy, IntTy}, 38 primitive::{FloatTy, IntTy},
@@ -274,6 +275,29 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
274 self.normalize_associated_types_in(ty) 275 self.normalize_associated_types_in(ty)
275 } 276 }
276 277
278 /// Replaces `impl Trait` in `ty` by type variables and obligations for
279 /// those variables. This is done for function arguments when calling a
280 /// function, and for return types when inside the function body, i.e. in
281 /// the cases where the `impl Trait` is 'transparent'. In other cases, `impl
282 /// Trait` is represented by `Ty::Opaque`.
283 fn insert_vars_for_impl_trait(&mut self, ty: Ty) -> Ty {
284 ty.fold(&mut |ty| match ty {
285 Ty::Opaque(preds) => {
286 tested_by!(insert_vars_for_impl_trait);
287 let var = self.table.new_type_var();
288 let var_subst = Substs::builder(1).push(var.clone()).build();
289 self.obligations.extend(
290 preds
291 .iter()
292 .map(|pred| pred.clone().subst_bound_vars(&var_subst))
293 .filter_map(Obligation::from_predicate),
294 );
295 var
296 }
297 _ => ty,
298 })
299 }
300
277 /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. 301 /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it.
278 fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { 302 fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
279 match ty { 303 match ty {
@@ -414,7 +438,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
414 438
415 self.infer_pat(*pat, &ty, BindingMode::default()); 439 self.infer_pat(*pat, &ty, BindingMode::default());
416 } 440 }
417 self.return_ty = self.make_ty(&data.ret_type); 441 let return_ty = self.make_ty(&data.ret_type);
442 self.return_ty = self.insert_vars_for_impl_trait(return_ty);
418 } 443 }
419 444
420 fn infer_body(&mut self) { 445 fn infer_body(&mut self) {
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index 2e3cdd53a..924ad3e81 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -613,6 +613,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
613 continue; 613 continue;
614 } 614 }
615 615
616 let param_ty = self.insert_vars_for_impl_trait(param_ty);
616 let param_ty = self.normalize_associated_types_in(param_ty); 617 let param_ty = self.normalize_associated_types_in(param_ty);
617 self.infer_expr_coerce(arg, &Expectation::has_type(param_ty.clone())); 618 self.infer_expr_coerce(arg, &Expectation::has_type(param_ty.clone()));
618 } 619 }
diff --git a/crates/ra_hir_ty/src/marks.rs b/crates/ra_hir_ty/src/marks.rs
index 0f754eb9c..fe74acf11 100644
--- a/crates/ra_hir_ty/src/marks.rs
+++ b/crates/ra_hir_ty/src/marks.rs
@@ -6,4 +6,5 @@ test_utils::marks!(
6 type_var_resolves_to_int_var 6 type_var_resolves_to_int_var
7 match_ergonomics_ref 7 match_ergonomics_ref
8 coerce_merge_fail_fallback 8 coerce_merge_fail_fallback
9 insert_vars_for_impl_trait
9); 10);
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index 6139adb72..802937cb0 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -1,7 +1,10 @@
1use super::{infer, type_at, type_at_pos};
2use crate::test_db::TestDB;
3use insta::assert_snapshot; 1use insta::assert_snapshot;
2
4use ra_db::fixture::WithFixture; 3use ra_db::fixture::WithFixture;
4use test_utils::covers;
5
6use super::{infer, infer_with_mismatches, type_at, type_at_pos};
7use crate::test_db::TestDB;
5 8
6#[test] 9#[test]
7fn infer_await() { 10fn infer_await() {
@@ -1486,3 +1489,61 @@ fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> {
1486 // this is a legitimate cycle 1489 // this is a legitimate cycle
1487 assert_eq!(t, "{unknown}"); 1490 assert_eq!(t, "{unknown}");
1488} 1491}
1492
1493#[test]
1494fn unify_impl_trait() {
1495 covers!(insert_vars_for_impl_trait);
1496 assert_snapshot!(
1497 infer_with_mismatches(r#"
1498trait Trait<T> {}
1499
1500fn foo(x: impl Trait<u32>) { loop {} }
1501fn bar<T>(x: impl Trait<T>) -> T { loop {} }
1502
1503struct S<T>(T);
1504impl<T> Trait<T> for S<T> {}
1505
1506fn default<T>() -> T { loop {} }
1507
1508fn test() -> impl Trait<i32> {
1509 let s1 = S(default());
1510 foo(s1);
1511 let x: i32 = bar(S(default()));
1512 S(default())
1513}
1514"#, true),
1515 @r###"
1516 [27; 28) 'x': impl Trait<u32>
1517 [47; 58) '{ loop {} }': ()
1518 [49; 56) 'loop {}': !
1519 [54; 56) '{}': ()
1520 [69; 70) 'x': impl Trait<T>
1521 [92; 103) '{ loop {} }': T
1522 [94; 101) 'loop {}': !
1523 [99; 101) '{}': ()
1524 [172; 183) '{ loop {} }': T
1525 [174; 181) 'loop {}': !
1526 [179; 181) '{}': ()
1527 [214; 310) '{ ...t()) }': S<i32>
1528 [224; 226) 's1': S<u32>
1529 [229; 230) 'S': S<u32>(T) -> S<T>
1530 [229; 241) 'S(default())': S<u32>
1531 [231; 238) 'default': fn default<u32>() -> T
1532 [231; 240) 'default()': u32
1533 [247; 250) 'foo': fn foo(impl Trait<u32>) -> ()
1534 [247; 254) 'foo(s1)': ()
1535 [251; 253) 's1': S<u32>
1536 [264; 265) 'x': i32
1537 [273; 276) 'bar': fn bar<i32>(impl Trait<T>) -> T
1538 [273; 290) 'bar(S(...lt()))': i32
1539 [277; 278) 'S': S<i32>(T) -> S<T>
1540 [277; 289) 'S(default())': S<i32>
1541 [279; 286) 'default': fn default<i32>() -> T
1542 [279; 288) 'default()': i32
1543 [296; 297) 'S': S<i32>(T) -> S<T>
1544 [296; 308) 'S(default())': S<i32>
1545 [298; 305) 'default': fn default<i32>() -> T
1546 [298; 307) 'default()': i32
1547 "###
1548 );
1549}
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs
index f06191963..09f0a2d98 100644
--- a/crates/ra_parser/src/grammar/expressions/atom.rs
+++ b/crates/ra_parser/src/grammar/expressions/atom.rs
@@ -248,7 +248,12 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker {
248 p.error("expected `{`"); 248 p.error("expected `{`");
249 } 249 }
250 } 250 }
251 expr(p); 251
252 if p.at_ts(EXPR_FIRST) {
253 expr(p);
254 } else {
255 p.error("expected expression");
256 }
252 m.complete(p, LAMBDA_EXPR) 257 m.complete(p, LAMBDA_EXPR)
253} 258}
254 259
diff --git a/crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.rs b/crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.rs
new file mode 100644
index 000000000..a2f74bd87
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.rs
@@ -0,0 +1,5 @@
1fn foo() -> i32 {
2 [1, 2, 3].iter()
3 .map(|it|)
4 .max::<i32>();
5}
diff --git a/crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.txt b/crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.txt
new file mode 100644
index 000000000..d1544634c
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.txt
@@ -0,0 +1,83 @@
1SOURCE_FILE@[0; 83)
2 FN_DEF@[0; 82)
3 FN_KW@[0; 2) "fn"
4 WHITESPACE@[2; 3) " "
5 NAME@[3; 6)
6 IDENT@[3; 6) "foo"
7 PARAM_LIST@[6; 8)
8 L_PAREN@[6; 7) "("
9 R_PAREN@[7; 8) ")"
10 WHITESPACE@[8; 9) " "
11 RET_TYPE@[9; 15)
12 THIN_ARROW@[9; 11) "->"
13 WHITESPACE@[11; 12) " "
14 PATH_TYPE@[12; 15)
15 PATH@[12; 15)
16 PATH_SEGMENT@[12; 15)
17 NAME_REF@[12; 15)
18 IDENT@[12; 15) "i32"
19 WHITESPACE@[15; 16) " "
20 BLOCK_EXPR@[16; 82)
21 BLOCK@[16; 82)
22 L_CURLY@[16; 17) "{"
23 WHITESPACE@[17; 22) "\n "
24 EXPR_STMT@[22; 80)
25 METHOD_CALL_EXPR@[22; 79)
26 METHOD_CALL_EXPR@[22; 57)
27 METHOD_CALL_EXPR@[22; 38)
28 ARRAY_EXPR@[22; 31)
29 L_BRACK@[22; 23) "["
30 LITERAL@[23; 24)
31 INT_NUMBER@[23; 24) "1"
32 COMMA@[24; 25) ","
33 WHITESPACE@[25; 26) " "
34 LITERAL@[26; 27)
35 INT_NUMBER@[26; 27) "2"
36 COMMA@[27; 28) ","
37 WHITESPACE@[28; 29) " "
38 LITERAL@[29; 30)
39 INT_NUMBER@[29; 30) "3"
40 R_BRACK@[30; 31) "]"
41 DOT@[31; 32) "."
42 NAME_REF@[32; 36)
43 IDENT@[32; 36) "iter"
44 ARG_LIST@[36; 38)
45 L_PAREN@[36; 37) "("
46 R_PAREN@[37; 38) ")"
47 WHITESPACE@[38; 47) "\n "
48 DOT@[47; 48) "."
49 NAME_REF@[48; 51)
50 IDENT@[48; 51) "map"
51 ARG_LIST@[51; 57)
52 L_PAREN@[51; 52) "("
53 LAMBDA_EXPR@[52; 56)
54 PARAM_LIST@[52; 56)
55 PIPE@[52; 53) "|"
56 PARAM@[53; 55)
57 BIND_PAT@[53; 55)
58 NAME@[53; 55)
59 IDENT@[53; 55) "it"
60 PIPE@[55; 56) "|"
61 R_PAREN@[56; 57) ")"
62 WHITESPACE@[57; 66) "\n "
63 DOT@[66; 67) "."
64 NAME_REF@[67; 70)
65 IDENT@[67; 70) "max"
66 TYPE_ARG_LIST@[70; 77)
67 COLONCOLON@[70; 72) "::"
68 L_ANGLE@[72; 73) "<"
69 TYPE_ARG@[73; 76)
70 PATH_TYPE@[73; 76)
71 PATH@[73; 76)
72 PATH_SEGMENT@[73; 76)
73 NAME_REF@[73; 76)
74 IDENT@[73; 76) "i32"
75 R_ANGLE@[76; 77) ">"
76 ARG_LIST@[77; 79)
77 L_PAREN@[77; 78) "("
78 R_PAREN@[78; 79) ")"
79 SEMI@[79; 80) ";"
80 WHITESPACE@[80; 81) "\n"
81 R_CURLY@[81; 82) "}"
82 WHITESPACE@[82; 83) "\n"
83error 56: expected expression
diff --git a/editors/code/package.json b/editors/code/package.json
index df8e9eecb..f7ab2c2f3 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -219,7 +219,7 @@
219 }, 219 },
220 "rust-analyzer.useClientWatching": { 220 "rust-analyzer.useClientWatching": {
221 "type": "boolean", 221 "type": "boolean",
222 "default": false, 222 "default": true,
223 "description": "client provided file watching instead of notify watching." 223 "description": "client provided file watching instead of notify watching."
224 }, 224 },
225 "rust-analyzer.cargo-watch.arguments": { 225 "rust-analyzer.cargo-watch.arguments": {
@@ -529,7 +529,7 @@
529 }, 529 },
530 { 530 {
531 "id": "ralsp.type.lifetime", 531 "id": "ralsp.type.lifetime",
532 "description": "Color for `Self` param type", 532 "description": "Color for lifetimes parameters",
533 "defaults": { 533 "defaults": {
534 "dark": "#4EC9B0", 534 "dark": "#4EC9B0",
535 "light": "#267F99", 535 "light": "#267F99",
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts
index a6e0f6454..e131f09df 100644
--- a/editors/code/src/config.ts
+++ b/editors/code/src/config.ts
@@ -31,7 +31,7 @@ export class Config {
31 public displayInlayHints = true; 31 public displayInlayHints = true;
32 public maxInlayHintLength: null | number = null; 32 public maxInlayHintLength: null | number = null;
33 public excludeGlobs = []; 33 public excludeGlobs = [];
34 public useClientWatching = false; 34 public useClientWatching = true;
35 public featureFlags = {}; 35 public featureFlags = {};
36 // for internal use 36 // for internal use
37 public withSysroot: null | boolean = null; 37 public withSysroot: null | boolean = null;
@@ -157,7 +157,7 @@ export class Config {
157 this.excludeGlobs = config.get('excludeGlobs') || []; 157 this.excludeGlobs = config.get('excludeGlobs') || [];
158 } 158 }
159 if (config.has('useClientWatching')) { 159 if (config.has('useClientWatching')) {
160 this.useClientWatching = config.get('useClientWatching') || false; 160 this.useClientWatching = config.get('useClientWatching') || true;
161 } 161 }
162 if (config.has('featureFlags')) { 162 if (config.has('featureFlags')) {
163 this.featureFlags = config.get('featureFlags') || {}; 163 this.featureFlags = config.get('featureFlags') || {};