diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-12-23 10:58:06 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2019-12-23 10:58:06 +0000 |
commit | ce07a2daa9e53aa86a769f8641b14c2878444fbc (patch) | |
tree | fc5802a209c642e862171a1d022634eefd2a03a9 /crates/ra_hir_ty/src/traits/builtin.rs | |
parent | 31c5888a4c0913c44d13f25f8cb79e0701e84f71 (diff) | |
parent | 1f7f4578f72721c1b0e17e8405f986fd2ce89aaf (diff) |
Merge #2636
2636: Chalk update and refactoring r=flodiebold a=flodiebold
This updates the Chalk integration to https://github.com/rust-lang/chalk/pull/311, which will presumably get merged soon, and refactors it some more, most notably introducing our own `TypeFamily` instead of reusing `ChalkIr`. It's still mostly the same as `ChalkIr` though, except for using Salsa `InternId`s directly.
Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir_ty/src/traits/builtin.rs')
-rw-r--r-- | crates/ra_hir_ty/src/traits/builtin.rs | 49 |
1 files changed, 33 insertions, 16 deletions
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 | ||
44 | pub(super) fn impl_datum( | 48 | pub(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 | ||
68 | fn 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 | |||
68 | fn closure_fn_trait_impl_datum( | 89 | fn 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 | ||
118 | fn closure_fn_trait_output_assoc_ty_value( | 135 | fn closure_fn_trait_output_assoc_ty_value( |