@@ -323,6 +323,7 @@ impl Ty {
323323 resolution : TypeNs ,
324324 resolved_segment : PathSegment < ' _ > ,
325325 remaining_segments : PathSegments < ' _ > ,
326+ infer_args : bool ,
326327 ) -> ( Ty , Option < TypeNs > ) {
327328 let ty = match resolution {
328329 TypeNs :: TraitId ( trait_) => {
@@ -400,9 +401,15 @@ impl Ty {
400401 ctx. db . ty ( adt. into ( ) ) . subst ( & substs)
401402 }
402403
403- TypeNs :: AdtId ( it) => Ty :: from_hir_path_inner ( ctx, resolved_segment, it. into ( ) ) ,
404- TypeNs :: BuiltinType ( it) => Ty :: from_hir_path_inner ( ctx, resolved_segment, it. into ( ) ) ,
405- TypeNs :: TypeAliasId ( it) => Ty :: from_hir_path_inner ( ctx, resolved_segment, it. into ( ) ) ,
404+ TypeNs :: AdtId ( it) => {
405+ Ty :: from_hir_path_inner ( ctx, resolved_segment, it. into ( ) , infer_args)
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+ }
406413 // FIXME: report error
407414 TypeNs :: EnumVariantId ( _) => return ( Ty :: Unknown , None ) ,
408415 } ;
@@ -428,7 +435,13 @@ impl Ty {
428435 ) ,
429436 Some ( i) => ( path. segments ( ) . get ( i - 1 ) . unwrap ( ) , path. segments ( ) . skip ( i) ) ,
430437 } ;
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+ )
432445 }
433446
434447 fn select_associated_type (
@@ -474,13 +487,14 @@ impl Ty {
474487 ctx : & TyLoweringContext < ' _ > ,
475488 segment : PathSegment < ' _ > ,
476489 typable : TyDefId ,
490+ infer_args : bool ,
477491 ) -> Ty {
478492 let generic_def = match typable {
479493 TyDefId :: BuiltinType ( _) => None ,
480494 TyDefId :: AdtId ( it) => Some ( it. into ( ) ) ,
481495 TyDefId :: TypeAliasId ( it) => Some ( it. into ( ) ) ,
482496 } ;
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 ) ;
484498 ctx. db . ty ( typable) . subst ( & substs)
485499 }
486500
@@ -493,6 +507,7 @@ impl Ty {
493507 // `ValueTyDefId` is just a convenient way to pass generics and
494508 // special-case enum variants
495509 resolved : ValueTyDefId ,
510+ infer_args : bool ,
496511 ) -> Substs {
497512 let last = path. segments ( ) . last ( ) . expect ( "path should have at least one segment" ) ;
498513 let ( segment, generic_def) = match resolved {
@@ -515,22 +530,27 @@ impl Ty {
515530 ( segment, Some ( var. parent . into ( ) ) )
516531 }
517532 } ;
518- substs_from_path_segment ( ctx, segment, generic_def, false )
533+ substs_from_path_segment ( ctx, segment, generic_def, infer_args )
519534 }
520535}
521536
522- pub ( super ) fn substs_from_path_segment (
537+ fn substs_from_path_segment (
523538 ctx : & TyLoweringContext < ' _ > ,
524539 segment : PathSegment < ' _ > ,
525540 def_generic : Option < GenericDefId > ,
526- _add_self_param : bool ,
541+ infer_args : bool ,
527542) -> Substs {
528543 let mut substs = Vec :: new ( ) ;
529544 let def_generics = def_generic. map ( |def| generics ( ctx. db . upcast ( ) , def) ) ;
530545
531546 let ( parent_params, self_params, type_params, impl_trait_params) =
532547 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+
533550 substs. extend ( iter:: repeat ( Ty :: Unknown ) . take ( parent_params) ) ;
551+
552+ let mut had_explicit_args = false ;
553+
534554 if let Some ( generic_args) = & segment. args_and_bindings {
535555 if !generic_args. has_self_type {
536556 substs. extend ( iter:: repeat ( Ty :: Unknown ) . take ( self_params) ) ;
@@ -542,31 +562,35 @@ pub(super) fn substs_from_path_segment(
542562 for arg in generic_args. args . iter ( ) . skip ( skip) . take ( expected_num) {
543563 match arg {
544564 GenericArg :: Type ( type_ref) => {
565+ had_explicit_args = true ;
545566 let ty = Ty :: from_hir ( ctx, type_ref) ;
546567 substs. push ( ty) ;
547568 }
548569 }
549570 }
550571 }
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) ;
557572
558- // handle defaults
559- if let Some ( def_generic) = def_generic {
560- let default_substs = ctx. db . generic_defaults ( def_generic) ;
561- assert_eq ! ( substs. len( ) , default_substs. len( ) ) ;
573+ // handle defaults. In expression or pattern path segments without
574+ // explicitly specified type arguments, missing type arguments are inferred
575+ // (i.e. defaults aren't used).
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( ) ) ;
562580
563- for ( i, default_ty) in default_substs. iter ( ) . enumerate ( ) {
564- if substs[ i] == Ty :: Unknown {
565- substs[ i] = default_ty. clone ( ) ;
581+ for default_ty in default_substs. iter ( ) . skip ( substs. len ( ) ) {
582+ substs. push ( default_ty. clone ( ) ) ;
566583 }
567584 }
568585 }
569586
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+
570594 Substs ( substs. into ( ) )
571595}
572596
@@ -615,9 +639,7 @@ impl TraitRef {
615639 segment : PathSegment < ' _ > ,
616640 resolved : TraitId ,
617641 ) -> Substs {
618- let has_self_param =
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)
642+ substs_from_path_segment ( ctx, segment, Some ( resolved. into ( ) ) , false )
621643 }
622644
623645 pub ( crate ) fn from_type_bound (
0 commit comments