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