diff options
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer.rs | 27 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/expr.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/marks.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/traits.rs | 65 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/expressions/atom.rs | 7 | ||||
-rw-r--r-- | crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.rs | 5 | ||||
-rw-r--r-- | crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.txt | 83 | ||||
-rw-r--r-- | editors/code/package.json | 4 | ||||
-rw-r--r-- | editors/code/src/config.ts | 4 |
10 files changed, 190 insertions, 9 deletions
@@ -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::{ | |||
32 | use hir_expand::{diagnostics::DiagnosticSink, name::name}; | 32 | use hir_expand::{diagnostics::DiagnosticSink, name::name}; |
33 | use ra_arena::map::ArenaMap; | 33 | use ra_arena::map::ArenaMap; |
34 | use ra_prof::profile; | 34 | use ra_prof::profile; |
35 | use test_utils::tested_by; | ||
35 | 36 | ||
36 | use super::{ | 37 | use 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 @@ | |||
1 | use super::{infer, type_at, type_at_pos}; | ||
2 | use crate::test_db::TestDB; | ||
3 | use insta::assert_snapshot; | 1 | use insta::assert_snapshot; |
2 | |||
4 | use ra_db::fixture::WithFixture; | 3 | use ra_db::fixture::WithFixture; |
4 | use test_utils::covers; | ||
5 | |||
6 | use super::{infer, infer_with_mismatches, type_at, type_at_pos}; | ||
7 | use crate::test_db::TestDB; | ||
5 | 8 | ||
6 | #[test] | 9 | #[test] |
7 | fn infer_await() { | 10 | fn 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] | ||
1494 | fn unify_impl_trait() { | ||
1495 | covers!(insert_vars_for_impl_trait); | ||
1496 | assert_snapshot!( | ||
1497 | infer_with_mismatches(r#" | ||
1498 | trait Trait<T> {} | ||
1499 | |||
1500 | fn foo(x: impl Trait<u32>) { loop {} } | ||
1501 | fn bar<T>(x: impl Trait<T>) -> T { loop {} } | ||
1502 | |||
1503 | struct S<T>(T); | ||
1504 | impl<T> Trait<T> for S<T> {} | ||
1505 | |||
1506 | fn default<T>() -> T { loop {} } | ||
1507 | |||
1508 | fn 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 @@ | |||
1 | fn 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 @@ | |||
1 | SOURCE_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" | ||
83 | error 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') || {}; |