aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/lower.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src/lower.rs')
-rw-r--r--crates/ra_hir_ty/src/lower.rs214
1 files changed, 168 insertions, 46 deletions
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index 35ac86a46..42713928f 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -21,8 +21,10 @@ use hir_def::{
21 HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, 21 HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId,
22 UnionId, VariantId, 22 UnionId, VariantId,
23}; 23};
24use hir_expand::name::Name;
24use ra_arena::map::ArenaMap; 25use ra_arena::map::ArenaMap;
25use ra_db::CrateId; 26use ra_db::CrateId;
27use test_utils::mark;
26 28
27use crate::{ 29use crate::{
28 db::HirDatabase, 30 db::HirDatabase,
@@ -31,10 +33,10 @@ use crate::{
31 all_super_trait_refs, associated_type_by_name_including_super_traits, generics, 33 all_super_trait_refs, associated_type_by_name_including_super_traits, generics,
32 make_mut_slice, variant_data, 34 make_mut_slice, variant_data,
33 }, 35 },
34 Binders, BoundVar, DebruijnIndex, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, 36 Binders, BoundVar, DebruijnIndex, FnSig, GenericPredicate, OpaqueTy, OpaqueTyId, PolyFnSig,
35 ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, 37 ProjectionPredicate, ProjectionTy, ReturnTypeImplTrait, ReturnTypeImplTraits, Substs,
38 TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk,
36}; 39};
37use hir_expand::name::Name;
38 40
39#[derive(Debug)] 41#[derive(Debug)]
40pub struct TyLoweringContext<'a> { 42pub struct TyLoweringContext<'a> {
@@ -47,7 +49,16 @@ pub struct TyLoweringContext<'a> {
47 /// possible currently, so this should be fine for now. 49 /// possible currently, so this should be fine for now.
48 pub type_param_mode: TypeParamLoweringMode, 50 pub type_param_mode: TypeParamLoweringMode,
49 pub impl_trait_mode: ImplTraitLoweringMode, 51 pub impl_trait_mode: ImplTraitLoweringMode,
50 pub impl_trait_counter: std::cell::Cell<u16>, 52 impl_trait_counter: std::cell::Cell<u16>,
53 /// 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
55 /// complicated). I don't like using interior mutability (as for the
56 /// counter), but I've tried and failed to make the lifetimes work for
57 /// passing around a `&mut TyLoweringContext`. The core problem is that
58 /// we're grouping the mutable data (the counter and this field) together
59 /// with the immutable context (the references to the DB and resolver).
60 /// Splitting this up would be a possible fix.
61 opaque_type_data: std::cell::RefCell<Vec<ReturnTypeImplTrait>>,
51} 62}
52 63
53impl<'a> TyLoweringContext<'a> { 64impl<'a> TyLoweringContext<'a> {
@@ -56,26 +67,42 @@ impl<'a> TyLoweringContext<'a> {
56 let impl_trait_mode = ImplTraitLoweringMode::Disallowed; 67 let impl_trait_mode = ImplTraitLoweringMode::Disallowed;
57 let type_param_mode = TypeParamLoweringMode::Placeholder; 68 let type_param_mode = TypeParamLoweringMode::Placeholder;
58 let in_binders = DebruijnIndex::INNERMOST; 69 let in_binders = DebruijnIndex::INNERMOST;
59 Self { db, resolver, in_binders, impl_trait_mode, impl_trait_counter, type_param_mode } 70 let opaque_type_data = std::cell::RefCell::new(Vec::new());
71 Self {
72 db,
73 resolver,
74 in_binders,
75 impl_trait_mode,
76 impl_trait_counter,
77 type_param_mode,
78 opaque_type_data,
79 }
60 } 80 }
61 81
62 pub fn with_shifted_in<T>( 82 pub fn with_debruijn<T>(
63 &self, 83 &self,
64 debruijn: DebruijnIndex, 84 debruijn: DebruijnIndex,
65 f: impl FnOnce(&TyLoweringContext) -> T, 85 f: impl FnOnce(&TyLoweringContext) -> T,
66 ) -> T { 86 ) -> T {
87 let opaque_ty_data_vec = self.opaque_type_data.replace(Vec::new());
67 let new_ctx = Self { 88 let new_ctx = Self {
68 in_binders: self.in_binders.shifted_in_from(debruijn), 89 in_binders: debruijn,
69 impl_trait_counter: std::cell::Cell::new(self.impl_trait_counter.get()), 90 impl_trait_counter: std::cell::Cell::new(self.impl_trait_counter.get()),
91 opaque_type_data: std::cell::RefCell::new(opaque_ty_data_vec),
70 ..*self 92 ..*self
71 }; 93 };
72 let result = f(&new_ctx); 94 let result = f(&new_ctx);
73 self.impl_trait_counter.set(new_ctx.impl_trait_counter.get()); 95 self.impl_trait_counter.set(new_ctx.impl_trait_counter.get());
96 self.opaque_type_data.replace(new_ctx.opaque_type_data.into_inner());
74 result 97 result
75 } 98 }
76 99
77 pub fn shifted_in(self, debruijn: DebruijnIndex) -> Self { 100 pub fn with_shifted_in<T>(
78 Self { in_binders: self.in_binders.shifted_in_from(debruijn), ..self } 101 &self,
102 debruijn: DebruijnIndex,
103 f: impl FnOnce(&TyLoweringContext) -> T,
104 ) -> T {
105 self.with_debruijn(self.in_binders.shifted_in_from(debruijn), f)
79 } 106 }
80 107
81 pub fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self { 108 pub fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self {
@@ -167,20 +194,44 @@ impl Ty {
167 TypeRef::ImplTrait(bounds) => { 194 TypeRef::ImplTrait(bounds) => {
168 match ctx.impl_trait_mode { 195 match ctx.impl_trait_mode {
169 ImplTraitLoweringMode::Opaque => { 196 ImplTraitLoweringMode::Opaque => {
170 let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); 197 let idx = ctx.impl_trait_counter.get();
171 let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| { 198 ctx.impl_trait_counter.set(idx + 1);
172 bounds 199
173 .iter() 200 assert!(idx as usize == ctx.opaque_type_data.borrow().len());
174 .flat_map(|b| { 201 // this dance is to make sure the data is in the right
175 GenericPredicate::from_type_bound(ctx, b, self_ty.clone()) 202 // place even if we encounter more opaque types while
176 }) 203 // lowering the bounds
177 .collect() 204 ctx.opaque_type_data
178 }); 205 .borrow_mut()
179 Ty::Opaque(predicates) 206 .push(ReturnTypeImplTrait { bounds: Binders::new(1, Vec::new()) });
207 // We don't want to lower the bounds inside the binders
208 // we're currently in, because they don't end up inside
209 // those binders. E.g. when we have `impl Trait<impl
210 // OtherTrait<T>>`, the `impl OtherTrait<T>` can't refer
211 // to the self parameter from `impl Trait`, and the
212 // bounds aren't actually stored nested within each
213 // other, but separately. So if the `T` refers to a type
214 // parameter of the outer function, it's just one binder
215 // away instead of two.
216 let actual_opaque_type_data = ctx
217 .with_debruijn(DebruijnIndex::INNERMOST, |ctx| {
218 ReturnTypeImplTrait::from_hir(ctx, &bounds)
219 });
220 ctx.opaque_type_data.borrow_mut()[idx as usize] = actual_opaque_type_data;
221
222 let func = match ctx.resolver.generic_def() {
223 Some(GenericDefId::FunctionId(f)) => f,
224 _ => panic!("opaque impl trait lowering in non-function"),
225 };
226 let impl_trait_id = OpaqueTyId::ReturnTypeImplTrait(func, idx);
227 let generics = generics(ctx.db.upcast(), func.into());
228 let parameters = Substs::bound_vars(&generics, ctx.in_binders);
229 Ty::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters })
180 } 230 }
181 ImplTraitLoweringMode::Param => { 231 ImplTraitLoweringMode::Param => {
182 let idx = ctx.impl_trait_counter.get(); 232 let idx = ctx.impl_trait_counter.get();
183 ctx.impl_trait_counter.set(idx + 1); 233 // FIXME we're probably doing something wrong here
234 ctx.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16);
184 if let Some(def) = ctx.resolver.generic_def() { 235 if let Some(def) = ctx.resolver.generic_def() {
185 let generics = generics(ctx.db.upcast(), def); 236 let generics = generics(ctx.db.upcast(), def);
186 let param = generics 237 let param = generics
@@ -197,7 +248,8 @@ impl Ty {
197 } 248 }
198 ImplTraitLoweringMode::Variable => { 249 ImplTraitLoweringMode::Variable => {
199 let idx = ctx.impl_trait_counter.get(); 250 let idx = ctx.impl_trait_counter.get();
200 ctx.impl_trait_counter.set(idx + 1); 251 // FIXME we're probably doing something wrong here
252 ctx.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16);
201 let (parent_params, self_params, list_params, _impl_trait_params) = 253 let (parent_params, self_params, list_params, _impl_trait_params) =
202 if let Some(def) = ctx.resolver.generic_def() { 254 if let Some(def) = ctx.resolver.generic_def() {
203 let generics = generics(ctx.db.upcast(), def); 255 let generics = generics(ctx.db.upcast(), def);
@@ -271,6 +323,7 @@ impl Ty {
271 resolution: TypeNs, 323 resolution: TypeNs,
272 resolved_segment: PathSegment<'_>, 324 resolved_segment: PathSegment<'_>,
273 remaining_segments: PathSegments<'_>, 325 remaining_segments: PathSegments<'_>,
326 infer_args: bool,
274 ) -> (Ty, Option<TypeNs>) { 327 ) -> (Ty, Option<TypeNs>) {
275 let ty = match resolution { 328 let ty = match resolution {
276 TypeNs::TraitId(trait_) => { 329 TypeNs::TraitId(trait_) => {
@@ -348,9 +401,15 @@ impl Ty {
348 ctx.db.ty(adt.into()).subst(&substs) 401 ctx.db.ty(adt.into()).subst(&substs)
349 } 402 }
350 403
351 TypeNs::AdtId(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), 404 TypeNs::AdtId(it) => {
352 TypeNs::BuiltinType(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), 405 Ty::from_hir_path_inner(ctx, resolved_segment, it.into(), infer_args)
353 TypeNs::TypeAliasId(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), 406 }
407 TypeNs::BuiltinType(it) => {
408 Ty::from_hir_path_inner(ctx, resolved_segment, it.into(), infer_args)
409 }
410 TypeNs::TypeAliasId(it) => {
411 Ty::from_hir_path_inner(ctx, resolved_segment, it.into(), infer_args)
412 }
354 // FIXME: report error 413 // FIXME: report error
355 TypeNs::EnumVariantId(_) => return (Ty::Unknown, None), 414 TypeNs::EnumVariantId(_) => return (Ty::Unknown, None),
356 }; 415 };
@@ -376,7 +435,13 @@ impl Ty {
376 ), 435 ),
377 Some(i) => (path.segments().get(i - 1).unwrap(), path.segments().skip(i)), 436 Some(i) => (path.segments().get(i - 1).unwrap(), path.segments().skip(i)),
378 }; 437 };
379 Ty::from_partly_resolved_hir_path(ctx, resolution, resolved_segment, remaining_segments) 438 Ty::from_partly_resolved_hir_path(
439 ctx,
440 resolution,
441 resolved_segment,
442 remaining_segments,
443 false,
444 )
380 } 445 }
381 446
382 fn select_associated_type( 447 fn select_associated_type(
@@ -422,13 +487,14 @@ impl Ty {
422 ctx: &TyLoweringContext<'_>, 487 ctx: &TyLoweringContext<'_>,
423 segment: PathSegment<'_>, 488 segment: PathSegment<'_>,
424 typable: TyDefId, 489 typable: TyDefId,
490 infer_args: bool,
425 ) -> Ty { 491 ) -> Ty {
426 let generic_def = match typable { 492 let generic_def = match typable {
427 TyDefId::BuiltinType(_) => None, 493 TyDefId::BuiltinType(_) => None,
428 TyDefId::AdtId(it) => Some(it.into()), 494 TyDefId::AdtId(it) => Some(it.into()),
429 TyDefId::TypeAliasId(it) => Some(it.into()), 495 TyDefId::TypeAliasId(it) => Some(it.into()),
430 }; 496 };
431 let substs = substs_from_path_segment(ctx, segment, generic_def, false); 497 let substs = substs_from_path_segment(ctx, segment, generic_def, infer_args);
432 ctx.db.ty(typable).subst(&substs) 498 ctx.db.ty(typable).subst(&substs)
433 } 499 }
434 500
@@ -441,6 +507,7 @@ impl Ty {
441 // `ValueTyDefId` is just a convenient way to pass generics and 507 // `ValueTyDefId` is just a convenient way to pass generics and
442 // special-case enum variants 508 // special-case enum variants
443 resolved: ValueTyDefId, 509 resolved: ValueTyDefId,
510 infer_args: bool,
444 ) -> Substs { 511 ) -> Substs {
445 let last = path.segments().last().expect("path should have at least one segment"); 512 let last = path.segments().last().expect("path should have at least one segment");
446 let (segment, generic_def) = match resolved { 513 let (segment, generic_def) = match resolved {
@@ -463,22 +530,27 @@ impl Ty {
463 (segment, Some(var.parent.into())) 530 (segment, Some(var.parent.into()))
464 } 531 }
465 }; 532 };
466 substs_from_path_segment(ctx, segment, generic_def, false) 533 substs_from_path_segment(ctx, segment, generic_def, infer_args)
467 } 534 }
468} 535}
469 536
470pub(super) fn substs_from_path_segment( 537fn substs_from_path_segment(
471 ctx: &TyLoweringContext<'_>, 538 ctx: &TyLoweringContext<'_>,
472 segment: PathSegment<'_>, 539 segment: PathSegment<'_>,
473 def_generic: Option<GenericDefId>, 540 def_generic: Option<GenericDefId>,
474 _add_self_param: bool, 541 infer_args: bool,
475) -> Substs { 542) -> Substs {
476 let mut substs = Vec::new(); 543 let mut substs = Vec::new();
477 let def_generics = def_generic.map(|def| generics(ctx.db.upcast(), def)); 544 let def_generics = def_generic.map(|def| generics(ctx.db.upcast(), def));
478 545
479 let (parent_params, self_params, type_params, impl_trait_params) = 546 let (parent_params, self_params, type_params, impl_trait_params) =
480 def_generics.map_or((0, 0, 0, 0), |g| g.provenance_split()); 547 def_generics.map_or((0, 0, 0, 0), |g| g.provenance_split());
548 let total_len = parent_params + self_params + type_params + impl_trait_params;
549
481 substs.extend(iter::repeat(Ty::Unknown).take(parent_params)); 550 substs.extend(iter::repeat(Ty::Unknown).take(parent_params));
551
552 let mut had_explicit_args = false;
553
482 if let Some(generic_args) = &segment.args_and_bindings { 554 if let Some(generic_args) = &segment.args_and_bindings {
483 if !generic_args.has_self_type { 555 if !generic_args.has_self_type {
484 substs.extend(iter::repeat(Ty::Unknown).take(self_params)); 556 substs.extend(iter::repeat(Ty::Unknown).take(self_params));
@@ -490,31 +562,35 @@ pub(super) fn substs_from_path_segment(
490 for arg in generic_args.args.iter().skip(skip).take(expected_num) { 562 for arg in generic_args.args.iter().skip(skip).take(expected_num) {
491 match arg { 563 match arg {
492 GenericArg::Type(type_ref) => { 564 GenericArg::Type(type_ref) => {
565 had_explicit_args = true;
493 let ty = Ty::from_hir(ctx, type_ref); 566 let ty = Ty::from_hir(ctx, type_ref);
494 substs.push(ty); 567 substs.push(ty);
495 } 568 }
496 } 569 }
497 } 570 }
498 } 571 }
499 let total_len = parent_params + self_params + type_params + impl_trait_params;
500 // add placeholders for args that were not provided
501 for _ in substs.len()..total_len {
502 substs.push(Ty::Unknown);
503 }
504 assert_eq!(substs.len(), total_len);
505 572
506 // handle defaults 573 // handle defaults. In expression or pattern path segments without
507 if let Some(def_generic) = def_generic { 574 // explicitly specified type arguments, missing type arguments are inferred
508 let default_substs = ctx.db.generic_defaults(def_generic); 575 // (i.e. defaults aren't used).
509 assert_eq!(substs.len(), default_substs.len()); 576 if !infer_args || had_explicit_args {
577 if let Some(def_generic) = def_generic {
578 let default_substs = ctx.db.generic_defaults(def_generic);
579 assert_eq!(total_len, default_substs.len());
510 580
511 for (i, default_ty) in default_substs.iter().enumerate() { 581 for default_ty in default_substs.iter().skip(substs.len()) {
512 if substs[i] == Ty::Unknown { 582 substs.push(default_ty.clone());
513 substs[i] = default_ty.clone();
514 } 583 }
515 } 584 }
516 } 585 }
517 586
587 // add placeholders for args that were not provided
588 // FIXME: emit diagnostics in contexts where this is not allowed
589 for _ in substs.len()..total_len {
590 substs.push(Ty::Unknown);
591 }
592 assert_eq!(substs.len(), total_len);
593
518 Substs(substs.into()) 594 Substs(substs.into())
519} 595}
520 596
@@ -563,9 +639,7 @@ impl TraitRef {
563 segment: PathSegment<'_>, 639 segment: PathSegment<'_>,
564 resolved: TraitId, 640 resolved: TraitId,
565 ) -> Substs { 641 ) -> Substs {
566 let has_self_param = 642 substs_from_path_segment(ctx, segment, Some(resolved.into()), false)
567 segment.args_and_bindings.as_ref().map(|a| a.has_self_type).unwrap_or(false);
568 substs_from_path_segment(ctx, segment, Some(resolved.into()), !has_self_param)
569 } 643 }
570 644
571 pub(crate) fn from_type_bound( 645 pub(crate) fn from_type_bound(
@@ -663,6 +737,30 @@ fn assoc_type_bindings_from_type_bound<'a>(
663 }) 737 })
664} 738}
665 739
740impl ReturnTypeImplTrait {
741 fn from_hir(ctx: &TyLoweringContext, bounds: &[TypeBound]) -> Self {
742 mark::hit!(lower_rpit);
743 let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0));
744 let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| {
745 bounds
746 .iter()
747 .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone()))
748 .collect()
749 });
750 ReturnTypeImplTrait { bounds: Binders::new(1, predicates) }
751 }
752}
753
754fn count_impl_traits(type_ref: &TypeRef) -> usize {
755 let mut count = 0;
756 type_ref.walk(&mut |type_ref| {
757 if matches!(type_ref, TypeRef::ImplTrait(_)) {
758 count += 1;
759 }
760 });
761 count
762}
763
666/// Build the signature of a callable item (function, struct or enum variant). 764/// Build the signature of a callable item (function, struct or enum variant).
667pub fn callable_item_sig(db: &dyn HirDatabase, def: CallableDef) -> PolyFnSig { 765pub fn callable_item_sig(db: &dyn HirDatabase, def: CallableDef) -> PolyFnSig {
668 match def { 766 match def {
@@ -864,7 +962,9 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
864 .with_impl_trait_mode(ImplTraitLoweringMode::Variable) 962 .with_impl_trait_mode(ImplTraitLoweringMode::Variable)
865 .with_type_param_mode(TypeParamLoweringMode::Variable); 963 .with_type_param_mode(TypeParamLoweringMode::Variable);
866 let params = data.params.iter().map(|tr| Ty::from_hir(&ctx_params, tr)).collect::<Vec<_>>(); 964 let params = data.params.iter().map(|tr| Ty::from_hir(&ctx_params, tr)).collect::<Vec<_>>();
867 let ctx_ret = ctx_params.with_impl_trait_mode(ImplTraitLoweringMode::Opaque); 965 let ctx_ret = TyLoweringContext::new(db, &resolver)
966 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
967 .with_type_param_mode(TypeParamLoweringMode::Variable);
868 let ret = Ty::from_hir(&ctx_ret, &data.ret_type); 968 let ret = Ty::from_hir(&ctx_ret, &data.ret_type);
869 let generics = generics(db.upcast(), def.into()); 969 let generics = generics(db.upcast(), def.into());
870 let num_binders = generics.len(); 970 let num_binders = generics.len();
@@ -1084,3 +1184,25 @@ pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<
1084 TraitRef::from_hir(&ctx, target_trait, Some(self_ty.value))?, 1184 TraitRef::from_hir(&ctx, target_trait, Some(self_ty.value))?,
1085 )) 1185 ))
1086} 1186}
1187
1188pub(crate) fn return_type_impl_traits(
1189 db: &impl HirDatabase,
1190 def: hir_def::FunctionId,
1191) -> Option<Arc<Binders<ReturnTypeImplTraits>>> {
1192 // FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe
1193 let data = db.function_data(def);
1194 let resolver = def.resolver(db.upcast());
1195 let ctx_ret = TyLoweringContext::new(db, &resolver)
1196 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
1197 .with_type_param_mode(TypeParamLoweringMode::Variable);
1198 let _ret = Ty::from_hir(&ctx_ret, &data.ret_type);
1199 let generics = generics(db.upcast(), def.into());
1200 let num_binders = generics.len();
1201 let return_type_impl_traits =
1202 ReturnTypeImplTraits { impl_traits: ctx_ret.opaque_type_data.into_inner() };
1203 if return_type_impl_traits.impl_traits.is_empty() {
1204 None
1205 } else {
1206 Some(Arc::new(Binders::new(num_binders, return_type_impl_traits)))
1207 }
1208}