diff options
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r-- | crates/ra_hir/src/ty/autoderef.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 14 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/unify.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 86 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 124 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits.rs | 17 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 8 |
7 files changed, 207 insertions, 46 deletions
diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs index 2535d4ae7..08f52a53b 100644 --- a/crates/ra_hir/src/ty/autoderef.rs +++ b/crates/ra_hir/src/ty/autoderef.rs | |||
@@ -7,7 +7,7 @@ use std::iter::successors; | |||
7 | 7 | ||
8 | use log::{info, warn}; | 8 | use log::{info, warn}; |
9 | 9 | ||
10 | use super::{traits::Solution, Canonical, Ty}; | 10 | use super::{traits::Solution, Canonical, Ty, TypeWalk}; |
11 | use crate::{HasGenericParams, HirDatabase, Name, Resolver}; | 11 | use crate::{HasGenericParams, HirDatabase, Name, Resolver}; |
12 | 12 | ||
13 | const AUTODEREF_RECURSION_LIMIT: usize = 10; | 13 | const AUTODEREF_RECURSION_LIMIT: usize = 10; |
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 812990426..ec3b7ffef 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -30,7 +30,7 @@ use super::{ | |||
30 | autoderef, lower, method_resolution, op, primitive, | 30 | autoderef, lower, method_resolution, op, primitive, |
31 | traits::{Guidance, Obligation, ProjectionPredicate, Solution}, | 31 | traits::{Guidance, Obligation, ProjectionPredicate, Solution}, |
32 | ApplicationTy, CallableDef, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, | 32 | ApplicationTy, CallableDef, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, |
33 | Ty, TypableDef, TypeCtor, | 33 | Ty, TypableDef, TypeCtor, TypeWalk, |
34 | }; | 34 | }; |
35 | use crate::{ | 35 | use crate::{ |
36 | adt::VariantDef, | 36 | adt::VariantDef, |
@@ -50,8 +50,8 @@ use crate::{ | |||
50 | }, | 50 | }, |
51 | ty::infer::diagnostics::InferenceDiagnostic, | 51 | ty::infer::diagnostics::InferenceDiagnostic, |
52 | type_ref::{Mutability, TypeRef}, | 52 | type_ref::{Mutability, TypeRef}, |
53 | AdtDef, ConstData, DefWithBody, FnData, Function, HirDatabase, ImplItem, ModuleDef, Name, Path, | 53 | AdtDef, ConstData, DefWithBody, FnData, Function, HasBody, HirDatabase, ImplItem, ModuleDef, |
54 | StructField, | 54 | Name, Path, StructField, |
55 | }; | 55 | }; |
56 | 56 | ||
57 | mod unify; | 57 | mod unify; |
@@ -749,7 +749,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
749 | let is_non_ref_pat = match &body[pat] { | 749 | let is_non_ref_pat = match &body[pat] { |
750 | Pat::Tuple(..) | 750 | Pat::Tuple(..) |
751 | | Pat::TupleStruct { .. } | 751 | | Pat::TupleStruct { .. } |
752 | | Pat::Struct { .. } | 752 | | Pat::Record { .. } |
753 | | Pat::Range { .. } | 753 | | Pat::Range { .. } |
754 | | Pat::Slice { .. } => true, | 754 | | Pat::Slice { .. } => true, |
755 | // FIXME: Path/Lit might actually evaluate to ref, but inference is unimplemented. | 755 | // FIXME: Path/Lit might actually evaluate to ref, but inference is unimplemented. |
@@ -806,10 +806,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
806 | let subty = self.infer_pat(*pat, expectation, default_bm); | 806 | let subty = self.infer_pat(*pat, expectation, default_bm); |
807 | Ty::apply_one(TypeCtor::Ref(*mutability), subty) | 807 | Ty::apply_one(TypeCtor::Ref(*mutability), subty) |
808 | } | 808 | } |
809 | Pat::TupleStruct { path: ref p, args: ref subpats } => { | 809 | Pat::TupleStruct { path: p, args: subpats } => { |
810 | self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm) | 810 | self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm) |
811 | } | 811 | } |
812 | Pat::Struct { path: ref p, args: ref fields } => { | 812 | Pat::Record { path: p, args: fields } => { |
813 | self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat) | 813 | self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat) |
814 | } | 814 | } |
815 | Pat::Path(path) => { | 815 | Pat::Path(path) => { |
@@ -817,7 +817,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
817 | let resolver = self.resolver.clone(); | 817 | let resolver = self.resolver.clone(); |
818 | self.infer_path_expr(&resolver, &path, pat.into()).unwrap_or(Ty::Unknown) | 818 | self.infer_path_expr(&resolver, &path, pat.into()).unwrap_or(Ty::Unknown) |
819 | } | 819 | } |
820 | Pat::Bind { mode, name: _name, subpat } => { | 820 | Pat::Bind { mode, name: _, subpat } => { |
821 | let mode = if mode == &BindingAnnotation::Unannotated { | 821 | let mode = if mode == &BindingAnnotation::Unannotated { |
822 | default_bm | 822 | default_bm |
823 | } else { | 823 | } else { |
diff --git a/crates/ra_hir/src/ty/infer/unify.rs b/crates/ra_hir/src/ty/infer/unify.rs index e7e8825d1..9a0d2d8f9 100644 --- a/crates/ra_hir/src/ty/infer/unify.rs +++ b/crates/ra_hir/src/ty/infer/unify.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | use super::{InferenceContext, Obligation}; | 3 | use super::{InferenceContext, Obligation}; |
4 | use crate::db::HirDatabase; | 4 | use crate::db::HirDatabase; |
5 | use crate::ty::{ | 5 | use crate::ty::{ |
6 | Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, TraitRef, Ty, | 6 | Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, TraitRef, Ty, TypeWalk, |
7 | }; | 7 | }; |
8 | 8 | ||
9 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 9 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { |
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 47d161277..f6f0137cf 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -8,7 +8,10 @@ | |||
8 | use std::iter; | 8 | use std::iter; |
9 | use std::sync::Arc; | 9 | use std::sync::Arc; |
10 | 10 | ||
11 | use super::{FnSig, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor}; | 11 | use super::{ |
12 | FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | ||
13 | TypeWalk, | ||
14 | }; | ||
12 | use crate::{ | 15 | use crate::{ |
13 | adt::VariantDef, | 16 | adt::VariantDef, |
14 | generics::HasGenericParams, | 17 | generics::HasGenericParams, |
@@ -62,7 +65,9 @@ impl Ty { | |||
62 | let self_ty = Ty::Bound(0); | 65 | let self_ty = Ty::Bound(0); |
63 | let predicates = bounds | 66 | let predicates = bounds |
64 | .iter() | 67 | .iter() |
65 | .map(|b| GenericPredicate::from_type_bound(db, resolver, b, self_ty.clone())) | 68 | .flat_map(|b| { |
69 | GenericPredicate::from_type_bound(db, resolver, b, self_ty.clone()) | ||
70 | }) | ||
66 | .collect::<Vec<_>>(); | 71 | .collect::<Vec<_>>(); |
67 | Ty::Dyn(predicates.into()) | 72 | Ty::Dyn(predicates.into()) |
68 | } | 73 | } |
@@ -70,7 +75,9 @@ impl Ty { | |||
70 | let self_ty = Ty::Bound(0); | 75 | let self_ty = Ty::Bound(0); |
71 | let predicates = bounds | 76 | let predicates = bounds |
72 | .iter() | 77 | .iter() |
73 | .map(|b| GenericPredicate::from_type_bound(db, resolver, b, self_ty.clone())) | 78 | .flat_map(|b| { |
79 | GenericPredicate::from_type_bound(db, resolver, b, self_ty.clone()) | ||
80 | }) | ||
74 | .collect::<Vec<_>>(); | 81 | .collect::<Vec<_>>(); |
75 | Ty::Opaque(predicates.into()) | 82 | Ty::Opaque(predicates.into()) |
76 | } | 83 | } |
@@ -326,15 +333,6 @@ impl TraitRef { | |||
326 | TraitRef { trait_, substs } | 333 | TraitRef { trait_, substs } |
327 | } | 334 | } |
328 | 335 | ||
329 | pub(crate) fn from_where_predicate( | ||
330 | db: &impl HirDatabase, | ||
331 | resolver: &Resolver, | ||
332 | pred: &WherePredicate, | ||
333 | ) -> Option<TraitRef> { | ||
334 | let self_ty = Ty::from_hir(db, resolver, &pred.type_ref); | ||
335 | TraitRef::from_type_bound(db, resolver, &pred.bound, self_ty) | ||
336 | } | ||
337 | |||
338 | pub(crate) fn from_type_bound( | 336 | pub(crate) fn from_type_bound( |
339 | db: &impl HirDatabase, | 337 | db: &impl HirDatabase, |
340 | resolver: &Resolver, | 338 | resolver: &Resolver, |
@@ -349,26 +347,58 @@ impl TraitRef { | |||
349 | } | 347 | } |
350 | 348 | ||
351 | impl GenericPredicate { | 349 | impl GenericPredicate { |
352 | pub(crate) fn from_where_predicate( | 350 | pub(crate) fn from_where_predicate<'a>( |
353 | db: &impl HirDatabase, | 351 | db: &'a impl HirDatabase, |
354 | resolver: &Resolver, | 352 | resolver: &'a Resolver, |
355 | where_predicate: &WherePredicate, | 353 | where_predicate: &'a WherePredicate, |
356 | ) -> GenericPredicate { | 354 | ) -> impl Iterator<Item = GenericPredicate> + 'a { |
357 | TraitRef::from_where_predicate(db, &resolver, where_predicate) | 355 | let self_ty = Ty::from_hir(db, resolver, &where_predicate.type_ref); |
358 | .map_or(GenericPredicate::Error, GenericPredicate::Implemented) | 356 | GenericPredicate::from_type_bound(db, resolver, &where_predicate.bound, self_ty) |
359 | } | 357 | } |
360 | 358 | ||
361 | pub(crate) fn from_type_bound( | 359 | pub(crate) fn from_type_bound<'a>( |
362 | db: &impl HirDatabase, | 360 | db: &'a impl HirDatabase, |
363 | resolver: &Resolver, | 361 | resolver: &'a Resolver, |
364 | bound: &TypeBound, | 362 | bound: &'a TypeBound, |
365 | self_ty: Ty, | 363 | self_ty: Ty, |
366 | ) -> GenericPredicate { | 364 | ) -> impl Iterator<Item = GenericPredicate> + 'a { |
367 | TraitRef::from_type_bound(db, &resolver, bound, self_ty) | 365 | let trait_ref = TraitRef::from_type_bound(db, &resolver, bound, self_ty); |
368 | .map_or(GenericPredicate::Error, GenericPredicate::Implemented) | 366 | iter::once(trait_ref.clone().map_or(GenericPredicate::Error, GenericPredicate::Implemented)) |
367 | .chain( | ||
368 | trait_ref.into_iter().flat_map(move |tr| { | ||
369 | assoc_type_bindings_from_type_bound(db, resolver, bound, tr) | ||
370 | }), | ||
371 | ) | ||
369 | } | 372 | } |
370 | } | 373 | } |
371 | 374 | ||
375 | fn assoc_type_bindings_from_type_bound<'a>( | ||
376 | db: &'a impl HirDatabase, | ||
377 | resolver: &'a Resolver, | ||
378 | bound: &'a TypeBound, | ||
379 | trait_ref: TraitRef, | ||
380 | ) -> impl Iterator<Item = GenericPredicate> + 'a { | ||
381 | let last_segment = match bound { | ||
382 | TypeBound::Path(path) => path.segments.last(), | ||
383 | TypeBound::Error => None, | ||
384 | }; | ||
385 | last_segment | ||
386 | .into_iter() | ||
387 | .flat_map(|segment| segment.args_and_bindings.iter()) | ||
388 | .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) | ||
389 | .map(move |(name, type_ref)| { | ||
390 | let associated_ty = match trait_ref.trait_.associated_type_by_name(db, name.clone()) { | ||
391 | None => return GenericPredicate::Error, | ||
392 | Some(t) => t, | ||
393 | }; | ||
394 | let projection_ty = | ||
395 | ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() }; | ||
396 | let ty = Ty::from_hir(db, resolver, type_ref); | ||
397 | let projection_predicate = ProjectionPredicate { projection_ty, ty }; | ||
398 | GenericPredicate::Projection(projection_predicate) | ||
399 | }) | ||
400 | } | ||
401 | |||
372 | /// Build the declared type of an item. This depends on the namespace; e.g. for | 402 | /// Build the declared type of an item. This depends on the namespace; e.g. for |
373 | /// `struct Foo(usize)`, we have two types: The type of the struct itself, and | 403 | /// `struct Foo(usize)`, we have two types: The type of the struct itself, and |
374 | /// the constructor function `(usize) -> Foo` which lives in the values | 404 | /// the constructor function `(usize) -> Foo` which lives in the values |
@@ -425,7 +455,7 @@ pub(crate) fn trait_env( | |||
425 | ) -> Arc<super::TraitEnvironment> { | 455 | ) -> Arc<super::TraitEnvironment> { |
426 | let predicates = resolver | 456 | let predicates = resolver |
427 | .where_predicates_in_scope() | 457 | .where_predicates_in_scope() |
428 | .map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) | 458 | .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) |
429 | .collect::<Vec<_>>(); | 459 | .collect::<Vec<_>>(); |
430 | 460 | ||
431 | Arc::new(super::TraitEnvironment { predicates }) | 461 | Arc::new(super::TraitEnvironment { predicates }) |
@@ -439,7 +469,7 @@ pub(crate) fn generic_predicates_query( | |||
439 | let resolver = def.resolver(db); | 469 | let resolver = def.resolver(db); |
440 | let predicates = resolver | 470 | let predicates = resolver |
441 | .where_predicates_in_scope() | 471 | .where_predicates_in_scope() |
442 | .map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) | 472 | .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) |
443 | .collect::<Vec<_>>(); | 473 | .collect::<Vec<_>>(); |
444 | predicates.into() | 474 | predicates.into() |
445 | } | 475 | } |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index b034fd59e..d92d4659b 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -2793,6 +2793,10 @@ fn main() { | |||
2793 | } | 2793 | } |
2794 | "#), | 2794 | "#), |
2795 | @r###" | 2795 | @r###" |
2796 | ![0; 17) '{Foo(v...,2,])}': Foo | ||
2797 | ![1; 4) 'Foo': Foo({unknown}) -> Foo | ||
2798 | ![1; 16) 'Foo(vec![1,2,])': Foo | ||
2799 | ![5; 15) 'vec![1,2,]': {unknown} | ||
2796 | [156; 182) '{ ...,2); }': () | 2800 | [156; 182) '{ ...,2); }': () |
2797 | [166; 167) 'x': Foo | 2801 | [166; 167) 'x': Foo |
2798 | "### | 2802 | "### |
@@ -3548,6 +3552,97 @@ fn test() { | |||
3548 | ); | 3552 | ); |
3549 | } | 3553 | } |
3550 | 3554 | ||
3555 | #[test] | ||
3556 | fn assoc_type_bindings() { | ||
3557 | assert_snapshot!( | ||
3558 | infer(r#" | ||
3559 | trait Trait { | ||
3560 | type Type; | ||
3561 | } | ||
3562 | |||
3563 | fn get<T: Trait>(t: T) -> <T as Trait>::Type {} | ||
3564 | fn get2<U, T: Trait<Type = U>>(t: T) -> U {} | ||
3565 | fn set<T: Trait<Type = u64>>(t: T) -> T {t} | ||
3566 | |||
3567 | struct S<T>; | ||
3568 | impl<T> Trait for S<T> { type Type = T; } | ||
3569 | |||
3570 | fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) { | ||
3571 | get(x); | ||
3572 | get2(x); | ||
3573 | get(y); | ||
3574 | get2(y); | ||
3575 | get(set(S)); | ||
3576 | get2(set(S)); | ||
3577 | get2(S::<str>); | ||
3578 | } | ||
3579 | "#), | ||
3580 | @r###" | ||
3581 | [50; 51) 't': T | ||
3582 | [78; 80) '{}': () | ||
3583 | [112; 113) 't': T | ||
3584 | [123; 125) '{}': () | ||
3585 | [155; 156) 't': T | ||
3586 | [166; 169) '{t}': T | ||
3587 | [167; 168) 't': T | ||
3588 | [257; 258) 'x': T | ||
3589 | [263; 264) 'y': impl Trait<Type = i64> | ||
3590 | [290; 398) '{ ...r>); }': () | ||
3591 | [296; 299) 'get': fn get<T>(T) -> <T as Trait>::Type | ||
3592 | [296; 302) 'get(x)': {unknown} | ||
3593 | [300; 301) 'x': T | ||
3594 | [308; 312) 'get2': fn get2<{unknown}, S<{unknown}>>(T) -> U | ||
3595 | [308; 315) 'get2(x)': {unknown} | ||
3596 | [313; 314) 'x': T | ||
3597 | [321; 324) 'get': fn get<impl Trait<Type = i64>>(T) -> <T as Trait>::Type | ||
3598 | [321; 327) 'get(y)': {unknown} | ||
3599 | [325; 326) 'y': impl Trait<Type = i64> | ||
3600 | [333; 337) 'get2': fn get2<{unknown}, S<{unknown}>>(T) -> U | ||
3601 | [333; 340) 'get2(y)': {unknown} | ||
3602 | [338; 339) 'y': impl Trait<Type = i64> | ||
3603 | [346; 349) 'get': fn get<S<u64>>(T) -> <T as Trait>::Type | ||
3604 | [346; 357) 'get(set(S))': u64 | ||
3605 | [350; 353) 'set': fn set<S<u64>>(T) -> T | ||
3606 | [350; 356) 'set(S)': S<u64> | ||
3607 | [354; 355) 'S': S<u64> | ||
3608 | [363; 367) 'get2': fn get2<u64, S<u64>>(T) -> U | ||
3609 | [363; 375) 'get2(set(S))': u64 | ||
3610 | [368; 371) 'set': fn set<S<u64>>(T) -> T | ||
3611 | [368; 374) 'set(S)': S<u64> | ||
3612 | [372; 373) 'S': S<u64> | ||
3613 | [381; 385) 'get2': fn get2<str, S<str>>(T) -> U | ||
3614 | [381; 395) 'get2(S::<str>)': str | ||
3615 | [386; 394) 'S::<str>': S<str> | ||
3616 | "### | ||
3617 | ); | ||
3618 | } | ||
3619 | |||
3620 | #[test] | ||
3621 | fn projection_eq_within_chalk() { | ||
3622 | // std::env::set_var("CHALK_DEBUG", "1"); | ||
3623 | assert_snapshot!( | ||
3624 | infer(r#" | ||
3625 | trait Trait1 { | ||
3626 | type Type; | ||
3627 | } | ||
3628 | trait Trait2<T> { | ||
3629 | fn foo(self) -> T; | ||
3630 | } | ||
3631 | impl<T, U> Trait2<T> for U where U: Trait1<Type = T> {} | ||
3632 | |||
3633 | fn test<T: Trait1<Type = u32>>(x: T) { | ||
3634 | x.foo(); | ||
3635 | } | ||
3636 | "#), | ||
3637 | @r###" | ||
3638 | [62; 66) 'self': Self | ||
3639 | [164; 165) 'x': T | ||
3640 | [170; 186) '{ ...o(); }': () | ||
3641 | [176; 177) 'x': T | ||
3642 | [176; 183) 'x.foo()': {unknown} | ||
3643 | "### | ||
3644 | ); | ||
3645 | } | ||
3551 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { | 3646 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { |
3552 | let file = db.parse(pos.file_id).ok().unwrap(); | 3647 | let file = db.parse(pos.file_id).ok().unwrap(); |
3553 | let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); | 3648 | let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); |
@@ -3566,7 +3661,6 @@ fn infer(content: &str) -> String { | |||
3566 | let source_file = db.parse(file_id).ok().unwrap(); | 3661 | let source_file = db.parse(file_id).ok().unwrap(); |
3567 | 3662 | ||
3568 | let mut acc = String::new(); | 3663 | let mut acc = String::new(); |
3569 | // acc.push_str("\n"); | ||
3570 | 3664 | ||
3571 | let mut infer_def = |inference_result: Arc<InferenceResult>, | 3665 | let mut infer_def = |inference_result: Arc<InferenceResult>, |
3572 | body_source_map: Arc<BodySourceMap>| { | 3666 | body_source_map: Arc<BodySourceMap>| { |
@@ -3574,7 +3668,9 @@ fn infer(content: &str) -> String { | |||
3574 | 3668 | ||
3575 | for (pat, ty) in inference_result.type_of_pat.iter() { | 3669 | for (pat, ty) in inference_result.type_of_pat.iter() { |
3576 | let syntax_ptr = match body_source_map.pat_syntax(pat) { | 3670 | let syntax_ptr = match body_source_map.pat_syntax(pat) { |
3577 | Some(sp) => sp.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()), | 3671 | Some(sp) => { |
3672 | sp.map(|ast| ast.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr())) | ||
3673 | } | ||
3578 | None => continue, | 3674 | None => continue, |
3579 | }; | 3675 | }; |
3580 | types.push((syntax_ptr, ty)); | 3676 | types.push((syntax_ptr, ty)); |
@@ -3582,22 +3678,34 @@ fn infer(content: &str) -> String { | |||
3582 | 3678 | ||
3583 | for (expr, ty) in inference_result.type_of_expr.iter() { | 3679 | for (expr, ty) in inference_result.type_of_expr.iter() { |
3584 | let syntax_ptr = match body_source_map.expr_syntax(expr) { | 3680 | let syntax_ptr = match body_source_map.expr_syntax(expr) { |
3585 | Some(sp) => sp, | 3681 | Some(sp) => { |
3682 | sp.map(|ast| ast.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr())) | ||
3683 | } | ||
3586 | None => continue, | 3684 | None => continue, |
3587 | }; | 3685 | }; |
3588 | types.push((syntax_ptr, ty)); | 3686 | types.push((syntax_ptr, ty)); |
3589 | } | 3687 | } |
3590 | 3688 | ||
3591 | // sort ranges for consistency | 3689 | // sort ranges for consistency |
3592 | types.sort_by_key(|(ptr, _)| (ptr.range().start(), ptr.range().end())); | 3690 | types.sort_by_key(|(src_ptr, _)| (src_ptr.ast.range().start(), src_ptr.ast.range().end())); |
3593 | for (syntax_ptr, ty) in &types { | 3691 | for (src_ptr, ty) in &types { |
3594 | let node = syntax_ptr.to_node(source_file.syntax()); | 3692 | let node = src_ptr.ast.to_node(&src_ptr.file_syntax(&db)); |
3693 | |||
3595 | let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.clone()) { | 3694 | let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.clone()) { |
3596 | (self_param.self_kw_token().text_range(), "self".to_string()) | 3695 | (self_param.self_kw_token().text_range(), "self".to_string()) |
3597 | } else { | 3696 | } else { |
3598 | (syntax_ptr.range(), node.text().to_string().replace("\n", " ")) | 3697 | (src_ptr.ast.range(), node.text().to_string().replace("\n", " ")) |
3599 | }; | 3698 | }; |
3600 | write!(acc, "{} '{}': {}\n", range, ellipsize(text, 15), ty.display(&db)).unwrap(); | 3699 | let macro_prefix = if src_ptr.file_id != file_id.into() { "!" } else { "" }; |
3700 | write!( | ||
3701 | acc, | ||
3702 | "{}{} '{}': {}\n", | ||
3703 | macro_prefix, | ||
3704 | range, | ||
3705 | ellipsize(text, 15), | ||
3706 | ty.display(&db) | ||
3707 | ) | ||
3708 | .unwrap(); | ||
3601 | } | 3709 | } |
3602 | }; | 3710 | }; |
3603 | 3711 | ||
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs index b634f0b79..6e0271a96 100644 --- a/crates/ra_hir/src/ty/traits.rs +++ b/crates/ra_hir/src/ty/traits.rs | |||
@@ -8,7 +8,7 @@ use ra_db::salsa; | |||
8 | use ra_prof::profile; | 8 | use ra_prof::profile; |
9 | use rustc_hash::FxHashSet; | 9 | use rustc_hash::FxHashSet; |
10 | 10 | ||
11 | use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty}; | 11 | use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; |
12 | use crate::{db::HirDatabase, Crate, ImplBlock, Trait}; | 12 | use crate::{db::HirDatabase, Crate, ImplBlock, Trait}; |
13 | 13 | ||
14 | use self::chalk::{from_chalk, ToChalk}; | 14 | use self::chalk::{from_chalk, ToChalk}; |
@@ -124,6 +124,9 @@ impl Obligation { | |||
124 | pub fn from_predicate(predicate: GenericPredicate) -> Option<Obligation> { | 124 | pub fn from_predicate(predicate: GenericPredicate) -> Option<Obligation> { |
125 | match predicate { | 125 | match predicate { |
126 | GenericPredicate::Implemented(trait_ref) => Some(Obligation::Trait(trait_ref)), | 126 | GenericPredicate::Implemented(trait_ref) => Some(Obligation::Trait(trait_ref)), |
127 | GenericPredicate::Projection(projection_pred) => { | ||
128 | Some(Obligation::Projection(projection_pred)) | ||
129 | } | ||
127 | GenericPredicate::Error => None, | 130 | GenericPredicate::Error => None, |
128 | } | 131 | } |
129 | } | 132 | } |
@@ -135,6 +138,18 @@ pub struct ProjectionPredicate { | |||
135 | pub ty: Ty, | 138 | pub ty: Ty, |
136 | } | 139 | } |
137 | 140 | ||
141 | impl TypeWalk for ProjectionPredicate { | ||
142 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
143 | self.projection_ty.walk(f); | ||
144 | self.ty.walk(f); | ||
145 | } | ||
146 | |||
147 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | ||
148 | self.projection_ty.walk_mut(f); | ||
149 | self.ty.walk_mut(f); | ||
150 | } | ||
151 | } | ||
152 | |||
138 | /// Solve a trait goal using Chalk. | 153 | /// Solve a trait goal using Chalk. |
139 | pub(crate) fn trait_solve_query( | 154 | pub(crate) fn trait_solve_query( |
140 | db: &impl HirDatabase, | 155 | db: &impl HirDatabase, |
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 2ebc06135..c201c5e50 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs | |||
@@ -19,6 +19,7 @@ use crate::{ | |||
19 | ty::display::HirDisplay, | 19 | ty::display::HirDisplay, |
20 | ty::{ | 20 | ty::{ |
21 | ApplicationTy, CallableDef, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | 21 | ApplicationTy, CallableDef, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, |
22 | TypeWalk, | ||
22 | }, | 23 | }, |
23 | Crate, HasGenericParams, ImplBlock, ImplItem, Trait, TypeAlias, | 24 | Crate, HasGenericParams, ImplBlock, ImplItem, Trait, TypeAlias, |
24 | }; | 25 | }; |
@@ -211,6 +212,13 @@ impl ToChalk for GenericPredicate { | |||
211 | GenericPredicate::Implemented(trait_ref) => { | 212 | GenericPredicate::Implemented(trait_ref) => { |
212 | make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0) | 213 | make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0) |
213 | } | 214 | } |
215 | GenericPredicate::Projection(projection_pred) => make_binders( | ||
216 | chalk_ir::WhereClause::ProjectionEq(chalk_ir::ProjectionEq { | ||
217 | projection: projection_pred.projection_ty.to_chalk(db), | ||
218 | ty: projection_pred.ty.to_chalk(db), | ||
219 | }), | ||
220 | 0, | ||
221 | ), | ||
214 | GenericPredicate::Error => { | 222 | GenericPredicate::Error => { |
215 | let impossible_trait_ref = chalk_ir::TraitRef { | 223 | let impossible_trait_ref = chalk_ir::TraitRef { |
216 | trait_id: UNKNOWN_TRAIT, | 224 | trait_id: UNKNOWN_TRAIT, |