diff options
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 53 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 131 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 150 |
4 files changed, 310 insertions, 33 deletions
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 8bab7e54b..09d26ce5a 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -5,6 +5,7 @@ | |||
5 | //! - Building the type for an item: This happens through the `type_for_def` query. | 5 | //! - Building the type for an item: This happens through the `type_for_def` query. |
6 | //! | 6 | //! |
7 | //! This usually involves resolving names, collecting generic arguments etc. | 7 | //! This usually involves resolving names, collecting generic arguments etc. |
8 | use std::sync::Arc; | ||
8 | use std::iter; | 9 | use std::iter; |
9 | 10 | ||
10 | use crate::{ | 11 | use crate::{ |
@@ -18,9 +19,9 @@ use crate::{ | |||
18 | resolve::{Resolver, Resolution}, | 19 | resolve::{Resolver, Resolution}, |
19 | path::{PathSegment, GenericArg}, | 20 | path::{PathSegment, GenericArg}, |
20 | generics::{GenericParams, HasGenericParams}, | 21 | generics::{GenericParams, HasGenericParams}, |
21 | adt::VariantDef, Trait | 22 | adt::VariantDef, Trait, generics::{ WherePredicate, GenericDef} |
22 | }; | 23 | }; |
23 | use super::{Ty, primitive, FnSig, Substs, TypeCtor, TraitRef}; | 24 | use super::{Ty, primitive, FnSig, Substs, TypeCtor, TraitRef, GenericPredicate}; |
24 | 25 | ||
25 | impl Ty { | 26 | impl Ty { |
26 | pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { | 27 | pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { |
@@ -208,16 +209,12 @@ pub(super) fn substs_from_path_segment( | |||
208 | } | 209 | } |
209 | 210 | ||
210 | impl TraitRef { | 211 | impl TraitRef { |
211 | pub(crate) fn from_hir( | 212 | pub(crate) fn from_path( |
212 | db: &impl HirDatabase, | 213 | db: &impl HirDatabase, |
213 | resolver: &Resolver, | 214 | resolver: &Resolver, |
214 | type_ref: &TypeRef, | 215 | path: &Path, |
215 | explicit_self_ty: Option<Ty>, | 216 | explicit_self_ty: Option<Ty>, |
216 | ) -> Option<Self> { | 217 | ) -> Option<Self> { |
217 | let path = match type_ref { | ||
218 | TypeRef::Path(path) => path, | ||
219 | _ => return None, | ||
220 | }; | ||
221 | let resolved = match resolver.resolve_path(db, &path).take_types()? { | 218 | let resolved = match resolver.resolve_path(db, &path).take_types()? { |
222 | Resolution::Def(ModuleDef::Trait(tr)) => tr, | 219 | Resolution::Def(ModuleDef::Trait(tr)) => tr, |
223 | _ => return None, | 220 | _ => return None, |
@@ -232,6 +229,19 @@ impl TraitRef { | |||
232 | Some(TraitRef { trait_: resolved, substs }) | 229 | Some(TraitRef { trait_: resolved, substs }) |
233 | } | 230 | } |
234 | 231 | ||
232 | pub(crate) fn from_hir( | ||
233 | db: &impl HirDatabase, | ||
234 | resolver: &Resolver, | ||
235 | type_ref: &TypeRef, | ||
236 | explicit_self_ty: Option<Ty>, | ||
237 | ) -> Option<Self> { | ||
238 | let path = match type_ref { | ||
239 | TypeRef::Path(path) => path, | ||
240 | _ => return None, | ||
241 | }; | ||
242 | TraitRef::from_path(db, resolver, path, explicit_self_ty) | ||
243 | } | ||
244 | |||
235 | fn substs_from_path( | 245 | fn substs_from_path( |
236 | db: &impl HirDatabase, | 246 | db: &impl HirDatabase, |
237 | resolver: &Resolver, | 247 | resolver: &Resolver, |
@@ -246,6 +256,15 @@ impl TraitRef { | |||
246 | let substs = Substs::identity(&trait_.generic_params(db)); | 256 | let substs = Substs::identity(&trait_.generic_params(db)); |
247 | TraitRef { trait_, substs } | 257 | TraitRef { trait_, substs } |
248 | } | 258 | } |
259 | |||
260 | pub(crate) fn for_where_predicate( | ||
261 | db: &impl HirDatabase, | ||
262 | resolver: &Resolver, | ||
263 | pred: &WherePredicate, | ||
264 | ) -> Option<TraitRef> { | ||
265 | let self_ty = Ty::from_hir(db, resolver, &pred.type_ref); | ||
266 | TraitRef::from_path(db, resolver, &pred.trait_ref, Some(self_ty)) | ||
267 | } | ||
249 | } | 268 | } |
250 | 269 | ||
251 | /// Build the declared type of an item. This depends on the namespace; e.g. for | 270 | /// Build the declared type of an item. This depends on the namespace; e.g. for |
@@ -294,6 +313,24 @@ pub(crate) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty { | |||
294 | Ty::from_hir(db, &resolver, type_ref) | 313 | Ty::from_hir(db, &resolver, type_ref) |
295 | } | 314 | } |
296 | 315 | ||
316 | /// Resolve the where clause(s) of an item with generics. | ||
317 | pub(crate) fn generic_predicates( | ||
318 | db: &impl HirDatabase, | ||
319 | def: GenericDef, | ||
320 | ) -> Arc<[GenericPredicate]> { | ||
321 | let resolver = def.resolver(db); | ||
322 | let generic_params = def.generic_params(db); | ||
323 | let predicates = generic_params | ||
324 | .where_predicates | ||
325 | .iter() | ||
326 | .map(|pred| { | ||
327 | TraitRef::for_where_predicate(db, &resolver, pred) | ||
328 | .map_or(GenericPredicate::Error, GenericPredicate::Implemented) | ||
329 | }) | ||
330 | .collect::<Vec<_>>(); | ||
331 | predicates.into() | ||
332 | } | ||
333 | |||
297 | fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { | 334 | fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { |
298 | let signature = def.signature(db); | 335 | let signature = def.signature(db); |
299 | let resolver = def.resolver(db); | 336 | let resolver = def.resolver(db); |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index a38fe35c7..59c85daed 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -2502,6 +2502,21 @@ fn test() { (&S).foo()<|>; } | |||
2502 | } | 2502 | } |
2503 | 2503 | ||
2504 | #[test] | 2504 | #[test] |
2505 | fn method_resolution_where_clause_for_unknown_trait() { | ||
2506 | // The blanket impl shouldn't apply because we can't even resolve UnknownTrait | ||
2507 | let t = type_at( | ||
2508 | r#" | ||
2509 | //- /main.rs | ||
2510 | trait Trait { fn foo(self) -> u128; } | ||
2511 | struct S; | ||
2512 | impl<T> Trait for T where T: UnknownTrait {} | ||
2513 | fn test() { (&S).foo()<|>; } | ||
2514 | "#, | ||
2515 | ); | ||
2516 | assert_eq!(t, "{unknown}"); | ||
2517 | } | ||
2518 | |||
2519 | #[test] | ||
2505 | fn method_resolution_where_clause_not_met() { | 2520 | fn method_resolution_where_clause_not_met() { |
2506 | // The blanket impl shouldn't apply because we can't prove S: Clone | 2521 | // The blanket impl shouldn't apply because we can't prove S: Clone |
2507 | let t = type_at( | 2522 | let t = type_at( |
@@ -2510,12 +2525,122 @@ fn method_resolution_where_clause_not_met() { | |||
2510 | trait Clone {} | 2525 | trait Clone {} |
2511 | trait Trait { fn foo(self) -> u128; } | 2526 | trait Trait { fn foo(self) -> u128; } |
2512 | struct S; | 2527 | struct S; |
2513 | impl S { fn foo(self) -> i8 { 0 } } | 2528 | impl<T> Trait for T where T: Clone {} |
2514 | impl<T> Trait for T where T: Clone { fn foo(self) -> u128 { 0 } } | ||
2515 | fn test() { (&S).foo()<|>; } | 2529 | fn test() { (&S).foo()<|>; } |
2516 | "#, | 2530 | "#, |
2517 | ); | 2531 | ); |
2518 | assert_eq!(t, "i8"); | 2532 | // This is also to make sure that we don't resolve to the foo method just |
2533 | // because that's the only method named foo we can find, which would make | ||
2534 | // the below tests not work | ||
2535 | assert_eq!(t, "{unknown}"); | ||
2536 | } | ||
2537 | |||
2538 | #[test] | ||
2539 | fn method_resolution_where_clause_inline_not_met() { | ||
2540 | // The blanket impl shouldn't apply because we can't prove S: Clone | ||
2541 | let t = type_at( | ||
2542 | r#" | ||
2543 | //- /main.rs | ||
2544 | trait Clone {} | ||
2545 | trait Trait { fn foo(self) -> u128; } | ||
2546 | struct S; | ||
2547 | impl<T: Clone> Trait for T {} | ||
2548 | fn test() { (&S).foo()<|>; } | ||
2549 | "#, | ||
2550 | ); | ||
2551 | assert_eq!(t, "{unknown}"); | ||
2552 | } | ||
2553 | |||
2554 | #[test] | ||
2555 | fn method_resolution_where_clause_1() { | ||
2556 | let t = type_at( | ||
2557 | r#" | ||
2558 | //- /main.rs | ||
2559 | trait Clone {} | ||
2560 | trait Trait { fn foo(self) -> u128; } | ||
2561 | struct S; | ||
2562 | impl Clone for S {}; | ||
2563 | impl<T> Trait for T where T: Clone {} | ||
2564 | fn test() { S.foo()<|>; } | ||
2565 | "#, | ||
2566 | ); | ||
2567 | assert_eq!(t, "u128"); | ||
2568 | } | ||
2569 | |||
2570 | #[test] | ||
2571 | fn method_resolution_where_clause_2() { | ||
2572 | let t = type_at( | ||
2573 | r#" | ||
2574 | //- /main.rs | ||
2575 | trait Into<T> { fn into(self) -> T; } | ||
2576 | trait From<T> { fn from(other: T) -> Self; } | ||
2577 | struct S1; | ||
2578 | struct S2; | ||
2579 | impl From<S2> for S1 {}; | ||
2580 | impl<T, U> Into<U> for T where U: From<T> {} | ||
2581 | fn test() { S2.into()<|>; } | ||
2582 | "#, | ||
2583 | ); | ||
2584 | assert_eq!(t, "S1"); | ||
2585 | } | ||
2586 | |||
2587 | #[test] | ||
2588 | fn method_resolution_where_clause_inline() { | ||
2589 | let t = type_at( | ||
2590 | r#" | ||
2591 | //- /main.rs | ||
2592 | trait Into<T> { fn into(self) -> T; } | ||
2593 | trait From<T> { fn from(other: T) -> Self; } | ||
2594 | struct S1; | ||
2595 | struct S2; | ||
2596 | impl From<S2> for S1 {}; | ||
2597 | impl<T, U: From<T>> Into<U> for T {} | ||
2598 | fn test() { S2.into()<|>; } | ||
2599 | "#, | ||
2600 | ); | ||
2601 | assert_eq!(t, "S1"); | ||
2602 | } | ||
2603 | |||
2604 | #[test] | ||
2605 | fn method_resolution_encountering_fn_type() { | ||
2606 | covers!(trait_resolution_on_fn_type); | ||
2607 | type_at( | ||
2608 | r#" | ||
2609 | //- /main.rs | ||
2610 | fn foo() {} | ||
2611 | trait FnOnce { fn call(self); } | ||
2612 | fn test() { foo.call()<|>; } | ||
2613 | "#, | ||
2614 | ); | ||
2615 | } | ||
2616 | |||
2617 | #[test] | ||
2618 | fn method_resolution_slow() { | ||
2619 | // this can get quite slow if we set the solver size limit too high | ||
2620 | let t = type_at( | ||
2621 | r#" | ||
2622 | //- /main.rs | ||
2623 | trait Send {} | ||
2624 | |||
2625 | struct S1; impl Send for S1; | ||
2626 | struct S2; impl Send for S2; | ||
2627 | struct U1; | ||
2628 | |||
2629 | trait Trait { fn method(self); } | ||
2630 | |||
2631 | struct X1<A, B> {} | ||
2632 | impl<A, B> Send for X1<A, B> where A: Send, B: Send {} | ||
2633 | |||
2634 | struct S<B, C> {} | ||
2635 | |||
2636 | trait Fn {} | ||
2637 | |||
2638 | impl<B, C> Trait for S<B, C> where C: Fn, B: Send {} | ||
2639 | |||
2640 | fn test() { (S {}).method()<|>; } | ||
2641 | "#, | ||
2642 | ); | ||
2643 | assert_eq!(t, "{unknown}"); | ||
2519 | } | 2644 | } |
2520 | 2645 | ||
2521 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { | 2646 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { |
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs index 4bbc99f0e..4260f7ef7 100644 --- a/crates/ra_hir/src/ty/traits.rs +++ b/crates/ra_hir/src/ty/traits.rs | |||
@@ -14,6 +14,11 @@ mod chalk; | |||
14 | 14 | ||
15 | pub(crate) type Solver = chalk_solve::Solver; | 15 | pub(crate) type Solver = chalk_solve::Solver; |
16 | 16 | ||
17 | /// This controls the maximum size of types Chalk considers. If we set this too | ||
18 | /// high, we can run into slow edge cases; if we set it too low, Chalk won't | ||
19 | /// find some solutions. | ||
20 | const CHALK_SOLVER_MAX_SIZE: usize = 2; | ||
21 | |||
17 | #[derive(Debug, Copy, Clone)] | 22 | #[derive(Debug, Copy, Clone)] |
18 | struct ChalkContext<'a, DB> { | 23 | struct ChalkContext<'a, DB> { |
19 | db: &'a DB, | 24 | db: &'a DB, |
@@ -22,7 +27,8 @@ struct ChalkContext<'a, DB> { | |||
22 | 27 | ||
23 | pub(crate) fn solver(_db: &impl HirDatabase, _krate: Crate) -> Arc<Mutex<Solver>> { | 28 | pub(crate) fn solver(_db: &impl HirDatabase, _krate: Crate) -> Arc<Mutex<Solver>> { |
24 | // krate parameter is just so we cache a unique solver per crate | 29 | // krate parameter is just so we cache a unique solver per crate |
25 | let solver_choice = chalk_solve::SolverChoice::SLG { max_size: 10 }; | 30 | let solver_choice = chalk_solve::SolverChoice::SLG { max_size: CHALK_SOLVER_MAX_SIZE }; |
31 | debug!("Creating new solver for crate {:?}", _krate); | ||
26 | Arc::new(Mutex::new(solver_choice.into_solver())) | 32 | Arc::new(Mutex::new(solver_choice.into_solver())) |
27 | } | 33 | } |
28 | 34 | ||
@@ -53,6 +59,7 @@ fn solve( | |||
53 | ) -> Option<chalk_solve::Solution> { | 59 | ) -> Option<chalk_solve::Solution> { |
54 | let context = ChalkContext { db, krate }; | 60 | let context = ChalkContext { db, krate }; |
55 | let solver = db.solver(krate); | 61 | let solver = db.solver(krate); |
62 | debug!("solve goal: {:?}", goal); | ||
56 | let solution = solver.lock().unwrap().solve(&context, goal); | 63 | let solution = solver.lock().unwrap().solve(&context, goal); |
57 | debug!("solve({:?}) => {:?}", goal, solution); | 64 | debug!("solve({:?}) => {:?}", goal, solution); |
58 | solution | 65 | solution |
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 8b77d21b4..027c5ec4c 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs | |||
@@ -6,15 +6,22 @@ use log::debug; | |||
6 | use chalk_ir::{TypeId, ImplId, TypeKindId, ProjectionTy, Parameter, Identifier, cast::Cast, PlaceholderIndex, UniverseIndex, TypeName}; | 6 | use chalk_ir::{TypeId, ImplId, TypeKindId, ProjectionTy, Parameter, Identifier, cast::Cast, PlaceholderIndex, UniverseIndex, TypeName}; |
7 | use chalk_rust_ir::{AssociatedTyDatum, TraitDatum, StructDatum, ImplDatum}; | 7 | use chalk_rust_ir::{AssociatedTyDatum, TraitDatum, StructDatum, ImplDatum}; |
8 | 8 | ||
9 | use test_utils::tested_by; | ||
9 | use ra_db::salsa::{InternId, InternKey}; | 10 | use ra_db::salsa::{InternId, InternKey}; |
10 | 11 | ||
11 | use crate::{ | 12 | use crate::{ |
12 | Trait, HasGenericParams, ImplBlock, | 13 | Trait, HasGenericParams, ImplBlock, |
13 | db::HirDatabase, | 14 | db::HirDatabase, |
14 | ty::{TraitRef, Ty, ApplicationTy, TypeCtor, Substs}, | 15 | ty::{TraitRef, Ty, ApplicationTy, TypeCtor, Substs, GenericPredicate, CallableDef}, |
16 | ty::display::HirDisplay, | ||
17 | generics::GenericDef, | ||
15 | }; | 18 | }; |
16 | use super::ChalkContext; | 19 | use super::ChalkContext; |
17 | 20 | ||
21 | /// This represents a trait whose name we could not resolve. | ||
22 | const UNKNOWN_TRAIT: chalk_ir::TraitId = | ||
23 | chalk_ir::TraitId(chalk_ir::RawId { index: u32::max_value() }); | ||
24 | |||
18 | pub(super) trait ToChalk { | 25 | pub(super) trait ToChalk { |
19 | type Chalk; | 26 | type Chalk; |
20 | fn to_chalk(self, db: &impl HirDatabase) -> Self::Chalk; | 27 | fn to_chalk(self, db: &impl HirDatabase) -> Self::Chalk; |
@@ -45,7 +52,10 @@ impl ToChalk for Ty { | |||
45 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), | 52 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), |
46 | // FIXME this is clearly incorrect, but probably not too incorrect | 53 | // FIXME this is clearly incorrect, but probably not too incorrect |
47 | // and I'm not sure what to actually do with Ty::Unknown | 54 | // and I'm not sure what to actually do with Ty::Unknown |
48 | Ty::Unknown => PlaceholderIndex { ui: UniverseIndex::ROOT, idx: 0 }.to_ty(), | 55 | // maybe an alternative would be `for<T> T`? (meaningless in rust, but expressible in chalk's Ty) |
56 | Ty::Unknown => { | ||
57 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::max_value() }.to_ty() | ||
58 | } | ||
49 | } | 59 | } |
50 | } | 60 | } |
51 | fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty) -> Self { | 61 | fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty) -> Self { |
@@ -146,6 +156,33 @@ impl ToChalk for ImplBlock { | |||
146 | } | 156 | } |
147 | } | 157 | } |
148 | 158 | ||
159 | impl ToChalk for GenericPredicate { | ||
160 | type Chalk = chalk_ir::QuantifiedWhereClause; | ||
161 | |||
162 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::QuantifiedWhereClause { | ||
163 | match self { | ||
164 | GenericPredicate::Implemented(trait_ref) => { | ||
165 | make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0) | ||
166 | } | ||
167 | GenericPredicate::Error => { | ||
168 | let impossible_trait_ref = chalk_ir::TraitRef { | ||
169 | trait_id: UNKNOWN_TRAIT, | ||
170 | parameters: vec![Ty::Unknown.to_chalk(db).cast()], | ||
171 | }; | ||
172 | make_binders(chalk_ir::WhereClause::Implemented(impossible_trait_ref), 0) | ||
173 | } | ||
174 | } | ||
175 | } | ||
176 | |||
177 | fn from_chalk( | ||
178 | _db: &impl HirDatabase, | ||
179 | _where_clause: chalk_ir::QuantifiedWhereClause, | ||
180 | ) -> GenericPredicate { | ||
181 | // This should never need to be called | ||
182 | unimplemented!() | ||
183 | } | ||
184 | } | ||
185 | |||
149 | fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { | 186 | fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { |
150 | chalk_ir::Binders { | 187 | chalk_ir::Binders { |
151 | value, | 188 | value, |
@@ -153,6 +190,19 @@ fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { | |||
153 | } | 190 | } |
154 | } | 191 | } |
155 | 192 | ||
193 | fn convert_where_clauses( | ||
194 | db: &impl HirDatabase, | ||
195 | def: GenericDef, | ||
196 | substs: &Substs, | ||
197 | ) -> Vec<chalk_ir::QuantifiedWhereClause> { | ||
198 | let generic_predicates = db.generic_predicates(def); | ||
199 | let mut result = Vec::with_capacity(generic_predicates.len()); | ||
200 | for pred in generic_predicates.iter() { | ||
201 | result.push(pred.clone().subst(substs).to_chalk(db)); | ||
202 | } | ||
203 | result | ||
204 | } | ||
205 | |||
156 | impl<'a, DB> chalk_solve::RustIrDatabase for ChalkContext<'a, DB> | 206 | impl<'a, DB> chalk_solve::RustIrDatabase for ChalkContext<'a, DB> |
157 | where | 207 | where |
158 | DB: HirDatabase, | 208 | DB: HirDatabase, |
@@ -162,18 +212,35 @@ where | |||
162 | } | 212 | } |
163 | fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc<TraitDatum> { | 213 | fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc<TraitDatum> { |
164 | debug!("trait_datum {:?}", trait_id); | 214 | debug!("trait_datum {:?}", trait_id); |
215 | if trait_id == UNKNOWN_TRAIT { | ||
216 | let trait_datum_bound = chalk_rust_ir::TraitDatumBound { | ||
217 | trait_ref: chalk_ir::TraitRef { | ||
218 | trait_id: UNKNOWN_TRAIT, | ||
219 | parameters: vec![chalk_ir::Ty::BoundVar(0).cast()], | ||
220 | }, | ||
221 | associated_ty_ids: Vec::new(), | ||
222 | where_clauses: Vec::new(), | ||
223 | flags: chalk_rust_ir::TraitFlags { | ||
224 | auto: false, | ||
225 | marker: false, | ||
226 | upstream: true, | ||
227 | fundamental: false, | ||
228 | }, | ||
229 | }; | ||
230 | return Arc::new(TraitDatum { binders: make_binders(trait_datum_bound, 1) }); | ||
231 | } | ||
165 | let trait_: Trait = from_chalk(self.db, trait_id); | 232 | let trait_: Trait = from_chalk(self.db, trait_id); |
166 | let generic_params = trait_.generic_params(self.db); | 233 | let generic_params = trait_.generic_params(self.db); |
167 | let bound_vars = Substs::bound_vars(&generic_params); | 234 | let bound_vars = Substs::bound_vars(&generic_params); |
168 | let trait_ref = trait_.trait_ref(self.db).subst(&bound_vars).to_chalk(self.db); | 235 | let trait_ref = trait_.trait_ref(self.db).subst(&bound_vars).to_chalk(self.db); |
169 | let flags = chalk_rust_ir::TraitFlags { | 236 | let flags = chalk_rust_ir::TraitFlags { |
237 | auto: trait_.is_auto(self.db), | ||
238 | upstream: trait_.module(self.db).krate(self.db) != Some(self.krate), | ||
170 | // FIXME set these flags correctly | 239 | // FIXME set these flags correctly |
171 | auto: false, | ||
172 | marker: false, | 240 | marker: false, |
173 | upstream: trait_.module(self.db).krate(self.db) != Some(self.krate), | ||
174 | fundamental: false, | 241 | fundamental: false, |
175 | }; | 242 | }; |
176 | let where_clauses = Vec::new(); // FIXME add where clauses | 243 | let where_clauses = convert_where_clauses(self.db, trait_.into(), &bound_vars); |
177 | let associated_ty_ids = Vec::new(); // FIXME add associated tys | 244 | let associated_ty_ids = Vec::new(); // FIXME add associated tys |
178 | let trait_datum_bound = | 245 | let trait_datum_bound = |
179 | chalk_rust_ir::TraitDatumBound { trait_ref, where_clauses, flags, associated_ty_ids }; | 246 | chalk_rust_ir::TraitDatumBound { trait_ref, where_clauses, flags, associated_ty_ids }; |
@@ -185,21 +252,48 @@ where | |||
185 | let type_ctor = from_chalk(self.db, struct_id); | 252 | let type_ctor = from_chalk(self.db, struct_id); |
186 | // FIXME might be nicer if we can create a fake GenericParams for the TypeCtor | 253 | // FIXME might be nicer if we can create a fake GenericParams for the TypeCtor |
187 | // FIXME extract this to a method on Ty | 254 | // FIXME extract this to a method on Ty |
188 | let (num_params, upstream) = match type_ctor { | 255 | let (num_params, where_clauses, upstream) = match type_ctor { |
189 | TypeCtor::Bool | 256 | TypeCtor::Bool |
190 | | TypeCtor::Char | 257 | | TypeCtor::Char |
191 | | TypeCtor::Int(_) | 258 | | TypeCtor::Int(_) |
192 | | TypeCtor::Float(_) | 259 | | TypeCtor::Float(_) |
193 | | TypeCtor::Never | 260 | | TypeCtor::Never |
194 | | TypeCtor::Str => (0, true), | 261 | | TypeCtor::Str => (0, vec![], true), |
195 | TypeCtor::Slice | TypeCtor::Array | TypeCtor::RawPtr(_) | TypeCtor::Ref(_) => (1, true), | 262 | TypeCtor::Slice | TypeCtor::Array | TypeCtor::RawPtr(_) | TypeCtor::Ref(_) => { |
196 | TypeCtor::FnPtr { num_args } => (num_args as usize + 1, true), | 263 | (1, vec![], true) |
197 | TypeCtor::Tuple { cardinality } => (cardinality as usize, true), | 264 | } |
198 | TypeCtor::FnDef(_) => unimplemented!(), | 265 | TypeCtor::FnPtr { num_args } => (num_args as usize + 1, vec![], true), |
266 | TypeCtor::Tuple { cardinality } => (cardinality as usize, vec![], true), | ||
267 | TypeCtor::FnDef(callable) => { | ||
268 | tested_by!(trait_resolution_on_fn_type); | ||
269 | let krate = match callable { | ||
270 | CallableDef::Function(f) => f.module(self.db).krate(self.db), | ||
271 | CallableDef::Struct(s) => s.module(self.db).krate(self.db), | ||
272 | CallableDef::EnumVariant(v) => { | ||
273 | v.parent_enum(self.db).module(self.db).krate(self.db) | ||
274 | } | ||
275 | }; | ||
276 | let generic_def: GenericDef = match callable { | ||
277 | CallableDef::Function(f) => f.into(), | ||
278 | CallableDef::Struct(s) => s.into(), | ||
279 | CallableDef::EnumVariant(v) => v.parent_enum(self.db).into(), | ||
280 | }; | ||
281 | let generic_params = generic_def.generic_params(self.db); | ||
282 | let bound_vars = Substs::bound_vars(&generic_params); | ||
283 | let where_clauses = convert_where_clauses(self.db, generic_def, &bound_vars); | ||
284 | ( | ||
285 | generic_params.count_params_including_parent(), | ||
286 | where_clauses, | ||
287 | krate != Some(self.krate), | ||
288 | ) | ||
289 | } | ||
199 | TypeCtor::Adt(adt) => { | 290 | TypeCtor::Adt(adt) => { |
200 | let generic_params = adt.generic_params(self.db); | 291 | let generic_params = adt.generic_params(self.db); |
292 | let bound_vars = Substs::bound_vars(&generic_params); | ||
293 | let where_clauses = convert_where_clauses(self.db, adt.into(), &bound_vars); | ||
201 | ( | 294 | ( |
202 | generic_params.count_params_including_parent(), | 295 | generic_params.count_params_including_parent(), |
296 | where_clauses, | ||
203 | adt.krate(self.db) != Some(self.krate), | 297 | adt.krate(self.db) != Some(self.krate), |
204 | ) | 298 | ) |
205 | } | 299 | } |
@@ -209,7 +303,6 @@ where | |||
209 | // FIXME set fundamental flag correctly | 303 | // FIXME set fundamental flag correctly |
210 | fundamental: false, | 304 | fundamental: false, |
211 | }; | 305 | }; |
212 | let where_clauses = Vec::new(); // FIXME add where clauses | ||
213 | let self_ty = chalk_ir::ApplicationTy { | 306 | let self_ty = chalk_ir::ApplicationTy { |
214 | name: TypeName::TypeKindId(type_ctor.to_chalk(self.db).into()), | 307 | name: TypeName::TypeKindId(type_ctor.to_chalk(self.db).into()), |
215 | parameters: (0..num_params).map(|i| chalk_ir::Ty::BoundVar(i).cast()).collect(), | 308 | parameters: (0..num_params).map(|i| chalk_ir::Ty::BoundVar(i).cast()).collect(), |
@@ -237,10 +330,23 @@ where | |||
237 | } else { | 330 | } else { |
238 | chalk_rust_ir::ImplType::External | 331 | chalk_rust_ir::ImplType::External |
239 | }; | 332 | }; |
333 | let where_clauses = convert_where_clauses(self.db, impl_block.into(), &bound_vars); | ||
334 | let negative = impl_block.is_negative(self.db); | ||
335 | debug!( | ||
336 | "impl {:?}: {}{} where {:?}", | ||
337 | impl_id, | ||
338 | if negative { "!" } else { "" }, | ||
339 | trait_ref.display(self.db), | ||
340 | where_clauses | ||
341 | ); | ||
342 | let trait_ref = trait_ref.to_chalk(self.db); | ||
240 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { | 343 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { |
241 | // FIXME handle negative impls (impl !Sync for Foo) | 344 | trait_ref: if negative { |
242 | trait_ref: chalk_rust_ir::PolarizedTraitRef::Positive(trait_ref.to_chalk(self.db)), | 345 | chalk_rust_ir::PolarizedTraitRef::Negative(trait_ref) |
243 | where_clauses: Vec::new(), // FIXME add where clauses | 346 | } else { |
347 | chalk_rust_ir::PolarizedTraitRef::Positive(trait_ref) | ||
348 | }, | ||
349 | where_clauses, | ||
244 | associated_ty_values: Vec::new(), // FIXME add associated type values | 350 | associated_ty_values: Vec::new(), // FIXME add associated type values |
245 | impl_type, | 351 | impl_type, |
246 | }; | 352 | }; |
@@ -249,16 +355,18 @@ where | |||
249 | } | 355 | } |
250 | fn impls_for_trait(&self, trait_id: chalk_ir::TraitId) -> Vec<ImplId> { | 356 | fn impls_for_trait(&self, trait_id: chalk_ir::TraitId) -> Vec<ImplId> { |
251 | debug!("impls_for_trait {:?}", trait_id); | 357 | debug!("impls_for_trait {:?}", trait_id); |
358 | if trait_id == UNKNOWN_TRAIT { | ||
359 | return Vec::new(); | ||
360 | } | ||
252 | let trait_ = from_chalk(self.db, trait_id); | 361 | let trait_ = from_chalk(self.db, trait_id); |
253 | self.db | 362 | let result: Vec<_> = self |
363 | .db | ||
254 | .impls_for_trait(self.krate, trait_) | 364 | .impls_for_trait(self.krate, trait_) |
255 | .iter() | 365 | .iter() |
256 | // FIXME temporary hack -- as long as we're not lowering where clauses | ||
257 | // correctly, ignore impls with them completely so as to not treat | ||
258 | // impl<T> Trait for T where T: ... as a blanket impl on all types | ||
259 | .filter(|impl_block| impl_block.generic_params(self.db).where_predicates.is_empty()) | ||
260 | .map(|impl_block| impl_block.to_chalk(self.db)) | 366 | .map(|impl_block| impl_block.to_chalk(self.db)) |
261 | .collect() | 367 | .collect(); |
368 | debug!("impls_for_trait returned {} impls", result.len()); | ||
369 | result | ||
262 | } | 370 | } |
263 | fn impl_provided_for( | 371 | fn impl_provided_for( |
264 | &self, | 372 | &self, |