diff options
Diffstat (limited to 'crates/hir_ty/src/lower.rs')
-rw-r--r-- | crates/hir_ty/src/lower.rs | 110 |
1 files changed, 93 insertions, 17 deletions
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 8a22d9ea3..c99dd8d0a 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -5,12 +5,14 @@ | |||
5 | //! - Building the type for an item: This happens through the `type_for_def` query. | 5 | //! - Building the type for an item: This happens through the `type_for_def` query. |
6 | //! | 6 | //! |
7 | //! This usually involves resolving names, collecting generic arguments etc. | 7 | //! This usually involves resolving names, collecting generic arguments etc. |
8 | use std::cell::{Cell, RefCell}; | ||
8 | use std::{iter, sync::Arc}; | 9 | use std::{iter, sync::Arc}; |
9 | 10 | ||
10 | use base_db::CrateId; | 11 | use base_db::CrateId; |
11 | use chalk_ir::{cast::Cast, fold::Shift, interner::HasInterner, Mutability, Safety}; | 12 | use chalk_ir::{cast::Cast, fold::Shift, interner::HasInterner, Mutability, Safety}; |
12 | use hir_def::{ | 13 | use hir_def::{ |
13 | adt::StructKind, | 14 | adt::StructKind, |
15 | body::{Expander, LowerCtx}, | ||
14 | builtin_type::BuiltinType, | 16 | builtin_type::BuiltinType, |
15 | generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget}, | 17 | generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget}, |
16 | path::{GenericArg, Path, PathSegment, PathSegments}, | 18 | path::{GenericArg, Path, PathSegment, PathSegments}, |
@@ -20,20 +22,22 @@ use hir_def::{ | |||
20 | GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, | 22 | GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, |
21 | TypeAliasId, TypeParamId, UnionId, VariantId, | 23 | TypeAliasId, TypeParamId, UnionId, VariantId, |
22 | }; | 24 | }; |
23 | use hir_expand::name::Name; | 25 | use hir_expand::{name::Name, ExpandResult}; |
24 | use la_arena::ArenaMap; | 26 | use la_arena::ArenaMap; |
25 | use smallvec::SmallVec; | 27 | use smallvec::SmallVec; |
26 | use stdx::impl_from; | 28 | use stdx::impl_from; |
29 | use syntax::ast; | ||
27 | 30 | ||
28 | use crate::{ | 31 | use crate::{ |
29 | db::HirDatabase, | 32 | db::HirDatabase, |
30 | dummy_usize_const, static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, | 33 | dummy_usize_const, |
31 | traits::chalk::{Interner, ToChalk}, | 34 | mapping::ToChalk, |
35 | static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, | ||
32 | utils::{ | 36 | utils::{ |
33 | all_super_trait_refs, associated_type_by_name_including_super_traits, generics, Generics, | 37 | all_super_trait_refs, associated_type_by_name_including_super_traits, generics, Generics, |
34 | }, | 38 | }, |
35 | AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig, | 39 | AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig, |
36 | FnSubst, ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause, | 40 | FnSubst, ImplTraitId, Interner, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause, |
37 | QuantifiedWhereClauses, ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, | 41 | QuantifiedWhereClauses, ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, |
38 | TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause, | 42 | TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause, |
39 | }; | 43 | }; |
@@ -49,7 +53,7 @@ pub struct TyLoweringContext<'a> { | |||
49 | /// possible currently, so this should be fine for now. | 53 | /// possible currently, so this should be fine for now. |
50 | pub type_param_mode: TypeParamLoweringMode, | 54 | pub type_param_mode: TypeParamLoweringMode, |
51 | pub impl_trait_mode: ImplTraitLoweringMode, | 55 | pub impl_trait_mode: ImplTraitLoweringMode, |
52 | impl_trait_counter: std::cell::Cell<u16>, | 56 | impl_trait_counter: Cell<u16>, |
53 | /// When turning `impl Trait` into opaque types, we have to collect the | 57 | /// When turning `impl Trait` into opaque types, we have to collect the |
54 | /// bounds at the same time to get the IDs correct (without becoming too | 58 | /// bounds at the same time to get the IDs correct (without becoming too |
55 | /// complicated). I don't like using interior mutability (as for the | 59 | /// complicated). I don't like using interior mutability (as for the |
@@ -58,16 +62,17 @@ pub struct TyLoweringContext<'a> { | |||
58 | /// we're grouping the mutable data (the counter and this field) together | 62 | /// we're grouping the mutable data (the counter and this field) together |
59 | /// with the immutable context (the references to the DB and resolver). | 63 | /// with the immutable context (the references to the DB and resolver). |
60 | /// Splitting this up would be a possible fix. | 64 | /// Splitting this up would be a possible fix. |
61 | opaque_type_data: std::cell::RefCell<Vec<ReturnTypeImplTrait>>, | 65 | opaque_type_data: RefCell<Vec<ReturnTypeImplTrait>>, |
66 | expander: RefCell<Option<Expander>>, | ||
62 | } | 67 | } |
63 | 68 | ||
64 | impl<'a> TyLoweringContext<'a> { | 69 | impl<'a> TyLoweringContext<'a> { |
65 | pub fn new(db: &'a dyn HirDatabase, resolver: &'a Resolver) -> Self { | 70 | pub fn new(db: &'a dyn HirDatabase, resolver: &'a Resolver) -> Self { |
66 | let impl_trait_counter = std::cell::Cell::new(0); | 71 | let impl_trait_counter = Cell::new(0); |
67 | let impl_trait_mode = ImplTraitLoweringMode::Disallowed; | 72 | let impl_trait_mode = ImplTraitLoweringMode::Disallowed; |
68 | let type_param_mode = TypeParamLoweringMode::Placeholder; | 73 | let type_param_mode = TypeParamLoweringMode::Placeholder; |
69 | let in_binders = DebruijnIndex::INNERMOST; | 74 | let in_binders = DebruijnIndex::INNERMOST; |
70 | let opaque_type_data = std::cell::RefCell::new(Vec::new()); | 75 | let opaque_type_data = RefCell::new(Vec::new()); |
71 | Self { | 76 | Self { |
72 | db, | 77 | db, |
73 | resolver, | 78 | resolver, |
@@ -76,6 +81,7 @@ impl<'a> TyLoweringContext<'a> { | |||
76 | impl_trait_counter, | 81 | impl_trait_counter, |
77 | type_param_mode, | 82 | type_param_mode, |
78 | opaque_type_data, | 83 | opaque_type_data, |
84 | expander: RefCell::new(None), | ||
79 | } | 85 | } |
80 | } | 86 | } |
81 | 87 | ||
@@ -85,15 +91,18 @@ impl<'a> TyLoweringContext<'a> { | |||
85 | f: impl FnOnce(&TyLoweringContext) -> T, | 91 | f: impl FnOnce(&TyLoweringContext) -> T, |
86 | ) -> T { | 92 | ) -> T { |
87 | let opaque_ty_data_vec = self.opaque_type_data.replace(Vec::new()); | 93 | let opaque_ty_data_vec = self.opaque_type_data.replace(Vec::new()); |
94 | let expander = self.expander.replace(None); | ||
88 | let new_ctx = Self { | 95 | let new_ctx = Self { |
89 | in_binders: debruijn, | 96 | in_binders: debruijn, |
90 | impl_trait_counter: std::cell::Cell::new(self.impl_trait_counter.get()), | 97 | impl_trait_counter: Cell::new(self.impl_trait_counter.get()), |
91 | opaque_type_data: std::cell::RefCell::new(opaque_ty_data_vec), | 98 | opaque_type_data: RefCell::new(opaque_ty_data_vec), |
99 | expander: RefCell::new(expander), | ||
92 | ..*self | 100 | ..*self |
93 | }; | 101 | }; |
94 | let result = f(&new_ctx); | 102 | let result = f(&new_ctx); |
95 | self.impl_trait_counter.set(new_ctx.impl_trait_counter.get()); | 103 | self.impl_trait_counter.set(new_ctx.impl_trait_counter.get()); |
96 | self.opaque_type_data.replace(new_ctx.opaque_type_data.into_inner()); | 104 | self.opaque_type_data.replace(new_ctx.opaque_type_data.into_inner()); |
105 | self.expander.replace(new_ctx.expander.into_inner()); | ||
97 | result | 106 | result |
98 | } | 107 | } |
99 | 108 | ||
@@ -286,6 +295,53 @@ impl<'a> TyLoweringContext<'a> { | |||
286 | } | 295 | } |
287 | } | 296 | } |
288 | } | 297 | } |
298 | TypeRef::Macro(macro_call) => { | ||
299 | let (expander, recursion_start) = { | ||
300 | let mut expander = self.expander.borrow_mut(); | ||
301 | if expander.is_some() { | ||
302 | (Some(expander), false) | ||
303 | } else { | ||
304 | if let Some(module_id) = self.resolver.module() { | ||
305 | *expander = Some(Expander::new( | ||
306 | self.db.upcast(), | ||
307 | macro_call.file_id, | ||
308 | module_id, | ||
309 | )); | ||
310 | (Some(expander), true) | ||
311 | } else { | ||
312 | (None, false) | ||
313 | } | ||
314 | } | ||
315 | }; | ||
316 | let ty = if let Some(mut expander) = expander { | ||
317 | let expander_mut = expander.as_mut().unwrap(); | ||
318 | let macro_call = macro_call.to_node(self.db.upcast()); | ||
319 | match expander_mut.enter_expand::<ast::Type>(self.db.upcast(), macro_call) { | ||
320 | Ok(ExpandResult { value: Some((mark, expanded)), .. }) => { | ||
321 | let ctx = | ||
322 | LowerCtx::new(self.db.upcast(), expander_mut.current_file_id()); | ||
323 | let type_ref = TypeRef::from_ast(&ctx, expanded); | ||
324 | |||
325 | drop(expander); | ||
326 | let ty = self.lower_ty(&type_ref); | ||
327 | |||
328 | self.expander | ||
329 | .borrow_mut() | ||
330 | .as_mut() | ||
331 | .unwrap() | ||
332 | .exit(self.db.upcast(), mark); | ||
333 | Some(ty) | ||
334 | } | ||
335 | _ => None, | ||
336 | } | ||
337 | } else { | ||
338 | None | ||
339 | }; | ||
340 | if recursion_start { | ||
341 | *self.expander.borrow_mut() = None; | ||
342 | } | ||
343 | ty.unwrap_or_else(|| TyKind::Error.intern(&Interner)) | ||
344 | } | ||
289 | TypeRef::Error => TyKind::Error.intern(&Interner), | 345 | TypeRef::Error => TyKind::Error.intern(&Interner), |
290 | }; | 346 | }; |
291 | (ty, res) | 347 | (ty, res) |
@@ -358,17 +414,16 @@ impl<'a> TyLoweringContext<'a> { | |||
358 | self.lower_trait_ref_from_resolved_path(trait_, resolved_segment, self_ty); | 414 | self.lower_trait_ref_from_resolved_path(trait_, resolved_segment, self_ty); |
359 | let ty = if remaining_segments.len() == 1 { | 415 | let ty = if remaining_segments.len() == 1 { |
360 | let segment = remaining_segments.first().unwrap(); | 416 | let segment = remaining_segments.first().unwrap(); |
361 | let found = associated_type_by_name_including_super_traits( | 417 | let found = self |
362 | self.db, | 418 | .db |
363 | trait_ref, | 419 | .trait_data(trait_ref.hir_trait_id()) |
364 | &segment.name, | 420 | .associated_type_by_name(&segment.name); |
365 | ); | ||
366 | match found { | 421 | match found { |
367 | Some((super_trait_ref, associated_ty)) => { | 422 | Some(associated_ty) => { |
368 | // FIXME handle type parameters on the segment | 423 | // FIXME handle type parameters on the segment |
369 | TyKind::Alias(AliasTy::Projection(ProjectionTy { | 424 | TyKind::Alias(AliasTy::Projection(ProjectionTy { |
370 | associated_ty_id: to_assoc_type_id(associated_ty), | 425 | associated_ty_id: to_assoc_type_id(associated_ty), |
371 | substitution: super_trait_ref.substitution, | 426 | substitution: trait_ref.substitution, |
372 | })) | 427 | })) |
373 | .intern(&Interner) | 428 | .intern(&Interner) |
374 | } | 429 | } |
@@ -1033,6 +1088,27 @@ pub(crate) fn generic_defaults_query( | |||
1033 | defaults | 1088 | defaults |
1034 | } | 1089 | } |
1035 | 1090 | ||
1091 | pub(crate) fn generic_defaults_recover( | ||
1092 | db: &dyn HirDatabase, | ||
1093 | _cycle: &[String], | ||
1094 | def: &GenericDefId, | ||
1095 | ) -> Arc<[Binders<Ty>]> { | ||
1096 | let generic_params = generics(db.upcast(), *def); | ||
1097 | |||
1098 | // we still need one default per parameter | ||
1099 | let defaults = generic_params | ||
1100 | .iter() | ||
1101 | .enumerate() | ||
1102 | .map(|(idx, _)| { | ||
1103 | let ty = TyKind::Error.intern(&Interner); | ||
1104 | |||
1105 | crate::make_only_type_binders(idx, ty) | ||
1106 | }) | ||
1107 | .collect(); | ||
1108 | |||
1109 | defaults | ||
1110 | } | ||
1111 | |||
1036 | fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig { | 1112 | fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig { |
1037 | let data = db.function_data(def); | 1113 | let data = db.function_data(def); |
1038 | let resolver = def.resolver(db.upcast()); | 1114 | let resolver = def.resolver(db.upcast()); |