aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock91
-rw-r--r--crates/ra_hir_ty/Cargo.toml9
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs71
-rw-r--r--crates/ra_hir_ty/src/tests.rs11
-rw-r--r--crates/ra_hir_ty/src/tests/coercion.rs55
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs132
-rw-r--r--crates/ra_hir_ty/src/traits.rs15
-rw-r--r--crates/ra_hir_ty/src/traits/builtin.rs201
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs77
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/interner.rs15
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/mapping.rs62
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/tls.rs2
-rw-r--r--crates/ra_hir_ty/src/utils.rs32
13 files changed, 420 insertions, 353 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d6635640f..66ae19b1e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -34,6 +34,15 @@ dependencies = [
34] 34]
35 35
36[[package]] 36[[package]]
37name = "ansi_term"
38version = "0.12.1"
39source = "registry+https://github.com/rust-lang/crates.io-index"
40checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
41dependencies = [
42 "winapi 0.3.9",
43]
44
45[[package]]
37name = "anyhow" 46name = "anyhow"
38version = "1.0.31" 47version = "1.0.31"
39source = "registry+https://github.com/rust-lang/crates.io-index" 48source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -52,6 +61,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
52checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" 61checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
53 62
54[[package]] 63[[package]]
64name = "atty"
65version = "0.2.14"
66source = "registry+https://github.com/rust-lang/crates.io-index"
67checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
68dependencies = [
69 "hermit-abi",
70 "libc",
71 "winapi 0.3.9",
72]
73
74[[package]]
55name = "autocfg" 75name = "autocfg"
56version = "1.0.0" 76version = "1.0.0"
57source = "registry+https://github.com/rust-lang/crates.io-index" 77source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -124,9 +144,9 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
124 144
125[[package]] 145[[package]]
126name = "chalk-derive" 146name = "chalk-derive"
127version = "0.15.0" 147version = "0.17.0"
128source = "registry+https://github.com/rust-lang/crates.io-index" 148source = "registry+https://github.com/rust-lang/crates.io-index"
129checksum = "c7379caa72d04103fcfd9bde5642b816f58e3ffd6a0d39347e9e35a066648226" 149checksum = "9396f12a23b1a40d5019aa81bc0cbd7ccd2c9736d6bc4afc95868533c2346dcb"
130dependencies = [ 150dependencies = [
131 "proc-macro2", 151 "proc-macro2",
132 "quote", 152 "quote",
@@ -135,35 +155,35 @@ dependencies = [
135] 155]
136 156
137[[package]] 157[[package]]
138name = "chalk-engine" 158name = "chalk-ir"
139version = "0.15.0" 159version = "0.17.0"
140source = "registry+https://github.com/rust-lang/crates.io-index" 160source = "registry+https://github.com/rust-lang/crates.io-index"
141checksum = "8e8afe48b5663504b485791ab4fae69cf4864869a71ceec9c758fd4d03423722" 161checksum = "87e9c67d500717d65ede27affb7ae40efe240d86fbefff1006fe0ffb62d4caf9"
142dependencies = [ 162dependencies = [
143 "chalk-derive", 163 "chalk-derive",
144 "chalk-ir", 164 "lazy_static",
145 "rustc-hash",
146 "tracing",
147] 165]
148 166
149[[package]] 167[[package]]
150name = "chalk-ir" 168name = "chalk-recursive"
151version = "0.15.0" 169version = "0.17.0"
152source = "registry+https://github.com/rust-lang/crates.io-index" 170source = "registry+https://github.com/rust-lang/crates.io-index"
153checksum = "231e391a03c1fc45874171d92be9542efedc939bac59d9501ee28b9521feb406" 171checksum = "a8fd2ac0fc06c857b95614d229bbe8ea317d1d94a7e8b9442a3f05c9a2c2d5f4"
154dependencies = [ 172dependencies = [
155 "chalk-derive", 173 "chalk-derive",
156 "lazy_static", 174 "chalk-ir",
175 "chalk-solve",
176 "rustc-hash",
177 "tracing",
157] 178]
158 179
159[[package]] 180[[package]]
160name = "chalk-solve" 181name = "chalk-solve"
161version = "0.15.0" 182version = "0.17.0"
162source = "registry+https://github.com/rust-lang/crates.io-index" 183source = "registry+https://github.com/rust-lang/crates.io-index"
163checksum = "72c969c0fd06ad50538253327ca3445ff02cc9d0209f94c3cbf198ad9d365b48" 184checksum = "2a79166f2405c1e51eadcc1344f5ee833c7b391532dd78f64a0731a9a123cc58"
164dependencies = [ 185dependencies = [
165 "chalk-derive", 186 "chalk-derive",
166 "chalk-engine",
167 "chalk-ir", 187 "chalk-ir",
168 "ena", 188 "ena",
169 "itertools", 189 "itertools",
@@ -171,6 +191,7 @@ dependencies = [
171 "rustc-hash", 191 "rustc-hash",
172 "tracing", 192 "tracing",
173 "tracing-subscriber", 193 "tracing-subscriber",
194 "tracing-tree",
174] 195]
175 196
176[[package]] 197[[package]]
@@ -972,6 +993,16 @@ dependencies = [
972] 993]
973 994
974[[package]] 995[[package]]
996name = "quanta"
997version = "0.3.1"
998source = "registry+https://github.com/rust-lang/crates.io-index"
999checksum = "f4f7a1905379198075914bc93d32a5465c40474f90a078bb13439cb00c547bcc"
1000dependencies = [
1001 "libc",
1002 "winapi 0.3.9",
1003]
1004
1005[[package]]
975name = "quote" 1006name = "quote"
976version = "1.0.7" 1007version = "1.0.7"
977source = "registry+https://github.com/rust-lang/crates.io-index" 1008source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1103,6 +1134,7 @@ version = "0.1.0"
1103dependencies = [ 1134dependencies = [
1104 "arrayvec", 1135 "arrayvec",
1105 "chalk-ir", 1136 "chalk-ir",
1137 "chalk-recursive",
1106 "chalk-solve", 1138 "chalk-solve",
1107 "ena", 1139 "ena",
1108 "expect", 1140 "expect",
@@ -1120,6 +1152,9 @@ dependencies = [
1120 "smallvec", 1152 "smallvec",
1121 "stdx", 1153 "stdx",
1122 "test_utils", 1154 "test_utils",
1155 "tracing",
1156 "tracing-subscriber",
1157 "tracing-tree",
1123] 1158]
1124 1159
1125[[package]] 1160[[package]]
@@ -1723,6 +1758,15 @@ dependencies = [
1723] 1758]
1724 1759
1725[[package]] 1760[[package]]
1761name = "termcolor"
1762version = "1.1.0"
1763source = "registry+https://github.com/rust-lang/crates.io-index"
1764checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
1765dependencies = [
1766 "winapi-util",
1767]
1768
1769[[package]]
1726name = "terminal_size" 1770name = "terminal_size"
1727version = "0.1.13" 1771version = "0.1.13"
1728source = "registry+https://github.com/rust-lang/crates.io-index" 1772source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1856,7 +1900,7 @@ version = "0.2.7"
1856source = "registry+https://github.com/rust-lang/crates.io-index" 1900source = "registry+https://github.com/rust-lang/crates.io-index"
1857checksum = "c72c8cf3ec4ed69fef614d011a5ae4274537a8a8c59133558029bd731eb71659" 1901checksum = "c72c8cf3ec4ed69fef614d011a5ae4274537a8a8c59133558029bd731eb71659"
1858dependencies = [ 1902dependencies = [
1859 "ansi_term", 1903 "ansi_term 0.11.0",
1860 "chrono", 1904 "chrono",
1861 "lazy_static", 1905 "lazy_static",
1862 "matchers", 1906 "matchers",
@@ -1871,6 +1915,21 @@ dependencies = [
1871] 1915]
1872 1916
1873[[package]] 1917[[package]]
1918name = "tracing-tree"
1919version = "0.1.3"
1920source = "registry+https://github.com/rust-lang/crates.io-index"
1921checksum = "e0a389731c9e6c56fef11e438e5b6afae861d5bc301c8b4bdca8d19f0e830d82"
1922dependencies = [
1923 "ansi_term 0.12.1",
1924 "atty",
1925 "chrono",
1926 "quanta",
1927 "termcolor",
1928 "tracing",
1929 "tracing-subscriber",
1930]
1931
1932[[package]]
1874name = "unicode-bidi" 1933name = "unicode-bidi"
1875version = "0.3.4" 1934version = "0.3.4"
1876source = "registry+https://github.com/rust-lang/crates.io-index" 1935source = "registry+https://github.com/rust-lang/crates.io-index"
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
28scoped-tls = "1" 28scoped-tls = "1"
29 29
30chalk-solve = { version = "0.15.0" } 30chalk-solve = { version = "0.17.0" }
31chalk-ir = { version = "0.15.0" } 31chalk-ir = { version = "0.17.0" }
32chalk-recursive = { version = "0.17.0" }
32 33
33[dev-dependencies] 34[dev-dependencies]
34insta = "0.16.0" 35insta = "0.16.0"
35expect = { path = "../expect" } 36expect = { path = "../expect" }
37
38tracing = "0.1"
39tracing-subscriber = { version = "0.2", default-features = false, features = ["env-filter", "registry"] }
40tracing-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
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use hir_def::{ 8use 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};
12use hir_expand::name::Name; 14use hir_expand::name::Name;
13use ra_db::CrateId; 15use ra_db::CrateId;
@@ -16,9 +18,12 @@ use rustc_hash::{FxHashMap, FxHashSet};
16 18
17use super::Substs; 19use super::Substs;
18use crate::{ 20use 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
47pub(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
98pub(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)]
44pub struct TraitImpls { 105pub 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
40fn 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
40fn check_types(ra_fixture: &str) { 49fn 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
48fn check_types_impl(ra_fixture: &str, display_source: bool) { 57fn 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
88fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { 98fn 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]
665fn coerce_unsize_trait_object() { 665fn coerce_unsize_trait_object_simple() {
666 assert_snapshot!(
667 infer_with_mismatches(r#"
668#[lang = "sized"]
669pub trait Sized {}
670#[lang = "unsize"]
671pub trait Unsize<T> {}
672#[lang = "coerce_unsized"]
673pub trait CoerceUnsized<T> {}
674
675impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
676
677trait Foo<T, U> {}
678trait Bar<U, T, X>: Foo<T, U> {}
679trait Baz<T, X>: Bar<usize, T, X> {}
680
681struct S<T, X>;
682impl<T, X> Foo<T, usize> for S<T, X> {}
683impl<T, X> Bar<usize, T, X> for S<T, X> {}
684impl<T, X> Baz<T, X> for S<T, X> {}
685
686fn 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]
711fn 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
736fn test() { 782fn 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]
1995fn fn_item_fn_trait() {
1996 check_types(
1997 r#"
1998#[lang = "fn_once"]
1999trait FnOnce<Args> {
2000 type Output;
2001}
2002
2003struct S;
2004
2005fn foo() -> S {}
2006
2007fn takes_closure<U, F: FnOnce() -> U>(f: F) -> U { f() }
2008
2009fn test() {
2010 takes_closure(foo);
2011} //^^^^^^^^^^^^^^^^^^ S
2012"#,
2013 );
2014}
2015
2016#[test]
1995fn unselected_projection_in_trait_env_1() { 2017fn 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]
3002fn infer_dyn_fn_output() { 3024fn 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 3028pub 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> { 3034pub 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> { 3038fn 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 3047fn infer_dyn_fn_once_output() {
3037 } 3048 check_types(
3038 } 3049 r#"
3050#[lang = "fn_once"]
3051pub trait FnOnce<Args> {
3052 type Output;
3053 extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
3054}
3039 3055
3040 fn foo() { 3056fn 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]
3070fn variable_kinds() { 3065fn variable_kinds_1() {
3071 check_types( 3066 check_types(
3072 r#" 3067 r#"
3073trait Trait<T> { fn get(self, t: T) -> T; } 3068trait Trait<T> { fn get(self, t: T) -> T; }
@@ -3083,3 +3078,20 @@ fn test() {
3083 "#, 3078 "#,
3084 ); 3079 );
3085} 3080}
3081
3082#[test]
3083fn variable_kinds_2() {
3084 check_types(
3085 r#"
3086trait Trait { fn get(self) -> Self; }
3087impl Trait for u128 {}
3088impl Trait for f32 {}
3089fn 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 @@
2use std::sync::Arc; 2use std::sync::Arc;
3 3
4use chalk_ir::cast::Cast; 4use chalk_ir::cast::Cast;
5use chalk_solve::Solver;
5use hir_def::{ 6use 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
35fn create_chalk_solver() -> chalk_solve::Solver<Interner> { 36fn 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`.
3use hir_def::{expr::Expr, lang_item::LangItemTarget, TraitId, TypeAliasId}; 3use hir_def::{expr::Expr, TraitId, TypeAliasId};
4use hir_expand::name::name; 4use hir_expand::name::name;
5use ra_db::CrateId; 5use ra_db::CrateId;
6 6
7use super::{AssocTyValue, Impl, UnsizeToSuperTraitObjectData}; 7use super::{AssocTyValue, Impl};
8use crate::{ 8use 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
15pub(super) struct BuiltinImplData { 12pub(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
62fn 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
98pub(super) fn impl_datum(db: &dyn HirDatabase, krate: CrateId, impl_: Impl) -> BuiltinImplData { 52pub(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
233fn 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
243fn 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
269fn 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
302fn 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(&current_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
365fn 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
4use log::debug; 4use log::debug;
5 5
6use chalk_ir::{fold::shift::Shift, GenericArg, TypeName}; 6use chalk_ir::{fold::shift::Shift, CanonicalVarKinds, GenericArg, TypeName};
7use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait}; 7use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait};
8 8
9use hir_def::{ 9use hir_def::{
@@ -14,7 +14,10 @@ use ra_db::{salsa::InternKey, CrateId};
14 14
15use super::{builtin, AssocTyValue, ChalkContext, Impl}; 15use super::{builtin, AssocTyValue, ChalkContext, Impl};
16use crate::{ 16use 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};
20use mapping::{convert_where_clauses, generic_predicate_to_inline_bound, make_binders}; 23use 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
224pub(crate) fn program_clauses_for_chalk_env_query( 265pub(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
354impl chalk_ir::interner::HasInterner for Interner { 369impl 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 433d6aa03..7dc9ee759 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);
@@ -138,7 +140,7 @@ impl ToChalk for Ty {
138 } 140 }
139} 141}
140 142
141const LIFETIME_PLACEHOLDER: PlaceholderIndex = 143const FAKE_PLACEHOLDER: PlaceholderIndex =
142 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::MAX }; 144 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::MAX };
143 145
144/// We currently don't model lifetimes, but Chalk does. So, we have to insert a 146/// We currently don't model lifetimes, but Chalk does. So, we have to insert a
@@ -149,10 +151,10 @@ fn ref_to_chalk(
149 subst: Substs, 151 subst: Substs,
150) -> chalk_ir::Ty<Interner> { 152) -> chalk_ir::Ty<Interner> {
151 let arg = subst[0].clone().to_chalk(db); 153 let arg = subst[0].clone().to_chalk(db);
152 let lifetime = LIFETIME_PLACEHOLDER.to_lifetime(&Interner); 154 let lifetime = FAKE_PLACEHOLDER.to_lifetime(&Interner);
153 chalk_ir::ApplicationTy { 155 chalk_ir::ApplicationTy {
154 name: TypeName::Ref(mutability.to_chalk(db)), 156 name: TypeName::Ref(mutability.to_chalk(db)),
155 substitution: chalk_ir::Substitution::from( 157 substitution: chalk_ir::Substitution::from_iter(
156 &Interner, 158 &Interner,
157 vec![lifetime.cast(&Interner), arg.cast(&Interner)], 159 vec![lifetime.cast(&Interner), arg.cast(&Interner)],
158 ), 160 ),
@@ -173,11 +175,40 @@ fn ref_from_chalk(
173 Ty::apply(TypeCtor::Ref(from_chalk(db, mutability)), Substs(tys)) 175 Ty::apply(TypeCtor::Ref(from_chalk(db, mutability)), Substs(tys))
174} 176}
175 177
178/// We currently don't model constants, but Chalk does. So, we have to insert a
179/// fake constant here, because Chalks built-in logic may expect it to be there.
180fn array_to_chalk(db: &dyn HirDatabase, subst: Substs) -> chalk_ir::Ty<Interner> {
181 let arg = subst[0].clone().to_chalk(db);
182 let usize_ty = chalk_ir::ApplicationTy {
183 name: TypeName::Scalar(Scalar::Uint(chalk_ir::UintTy::Usize)),
184 substitution: chalk_ir::Substitution::empty(&Interner),
185 }
186 .intern(&Interner);
187 let const_ = FAKE_PLACEHOLDER.to_const(&Interner, usize_ty);
188 chalk_ir::ApplicationTy {
189 name: TypeName::Array,
190 substitution: chalk_ir::Substitution::from_iter(
191 &Interner,
192 vec![arg.cast(&Interner), const_.cast(&Interner)],
193 ),
194 }
195 .intern(&Interner)
196}
197
198/// Here we remove the const from the type we got from Chalk.
199fn array_from_chalk(db: &dyn HirDatabase, subst: chalk_ir::Substitution<Interner>) -> Ty {
200 let tys = subst
201 .iter(&Interner)
202 .filter_map(|p| Some(from_chalk(db, p.ty(&Interner)?.clone())))
203 .collect();
204 Ty::apply(TypeCtor::Array, Substs(tys))
205}
206
176impl ToChalk for Substs { 207impl ToChalk for Substs {
177 type Chalk = chalk_ir::Substitution<Interner>; 208 type Chalk = chalk_ir::Substitution<Interner>;
178 209
179 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Substitution<Interner> { 210 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Substitution<Interner> {
180 chalk_ir::Substitution::from(&Interner, self.iter().map(|ty| ty.clone().to_chalk(db))) 211 chalk_ir::Substitution::from_iter(&Interner, self.iter().map(|ty| ty.clone().to_chalk(db)))
181 } 212 }
182 213
183 fn from_chalk(db: &dyn HirDatabase, parameters: chalk_ir::Substitution<Interner>) -> Substs { 214 fn from_chalk(db: &dyn HirDatabase, parameters: chalk_ir::Substitution<Interner>) -> Substs {
@@ -263,6 +294,7 @@ impl ToChalk for TypeCtor {
263 TypeCtor::Tuple { cardinality } => TypeName::Tuple(cardinality.into()), 294 TypeCtor::Tuple { cardinality } => TypeName::Tuple(cardinality.into()),
264 TypeCtor::RawPtr(mutability) => TypeName::Raw(mutability.to_chalk(db)), 295 TypeCtor::RawPtr(mutability) => TypeName::Raw(mutability.to_chalk(db)),
265 TypeCtor::Slice => TypeName::Slice, 296 TypeCtor::Slice => TypeName::Slice,
297 TypeCtor::Array => TypeName::Array,
266 TypeCtor::Ref(mutability) => TypeName::Ref(mutability.to_chalk(db)), 298 TypeCtor::Ref(mutability) => TypeName::Ref(mutability.to_chalk(db)),
267 TypeCtor::Str => TypeName::Str, 299 TypeCtor::Str => TypeName::Str,
268 TypeCtor::FnDef(callable_def) => { 300 TypeCtor::FnDef(callable_def) => {
@@ -271,10 +303,8 @@ impl ToChalk for TypeCtor {
271 } 303 }
272 TypeCtor::Never => TypeName::Never, 304 TypeCtor::Never => TypeName::Never,
273 305
274 TypeCtor::Adt(_) 306 // FIXME convert these
275 | TypeCtor::Array 307 TypeCtor::Adt(_) | TypeCtor::FnPtr { .. } | TypeCtor::Closure { .. } => {
276 | TypeCtor::FnPtr { .. }
277 | TypeCtor::Closure { .. } => {
278 // other TypeCtors get interned and turned into a chalk StructId 308 // other TypeCtors get interned and turned into a chalk StructId
279 let struct_id = db.intern_type_ctor(self).into(); 309 let struct_id = db.intern_type_ctor(self).into();
280 TypeName::Adt(struct_id) 310 TypeName::Adt(struct_id)
@@ -492,6 +522,11 @@ impl ToChalk for GenericPredicate {
492 // we shouldn't get these from Chalk 522 // we shouldn't get these from Chalk
493 panic!("encountered LifetimeOutlives from Chalk") 523 panic!("encountered LifetimeOutlives from Chalk")
494 } 524 }
525
526 chalk_ir::WhereClause::TypeOutlives(_) => {
527 // we shouldn't get these from Chalk
528 panic!("encountered TypeOutlives from Chalk")
529 }
495 } 530 }
496 } 531 }
497} 532}
@@ -570,7 +605,10 @@ where
570 ) 605 )
571 }); 606 });
572 let value = self.value.to_chalk(db); 607 let value = self.value.to_chalk(db);
573 chalk_ir::Canonical { value, binders: chalk_ir::CanonicalVarKinds::from(&Interner, kinds) } 608 chalk_ir::Canonical {
609 value,
610 binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds),
611 }
574 } 612 }
575 613
576 fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { 614 fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> {
@@ -691,7 +729,7 @@ where
691 T: HasInterner<Interner = Interner>, 729 T: HasInterner<Interner = Interner>,
692{ 730{
693 chalk_ir::Binders::new( 731 chalk_ir::Binders::new(
694 chalk_ir::VariableKinds::from( 732 chalk_ir::VariableKinds::from_iter(
695 &Interner, 733 &Interner,
696 std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General)).take(num_vars), 734 std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyKind::General)).take(num_vars),
697 ), 735 ),
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 {}", &params[0], trait_data.name,)?; 161 write!(fmt, "<{:?} as {}", &params[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.
115pub(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
145pub(super) fn associated_type_by_name_including_super_traits( 113pub(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,