diff options
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r-- | crates/ra_hir_ty/Cargo.toml | 9 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/method_resolution.rs | 71 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests.rs | 11 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/coercion.rs | 55 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/traits.rs | 132 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits.rs | 15 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/builtin.rs | 201 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk.rs | 77 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk/interner.rs | 15 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk/mapping.rs | 62 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk/tls.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/utils.rs | 32 |
12 files changed, 345 insertions, 337 deletions
diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml index ce257dc0b..90368220b 100644 --- a/crates/ra_hir_ty/Cargo.toml +++ b/crates/ra_hir_ty/Cargo.toml | |||
@@ -27,9 +27,14 @@ test_utils = { path = "../test_utils" } | |||
27 | 27 | ||
28 | scoped-tls = "1" | 28 | scoped-tls = "1" |
29 | 29 | ||
30 | chalk-solve = { version = "0.15.0" } | 30 | chalk-solve = { version = "0.17.0" } |
31 | chalk-ir = { version = "0.15.0" } | 31 | chalk-ir = { version = "0.17.0" } |
32 | chalk-recursive = { version = "0.17.0" } | ||
32 | 33 | ||
33 | [dev-dependencies] | 34 | [dev-dependencies] |
34 | insta = "0.16.0" | 35 | insta = "0.16.0" |
35 | expect = { path = "../expect" } | 36 | expect = { path = "../expect" } |
37 | |||
38 | tracing = "0.1" | ||
39 | tracing-subscriber = { version = "0.2", default-features = false, features = ["env-filter", "registry"] } | ||
40 | tracing-tree = { version = "0.1.3" } | ||
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index a45febbf7..fb4b30a13 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs | |||
@@ -6,8 +6,10 @@ use std::{iter, sync::Arc}; | |||
6 | 6 | ||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use hir_def::{ | 8 | use hir_def::{ |
9 | lang_item::LangItemTarget, type_ref::Mutability, AssocContainerId, AssocItemId, FunctionId, | 9 | builtin_type::{IntBitness, Signedness}, |
10 | HasModule, ImplId, Lookup, TraitId, | 10 | lang_item::LangItemTarget, |
11 | type_ref::Mutability, | ||
12 | AssocContainerId, AssocItemId, FunctionId, HasModule, ImplId, Lookup, TraitId, | ||
11 | }; | 13 | }; |
12 | use hir_expand::name::Name; | 14 | use hir_expand::name::Name; |
13 | use ra_db::CrateId; | 15 | use ra_db::CrateId; |
@@ -16,9 +18,12 @@ use rustc_hash::{FxHashMap, FxHashSet}; | |||
16 | 18 | ||
17 | use super::Substs; | 19 | use super::Substs; |
18 | use crate::{ | 20 | use crate::{ |
19 | autoderef, db::HirDatabase, primitive::FloatBitness, utils::all_super_traits, ApplicationTy, | 21 | autoderef, |
20 | Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TyKind, TypeCtor, | 22 | db::HirDatabase, |
21 | TypeWalk, | 23 | primitive::{FloatBitness, FloatTy, IntTy}, |
24 | utils::all_super_traits, | ||
25 | ApplicationTy, Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TyKind, | ||
26 | TypeCtor, TypeWalk, | ||
22 | }; | 27 | }; |
23 | 28 | ||
24 | /// This is used as a key for indexing impls. | 29 | /// This is used as a key for indexing impls. |
@@ -39,6 +44,62 @@ impl TyFingerprint { | |||
39 | } | 44 | } |
40 | } | 45 | } |
41 | 46 | ||
47 | pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [ | ||
48 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
49 | signedness: Signedness::Unsigned, | ||
50 | bitness: IntBitness::X8, | ||
51 | })), | ||
52 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
53 | signedness: Signedness::Unsigned, | ||
54 | bitness: IntBitness::X16, | ||
55 | })), | ||
56 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
57 | signedness: Signedness::Unsigned, | ||
58 | bitness: IntBitness::X32, | ||
59 | })), | ||
60 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
61 | signedness: Signedness::Unsigned, | ||
62 | bitness: IntBitness::X64, | ||
63 | })), | ||
64 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
65 | signedness: Signedness::Unsigned, | ||
66 | bitness: IntBitness::X128, | ||
67 | })), | ||
68 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
69 | signedness: Signedness::Unsigned, | ||
70 | bitness: IntBitness::Xsize, | ||
71 | })), | ||
72 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
73 | signedness: Signedness::Signed, | ||
74 | bitness: IntBitness::X8, | ||
75 | })), | ||
76 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
77 | signedness: Signedness::Signed, | ||
78 | bitness: IntBitness::X16, | ||
79 | })), | ||
80 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
81 | signedness: Signedness::Signed, | ||
82 | bitness: IntBitness::X32, | ||
83 | })), | ||
84 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
85 | signedness: Signedness::Signed, | ||
86 | bitness: IntBitness::X64, | ||
87 | })), | ||
88 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
89 | signedness: Signedness::Signed, | ||
90 | bitness: IntBitness::X128, | ||
91 | })), | ||
92 | TyFingerprint::Apply(TypeCtor::Int(IntTy { | ||
93 | signedness: Signedness::Signed, | ||
94 | bitness: IntBitness::Xsize, | ||
95 | })), | ||
96 | ]; | ||
97 | |||
98 | pub(crate) const ALL_FLOAT_FPS: [TyFingerprint; 2] = [ | ||
99 | TyFingerprint::Apply(TypeCtor::Float(FloatTy { bitness: FloatBitness::X32 })), | ||
100 | TyFingerprint::Apply(TypeCtor::Float(FloatTy { bitness: FloatBitness::X64 })), | ||
101 | ]; | ||
102 | |||
42 | /// Trait impls defined or available in some crate. | 103 | /// Trait impls defined or available in some crate. |
43 | #[derive(Debug, Eq, PartialEq)] | 104 | #[derive(Debug, Eq, PartialEq)] |
44 | pub struct TraitImpls { | 105 | pub struct TraitImpls { |
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index 69f2d7667..27f5a60bf 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs | |||
@@ -37,6 +37,15 @@ use crate::{ | |||
37 | // against snapshots of the expected results using insta. Use cargo-insta to | 37 | // against snapshots of the expected results using insta. Use cargo-insta to |
38 | // update the snapshots. | 38 | // update the snapshots. |
39 | 39 | ||
40 | fn setup_tracing() -> tracing::subscriber::DefaultGuard { | ||
41 | use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Registry}; | ||
42 | use tracing_tree::HierarchicalLayer; | ||
43 | let filter = EnvFilter::from_env("CHALK_DEBUG"); | ||
44 | let layer = HierarchicalLayer::default().with_indent_amount(2).with_writer(std::io::stderr); | ||
45 | let subscriber = Registry::default().with(filter).with(layer); | ||
46 | tracing::subscriber::set_default(subscriber) | ||
47 | } | ||
48 | |||
40 | fn check_types(ra_fixture: &str) { | 49 | fn check_types(ra_fixture: &str) { |
41 | check_types_impl(ra_fixture, false) | 50 | check_types_impl(ra_fixture, false) |
42 | } | 51 | } |
@@ -46,6 +55,7 @@ fn check_types_source_code(ra_fixture: &str) { | |||
46 | } | 55 | } |
47 | 56 | ||
48 | fn check_types_impl(ra_fixture: &str, display_source: bool) { | 57 | fn check_types_impl(ra_fixture: &str, display_source: bool) { |
58 | let _tracing = setup_tracing(); | ||
49 | let db = TestDB::with_files(ra_fixture); | 59 | let db = TestDB::with_files(ra_fixture); |
50 | let mut checked_one = false; | 60 | let mut checked_one = false; |
51 | for (file_id, annotations) in db.extract_annotations() { | 61 | for (file_id, annotations) in db.extract_annotations() { |
@@ -86,6 +96,7 @@ fn infer(ra_fixture: &str) -> String { | |||
86 | } | 96 | } |
87 | 97 | ||
88 | fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { | 98 | fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { |
99 | let _tracing = setup_tracing(); | ||
89 | let (db, file_id) = TestDB::with_single_file(content); | 100 | let (db, file_id) = TestDB::with_single_file(content); |
90 | 101 | ||
91 | let mut buf = String::new(); | 102 | let mut buf = String::new(); |
diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs index 136d28a91..d7fb6a962 100644 --- a/crates/ra_hir_ty/src/tests/coercion.rs +++ b/crates/ra_hir_ty/src/tests/coercion.rs | |||
@@ -662,7 +662,53 @@ fn test() { | |||
662 | } | 662 | } |
663 | 663 | ||
664 | #[test] | 664 | #[test] |
665 | fn coerce_unsize_trait_object() { | 665 | fn coerce_unsize_trait_object_simple() { |
666 | assert_snapshot!( | ||
667 | infer_with_mismatches(r#" | ||
668 | #[lang = "sized"] | ||
669 | pub trait Sized {} | ||
670 | #[lang = "unsize"] | ||
671 | pub trait Unsize<T> {} | ||
672 | #[lang = "coerce_unsized"] | ||
673 | pub trait CoerceUnsized<T> {} | ||
674 | |||
675 | impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {} | ||
676 | |||
677 | trait Foo<T, U> {} | ||
678 | trait Bar<U, T, X>: Foo<T, U> {} | ||
679 | trait Baz<T, X>: Bar<usize, T, X> {} | ||
680 | |||
681 | struct S<T, X>; | ||
682 | impl<T, X> Foo<T, usize> for S<T, X> {} | ||
683 | impl<T, X> Bar<usize, T, X> for S<T, X> {} | ||
684 | impl<T, X> Baz<T, X> for S<T, X> {} | ||
685 | |||
686 | fn test() { | ||
687 | let obj: &dyn Baz<i8, i16> = &S; | ||
688 | let obj: &dyn Bar<_, i8, i16> = &S; | ||
689 | let obj: &dyn Foo<i8, _> = &S; | ||
690 | } | ||
691 | "#, true), | ||
692 | @r###" | ||
693 | 424..539 '{ ... &S; }': () | ||
694 | 434..437 'obj': &dyn Baz<i8, i16> | ||
695 | 459..461 '&S': &S<i8, i16> | ||
696 | 460..461 'S': S<i8, i16> | ||
697 | 471..474 'obj': &dyn Bar<usize, i8, i16> | ||
698 | 499..501 '&S': &S<i8, i16> | ||
699 | 500..501 'S': S<i8, i16> | ||
700 | 511..514 'obj': &dyn Foo<i8, usize> | ||
701 | 534..536 '&S': &S<i8, {unknown}> | ||
702 | 535..536 'S': S<i8, {unknown}> | ||
703 | "### | ||
704 | ); | ||
705 | } | ||
706 | |||
707 | #[test] | ||
708 | // The rust reference says this should be possible, but rustc doesn't implement | ||
709 | // it. We used to support it, but Chalk doesn't. | ||
710 | #[ignore] | ||
711 | fn coerce_unsize_trait_object_to_trait_object() { | ||
666 | assert_snapshot!( | 712 | assert_snapshot!( |
667 | infer_with_mismatches(r#" | 713 | infer_with_mismatches(r#" |
668 | #[lang = "sized"] | 714 | #[lang = "sized"] |
@@ -735,16 +781,17 @@ impl D for S {} | |||
735 | 781 | ||
736 | fn test() { | 782 | fn test() { |
737 | let obj: &dyn D = &S; | 783 | let obj: &dyn D = &S; |
738 | let obj: &dyn A = obj; | 784 | let obj: &dyn A = &S; |
739 | } | 785 | } |
740 | "#, true), | 786 | "#, true), |
741 | @r###" | 787 | @r###" |
742 | 328..384 '{ ...obj; }': () | 788 | 328..383 '{ ... &S; }': () |
743 | 338..341 'obj': &dyn D | 789 | 338..341 'obj': &dyn D |
744 | 352..354 '&S': &S | 790 | 352..354 '&S': &S |
745 | 353..354 'S': S | 791 | 353..354 'S': S |
746 | 364..367 'obj': &dyn A | 792 | 364..367 'obj': &dyn A |
747 | 378..381 'obj': &dyn D | 793 | 378..380 '&S': &S |
794 | 379..380 'S': S | ||
748 | "### | 795 | "### |
749 | ); | 796 | ); |
750 | } | 797 | } |
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index 529d9e253..27737fa94 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs | |||
@@ -1992,6 +1992,28 @@ fn test() { | |||
1992 | } | 1992 | } |
1993 | 1993 | ||
1994 | #[test] | 1994 | #[test] |
1995 | fn fn_item_fn_trait() { | ||
1996 | check_types( | ||
1997 | r#" | ||
1998 | #[lang = "fn_once"] | ||
1999 | trait FnOnce<Args> { | ||
2000 | type Output; | ||
2001 | } | ||
2002 | |||
2003 | struct S; | ||
2004 | |||
2005 | fn foo() -> S {} | ||
2006 | |||
2007 | fn takes_closure<U, F: FnOnce() -> U>(f: F) -> U { f() } | ||
2008 | |||
2009 | fn test() { | ||
2010 | takes_closure(foo); | ||
2011 | } //^^^^^^^^^^^^^^^^^^ S | ||
2012 | "#, | ||
2013 | ); | ||
2014 | } | ||
2015 | |||
2016 | #[test] | ||
1995 | fn unselected_projection_in_trait_env_1() { | 2017 | fn unselected_projection_in_trait_env_1() { |
1996 | check_types( | 2018 | check_types( |
1997 | r#" | 2019 | r#" |
@@ -3000,74 +3022,47 @@ fn infer_box_fn_arg() { | |||
3000 | 3022 | ||
3001 | #[test] | 3023 | #[test] |
3002 | fn infer_dyn_fn_output() { | 3024 | fn infer_dyn_fn_output() { |
3003 | assert_snapshot!( | 3025 | check_types( |
3004 | infer( | 3026 | r#" |
3005 | r#" | 3027 | #[lang = "fn_once"] |
3006 | //- /lib.rs deps:std | 3028 | pub trait FnOnce<Args> { |
3007 | 3029 | type Output; | |
3008 | #[lang = "fn_once"] | 3030 | extern "rust-call" fn call_once(self, args: Args) -> Self::Output; |
3009 | pub trait FnOnce<Args> { | 3031 | } |
3010 | type Output; | ||
3011 | |||
3012 | extern "rust-call" fn call_once(self, args: Args) -> Self::Output; | ||
3013 | } | ||
3014 | |||
3015 | #[lang = "fn"] | ||
3016 | pub trait Fn<Args>:FnOnce<Args> { | ||
3017 | extern "rust-call" fn call(&self, args: Args) -> Self::Output; | ||
3018 | } | ||
3019 | |||
3020 | #[lang = "deref"] | ||
3021 | pub trait Deref { | ||
3022 | type Target: ?Sized; | ||
3023 | |||
3024 | fn deref(&self) -> &Self::Target; | ||
3025 | } | ||
3026 | 3032 | ||
3027 | #[lang = "owned_box"] | 3033 | #[lang = "fn"] |
3028 | pub struct Box<T: ?Sized> { | 3034 | pub trait Fn<Args>: FnOnce<Args> { |
3029 | inner: *mut T, | 3035 | extern "rust-call" fn call(&self, args: Args) -> Self::Output; |
3030 | } | 3036 | } |
3031 | 3037 | ||
3032 | impl<T: ?Sized> Deref for Box<T> { | 3038 | fn foo() { |
3033 | type Target = T; | 3039 | let f: &dyn Fn() -> i32; |
3040 | f(); | ||
3041 | //^^^ i32 | ||
3042 | }"#, | ||
3043 | ); | ||
3044 | } | ||
3034 | 3045 | ||
3035 | fn deref(&self) -> &T { | 3046 | #[test] |
3036 | &self.inner | 3047 | fn infer_dyn_fn_once_output() { |
3037 | } | 3048 | check_types( |
3038 | } | 3049 | r#" |
3050 | #[lang = "fn_once"] | ||
3051 | pub trait FnOnce<Args> { | ||
3052 | type Output; | ||
3053 | extern "rust-call" fn call_once(self, args: Args) -> Self::Output; | ||
3054 | } | ||
3039 | 3055 | ||
3040 | fn foo() { | 3056 | fn foo() { |
3041 | let f: Box<dyn Fn() -> i32> = box(|| 5); | 3057 | let f: dyn FnOnce() -> i32; |
3042 | let x = f(); | 3058 | f(); |
3043 | } | 3059 | //^^^ i32 |
3044 | "# | 3060 | }"#, |
3045 | ), | ||
3046 | @r###" | ||
3047 | 100..104 'self': Self | ||
3048 | 106..110 'args': Args | ||
3049 | 219..223 'self': &Self | ||
3050 | 225..229 'args': Args | ||
3051 | 333..337 'self': &Self | ||
3052 | 503..507 'self': &Box<T> | ||
3053 | 515..542 '{ ... }': &T | ||
3054 | 525..536 '&self.inner': &*mut T | ||
3055 | 526..530 'self': &Box<T> | ||
3056 | 526..536 'self.inner': *mut T | ||
3057 | 555..620 '{ ...f(); }': () | ||
3058 | 565..566 'f': Box<dyn Fn<(), Output = i32>> | ||
3059 | 591..600 'box(|| 5)': Box<|| -> i32> | ||
3060 | 595..599 '|| 5': || -> i32 | ||
3061 | 598..599 '5': i32 | ||
3062 | 610..611 'x': FnOnce::Output<dyn Fn<(), Output = i32>, ()> | ||
3063 | 614..615 'f': Box<dyn Fn<(), Output = i32>> | ||
3064 | 614..617 'f()': FnOnce::Output<dyn Fn<(), Output = i32>, ()> | ||
3065 | "### | ||
3066 | ); | 3061 | ); |
3067 | } | 3062 | } |
3068 | 3063 | ||
3069 | #[test] | 3064 | #[test] |
3070 | fn variable_kinds() { | 3065 | fn variable_kinds_1() { |
3071 | check_types( | 3066 | check_types( |
3072 | r#" | 3067 | r#" |
3073 | trait Trait<T> { fn get(self, t: T) -> T; } | 3068 | trait Trait<T> { fn get(self, t: T) -> T; } |
@@ -3083,3 +3078,20 @@ fn test() { | |||
3083 | "#, | 3078 | "#, |
3084 | ); | 3079 | ); |
3085 | } | 3080 | } |
3081 | |||
3082 | #[test] | ||
3083 | fn variable_kinds_2() { | ||
3084 | check_types( | ||
3085 | r#" | ||
3086 | trait Trait { fn get(self) -> Self; } | ||
3087 | impl Trait for u128 {} | ||
3088 | impl Trait for f32 {} | ||
3089 | fn test() { | ||
3090 | 1.get(); | ||
3091 | //^^^^^^^ u128 | ||
3092 | (1.).get(); | ||
3093 | //^^^^^^^^^^ f32 | ||
3094 | } | ||
3095 | "#, | ||
3096 | ); | ||
3097 | } | ||
diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs index 2a6d7faef..f7edb4c8b 100644 --- a/crates/ra_hir_ty/src/traits.rs +++ b/crates/ra_hir_ty/src/traits.rs | |||
@@ -2,6 +2,7 @@ | |||
2 | use std::sync::Arc; | 2 | use std::sync::Arc; |
3 | 3 | ||
4 | use chalk_ir::cast::Cast; | 4 | use chalk_ir::cast::Cast; |
5 | use chalk_solve::Solver; | ||
5 | use hir_def::{ | 6 | use hir_def::{ |
6 | expr::ExprId, lang_item::LangItemTarget, DefWithBodyId, ImplId, TraitId, TypeAliasId, | 7 | expr::ExprId, lang_item::LangItemTarget, DefWithBodyId, ImplId, TraitId, TypeAliasId, |
7 | }; | 8 | }; |
@@ -32,9 +33,10 @@ struct ChalkContext<'a> { | |||
32 | krate: CrateId, | 33 | krate: CrateId, |
33 | } | 34 | } |
34 | 35 | ||
35 | fn create_chalk_solver() -> chalk_solve::Solver<Interner> { | 36 | fn create_chalk_solver() -> chalk_recursive::RecursiveSolver<Interner> { |
36 | let solver_choice = chalk_solve::SolverChoice::recursive(); | 37 | let overflow_depth = 100; |
37 | solver_choice.into_solver() | 38 | let caching_enabled = true; |
39 | chalk_recursive::RecursiveSolver::new(overflow_depth, caching_enabled) | ||
38 | } | 40 | } |
39 | 41 | ||
40 | /// A set of clauses that we assume to be true. E.g. if we are inside this function: | 42 | /// A set of clauses that we assume to be true. E.g. if we are inside this function: |
@@ -293,13 +295,8 @@ pub enum Impl { | |||
293 | /// A normal impl from an impl block. | 295 | /// A normal impl from an impl block. |
294 | ImplDef(ImplId), | 296 | ImplDef(ImplId), |
295 | /// Closure types implement the Fn traits synthetically. | 297 | /// Closure types implement the Fn traits synthetically. |
298 | // FIXME: implement closure support from Chalk, remove this | ||
296 | ClosureFnTraitImpl(ClosureFnTraitImplData), | 299 | ClosureFnTraitImpl(ClosureFnTraitImplData), |
297 | /// [T; n]: Unsize<[T]> | ||
298 | UnsizeArray, | ||
299 | /// T: Unsize<dyn Trait> where T: Trait | ||
300 | UnsizeToTraitObject(TraitId), | ||
301 | /// dyn Trait: Unsize<dyn SuperTrait> if Trait: SuperTrait | ||
302 | UnsizeToSuperTraitObject(UnsizeToSuperTraitObjectData), | ||
303 | } | 300 | } |
304 | /// This exists just for Chalk, because our ImplIds are only unique per module. | 301 | /// This exists just for Chalk, because our ImplIds are only unique per module. |
305 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 302 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs index 6d5f2d46a..86e22e459 100644 --- a/crates/ra_hir_ty/src/traits/builtin.rs +++ b/crates/ra_hir_ty/src/traits/builtin.rs | |||
@@ -1,15 +1,12 @@ | |||
1 | //! This module provides the built-in trait implementations, e.g. to make | 1 | //! This module provides the built-in trait implementations, e.g. to make |
2 | //! closures implement `Fn`. | 2 | //! closures implement `Fn`. |
3 | use hir_def::{expr::Expr, lang_item::LangItemTarget, TraitId, TypeAliasId}; | 3 | use hir_def::{expr::Expr, TraitId, TypeAliasId}; |
4 | use hir_expand::name::name; | 4 | use hir_expand::name::name; |
5 | use ra_db::CrateId; | 5 | use ra_db::CrateId; |
6 | 6 | ||
7 | use super::{AssocTyValue, Impl, UnsizeToSuperTraitObjectData}; | 7 | use super::{AssocTyValue, Impl}; |
8 | use crate::{ | 8 | use crate::{ |
9 | db::HirDatabase, | 9 | db::HirDatabase, ApplicationTy, BoundVar, DebruijnIndex, Substs, TraitRef, Ty, TypeCtor, |
10 | utils::{all_super_traits, generics}, | ||
11 | ApplicationTy, Binders, BoundVar, DebruijnIndex, GenericPredicate, Substs, TraitRef, Ty, | ||
12 | TypeCtor, TypeWalk, | ||
13 | }; | 10 | }; |
14 | 11 | ||
15 | pub(super) struct BuiltinImplData { | 12 | pub(super) struct BuiltinImplData { |
@@ -31,7 +28,7 @@ pub(super) fn get_builtin_impls( | |||
31 | krate: CrateId, | 28 | krate: CrateId, |
32 | ty: &Ty, | 29 | ty: &Ty, |
33 | // The first argument for the trait, if present | 30 | // The first argument for the trait, if present |
34 | arg: &Option<Ty>, | 31 | _arg: &Option<Ty>, |
35 | trait_: TraitId, | 32 | trait_: TraitId, |
36 | mut callback: impl FnMut(Impl), | 33 | mut callback: impl FnMut(Impl), |
37 | ) { | 34 | ) { |
@@ -50,60 +47,12 @@ pub(super) fn get_builtin_impls( | |||
50 | } | 47 | } |
51 | } | 48 | } |
52 | } | 49 | } |
53 | |||
54 | let unsize_trait = get_unsize_trait(db, krate); | ||
55 | if let Some(actual_trait) = unsize_trait { | ||
56 | if trait_ == actual_trait { | ||
57 | get_builtin_unsize_impls(db, krate, ty, arg, callback); | ||
58 | } | ||
59 | } | ||
60 | } | ||
61 | |||
62 | fn get_builtin_unsize_impls( | ||
63 | db: &dyn HirDatabase, | ||
64 | krate: CrateId, | ||
65 | ty: &Ty, | ||
66 | // The first argument for the trait, if present | ||
67 | arg: &Option<Ty>, | ||
68 | mut callback: impl FnMut(Impl), | ||
69 | ) { | ||
70 | if !check_unsize_impl_prerequisites(db, krate) { | ||
71 | return; | ||
72 | } | ||
73 | |||
74 | if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Array, .. }) = ty { | ||
75 | callback(Impl::UnsizeArray); | ||
76 | return; // array is unsized, the rest of the impls shouldn't apply | ||
77 | } | ||
78 | |||
79 | if let Some(target_trait) = arg.as_ref().and_then(|t| t.dyn_trait_ref()) { | ||
80 | // FIXME what about more complicated dyn tys with marker traits? | ||
81 | if let Some(trait_ref) = ty.dyn_trait_ref() { | ||
82 | if trait_ref.trait_ != target_trait.trait_ { | ||
83 | let super_traits = all_super_traits(db.upcast(), trait_ref.trait_); | ||
84 | if super_traits.contains(&target_trait.trait_) { | ||
85 | callback(Impl::UnsizeToSuperTraitObject(UnsizeToSuperTraitObjectData { | ||
86 | trait_: trait_ref.trait_, | ||
87 | super_trait: target_trait.trait_, | ||
88 | })); | ||
89 | } | ||
90 | } | ||
91 | } else { | ||
92 | // FIXME only for sized types | ||
93 | callback(Impl::UnsizeToTraitObject(target_trait.trait_)); | ||
94 | } | ||
95 | } | ||
96 | } | 50 | } |
97 | 51 | ||
98 | pub(super) fn impl_datum(db: &dyn HirDatabase, krate: CrateId, impl_: Impl) -> BuiltinImplData { | 52 | pub(super) fn impl_datum(db: &dyn HirDatabase, krate: CrateId, impl_: Impl) -> BuiltinImplData { |
99 | match impl_ { | 53 | match impl_ { |
100 | Impl::ImplDef(_) => unreachable!(), | 54 | Impl::ImplDef(_) => unreachable!(), |
101 | Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data), | 55 | Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data), |
102 | Impl::UnsizeArray => array_unsize_impl_datum(db, krate), | ||
103 | Impl::UnsizeToTraitObject(trait_) => trait_object_unsize_impl_datum(db, krate, trait_), | ||
104 | Impl::UnsizeToSuperTraitObject(data) => { | ||
105 | super_trait_object_unsize_impl_datum(db, krate, data) | ||
106 | } | ||
107 | } | 56 | } |
108 | } | 57 | } |
109 | 58 | ||
@@ -227,145 +176,3 @@ fn closure_fn_trait_output_assoc_ty_value( | |||
227 | value: output_ty, | 176 | value: output_ty, |
228 | } | 177 | } |
229 | } | 178 | } |
230 | |||
231 | // Array unsizing | ||
232 | |||
233 | fn check_unsize_impl_prerequisites(db: &dyn HirDatabase, krate: CrateId) -> bool { | ||
234 | // the Unsize trait needs to exist and have two type parameters (Self and T) | ||
235 | let unsize_trait = match get_unsize_trait(db, krate) { | ||
236 | Some(t) => t, | ||
237 | None => return false, | ||
238 | }; | ||
239 | let generic_params = generics(db.upcast(), unsize_trait.into()); | ||
240 | generic_params.len() == 2 | ||
241 | } | ||
242 | |||
243 | fn array_unsize_impl_datum(db: &dyn HirDatabase, krate: CrateId) -> BuiltinImplData { | ||
244 | // impl<T> Unsize<[T]> for [T; _] | ||
245 | // (this can be a single impl because we don't distinguish array sizes currently) | ||
246 | |||
247 | let trait_ = get_unsize_trait(db, krate) // get unsize trait | ||
248 | // the existence of the Unsize trait has been checked before | ||
249 | .expect("Unsize trait missing"); | ||
250 | |||
251 | let var = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); | ||
252 | let substs = Substs::builder(2) | ||
253 | .push(Ty::apply_one(TypeCtor::Array, var.clone())) | ||
254 | .push(Ty::apply_one(TypeCtor::Slice, var)) | ||
255 | .build(); | ||
256 | |||
257 | let trait_ref = TraitRef { trait_, substs }; | ||
258 | |||
259 | BuiltinImplData { | ||
260 | num_vars: 1, | ||
261 | trait_ref, | ||
262 | where_clauses: Vec::new(), | ||
263 | assoc_ty_values: Vec::new(), | ||
264 | } | ||
265 | } | ||
266 | |||
267 | // Trait object unsizing | ||
268 | |||
269 | fn trait_object_unsize_impl_datum( | ||
270 | db: &dyn HirDatabase, | ||
271 | krate: CrateId, | ||
272 | trait_: TraitId, | ||
273 | ) -> BuiltinImplData { | ||
274 | // impl<T, T1, ...> Unsize<dyn Trait<T1, ...>> for T where T: Trait<T1, ...> | ||
275 | |||
276 | let unsize_trait = get_unsize_trait(db, krate) // get unsize trait | ||
277 | // the existence of the Unsize trait has been checked before | ||
278 | .expect("Unsize trait missing"); | ||
279 | |||
280 | let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); | ||
281 | |||
282 | let target_substs = Substs::build_for_def(db, trait_) | ||
283 | .push(Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0))) | ||
284 | .fill_with_bound_vars(DebruijnIndex::ONE, 1) | ||
285 | .build(); | ||
286 | let num_vars = target_substs.len(); | ||
287 | let target_trait_ref = TraitRef { trait_, substs: target_substs }; | ||
288 | let target_bounds = vec![GenericPredicate::Implemented(target_trait_ref)]; | ||
289 | |||
290 | let self_substs = | ||
291 | Substs::build_for_def(db, trait_).fill_with_bound_vars(DebruijnIndex::INNERMOST, 0).build(); | ||
292 | let self_trait_ref = TraitRef { trait_, substs: self_substs }; | ||
293 | let where_clauses = vec![GenericPredicate::Implemented(self_trait_ref)]; | ||
294 | |||
295 | let impl_substs = Substs::builder(2).push(self_ty).push(Ty::Dyn(target_bounds.into())).build(); | ||
296 | |||
297 | let trait_ref = TraitRef { trait_: unsize_trait, substs: impl_substs }; | ||
298 | |||
299 | BuiltinImplData { num_vars, trait_ref, where_clauses, assoc_ty_values: Vec::new() } | ||
300 | } | ||
301 | |||
302 | fn super_trait_object_unsize_impl_datum( | ||
303 | db: &dyn HirDatabase, | ||
304 | krate: CrateId, | ||
305 | data: UnsizeToSuperTraitObjectData, | ||
306 | ) -> BuiltinImplData { | ||
307 | // impl<T1, ...> Unsize<dyn SuperTrait> for dyn Trait<T1, ...> | ||
308 | |||
309 | let unsize_trait = get_unsize_trait(db, krate) // get unsize trait | ||
310 | // the existence of the Unsize trait has been checked before | ||
311 | .expect("Unsize trait missing"); | ||
312 | |||
313 | let self_substs = Substs::build_for_def(db, data.trait_) | ||
314 | .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0) | ||
315 | .build(); | ||
316 | let self_trait_ref = TraitRef { trait_: data.trait_, substs: self_substs.clone() }; | ||
317 | |||
318 | let num_vars = self_substs.len() - 1; | ||
319 | |||
320 | // we need to go from our trait to the super trait, substituting type parameters | ||
321 | let path = crate::utils::find_super_trait_path(db.upcast(), data.trait_, data.super_trait); | ||
322 | |||
323 | let mut current_trait_ref = self_trait_ref.clone(); | ||
324 | for t in path.into_iter().skip(1) { | ||
325 | let bounds = db.generic_predicates(current_trait_ref.trait_.into()); | ||
326 | let super_trait_ref = bounds | ||
327 | .iter() | ||
328 | .find_map(|b| match &b.value { | ||
329 | GenericPredicate::Implemented(tr) | ||
330 | if tr.trait_ == t | ||
331 | && tr.substs[0] | ||
332 | == Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)) => | ||
333 | { | ||
334 | Some(Binders { value: tr, num_binders: b.num_binders }) | ||
335 | } | ||
336 | _ => None, | ||
337 | }) | ||
338 | .expect("trait bound for known super trait not found"); | ||
339 | current_trait_ref = super_trait_ref.cloned().subst(¤t_trait_ref.substs); | ||
340 | } | ||
341 | |||
342 | // We need to renumber the variables a bit now: from ^0.0, ^0.1, ^0.2, ... | ||
343 | // to ^0.0, ^1.0, ^1.1. The reason for this is that the first variable comes | ||
344 | // from the dyn Trait binder, while the other variables come from the impl. | ||
345 | let new_substs = Substs::builder(num_vars + 1) | ||
346 | .push(Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0))) | ||
347 | .fill_with_bound_vars(DebruijnIndex::ONE, 0) | ||
348 | .build(); | ||
349 | |||
350 | let self_bounds = | ||
351 | vec![GenericPredicate::Implemented(self_trait_ref.subst_bound_vars(&new_substs))]; | ||
352 | let super_bounds = | ||
353 | vec![GenericPredicate::Implemented(current_trait_ref.subst_bound_vars(&new_substs))]; | ||
354 | |||
355 | let substs = Substs::builder(2) | ||
356 | .push(Ty::Dyn(self_bounds.into())) | ||
357 | .push(Ty::Dyn(super_bounds.into())) | ||
358 | .build(); | ||
359 | |||
360 | let trait_ref = TraitRef { trait_: unsize_trait, substs }; | ||
361 | |||
362 | BuiltinImplData { num_vars, trait_ref, where_clauses: Vec::new(), assoc_ty_values: Vec::new() } | ||
363 | } | ||
364 | |||
365 | fn get_unsize_trait(db: &dyn HirDatabase, krate: CrateId) -> Option<TraitId> { | ||
366 | let target = db.lang_item(krate, "unsize".into())?; | ||
367 | match target { | ||
368 | LangItemTarget::TraitId(t) => Some(t), | ||
369 | _ => None, | ||
370 | } | ||
371 | } | ||
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index c97b81d57..c448aea65 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs | |||
@@ -3,7 +3,7 @@ use std::sync::Arc; | |||
3 | 3 | ||
4 | use log::debug; | 4 | use log::debug; |
5 | 5 | ||
6 | use chalk_ir::{fold::shift::Shift, GenericArg, TypeName}; | 6 | use chalk_ir::{fold::shift::Shift, CanonicalVarKinds, GenericArg, TypeName}; |
7 | use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait}; | 7 | use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait}; |
8 | 8 | ||
9 | use hir_def::{ | 9 | use hir_def::{ |
@@ -14,7 +14,10 @@ use ra_db::{salsa::InternKey, CrateId}; | |||
14 | 14 | ||
15 | use super::{builtin, AssocTyValue, ChalkContext, Impl}; | 15 | use super::{builtin, AssocTyValue, ChalkContext, Impl}; |
16 | use crate::{ | 16 | use crate::{ |
17 | db::HirDatabase, display::HirDisplay, method_resolution::TyFingerprint, utils::generics, | 17 | db::HirDatabase, |
18 | display::HirDisplay, | ||
19 | method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, | ||
20 | utils::generics, | ||
18 | CallableDef, DebruijnIndex, GenericPredicate, Substs, Ty, TypeCtor, | 21 | CallableDef, DebruijnIndex, GenericPredicate, Substs, Ty, TypeCtor, |
19 | }; | 22 | }; |
20 | use mapping::{convert_where_clauses, generic_predicate_to_inline_bound, make_binders}; | 23 | use mapping::{convert_where_clauses, generic_predicate_to_inline_bound, make_binders}; |
@@ -66,13 +69,31 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
66 | &self, | 69 | &self, |
67 | trait_id: TraitId, | 70 | trait_id: TraitId, |
68 | parameters: &[GenericArg<Interner>], | 71 | parameters: &[GenericArg<Interner>], |
72 | binders: &CanonicalVarKinds<Interner>, | ||
69 | ) -> Vec<ImplId> { | 73 | ) -> Vec<ImplId> { |
70 | debug!("impls_for_trait {:?}", trait_id); | 74 | debug!("impls_for_trait {:?}", trait_id); |
71 | let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); | 75 | let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); |
72 | 76 | ||
73 | let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref(&Interner).clone()); | 77 | let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref(&Interner).clone()); |
74 | 78 | ||
79 | fn binder_kind(ty: &Ty, binders: &CanonicalVarKinds<Interner>) -> Option<chalk_ir::TyKind> { | ||
80 | if let Ty::Bound(bv) = ty { | ||
81 | let binders = binders.as_slice(&Interner); | ||
82 | if bv.debruijn == DebruijnIndex::INNERMOST { | ||
83 | if let chalk_ir::VariableKind::Ty(tk) = binders[bv.index].kind { | ||
84 | return Some(tk); | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | None | ||
89 | } | ||
90 | |||
75 | let self_ty_fp = TyFingerprint::for_impl(&ty); | 91 | let self_ty_fp = TyFingerprint::for_impl(&ty); |
92 | let fps: &[TyFingerprint] = match binder_kind(&ty, binders) { | ||
93 | Some(chalk_ir::TyKind::Integer) => &ALL_INT_FPS, | ||
94 | Some(chalk_ir::TyKind::Float) => &ALL_FLOAT_FPS, | ||
95 | _ => self_ty_fp.as_ref().map(std::slice::from_ref).unwrap_or(&[]), | ||
96 | }; | ||
76 | 97 | ||
77 | // Note: Since we're using impls_for_trait, only impls where the trait | 98 | // Note: Since we're using impls_for_trait, only impls where the trait |
78 | // can be resolved should ever reach Chalk. `impl_datum` relies on that | 99 | // can be resolved should ever reach Chalk. `impl_datum` relies on that |
@@ -83,17 +104,21 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
83 | 104 | ||
84 | let id_to_chalk = |id: hir_def::ImplId| Impl::ImplDef(id).to_chalk(self.db); | 105 | let id_to_chalk = |id: hir_def::ImplId| Impl::ImplDef(id).to_chalk(self.db); |
85 | 106 | ||
86 | let mut result: Vec<_> = match self_ty_fp { | 107 | let mut result: Vec<_> = if fps.is_empty() { |
87 | Some(fp) => impl_maps | 108 | debug!("Unrestricted search for {:?} impls...", trait_); |
109 | impl_maps | ||
110 | .iter() | ||
111 | .flat_map(|crate_impl_defs| crate_impl_defs.for_trait(trait_).map(id_to_chalk)) | ||
112 | .collect() | ||
113 | } else { | ||
114 | impl_maps | ||
88 | .iter() | 115 | .iter() |
89 | .flat_map(|crate_impl_defs| { | 116 | .flat_map(|crate_impl_defs| { |
90 | crate_impl_defs.for_trait_and_self_ty(trait_, fp).map(id_to_chalk) | 117 | fps.iter().flat_map(move |fp| { |
118 | crate_impl_defs.for_trait_and_self_ty(trait_, *fp).map(id_to_chalk) | ||
119 | }) | ||
91 | }) | 120 | }) |
92 | .collect(), | 121 | .collect() |
93 | None => impl_maps | ||
94 | .iter() | ||
95 | .flat_map(|crate_impl_defs| crate_impl_defs.for_trait(trait_).map(id_to_chalk)) | ||
96 | .collect(), | ||
97 | }; | 122 | }; |
98 | 123 | ||
99 | let arg: Option<Ty> = | 124 | let arg: Option<Ty> = |
@@ -219,6 +244,22 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
219 | // FIXME: implement closure support | 244 | // FIXME: implement closure support |
220 | unimplemented!() | 245 | unimplemented!() |
221 | } | 246 | } |
247 | |||
248 | fn trait_name(&self, _trait_id: chalk_ir::TraitId<Interner>) -> String { | ||
249 | unimplemented!() | ||
250 | } | ||
251 | fn adt_name(&self, _struct_id: chalk_ir::AdtId<Interner>) -> String { | ||
252 | unimplemented!() | ||
253 | } | ||
254 | fn assoc_type_name(&self, _assoc_ty_id: chalk_ir::AssocTypeId<Interner>) -> String { | ||
255 | unimplemented!() | ||
256 | } | ||
257 | fn opaque_type_name(&self, _opaque_ty_id: chalk_ir::OpaqueTyId<Interner>) -> String { | ||
258 | unimplemented!() | ||
259 | } | ||
260 | fn fn_def_name(&self, _fn_def_id: chalk_ir::FnDefId<Interner>) -> String { | ||
261 | unimplemented!() | ||
262 | } | ||
222 | } | 263 | } |
223 | 264 | ||
224 | pub(crate) fn program_clauses_for_chalk_env_query( | 265 | pub(crate) fn program_clauses_for_chalk_env_query( |
@@ -354,12 +395,18 @@ pub(crate) fn struct_datum_query( | |||
354 | fundamental: false, | 395 | fundamental: false, |
355 | phantom_data: false, | 396 | phantom_data: false, |
356 | }; | 397 | }; |
357 | let struct_datum_bound = rust_ir::AdtDatumBound { | 398 | // FIXME provide enum variants properly (for auto traits) |
358 | fields: Vec::new(), // FIXME add fields (only relevant for auto traits) | 399 | let variant = rust_ir::AdtVariantDatum { |
359 | where_clauses, | 400 | fields: Vec::new(), // FIXME add fields (only relevant for auto traits), |
401 | }; | ||
402 | let struct_datum_bound = rust_ir::AdtDatumBound { variants: vec![variant], where_clauses }; | ||
403 | let struct_datum = StructDatum { | ||
404 | // FIXME set ADT kind | ||
405 | kind: rust_ir::AdtKind::Struct, | ||
406 | id: struct_id, | ||
407 | binders: make_binders(struct_datum_bound, num_params), | ||
408 | flags, | ||
360 | }; | 409 | }; |
361 | let struct_datum = | ||
362 | StructDatum { id: struct_id, binders: make_binders(struct_datum_bound, num_params), flags }; | ||
363 | Arc::new(struct_datum) | 410 | Arc::new(struct_datum) |
364 | } | 411 | } |
365 | 412 | ||
diff --git a/crates/ra_hir_ty/src/traits/chalk/interner.rs b/crates/ra_hir_ty/src/traits/chalk/interner.rs index 15426b022..156b691b4 100644 --- a/crates/ra_hir_ty/src/traits/chalk/interner.rs +++ b/crates/ra_hir_ty/src/traits/chalk/interner.rs | |||
@@ -39,6 +39,7 @@ impl chalk_ir::interner::Interner for Interner { | |||
39 | type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>; | 39 | type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>; |
40 | type InternedVariableKinds = Vec<chalk_ir::VariableKind<Self>>; | 40 | type InternedVariableKinds = Vec<chalk_ir::VariableKind<Self>>; |
41 | type InternedCanonicalVarKinds = Vec<chalk_ir::CanonicalVarKind<Self>>; | 41 | type InternedCanonicalVarKinds = Vec<chalk_ir::CanonicalVarKind<Self>>; |
42 | type InternedConstraints = Vec<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>>; | ||
42 | type DefId = InternId; | 43 | type DefId = InternId; |
43 | type InternedAdtId = crate::TypeCtorId; | 44 | type InternedAdtId = crate::TypeCtorId; |
44 | type Identifier = TypeAliasId; | 45 | type Identifier = TypeAliasId; |
@@ -349,6 +350,20 @@ impl chalk_ir::interner::Interner for Interner { | |||
349 | ) -> &'a [chalk_ir::CanonicalVarKind<Self>] { | 350 | ) -> &'a [chalk_ir::CanonicalVarKind<Self>] { |
350 | &canonical_var_kinds | 351 | &canonical_var_kinds |
351 | } | 352 | } |
353 | |||
354 | fn intern_constraints<E>( | ||
355 | &self, | ||
356 | data: impl IntoIterator<Item = Result<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>, E>>, | ||
357 | ) -> Result<Self::InternedConstraints, E> { | ||
358 | data.into_iter().collect() | ||
359 | } | ||
360 | |||
361 | fn constraints_data<'a>( | ||
362 | &self, | ||
363 | constraints: &'a Self::InternedConstraints, | ||
364 | ) -> &'a [chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>] { | ||
365 | constraints | ||
366 | } | ||
352 | } | 367 | } |
353 | 368 | ||
354 | impl chalk_ir::interner::HasInterner for Interner { | 369 | impl chalk_ir::interner::HasInterner for Interner { |
diff --git a/crates/ra_hir_ty/src/traits/chalk/mapping.rs b/crates/ra_hir_ty/src/traits/chalk/mapping.rs index cb354d586..06453ef82 100644 --- a/crates/ra_hir_ty/src/traits/chalk/mapping.rs +++ b/crates/ra_hir_ty/src/traits/chalk/mapping.rs | |||
@@ -29,6 +29,7 @@ impl ToChalk for Ty { | |||
29 | match self { | 29 | match self { |
30 | Ty::Apply(apply_ty) => match apply_ty.ctor { | 30 | Ty::Apply(apply_ty) => match apply_ty.ctor { |
31 | TypeCtor::Ref(m) => ref_to_chalk(db, m, apply_ty.parameters), | 31 | TypeCtor::Ref(m) => ref_to_chalk(db, m, apply_ty.parameters), |
32 | TypeCtor::Array => array_to_chalk(db, apply_ty.parameters), | ||
32 | TypeCtor::FnPtr { num_args: _ } => { | 33 | TypeCtor::FnPtr { num_args: _ } => { |
33 | let substitution = apply_ty.parameters.to_chalk(db).shifted_in(&Interner); | 34 | let substitution = apply_ty.parameters.to_chalk(db).shifted_in(&Interner); |
34 | chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: 0, substitution }) | 35 | chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: 0, substitution }) |
@@ -61,13 +62,13 @@ impl ToChalk for Ty { | |||
61 | Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx).intern(&Interner), | 62 | Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx).intern(&Interner), |
62 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), | 63 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), |
63 | Ty::Dyn(predicates) => { | 64 | Ty::Dyn(predicates) => { |
64 | let where_clauses = chalk_ir::QuantifiedWhereClauses::from( | 65 | let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter( |
65 | &Interner, | 66 | &Interner, |
66 | predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)), | 67 | predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)), |
67 | ); | 68 | ); |
68 | let bounded_ty = chalk_ir::DynTy { | 69 | let bounded_ty = chalk_ir::DynTy { |
69 | bounds: make_binders(where_clauses, 1), | 70 | bounds: make_binders(where_clauses, 1), |
70 | lifetime: LIFETIME_PLACEHOLDER.to_lifetime(&Interner), | 71 | lifetime: FAKE_PLACEHOLDER.to_lifetime(&Interner), |
71 | }; | 72 | }; |
72 | chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner) | 73 | chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner) |
73 | } | 74 | } |
@@ -92,6 +93,7 @@ impl ToChalk for Ty { | |||
92 | chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name { | 93 | chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name { |
93 | TypeName::Error => Ty::Unknown, | 94 | TypeName::Error => Ty::Unknown, |
94 | TypeName::Ref(m) => ref_from_chalk(db, m, apply_ty.substitution), | 95 | TypeName::Ref(m) => ref_from_chalk(db, m, apply_ty.substitution), |
96 | TypeName::Array => array_from_chalk(db, apply_ty.substitution), | ||
95 | _ => { | 97 | _ => { |
96 | let ctor = from_chalk(db, apply_ty.name); | 98 | let ctor = from_chalk(db, apply_ty.name); |
97 | let parameters = from_chalk(db, apply_ty.substitution); | 99 | let parameters = from_chalk(db, apply_ty.substitution); |
@@ -142,7 +144,7 @@ impl ToChalk for Ty { | |||
142 | } | 144 | } |
143 | } | 145 | } |
144 | 146 | ||
145 | const LIFETIME_PLACEHOLDER: PlaceholderIndex = | 147 | const FAKE_PLACEHOLDER: PlaceholderIndex = |
146 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::MAX }; | 148 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::MAX }; |
147 | 149 | ||
148 | /// We currently don't model lifetimes, but Chalk does. So, we have to insert a | 150 | /// We currently don't model lifetimes, but Chalk does. So, we have to insert a |
@@ -153,10 +155,10 @@ fn ref_to_chalk( | |||
153 | subst: Substs, | 155 | subst: Substs, |
154 | ) -> chalk_ir::Ty<Interner> { | 156 | ) -> chalk_ir::Ty<Interner> { |
155 | let arg = subst[0].clone().to_chalk(db); | 157 | let arg = subst[0].clone().to_chalk(db); |
156 | let lifetime = LIFETIME_PLACEHOLDER.to_lifetime(&Interner); | 158 | let lifetime = FAKE_PLACEHOLDER.to_lifetime(&Interner); |
157 | chalk_ir::ApplicationTy { | 159 | chalk_ir::ApplicationTy { |
158 | name: TypeName::Ref(mutability.to_chalk(db)), | 160 | name: TypeName::Ref(mutability.to_chalk(db)), |
159 | substitution: chalk_ir::Substitution::from( | 161 | substitution: chalk_ir::Substitution::from_iter( |
160 | &Interner, | 162 | &Interner, |
161 | vec![lifetime.cast(&Interner), arg.cast(&Interner)], | 163 | vec![lifetime.cast(&Interner), arg.cast(&Interner)], |
162 | ), | 164 | ), |
@@ -177,11 +179,40 @@ fn ref_from_chalk( | |||
177 | Ty::apply(TypeCtor::Ref(from_chalk(db, mutability)), Substs(tys)) | 179 | Ty::apply(TypeCtor::Ref(from_chalk(db, mutability)), Substs(tys)) |
178 | } | 180 | } |
179 | 181 | ||
182 | /// We currently don't model constants, but Chalk does. So, we have to insert a | ||
183 | /// fake constant here, because Chalks built-in logic may expect it to be there. | ||
184 | fn array_to_chalk(db: &dyn HirDatabase, subst: Substs) -> chalk_ir::Ty<Interner> { | ||
185 | let arg = subst[0].clone().to_chalk(db); | ||
186 | let usize_ty = chalk_ir::ApplicationTy { | ||
187 | name: TypeName::Scalar(Scalar::Uint(chalk_ir::UintTy::Usize)), | ||
188 | substitution: chalk_ir::Substitution::empty(&Interner), | ||
189 | } | ||
190 | .intern(&Interner); | ||
191 | let const_ = FAKE_PLACEHOLDER.to_const(&Interner, usize_ty); | ||
192 | chalk_ir::ApplicationTy { | ||
193 | name: TypeName::Array, | ||
194 | substitution: chalk_ir::Substitution::from_iter( | ||
195 | &Interner, | ||
196 | vec![arg.cast(&Interner), const_.cast(&Interner)], | ||
197 | ), | ||
198 | } | ||
199 | .intern(&Interner) | ||
200 | } | ||
201 | |||
202 | /// Here we remove the const from the type we got from Chalk. | ||
203 | fn array_from_chalk(db: &dyn HirDatabase, subst: chalk_ir::Substitution<Interner>) -> Ty { | ||
204 | let tys = subst | ||
205 | .iter(&Interner) | ||
206 | .filter_map(|p| Some(from_chalk(db, p.ty(&Interner)?.clone()))) | ||
207 | .collect(); | ||
208 | Ty::apply(TypeCtor::Array, Substs(tys)) | ||
209 | } | ||
210 | |||
180 | impl ToChalk for Substs { | 211 | impl ToChalk for Substs { |
181 | type Chalk = chalk_ir::Substitution<Interner>; | 212 | type Chalk = chalk_ir::Substitution<Interner>; |
182 | 213 | ||
183 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Substitution<Interner> { | 214 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Substitution<Interner> { |
184 | chalk_ir::Substitution::from(&Interner, self.iter().map(|ty| ty.clone().to_chalk(db))) | 215 | chalk_ir::Substitution::from_iter(&Interner, self.iter().map(|ty| ty.clone().to_chalk(db))) |
185 | } | 216 | } |
186 | 217 | ||
187 | fn from_chalk(db: &dyn HirDatabase, parameters: chalk_ir::Substitution<Interner>) -> Substs { | 218 | fn from_chalk(db: &dyn HirDatabase, parameters: chalk_ir::Substitution<Interner>) -> Substs { |
@@ -267,6 +298,7 @@ impl ToChalk for TypeCtor { | |||
267 | TypeCtor::Tuple { cardinality } => TypeName::Tuple(cardinality.into()), | 298 | TypeCtor::Tuple { cardinality } => TypeName::Tuple(cardinality.into()), |
268 | TypeCtor::RawPtr(mutability) => TypeName::Raw(mutability.to_chalk(db)), | 299 | TypeCtor::RawPtr(mutability) => TypeName::Raw(mutability.to_chalk(db)), |
269 | TypeCtor::Slice => TypeName::Slice, | 300 | TypeCtor::Slice => TypeName::Slice, |
301 | TypeCtor::Array => TypeName::Array, | ||
270 | TypeCtor::Ref(mutability) => TypeName::Ref(mutability.to_chalk(db)), | 302 | TypeCtor::Ref(mutability) => TypeName::Ref(mutability.to_chalk(db)), |
271 | TypeCtor::Str => TypeName::Str, | 303 | TypeCtor::Str => TypeName::Str, |
272 | TypeCtor::FnDef(callable_def) => { | 304 | TypeCtor::FnDef(callable_def) => { |
@@ -275,10 +307,8 @@ impl ToChalk for TypeCtor { | |||
275 | } | 307 | } |
276 | TypeCtor::Never => TypeName::Never, | 308 | TypeCtor::Never => TypeName::Never, |
277 | 309 | ||
278 | TypeCtor::Adt(_) | 310 | // FIXME convert these |
279 | | TypeCtor::Array | 311 | TypeCtor::Adt(_) | TypeCtor::FnPtr { .. } | TypeCtor::Closure { .. } => { |
280 | | TypeCtor::FnPtr { .. } | ||
281 | | TypeCtor::Closure { .. } => { | ||
282 | // other TypeCtors get interned and turned into a chalk StructId | 312 | // other TypeCtors get interned and turned into a chalk StructId |
283 | let struct_id = db.intern_type_ctor(self).into(); | 313 | let struct_id = db.intern_type_ctor(self).into(); |
284 | TypeName::Adt(struct_id) | 314 | TypeName::Adt(struct_id) |
@@ -496,6 +526,11 @@ impl ToChalk for GenericPredicate { | |||
496 | // we shouldn't get these from Chalk | 526 | // we shouldn't get these from Chalk |
497 | panic!("encountered LifetimeOutlives from Chalk") | 527 | panic!("encountered LifetimeOutlives from Chalk") |
498 | } | 528 | } |
529 | |||
530 | chalk_ir::WhereClause::TypeOutlives(_) => { | ||
531 | // we shouldn't get these from Chalk | ||
532 | panic!("encountered TypeOutlives from Chalk") | ||
533 | } | ||
499 | } | 534 | } |
500 | } | 535 | } |
501 | } | 536 | } |
@@ -574,7 +609,10 @@ where | |||
574 | ) | 609 | ) |
575 | }); | 610 | }); |
576 | let value = self.value.to_chalk(db); | 611 | let value = self.value.to_chalk(db); |
577 | chalk_ir::Canonical { value, binders: chalk_ir::CanonicalVarKinds::from(&Interner, kinds) } | 612 | chalk_ir::Canonical { |
613 | value, | ||
614 | binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds), | ||
615 | } | ||
578 | } | 616 | } |
579 | 617 | ||
580 | fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { | 618 | fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { |
@@ -695,7 +733,7 @@ where | |||
695 | T: HasInterner<Interner = Interner>, | 733 | T: HasInterner<Interner = Interner>, |
696 | { | 734 | { |
697 | chalk_ir::Binders::new( | 735 | chalk_ir::Binders::new( |
698 | chalk_ir::VariableKinds::from( | 736 | chalk_ir::VariableKinds::from_iter( |
699 | &Interner, | 737 | &Interner, |
700 | std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General)).take(num_vars), | 738 | std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General)).take(num_vars), |
701 | ), | 739 | ), |
diff --git a/crates/ra_hir_ty/src/traits/chalk/tls.rs b/crates/ra_hir_ty/src/traits/chalk/tls.rs index e6a9d3211..1e226baea 100644 --- a/crates/ra_hir_ty/src/traits/chalk/tls.rs +++ b/crates/ra_hir_ty/src/traits/chalk/tls.rs | |||
@@ -157,7 +157,7 @@ impl DebugContext<'_> { | |||
157 | _ => panic!("associated type not in trait"), | 157 | _ => panic!("associated type not in trait"), |
158 | }; | 158 | }; |
159 | let trait_data = self.0.trait_data(trait_); | 159 | let trait_data = self.0.trait_data(trait_); |
160 | let params = projection_ty.substitution.parameters(&Interner); | 160 | let params = projection_ty.substitution.as_slice(&Interner); |
161 | write!(fmt, "<{:?} as {}", ¶ms[0], trait_data.name,)?; | 161 | write!(fmt, "<{:?} as {}", ¶ms[0], trait_data.name,)?; |
162 | if params.len() > 1 { | 162 | if params.len() > 1 { |
163 | write!( | 163 | write!( |
diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs index c45820ff0..e3e244268 100644 --- a/crates/ra_hir_ty/src/utils.rs +++ b/crates/ra_hir_ty/src/utils.rs | |||
@@ -110,38 +110,6 @@ pub(super) fn all_super_trait_refs(db: &dyn HirDatabase, trait_ref: TraitRef) -> | |||
110 | result | 110 | result |
111 | } | 111 | } |
112 | 112 | ||
113 | /// Finds a path from a trait to one of its super traits. Returns an empty | ||
114 | /// vector if there is no path. | ||
115 | pub(super) fn find_super_trait_path( | ||
116 | db: &dyn DefDatabase, | ||
117 | trait_: TraitId, | ||
118 | super_trait: TraitId, | ||
119 | ) -> Vec<TraitId> { | ||
120 | let mut result = Vec::with_capacity(2); | ||
121 | result.push(trait_); | ||
122 | return if go(db, super_trait, &mut result) { result } else { Vec::new() }; | ||
123 | |||
124 | fn go(db: &dyn DefDatabase, super_trait: TraitId, path: &mut Vec<TraitId>) -> bool { | ||
125 | let trait_ = *path.last().unwrap(); | ||
126 | if trait_ == super_trait { | ||
127 | return true; | ||
128 | } | ||
129 | |||
130 | for tt in direct_super_traits(db, trait_) { | ||
131 | if path.contains(&tt) { | ||
132 | continue; | ||
133 | } | ||
134 | path.push(tt); | ||
135 | if go(db, super_trait, path) { | ||
136 | return true; | ||
137 | } else { | ||
138 | path.pop(); | ||
139 | } | ||
140 | } | ||
141 | false | ||
142 | } | ||
143 | } | ||
144 | |||
145 | pub(super) fn associated_type_by_name_including_super_traits( | 113 | pub(super) fn associated_type_by_name_including_super_traits( |
146 | db: &dyn HirDatabase, | 114 | db: &dyn HirDatabase, |
147 | trait_ref: TraitRef, | 115 | trait_ref: TraitRef, |