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