diff options
Diffstat (limited to 'crates/ra_hir_ty/src/lower.rs')
-rw-r--r-- | crates/ra_hir_ty/src/lower.rs | 329 |
1 files changed, 241 insertions, 88 deletions
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 35ac86a46..f274579ea 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs | |||
@@ -5,10 +5,7 @@ | |||
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::iter; | 8 | use std::{iter, sync::Arc}; |
9 | use std::sync::Arc; | ||
10 | |||
11 | use smallvec::SmallVec; | ||
12 | 9 | ||
13 | use hir_def::{ | 10 | use hir_def::{ |
14 | adt::StructKind, | 11 | adt::StructKind, |
@@ -21,8 +18,12 @@ use hir_def::{ | |||
21 | HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, | 18 | HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, |
22 | UnionId, VariantId, | 19 | UnionId, VariantId, |
23 | }; | 20 | }; |
21 | use hir_expand::name::Name; | ||
24 | use ra_arena::map::ArenaMap; | 22 | use ra_arena::map::ArenaMap; |
25 | use ra_db::CrateId; | 23 | use ra_db::CrateId; |
24 | use smallvec::SmallVec; | ||
25 | use stdx::impl_from; | ||
26 | use test_utils::mark; | ||
26 | 27 | ||
27 | use crate::{ | 28 | use crate::{ |
28 | db::HirDatabase, | 29 | db::HirDatabase, |
@@ -31,10 +32,10 @@ use crate::{ | |||
31 | all_super_trait_refs, associated_type_by_name_including_super_traits, generics, | 32 | all_super_trait_refs, associated_type_by_name_including_super_traits, generics, |
32 | make_mut_slice, variant_data, | 33 | make_mut_slice, variant_data, |
33 | }, | 34 | }, |
34 | Binders, BoundVar, DebruijnIndex, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, | 35 | Binders, BoundVar, DebruijnIndex, FnSig, GenericPredicate, OpaqueTy, OpaqueTyId, PolyFnSig, |
35 | ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, | 36 | ProjectionPredicate, ProjectionTy, ReturnTypeImplTrait, ReturnTypeImplTraits, Substs, |
37 | TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, | ||
36 | }; | 38 | }; |
37 | use hir_expand::name::Name; | ||
38 | 39 | ||
39 | #[derive(Debug)] | 40 | #[derive(Debug)] |
40 | pub struct TyLoweringContext<'a> { | 41 | pub struct TyLoweringContext<'a> { |
@@ -47,7 +48,16 @@ pub struct TyLoweringContext<'a> { | |||
47 | /// possible currently, so this should be fine for now. | 48 | /// possible currently, so this should be fine for now. |
48 | pub type_param_mode: TypeParamLoweringMode, | 49 | pub type_param_mode: TypeParamLoweringMode, |
49 | pub impl_trait_mode: ImplTraitLoweringMode, | 50 | pub impl_trait_mode: ImplTraitLoweringMode, |
50 | pub impl_trait_counter: std::cell::Cell<u16>, | 51 | impl_trait_counter: std::cell::Cell<u16>, |
52 | /// When turning `impl Trait` into opaque types, we have to collect the | ||
53 | /// bounds at the same time to get the IDs correct (without becoming too | ||
54 | /// complicated). I don't like using interior mutability (as for the | ||
55 | /// counter), but I've tried and failed to make the lifetimes work for | ||
56 | /// passing around a `&mut TyLoweringContext`. The core problem is that | ||
57 | /// we're grouping the mutable data (the counter and this field) together | ||
58 | /// with the immutable context (the references to the DB and resolver). | ||
59 | /// Splitting this up would be a possible fix. | ||
60 | opaque_type_data: std::cell::RefCell<Vec<ReturnTypeImplTrait>>, | ||
51 | } | 61 | } |
52 | 62 | ||
53 | impl<'a> TyLoweringContext<'a> { | 63 | impl<'a> TyLoweringContext<'a> { |
@@ -56,26 +66,42 @@ impl<'a> TyLoweringContext<'a> { | |||
56 | let impl_trait_mode = ImplTraitLoweringMode::Disallowed; | 66 | let impl_trait_mode = ImplTraitLoweringMode::Disallowed; |
57 | let type_param_mode = TypeParamLoweringMode::Placeholder; | 67 | let type_param_mode = TypeParamLoweringMode::Placeholder; |
58 | let in_binders = DebruijnIndex::INNERMOST; | 68 | let in_binders = DebruijnIndex::INNERMOST; |
59 | Self { db, resolver, in_binders, impl_trait_mode, impl_trait_counter, type_param_mode } | 69 | let opaque_type_data = std::cell::RefCell::new(Vec::new()); |
70 | Self { | ||
71 | db, | ||
72 | resolver, | ||
73 | in_binders, | ||
74 | impl_trait_mode, | ||
75 | impl_trait_counter, | ||
76 | type_param_mode, | ||
77 | opaque_type_data, | ||
78 | } | ||
60 | } | 79 | } |
61 | 80 | ||
62 | pub fn with_shifted_in<T>( | 81 | pub fn with_debruijn<T>( |
63 | &self, | 82 | &self, |
64 | debruijn: DebruijnIndex, | 83 | debruijn: DebruijnIndex, |
65 | f: impl FnOnce(&TyLoweringContext) -> T, | 84 | f: impl FnOnce(&TyLoweringContext) -> T, |
66 | ) -> T { | 85 | ) -> T { |
86 | let opaque_ty_data_vec = self.opaque_type_data.replace(Vec::new()); | ||
67 | let new_ctx = Self { | 87 | let new_ctx = Self { |
68 | in_binders: self.in_binders.shifted_in_from(debruijn), | 88 | in_binders: debruijn, |
69 | impl_trait_counter: std::cell::Cell::new(self.impl_trait_counter.get()), | 89 | impl_trait_counter: std::cell::Cell::new(self.impl_trait_counter.get()), |
90 | opaque_type_data: std::cell::RefCell::new(opaque_ty_data_vec), | ||
70 | ..*self | 91 | ..*self |
71 | }; | 92 | }; |
72 | let result = f(&new_ctx); | 93 | let result = f(&new_ctx); |
73 | self.impl_trait_counter.set(new_ctx.impl_trait_counter.get()); | 94 | self.impl_trait_counter.set(new_ctx.impl_trait_counter.get()); |
95 | self.opaque_type_data.replace(new_ctx.opaque_type_data.into_inner()); | ||
74 | result | 96 | result |
75 | } | 97 | } |
76 | 98 | ||
77 | pub fn shifted_in(self, debruijn: DebruijnIndex) -> Self { | 99 | pub fn with_shifted_in<T>( |
78 | Self { in_binders: self.in_binders.shifted_in_from(debruijn), ..self } | 100 | &self, |
101 | debruijn: DebruijnIndex, | ||
102 | f: impl FnOnce(&TyLoweringContext) -> T, | ||
103 | ) -> T { | ||
104 | self.with_debruijn(self.in_binders.shifted_in_from(debruijn), f) | ||
79 | } | 105 | } |
80 | 106 | ||
81 | pub fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self { | 107 | pub fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self { |
@@ -150,9 +176,12 @@ impl Ty { | |||
150 | Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) | 176 | Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) |
151 | } | 177 | } |
152 | TypeRef::Placeholder => Ty::Unknown, | 178 | TypeRef::Placeholder => Ty::Unknown, |
153 | TypeRef::Fn(params) => { | 179 | TypeRef::Fn(params, is_varargs) => { |
154 | let sig = Substs(params.iter().map(|tr| Ty::from_hir(ctx, tr)).collect()); | 180 | let sig = Substs(params.iter().map(|tr| Ty::from_hir(ctx, tr)).collect()); |
155 | Ty::apply(TypeCtor::FnPtr { num_args: sig.len() as u16 - 1 }, sig) | 181 | Ty::apply( |
182 | TypeCtor::FnPtr { num_args: sig.len() as u16 - 1, is_varargs: *is_varargs }, | ||
183 | sig, | ||
184 | ) | ||
156 | } | 185 | } |
157 | TypeRef::DynTrait(bounds) => { | 186 | TypeRef::DynTrait(bounds) => { |
158 | let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); | 187 | let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); |
@@ -167,20 +196,44 @@ impl Ty { | |||
167 | TypeRef::ImplTrait(bounds) => { | 196 | TypeRef::ImplTrait(bounds) => { |
168 | match ctx.impl_trait_mode { | 197 | match ctx.impl_trait_mode { |
169 | ImplTraitLoweringMode::Opaque => { | 198 | ImplTraitLoweringMode::Opaque => { |
170 | let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); | 199 | let idx = ctx.impl_trait_counter.get(); |
171 | let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| { | 200 | ctx.impl_trait_counter.set(idx + 1); |
172 | bounds | 201 | |
173 | .iter() | 202 | assert!(idx as usize == ctx.opaque_type_data.borrow().len()); |
174 | .flat_map(|b| { | 203 | // this dance is to make sure the data is in the right |
175 | GenericPredicate::from_type_bound(ctx, b, self_ty.clone()) | 204 | // place even if we encounter more opaque types while |
176 | }) | 205 | // lowering the bounds |
177 | .collect() | 206 | ctx.opaque_type_data |
178 | }); | 207 | .borrow_mut() |
179 | Ty::Opaque(predicates) | 208 | .push(ReturnTypeImplTrait { bounds: Binders::new(1, Vec::new()) }); |
209 | // We don't want to lower the bounds inside the binders | ||
210 | // we're currently in, because they don't end up inside | ||
211 | // those binders. E.g. when we have `impl Trait<impl | ||
212 | // OtherTrait<T>>`, the `impl OtherTrait<T>` can't refer | ||
213 | // to the self parameter from `impl Trait`, and the | ||
214 | // bounds aren't actually stored nested within each | ||
215 | // other, but separately. So if the `T` refers to a type | ||
216 | // parameter of the outer function, it's just one binder | ||
217 | // away instead of two. | ||
218 | let actual_opaque_type_data = ctx | ||
219 | .with_debruijn(DebruijnIndex::INNERMOST, |ctx| { | ||
220 | ReturnTypeImplTrait::from_hir(ctx, &bounds) | ||
221 | }); | ||
222 | ctx.opaque_type_data.borrow_mut()[idx as usize] = actual_opaque_type_data; | ||
223 | |||
224 | let func = match ctx.resolver.generic_def() { | ||
225 | Some(GenericDefId::FunctionId(f)) => f, | ||
226 | _ => panic!("opaque impl trait lowering in non-function"), | ||
227 | }; | ||
228 | let impl_trait_id = OpaqueTyId::ReturnTypeImplTrait(func, idx); | ||
229 | let generics = generics(ctx.db.upcast(), func.into()); | ||
230 | let parameters = Substs::bound_vars(&generics, ctx.in_binders); | ||
231 | Ty::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters }) | ||
180 | } | 232 | } |
181 | ImplTraitLoweringMode::Param => { | 233 | ImplTraitLoweringMode::Param => { |
182 | let idx = ctx.impl_trait_counter.get(); | 234 | let idx = ctx.impl_trait_counter.get(); |
183 | ctx.impl_trait_counter.set(idx + 1); | 235 | // FIXME we're probably doing something wrong here |
236 | ctx.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16); | ||
184 | if let Some(def) = ctx.resolver.generic_def() { | 237 | if let Some(def) = ctx.resolver.generic_def() { |
185 | let generics = generics(ctx.db.upcast(), def); | 238 | let generics = generics(ctx.db.upcast(), def); |
186 | let param = generics | 239 | let param = generics |
@@ -197,7 +250,8 @@ impl Ty { | |||
197 | } | 250 | } |
198 | ImplTraitLoweringMode::Variable => { | 251 | ImplTraitLoweringMode::Variable => { |
199 | let idx = ctx.impl_trait_counter.get(); | 252 | let idx = ctx.impl_trait_counter.get(); |
200 | ctx.impl_trait_counter.set(idx + 1); | 253 | // FIXME we're probably doing something wrong here |
254 | ctx.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16); | ||
201 | let (parent_params, self_params, list_params, _impl_trait_params) = | 255 | let (parent_params, self_params, list_params, _impl_trait_params) = |
202 | if let Some(def) = ctx.resolver.generic_def() { | 256 | if let Some(def) = ctx.resolver.generic_def() { |
203 | let generics = generics(ctx.db.upcast(), def); | 257 | let generics = generics(ctx.db.upcast(), def); |
@@ -271,6 +325,7 @@ impl Ty { | |||
271 | resolution: TypeNs, | 325 | resolution: TypeNs, |
272 | resolved_segment: PathSegment<'_>, | 326 | resolved_segment: PathSegment<'_>, |
273 | remaining_segments: PathSegments<'_>, | 327 | remaining_segments: PathSegments<'_>, |
328 | infer_args: bool, | ||
274 | ) -> (Ty, Option<TypeNs>) { | 329 | ) -> (Ty, Option<TypeNs>) { |
275 | let ty = match resolution { | 330 | let ty = match resolution { |
276 | TypeNs::TraitId(trait_) => { | 331 | TypeNs::TraitId(trait_) => { |
@@ -284,17 +339,17 @@ impl Ty { | |||
284 | TraitRef::from_resolved_path(ctx, trait_, resolved_segment, self_ty); | 339 | TraitRef::from_resolved_path(ctx, trait_, resolved_segment, self_ty); |
285 | let ty = if remaining_segments.len() == 1 { | 340 | let ty = if remaining_segments.len() == 1 { |
286 | let segment = remaining_segments.first().unwrap(); | 341 | let segment = remaining_segments.first().unwrap(); |
287 | let associated_ty = associated_type_by_name_including_super_traits( | 342 | let found = associated_type_by_name_including_super_traits( |
288 | ctx.db.upcast(), | 343 | ctx.db, |
289 | trait_ref.trait_, | 344 | trait_ref.clone(), |
290 | &segment.name, | 345 | &segment.name, |
291 | ); | 346 | ); |
292 | match associated_ty { | 347 | match found { |
293 | Some(associated_ty) => { | 348 | Some((super_trait_ref, associated_ty)) => { |
294 | // FIXME handle type parameters on the segment | 349 | // FIXME handle type parameters on the segment |
295 | Ty::Projection(ProjectionTy { | 350 | Ty::Projection(ProjectionTy { |
296 | associated_ty, | 351 | associated_ty, |
297 | parameters: trait_ref.substs, | 352 | parameters: super_trait_ref.substs, |
298 | }) | 353 | }) |
299 | } | 354 | } |
300 | None => { | 355 | None => { |
@@ -348,9 +403,15 @@ impl Ty { | |||
348 | ctx.db.ty(adt.into()).subst(&substs) | 403 | ctx.db.ty(adt.into()).subst(&substs) |
349 | } | 404 | } |
350 | 405 | ||
351 | TypeNs::AdtId(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), | 406 | TypeNs::AdtId(it) => { |
352 | TypeNs::BuiltinType(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), | 407 | 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()), | 408 | } |
409 | TypeNs::BuiltinType(it) => { | ||
410 | Ty::from_hir_path_inner(ctx, resolved_segment, it.into(), infer_args) | ||
411 | } | ||
412 | TypeNs::TypeAliasId(it) => { | ||
413 | Ty::from_hir_path_inner(ctx, resolved_segment, it.into(), infer_args) | ||
414 | } | ||
354 | // FIXME: report error | 415 | // FIXME: report error |
355 | TypeNs::EnumVariantId(_) => return (Ty::Unknown, None), | 416 | TypeNs::EnumVariantId(_) => return (Ty::Unknown, None), |
356 | }; | 417 | }; |
@@ -376,7 +437,13 @@ impl Ty { | |||
376 | ), | 437 | ), |
377 | Some(i) => (path.segments().get(i - 1).unwrap(), path.segments().skip(i)), | 438 | Some(i) => (path.segments().get(i - 1).unwrap(), path.segments().skip(i)), |
378 | }; | 439 | }; |
379 | Ty::from_partly_resolved_hir_path(ctx, resolution, resolved_segment, remaining_segments) | 440 | Ty::from_partly_resolved_hir_path( |
441 | ctx, | ||
442 | resolution, | ||
443 | resolved_segment, | ||
444 | remaining_segments, | ||
445 | false, | ||
446 | ) | ||
380 | } | 447 | } |
381 | 448 | ||
382 | fn select_associated_type( | 449 | fn select_associated_type( |
@@ -402,6 +469,9 @@ impl Ty { | |||
402 | } | 469 | } |
403 | TypeParamLoweringMode::Variable => t.substs.clone(), | 470 | TypeParamLoweringMode::Variable => t.substs.clone(), |
404 | }; | 471 | }; |
472 | // We need to shift in the bound vars, since | ||
473 | // associated_type_shorthand_candidates does not do that | ||
474 | let substs = substs.shift_bound_vars(ctx.in_binders); | ||
405 | // FIXME handle type parameters on the segment | 475 | // FIXME handle type parameters on the segment |
406 | return Some(Ty::Projection(ProjectionTy { | 476 | return Some(Ty::Projection(ProjectionTy { |
407 | associated_ty, | 477 | associated_ty, |
@@ -422,13 +492,14 @@ impl Ty { | |||
422 | ctx: &TyLoweringContext<'_>, | 492 | ctx: &TyLoweringContext<'_>, |
423 | segment: PathSegment<'_>, | 493 | segment: PathSegment<'_>, |
424 | typable: TyDefId, | 494 | typable: TyDefId, |
495 | infer_args: bool, | ||
425 | ) -> Ty { | 496 | ) -> Ty { |
426 | let generic_def = match typable { | 497 | let generic_def = match typable { |
427 | TyDefId::BuiltinType(_) => None, | 498 | TyDefId::BuiltinType(_) => None, |
428 | TyDefId::AdtId(it) => Some(it.into()), | 499 | TyDefId::AdtId(it) => Some(it.into()), |
429 | TyDefId::TypeAliasId(it) => Some(it.into()), | 500 | TyDefId::TypeAliasId(it) => Some(it.into()), |
430 | }; | 501 | }; |
431 | let substs = substs_from_path_segment(ctx, segment, generic_def, false); | 502 | let substs = substs_from_path_segment(ctx, segment, generic_def, infer_args); |
432 | ctx.db.ty(typable).subst(&substs) | 503 | ctx.db.ty(typable).subst(&substs) |
433 | } | 504 | } |
434 | 505 | ||
@@ -441,6 +512,7 @@ impl Ty { | |||
441 | // `ValueTyDefId` is just a convenient way to pass generics and | 512 | // `ValueTyDefId` is just a convenient way to pass generics and |
442 | // special-case enum variants | 513 | // special-case enum variants |
443 | resolved: ValueTyDefId, | 514 | resolved: ValueTyDefId, |
515 | infer_args: bool, | ||
444 | ) -> Substs { | 516 | ) -> Substs { |
445 | let last = path.segments().last().expect("path should have at least one segment"); | 517 | let last = path.segments().last().expect("path should have at least one segment"); |
446 | let (segment, generic_def) = match resolved { | 518 | let (segment, generic_def) = match resolved { |
@@ -463,22 +535,27 @@ impl Ty { | |||
463 | (segment, Some(var.parent.into())) | 535 | (segment, Some(var.parent.into())) |
464 | } | 536 | } |
465 | }; | 537 | }; |
466 | substs_from_path_segment(ctx, segment, generic_def, false) | 538 | substs_from_path_segment(ctx, segment, generic_def, infer_args) |
467 | } | 539 | } |
468 | } | 540 | } |
469 | 541 | ||
470 | pub(super) fn substs_from_path_segment( | 542 | fn substs_from_path_segment( |
471 | ctx: &TyLoweringContext<'_>, | 543 | ctx: &TyLoweringContext<'_>, |
472 | segment: PathSegment<'_>, | 544 | segment: PathSegment<'_>, |
473 | def_generic: Option<GenericDefId>, | 545 | def_generic: Option<GenericDefId>, |
474 | _add_self_param: bool, | 546 | infer_args: bool, |
475 | ) -> Substs { | 547 | ) -> Substs { |
476 | let mut substs = Vec::new(); | 548 | let mut substs = Vec::new(); |
477 | let def_generics = def_generic.map(|def| generics(ctx.db.upcast(), def)); | 549 | let def_generics = def_generic.map(|def| generics(ctx.db.upcast(), def)); |
478 | 550 | ||
479 | let (parent_params, self_params, type_params, impl_trait_params) = | 551 | let (parent_params, self_params, type_params, impl_trait_params) = |
480 | def_generics.map_or((0, 0, 0, 0), |g| g.provenance_split()); | 552 | def_generics.map_or((0, 0, 0, 0), |g| g.provenance_split()); |
553 | let total_len = parent_params + self_params + type_params + impl_trait_params; | ||
554 | |||
481 | substs.extend(iter::repeat(Ty::Unknown).take(parent_params)); | 555 | substs.extend(iter::repeat(Ty::Unknown).take(parent_params)); |
556 | |||
557 | let mut had_explicit_args = false; | ||
558 | |||
482 | if let Some(generic_args) = &segment.args_and_bindings { | 559 | if let Some(generic_args) = &segment.args_and_bindings { |
483 | if !generic_args.has_self_type { | 560 | if !generic_args.has_self_type { |
484 | substs.extend(iter::repeat(Ty::Unknown).take(self_params)); | 561 | substs.extend(iter::repeat(Ty::Unknown).take(self_params)); |
@@ -490,31 +567,37 @@ pub(super) fn substs_from_path_segment( | |||
490 | for arg in generic_args.args.iter().skip(skip).take(expected_num) { | 567 | for arg in generic_args.args.iter().skip(skip).take(expected_num) { |
491 | match arg { | 568 | match arg { |
492 | GenericArg::Type(type_ref) => { | 569 | GenericArg::Type(type_ref) => { |
570 | had_explicit_args = true; | ||
493 | let ty = Ty::from_hir(ctx, type_ref); | 571 | let ty = Ty::from_hir(ctx, type_ref); |
494 | substs.push(ty); | 572 | substs.push(ty); |
495 | } | 573 | } |
496 | } | 574 | } |
497 | } | 575 | } |
498 | } | 576 | } |
499 | let total_len = parent_params + self_params + type_params + impl_trait_params; | 577 | |
578 | // handle defaults. In expression or pattern path segments without | ||
579 | // explicitly specified type arguments, missing type arguments are inferred | ||
580 | // (i.e. defaults aren't used). | ||
581 | if !infer_args || had_explicit_args { | ||
582 | if let Some(def_generic) = def_generic { | ||
583 | let defaults = ctx.db.generic_defaults(def_generic); | ||
584 | assert_eq!(total_len, defaults.len()); | ||
585 | |||
586 | for default_ty in defaults.iter().skip(substs.len()) { | ||
587 | // each default can depend on the previous parameters | ||
588 | let substs_so_far = Substs(substs.clone().into()); | ||
589 | substs.push(default_ty.clone().subst(&substs_so_far)); | ||
590 | } | ||
591 | } | ||
592 | } | ||
593 | |||
500 | // add placeholders for args that were not provided | 594 | // add placeholders for args that were not provided |
595 | // FIXME: emit diagnostics in contexts where this is not allowed | ||
501 | for _ in substs.len()..total_len { | 596 | for _ in substs.len()..total_len { |
502 | substs.push(Ty::Unknown); | 597 | substs.push(Ty::Unknown); |
503 | } | 598 | } |
504 | assert_eq!(substs.len(), total_len); | 599 | assert_eq!(substs.len(), total_len); |
505 | 600 | ||
506 | // handle defaults | ||
507 | if let Some(def_generic) = def_generic { | ||
508 | let default_substs = ctx.db.generic_defaults(def_generic); | ||
509 | assert_eq!(substs.len(), default_substs.len()); | ||
510 | |||
511 | for (i, default_ty) in default_substs.iter().enumerate() { | ||
512 | if substs[i] == Ty::Unknown { | ||
513 | substs[i] = default_ty.clone(); | ||
514 | } | ||
515 | } | ||
516 | } | ||
517 | |||
518 | Substs(substs.into()) | 601 | Substs(substs.into()) |
519 | } | 602 | } |
520 | 603 | ||
@@ -563,9 +646,7 @@ impl TraitRef { | |||
563 | segment: PathSegment<'_>, | 646 | segment: PathSegment<'_>, |
564 | resolved: TraitId, | 647 | resolved: TraitId, |
565 | ) -> Substs { | 648 | ) -> Substs { |
566 | let has_self_param = | 649 | 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 | } | 650 | } |
570 | 651 | ||
571 | pub(crate) fn from_type_bound( | 652 | pub(crate) fn from_type_bound( |
@@ -632,17 +713,16 @@ fn assoc_type_bindings_from_type_bound<'a>( | |||
632 | .flat_map(|segment| segment.args_and_bindings.into_iter()) | 713 | .flat_map(|segment| segment.args_and_bindings.into_iter()) |
633 | .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) | 714 | .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) |
634 | .flat_map(move |binding| { | 715 | .flat_map(move |binding| { |
635 | let associated_ty = associated_type_by_name_including_super_traits( | 716 | let found = associated_type_by_name_including_super_traits( |
636 | ctx.db.upcast(), | 717 | ctx.db, |
637 | trait_ref.trait_, | 718 | trait_ref.clone(), |
638 | &binding.name, | 719 | &binding.name, |
639 | ); | 720 | ); |
640 | let associated_ty = match associated_ty { | 721 | let (super_trait_ref, associated_ty) = match found { |
641 | None => return SmallVec::<[GenericPredicate; 1]>::new(), | 722 | None => return SmallVec::<[GenericPredicate; 1]>::new(), |
642 | Some(t) => t, | 723 | Some(t) => t, |
643 | }; | 724 | }; |
644 | let projection_ty = | 725 | let projection_ty = ProjectionTy { associated_ty, parameters: super_trait_ref.substs }; |
645 | ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() }; | ||
646 | let mut preds = SmallVec::with_capacity( | 726 | let mut preds = SmallVec::with_capacity( |
647 | binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(), | 727 | binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(), |
648 | ); | 728 | ); |
@@ -663,12 +743,36 @@ fn assoc_type_bindings_from_type_bound<'a>( | |||
663 | }) | 743 | }) |
664 | } | 744 | } |
665 | 745 | ||
746 | impl ReturnTypeImplTrait { | ||
747 | fn from_hir(ctx: &TyLoweringContext, bounds: &[TypeBound]) -> Self { | ||
748 | mark::hit!(lower_rpit); | ||
749 | let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); | ||
750 | let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| { | ||
751 | bounds | ||
752 | .iter() | ||
753 | .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone())) | ||
754 | .collect() | ||
755 | }); | ||
756 | ReturnTypeImplTrait { bounds: Binders::new(1, predicates) } | ||
757 | } | ||
758 | } | ||
759 | |||
760 | fn count_impl_traits(type_ref: &TypeRef) -> usize { | ||
761 | let mut count = 0; | ||
762 | type_ref.walk(&mut |type_ref| { | ||
763 | if matches!(type_ref, TypeRef::ImplTrait(_)) { | ||
764 | count += 1; | ||
765 | } | ||
766 | }); | ||
767 | count | ||
768 | } | ||
769 | |||
666 | /// Build the signature of a callable item (function, struct or enum variant). | 770 | /// Build the signature of a callable item (function, struct or enum variant). |
667 | pub fn callable_item_sig(db: &dyn HirDatabase, def: CallableDef) -> PolyFnSig { | 771 | pub fn callable_item_sig(db: &dyn HirDatabase, def: CallableDefId) -> PolyFnSig { |
668 | match def { | 772 | match def { |
669 | CallableDef::FunctionId(f) => fn_sig_for_fn(db, f), | 773 | CallableDefId::FunctionId(f) => fn_sig_for_fn(db, f), |
670 | CallableDef::StructId(s) => fn_sig_for_struct_constructor(db, s), | 774 | CallableDefId::StructId(s) => fn_sig_for_struct_constructor(db, s), |
671 | CallableDef::EnumVariantId(e) => fn_sig_for_enum_variant_constructor(db, e), | 775 | CallableDefId::EnumVariantId(e) => fn_sig_for_enum_variant_constructor(db, e), |
672 | } | 776 | } |
673 | } | 777 | } |
674 | 778 | ||
@@ -844,17 +948,42 @@ pub(crate) fn generic_predicates_query( | |||
844 | } | 948 | } |
845 | 949 | ||
846 | /// Resolve the default type params from generics | 950 | /// Resolve the default type params from generics |
847 | pub(crate) fn generic_defaults_query(db: &dyn HirDatabase, def: GenericDefId) -> Substs { | 951 | pub(crate) fn generic_defaults_query( |
952 | db: &dyn HirDatabase, | ||
953 | def: GenericDefId, | ||
954 | ) -> Arc<[Binders<Ty>]> { | ||
848 | let resolver = def.resolver(db.upcast()); | 955 | let resolver = def.resolver(db.upcast()); |
849 | let ctx = TyLoweringContext::new(db, &resolver); | 956 | let ctx = |
957 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | ||
850 | let generic_params = generics(db.upcast(), def); | 958 | let generic_params = generics(db.upcast(), def); |
851 | 959 | ||
852 | let defaults = generic_params | 960 | let defaults = generic_params |
853 | .iter() | 961 | .iter() |
854 | .map(|(_idx, p)| p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(&ctx, t))) | 962 | .enumerate() |
963 | .map(|(idx, (_, p))| { | ||
964 | let mut ty = p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(&ctx, t)); | ||
965 | |||
966 | // Each default can only refer to previous parameters. | ||
967 | ty.walk_mut_binders( | ||
968 | &mut |ty, binders| match ty { | ||
969 | Ty::Bound(BoundVar { debruijn, index }) if *debruijn == binders => { | ||
970 | if *index >= idx { | ||
971 | // type variable default referring to parameter coming | ||
972 | // after it. This is forbidden (FIXME: report | ||
973 | // diagnostic) | ||
974 | *ty = Ty::Unknown; | ||
975 | } | ||
976 | } | ||
977 | _ => {} | ||
978 | }, | ||
979 | DebruijnIndex::INNERMOST, | ||
980 | ); | ||
981 | |||
982 | Binders::new(idx, ty) | ||
983 | }) | ||
855 | .collect(); | 984 | .collect(); |
856 | 985 | ||
857 | Substs(defaults) | 986 | defaults |
858 | } | 987 | } |
859 | 988 | ||
860 | fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig { | 989 | fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig { |
@@ -864,11 +993,13 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig { | |||
864 | .with_impl_trait_mode(ImplTraitLoweringMode::Variable) | 993 | .with_impl_trait_mode(ImplTraitLoweringMode::Variable) |
865 | .with_type_param_mode(TypeParamLoweringMode::Variable); | 994 | .with_type_param_mode(TypeParamLoweringMode::Variable); |
866 | let params = data.params.iter().map(|tr| Ty::from_hir(&ctx_params, tr)).collect::<Vec<_>>(); | 995 | 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); | 996 | let ctx_ret = TyLoweringContext::new(db, &resolver) |
997 | .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) | ||
998 | .with_type_param_mode(TypeParamLoweringMode::Variable); | ||
868 | let ret = Ty::from_hir(&ctx_ret, &data.ret_type); | 999 | let ret = Ty::from_hir(&ctx_ret, &data.ret_type); |
869 | let generics = generics(db.upcast(), def.into()); | 1000 | let generics = generics(db.upcast(), def.into()); |
870 | let num_binders = generics.len(); | 1001 | let num_binders = generics.len(); |
871 | Binders::new(num_binders, FnSig::from_params_and_return(params, ret)) | 1002 | Binders::new(num_binders, FnSig::from_params_and_return(params, ret, data.is_varargs)) |
872 | } | 1003 | } |
873 | 1004 | ||
874 | /// Build the declared type of a function. This should not need to look at the | 1005 | /// Build the declared type of a function. This should not need to look at the |
@@ -919,7 +1050,7 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS | |||
919 | let params = | 1050 | let params = |
920 | fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>(); | 1051 | fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>(); |
921 | let ret = type_for_adt(db, def.into()); | 1052 | let ret = type_for_adt(db, def.into()); |
922 | Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value)) | 1053 | Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value, false)) |
923 | } | 1054 | } |
924 | 1055 | ||
925 | /// Build the type of a tuple struct constructor. | 1056 | /// Build the type of a tuple struct constructor. |
@@ -943,7 +1074,7 @@ fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) | |||
943 | let params = | 1074 | let params = |
944 | fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>(); | 1075 | fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>(); |
945 | let ret = type_for_adt(db, def.parent.into()); | 1076 | let ret = type_for_adt(db, def.parent.into()); |
946 | Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value)) | 1077 | Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value, false)) |
947 | } | 1078 | } |
948 | 1079 | ||
949 | /// Build the type of a tuple enum variant constructor. | 1080 | /// Build the type of a tuple enum variant constructor. |
@@ -976,31 +1107,31 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> { | |||
976 | } | 1107 | } |
977 | 1108 | ||
978 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 1109 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
979 | pub enum CallableDef { | 1110 | pub enum CallableDefId { |
980 | FunctionId(FunctionId), | 1111 | FunctionId(FunctionId), |
981 | StructId(StructId), | 1112 | StructId(StructId), |
982 | EnumVariantId(EnumVariantId), | 1113 | EnumVariantId(EnumVariantId), |
983 | } | 1114 | } |
984 | impl_froms!(CallableDef: FunctionId, StructId, EnumVariantId); | 1115 | impl_from!(FunctionId, StructId, EnumVariantId for CallableDefId); |
985 | 1116 | ||
986 | impl CallableDef { | 1117 | impl CallableDefId { |
987 | pub fn krate(self, db: &dyn HirDatabase) -> CrateId { | 1118 | pub fn krate(self, db: &dyn HirDatabase) -> CrateId { |
988 | let db = db.upcast(); | 1119 | let db = db.upcast(); |
989 | match self { | 1120 | match self { |
990 | CallableDef::FunctionId(f) => f.lookup(db).module(db), | 1121 | CallableDefId::FunctionId(f) => f.lookup(db).module(db), |
991 | CallableDef::StructId(s) => s.lookup(db).container.module(db), | 1122 | CallableDefId::StructId(s) => s.lookup(db).container.module(db), |
992 | CallableDef::EnumVariantId(e) => e.parent.lookup(db).container.module(db), | 1123 | CallableDefId::EnumVariantId(e) => e.parent.lookup(db).container.module(db), |
993 | } | 1124 | } |
994 | .krate | 1125 | .krate |
995 | } | 1126 | } |
996 | } | 1127 | } |
997 | 1128 | ||
998 | impl From<CallableDef> for GenericDefId { | 1129 | impl From<CallableDefId> for GenericDefId { |
999 | fn from(def: CallableDef) -> GenericDefId { | 1130 | fn from(def: CallableDefId) -> GenericDefId { |
1000 | match def { | 1131 | match def { |
1001 | CallableDef::FunctionId(f) => f.into(), | 1132 | CallableDefId::FunctionId(f) => f.into(), |
1002 | CallableDef::StructId(s) => s.into(), | 1133 | CallableDefId::StructId(s) => s.into(), |
1003 | CallableDef::EnumVariantId(e) => e.into(), | 1134 | CallableDefId::EnumVariantId(e) => e.into(), |
1004 | } | 1135 | } |
1005 | } | 1136 | } |
1006 | } | 1137 | } |
@@ -1011,7 +1142,7 @@ pub enum TyDefId { | |||
1011 | AdtId(AdtId), | 1142 | AdtId(AdtId), |
1012 | TypeAliasId(TypeAliasId), | 1143 | TypeAliasId(TypeAliasId), |
1013 | } | 1144 | } |
1014 | impl_froms!(TyDefId: BuiltinType, AdtId(StructId, EnumId, UnionId), TypeAliasId); | 1145 | impl_from!(BuiltinType, AdtId(StructId, EnumId, UnionId), TypeAliasId for TyDefId); |
1015 | 1146 | ||
1016 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 1147 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
1017 | pub enum ValueTyDefId { | 1148 | pub enum ValueTyDefId { |
@@ -1021,7 +1152,7 @@ pub enum ValueTyDefId { | |||
1021 | ConstId(ConstId), | 1152 | ConstId(ConstId), |
1022 | StaticId(StaticId), | 1153 | StaticId(StaticId), |
1023 | } | 1154 | } |
1024 | impl_froms!(ValueTyDefId: FunctionId, StructId, EnumVariantId, ConstId, StaticId); | 1155 | impl_from!(FunctionId, StructId, EnumVariantId, ConstId, StaticId for ValueTyDefId); |
1025 | 1156 | ||
1026 | /// Build the declared type of an item. This depends on the namespace; e.g. for | 1157 | /// Build the declared type of an item. This depends on the namespace; e.g. for |
1027 | /// `struct Foo(usize)`, we have two types: The type of the struct itself, and | 1158 | /// `struct Foo(usize)`, we have two types: The type of the struct itself, and |
@@ -1084,3 +1215,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))?, | 1215 | TraitRef::from_hir(&ctx, target_trait, Some(self_ty.value))?, |
1085 | )) | 1216 | )) |
1086 | } | 1217 | } |
1218 | |||
1219 | pub(crate) fn return_type_impl_traits( | ||
1220 | db: &dyn HirDatabase, | ||
1221 | def: hir_def::FunctionId, | ||
1222 | ) -> Option<Arc<Binders<ReturnTypeImplTraits>>> { | ||
1223 | // FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe | ||
1224 | let data = db.function_data(def); | ||
1225 | let resolver = def.resolver(db.upcast()); | ||
1226 | let ctx_ret = TyLoweringContext::new(db, &resolver) | ||
1227 | .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) | ||
1228 | .with_type_param_mode(TypeParamLoweringMode::Variable); | ||
1229 | let _ret = Ty::from_hir(&ctx_ret, &data.ret_type); | ||
1230 | let generics = generics(db.upcast(), def.into()); | ||
1231 | let num_binders = generics.len(); | ||
1232 | let return_type_impl_traits = | ||
1233 | ReturnTypeImplTraits { impl_traits: ctx_ret.opaque_type_data.into_inner() }; | ||
1234 | if return_type_impl_traits.impl_traits.is_empty() { | ||
1235 | None | ||
1236 | } else { | ||
1237 | Some(Arc::new(Binders::new(num_binders, return_type_impl_traits))) | ||
1238 | } | ||
1239 | } | ||