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