aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/traits/builtin.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src/traits/builtin.rs')
-rw-r--r--crates/ra_hir_ty/src/traits/builtin.rs178
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`.
3use hir_def::{expr::Expr, TraitId, TypeAliasId};
4use hir_expand::name::name;
5use ra_db::CrateId;
6
7use super::{AssocTyValue, Impl};
8use crate::{
9 db::HirDatabase, ApplicationTy, BoundVar, DebruijnIndex, Substs, TraitRef, Ty, TypeCtor,
10};
11
12pub(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
19pub(super) struct BuiltinImplAssocTyValueData {
20 pub impl_: Impl,
21 pub assoc_ty_id: TypeAliasId,
22 pub num_vars: usize,
23 pub value: Ty,
24}
25
26pub(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
52pub(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
59pub(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
74fn 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
95fn 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
147fn 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}