aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/lower.rs
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2020-05-29 18:14:04 +0100
committerFlorian Diebold <[email protected]>2020-06-05 19:09:13 +0100
commita4a4a1854ebb53e1cdd7a5e3b308112bbbf3c676 (patch)
tree343d39c2a01bd3643bcab13eb01dfbd4f6a511cc /crates/ra_hir_ty/src/lower.rs
parent02f7b5d7abbab829c2a0f66cdcbb6678afb412a4 (diff)
Fix type parameter defaults
They should not be applied in expression or pattern contexts, unless there are other explicitly given type args.
Diffstat (limited to 'crates/ra_hir_ty/src/lower.rs')
-rw-r--r--crates/ra_hir_ty/src/lower.rs70
1 files changed, 46 insertions, 24 deletions
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index a05cbd7fc..42713928f 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -323,6 +323,7 @@ impl Ty {
323 resolution: TypeNs, 323 resolution: TypeNs,
324 resolved_segment: PathSegment<'_>, 324 resolved_segment: PathSegment<'_>,
325 remaining_segments: PathSegments<'_>, 325 remaining_segments: PathSegments<'_>,
326 infer_args: bool,
326 ) -> (Ty, Option<TypeNs>) { 327 ) -> (Ty, Option<TypeNs>) {
327 let ty = match resolution { 328 let ty = match resolution {
328 TypeNs::TraitId(trait_) => { 329 TypeNs::TraitId(trait_) => {
@@ -400,9 +401,15 @@ impl Ty {
400 ctx.db.ty(adt.into()).subst(&substs) 401 ctx.db.ty(adt.into()).subst(&substs)
401 } 402 }
402 403
403 TypeNs::AdtId(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), 404 TypeNs::AdtId(it) => {
404 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)
405 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 }
406 // FIXME: report error 413 // FIXME: report error
407 TypeNs::EnumVariantId(_) => return (Ty::Unknown, None), 414 TypeNs::EnumVariantId(_) => return (Ty::Unknown, None),
408 }; 415 };
@@ -428,7 +435,13 @@ impl Ty {
428 ), 435 ),
429 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)),
430 }; 437 };
431 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 )
432 } 445 }
433 446
434 fn select_associated_type( 447 fn select_associated_type(
@@ -474,13 +487,14 @@ impl Ty {
474 ctx: &TyLoweringContext<'_>, 487 ctx: &TyLoweringContext<'_>,
475 segment: PathSegment<'_>, 488 segment: PathSegment<'_>,
476 typable: TyDefId, 489 typable: TyDefId,
490 infer_args: bool,
477 ) -> Ty { 491 ) -> Ty {
478 let generic_def = match typable { 492 let generic_def = match typable {
479 TyDefId::BuiltinType(_) => None, 493 TyDefId::BuiltinType(_) => None,
480 TyDefId::AdtId(it) => Some(it.into()), 494 TyDefId::AdtId(it) => Some(it.into()),
481 TyDefId::TypeAliasId(it) => Some(it.into()), 495 TyDefId::TypeAliasId(it) => Some(it.into()),
482 }; 496 };
483 let substs = substs_from_path_segment(ctx, segment, generic_def, false); 497 let substs = substs_from_path_segment(ctx, segment, generic_def, infer_args);
484 ctx.db.ty(typable).subst(&substs) 498 ctx.db.ty(typable).subst(&substs)
485 } 499 }
486 500
@@ -493,6 +507,7 @@ impl Ty {
493 // `ValueTyDefId` is just a convenient way to pass generics and 507 // `ValueTyDefId` is just a convenient way to pass generics and
494 // special-case enum variants 508 // special-case enum variants
495 resolved: ValueTyDefId, 509 resolved: ValueTyDefId,
510 infer_args: bool,
496 ) -> Substs { 511 ) -> Substs {
497 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");
498 let (segment, generic_def) = match resolved { 513 let (segment, generic_def) = match resolved {
@@ -515,22 +530,27 @@ impl Ty {
515 (segment, Some(var.parent.into())) 530 (segment, Some(var.parent.into()))
516 } 531 }
517 }; 532 };
518 substs_from_path_segment(ctx, segment, generic_def, false) 533 substs_from_path_segment(ctx, segment, generic_def, infer_args)
519 } 534 }
520} 535}
521 536
522pub(super) fn substs_from_path_segment( 537fn substs_from_path_segment(
523 ctx: &TyLoweringContext<'_>, 538 ctx: &TyLoweringContext<'_>,
524 segment: PathSegment<'_>, 539 segment: PathSegment<'_>,
525 def_generic: Option<GenericDefId>, 540 def_generic: Option<GenericDefId>,
526 _add_self_param: bool, 541 infer_args: bool,
527) -> Substs { 542) -> Substs {
528 let mut substs = Vec::new(); 543 let mut substs = Vec::new();
529 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));
530 545
531 let (parent_params, self_params, type_params, impl_trait_params) = 546 let (parent_params, self_params, type_params, impl_trait_params) =
532 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
533 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
534 if let Some(generic_args) = &segment.args_and_bindings { 554 if let Some(generic_args) = &segment.args_and_bindings {
535 if !generic_args.has_self_type { 555 if !generic_args.has_self_type {
536 substs.extend(iter::repeat(Ty::Unknown).take(self_params)); 556 substs.extend(iter::repeat(Ty::Unknown).take(self_params));
@@ -542,31 +562,35 @@ pub(super) fn substs_from_path_segment(
542 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) {
543 match arg { 563 match arg {
544 GenericArg::Type(type_ref) => { 564 GenericArg::Type(type_ref) => {
565 had_explicit_args = true;
545 let ty = Ty::from_hir(ctx, type_ref); 566 let ty = Ty::from_hir(ctx, type_ref);
546 substs.push(ty); 567 substs.push(ty);
547 } 568 }
548 } 569 }
549 } 570 }
550 } 571 }
551 let total_len = parent_params + self_params + type_params + impl_trait_params;
552 // add placeholders for args that were not provided
553 for _ in substs.len()..total_len {
554 substs.push(Ty::Unknown);
555 }
556 assert_eq!(substs.len(), total_len);
557 572
558 // handle defaults 573 // handle defaults. In expression or pattern path segments without
559 if let Some(def_generic) = def_generic { 574 // explicitly specified type arguments, missing type arguments are inferred
560 let default_substs = ctx.db.generic_defaults(def_generic); 575 // (i.e. defaults aren't used).
561 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());
562 580
563 for (i, default_ty) in default_substs.iter().enumerate() { 581 for default_ty in default_substs.iter().skip(substs.len()) {
564 if substs[i] == Ty::Unknown { 582 substs.push(default_ty.clone());
565 substs[i] = default_ty.clone();
566 } 583 }
567 } 584 }
568 } 585 }
569 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
570 Substs(substs.into()) 594 Substs(substs.into())
571} 595}
572 596
@@ -615,9 +639,7 @@ impl TraitRef {
615 segment: PathSegment<'_>, 639 segment: PathSegment<'_>,
616 resolved: TraitId, 640 resolved: TraitId,
617 ) -> Substs { 641 ) -> Substs {
618 let has_self_param = 642 substs_from_path_segment(ctx, segment, Some(resolved.into()), false)
619 segment.args_and_bindings.as_ref().map(|a| a.has_self_type).unwrap_or(false);
620 substs_from_path_segment(ctx, segment, Some(resolved.into()), !has_self_param)
621 } 643 }
622 644
623 pub(crate) fn from_type_bound( 645 pub(crate) fn from_type_bound(