aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-12-15 17:56:38 +0000
committerFlorian Diebold <[email protected]>2019-12-15 17:56:38 +0000
commit6e1c2d0df89a390be33c81b6e03a5ad352763593 (patch)
treef3ba344e185e17e6e62ce650462fd63af9eddd26
parentac961b261458bfeb23f7d4e896d5f957b0854a3a (diff)
Handle impl Trait more correctly
When calling a function, argument-position impl Trait is transparent; same for return-position impl Trait when inside the function. So in these cases, we need to represent that type not by `Ty::Opaque`, but by a type variable that can be unified with whatever flows into there.
-rw-r--r--crates/ra_hir_ty/src/infer.rs25
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs1
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs31
3 files changed, 56 insertions, 1 deletions
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index af42854cc..1aa1330a6 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -274,6 +274,28 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
274 self.normalize_associated_types_in(ty) 274 self.normalize_associated_types_in(ty)
275 } 275 }
276 276
277 /// Replaces `impl Trait` in `ty` by type variables and obligations for
278 /// those variables. This is done for function arguments when calling a
279 /// function, and for return types when inside the function body, i.e. in
280 /// the cases where the `impl Trait` is 'transparent'. In other cases, `impl
281 /// Trait` is represented by `Ty::Opaque`.
282 fn insert_vars_for_impl_trait(&mut self, ty: Ty) -> Ty {
283 ty.fold(&mut |ty| match ty {
284 Ty::Opaque(preds) => {
285 let var = self.table.new_type_var();
286 let var_subst = Substs::builder(1).push(var.clone()).build();
287 self.obligations.extend(
288 preds
289 .iter()
290 .map(|pred| pred.clone().subst_bound_vars(&var_subst))
291 .filter_map(Obligation::from_predicate),
292 );
293 var
294 }
295 _ => ty,
296 })
297 }
298
277 /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. 299 /// 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 { 300 fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
279 match ty { 301 match ty {
@@ -414,7 +436,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
414 436
415 self.infer_pat(*pat, &ty, BindingMode::default()); 437 self.infer_pat(*pat, &ty, BindingMode::default());
416 } 438 }
417 self.return_ty = self.make_ty(&data.ret_type); 439 let return_ty = self.make_ty(&data.ret_type);
440 self.return_ty = self.insert_vars_for_impl_trait(return_ty);
418 } 441 }
419 442
420 fn infer_body(&mut self) { 443 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/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index a926d01e5..d8673c90d 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -1509,6 +1509,37 @@ fn test() -> impl Trait<i32> {
1509} 1509}
1510"#, true), 1510"#, true),
1511 @r###" 1511 @r###"
1512 [27; 28) 'x': impl Trait<u32>
1513 [47; 58) '{ loop {} }': ()
1514 [49; 56) 'loop {}': !
1515 [54; 56) '{}': ()
1516 [69; 70) 'x': impl Trait<T>
1517 [92; 103) '{ loop {} }': T
1518 [94; 101) 'loop {}': !
1519 [99; 101) '{}': ()
1520 [172; 183) '{ loop {} }': T
1521 [174; 181) 'loop {}': !
1522 [179; 181) '{}': ()
1523 [214; 310) '{ ...t()) }': S<i32>
1524 [224; 226) 's1': S<u32>
1525 [229; 230) 'S': S<u32>(T) -> S<T>
1526 [229; 241) 'S(default())': S<u32>
1527 [231; 238) 'default': fn default<u32>() -> T
1528 [231; 240) 'default()': u32
1529 [247; 250) 'foo': fn foo(impl Trait<u32>) -> ()
1530 [247; 254) 'foo(s1)': ()
1531 [251; 253) 's1': S<u32>
1532 [264; 265) 'x': i32
1533 [273; 276) 'bar': fn bar<i32>(impl Trait<T>) -> T
1534 [273; 290) 'bar(S(...lt()))': i32
1535 [277; 278) 'S': S<i32>(T) -> S<T>
1536 [277; 289) 'S(default())': S<i32>
1537 [279; 286) 'default': fn default<i32>() -> T
1538 [279; 288) 'default()': i32
1539 [296; 297) 'S': S<i32>(T) -> S<T>
1540 [296; 308) 'S(default())': S<i32>
1541 [298; 305) 'default': fn default<i32>() -> T
1542 [298; 307) 'default()': i32
1512 "### 1543 "###
1513 ); 1544 );
1514} 1545}