aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_assists/src/assist_ctx.rs2
-rw-r--r--crates/ra_assists/src/assists/add_missing_impl_members.rs131
-rw-r--r--crates/ra_assists/src/doc_tests/generated.rs22
-rw-r--r--crates/ra_hir/src/code_model.rs11
-rw-r--r--crates/ra_hir_def/src/data.rs21
-rw-r--r--crates/ra_hir_def/src/path.rs8
-rw-r--r--crates/ra_hir_ty/Cargo.toml7
-rw-r--r--crates/ra_hir_ty/src/db.rs35
-rw-r--r--crates/ra_hir_ty/src/infer.rs23
-rw-r--r--crates/ra_hir_ty/src/tests/method_resolution.rs4
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs74
-rw-r--r--crates/ra_hir_ty/src/traits.rs24
-rw-r--r--crates/ra_hir_ty/src/traits/builtin.rs49
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs468
-rw-r--r--crates/ra_lsp_server/Cargo.toml2
-rw-r--r--crates/ra_lsp_server/src/caps.rs1
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs4
17 files changed, 578 insertions, 308 deletions
diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs
index 993aebc47..28152f724 100644
--- a/crates/ra_assists/src/assist_ctx.rs
+++ b/crates/ra_assists/src/assist_ctx.rs
@@ -46,7 +46,7 @@ pub(crate) enum Assist {
46/// 46///
47/// Note, however, that we don't actually use such two-phase logic at the 47/// Note, however, that we don't actually use such two-phase logic at the
48/// moment, because the LSP API is pretty awkward in this place, and it's much 48/// moment, because the LSP API is pretty awkward in this place, and it's much
49/// easier to just compute the edit eagerly :-)#[derive(Debug, Clone)] 49/// easier to just compute the edit eagerly :-)
50#[derive(Debug)] 50#[derive(Debug)]
51pub(crate) struct AssistCtx<'a, DB> { 51pub(crate) struct AssistCtx<'a, DB> {
52 pub(crate) db: &'a DB, 52 pub(crate) db: &'a DB,
diff --git a/crates/ra_assists/src/assists/add_missing_impl_members.rs b/crates/ra_assists/src/assists/add_missing_impl_members.rs
index cef669cb5..bc49e71fe 100644
--- a/crates/ra_assists/src/assists/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/assists/add_missing_impl_members.rs
@@ -1,3 +1,5 @@
1use std::collections::HashMap;
2
1use hir::{db::HirDatabase, HasSource}; 3use hir::{db::HirDatabase, HasSource};
2use ra_syntax::{ 4use ra_syntax::{
3 ast::{self, edit, make, AstNode, NameOwner}, 5 ast::{self, edit, make, AstNode, NameOwner},
@@ -17,26 +19,26 @@ enum AddMissingImplMembersMode {
17// Adds scaffold for required impl members. 19// Adds scaffold for required impl members.
18// 20//
19// ``` 21// ```
20// trait T { 22// trait Trait<T> {
21// Type X; 23// Type X;
22// fn foo(&self); 24// fn foo(&self) -> T;
23// fn bar(&self) {} 25// fn bar(&self) {}
24// } 26// }
25// 27//
26// impl T for () {<|> 28// impl Trait<u32> for () {<|>
27// 29//
28// } 30// }
29// ``` 31// ```
30// -> 32// ->
31// ``` 33// ```
32// trait T { 34// trait Trait<T> {
33// Type X; 35// Type X;
34// fn foo(&self); 36// fn foo(&self) -> T;
35// fn bar(&self) {} 37// fn bar(&self) {}
36// } 38// }
37// 39//
38// impl T for () { 40// impl Trait<u32> for () {
39// fn foo(&self) { unimplemented!() } 41// fn foo(&self) -> u32 { unimplemented!() }
40// 42//
41// } 43// }
42// ``` 44// ```
@@ -54,13 +56,13 @@ pub(crate) fn add_missing_impl_members(ctx: AssistCtx<impl HirDatabase>) -> Opti
54// Adds scaffold for overriding default impl members. 56// Adds scaffold for overriding default impl members.
55// 57//
56// ``` 58// ```
57// trait T { 59// trait Trait {
58// Type X; 60// Type X;
59// fn foo(&self); 61// fn foo(&self);
60// fn bar(&self) {} 62// fn bar(&self) {}
61// } 63// }
62// 64//
63// impl T for () { 65// impl Trait for () {
64// Type X = (); 66// Type X = ();
65// fn foo(&self) {}<|> 67// fn foo(&self) {}<|>
66// 68//
@@ -68,13 +70,13 @@ pub(crate) fn add_missing_impl_members(ctx: AssistCtx<impl HirDatabase>) -> Opti
68// ``` 70// ```
69// -> 71// ->
70// ``` 72// ```
71// trait T { 73// trait Trait {
72// Type X; 74// Type X;
73// fn foo(&self); 75// fn foo(&self);
74// fn bar(&self) {} 76// fn bar(&self) {}
75// } 77// }
76// 78//
77// impl T for () { 79// impl Trait for () {
78// Type X = (); 80// Type X = ();
79// fn foo(&self) {} 81// fn foo(&self) {}
80// fn bar(&self) {} 82// fn bar(&self) {}
@@ -99,7 +101,7 @@ fn add_missing_impl_members_inner(
99 let impl_node = ctx.find_node_at_offset::<ast::ImplBlock>()?; 101 let impl_node = ctx.find_node_at_offset::<ast::ImplBlock>()?;
100 let impl_item_list = impl_node.item_list()?; 102 let impl_item_list = impl_node.item_list()?;
101 103
102 let trait_def = { 104 let (trait_, trait_def) = {
103 let analyzer = ctx.source_analyzer(impl_node.syntax(), None); 105 let analyzer = ctx.source_analyzer(impl_node.syntax(), None);
104 106
105 resolve_target_trait_def(ctx.db, &analyzer, &impl_node)? 107 resolve_target_trait_def(ctx.db, &analyzer, &impl_node)?
@@ -132,10 +134,25 @@ fn add_missing_impl_members_inner(
132 return None; 134 return None;
133 } 135 }
134 136
137 let file_id = ctx.frange.file_id;
138 let db = ctx.db;
139
135 ctx.add_assist(AssistId(assist_id), label, |edit| { 140 ctx.add_assist(AssistId(assist_id), label, |edit| {
136 let n_existing_items = impl_item_list.impl_items().count(); 141 let n_existing_items = impl_item_list.impl_items().count();
142 let substs = get_syntactic_substs(impl_node).unwrap_or_default();
143 let generic_def: hir::GenericDef = trait_.into();
144 let substs_by_param: HashMap<_, _> = generic_def
145 .params(db)
146 .into_iter()
147 // this is a trait impl, so we need to skip the first type parameter -- this is a bit hacky
148 .skip(1)
149 .zip(substs.into_iter())
150 .collect();
137 let items = missing_items 151 let items = missing_items
138 .into_iter() 152 .into_iter()
153 .map(|it| {
154 substitute_type_params(db, hir::InFile::new(file_id.into(), it), &substs_by_param)
155 })
139 .map(|it| match it { 156 .map(|it| match it {
140 ast::ImplItem::FnDef(def) => ast::ImplItem::FnDef(add_body(def)), 157 ast::ImplItem::FnDef(def) => ast::ImplItem::FnDef(add_body(def)),
141 _ => it, 158 _ => it,
@@ -160,13 +177,63 @@ fn add_body(fn_def: ast::FnDef) -> ast::FnDef {
160 } 177 }
161} 178}
162 179
180// FIXME: It would probably be nicer if we could get this via HIR (i.e. get the
181// trait ref, and then go from the types in the substs back to the syntax)
182// FIXME: This should be a general utility (not even just for assists)
183fn get_syntactic_substs(impl_block: ast::ImplBlock) -> Option<Vec<ast::TypeRef>> {
184 let target_trait = impl_block.target_trait()?;
185 let path_type = match target_trait {
186 ast::TypeRef::PathType(path) => path,
187 _ => return None,
188 };
189 let type_arg_list = path_type.path()?.segment()?.type_arg_list()?;
190 let mut result = Vec::new();
191 for type_arg in type_arg_list.type_args() {
192 let type_arg: ast::TypeArg = type_arg;
193 result.push(type_arg.type_ref()?);
194 }
195 Some(result)
196}
197
198// FIXME: This should be a general utility (not even just for assists)
199fn substitute_type_params<N: AstNode>(
200 db: &impl HirDatabase,
201 node: hir::InFile<N>,
202 substs: &HashMap<hir::TypeParam, ast::TypeRef>,
203) -> N {
204 let type_param_replacements = node
205 .value
206 .syntax()
207 .descendants()
208 .filter_map(ast::TypeRef::cast)
209 .filter_map(|n| {
210 let path = match &n {
211 ast::TypeRef::PathType(path_type) => path_type.path()?,
212 _ => return None,
213 };
214 let analyzer = hir::SourceAnalyzer::new(db, node.with_value(n.syntax()), None);
215 let resolution = analyzer.resolve_path(db, &path)?;
216 match resolution {
217 hir::PathResolution::TypeParam(tp) => Some((n, substs.get(&tp)?.clone())),
218 _ => None,
219 }
220 })
221 .collect::<Vec<_>>();
222
223 if type_param_replacements.is_empty() {
224 node.value
225 } else {
226 edit::replace_descendants(&node.value, type_param_replacements.into_iter())
227 }
228}
229
163/// Given an `ast::ImplBlock`, resolves the target trait (the one being 230/// Given an `ast::ImplBlock`, resolves the target trait (the one being
164/// implemented) to a `ast::TraitDef`. 231/// implemented) to a `ast::TraitDef`.
165fn resolve_target_trait_def( 232fn resolve_target_trait_def(
166 db: &impl HirDatabase, 233 db: &impl HirDatabase,
167 analyzer: &hir::SourceAnalyzer, 234 analyzer: &hir::SourceAnalyzer,
168 impl_block: &ast::ImplBlock, 235 impl_block: &ast::ImplBlock,
169) -> Option<ast::TraitDef> { 236) -> Option<(hir::Trait, ast::TraitDef)> {
170 let ast_path = impl_block 237 let ast_path = impl_block
171 .target_trait() 238 .target_trait()
172 .map(|it| it.syntax().clone()) 239 .map(|it| it.syntax().clone())
@@ -174,7 +241,9 @@ fn resolve_target_trait_def(
174 .path()?; 241 .path()?;
175 242
176 match analyzer.resolve_path(db, &ast_path) { 243 match analyzer.resolve_path(db, &ast_path) {
177 Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def.source(db).value), 244 Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => {
245 Some((def, def.source(db).value))
246 }
178 _ => None, 247 _ => None,
179 } 248 }
180} 249}
@@ -281,6 +350,40 @@ impl Foo for S {
281 } 350 }
282 351
283 #[test] 352 #[test]
353 fn fill_in_type_params_1() {
354 check_assist(
355 add_missing_impl_members,
356 "
357trait Foo<T> { fn foo(&self, t: T) -> &T; }
358struct S;
359impl Foo<u32> for S { <|> }",
360 "
361trait Foo<T> { fn foo(&self, t: T) -> &T; }
362struct S;
363impl Foo<u32> for S {
364 <|>fn foo(&self, t: u32) -> &u32 { unimplemented!() }
365}",
366 );
367 }
368
369 #[test]
370 fn fill_in_type_params_2() {
371 check_assist(
372 add_missing_impl_members,
373 "
374trait Foo<T> { fn foo(&self, t: T) -> &T; }
375struct S;
376impl<U> Foo<U> for S { <|> }",
377 "
378trait Foo<T> { fn foo(&self, t: T) -> &T; }
379struct S;
380impl<U> Foo<U> for S {
381 <|>fn foo(&self, t: U) -> &U { unimplemented!() }
382}",
383 );
384 }
385
386 #[test]
284 fn test_cursor_after_empty_impl_block() { 387 fn test_cursor_after_empty_impl_block() {
285 check_assist( 388 check_assist(
286 add_missing_impl_members, 389 add_missing_impl_members,
diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs
index 4586eeb59..7d84dc8fb 100644
--- a/crates/ra_assists/src/doc_tests/generated.rs
+++ b/crates/ra_assists/src/doc_tests/generated.rs
@@ -101,26 +101,26 @@ fn doctest_add_impl_default_members() {
101 check( 101 check(
102 "add_impl_default_members", 102 "add_impl_default_members",
103 r#####" 103 r#####"
104trait T { 104trait Trait {
105 Type X; 105 Type X;
106 fn foo(&self); 106 fn foo(&self);
107 fn bar(&self) {} 107 fn bar(&self) {}
108} 108}
109 109
110impl T for () { 110impl Trait for () {
111 Type X = (); 111 Type X = ();
112 fn foo(&self) {}<|> 112 fn foo(&self) {}<|>
113 113
114} 114}
115"#####, 115"#####,
116 r#####" 116 r#####"
117trait T { 117trait Trait {
118 Type X; 118 Type X;
119 fn foo(&self); 119 fn foo(&self);
120 fn bar(&self) {} 120 fn bar(&self) {}
121} 121}
122 122
123impl T for () { 123impl Trait for () {
124 Type X = (); 124 Type X = ();
125 fn foo(&self) {} 125 fn foo(&self) {}
126 fn bar(&self) {} 126 fn bar(&self) {}
@@ -135,25 +135,25 @@ fn doctest_add_impl_missing_members() {
135 check( 135 check(
136 "add_impl_missing_members", 136 "add_impl_missing_members",
137 r#####" 137 r#####"
138trait T { 138trait Trait<T> {
139 Type X; 139 Type X;
140 fn foo(&self); 140 fn foo(&self) -> T;
141 fn bar(&self) {} 141 fn bar(&self) {}
142} 142}
143 143
144impl T for () {<|> 144impl Trait<u32> for () {<|>
145 145
146} 146}
147"#####, 147"#####,
148 r#####" 148 r#####"
149trait T { 149trait Trait<T> {
150 Type X; 150 Type X;
151 fn foo(&self); 151 fn foo(&self) -> T;
152 fn bar(&self) {} 152 fn bar(&self) {}
153} 153}
154 154
155impl T for () { 155impl Trait<u32> for () {
156 fn foo(&self) { unimplemented!() } 156 fn foo(&self) -> u32 { unimplemented!() }
157 157
158} 158}
159"#####, 159"#####,
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index bcfc0d03e..76d8f85f1 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -644,6 +644,17 @@ impl_froms!(
644 Const 644 Const
645); 645);
646 646
647impl GenericDef {
648 pub fn params(self, db: &impl HirDatabase) -> Vec<TypeParam> {
649 let generics: Arc<hir_def::generics::GenericParams> = db.generic_params(self.into());
650 generics
651 .types
652 .iter()
653 .map(|(local_id, _)| TypeParam { id: TypeParamId { parent: self.into(), local_id } })
654 .collect()
655 }
656}
657
647#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 658#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
648pub struct Local { 659pub struct Local {
649 pub(crate) parent: DefWithBody, 660 pub(crate) parent: DefWithBody,
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index 1aa9a9b7d..c900a6a18 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -10,8 +10,9 @@ use ra_syntax::ast::{self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAs
10 10
11use crate::{ 11use crate::{
12 db::DefDatabase, 12 db::DefDatabase,
13 path::{path, GenericArgs, Path},
13 src::HasSource, 14 src::HasSource,
14 type_ref::{Mutability, TypeRef}, 15 type_ref::{Mutability, TypeBound, TypeRef},
15 AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule, 16 AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule,
16 ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, 17 ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
17}; 18};
@@ -62,11 +63,29 @@ impl FunctionData {
62 TypeRef::unit() 63 TypeRef::unit()
63 }; 64 };
64 65
66 let ret_type = if src.value.is_async() {
67 let future_impl = desugar_future_path(ret_type);
68 let ty_bound = TypeBound::Path(future_impl);
69 TypeRef::ImplTrait(vec![ty_bound])
70 } else {
71 ret_type
72 };
73
65 let sig = FunctionData { name, params, ret_type, has_self_param }; 74 let sig = FunctionData { name, params, ret_type, has_self_param };
66 Arc::new(sig) 75 Arc::new(sig)
67 } 76 }
68} 77}
69 78
79fn desugar_future_path(orig: TypeRef) -> Path {
80 let path = path![std::future::Future];
81 let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect();
82 let mut last = GenericArgs::empty();
83 last.bindings.push((name![Output], orig));
84 generic_args.push(Some(Arc::new(last)));
85
86 Path::from_known_path(path, generic_args)
87}
88
70#[derive(Debug, Clone, PartialEq, Eq)] 89#[derive(Debug, Clone, PartialEq, Eq)]
71pub struct TypeAliasData { 90pub struct TypeAliasData {
72 pub name: Name, 91 pub name: Name,
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs
index 8e1294201..107d2d799 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -130,6 +130,14 @@ impl Path {
130 Path { type_anchor: None, mod_path: name_ref.as_name().into(), generic_args: vec![None] } 130 Path { type_anchor: None, mod_path: name_ref.as_name().into(), generic_args: vec![None] }
131 } 131 }
132 132
133 /// Converts a known mod path to `Path`.
134 pub(crate) fn from_known_path(
135 path: ModPath,
136 generic_args: Vec<Option<Arc<GenericArgs>>>,
137 ) -> Path {
138 Path { type_anchor: None, mod_path: path, generic_args }
139 }
140
133 pub fn kind(&self) -> &PathKind { 141 pub fn kind(&self) -> &PathKind {
134 &self.mod_path.kind 142 &self.mod_path.kind
135 } 143 }
diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml
index d277bf2bc..60793db44 100644
--- a/crates/ra_hir_ty/Cargo.toml
+++ b/crates/ra_hir_ty/Cargo.toml
@@ -21,10 +21,9 @@ ra_prof = { path = "../ra_prof" }
21ra_syntax = { path = "../ra_syntax" } 21ra_syntax = { path = "../ra_syntax" }
22test_utils = { path = "../test_utils" } 22test_utils = { path = "../test_utils" }
23 23
24# https://github.com/rust-lang/chalk/pull/294 24chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" }
25chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "151949dece8117d180b5d197a7afa968c3ba14bb" } 25chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" }
26chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "151949dece8117d180b5d197a7afa968c3ba14bb" } 26chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" }
27chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "151949dece8117d180b5d197a7afa968c3ba14bb" }
28 27
29lalrpop-intern = "0.15.1" 28lalrpop-intern = "0.15.1"
30 29
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs
index 222a36a9f..d52f65b83 100644
--- a/crates/ra_hir_ty/src/db.rs
+++ b/crates/ra_hir_ty/src/db.rs
@@ -10,7 +10,7 @@ use ra_db::{salsa, CrateId};
10 10
11use crate::{ 11use crate::{
12 method_resolution::CrateImplBlocks, 12 method_resolution::CrateImplBlocks,
13 traits::{AssocTyValue, Impl}, 13 traits::{chalk, AssocTyValue, Impl},
14 CallableDef, FnSig, GenericPredicate, InferenceResult, Substs, TraitRef, Ty, TyDefId, TypeCtor, 14 CallableDef, FnSig, GenericPredicate, InferenceResult, Substs, TraitRef, Ty, TyDefId, TypeCtor,
15 ValueTyDefId, 15 ValueTyDefId,
16}; 16};
@@ -77,39 +77,24 @@ pub trait HirDatabase: DefDatabase {
77 #[salsa::interned] 77 #[salsa::interned]
78 fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> crate::traits::AssocTyValueId; 78 fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> crate::traits::AssocTyValueId;
79 79
80 #[salsa::invoke(crate::traits::chalk::associated_ty_data_query)] 80 #[salsa::invoke(chalk::associated_ty_data_query)]
81 fn associated_ty_data( 81 fn associated_ty_data(&self, id: chalk::AssocTypeId) -> Arc<chalk::AssociatedTyDatum>;
82 &self,
83 id: chalk_ir::TypeId,
84 ) -> Arc<chalk_rust_ir::AssociatedTyDatum<chalk_ir::family::ChalkIr>>;
85 82
86 #[salsa::invoke(crate::traits::chalk::trait_datum_query)] 83 #[salsa::invoke(chalk::trait_datum_query)]
87 fn trait_datum( 84 fn trait_datum(&self, krate: CrateId, trait_id: chalk::TraitId) -> Arc<chalk::TraitDatum>;
88 &self,
89 krate: CrateId,
90 trait_id: chalk_ir::TraitId,
91 ) -> Arc<chalk_rust_ir::TraitDatum<chalk_ir::family::ChalkIr>>;
92 85
93 #[salsa::invoke(crate::traits::chalk::struct_datum_query)] 86 #[salsa::invoke(chalk::struct_datum_query)]
94 fn struct_datum( 87 fn struct_datum(&self, krate: CrateId, struct_id: chalk::StructId) -> Arc<chalk::StructDatum>;
95 &self,
96 krate: CrateId,
97 struct_id: chalk_ir::StructId,
98 ) -> Arc<chalk_rust_ir::StructDatum<chalk_ir::family::ChalkIr>>;
99 88
100 #[salsa::invoke(crate::traits::chalk::impl_datum_query)] 89 #[salsa::invoke(crate::traits::chalk::impl_datum_query)]
101 fn impl_datum( 90 fn impl_datum(&self, krate: CrateId, impl_id: chalk::ImplId) -> Arc<chalk::ImplDatum>;
102 &self,
103 krate: CrateId,
104 impl_id: chalk_ir::ImplId,
105 ) -> Arc<chalk_rust_ir::ImplDatum<chalk_ir::family::ChalkIr>>;
106 91
107 #[salsa::invoke(crate::traits::chalk::associated_ty_value_query)] 92 #[salsa::invoke(crate::traits::chalk::associated_ty_value_query)]
108 fn associated_ty_value( 93 fn associated_ty_value(
109 &self, 94 &self,
110 krate: CrateId, 95 krate: CrateId,
111 id: chalk_rust_ir::AssociatedTyValueId, 96 id: chalk::AssociatedTyValueId,
112 ) -> Arc<chalk_rust_ir::AssociatedTyValue<chalk_ir::family::ChalkIr>>; 97 ) -> Arc<chalk::AssociatedTyValue>;
113 98
114 #[salsa::invoke(crate::traits::trait_solve_query)] 99 #[salsa::invoke(crate::traits::trait_solve_query)]
115 fn trait_solve( 100 fn trait_solve(
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index e97b81473..32c0d07a5 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -37,8 +37,8 @@ use test_utils::tested_by;
37use super::{ 37use super::{
38 primitive::{FloatTy, IntTy}, 38 primitive::{FloatTy, IntTy},
39 traits::{Guidance, Obligation, ProjectionPredicate, Solution}, 39 traits::{Guidance, Obligation, ProjectionPredicate, Solution},
40 ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, 40 ApplicationTy, GenericPredicate, InEnvironment, ProjectionTy, Substs, TraitEnvironment,
41 TypeWalk, Uncertain, 41 TraitRef, Ty, TypeCtor, TypeWalk, Uncertain,
42}; 42};
43use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic}; 43use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic};
44 44
@@ -379,6 +379,25 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
379 ) -> Ty { 379 ) -> Ty {
380 match assoc_ty { 380 match assoc_ty {
381 Some(res_assoc_ty) => { 381 Some(res_assoc_ty) => {
382 // FIXME:
383 // Check if inner_ty is is `impl Trait` and contained input TypeAlias id
384 // this is a workaround while Chalk assoc type projection doesn't always work yet,
385 // but once that is fixed I don't think we should keep this
386 // (we'll probably change how associated types are resolved anyway)
387 if let Ty::Opaque(ref predicates) = inner_ty {
388 for p in predicates.iter() {
389 if let GenericPredicate::Projection(projection) = p {
390 if projection.projection_ty.associated_ty == res_assoc_ty {
391 if let ty_app!(_, params) = &projection.ty {
392 if params.len() == 0 {
393 return projection.ty.clone();
394 }
395 }
396 }
397 }
398 }
399 }
400
382 let ty = self.table.new_type_var(); 401 let ty = self.table.new_type_var();
383 let builder = Substs::build_for_def(self.db, res_assoc_ty) 402 let builder = Substs::build_for_def(self.db, res_assoc_ty)
384 .push(inner_ty) 403 .push(inner_ty)
diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs
index 45164c9e9..ce9a06fde 100644
--- a/crates/ra_hir_ty/src/tests/method_resolution.rs
+++ b/crates/ra_hir_ty/src/tests/method_resolution.rs
@@ -865,7 +865,7 @@ mod foo {
865 865
866#[test] 866#[test]
867fn method_resolution_where_clause_for_unknown_trait() { 867fn method_resolution_where_clause_for_unknown_trait() {
868 // The blanket impl shouldn't apply because we can't even resolve UnknownTrait 868 // The blanket impl currently applies because we ignore the unresolved where clause
869 let t = type_at( 869 let t = type_at(
870 r#" 870 r#"
871//- /main.rs 871//- /main.rs
@@ -875,7 +875,7 @@ impl<T> Trait for T where T: UnknownTrait {}
875fn test() { (&S).foo()<|>; } 875fn test() { (&S).foo()<|>; }
876"#, 876"#,
877 ); 877 );
878 assert_eq!(t, "{unknown}"); 878 assert_eq!(t, "u128");
879} 879}
880 880
881#[test] 881#[test]
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index 76e2198b6..0bc72644a 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -38,6 +38,63 @@ mod future {
38} 38}
39 39
40#[test] 40#[test]
41fn infer_async() {
42 let (db, pos) = TestDB::with_position(
43 r#"
44//- /main.rs crate:main deps:std
45
46async fn foo() -> u64 {
47 128
48}
49
50fn test() {
51 let r = foo();
52 let v = r.await;
53 v<|>;
54}
55
56//- /std.rs crate:std
57#[prelude_import] use future::*;
58mod future {
59 trait Future {
60 type Output;
61 }
62}
63
64"#,
65 );
66 assert_eq!("u64", type_at_pos(&db, pos));
67}
68
69#[test]
70fn infer_desugar_async() {
71 let (db, pos) = TestDB::with_position(
72 r#"
73//- /main.rs crate:main deps:std
74
75async fn foo() -> u64 {
76 128
77}
78
79fn test() {
80 let r = foo();
81 r<|>;
82}
83
84//- /std.rs crate:std
85#[prelude_import] use future::*;
86mod future {
87 trait Future {
88 type Output;
89 }
90}
91
92"#,
93 );
94 assert_eq!("impl Future<Output = u64>", type_at_pos(&db, pos));
95}
96
97#[test]
41fn infer_try() { 98fn infer_try() {
42 let (db, pos) = TestDB::with_position( 99 let (db, pos) = TestDB::with_position(
43 r#" 100 r#"
@@ -959,6 +1016,23 @@ fn test() {
959} 1016}
960 1017
961#[test] 1018#[test]
1019fn error_bound_chalk() {
1020 let t = type_at(
1021 r#"
1022//- /main.rs
1023trait Trait {
1024 fn foo(&self) -> u32 {}
1025}
1026
1027fn test(x: (impl Trait + UnknownTrait)) {
1028 x.foo()<|>;
1029}
1030"#,
1031 );
1032 assert_eq!(t, "u32");
1033}
1034
1035#[test]
962fn assoc_type_bindings() { 1036fn assoc_type_bindings() {
963 assert_snapshot!( 1037 assert_snapshot!(
964 infer(r#" 1038 infer(r#"
diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs
index d49f8fb4b..c4dc857bc 100644
--- a/crates/ra_hir_ty/src/traits.rs
+++ b/crates/ra_hir_ty/src/traits.rs
@@ -1,7 +1,7 @@
1//! Trait solving using Chalk. 1//! Trait solving using Chalk.
2use std::sync::{Arc, Mutex}; 2use std::sync::{Arc, Mutex};
3 3
4use chalk_ir::{cast::Cast, family::ChalkIr}; 4use chalk_ir::cast::Cast;
5use hir_def::{expr::ExprId, DefWithBodyId, ImplId, TraitId, TypeAliasId}; 5use hir_def::{expr::ExprId, DefWithBodyId, ImplId, TraitId, TypeAliasId};
6use log::debug; 6use log::debug;
7use ra_db::{impl_intern_key, salsa, CrateId}; 7use ra_db::{impl_intern_key, salsa, CrateId};
@@ -12,7 +12,7 @@ use crate::db::HirDatabase;
12 12
13use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; 13use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk};
14 14
15use self::chalk::{from_chalk, ToChalk}; 15use self::chalk::{from_chalk, ToChalk, TypeFamily};
16 16
17pub(crate) mod chalk; 17pub(crate) mod chalk;
18mod builtin; 18mod builtin;
@@ -20,7 +20,7 @@ mod builtin;
20#[derive(Debug, Clone)] 20#[derive(Debug, Clone)]
21pub struct TraitSolver { 21pub struct TraitSolver {
22 krate: CrateId, 22 krate: CrateId,
23 inner: Arc<Mutex<chalk_solve::Solver<ChalkIr>>>, 23 inner: Arc<Mutex<chalk_solve::Solver<TypeFamily>>>,
24} 24}
25 25
26/// We need eq for salsa 26/// We need eq for salsa
@@ -36,8 +36,8 @@ impl TraitSolver {
36 fn solve( 36 fn solve(
37 &self, 37 &self,
38 db: &impl HirDatabase, 38 db: &impl HirDatabase,
39 goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal<ChalkIr>>>, 39 goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal<TypeFamily>>>,
40 ) -> Option<chalk_solve::Solution<ChalkIr>> { 40 ) -> Option<chalk_solve::Solution<TypeFamily>> {
41 let context = ChalkContext { db, krate: self.krate }; 41 let context = ChalkContext { db, krate: self.krate };
42 debug!("solve goal: {:?}", goal); 42 debug!("solve goal: {:?}", goal);
43 let mut solver = match self.inner.lock() { 43 let mut solver = match self.inner.lock() {
@@ -201,17 +201,17 @@ pub(crate) fn trait_solve_query(
201 201
202fn solution_from_chalk( 202fn solution_from_chalk(
203 db: &impl HirDatabase, 203 db: &impl HirDatabase,
204 solution: chalk_solve::Solution<ChalkIr>, 204 solution: chalk_solve::Solution<TypeFamily>,
205) -> Solution { 205) -> Solution {
206 let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<ChalkIr>>| { 206 let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<TypeFamily>>| {
207 let value = subst 207 let value = subst
208 .value 208 .value
209 .parameters 209 .parameters
210 .into_iter() 210 .into_iter()
211 .map(|p| { 211 .map(|p| {
212 let ty = match p { 212 let ty = match p.ty() {
213 chalk_ir::Parameter(chalk_ir::ParameterKind::Ty(ty)) => from_chalk(db, ty), 213 Some(ty) => from_chalk(db, ty.clone()),
214 chalk_ir::Parameter(chalk_ir::ParameterKind::Lifetime(_)) => unimplemented!(), 214 None => unimplemented!(),
215 }; 215 };
216 ty 216 ty
217 }) 217 })
@@ -291,7 +291,7 @@ impl FnTrait {
291 } 291 }
292} 292}
293 293
294#[derive(Debug, Clone, PartialEq, Eq, Hash)] 294#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
295pub struct ClosureFnTraitImplData { 295pub struct ClosureFnTraitImplData {
296 def: DefWithBodyId, 296 def: DefWithBodyId,
297 expr: ExprId, 297 expr: ExprId,
@@ -300,7 +300,7 @@ pub struct ClosureFnTraitImplData {
300 300
301/// An impl. Usually this comes from an impl block, but some built-in types get 301/// An impl. Usually this comes from an impl block, but some built-in types get
302/// synthetic impls. 302/// synthetic impls.
303#[derive(Debug, Clone, PartialEq, Eq, Hash)] 303#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
304pub enum Impl { 304pub enum Impl {
305 /// A normal impl from an impl block. 305 /// A normal impl from an impl block.
306 ImplBlock(ImplId), 306 ImplBlock(ImplId),
diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs
index cd587a338..dd41176f0 100644
--- a/crates/ra_hir_ty/src/traits/builtin.rs
+++ b/crates/ra_hir_ty/src/traits/builtin.rs
@@ -28,24 +28,24 @@ pub(super) fn get_builtin_impls(
28 trait_: TraitId, 28 trait_: TraitId,
29 mut callback: impl FnMut(Impl), 29 mut callback: impl FnMut(Impl),
30) { 30) {
31 // Note: since impl_datum needs to be infallible, we need to make sure here
32 // that we have all prerequisites to build the respective impls.
31 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty { 33 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty {
32 for &fn_trait in [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter() 34 for &fn_trait in [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter()
33 { 35 {
34 if let Some(actual_trait) = get_fn_trait(db, krate, fn_trait) { 36 if let Some(actual_trait) = get_fn_trait(db, krate, fn_trait) {
35 if trait_ == actual_trait { 37 if trait_ == actual_trait {
36 let impl_ = super::ClosureFnTraitImplData { def: *def, expr: *expr, fn_trait }; 38 let impl_ = super::ClosureFnTraitImplData { def: *def, expr: *expr, fn_trait };
37 callback(Impl::ClosureFnTraitImpl(impl_)); 39 if check_closure_fn_trait_impl_prerequisites(db, krate, impl_) {
40 callback(Impl::ClosureFnTraitImpl(impl_));
41 }
38 } 42 }
39 } 43 }
40 } 44 }
41 } 45 }
42} 46}
43 47
44pub(super) fn impl_datum( 48pub(super) fn impl_datum(db: &impl HirDatabase, krate: CrateId, impl_: Impl) -> BuiltinImplData {
45 db: &impl HirDatabase,
46 krate: CrateId,
47 impl_: Impl,
48) -> Option<BuiltinImplData> {
49 match impl_ { 49 match impl_ {
50 Impl::ImplBlock(_) => unreachable!(), 50 Impl::ImplBlock(_) => unreachable!(),
51 Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data), 51 Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data),
@@ -65,21 +65,38 @@ pub(super) fn associated_ty_value(
65 } 65 }
66} 66}
67 67
68fn check_closure_fn_trait_impl_prerequisites(
69 db: &impl HirDatabase,
70 krate: CrateId,
71 data: super::ClosureFnTraitImplData,
72) -> bool {
73 // the respective Fn/FnOnce/FnMut trait needs to exist
74 if get_fn_trait(db, krate, data.fn_trait).is_none() {
75 return false;
76 }
77
78 // FIXME: there are more assumptions that we should probably check here:
79 // the traits having no type params, FnOnce being a supertrait
80
81 // the FnOnce trait needs to exist and have an assoc type named Output
82 let fn_once_trait = match get_fn_trait(db, krate, super::FnTrait::FnOnce) {
83 Some(t) => t,
84 None => return false,
85 };
86 db.trait_data(fn_once_trait).associated_type_by_name(&name![Output]).is_some()
87}
88
68fn closure_fn_trait_impl_datum( 89fn closure_fn_trait_impl_datum(
69 db: &impl HirDatabase, 90 db: &impl HirDatabase,
70 krate: CrateId, 91 krate: CrateId,
71 data: super::ClosureFnTraitImplData, 92 data: super::ClosureFnTraitImplData,
72) -> Option<BuiltinImplData> { 93) -> BuiltinImplData {
73 // for some closure |X, Y| -> Z: 94 // for some closure |X, Y| -> Z:
74 // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V } 95 // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V }
75 96
76 let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait 97 let trait_ = get_fn_trait(db, krate, data.fn_trait) // get corresponding fn trait
77 98 // the existence of the Fn trait has been checked before
78 // validate FnOnce trait, since we need it in the assoc ty value definition 99 .expect("fn trait for closure impl missing");
79 // and don't want to return a valid value only to find out later that FnOnce
80 // is broken
81 let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?;
82 let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
83 100
84 let num_args: u16 = match &db.body(data.def.into())[data.expr] { 101 let num_args: u16 = match &db.body(data.def.into())[data.expr] {
85 Expr::Lambda { args, .. } => args.len() as u16, 102 Expr::Lambda { args, .. } => args.len() as u16,
@@ -107,12 +124,12 @@ fn closure_fn_trait_impl_datum(
107 124
108 let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone()); 125 let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone());
109 126
110 Some(BuiltinImplData { 127 BuiltinImplData {
111 num_vars: num_args as usize + 1, 128 num_vars: num_args as usize + 1,
112 trait_ref, 129 trait_ref,
113 where_clauses: Vec::new(), 130 where_clauses: Vec::new(),
114 assoc_ty_values: vec![output_ty_id], 131 assoc_ty_values: vec![output_ty_id],
115 }) 132 }
116} 133}
117 134
118fn closure_fn_trait_output_assoc_ty_value( 135fn closure_fn_trait_output_assoc_ty_value(
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index 5eb032d86..555930c9b 100644
--- a/crates/ra_hir_ty/src/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -1,17 +1,11 @@
1//! Conversion code from/to Chalk. 1//! Conversion code from/to Chalk.
2use std::sync::Arc; 2use std::{fmt, sync::Arc};
3 3
4use log::debug; 4use log::debug;
5 5
6use chalk_ir::{ 6use chalk_ir::{cast::Cast, Parameter, PlaceholderIndex, TypeName, UniverseIndex};
7 cast::Cast, family::ChalkIr, Identifier, Parameter, PlaceholderIndex, TypeId, TypeKindId,
8 TypeName, UniverseIndex,
9};
10use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum};
11 7
12use hir_def::{ 8use hir_def::{AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId};
13 AssocContainerId, AssocItemId, GenericDefId, HasModule, ImplId, Lookup, TraitId, TypeAliasId,
14};
15use ra_db::{ 9use ra_db::{
16 salsa::{InternId, InternKey}, 10 salsa::{InternId, InternKey},
17 CrateId, 11 CrateId,
@@ -23,9 +17,83 @@ use crate::{
23 ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, 17 ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk,
24}; 18};
25 19
26/// This represents a trait whose name we could not resolve. 20#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
27const UNKNOWN_TRAIT: chalk_ir::TraitId = 21pub struct TypeFamily {}
28 chalk_ir::TraitId(chalk_ir::RawId { index: u32::max_value() }); 22
23impl chalk_ir::family::TypeFamily for TypeFamily {
24 type InternedType = Box<chalk_ir::TyData<Self>>;
25 type InternedLifetime = chalk_ir::LifetimeData<Self>;
26 type InternedParameter = chalk_ir::ParameterData<Self>;
27 type DefId = InternId;
28
29 // FIXME: implement these
30 fn debug_struct_id(
31 _type_kind_id: chalk_ir::StructId<Self>,
32 _fmt: &mut fmt::Formatter<'_>,
33 ) -> Option<fmt::Result> {
34 None
35 }
36
37 fn debug_trait_id(
38 _type_kind_id: chalk_ir::TraitId<Self>,
39 _fmt: &mut fmt::Formatter<'_>,
40 ) -> Option<fmt::Result> {
41 None
42 }
43
44 fn debug_assoc_type_id(
45 _id: chalk_ir::AssocTypeId<Self>,
46 _fmt: &mut fmt::Formatter<'_>,
47 ) -> Option<fmt::Result> {
48 None
49 }
50
51 fn debug_projection(
52 _projection: &chalk_ir::ProjectionTy<Self>,
53 _fmt: &mut fmt::Formatter<'_>,
54 ) -> Option<fmt::Result> {
55 None
56 }
57
58 fn intern_ty(ty: chalk_ir::TyData<Self>) -> Box<chalk_ir::TyData<Self>> {
59 Box::new(ty)
60 }
61
62 fn ty_data(ty: &Box<chalk_ir::TyData<Self>>) -> &chalk_ir::TyData<Self> {
63 ty
64 }
65
66 fn intern_lifetime(lifetime: chalk_ir::LifetimeData<Self>) -> chalk_ir::LifetimeData<Self> {
67 lifetime
68 }
69
70 fn lifetime_data(lifetime: &chalk_ir::LifetimeData<Self>) -> &chalk_ir::LifetimeData<Self> {
71 lifetime
72 }
73
74 fn intern_parameter(parameter: chalk_ir::ParameterData<Self>) -> chalk_ir::ParameterData<Self> {
75 parameter
76 }
77
78 fn parameter_data(parameter: &chalk_ir::ParameterData<Self>) -> &chalk_ir::ParameterData<Self> {
79 parameter
80 }
81}
82
83impl chalk_ir::family::HasTypeFamily for TypeFamily {
84 type TypeFamily = Self;
85}
86
87pub type AssocTypeId = chalk_ir::AssocTypeId<TypeFamily>;
88pub type AssociatedTyDatum = chalk_rust_ir::AssociatedTyDatum<TypeFamily>;
89pub type TraitId = chalk_ir::TraitId<TypeFamily>;
90pub type TraitDatum = chalk_rust_ir::TraitDatum<TypeFamily>;
91pub type StructId = chalk_ir::StructId<TypeFamily>;
92pub type StructDatum = chalk_rust_ir::StructDatum<TypeFamily>;
93pub type ImplId = chalk_ir::ImplId<TypeFamily>;
94pub type ImplDatum = chalk_rust_ir::ImplDatum<TypeFamily>;
95pub type AssociatedTyValueId = chalk_rust_ir::AssociatedTyValueId;
96pub type AssociatedTyValue = chalk_rust_ir::AssociatedTyValue<TypeFamily>;
29 97
30pub(super) trait ToChalk { 98pub(super) trait ToChalk {
31 type Chalk; 99 type Chalk;
@@ -41,21 +109,11 @@ where
41} 109}
42 110
43impl ToChalk for Ty { 111impl ToChalk for Ty {
44 type Chalk = chalk_ir::Ty<ChalkIr>; 112 type Chalk = chalk_ir::Ty<TypeFamily>;
45 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty<ChalkIr> { 113 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty<TypeFamily> {
46 match self { 114 match self {
47 Ty::Apply(apply_ty) => { 115 Ty::Apply(apply_ty) => {
48 let name = match apply_ty.ctor { 116 let name = apply_ty.ctor.to_chalk(db);
49 TypeCtor::AssociatedType(type_alias) => {
50 let type_id = type_alias.to_chalk(db);
51 TypeName::AssociatedType(type_id)
52 }
53 _ => {
54 // other TypeCtors get interned and turned into a chalk StructId
55 let struct_id = apply_ty.ctor.to_chalk(db);
56 TypeName::TypeKindId(struct_id.into())
57 }
58 };
59 let parameters = apply_ty.parameters.to_chalk(db); 117 let parameters = apply_ty.parameters.to_chalk(db);
60 chalk_ir::ApplicationTy { name, parameters }.cast().intern() 118 chalk_ir::ApplicationTy { name, parameters }.cast().intern()
61 } 119 }
@@ -65,17 +123,30 @@ impl ToChalk for Ty {
65 chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast().intern() 123 chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast().intern()
66 } 124 }
67 Ty::Param { idx, .. } => { 125 Ty::Param { idx, .. } => {
68 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty::<ChalkIr>() 126 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }
127 .to_ty::<TypeFamily>()
69 } 128 }
70 Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(), 129 Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(),
71 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), 130 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"),
72 Ty::Dyn(predicates) => { 131 Ty::Dyn(predicates) => {
73 let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect(); 132 let where_clauses = predicates
74 chalk_ir::TyData::Dyn(make_binders(where_clauses, 1)).intern() 133 .iter()
134 .filter(|p| !p.is_error())
135 .cloned()
136 .map(|p| p.to_chalk(db))
137 .collect();
138 let bounded_ty = chalk_ir::BoundedTy { bounds: make_binders(where_clauses, 1) };
139 chalk_ir::TyData::Dyn(bounded_ty).intern()
75 } 140 }
76 Ty::Opaque(predicates) => { 141 Ty::Opaque(predicates) => {
77 let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect(); 142 let where_clauses = predicates
78 chalk_ir::TyData::Opaque(make_binders(where_clauses, 1)).intern() 143 .iter()
144 .filter(|p| !p.is_error())
145 .cloned()
146 .map(|p| p.to_chalk(db))
147 .collect();
148 let bounded_ty = chalk_ir::BoundedTy { bounds: make_binders(where_clauses, 1) };
149 chalk_ir::TyData::Opaque(bounded_ty).intern()
79 } 150 }
80 Ty::Unknown => { 151 Ty::Unknown => {
81 let parameters = Vec::new(); 152 let parameters = Vec::new();
@@ -84,30 +155,19 @@ impl ToChalk for Ty {
84 } 155 }
85 } 156 }
86 } 157 }
87 fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty<ChalkIr>) -> Self { 158 fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty<TypeFamily>) -> Self {
88 match chalk.data().clone() { 159 match chalk.data().clone() {
89 chalk_ir::TyData::Apply(apply_ty) => { 160 chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name {
90 // FIXME this is kind of hacky due to the fact that 161 TypeName::Error => Ty::Unknown,
91 // TypeName::Placeholder is a Ty::Param on our side 162 _ => {
92 match apply_ty.name { 163 let ctor = from_chalk(db, apply_ty.name);
93 TypeName::TypeKindId(TypeKindId::StructId(struct_id)) => { 164 let parameters = from_chalk(db, apply_ty.parameters);
94 let ctor = from_chalk(db, struct_id); 165 Ty::Apply(ApplicationTy { ctor, parameters })
95 let parameters = from_chalk(db, apply_ty.parameters);
96 Ty::Apply(ApplicationTy { ctor, parameters })
97 }
98 TypeName::AssociatedType(type_id) => {
99 let ctor = TypeCtor::AssociatedType(from_chalk(db, type_id));
100 let parameters = from_chalk(db, apply_ty.parameters);
101 Ty::Apply(ApplicationTy { ctor, parameters })
102 }
103 TypeName::Error => Ty::Unknown,
104 // FIXME handle TypeKindId::Trait/Type here
105 TypeName::TypeKindId(_) => unimplemented!(),
106 TypeName::Placeholder(idx) => {
107 assert_eq!(idx.ui, UniverseIndex::ROOT);
108 Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() }
109 }
110 } 166 }
167 },
168 chalk_ir::TyData::Placeholder(idx) => {
169 assert_eq!(idx.ui, UniverseIndex::ROOT);
170 Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() }
111 } 171 }
112 chalk_ir::TyData::Projection(proj) => { 172 chalk_ir::TyData::Projection(proj) => {
113 let associated_ty = from_chalk(db, proj.associated_ty_id); 173 let associated_ty = from_chalk(db, proj.associated_ty_id);
@@ -118,15 +178,15 @@ impl ToChalk for Ty {
118 chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx as u32), 178 chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx as u32),
119 chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown, 179 chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown,
120 chalk_ir::TyData::Dyn(where_clauses) => { 180 chalk_ir::TyData::Dyn(where_clauses) => {
121 assert_eq!(where_clauses.binders.len(), 1); 181 assert_eq!(where_clauses.bounds.binders.len(), 1);
122 let predicates = 182 let predicates =
123 where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); 183 where_clauses.bounds.value.into_iter().map(|c| from_chalk(db, c)).collect();
124 Ty::Dyn(predicates) 184 Ty::Dyn(predicates)
125 } 185 }
126 chalk_ir::TyData::Opaque(where_clauses) => { 186 chalk_ir::TyData::Opaque(where_clauses) => {
127 assert_eq!(where_clauses.binders.len(), 1); 187 assert_eq!(where_clauses.bounds.binders.len(), 1);
128 let predicates = 188 let predicates =
129 where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); 189 where_clauses.bounds.value.into_iter().map(|c| from_chalk(db, c)).collect();
130 Ty::Opaque(predicates) 190 Ty::Opaque(predicates)
131 } 191 }
132 } 192 }
@@ -134,18 +194,21 @@ impl ToChalk for Ty {
134} 194}
135 195
136impl ToChalk for Substs { 196impl ToChalk for Substs {
137 type Chalk = Vec<chalk_ir::Parameter<ChalkIr>>; 197 type Chalk = Vec<chalk_ir::Parameter<TypeFamily>>;
138 198
139 fn to_chalk(self, db: &impl HirDatabase) -> Vec<Parameter<ChalkIr>> { 199 fn to_chalk(self, db: &impl HirDatabase) -> Vec<Parameter<TypeFamily>> {
140 self.iter().map(|ty| ty.clone().to_chalk(db).cast()).collect() 200 self.iter().map(|ty| ty.clone().to_chalk(db).cast()).collect()
141 } 201 }
142 202
143 fn from_chalk(db: &impl HirDatabase, parameters: Vec<chalk_ir::Parameter<ChalkIr>>) -> Substs { 203 fn from_chalk(
204 db: &impl HirDatabase,
205 parameters: Vec<chalk_ir::Parameter<TypeFamily>>,
206 ) -> Substs {
144 let tys = parameters 207 let tys = parameters
145 .into_iter() 208 .into_iter()
146 .map(|p| match p { 209 .map(|p| match p.ty() {
147 chalk_ir::Parameter(chalk_ir::ParameterKind::Ty(ty)) => from_chalk(db, ty), 210 Some(ty) => from_chalk(db, ty.clone()),
148 chalk_ir::Parameter(chalk_ir::ParameterKind::Lifetime(_)) => unimplemented!(), 211 None => unimplemented!(),
149 }) 212 })
150 .collect(); 213 .collect();
151 Substs(tys) 214 Substs(tys)
@@ -153,88 +216,102 @@ impl ToChalk for Substs {
153} 216}
154 217
155impl ToChalk for TraitRef { 218impl ToChalk for TraitRef {
156 type Chalk = chalk_ir::TraitRef<ChalkIr>; 219 type Chalk = chalk_ir::TraitRef<TypeFamily>;
157 220
158 fn to_chalk(self: TraitRef, db: &impl HirDatabase) -> chalk_ir::TraitRef<ChalkIr> { 221 fn to_chalk(self: TraitRef, db: &impl HirDatabase) -> chalk_ir::TraitRef<TypeFamily> {
159 let trait_id = self.trait_.to_chalk(db); 222 let trait_id = self.trait_.to_chalk(db);
160 let parameters = self.substs.to_chalk(db); 223 let parameters = self.substs.to_chalk(db);
161 chalk_ir::TraitRef { trait_id, parameters } 224 chalk_ir::TraitRef { trait_id, parameters }
162 } 225 }
163 226
164 fn from_chalk(db: &impl HirDatabase, trait_ref: chalk_ir::TraitRef<ChalkIr>) -> Self { 227 fn from_chalk(db: &impl HirDatabase, trait_ref: chalk_ir::TraitRef<TypeFamily>) -> Self {
165 let trait_ = from_chalk(db, trait_ref.trait_id); 228 let trait_ = from_chalk(db, trait_ref.trait_id);
166 let substs = from_chalk(db, trait_ref.parameters); 229 let substs = from_chalk(db, trait_ref.parameters);
167 TraitRef { trait_, substs } 230 TraitRef { trait_, substs }
168 } 231 }
169} 232}
170 233
171impl ToChalk for TraitId { 234impl ToChalk for hir_def::TraitId {
172 type Chalk = chalk_ir::TraitId; 235 type Chalk = TraitId;
173 236
174 fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TraitId { 237 fn to_chalk(self, _db: &impl HirDatabase) -> TraitId {
175 chalk_ir::TraitId(id_to_chalk(self)) 238 chalk_ir::TraitId(self.as_intern_id())
176 } 239 }
177 240
178 fn from_chalk(_db: &impl HirDatabase, trait_id: chalk_ir::TraitId) -> TraitId { 241 fn from_chalk(_db: &impl HirDatabase, trait_id: TraitId) -> hir_def::TraitId {
179 id_from_chalk(trait_id.0) 242 InternKey::from_intern_id(trait_id.0)
180 } 243 }
181} 244}
182 245
183impl ToChalk for TypeCtor { 246impl ToChalk for TypeCtor {
184 type Chalk = chalk_ir::StructId; 247 type Chalk = TypeName<TypeFamily>;
185 248
186 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::StructId { 249 fn to_chalk(self, db: &impl HirDatabase) -> TypeName<TypeFamily> {
187 db.intern_type_ctor(self).into() 250 match self {
251 TypeCtor::AssociatedType(type_alias) => {
252 let type_id = type_alias.to_chalk(db);
253 TypeName::AssociatedType(type_id)
254 }
255 _ => {
256 // other TypeCtors get interned and turned into a chalk StructId
257 let struct_id = db.intern_type_ctor(self).into();
258 TypeName::Struct(struct_id)
259 }
260 }
188 } 261 }
189 262
190 fn from_chalk(db: &impl HirDatabase, struct_id: chalk_ir::StructId) -> TypeCtor { 263 fn from_chalk(db: &impl HirDatabase, type_name: TypeName<TypeFamily>) -> TypeCtor {
191 db.lookup_intern_type_ctor(struct_id.into()) 264 match type_name {
265 TypeName::Struct(struct_id) => db.lookup_intern_type_ctor(struct_id.into()),
266 TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)),
267 TypeName::Error => {
268 // this should not be reached, since we don't represent TypeName::Error with TypeCtor
269 unreachable!()
270 }
271 }
192 } 272 }
193} 273}
194 274
195impl ToChalk for Impl { 275impl ToChalk for Impl {
196 type Chalk = chalk_ir::ImplId; 276 type Chalk = ImplId;
197 277
198 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ImplId { 278 fn to_chalk(self, db: &impl HirDatabase) -> ImplId {
199 db.intern_chalk_impl(self).into() 279 db.intern_chalk_impl(self).into()
200 } 280 }
201 281
202 fn from_chalk(db: &impl HirDatabase, impl_id: chalk_ir::ImplId) -> Impl { 282 fn from_chalk(db: &impl HirDatabase, impl_id: ImplId) -> Impl {
203 db.lookup_intern_chalk_impl(impl_id.into()) 283 db.lookup_intern_chalk_impl(impl_id.into())
204 } 284 }
205} 285}
206 286
207impl ToChalk for TypeAliasId { 287impl ToChalk for TypeAliasId {
208 type Chalk = chalk_ir::TypeId; 288 type Chalk = AssocTypeId;
209 289
210 fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TypeId { 290 fn to_chalk(self, _db: &impl HirDatabase) -> AssocTypeId {
211 chalk_ir::TypeId(id_to_chalk(self)) 291 chalk_ir::AssocTypeId(self.as_intern_id())
212 } 292 }
213 293
214 fn from_chalk(_db: &impl HirDatabase, type_alias_id: chalk_ir::TypeId) -> TypeAliasId { 294 fn from_chalk(_db: &impl HirDatabase, type_alias_id: AssocTypeId) -> TypeAliasId {
215 id_from_chalk(type_alias_id.0) 295 InternKey::from_intern_id(type_alias_id.0)
216 } 296 }
217} 297}
218 298
219impl ToChalk for AssocTyValue { 299impl ToChalk for AssocTyValue {
220 type Chalk = chalk_rust_ir::AssociatedTyValueId; 300 type Chalk = AssociatedTyValueId;
221 301
222 fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::AssociatedTyValueId { 302 fn to_chalk(self, db: &impl HirDatabase) -> AssociatedTyValueId {
223 db.intern_assoc_ty_value(self).into() 303 db.intern_assoc_ty_value(self).into()
224 } 304 }
225 305
226 fn from_chalk( 306 fn from_chalk(db: &impl HirDatabase, assoc_ty_value_id: AssociatedTyValueId) -> AssocTyValue {
227 db: &impl HirDatabase,
228 assoc_ty_value_id: chalk_rust_ir::AssociatedTyValueId,
229 ) -> AssocTyValue {
230 db.lookup_intern_assoc_ty_value(assoc_ty_value_id.into()) 307 db.lookup_intern_assoc_ty_value(assoc_ty_value_id.into())
231 } 308 }
232} 309}
233 310
234impl ToChalk for GenericPredicate { 311impl ToChalk for GenericPredicate {
235 type Chalk = chalk_ir::QuantifiedWhereClause<ChalkIr>; 312 type Chalk = chalk_ir::QuantifiedWhereClause<TypeFamily>;
236 313
237 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::QuantifiedWhereClause<ChalkIr> { 314 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::QuantifiedWhereClause<TypeFamily> {
238 match self { 315 match self {
239 GenericPredicate::Implemented(trait_ref) => { 316 GenericPredicate::Implemented(trait_ref) => {
240 make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0) 317 make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0)
@@ -246,26 +323,16 @@ impl ToChalk for GenericPredicate {
246 }), 323 }),
247 0, 324 0,
248 ), 325 ),
249 GenericPredicate::Error => { 326 GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"),
250 let impossible_trait_ref = chalk_ir::TraitRef {
251 trait_id: UNKNOWN_TRAIT,
252 parameters: vec![Ty::Unknown.to_chalk(db).cast()],
253 };
254 make_binders(chalk_ir::WhereClause::Implemented(impossible_trait_ref), 0)
255 }
256 } 327 }
257 } 328 }
258 329
259 fn from_chalk( 330 fn from_chalk(
260 db: &impl HirDatabase, 331 db: &impl HirDatabase,
261 where_clause: chalk_ir::QuantifiedWhereClause<ChalkIr>, 332 where_clause: chalk_ir::QuantifiedWhereClause<TypeFamily>,
262 ) -> GenericPredicate { 333 ) -> GenericPredicate {
263 match where_clause.value { 334 match where_clause.value {
264 chalk_ir::WhereClause::Implemented(tr) => { 335 chalk_ir::WhereClause::Implemented(tr) => {
265 if tr.trait_id == UNKNOWN_TRAIT {
266 // FIXME we need an Error enum on the Chalk side to avoid this
267 return GenericPredicate::Error;
268 }
269 GenericPredicate::Implemented(from_chalk(db, tr)) 336 GenericPredicate::Implemented(from_chalk(db, tr))
270 } 337 }
271 chalk_ir::WhereClause::ProjectionEq(projection_eq) => { 338 chalk_ir::WhereClause::ProjectionEq(projection_eq) => {
@@ -278,9 +345,9 @@ impl ToChalk for GenericPredicate {
278} 345}
279 346
280impl ToChalk for ProjectionTy { 347impl ToChalk for ProjectionTy {
281 type Chalk = chalk_ir::ProjectionTy<ChalkIr>; 348 type Chalk = chalk_ir::ProjectionTy<TypeFamily>;
282 349
283 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ProjectionTy<ChalkIr> { 350 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ProjectionTy<TypeFamily> {
284 chalk_ir::ProjectionTy { 351 chalk_ir::ProjectionTy {
285 associated_ty_id: self.associated_ty.to_chalk(db), 352 associated_ty_id: self.associated_ty.to_chalk(db),
286 parameters: self.parameters.to_chalk(db), 353 parameters: self.parameters.to_chalk(db),
@@ -289,7 +356,7 @@ impl ToChalk for ProjectionTy {
289 356
290 fn from_chalk( 357 fn from_chalk(
291 db: &impl HirDatabase, 358 db: &impl HirDatabase,
292 projection_ty: chalk_ir::ProjectionTy<ChalkIr>, 359 projection_ty: chalk_ir::ProjectionTy<TypeFamily>,
293 ) -> ProjectionTy { 360 ) -> ProjectionTy {
294 ProjectionTy { 361 ProjectionTy {
295 associated_ty: from_chalk(db, projection_ty.associated_ty_id), 362 associated_ty: from_chalk(db, projection_ty.associated_ty_id),
@@ -299,31 +366,31 @@ impl ToChalk for ProjectionTy {
299} 366}
300 367
301impl ToChalk for super::ProjectionPredicate { 368impl ToChalk for super::ProjectionPredicate {
302 type Chalk = chalk_ir::Normalize<ChalkIr>; 369 type Chalk = chalk_ir::Normalize<TypeFamily>;
303 370
304 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Normalize<ChalkIr> { 371 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Normalize<TypeFamily> {
305 chalk_ir::Normalize { 372 chalk_ir::Normalize {
306 projection: self.projection_ty.to_chalk(db), 373 projection: self.projection_ty.to_chalk(db),
307 ty: self.ty.to_chalk(db), 374 ty: self.ty.to_chalk(db),
308 } 375 }
309 } 376 }
310 377
311 fn from_chalk(_db: &impl HirDatabase, _normalize: chalk_ir::Normalize<ChalkIr>) -> Self { 378 fn from_chalk(_db: &impl HirDatabase, _normalize: chalk_ir::Normalize<TypeFamily>) -> Self {
312 unimplemented!() 379 unimplemented!()
313 } 380 }
314} 381}
315 382
316impl ToChalk for Obligation { 383impl ToChalk for Obligation {
317 type Chalk = chalk_ir::DomainGoal<ChalkIr>; 384 type Chalk = chalk_ir::DomainGoal<TypeFamily>;
318 385
319 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::DomainGoal<ChalkIr> { 386 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::DomainGoal<TypeFamily> {
320 match self { 387 match self {
321 Obligation::Trait(tr) => tr.to_chalk(db).cast(), 388 Obligation::Trait(tr) => tr.to_chalk(db).cast(),
322 Obligation::Projection(pr) => pr.to_chalk(db).cast(), 389 Obligation::Projection(pr) => pr.to_chalk(db).cast(),
323 } 390 }
324 } 391 }
325 392
326 fn from_chalk(_db: &impl HirDatabase, _goal: chalk_ir::DomainGoal<ChalkIr>) -> Self { 393 fn from_chalk(_db: &impl HirDatabase, _goal: chalk_ir::DomainGoal<TypeFamily>) -> Self {
327 unimplemented!() 394 unimplemented!()
328 } 395 }
329} 396}
@@ -347,16 +414,17 @@ where
347} 414}
348 415
349impl ToChalk for Arc<super::TraitEnvironment> { 416impl ToChalk for Arc<super::TraitEnvironment> {
350 type Chalk = chalk_ir::Environment<ChalkIr>; 417 type Chalk = chalk_ir::Environment<TypeFamily>;
351 418
352 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Environment<ChalkIr> { 419 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Environment<TypeFamily> {
353 let mut clauses = Vec::new(); 420 let mut clauses = Vec::new();
354 for pred in &self.predicates { 421 for pred in &self.predicates {
355 if pred.is_error() { 422 if pred.is_error() {
356 // for env, we just ignore errors 423 // for env, we just ignore errors
357 continue; 424 continue;
358 } 425 }
359 let program_clause: chalk_ir::ProgramClause<ChalkIr> = pred.clone().to_chalk(db).cast(); 426 let program_clause: chalk_ir::ProgramClause<TypeFamily> =
427 pred.clone().to_chalk(db).cast();
360 clauses.push(program_clause.into_from_env_clause()); 428 clauses.push(program_clause.into_from_env_clause());
361 } 429 }
362 chalk_ir::Environment::new().add_clauses(clauses) 430 chalk_ir::Environment::new().add_clauses(clauses)
@@ -364,7 +432,7 @@ impl ToChalk for Arc<super::TraitEnvironment> {
364 432
365 fn from_chalk( 433 fn from_chalk(
366 _db: &impl HirDatabase, 434 _db: &impl HirDatabase,
367 _env: chalk_ir::Environment<ChalkIr>, 435 _env: chalk_ir::Environment<TypeFamily>,
368 ) -> Arc<super::TraitEnvironment> { 436 ) -> Arc<super::TraitEnvironment> {
369 unimplemented!() 437 unimplemented!()
370 } 438 }
@@ -372,7 +440,7 @@ impl ToChalk for Arc<super::TraitEnvironment> {
372 440
373impl<T: ToChalk> ToChalk for super::InEnvironment<T> 441impl<T: ToChalk> ToChalk for super::InEnvironment<T>
374where 442where
375 T::Chalk: chalk_ir::family::HasTypeFamily<TypeFamily = ChalkIr>, 443 T::Chalk: chalk_ir::family::HasTypeFamily<TypeFamily = TypeFamily>,
376{ 444{
377 type Chalk = chalk_ir::InEnvironment<T::Chalk>; 445 type Chalk = chalk_ir::InEnvironment<T::Chalk>;
378 446
@@ -395,9 +463,9 @@ where
395} 463}
396 464
397impl ToChalk for builtin::BuiltinImplData { 465impl ToChalk for builtin::BuiltinImplData {
398 type Chalk = chalk_rust_ir::ImplDatum<ChalkIr>; 466 type Chalk = ImplDatum;
399 467
400 fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::ImplDatum<ChalkIr> { 468 fn to_chalk(self, db: &impl HirDatabase) -> ImplDatum {
401 let impl_type = chalk_rust_ir::ImplType::External; 469 let impl_type = chalk_rust_ir::ImplType::External;
402 let where_clauses = self.where_clauses.into_iter().map(|w| w.to_chalk(db)).collect(); 470 let where_clauses = self.where_clauses.into_iter().map(|w| w.to_chalk(db)).collect();
403 471
@@ -413,15 +481,15 @@ impl ToChalk for builtin::BuiltinImplData {
413 } 481 }
414 } 482 }
415 483
416 fn from_chalk(_db: &impl HirDatabase, _data: chalk_rust_ir::ImplDatum<ChalkIr>) -> Self { 484 fn from_chalk(_db: &impl HirDatabase, _data: ImplDatum) -> Self {
417 unimplemented!() 485 unimplemented!()
418 } 486 }
419} 487}
420 488
421impl ToChalk for builtin::BuiltinImplAssocTyValueData { 489impl ToChalk for builtin::BuiltinImplAssocTyValueData {
422 type Chalk = chalk_rust_ir::AssociatedTyValue<ChalkIr>; 490 type Chalk = AssociatedTyValue;
423 491
424 fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::AssociatedTyValue<ChalkIr> { 492 fn to_chalk(self, db: &impl HirDatabase) -> AssociatedTyValue {
425 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: self.value.to_chalk(db) }; 493 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: self.value.to_chalk(db) };
426 494
427 chalk_rust_ir::AssociatedTyValue { 495 chalk_rust_ir::AssociatedTyValue {
@@ -433,7 +501,7 @@ impl ToChalk for builtin::BuiltinImplAssocTyValueData {
433 501
434 fn from_chalk( 502 fn from_chalk(
435 _db: &impl HirDatabase, 503 _db: &impl HirDatabase,
436 _data: chalk_rust_ir::AssociatedTyValue<ChalkIr>, 504 _data: AssociatedTyValue,
437 ) -> builtin::BuiltinImplAssocTyValueData { 505 ) -> builtin::BuiltinImplAssocTyValueData {
438 unimplemented!() 506 unimplemented!()
439 } 507 }
@@ -450,46 +518,46 @@ fn convert_where_clauses(
450 db: &impl HirDatabase, 518 db: &impl HirDatabase,
451 def: GenericDefId, 519 def: GenericDefId,
452 substs: &Substs, 520 substs: &Substs,
453) -> Vec<chalk_ir::QuantifiedWhereClause<ChalkIr>> { 521) -> Vec<chalk_ir::QuantifiedWhereClause<TypeFamily>> {
454 let generic_predicates = db.generic_predicates(def); 522 let generic_predicates = db.generic_predicates(def);
455 let mut result = Vec::with_capacity(generic_predicates.len()); 523 let mut result = Vec::with_capacity(generic_predicates.len());
456 for pred in generic_predicates.iter() { 524 for pred in generic_predicates.iter() {
457 if pred.is_error() { 525 if pred.is_error() {
458 // HACK: Return just the single predicate (which is always false 526 // skip errored predicates completely
459 // anyway), otherwise Chalk can easily get into slow situations 527 continue;
460 return vec![pred.clone().subst(substs).to_chalk(db)];
461 } 528 }
462 result.push(pred.clone().subst(substs).to_chalk(db)); 529 result.push(pred.clone().subst(substs).to_chalk(db));
463 } 530 }
464 result 531 result
465} 532}
466 533
467impl<'a, DB> chalk_solve::RustIrDatabase<ChalkIr> for ChalkContext<'a, DB> 534impl<'a, DB> chalk_solve::RustIrDatabase<TypeFamily> for ChalkContext<'a, DB>
468where 535where
469 DB: HirDatabase, 536 DB: HirDatabase,
470{ 537{
471 fn associated_ty_data(&self, id: TypeId) -> Arc<AssociatedTyDatum<ChalkIr>> { 538 fn associated_ty_data(&self, id: AssocTypeId) -> Arc<AssociatedTyDatum> {
472 self.db.associated_ty_data(id) 539 self.db.associated_ty_data(id)
473 } 540 }
474 fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc<TraitDatum<ChalkIr>> { 541 fn trait_datum(&self, trait_id: TraitId) -> Arc<TraitDatum> {
475 self.db.trait_datum(self.krate, trait_id) 542 self.db.trait_datum(self.krate, trait_id)
476 } 543 }
477 fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum<ChalkIr>> { 544 fn struct_datum(&self, struct_id: StructId) -> Arc<StructDatum> {
478 self.db.struct_datum(self.krate, struct_id) 545 self.db.struct_datum(self.krate, struct_id)
479 } 546 }
480 fn impl_datum(&self, impl_id: chalk_ir::ImplId) -> Arc<ImplDatum<ChalkIr>> { 547 fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> {
481 self.db.impl_datum(self.krate, impl_id) 548 self.db.impl_datum(self.krate, impl_id)
482 } 549 }
483 fn impls_for_trait( 550 fn impls_for_trait(
484 &self, 551 &self,
485 trait_id: chalk_ir::TraitId, 552 trait_id: TraitId,
486 parameters: &[Parameter<ChalkIr>], 553 parameters: &[Parameter<TypeFamily>],
487 ) -> Vec<chalk_ir::ImplId> { 554 ) -> Vec<ImplId> {
488 debug!("impls_for_trait {:?}", trait_id); 555 debug!("impls_for_trait {:?}", trait_id);
489 if trait_id == UNKNOWN_TRAIT { 556 let trait_: hir_def::TraitId = from_chalk(self.db, trait_id);
490 return Vec::new(); 557
491 } 558 // Note: Since we're using impls_for_trait, only impls where the trait
492 let trait_: TraitId = from_chalk(self.db, trait_id); 559 // can be resolved should ever reach Chalk. `impl_datum` relies on that
560 // and will panic if the trait can't be resolved.
493 let mut result: Vec<_> = self 561 let mut result: Vec<_> = self
494 .db 562 .db
495 .impls_for_trait(self.krate, trait_.into()) 563 .impls_for_trait(self.krate, trait_.into())
@@ -508,39 +576,32 @@ where
508 debug!("impls_for_trait returned {} impls", result.len()); 576 debug!("impls_for_trait returned {} impls", result.len());
509 result 577 result
510 } 578 }
511 fn impl_provided_for( 579 fn impl_provided_for(&self, auto_trait_id: TraitId, struct_id: StructId) -> bool {
512 &self,
513 auto_trait_id: chalk_ir::TraitId,
514 struct_id: chalk_ir::StructId,
515 ) -> bool {
516 debug!("impl_provided_for {:?}, {:?}", auto_trait_id, struct_id); 580 debug!("impl_provided_for {:?}, {:?}", auto_trait_id, struct_id);
517 false // FIXME 581 false // FIXME
518 } 582 }
519 fn type_name(&self, _id: TypeKindId) -> Identifier { 583 fn associated_ty_value(&self, id: AssociatedTyValueId) -> Arc<AssociatedTyValue> {
520 unimplemented!()
521 }
522 fn associated_ty_value(
523 &self,
524 id: chalk_rust_ir::AssociatedTyValueId,
525 ) -> Arc<AssociatedTyValue<ChalkIr>> {
526 self.db.associated_ty_value(self.krate.into(), id) 584 self.db.associated_ty_value(self.krate.into(), id)
527 } 585 }
528 fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<ChalkIr>> { 586 fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<TypeFamily>> {
529 vec![] 587 vec![]
530 } 588 }
531 fn local_impls_to_coherence_check( 589 fn local_impls_to_coherence_check(&self, _trait_id: TraitId) -> Vec<ImplId> {
532 &self,
533 _trait_id: chalk_ir::TraitId,
534 ) -> Vec<chalk_ir::ImplId> {
535 // We don't do coherence checking (yet) 590 // We don't do coherence checking (yet)
536 unimplemented!() 591 unimplemented!()
537 } 592 }
593 fn as_struct_id(&self, id: &TypeName<TypeFamily>) -> Option<StructId> {
594 match id {
595 TypeName::Struct(struct_id) => Some(*struct_id),
596 _ => None,
597 }
598 }
538} 599}
539 600
540pub(crate) fn associated_ty_data_query( 601pub(crate) fn associated_ty_data_query(
541 db: &impl HirDatabase, 602 db: &impl HirDatabase,
542 id: TypeId, 603 id: AssocTypeId,
543) -> Arc<AssociatedTyDatum<ChalkIr>> { 604) -> Arc<AssociatedTyDatum> {
544 debug!("associated_ty_data {:?}", id); 605 debug!("associated_ty_data {:?}", id);
545 let type_alias: TypeAliasId = from_chalk(db, id); 606 let type_alias: TypeAliasId = from_chalk(db, id);
546 let trait_ = match type_alias.lookup(db).container { 607 let trait_ = match type_alias.lookup(db).container {
@@ -565,28 +626,10 @@ pub(crate) fn associated_ty_data_query(
565pub(crate) fn trait_datum_query( 626pub(crate) fn trait_datum_query(
566 db: &impl HirDatabase, 627 db: &impl HirDatabase,
567 krate: CrateId, 628 krate: CrateId,
568 trait_id: chalk_ir::TraitId, 629 trait_id: TraitId,
569) -> Arc<TraitDatum<ChalkIr>> { 630) -> Arc<TraitDatum> {
570 debug!("trait_datum {:?}", trait_id); 631 debug!("trait_datum {:?}", trait_id);
571 if trait_id == UNKNOWN_TRAIT { 632 let trait_: hir_def::TraitId = from_chalk(db, trait_id);
572 let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses: Vec::new() };
573
574 let flags = chalk_rust_ir::TraitFlags {
575 auto: false,
576 marker: false,
577 upstream: true,
578 fundamental: false,
579 non_enumerable: true,
580 coinductive: false,
581 };
582 return Arc::new(TraitDatum {
583 id: trait_id,
584 binders: make_binders(trait_datum_bound, 1),
585 flags,
586 associated_ty_ids: vec![],
587 });
588 }
589 let trait_: TraitId = from_chalk(db, trait_id);
590 let trait_data = db.trait_data(trait_); 633 let trait_data = db.trait_data(trait_);
591 debug!("trait {:?} = {:?}", trait_id, trait_data.name); 634 debug!("trait {:?} = {:?}", trait_id, trait_data.name);
592 let generic_params = generics(db, trait_.into()); 635 let generic_params = generics(db, trait_.into());
@@ -616,10 +659,10 @@ pub(crate) fn trait_datum_query(
616pub(crate) fn struct_datum_query( 659pub(crate) fn struct_datum_query(
617 db: &impl HirDatabase, 660 db: &impl HirDatabase,
618 krate: CrateId, 661 krate: CrateId,
619 struct_id: chalk_ir::StructId, 662 struct_id: StructId,
620) -> Arc<StructDatum<ChalkIr>> { 663) -> Arc<StructDatum> {
621 debug!("struct_datum {:?}", struct_id); 664 debug!("struct_datum {:?}", struct_id);
622 let type_ctor: TypeCtor = from_chalk(db, struct_id); 665 let type_ctor: TypeCtor = from_chalk(db, TypeName::Struct(struct_id));
623 debug!("struct {:?} = {:?}", struct_id, type_ctor); 666 debug!("struct {:?} = {:?}", struct_id, type_ctor);
624 let num_params = type_ctor.num_ty_params(db); 667 let num_params = type_ctor.num_ty_params(db);
625 let upstream = type_ctor.krate(db) != Some(krate); 668 let upstream = type_ctor.krate(db) != Some(krate);
@@ -648,25 +691,27 @@ pub(crate) fn struct_datum_query(
648pub(crate) fn impl_datum_query( 691pub(crate) fn impl_datum_query(
649 db: &impl HirDatabase, 692 db: &impl HirDatabase,
650 krate: CrateId, 693 krate: CrateId,
651 impl_id: chalk_ir::ImplId, 694 impl_id: ImplId,
652) -> Arc<ImplDatum<ChalkIr>> { 695) -> Arc<ImplDatum> {
653 let _p = ra_prof::profile("impl_datum"); 696 let _p = ra_prof::profile("impl_datum");
654 debug!("impl_datum {:?}", impl_id); 697 debug!("impl_datum {:?}", impl_id);
655 let impl_: Impl = from_chalk(db, impl_id); 698 let impl_: Impl = from_chalk(db, impl_id);
656 match impl_ { 699 match impl_ {
657 Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block), 700 Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block),
658 _ => builtin::impl_datum(db, krate, impl_).map(|d| Arc::new(d.to_chalk(db))), 701 _ => Arc::new(builtin::impl_datum(db, krate, impl_).to_chalk(db)),
659 } 702 }
660 .unwrap_or_else(invalid_impl_datum)
661} 703}
662 704
663fn impl_block_datum( 705fn impl_block_datum(
664 db: &impl HirDatabase, 706 db: &impl HirDatabase,
665 krate: CrateId, 707 krate: CrateId,
666 chalk_id: chalk_ir::ImplId, 708 chalk_id: ImplId,
667 impl_id: ImplId, 709 impl_id: hir_def::ImplId,
668) -> Option<Arc<ImplDatum<ChalkIr>>> { 710) -> Arc<ImplDatum> {
669 let trait_ref = db.impl_trait(impl_id)?; 711 let trait_ref = db
712 .impl_trait(impl_id)
713 // ImplIds for impls where the trait ref can't be resolved should never reach Chalk
714 .expect("invalid impl passed to Chalk");
670 let impl_data = db.impl_data(impl_id); 715 let impl_data = db.impl_data(impl_id);
671 716
672 let generic_params = generics(db, impl_id.into()); 717 let generic_params = generics(db, impl_id.into());
@@ -718,29 +763,14 @@ fn impl_block_datum(
718 polarity, 763 polarity,
719 associated_ty_value_ids, 764 associated_ty_value_ids,
720 }; 765 };
721 Some(Arc::new(impl_datum))
722}
723
724fn invalid_impl_datum() -> Arc<ImplDatum<ChalkIr>> {
725 let trait_ref = chalk_ir::TraitRef {
726 trait_id: UNKNOWN_TRAIT,
727 parameters: vec![chalk_ir::TyData::BoundVar(0).cast().intern().cast()],
728 };
729 let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses: Vec::new() };
730 let impl_datum = ImplDatum {
731 binders: make_binders(impl_datum_bound, 1),
732 impl_type: chalk_rust_ir::ImplType::External,
733 polarity: chalk_rust_ir::Polarity::Positive,
734 associated_ty_value_ids: Vec::new(),
735 };
736 Arc::new(impl_datum) 766 Arc::new(impl_datum)
737} 767}
738 768
739pub(crate) fn associated_ty_value_query( 769pub(crate) fn associated_ty_value_query(
740 db: &impl HirDatabase, 770 db: &impl HirDatabase,
741 krate: CrateId, 771 krate: CrateId,
742 id: chalk_rust_ir::AssociatedTyValueId, 772 id: AssociatedTyValueId,
743) -> Arc<chalk_rust_ir::AssociatedTyValue<ChalkIr>> { 773) -> Arc<AssociatedTyValue> {
744 let data: AssocTyValue = from_chalk(db, id); 774 let data: AssocTyValue = from_chalk(db, id);
745 match data { 775 match data {
746 AssocTyValue::TypeAlias(type_alias) => { 776 AssocTyValue::TypeAlias(type_alias) => {
@@ -754,7 +784,7 @@ fn type_alias_associated_ty_value(
754 db: &impl HirDatabase, 784 db: &impl HirDatabase,
755 _krate: CrateId, 785 _krate: CrateId,
756 type_alias: TypeAliasId, 786 type_alias: TypeAliasId,
757) -> Arc<AssociatedTyValue<ChalkIr>> { 787) -> Arc<AssociatedTyValue> {
758 let type_alias_data = db.type_alias_data(type_alias); 788 let type_alias_data = db.type_alias_data(type_alias);
759 let impl_id = match type_alias.lookup(db).container { 789 let impl_id = match type_alias.lookup(db).container {
760 AssocContainerId::ImplId(it) => it, 790 AssocContainerId::ImplId(it) => it,
@@ -786,27 +816,27 @@ fn id_to_chalk<T: InternKey>(salsa_id: T) -> chalk_ir::RawId {
786 chalk_ir::RawId { index: salsa_id.as_intern_id().as_u32() } 816 chalk_ir::RawId { index: salsa_id.as_intern_id().as_u32() }
787} 817}
788 818
789impl From<chalk_ir::StructId> for crate::TypeCtorId { 819impl From<StructId> for crate::TypeCtorId {
790 fn from(struct_id: chalk_ir::StructId) -> Self { 820 fn from(struct_id: StructId) -> Self {
791 id_from_chalk(struct_id.0) 821 InternKey::from_intern_id(struct_id.0)
792 } 822 }
793} 823}
794 824
795impl From<crate::TypeCtorId> for chalk_ir::StructId { 825impl From<crate::TypeCtorId> for StructId {
796 fn from(type_ctor_id: crate::TypeCtorId) -> Self { 826 fn from(type_ctor_id: crate::TypeCtorId) -> Self {
797 chalk_ir::StructId(id_to_chalk(type_ctor_id)) 827 chalk_ir::StructId(type_ctor_id.as_intern_id())
798 } 828 }
799} 829}
800 830
801impl From<chalk_ir::ImplId> for crate::traits::GlobalImplId { 831impl From<ImplId> for crate::traits::GlobalImplId {
802 fn from(impl_id: chalk_ir::ImplId) -> Self { 832 fn from(impl_id: ImplId) -> Self {
803 id_from_chalk(impl_id.0) 833 InternKey::from_intern_id(impl_id.0)
804 } 834 }
805} 835}
806 836
807impl From<crate::traits::GlobalImplId> for chalk_ir::ImplId { 837impl From<crate::traits::GlobalImplId> for ImplId {
808 fn from(impl_id: crate::traits::GlobalImplId) -> Self { 838 fn from(impl_id: crate::traits::GlobalImplId) -> Self {
809 chalk_ir::ImplId(id_to_chalk(impl_id)) 839 chalk_ir::ImplId(impl_id.as_intern_id())
810 } 840 }
811} 841}
812 842
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml
index e826c10ef..030e9033c 100644
--- a/crates/ra_lsp_server/Cargo.toml
+++ b/crates/ra_lsp_server/Cargo.toml
@@ -14,7 +14,7 @@ serde_json = "1.0.34"
14serde = { version = "1.0.83", features = ["derive"] } 14serde = { version = "1.0.83", features = ["derive"] }
15crossbeam-channel = "0.4" 15crossbeam-channel = "0.4"
16log = "0.4.3" 16log = "0.4.3"
17lsp-types = { version = "0.65.0", features = ["proposed"] } 17lsp-types = { version = "0.67.0", features = ["proposed"] }
18rustc-hash = "1.0" 18rustc-hash = "1.0"
19parking_lot = "0.10.0" 19parking_lot = "0.10.0"
20jod-thread = "0.1.0" 20jod-thread = "0.1.0"
diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs
index eeca67ee1..ceb4c4259 100644
--- a/crates/ra_lsp_server/src/caps.rs
+++ b/crates/ra_lsp_server/src/caps.rs
@@ -46,6 +46,7 @@ pub fn server_capabilities() -> ServerCapabilities {
46 more_trigger_character: Some(vec![".".to_string(), ">".to_string()]), 46 more_trigger_character: Some(vec![".".to_string(), ">".to_string()]),
47 }), 47 }),
48 selection_range_provider: Some(SelectionRangeProviderCapability::Simple(true)), 48 selection_range_provider: Some(SelectionRangeProviderCapability::Simple(true)),
49 semantic_highlighting: None,
49 folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)), 50 folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)),
50 rename_provider: Some(RenameProviderCapability::Options(RenameOptions { 51 rename_provider: Some(RenameProviderCapability::Options(RenameOptions {
51 prepare_provider: Some(true), 52 prepare_provider: Some(true),
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index a8f625176..baaef3023 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -221,6 +221,10 @@ impl ast::FnDef {
221 .and_then(|it| it.into_token()) 221 .and_then(|it| it.into_token())
222 .filter(|it| it.kind() == T![;]) 222 .filter(|it| it.kind() == T![;])
223 } 223 }
224
225 pub fn is_async(&self) -> bool {
226 self.syntax().children_with_tokens().any(|it| it.kind() == T![async])
227 }
224} 228}
225 229
226impl ast::LetStmt { 230impl ast::LetStmt {