@@ -965,6 +965,7 @@ import {
965
965
SignatureFlags,
966
966
SignatureKind,
967
967
singleElementArray,
968
+ SingleSignatureType,
968
969
skipOuterExpressions,
969
970
skipParentheses,
970
971
skipTrivia,
@@ -7088,7 +7089,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
7088
7089
7089
7090
const abstractSignatures = filter(resolved.constructSignatures, signature => !!(signature.flags & SignatureFlags.Abstract));
7090
7091
if (some(abstractSignatures)) {
7091
- const types = map(abstractSignatures, getOrCreateTypeFromSignature);
7092
+ const types = map(abstractSignatures, s => getOrCreateTypeFromSignature(s) );
7092
7093
// count the number of type elements excluding abstract constructors
7093
7094
const typeElementCount = resolved.callSignatures.length +
7094
7095
(resolved.constructSignatures.length - abstractSignatures.length) +
@@ -15648,7 +15649,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
15648
15649
return signature;
15649
15650
}
15650
15651
15651
- function getOrCreateTypeFromSignature(signature: Signature): ObjectType {
15652
+ function getOrCreateTypeFromSignature(signature: Signature, outerTypeParameters?: TypeParameter[] ): ObjectType {
15652
15653
// There are two ways to declare a construct signature, one is by declaring a class constructor
15653
15654
// using the constructor keyword, and the other is declaring a bare construct signature in an
15654
15655
// object type literal or interface (using the new keyword). Each way of declaring a constructor
@@ -15659,7 +15660,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
15659
15660
// If declaration is undefined, it is likely to be the signature of the default constructor.
15660
15661
const isConstructor = kind === undefined || kind === SyntaxKind.Constructor || kind === SyntaxKind.ConstructSignature || kind === SyntaxKind.ConstructorType;
15661
15662
15662
- const type = createObjectType(ObjectFlags.Anonymous);
15663
+ // The type must have a symbol with a `Function` flag and a declaration in order to be correctly flagged as possibly containing
15664
+ // type variables by `couldContainTypeVariables`
15665
+ const type = createObjectType(ObjectFlags.Anonymous | ObjectFlags.SingleSignatureType, createSymbol(SymbolFlags.Function, InternalSymbolName.Function)) as SingleSignatureType;
15666
+ if (signature.declaration) {
15667
+ type.symbol.declarations = [signature.declaration];
15668
+ type.symbol.valueDeclaration = signature.declaration;
15669
+ }
15670
+ outerTypeParameters ||= signature.declaration && getOuterTypeParameters(signature.declaration, /*includeThisTypes*/ true);
15671
+ type.outerTypeParameters = outerTypeParameters;
15672
+
15663
15673
type.members = emptySymbols;
15664
15674
type.properties = emptyArray;
15665
15675
type.callSignatures = !isConstructor ? [signature] : emptyArray;
@@ -19630,7 +19640,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
19630
19640
const links = getNodeLinks(declaration);
19631
19641
const target = type.objectFlags & ObjectFlags.Reference ? links.resolvedType! as DeferredTypeReference :
19632
19642
type.objectFlags & ObjectFlags.Instantiated ? type.target! : type;
19633
- let typeParameters = links.outerTypeParameters;
19643
+ let typeParameters = type.objectFlags & ObjectFlags.SingleSignatureType ? (type as SingleSignatureType).outerTypeParameters : links.outerTypeParameters;
19634
19644
if (!typeParameters) {
19635
19645
// The first time an anonymous type is instantiated we compute and store a list of the type
19636
19646
// parameters that are in scope (and therefore potentially referenced). For type literals that
@@ -19860,6 +19870,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
19860
19870
if (type.objectFlags & ObjectFlags.InstantiationExpressionType) {
19861
19871
(result as InstantiationExpressionType).node = (type as InstantiationExpressionType).node;
19862
19872
}
19873
+ if (type.objectFlags & ObjectFlags.SingleSignatureType) {
19874
+ (result as SingleSignatureType).outerTypeParameters = (type as SingleSignatureType).outerTypeParameters;
19875
+ }
19863
19876
result.target = type;
19864
19877
result.mapper = mapper;
19865
19878
result.aliasSymbol = aliasSymbol || type.aliasSymbol;
@@ -25483,6 +25496,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
25483
25496
}
25484
25497
}
25485
25498
25499
+ /**
25500
+ * @returns `true` if `type` has the shape `[T[0]]` where `T` is `typeParameter`
25501
+ */
25502
+ function isTupleOfSelf(typeParameter: TypeParameter, type: Type) {
25503
+ return isTupleType(type) && getTupleElementType(type, 0) === getIndexedAccessType(typeParameter, getNumberLiteralType(0)) && !getTypeOfPropertyOfType(type, "1" as __String);
25504
+ }
25505
+
25486
25506
function inferTypes(inferences: InferenceInfo[], originalSource: Type, originalTarget: Type, priority = InferencePriority.None, contravariant = false) {
25487
25507
let bivariant = false;
25488
25508
let propagationType: Type;
@@ -25611,6 +25631,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
25611
25631
inference.priority = priority;
25612
25632
}
25613
25633
if (priority === inference.priority) {
25634
+ // Inferring A to [A[0]] is a zero information inference (it guarantees A becomes its constraint), but oft arises from generic argument list inferences
25635
+ // By discarding it early, we can allow more fruitful results to be used instead.
25636
+ if (isTupleOfSelf(inference.typeParameter, candidate)) {
25637
+ return;
25638
+ }
25614
25639
// We make contravariant inferences only if we are in a pure contravariant position,
25615
25640
// i.e. only if we have not descended into a bivariant position.
25616
25641
if (contravariant && !bivariant) {
@@ -26347,23 +26372,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
26347
26372
// inference error only occurs when there are *conflicting* candidates, i.e.
26348
26373
// candidates with no common supertype.
26349
26374
const defaultType = getDefaultFromTypeParameter(inference.typeParameter);
26350
- if (defaultType) {
26351
- // Instantiate the default type. Any forward reference to a type
26352
- // parameter should be instantiated to the empty object type.
26353
- inferredType = instantiateType(defaultType, mergeTypeMappers(createBackreferenceMapper(context, index), context.nonFixingMapper));
26354
- }
26375
+ inferredType = defaultType;
26355
26376
}
26356
26377
}
26357
26378
else {
26358
26379
inferredType = getTypeFromInference(inference);
26359
26380
}
26360
26381
26361
- inference.inferredType = inferredType || getDefaultTypeArgumentType(!!(context.flags & InferenceFlags.AnyDefault));
26382
+ const isDefault = !inferredType;
26383
+ inferredType ||= getDefaultTypeArgumentType(!!(context.flags & InferenceFlags.AnyDefault));
26384
+ inference.inferredType = inferredType;
26385
+ // Instantiate the inferred type. Any forward reference to a type
26386
+ // parameter should be instantiated to the empty object type.
26387
+ inferredType = instantiateType(inferredType, mergeTypeMappers(createBackreferenceMapper(context, index), context.nonFixingMapper));
26388
+ inference.inferredType = inferredType;
26362
26389
26363
26390
const constraint = getConstraintOfTypeParameter(inference.typeParameter);
26364
26391
if (constraint) {
26365
26392
const instantiatedConstraint = instantiateType(constraint, context.nonFixingMapper);
26366
- if (!inferredType || !context.compareTypes(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) {
26393
+ if (isDefault || !context.compareTypes(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) {
26367
26394
// If the fallback type satisfies the constraint, we pick it. Otherwise, we pick the constraint.
26368
26395
inference.inferredType = fallbackType && context.compareTypes(fallbackType, getTypeWithThisArgument(instantiatedConstraint, fallbackType)) ? fallbackType : instantiatedConstraint;
26369
26396
}
@@ -34265,7 +34292,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
34265
34292
// If one or more arguments are still excluded (as indicated by CheckMode.SkipContextSensitive),
34266
34293
// we obtain the regular type of any object literal arguments because we may not have inferred complete
34267
34294
// parameter types yet and therefore excess property checks may yield false positives (see #17041).
34268
- const checkArgType = checkMode & CheckMode.SkipContextSensitive ? getRegularTypeOfObjectLiteral(argType) : argType;
34295
+ const checkArgType = instantiateType( checkMode & CheckMode.SkipContextSensitive ? getRegularTypeOfObjectLiteral(argType) : argType, signature.mapper) ;
34269
34296
const effectiveCheckArgumentNode = getEffectiveCheckNode(arg);
34270
34297
if (!checkTypeRelatedToAndOptionallyElaborate(checkArgType, paramType, relation, reportErrors ? effectiveCheckArgumentNode : undefined, effectiveCheckArgumentNode, headMessage, containingMessageChain, errorOutputContainer)) {
34271
34298
Debug.assert(!reportErrors || !!errorOutputContainer.errors, "parameter should have errors when reporting errors");
@@ -39287,7 +39314,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
39287
39314
}
39288
39315
}
39289
39316
}
39290
- return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, context));
39317
+ // TODO: The signature may reference any outer inference contexts, but we map pop off and then apply new inference contexts, and thus get different inferred types.
39318
+ // That this is cached on the *first* such attempt is not currently an issue, since expression types *also* get cached on the first pass. If we ever properly speculate, though,
39319
+ // the cached "isolatedSignatureType" signature field absolutely needs to be included in the list of speculative caches.
39320
+ return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, context), flatMap(inferenceContexts, c => c && map(c.inferences, i => i.typeParameter)).slice());
39291
39321
}
39292
39322
}
39293
39323
}
0 commit comments