diff options
Diffstat (limited to 'crates/ra_hir_ty/src/traits/builtin.rs')
-rw-r--r-- | crates/ra_hir_ty/src/traits/builtin.rs | 178 |
1 files changed, 0 insertions, 178 deletions
diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs deleted file mode 100644 index 60cc9a9f5..000000000 --- a/crates/ra_hir_ty/src/traits/builtin.rs +++ /dev/null | |||
@@ -1,178 +0,0 @@ | |||
1 | //! This module provides the built-in trait implementations, e.g. to make | ||
2 | //! closures implement `Fn`. | ||
3 | use hir_def::{expr::Expr, TraitId, TypeAliasId}; | ||
4 | use hir_expand::name::name; | ||
5 | use ra_db::CrateId; | ||
6 | |||
7 | use super::{AssocTyValue, Impl}; | ||
8 | use crate::{ | ||
9 | db::HirDatabase, ApplicationTy, BoundVar, DebruijnIndex, Substs, TraitRef, Ty, TypeCtor, | ||
10 | }; | ||
11 | |||
12 | pub(super) struct BuiltinImplData { | ||
13 | pub num_vars: usize, | ||
14 | pub trait_ref: TraitRef, | ||
15 | pub where_clauses: Vec<super::GenericPredicate>, | ||
16 | pub assoc_ty_values: Vec<AssocTyValue>, | ||
17 | } | ||
18 | |||
19 | pub(super) struct BuiltinImplAssocTyValueData { | ||
20 | pub impl_: Impl, | ||
21 | pub assoc_ty_id: TypeAliasId, | ||
22 | pub num_vars: usize, | ||
23 | pub value: Ty, | ||
24 | } | ||
25 | |||
26 | pub(super) fn get_builtin_impls( | ||
27 | db: &dyn HirDatabase, | ||
28 | krate: CrateId, | ||
29 | ty: &Ty, | ||
30 | // The first argument for the trait, if present | ||
31 | _arg: &Option<Ty>, | ||
32 | trait_: TraitId, | ||
33 | mut callback: impl FnMut(Impl), | ||
34 | ) { | ||
35 | // Note: since impl_datum needs to be infallible, we need to make sure here | ||
36 | // that we have all prerequisites to build the respective impls. | ||
37 | if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty { | ||
38 | for &fn_trait in [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter() | ||
39 | { | ||
40 | if let Some(actual_trait) = fn_trait.get_id(db, krate) { | ||
41 | if trait_ == actual_trait { | ||
42 | let impl_ = super::ClosureFnTraitImplData { def: *def, expr: *expr, fn_trait }; | ||
43 | if check_closure_fn_trait_impl_prerequisites(db, krate, impl_) { | ||
44 | callback(Impl::ClosureFnTraitImpl(impl_)); | ||
45 | } | ||
46 | } | ||
47 | } | ||
48 | } | ||
49 | } | ||
50 | } | ||
51 | |||
52 | pub(super) fn impl_datum(db: &dyn HirDatabase, krate: CrateId, impl_: Impl) -> BuiltinImplData { | ||
53 | match impl_ { | ||
54 | Impl::ImplDef(_) => unreachable!(), | ||
55 | Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data), | ||
56 | } | ||
57 | } | ||
58 | |||
59 | pub(super) fn associated_ty_value( | ||
60 | db: &dyn HirDatabase, | ||
61 | krate: CrateId, | ||
62 | data: AssocTyValue, | ||
63 | ) -> BuiltinImplAssocTyValueData { | ||
64 | match data { | ||
65 | AssocTyValue::TypeAlias(_) => unreachable!(), | ||
66 | AssocTyValue::ClosureFnTraitImplOutput(data) => { | ||
67 | closure_fn_trait_output_assoc_ty_value(db, krate, data) | ||
68 | } | ||
69 | } | ||
70 | } | ||
71 | |||
72 | // Closure Fn trait impls | ||
73 | |||
74 | fn check_closure_fn_trait_impl_prerequisites( | ||
75 | db: &dyn HirDatabase, | ||
76 | krate: CrateId, | ||
77 | data: super::ClosureFnTraitImplData, | ||
78 | ) -> bool { | ||
79 | // the respective Fn/FnOnce/FnMut trait needs to exist | ||
80 | if data.fn_trait.get_id(db, krate).is_none() { | ||
81 | return false; | ||
82 | } | ||
83 | |||
84 | // FIXME: there are more assumptions that we should probably check here: | ||
85 | // the traits having no type params, FnOnce being a supertrait | ||
86 | |||
87 | // the FnOnce trait needs to exist and have an assoc type named Output | ||
88 | let fn_once_trait = match (super::FnTrait::FnOnce).get_id(db, krate) { | ||
89 | Some(t) => t, | ||
90 | None => return false, | ||
91 | }; | ||
92 | db.trait_data(fn_once_trait).associated_type_by_name(&name![Output]).is_some() | ||
93 | } | ||
94 | |||
95 | fn closure_fn_trait_impl_datum( | ||
96 | db: &dyn HirDatabase, | ||
97 | krate: CrateId, | ||
98 | data: super::ClosureFnTraitImplData, | ||
99 | ) -> BuiltinImplData { | ||
100 | // for some closure |X, Y| -> Z: | ||
101 | // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V } | ||
102 | |||
103 | let trait_ = data | ||
104 | .fn_trait | ||
105 | .get_id(db, krate) // get corresponding fn trait | ||
106 | // the existence of the Fn trait has been checked before | ||
107 | .expect("fn trait for closure impl missing"); | ||
108 | |||
109 | let num_args: u16 = match &db.body(data.def)[data.expr] { | ||
110 | Expr::Lambda { args, .. } => args.len() as u16, | ||
111 | _ => { | ||
112 | log::warn!("closure for closure type {:?} not found", data); | ||
113 | 0 | ||
114 | } | ||
115 | }; | ||
116 | |||
117 | let arg_ty = Ty::apply( | ||
118 | TypeCtor::Tuple { cardinality: num_args }, | ||
119 | Substs::builder(num_args as usize) | ||
120 | .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0) | ||
121 | .build(), | ||
122 | ); | ||
123 | let sig_ty = Ty::apply( | ||
124 | TypeCtor::FnPtr { num_args, is_varargs: false }, | ||
125 | Substs::builder(num_args as usize + 1) | ||
126 | .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0) | ||
127 | .build(), | ||
128 | ); | ||
129 | |||
130 | let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty); | ||
131 | |||
132 | let trait_ref = TraitRef { | ||
133 | trait_, | ||
134 | substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(), | ||
135 | }; | ||
136 | |||
137 | let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data); | ||
138 | |||
139 | BuiltinImplData { | ||
140 | num_vars: num_args as usize + 1, | ||
141 | trait_ref, | ||
142 | where_clauses: Vec::new(), | ||
143 | assoc_ty_values: vec![output_ty_id], | ||
144 | } | ||
145 | } | ||
146 | |||
147 | fn closure_fn_trait_output_assoc_ty_value( | ||
148 | db: &dyn HirDatabase, | ||
149 | krate: CrateId, | ||
150 | data: super::ClosureFnTraitImplData, | ||
151 | ) -> BuiltinImplAssocTyValueData { | ||
152 | let impl_ = Impl::ClosureFnTraitImpl(data); | ||
153 | |||
154 | let num_args: u16 = match &db.body(data.def)[data.expr] { | ||
155 | Expr::Lambda { args, .. } => args.len() as u16, | ||
156 | _ => { | ||
157 | log::warn!("closure for closure type {:?} not found", data); | ||
158 | 0 | ||
159 | } | ||
160 | }; | ||
161 | |||
162 | let output_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, num_args.into())); | ||
163 | |||
164 | let fn_once_trait = | ||
165 | (super::FnTrait::FnOnce).get_id(db, krate).expect("assoc ty value should not exist"); | ||
166 | |||
167 | let output_ty_id = db | ||
168 | .trait_data(fn_once_trait) | ||
169 | .associated_type_by_name(&name![Output]) | ||
170 | .expect("assoc ty value should not exist"); | ||
171 | |||
172 | BuiltinImplAssocTyValueData { | ||
173 | impl_, | ||
174 | assoc_ty_id: output_ty_id, | ||
175 | num_vars: num_args as usize + 1, | ||
176 | value: output_ty, | ||
177 | } | ||
178 | } | ||