aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty')
-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
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
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 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
145const LIFETIME_PLACEHOLDER: PlaceholderIndex = 147const 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.
184fn 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.
203fn 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
180impl ToChalk for Substs { 211impl 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 {}", &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,