diff options
author | Florian Diebold <[email protected]> | 2019-06-15 17:20:59 +0100 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-06-15 17:21:23 +0100 |
commit | 3e78a6e3e0dbe5ad2ae712ec5c94a3792745f26c (patch) | |
tree | a6f46e5b38ab632474dd6f87734d9ddfa8b83757 /crates/ra_hir/src/ty/autoderef.rs | |
parent | ca5ed2307c6dd8396f58460652c77a6a63704e0b (diff) |
Somewhat handle variables in the derefed type, and add another test
Diffstat (limited to 'crates/ra_hir/src/ty/autoderef.rs')
-rw-r--r-- | crates/ra_hir/src/ty/autoderef.rs | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs index bee756d80..11f489489 100644 --- a/crates/ra_hir/src/ty/autoderef.rs +++ b/crates/ra_hir/src/ty/autoderef.rs | |||
@@ -5,7 +5,7 @@ | |||
5 | 5 | ||
6 | use std::iter::successors; | 6 | use std::iter::successors; |
7 | 7 | ||
8 | use log::info; | 8 | use log::{info, warn}; |
9 | 9 | ||
10 | use crate::{HirDatabase, Name, Resolver}; | 10 | use crate::{HirDatabase, Name, Resolver}; |
11 | use super::{traits::Solution, Ty, Canonical}; | 11 | use super::{traits::Solution, Ty, Canonical}; |
@@ -43,15 +43,13 @@ fn deref_by_trait( | |||
43 | let target = deref_trait.associated_type_by_name(db, Name::target())?; | 43 | let target = deref_trait.associated_type_by_name(db, Name::target())?; |
44 | 44 | ||
45 | // FIXME we should check that Deref has no type parameters, because we assume it below | 45 | // FIXME we should check that Deref has no type parameters, because we assume it below |
46 | |||
47 | // FIXME make the Canonical handling nicer | 46 | // FIXME make the Canonical handling nicer |
48 | // TODO shift inference variables in ty | ||
49 | 47 | ||
50 | let projection = super::traits::ProjectionPredicate { | 48 | let projection = super::traits::ProjectionPredicate { |
51 | ty: Ty::Bound(0), | 49 | ty: Ty::Bound(0), |
52 | projection_ty: super::ProjectionTy { | 50 | projection_ty: super::ProjectionTy { |
53 | associated_ty: target, | 51 | associated_ty: target, |
54 | parameters: vec![ty.value.clone()].into(), | 52 | parameters: vec![ty.value.clone().shift_bound_vars(1)].into(), |
55 | }, | 53 | }, |
56 | }; | 54 | }; |
57 | 55 | ||
@@ -61,10 +59,26 @@ fn deref_by_trait( | |||
61 | 59 | ||
62 | match &solution { | 60 | match &solution { |
63 | Solution::Unique(vars) => { | 61 | Solution::Unique(vars) => { |
62 | // FIXME: vars may contain solutions for any inference variables | ||
63 | // that happened to be inside ty. To correctly handle these, we | ||
64 | // would have to pass the solution up to the inference context, but | ||
65 | // that requires a larger refactoring (especially if the deref | ||
66 | // happens during method resolution). So for the moment, we just | ||
67 | // check that we're not in the situation we're we would actually | ||
68 | // need to handle the values of the additional variables, i.e. | ||
69 | // they're just being 'passed through'. In the 'standard' case where | ||
70 | // we have `impl<T> Deref for Foo<T> { Target = T }`, that should be | ||
71 | // the case. | ||
72 | for i in 1..vars.0.num_vars { | ||
73 | if vars.0.value[i] != Ty::Bound((i - 1) as u32) { | ||
74 | warn!("complex solution for derefing {:?}: {:?}, ignoring", ty, solution); | ||
75 | return None; | ||
76 | } | ||
77 | } | ||
64 | Some(Canonical { value: vars.0.value[0].clone(), num_vars: vars.0.num_vars }) | 78 | Some(Canonical { value: vars.0.value[0].clone(), num_vars: vars.0.num_vars }) |
65 | } | 79 | } |
66 | Solution::Ambig(_) => { | 80 | Solution::Ambig(_) => { |
67 | info!("Ambiguous solution for deref: {:?}", solution); | 81 | info!("Ambiguous solution for derefing {:?}: {:?}", ty, solution); |
68 | None | 82 | None |
69 | } | 83 | } |
70 | } | 84 | } |