diff options
Diffstat (limited to 'crates/ra_hir_ty/src/lower.rs')
-rw-r--r-- | crates/ra_hir_ty/src/lower.rs | 753 |
1 files changed, 753 insertions, 0 deletions
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs new file mode 100644 index 000000000..53d955a12 --- /dev/null +++ b/crates/ra_hir_ty/src/lower.rs | |||
@@ -0,0 +1,753 @@ | |||
1 | //! Methods for lowering the HIR to types. There are two main cases here: | ||
2 | //! | ||
3 | //! - Lowering a type reference like `&usize` or `Option<foo::bar::Baz>` to a | ||
4 | //! type: The entry point for this is `Ty::from_hir`. | ||
5 | //! - Building the type for an item: This happens through the `type_for_def` query. | ||
6 | //! | ||
7 | //! This usually involves resolving names, collecting generic arguments etc. | ||
8 | use std::iter; | ||
9 | use std::sync::Arc; | ||
10 | |||
11 | use hir_def::{ | ||
12 | builtin_type::BuiltinType, | ||
13 | generics::WherePredicate, | ||
14 | path::{GenericArg, Path, PathKind, PathSegment}, | ||
15 | resolver::{HasResolver, Resolver, TypeNs}, | ||
16 | type_ref::{TypeBound, TypeRef}, | ||
17 | AdtId, AstItemDef, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, | ||
18 | LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId, | ||
19 | }; | ||
20 | use ra_arena::map::ArenaMap; | ||
21 | use ra_db::CrateId; | ||
22 | |||
23 | use super::{ | ||
24 | FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, | ||
25 | Ty, TypeCtor, TypeWalk, | ||
26 | }; | ||
27 | use crate::{ | ||
28 | db::HirDatabase, | ||
29 | primitive::{FloatTy, IntTy}, | ||
30 | utils::make_mut_slice, | ||
31 | utils::{all_super_traits, associated_type_by_name_including_super_traits, variant_data}, | ||
32 | }; | ||
33 | |||
34 | impl Ty { | ||
35 | pub fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { | ||
36 | match type_ref { | ||
37 | TypeRef::Never => Ty::simple(TypeCtor::Never), | ||
38 | TypeRef::Tuple(inner) => { | ||
39 | let inner_tys: Arc<[Ty]> = | ||
40 | inner.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect(); | ||
41 | Ty::apply( | ||
42 | TypeCtor::Tuple { cardinality: inner_tys.len() as u16 }, | ||
43 | Substs(inner_tys), | ||
44 | ) | ||
45 | } | ||
46 | TypeRef::Path(path) => Ty::from_hir_path(db, resolver, path), | ||
47 | TypeRef::RawPtr(inner, mutability) => { | ||
48 | let inner_ty = Ty::from_hir(db, resolver, inner); | ||
49 | Ty::apply_one(TypeCtor::RawPtr(*mutability), inner_ty) | ||
50 | } | ||
51 | TypeRef::Array(inner) => { | ||
52 | let inner_ty = Ty::from_hir(db, resolver, inner); | ||
53 | Ty::apply_one(TypeCtor::Array, inner_ty) | ||
54 | } | ||
55 | TypeRef::Slice(inner) => { | ||
56 | let inner_ty = Ty::from_hir(db, resolver, inner); | ||
57 | Ty::apply_one(TypeCtor::Slice, inner_ty) | ||
58 | } | ||
59 | TypeRef::Reference(inner, mutability) => { | ||
60 | let inner_ty = Ty::from_hir(db, resolver, inner); | ||
61 | Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) | ||
62 | } | ||
63 | TypeRef::Placeholder => Ty::Unknown, | ||
64 | TypeRef::Fn(params) => { | ||
65 | let sig = Substs(params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect()); | ||
66 | Ty::apply(TypeCtor::FnPtr { num_args: sig.len() as u16 - 1 }, sig) | ||
67 | } | ||
68 | TypeRef::DynTrait(bounds) => { | ||
69 | let self_ty = Ty::Bound(0); | ||
70 | let predicates = bounds | ||
71 | .iter() | ||
72 | .flat_map(|b| { | ||
73 | GenericPredicate::from_type_bound(db, resolver, b, self_ty.clone()) | ||
74 | }) | ||
75 | .collect(); | ||
76 | Ty::Dyn(predicates) | ||
77 | } | ||
78 | TypeRef::ImplTrait(bounds) => { | ||
79 | let self_ty = Ty::Bound(0); | ||
80 | let predicates = bounds | ||
81 | .iter() | ||
82 | .flat_map(|b| { | ||
83 | GenericPredicate::from_type_bound(db, resolver, b, self_ty.clone()) | ||
84 | }) | ||
85 | .collect(); | ||
86 | Ty::Opaque(predicates) | ||
87 | } | ||
88 | TypeRef::Error => Ty::Unknown, | ||
89 | } | ||
90 | } | ||
91 | |||
92 | /// This is only for `generic_predicates_for_param`, where we can't just | ||
93 | /// lower the self types of the predicates since that could lead to cycles. | ||
94 | /// So we just check here if the `type_ref` resolves to a generic param, and which. | ||
95 | fn from_hir_only_param( | ||
96 | db: &impl HirDatabase, | ||
97 | resolver: &Resolver, | ||
98 | type_ref: &TypeRef, | ||
99 | ) -> Option<u32> { | ||
100 | let path = match type_ref { | ||
101 | TypeRef::Path(path) => path, | ||
102 | _ => return None, | ||
103 | }; | ||
104 | if let PathKind::Type(_) = &path.kind { | ||
105 | return None; | ||
106 | } | ||
107 | if path.segments.len() > 1 { | ||
108 | return None; | ||
109 | } | ||
110 | let resolution = match resolver.resolve_path_in_type_ns(db, path) { | ||
111 | Some((it, None)) => it, | ||
112 | _ => return None, | ||
113 | }; | ||
114 | if let TypeNs::GenericParam(idx) = resolution { | ||
115 | Some(idx) | ||
116 | } else { | ||
117 | None | ||
118 | } | ||
119 | } | ||
120 | |||
121 | pub(crate) fn from_type_relative_path( | ||
122 | db: &impl HirDatabase, | ||
123 | resolver: &Resolver, | ||
124 | ty: Ty, | ||
125 | remaining_segments: &[PathSegment], | ||
126 | ) -> Ty { | ||
127 | if remaining_segments.len() == 1 { | ||
128 | // resolve unselected assoc types | ||
129 | let segment = &remaining_segments[0]; | ||
130 | Ty::select_associated_type(db, resolver, ty, segment) | ||
131 | } else if remaining_segments.len() > 1 { | ||
132 | // FIXME report error (ambiguous associated type) | ||
133 | Ty::Unknown | ||
134 | } else { | ||
135 | ty | ||
136 | } | ||
137 | } | ||
138 | |||
139 | pub(crate) fn from_partly_resolved_hir_path( | ||
140 | db: &impl HirDatabase, | ||
141 | resolver: &Resolver, | ||
142 | resolution: TypeNs, | ||
143 | resolved_segment: &PathSegment, | ||
144 | remaining_segments: &[PathSegment], | ||
145 | ) -> Ty { | ||
146 | let ty = match resolution { | ||
147 | TypeNs::TraitId(trait_) => { | ||
148 | let trait_ref = | ||
149 | TraitRef::from_resolved_path(db, resolver, trait_, resolved_segment, None); | ||
150 | return if remaining_segments.len() == 1 { | ||
151 | let segment = &remaining_segments[0]; | ||
152 | let associated_ty = associated_type_by_name_including_super_traits( | ||
153 | db, | ||
154 | trait_ref.trait_, | ||
155 | &segment.name, | ||
156 | ); | ||
157 | match associated_ty { | ||
158 | Some(associated_ty) => { | ||
159 | // FIXME handle type parameters on the segment | ||
160 | Ty::Projection(ProjectionTy { | ||
161 | associated_ty, | ||
162 | parameters: trait_ref.substs, | ||
163 | }) | ||
164 | } | ||
165 | None => { | ||
166 | // FIXME: report error (associated type not found) | ||
167 | Ty::Unknown | ||
168 | } | ||
169 | } | ||
170 | } else if remaining_segments.len() > 1 { | ||
171 | // FIXME report error (ambiguous associated type) | ||
172 | Ty::Unknown | ||
173 | } else { | ||
174 | Ty::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)])) | ||
175 | }; | ||
176 | } | ||
177 | TypeNs::GenericParam(idx) => { | ||
178 | // FIXME: maybe return name in resolution? | ||
179 | let name = resolved_segment.name.clone(); | ||
180 | Ty::Param { idx, name } | ||
181 | } | ||
182 | TypeNs::SelfType(impl_id) => { | ||
183 | let impl_data = db.impl_data(impl_id); | ||
184 | let resolver = impl_id.resolver(db); | ||
185 | Ty::from_hir(db, &resolver, &impl_data.target_type) | ||
186 | } | ||
187 | TypeNs::AdtSelfType(adt) => db.ty(adt.into()), | ||
188 | |||
189 | TypeNs::AdtId(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()), | ||
190 | TypeNs::BuiltinType(it) => { | ||
191 | Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()) | ||
192 | } | ||
193 | TypeNs::TypeAliasId(it) => { | ||
194 | Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()) | ||
195 | } | ||
196 | // FIXME: report error | ||
197 | TypeNs::EnumVariantId(_) => return Ty::Unknown, | ||
198 | }; | ||
199 | |||
200 | Ty::from_type_relative_path(db, resolver, ty, remaining_segments) | ||
201 | } | ||
202 | |||
203 | pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty { | ||
204 | // Resolve the path (in type namespace) | ||
205 | if let PathKind::Type(type_ref) = &path.kind { | ||
206 | let ty = Ty::from_hir(db, resolver, &type_ref); | ||
207 | let remaining_segments = &path.segments[..]; | ||
208 | return Ty::from_type_relative_path(db, resolver, ty, remaining_segments); | ||
209 | } | ||
210 | let (resolution, remaining_index) = match resolver.resolve_path_in_type_ns(db, path) { | ||
211 | Some(it) => it, | ||
212 | None => return Ty::Unknown, | ||
213 | }; | ||
214 | let (resolved_segment, remaining_segments) = match remaining_index { | ||
215 | None => ( | ||
216 | path.segments.last().expect("resolved path has at least one element"), | ||
217 | &[] as &[PathSegment], | ||
218 | ), | ||
219 | Some(i) => (&path.segments[i - 1], &path.segments[i..]), | ||
220 | }; | ||
221 | Ty::from_partly_resolved_hir_path( | ||
222 | db, | ||
223 | resolver, | ||
224 | resolution, | ||
225 | resolved_segment, | ||
226 | remaining_segments, | ||
227 | ) | ||
228 | } | ||
229 | |||
230 | fn select_associated_type( | ||
231 | db: &impl HirDatabase, | ||
232 | resolver: &Resolver, | ||
233 | self_ty: Ty, | ||
234 | segment: &PathSegment, | ||
235 | ) -> Ty { | ||
236 | let param_idx = match self_ty { | ||
237 | Ty::Param { idx, .. } => idx, | ||
238 | _ => return Ty::Unknown, // Error: Ambiguous associated type | ||
239 | }; | ||
240 | let def = match resolver.generic_def() { | ||
241 | Some(def) => def, | ||
242 | None => return Ty::Unknown, // this can't actually happen | ||
243 | }; | ||
244 | let predicates = db.generic_predicates_for_param(def.into(), param_idx); | ||
245 | let traits_from_env = predicates.iter().filter_map(|pred| match pred { | ||
246 | GenericPredicate::Implemented(tr) if tr.self_ty() == &self_ty => Some(tr.trait_), | ||
247 | _ => None, | ||
248 | }); | ||
249 | let traits = traits_from_env.flat_map(|t| all_super_traits(db, t)); | ||
250 | for t in traits { | ||
251 | if let Some(associated_ty) = db.trait_data(t).associated_type_by_name(&segment.name) { | ||
252 | let substs = | ||
253 | Substs::build_for_def(db, t).push(self_ty.clone()).fill_with_unknown().build(); | ||
254 | // FIXME handle type parameters on the segment | ||
255 | return Ty::Projection(ProjectionTy { associated_ty, parameters: substs }); | ||
256 | } | ||
257 | } | ||
258 | Ty::Unknown | ||
259 | } | ||
260 | |||
261 | fn from_hir_path_inner( | ||
262 | db: &impl HirDatabase, | ||
263 | resolver: &Resolver, | ||
264 | segment: &PathSegment, | ||
265 | typable: TyDefId, | ||
266 | ) -> Ty { | ||
267 | let generic_def = match typable { | ||
268 | TyDefId::BuiltinType(_) => None, | ||
269 | TyDefId::AdtId(it) => Some(it.into()), | ||
270 | TyDefId::TypeAliasId(it) => Some(it.into()), | ||
271 | }; | ||
272 | let substs = substs_from_path_segment(db, resolver, segment, generic_def, false); | ||
273 | db.ty(typable).subst(&substs) | ||
274 | } | ||
275 | |||
276 | /// Collect generic arguments from a path into a `Substs`. See also | ||
277 | /// `create_substs_for_ast_path` and `def_to_ty` in rustc. | ||
278 | pub(super) fn substs_from_path( | ||
279 | db: &impl HirDatabase, | ||
280 | resolver: &Resolver, | ||
281 | path: &Path, | ||
282 | // Note that we don't call `db.value_type(resolved)` here, | ||
283 | // `ValueTyDefId` is just a convenient way to pass generics and | ||
284 | // special-case enum variants | ||
285 | resolved: ValueTyDefId, | ||
286 | ) -> Substs { | ||
287 | let last = path.segments.last().expect("path should have at least one segment"); | ||
288 | let (segment, generic_def) = match resolved { | ||
289 | ValueTyDefId::FunctionId(it) => (last, Some(it.into())), | ||
290 | ValueTyDefId::StructId(it) => (last, Some(it.into())), | ||
291 | ValueTyDefId::ConstId(it) => (last, Some(it.into())), | ||
292 | ValueTyDefId::StaticId(_) => (last, None), | ||
293 | ValueTyDefId::EnumVariantId(var) => { | ||
294 | // the generic args for an enum variant may be either specified | ||
295 | // on the segment referring to the enum, or on the segment | ||
296 | // referring to the variant. So `Option::<T>::None` and | ||
297 | // `Option::None::<T>` are both allowed (though the former is | ||
298 | // preferred). See also `def_ids_for_path_segments` in rustc. | ||
299 | let len = path.segments.len(); | ||
300 | let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some() { | ||
301 | // Option::<T>::None | ||
302 | &path.segments[len - 2] | ||
303 | } else { | ||
304 | // Option::None::<T> | ||
305 | last | ||
306 | }; | ||
307 | (segment, Some(var.parent.into())) | ||
308 | } | ||
309 | }; | ||
310 | substs_from_path_segment(db, resolver, segment, generic_def, false) | ||
311 | } | ||
312 | } | ||
313 | |||
314 | pub(super) fn substs_from_path_segment( | ||
315 | db: &impl HirDatabase, | ||
316 | resolver: &Resolver, | ||
317 | segment: &PathSegment, | ||
318 | def_generic: Option<GenericDefId>, | ||
319 | add_self_param: bool, | ||
320 | ) -> Substs { | ||
321 | let mut substs = Vec::new(); | ||
322 | let def_generics = def_generic.map(|def| db.generic_params(def.into())); | ||
323 | |||
324 | let (parent_param_count, param_count) = | ||
325 | def_generics.map_or((0, 0), |g| (g.count_parent_params(), g.params.len())); | ||
326 | substs.extend(iter::repeat(Ty::Unknown).take(parent_param_count)); | ||
327 | if add_self_param { | ||
328 | // FIXME this add_self_param argument is kind of a hack: Traits have the | ||
329 | // Self type as an implicit first type parameter, but it can't be | ||
330 | // actually provided in the type arguments | ||
331 | // (well, actually sometimes it can, in the form of type-relative paths: `<Foo as Default>::default()`) | ||
332 | substs.push(Ty::Unknown); | ||
333 | } | ||
334 | if let Some(generic_args) = &segment.args_and_bindings { | ||
335 | // if args are provided, it should be all of them, but we can't rely on that | ||
336 | let self_param_correction = if add_self_param { 1 } else { 0 }; | ||
337 | let param_count = param_count - self_param_correction; | ||
338 | for arg in generic_args.args.iter().take(param_count) { | ||
339 | match arg { | ||
340 | GenericArg::Type(type_ref) => { | ||
341 | let ty = Ty::from_hir(db, resolver, type_ref); | ||
342 | substs.push(ty); | ||
343 | } | ||
344 | } | ||
345 | } | ||
346 | } | ||
347 | // add placeholders for args that were not provided | ||
348 | let supplied_params = substs.len(); | ||
349 | for _ in supplied_params..parent_param_count + param_count { | ||
350 | substs.push(Ty::Unknown); | ||
351 | } | ||
352 | assert_eq!(substs.len(), parent_param_count + param_count); | ||
353 | |||
354 | // handle defaults | ||
355 | if let Some(def_generic) = def_generic { | ||
356 | let default_substs = db.generic_defaults(def_generic.into()); | ||
357 | assert_eq!(substs.len(), default_substs.len()); | ||
358 | |||
359 | for (i, default_ty) in default_substs.iter().enumerate() { | ||
360 | if substs[i] == Ty::Unknown { | ||
361 | substs[i] = default_ty.clone(); | ||
362 | } | ||
363 | } | ||
364 | } | ||
365 | |||
366 | Substs(substs.into()) | ||
367 | } | ||
368 | |||
369 | impl TraitRef { | ||
370 | pub(crate) fn from_path( | ||
371 | db: &impl HirDatabase, | ||
372 | resolver: &Resolver, | ||
373 | path: &Path, | ||
374 | explicit_self_ty: Option<Ty>, | ||
375 | ) -> Option<Self> { | ||
376 | let resolved = match resolver.resolve_path_in_type_ns_fully(db, &path)? { | ||
377 | TypeNs::TraitId(tr) => tr, | ||
378 | _ => return None, | ||
379 | }; | ||
380 | let segment = path.segments.last().expect("path should have at least one segment"); | ||
381 | Some(TraitRef::from_resolved_path(db, resolver, resolved.into(), segment, explicit_self_ty)) | ||
382 | } | ||
383 | |||
384 | pub(super) fn from_resolved_path( | ||
385 | db: &impl HirDatabase, | ||
386 | resolver: &Resolver, | ||
387 | resolved: TraitId, | ||
388 | segment: &PathSegment, | ||
389 | explicit_self_ty: Option<Ty>, | ||
390 | ) -> Self { | ||
391 | let mut substs = TraitRef::substs_from_path(db, resolver, segment, resolved); | ||
392 | if let Some(self_ty) = explicit_self_ty { | ||
393 | make_mut_slice(&mut substs.0)[0] = self_ty; | ||
394 | } | ||
395 | TraitRef { trait_: resolved, substs } | ||
396 | } | ||
397 | |||
398 | pub(crate) fn from_hir( | ||
399 | db: &impl HirDatabase, | ||
400 | resolver: &Resolver, | ||
401 | type_ref: &TypeRef, | ||
402 | explicit_self_ty: Option<Ty>, | ||
403 | ) -> Option<Self> { | ||
404 | let path = match type_ref { | ||
405 | TypeRef::Path(path) => path, | ||
406 | _ => return None, | ||
407 | }; | ||
408 | TraitRef::from_path(db, resolver, path, explicit_self_ty) | ||
409 | } | ||
410 | |||
411 | fn substs_from_path( | ||
412 | db: &impl HirDatabase, | ||
413 | resolver: &Resolver, | ||
414 | segment: &PathSegment, | ||
415 | resolved: TraitId, | ||
416 | ) -> Substs { | ||
417 | let has_self_param = | ||
418 | segment.args_and_bindings.as_ref().map(|a| a.has_self_type).unwrap_or(false); | ||
419 | substs_from_path_segment(db, resolver, segment, Some(resolved.into()), !has_self_param) | ||
420 | } | ||
421 | |||
422 | pub fn for_trait(db: &impl HirDatabase, trait_: TraitId) -> TraitRef { | ||
423 | let substs = Substs::identity(&db.generic_params(trait_.into())); | ||
424 | TraitRef { trait_, substs } | ||
425 | } | ||
426 | |||
427 | pub(crate) fn from_type_bound( | ||
428 | db: &impl HirDatabase, | ||
429 | resolver: &Resolver, | ||
430 | bound: &TypeBound, | ||
431 | self_ty: Ty, | ||
432 | ) -> Option<TraitRef> { | ||
433 | match bound { | ||
434 | TypeBound::Path(path) => TraitRef::from_path(db, resolver, path, Some(self_ty)), | ||
435 | TypeBound::Error => None, | ||
436 | } | ||
437 | } | ||
438 | } | ||
439 | |||
440 | impl GenericPredicate { | ||
441 | pub(crate) fn from_where_predicate<'a>( | ||
442 | db: &'a impl HirDatabase, | ||
443 | resolver: &'a Resolver, | ||
444 | where_predicate: &'a WherePredicate, | ||
445 | ) -> impl Iterator<Item = GenericPredicate> + 'a { | ||
446 | let self_ty = Ty::from_hir(db, resolver, &where_predicate.type_ref); | ||
447 | GenericPredicate::from_type_bound(db, resolver, &where_predicate.bound, self_ty) | ||
448 | } | ||
449 | |||
450 | pub(crate) fn from_type_bound<'a>( | ||
451 | db: &'a impl HirDatabase, | ||
452 | resolver: &'a Resolver, | ||
453 | bound: &'a TypeBound, | ||
454 | self_ty: Ty, | ||
455 | ) -> impl Iterator<Item = GenericPredicate> + 'a { | ||
456 | let trait_ref = TraitRef::from_type_bound(db, &resolver, bound, self_ty); | ||
457 | iter::once(trait_ref.clone().map_or(GenericPredicate::Error, GenericPredicate::Implemented)) | ||
458 | .chain( | ||
459 | trait_ref.into_iter().flat_map(move |tr| { | ||
460 | assoc_type_bindings_from_type_bound(db, resolver, bound, tr) | ||
461 | }), | ||
462 | ) | ||
463 | } | ||
464 | } | ||
465 | |||
466 | fn assoc_type_bindings_from_type_bound<'a>( | ||
467 | db: &'a impl HirDatabase, | ||
468 | resolver: &'a Resolver, | ||
469 | bound: &'a TypeBound, | ||
470 | trait_ref: TraitRef, | ||
471 | ) -> impl Iterator<Item = GenericPredicate> + 'a { | ||
472 | let last_segment = match bound { | ||
473 | TypeBound::Path(path) => path.segments.last(), | ||
474 | TypeBound::Error => None, | ||
475 | }; | ||
476 | last_segment | ||
477 | .into_iter() | ||
478 | .flat_map(|segment| segment.args_and_bindings.iter()) | ||
479 | .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) | ||
480 | .map(move |(name, type_ref)| { | ||
481 | let associated_ty = | ||
482 | associated_type_by_name_including_super_traits(db, trait_ref.trait_, &name); | ||
483 | let associated_ty = match associated_ty { | ||
484 | None => return GenericPredicate::Error, | ||
485 | Some(t) => t, | ||
486 | }; | ||
487 | let projection_ty = | ||
488 | ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() }; | ||
489 | let ty = Ty::from_hir(db, resolver, type_ref); | ||
490 | let projection_predicate = ProjectionPredicate { projection_ty, ty }; | ||
491 | GenericPredicate::Projection(projection_predicate) | ||
492 | }) | ||
493 | } | ||
494 | |||
495 | /// Build the signature of a callable item (function, struct or enum variant). | ||
496 | pub fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSig { | ||
497 | match def { | ||
498 | CallableDef::FunctionId(f) => fn_sig_for_fn(db, f), | ||
499 | CallableDef::StructId(s) => fn_sig_for_struct_constructor(db, s), | ||
500 | CallableDef::EnumVariantId(e) => fn_sig_for_enum_variant_constructor(db, e), | ||
501 | } | ||
502 | } | ||
503 | |||
504 | /// Build the type of all specific fields of a struct or enum variant. | ||
505 | pub(crate) fn field_types_query( | ||
506 | db: &impl HirDatabase, | ||
507 | variant_id: VariantId, | ||
508 | ) -> Arc<ArenaMap<LocalStructFieldId, Ty>> { | ||
509 | let var_data = variant_data(db, variant_id); | ||
510 | let resolver = match variant_id { | ||
511 | VariantId::StructId(it) => it.resolver(db), | ||
512 | VariantId::UnionId(it) => it.resolver(db), | ||
513 | VariantId::EnumVariantId(it) => it.parent.resolver(db), | ||
514 | }; | ||
515 | let mut res = ArenaMap::default(); | ||
516 | for (field_id, field_data) in var_data.fields().iter() { | ||
517 | res.insert(field_id, Ty::from_hir(db, &resolver, &field_data.type_ref)) | ||
518 | } | ||
519 | Arc::new(res) | ||
520 | } | ||
521 | |||
522 | /// This query exists only to be used when resolving short-hand associated types | ||
523 | /// like `T::Item`. | ||
524 | /// | ||
525 | /// See the analogous query in rustc and its comment: | ||
526 | /// https://github.com/rust-lang/rust/blob/9150f844e2624eb013ec78ca08c1d416e6644026/src/librustc_typeck/astconv.rs#L46 | ||
527 | /// This is a query mostly to handle cycles somewhat gracefully; e.g. the | ||
528 | /// following bounds are disallowed: `T: Foo<U::Item>, U: Foo<T::Item>`, but | ||
529 | /// these are fine: `T: Foo<U::Item>, U: Foo<()>`. | ||
530 | pub(crate) fn generic_predicates_for_param_query( | ||
531 | db: &impl HirDatabase, | ||
532 | def: GenericDefId, | ||
533 | param_idx: u32, | ||
534 | ) -> Arc<[GenericPredicate]> { | ||
535 | let resolver = def.resolver(db); | ||
536 | resolver | ||
537 | .where_predicates_in_scope() | ||
538 | // we have to filter out all other predicates *first*, before attempting to lower them | ||
539 | .filter(|pred| Ty::from_hir_only_param(db, &resolver, &pred.type_ref) == Some(param_idx)) | ||
540 | .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) | ||
541 | .collect() | ||
542 | } | ||
543 | |||
544 | impl TraitEnvironment { | ||
545 | pub fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc<TraitEnvironment> { | ||
546 | let predicates = resolver | ||
547 | .where_predicates_in_scope() | ||
548 | .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) | ||
549 | .collect::<Vec<_>>(); | ||
550 | |||
551 | Arc::new(TraitEnvironment { predicates }) | ||
552 | } | ||
553 | } | ||
554 | |||
555 | /// Resolve the where clause(s) of an item with generics. | ||
556 | pub(crate) fn generic_predicates_query( | ||
557 | db: &impl HirDatabase, | ||
558 | def: GenericDefId, | ||
559 | ) -> Arc<[GenericPredicate]> { | ||
560 | let resolver = def.resolver(db); | ||
561 | resolver | ||
562 | .where_predicates_in_scope() | ||
563 | .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) | ||
564 | .collect() | ||
565 | } | ||
566 | |||
567 | /// Resolve the default type params from generics | ||
568 | pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDefId) -> Substs { | ||
569 | let resolver = def.resolver(db); | ||
570 | let generic_params = db.generic_params(def.into()); | ||
571 | |||
572 | let defaults = generic_params | ||
573 | .params_including_parent() | ||
574 | .into_iter() | ||
575 | .map(|p| p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(db, &resolver, t))) | ||
576 | .collect(); | ||
577 | |||
578 | Substs(defaults) | ||
579 | } | ||
580 | |||
581 | fn fn_sig_for_fn(db: &impl HirDatabase, def: FunctionId) -> FnSig { | ||
582 | let data = db.function_data(def); | ||
583 | let resolver = def.resolver(db); | ||
584 | let params = data.params.iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>(); | ||
585 | let ret = Ty::from_hir(db, &resolver, &data.ret_type); | ||
586 | FnSig::from_params_and_return(params, ret) | ||
587 | } | ||
588 | |||
589 | /// Build the declared type of a function. This should not need to look at the | ||
590 | /// function body. | ||
591 | fn type_for_fn(db: &impl HirDatabase, def: FunctionId) -> Ty { | ||
592 | let generics = db.generic_params(def.into()); | ||
593 | let substs = Substs::identity(&generics); | ||
594 | Ty::apply(TypeCtor::FnDef(def.into()), substs) | ||
595 | } | ||
596 | |||
597 | /// Build the declared type of a const. | ||
598 | fn type_for_const(db: &impl HirDatabase, def: ConstId) -> Ty { | ||
599 | let data = db.const_data(def); | ||
600 | let resolver = def.resolver(db); | ||
601 | |||
602 | Ty::from_hir(db, &resolver, &data.type_ref) | ||
603 | } | ||
604 | |||
605 | /// Build the declared type of a static. | ||
606 | fn type_for_static(db: &impl HirDatabase, def: StaticId) -> Ty { | ||
607 | let data = db.static_data(def); | ||
608 | let resolver = def.resolver(db); | ||
609 | |||
610 | Ty::from_hir(db, &resolver, &data.type_ref) | ||
611 | } | ||
612 | |||
613 | /// Build the declared type of a static. | ||
614 | fn type_for_builtin(def: BuiltinType) -> Ty { | ||
615 | Ty::simple(match def { | ||
616 | BuiltinType::Char => TypeCtor::Char, | ||
617 | BuiltinType::Bool => TypeCtor::Bool, | ||
618 | BuiltinType::Str => TypeCtor::Str, | ||
619 | BuiltinType::Int(t) => TypeCtor::Int(IntTy::from(t).into()), | ||
620 | BuiltinType::Float(t) => TypeCtor::Float(FloatTy::from(t).into()), | ||
621 | }) | ||
622 | } | ||
623 | |||
624 | fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> FnSig { | ||
625 | let struct_data = db.struct_data(def.into()); | ||
626 | let fields = struct_data.variant_data.fields(); | ||
627 | let resolver = def.resolver(db); | ||
628 | let params = fields | ||
629 | .iter() | ||
630 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) | ||
631 | .collect::<Vec<_>>(); | ||
632 | let ret = type_for_adt(db, def.into()); | ||
633 | FnSig::from_params_and_return(params, ret) | ||
634 | } | ||
635 | |||
636 | /// Build the type of a tuple struct constructor. | ||
637 | fn type_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> Ty { | ||
638 | let struct_data = db.struct_data(def.into()); | ||
639 | if struct_data.variant_data.is_unit() { | ||
640 | return type_for_adt(db, def.into()); // Unit struct | ||
641 | } | ||
642 | let generics = db.generic_params(def.into()); | ||
643 | let substs = Substs::identity(&generics); | ||
644 | Ty::apply(TypeCtor::FnDef(def.into()), substs) | ||
645 | } | ||
646 | |||
647 | fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> FnSig { | ||
648 | let enum_data = db.enum_data(def.parent); | ||
649 | let var_data = &enum_data.variants[def.local_id]; | ||
650 | let fields = var_data.variant_data.fields(); | ||
651 | let resolver = def.parent.resolver(db); | ||
652 | let params = fields | ||
653 | .iter() | ||
654 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) | ||
655 | .collect::<Vec<_>>(); | ||
656 | let generics = db.generic_params(def.parent.into()); | ||
657 | let substs = Substs::identity(&generics); | ||
658 | let ret = type_for_adt(db, def.parent.into()).subst(&substs); | ||
659 | FnSig::from_params_and_return(params, ret) | ||
660 | } | ||
661 | |||
662 | /// Build the type of a tuple enum variant constructor. | ||
663 | fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> Ty { | ||
664 | let enum_data = db.enum_data(def.parent); | ||
665 | let var_data = &enum_data.variants[def.local_id].variant_data; | ||
666 | if var_data.is_unit() { | ||
667 | return type_for_adt(db, def.parent.into()); // Unit variant | ||
668 | } | ||
669 | let generics = db.generic_params(def.parent.into()); | ||
670 | let substs = Substs::identity(&generics); | ||
671 | Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs) | ||
672 | } | ||
673 | |||
674 | fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Ty { | ||
675 | let generics = db.generic_params(adt.into()); | ||
676 | Ty::apply(TypeCtor::Adt(adt), Substs::identity(&generics)) | ||
677 | } | ||
678 | |||
679 | fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Ty { | ||
680 | let generics = db.generic_params(t.into()); | ||
681 | let resolver = t.resolver(db); | ||
682 | let type_ref = &db.type_alias_data(t).type_ref; | ||
683 | let substs = Substs::identity(&generics); | ||
684 | let inner = Ty::from_hir(db, &resolver, type_ref.as_ref().unwrap_or(&TypeRef::Error)); | ||
685 | inner.subst(&substs) | ||
686 | } | ||
687 | |||
688 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
689 | pub enum CallableDef { | ||
690 | FunctionId(FunctionId), | ||
691 | StructId(StructId), | ||
692 | EnumVariantId(EnumVariantId), | ||
693 | } | ||
694 | impl_froms!(CallableDef: FunctionId, StructId, EnumVariantId); | ||
695 | |||
696 | impl CallableDef { | ||
697 | pub fn krate(self, db: &impl HirDatabase) -> CrateId { | ||
698 | match self { | ||
699 | CallableDef::FunctionId(f) => f.lookup(db).module(db).krate, | ||
700 | CallableDef::StructId(s) => s.module(db).krate, | ||
701 | CallableDef::EnumVariantId(e) => e.parent.module(db).krate, | ||
702 | } | ||
703 | } | ||
704 | } | ||
705 | |||
706 | impl From<CallableDef> for GenericDefId { | ||
707 | fn from(def: CallableDef) -> GenericDefId { | ||
708 | match def { | ||
709 | CallableDef::FunctionId(f) => f.into(), | ||
710 | CallableDef::StructId(s) => s.into(), | ||
711 | CallableDef::EnumVariantId(e) => e.into(), | ||
712 | } | ||
713 | } | ||
714 | } | ||
715 | |||
716 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
717 | pub enum TyDefId { | ||
718 | BuiltinType(BuiltinType), | ||
719 | AdtId(AdtId), | ||
720 | TypeAliasId(TypeAliasId), | ||
721 | } | ||
722 | impl_froms!(TyDefId: BuiltinType, AdtId(StructId, EnumId, UnionId), TypeAliasId); | ||
723 | |||
724 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
725 | pub enum ValueTyDefId { | ||
726 | FunctionId(FunctionId), | ||
727 | StructId(StructId), | ||
728 | EnumVariantId(EnumVariantId), | ||
729 | ConstId(ConstId), | ||
730 | StaticId(StaticId), | ||
731 | } | ||
732 | impl_froms!(ValueTyDefId: FunctionId, StructId, EnumVariantId, ConstId, StaticId); | ||
733 | |||
734 | /// Build the declared type of an item. This depends on the namespace; e.g. for | ||
735 | /// `struct Foo(usize)`, we have two types: The type of the struct itself, and | ||
736 | /// the constructor function `(usize) -> Foo` which lives in the values | ||
737 | /// namespace. | ||
738 | pub(crate) fn ty_query(db: &impl HirDatabase, def: TyDefId) -> Ty { | ||
739 | match def { | ||
740 | TyDefId::BuiltinType(it) => type_for_builtin(it), | ||
741 | TyDefId::AdtId(it) => type_for_adt(db, it), | ||
742 | TyDefId::TypeAliasId(it) => type_for_type_alias(db, it), | ||
743 | } | ||
744 | } | ||
745 | pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty { | ||
746 | match def { | ||
747 | ValueTyDefId::FunctionId(it) => type_for_fn(db, it), | ||
748 | ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it), | ||
749 | ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it), | ||
750 | ValueTyDefId::ConstId(it) => type_for_const(db, it), | ||
751 | ValueTyDefId::StaticId(it) => type_for_static(db, it), | ||
752 | } | ||
753 | } | ||