@@ -188,15 +188,13 @@ export class Resolver extends DiagnosticEmitter {
188
188
}
189
189
}
190
190
if ( node . isNullable ) {
191
- if ( ! type . is ( TypeFlags . REFERENCE ) ) {
192
- if ( reportMode == ReportMode . REPORT ) {
193
- this . error (
194
- DiagnosticCode . Basic_type_0_cannot_be_nullable ,
195
- node . range , type . toString ( )
196
- ) ;
197
- }
191
+ if ( type . is ( TypeFlags . REFERENCE ) ) return type . asNullable ( ) ;
192
+ if ( reportMode == ReportMode . REPORT ) {
193
+ this . error (
194
+ DiagnosticCode . Basic_type_0_cannot_be_nullable ,
195
+ node . range , type . toString ( )
196
+ ) ;
198
197
}
199
- return type . asNullable ( ) ;
200
198
}
201
199
return type ;
202
200
}
@@ -692,21 +690,105 @@ export class Resolver extends DiagnosticEmitter {
692
690
return typeArguments ;
693
691
}
694
692
695
- /** Infers the generic type(s) of an argument expression and updates `ctxTypes`. */
696
- inferGenericType (
697
- /** The generic type being inferred. */
698
- typeNode : TypeNode ,
699
- /** The respective argument expression. */
700
- exprNode : Expression ,
701
- /** Contextual flow. */
693
+ /** Resolves respectively infers the concrete instance of a function by call context. */
694
+ maybeInferCall (
695
+ node : CallExpression ,
696
+ prototype : FunctionPrototype ,
702
697
ctxFlow : Flow ,
703
- /** Contextual types, i.e. `T`, with unknown types initialized to `auto`. */
704
- ctxTypes : Map < string , Type > ,
705
- /** The names of the type parameters being inferred. */
706
- typeParameterNames : Set < string >
707
- ) : void {
708
- var type = this . resolveExpression ( exprNode , ctxFlow , Type . auto , ReportMode . SWALLOW ) ;
709
- if ( type ) this . propagateInferredGenericTypes ( typeNode , type , ctxFlow , ctxTypes , typeParameterNames ) ;
698
+ reportMode : ReportMode = ReportMode . REPORT
699
+ ) : Function | null {
700
+ var typeArguments = node . typeArguments ;
701
+
702
+ // resolve generic call if type arguments have been provided
703
+ if ( typeArguments ) {
704
+ if ( ! prototype . is ( CommonFlags . GENERIC ) ) {
705
+ if ( reportMode == ReportMode . REPORT ) {
706
+ this . error (
707
+ DiagnosticCode . Type_0_is_not_generic ,
708
+ node . expression . range , prototype . internalName
709
+ ) ;
710
+ }
711
+ return null ;
712
+ }
713
+ return this . resolveFunctionInclTypeArguments (
714
+ prototype ,
715
+ node . typeArguments ,
716
+ ctxFlow . actualFunction ,
717
+ makeMap ( ctxFlow . contextualTypeArguments ) , // don't inherit
718
+ node ,
719
+ reportMode
720
+ ) ;
721
+ }
722
+
723
+ // infer generic call if type arguments have been omitted
724
+ if ( prototype . is ( CommonFlags . GENERIC ) ) {
725
+ let contextualTypeArguments = makeMap < string , Type > ( ctxFlow . contextualTypeArguments ) ;
726
+
727
+ // fill up contextual types with auto for each generic component
728
+ let typeParameterNodes = assert ( prototype . typeParameterNodes ) ;
729
+ let numTypeParameters = typeParameterNodes . length ;
730
+ let typeParameterNames = new Set < string > ( ) ;
731
+ for ( let i = 0 ; i < numTypeParameters ; ++ i ) {
732
+ let name = typeParameterNodes [ i ] . name . text ;
733
+ contextualTypeArguments . set ( name , Type . auto ) ;
734
+ typeParameterNames . add ( name ) ;
735
+ }
736
+
737
+ let parameterNodes = prototype . functionTypeNode . parameters ;
738
+ let numParameters = parameterNodes . length ;
739
+ let argumentNodes = node . arguments ;
740
+ let numArguments = argumentNodes . length ;
741
+
742
+ // infer types with generic components while updating contextual types
743
+ for ( let i = 0 ; i < numParameters ; ++ i ) {
744
+ let argumentExpression = i < numArguments ? argumentNodes [ i ] : parameterNodes [ i ] . initializer ;
745
+ if ( ! argumentExpression ) { // missing initializer -> too few arguments
746
+ if ( reportMode == ReportMode . REPORT ) {
747
+ this . error (
748
+ DiagnosticCode . Expected_0_arguments_but_got_1 ,
749
+ node . range , numParameters . toString ( 10 ) , numArguments . toString ( 10 )
750
+ ) ;
751
+ }
752
+ return null ;
753
+ }
754
+ let typeNode = parameterNodes [ i ] . type ;
755
+ if ( typeNode . hasGenericComponent ( typeParameterNodes ) ) {
756
+ let type = this . resolveExpression ( argumentExpression , ctxFlow , Type . auto , ReportMode . SWALLOW ) ;
757
+ if ( type ) this . propagateInferredGenericTypes ( typeNode , type , ctxFlow , contextualTypeArguments , typeParameterNames ) ;
758
+ }
759
+ }
760
+
761
+ // apply concrete types to the generic function signature
762
+ let resolvedTypeArguments = new Array < Type > ( numTypeParameters ) ;
763
+ for ( let i = 0 ; i < numTypeParameters ; ++ i ) {
764
+ let name = typeParameterNodes [ i ] . name . text ;
765
+ if ( contextualTypeArguments . has ( name ) ) {
766
+ let inferredType = contextualTypeArguments . get ( name ) ! ;
767
+ if ( inferredType != Type . auto ) {
768
+ resolvedTypeArguments [ i ] = inferredType ;
769
+ continue ;
770
+ }
771
+ }
772
+ // unused template, e.g. `function test<T>(): void {...}` called as `test()`
773
+ // invalid because the type is effectively unknown inside the function body
774
+ if ( reportMode == ReportMode . REPORT ) {
775
+ this . error (
776
+ DiagnosticCode . Type_argument_expected ,
777
+ node . expression . range . atEnd
778
+ ) ;
779
+ }
780
+ return null ;
781
+ }
782
+ return this . resolveFunction (
783
+ prototype ,
784
+ resolvedTypeArguments ,
785
+ makeMap < string , Type > ( ctxFlow . contextualTypeArguments ) ,
786
+ reportMode
787
+ ) ;
788
+ }
789
+
790
+ // otherwise resolve the non-generic call as usual
791
+ return this . resolveFunction ( prototype , null , makeMap < string , Type > ( ) , reportMode ) ;
710
792
}
711
793
712
794
/** Updates contextual types with a possibly encapsulated inferred type. */
@@ -2185,31 +2267,20 @@ export class Resolver extends DiagnosticEmitter {
2185
2267
reportMode
2186
2268
) ;
2187
2269
if ( ! target ) return null ;
2188
-
2189
2270
switch ( target . kind ) {
2190
2271
case ElementKind . FUNCTION_PROTOTYPE : {
2191
- // `unchecked(expr: *): *` is special
2272
+ // `unchecked` behaves like parenthesized
2192
2273
if (
2193
2274
( < FunctionPrototype > target ) . internalName == BuiltinSymbols . unchecked &&
2194
2275
node . arguments . length > 0
2195
2276
) {
2196
2277
return this . resolveExpression ( node . arguments [ 0 ] , ctxFlow , ctxType , reportMode ) ;
2197
2278
}
2198
- // otherwise resolve normally
2199
- let instance = this . resolveFunctionInclTypeArguments (
2200
- < FunctionPrototype > target ,
2201
- node . typeArguments ,
2202
- ctxFlow . actualFunction ,
2203
- makeMap ( ctxFlow . contextualTypeArguments ) , // don't inherit
2204
- node ,
2205
- reportMode
2206
- ) ;
2279
+ let instance = this . maybeInferCall ( node , < FunctionPrototype > target , ctxFlow , reportMode ) ;
2207
2280
if ( ! instance ) return null ;
2208
2281
return instance . signature . returnType ;
2209
2282
}
2210
- case ElementKind . FUNCTION_TARGET : {
2211
- return ( < FunctionTarget > target ) . signature . returnType ;
2212
- }
2283
+ case ElementKind . FUNCTION_TARGET : return ( < FunctionTarget > target ) . signature . returnType ;
2213
2284
}
2214
2285
if ( reportMode == ReportMode . REPORT ) {
2215
2286
this . error (
0 commit comments