@zzzen/pyright-internal 1.2.0-dev.20230716 → 1.2.0-dev.20230730

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/dist/analyzer/backgroundAnalysisProgram.d.ts +2 -2
  2. package/dist/analyzer/backgroundAnalysisProgram.js.map +1 -1
  3. package/dist/analyzer/binder.js +0 -1
  4. package/dist/analyzer/binder.js.map +1 -1
  5. package/dist/analyzer/checker.d.ts +1 -0
  6. package/dist/analyzer/checker.js +15 -45
  7. package/dist/analyzer/checker.js.map +1 -1
  8. package/dist/analyzer/codeFlowEngine.js +17 -10
  9. package/dist/analyzer/codeFlowEngine.js.map +1 -1
  10. package/dist/analyzer/constraintSolver.js +36 -12
  11. package/dist/analyzer/constraintSolver.js.map +1 -1
  12. package/dist/analyzer/constructorTransform.js +11 -1
  13. package/dist/analyzer/constructorTransform.js.map +1 -1
  14. package/dist/analyzer/constructors.js +36 -14
  15. package/dist/analyzer/constructors.js.map +1 -1
  16. package/dist/analyzer/namedTuples.js +1 -0
  17. package/dist/analyzer/namedTuples.js.map +1 -1
  18. package/dist/analyzer/patternMatching.js +24 -0
  19. package/dist/analyzer/patternMatching.js.map +1 -1
  20. package/dist/analyzer/program.d.ts +4 -2
  21. package/dist/analyzer/program.js +31 -25
  22. package/dist/analyzer/program.js.map +1 -1
  23. package/dist/analyzer/sourceFile.d.ts +5 -0
  24. package/dist/analyzer/sourceFile.js +11 -5
  25. package/dist/analyzer/sourceFile.js.map +1 -1
  26. package/dist/analyzer/typeCacheUtils.d.ts +7 -2
  27. package/dist/analyzer/typeCacheUtils.js +11 -7
  28. package/dist/analyzer/typeCacheUtils.js.map +1 -1
  29. package/dist/analyzer/typeEvaluator.js +858 -639
  30. package/dist/analyzer/typeEvaluator.js.map +1 -1
  31. package/dist/analyzer/typeEvaluatorTypes.d.ts +3 -2
  32. package/dist/analyzer/typeEvaluatorTypes.js.map +1 -1
  33. package/dist/analyzer/typeGuards.js +43 -8
  34. package/dist/analyzer/typeGuards.js.map +1 -1
  35. package/dist/analyzer/typeUtils.d.ts +4 -2
  36. package/dist/analyzer/typeUtils.js +65 -13
  37. package/dist/analyzer/typeUtils.js.map +1 -1
  38. package/dist/analyzer/types.d.ts +4 -4
  39. package/dist/analyzer/types.js +20 -5
  40. package/dist/analyzer/types.js.map +1 -1
  41. package/dist/backgroundAnalysisBase.d.ts +4 -4
  42. package/dist/backgroundAnalysisBase.js +6 -6
  43. package/dist/backgroundAnalysisBase.js.map +1 -1
  44. package/dist/backgroundThreadBase.js +1 -1
  45. package/dist/backgroundThreadBase.js.map +1 -1
  46. package/dist/common/configOptions.d.ts +1 -0
  47. package/dist/common/configOptions.js +5 -1
  48. package/dist/common/configOptions.js.map +1 -1
  49. package/dist/common/diagnosticRules.d.ts +1 -0
  50. package/dist/common/diagnosticRules.js +1 -0
  51. package/dist/common/diagnosticRules.js.map +1 -1
  52. package/dist/languageService/callHierarchyProvider.js +7 -10
  53. package/dist/languageService/callHierarchyProvider.js.map +1 -1
  54. package/dist/languageService/completionProvider.js +10 -4
  55. package/dist/languageService/completionProvider.js.map +1 -1
  56. package/dist/languageService/tooltipUtils.js +5 -2
  57. package/dist/languageService/tooltipUtils.js.map +1 -1
  58. package/dist/localization/localize.d.ts +7 -4
  59. package/dist/localization/localize.js +17 -2
  60. package/dist/localization/localize.js.map +1 -1
  61. package/dist/localization/package.nls.cs.json +6 -6
  62. package/dist/localization/package.nls.de.json +6 -6
  63. package/dist/localization/package.nls.en-us.json +6 -6
  64. package/dist/localization/package.nls.es.json +6 -6
  65. package/dist/localization/package.nls.fr.json +6 -6
  66. package/dist/localization/package.nls.it.json +6 -6
  67. package/dist/localization/package.nls.ja.json +6 -6
  68. package/dist/localization/package.nls.ko.json +6 -6
  69. package/dist/localization/package.nls.pl.json +6 -6
  70. package/dist/localization/package.nls.pt-br.json +6 -6
  71. package/dist/localization/package.nls.qps-ploc.json +6 -6
  72. package/dist/localization/package.nls.ru.json +6 -6
  73. package/dist/localization/package.nls.tr.json +6 -6
  74. package/dist/localization/package.nls.zh-cn.json +6 -6
  75. package/dist/localization/package.nls.zh-tw.json +6 -6
  76. package/dist/tests/checker.test.js +2 -2
  77. package/dist/tests/completions.test.js +40 -0
  78. package/dist/tests/completions.test.js.map +1 -1
  79. package/dist/tests/config.test.js +12 -0
  80. package/dist/tests/config.test.js.map +1 -1
  81. package/dist/tests/fourslash/showcallhierarchy.incomingCalls.overriddenFunction.fourslash.d.ts +1 -0
  82. package/dist/tests/fourslash/showcallhierarchy.incomingCalls.overriddenFunction.fourslash.js +40 -0
  83. package/dist/tests/fourslash/showcallhierarchy.incomingCalls.overriddenFunction.fourslash.js.map +1 -0
  84. package/dist/tests/typeEvaluator1.test.js +17 -1
  85. package/dist/tests/typeEvaluator1.test.js.map +1 -1
  86. package/dist/tests/typeEvaluator2.test.js +24 -2
  87. package/dist/tests/typeEvaluator2.test.js.map +1 -1
  88. package/dist/tests/typeEvaluator3.test.js +14 -4
  89. package/dist/tests/typeEvaluator3.test.js.map +1 -1
  90. package/dist/tests/typeEvaluator4.test.js +9 -1
  91. package/dist/tests/typeEvaluator4.test.js.map +1 -1
  92. package/dist/tests/typeEvaluator5.test.js +8 -4
  93. package/dist/tests/typeEvaluator5.test.js.map +1 -1
  94. package/package.json +7 -6
@@ -175,7 +175,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
175
175
  let typeCache = new Map();
176
176
  let effectiveTypeCache = new Map();
177
177
  let expectedTypeCache = new Map();
178
- let classTypeHooks = [];
178
+ let deferredClassCompletions = [];
179
179
  let cancellationToken;
180
180
  let isBasicTypesInitialized = false;
181
181
  let noneType;
@@ -1420,6 +1420,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
1420
1420
  let classOrObjectBase;
1421
1421
  let memberAccessClass;
1422
1422
  let bindFunction = true;
1423
+ let useDescriptorSetterType = false;
1423
1424
  switch (expression.nodeType) {
1424
1425
  case 38 /* Name */: {
1425
1426
  const symbolWithScope = lookUpSymbolRecursive(expression, expression.value, /* honorCodeFlow */ true);
@@ -1460,6 +1461,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
1460
1461
  if (classMemberInfo === null || classMemberInfo === void 0 ? void 0 : classMemberInfo.isInstanceMember) {
1461
1462
  bindFunction = false;
1462
1463
  }
1464
+ useDescriptorSetterType = true;
1463
1465
  }
1464
1466
  else if ((0, types_1.isInstantiableClass)(baseType)) {
1465
1467
  classMemberInfo = (0, typeUtils_1.lookUpClassMember)(baseType, expression.memberName.value, 8 /* SkipInstanceVariables */ | 16 /* DeclaredTypesOnly */);
@@ -1505,7 +1507,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
1505
1507
  let declaredType = (_b = getDeclaredTypeOfSymbol(symbol)) === null || _b === void 0 ? void 0 : _b.type;
1506
1508
  if (declaredType) {
1507
1509
  // If it's a descriptor, we need to get the setter type.
1508
- if ((0, types_1.isClassInstance)(declaredType)) {
1510
+ if (useDescriptorSetterType && (0, types_1.isClassInstance)(declaredType)) {
1509
1511
  const setterInfo = (0, typeUtils_1.lookUpClassMember)(declaredType, '__set__');
1510
1512
  const setter = setterInfo ? getTypeOfMember(setterInfo) : undefined;
1511
1513
  if (setterInfo && setter && (0, types_1.isFunction)(setter) && setter.details.parameters.length >= 3) {
@@ -1908,7 +1910,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
1908
1910
  }
1909
1911
  function isDiagnosticSuppressedForNode(node) {
1910
1912
  return (suppressedNodeStack.some((suppressedNode) => ParseTreeUtils.isNodeContainedWithin(node, suppressedNode)) ||
1911
- isSpeculativeModeInUse(node));
1913
+ speculativeTypeTracker.isSpeculative(node, /* ignoreIfDiagnosticsAllowed */ true));
1912
1914
  }
1913
1915
  function addDiagnostic(diagLevel, rule, message, node, range) {
1914
1916
  if (diagLevel === 'none') {
@@ -2392,20 +2394,22 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
2392
2394
  // its bound type and a constrained TypeVar is expanded to its individual
2393
2395
  // constrained types). If conditionFilter is specified, conditions that
2394
2396
  // do not match will be ignored.
2395
- function mapSubtypesExpandTypeVars(type, conditionFilter, callback) {
2397
+ function mapSubtypesExpandTypeVars(type, conditionFilter, callback, recursionCount = 0) {
2396
2398
  const newSubtypes = [];
2397
2399
  let typeChanged = false;
2398
- const expandSubtype = (unexpandedType) => {
2400
+ function expandSubtype(unexpandedType, isLastSubtype) {
2399
2401
  let expandedType = (0, types_1.isUnion)(unexpandedType) ? unexpandedType : makeTopLevelTypeVarsConcrete(unexpandedType);
2400
2402
  expandedType = (0, typeUtils_1.transformPossibleRecursiveTypeAlias)(expandedType);
2401
- (0, typeUtils_1.doForEachSubtype)(expandedType, (subtype) => {
2403
+ (0, typeUtils_1.doForEachSubtype)(expandedType, (subtype, index, allSubtypes) => {
2402
2404
  var _a;
2403
2405
  if (conditionFilter) {
2404
- if (!types_1.TypeCondition.isCompatible((0, typeUtils_1.getTypeCondition)(subtype), conditionFilter)) {
2406
+ const filteredType = applyConditionFilterToType(subtype, conditionFilter, recursionCount);
2407
+ if (!filteredType) {
2405
2408
  return undefined;
2406
2409
  }
2410
+ subtype = filteredType;
2407
2411
  }
2408
- let transformedType = callback(subtype, unexpandedType);
2412
+ let transformedType = callback(subtype, unexpandedType, isLastSubtype && index === allSubtypes.length - 1);
2409
2413
  if (transformedType !== unexpandedType) {
2410
2414
  typeChanged = true;
2411
2415
  }
@@ -2419,14 +2423,14 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
2419
2423
  }
2420
2424
  return undefined;
2421
2425
  });
2422
- };
2426
+ }
2423
2427
  if ((0, types_1.isUnion)(type)) {
2424
- type.subtypes.forEach((subtype) => {
2425
- expandSubtype(subtype);
2428
+ type.subtypes.forEach((subtype, index) => {
2429
+ expandSubtype(subtype, index === type.subtypes.length - 1);
2426
2430
  });
2427
2431
  }
2428
2432
  else {
2429
- expandSubtype(type);
2433
+ expandSubtype(type, /* isLastSubtype */ true);
2430
2434
  }
2431
2435
  if (!typeChanged) {
2432
2436
  return type;
@@ -2438,6 +2442,40 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
2438
2442
  }
2439
2443
  return newType;
2440
2444
  }
2445
+ function applyConditionFilterToType(type, conditionFilter, recursionCount) {
2446
+ if (recursionCount > types_1.maxTypeRecursionCount) {
2447
+ return type;
2448
+ }
2449
+ recursionCount++;
2450
+ // If the type has a condition associated with it, make sure it's compatible.
2451
+ if (!types_1.TypeCondition.isCompatible((0, typeUtils_1.getTypeCondition)(type), conditionFilter)) {
2452
+ return undefined;
2453
+ }
2454
+ // If the type is generic, see if any of its type arguments should be filtered.
2455
+ // This is possible only in cases where the type parameter is covariant.
2456
+ // TODO - handle functions and tuples
2457
+ if ((0, types_1.isClass)(type) && type.typeArguments && !type.tupleTypeArguments) {
2458
+ inferTypeParameterVarianceForClass(type);
2459
+ let typeWasTransformed = false;
2460
+ const filteredTypeArgs = type.typeArguments.map((typeArg, index) => {
2461
+ const variance = types_1.TypeVarType.getVariance(type.details.typeParameters[index]);
2462
+ if (variance !== 3 /* Covariant */) {
2463
+ return typeArg;
2464
+ }
2465
+ const filteredTypeArg = mapSubtypesExpandTypeVars(typeArg, conditionFilter, (expandedSubtype) => {
2466
+ return expandedSubtype;
2467
+ }, recursionCount);
2468
+ if (filteredTypeArg !== typeArg) {
2469
+ typeWasTransformed = true;
2470
+ }
2471
+ return filteredTypeArg;
2472
+ });
2473
+ if (typeWasTransformed) {
2474
+ return types_1.ClassType.cloneForSpecialization(type, filteredTypeArgs, /* isTypeArgumentExplicit */ true);
2475
+ }
2476
+ }
2477
+ return type;
2478
+ }
2441
2479
  function markNamesAccessed(node, names) {
2442
2480
  const fileInfo = AnalyzerNodeInfo.getFileInfo(node);
2443
2481
  const scope = ScopeUtils.getScopeForNode(node);
@@ -2814,7 +2852,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
2814
2852
  // Verify that the name does not refer to a (non type alias) variable.
2815
2853
  if (effectiveTypeInfo.includesVariableDecl && !type.typeAliasInfo) {
2816
2854
  let isAllowedTypeForVariable = (0, types_1.isTypeVar)(type) || (0, typeUtils_1.isTypeAliasPlaceholder)(type);
2817
- if ((0, types_1.isClass)(type) && !type.includeSubclasses) {
2855
+ if ((0, types_1.isClass)(type) && !type.includeSubclasses && !symbol.hasTypedDeclarations()) {
2818
2856
  // This check exempts class types that are created by calling
2819
2857
  // NewType, NamedTuple, and by invoking a metaclass directly.
2820
2858
  isAllowedTypeForVariable = true;
@@ -2892,13 +2930,19 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
2892
2930
  function getCodeFlowTypeForCapturedVariable(node, symbolWithScope, effectiveType) {
2893
2931
  // This function applies only to variables, parameters, and imports, not to other
2894
2932
  // types of symbols.
2895
- if (!symbolWithScope.symbol
2896
- .getDeclarations()
2897
- .every((decl) => decl.type === 1 /* Variable */ ||
2933
+ const decls = symbolWithScope.symbol.getDeclarations();
2934
+ if (!decls.every((decl) => decl.type === 1 /* Variable */ ||
2898
2935
  decl.type === 2 /* Parameter */ ||
2899
2936
  decl.type === 8 /* Alias */)) {
2900
2937
  return undefined;
2901
2938
  }
2939
+ // If the symbol is modified in scopes other than the one in which it is
2940
+ // declared (e.g. through a nonlocal or global binding), it is not eligible
2941
+ // for code flow analysis.
2942
+ if (!decls.every((decl) => decl.type === 2 /* Parameter */ ||
2943
+ ScopeUtils.getScopeForNode(decl.node) === symbolWithScope.scope)) {
2944
+ return undefined;
2945
+ }
2902
2946
  // If the symbol is a variable captured by an inner function
2903
2947
  // or lambda, see if we can infer the type from the outer scope.
2904
2948
  const scopeHierarchy = ScopeUtils.getScopeHierarchy(node, symbolWithScope.scope);
@@ -2934,7 +2978,11 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
2934
2978
  return !codeFlowEngine.isFlowNodeReachable(declCodeFlowNode, innerScopeCodeFlowNode,
2935
2979
  /* ignoreNoReturn */ true);
2936
2980
  })) {
2937
- return getFlowTypeOfReference(node, symbolWithScope.symbol.id, effectiveType, innerScopeNode);
2981
+ let typeAtStart = effectiveType;
2982
+ if (symbolWithScope.symbol.isInitiallyUnbound()) {
2983
+ typeAtStart = types_1.UnboundType.create();
2984
+ }
2985
+ return getFlowTypeOfReference(node, symbolWithScope.symbol.id, typeAtStart, innerScopeNode);
2938
2986
  }
2939
2987
  }
2940
2988
  }
@@ -3290,7 +3338,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
3290
3338
  baseType = objectType;
3291
3339
  }
3292
3340
  }
3293
- const getTypeOfNoneBase = (subtype) => {
3341
+ function getTypeOfNoneBase(subtype) {
3294
3342
  if (noneType && (0, types_1.isInstantiableClass)(noneType)) {
3295
3343
  if (types_1.TypeBase.isInstance(subtype)) {
3296
3344
  return getTypeOfObjectMember(node.memberName, types_1.ClassType.cloneAsInstance(noneType), memberName, usage, diag);
@@ -3300,7 +3348,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
3300
3348
  }
3301
3349
  }
3302
3350
  return undefined;
3303
- };
3351
+ }
3304
3352
  if ((0, types_1.isParamSpec)(baseType) && baseType.paramSpecAccess) {
3305
3353
  baseType = makeTopLevelTypeVarsConcrete(baseType);
3306
3354
  }
@@ -3346,11 +3394,14 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
3346
3394
  if (baseType.details.recursiveTypeAliasName) {
3347
3395
  return { type: types_1.UnknownType.create(/* isIncomplete */ true), isIncomplete: true };
3348
3396
  }
3349
- return getTypeOfMemberAccessWithBaseType(node, {
3350
- type: makeTopLevelTypeVarsConcrete(baseType),
3351
- bindToType: baseType,
3352
- isIncomplete,
3353
- }, usage, 0 /* None */);
3397
+ if (!baseType.details.isVariadic) {
3398
+ return getTypeOfMemberAccessWithBaseType(node, {
3399
+ type: makeTopLevelTypeVarsConcrete(baseType),
3400
+ bindToType: baseType,
3401
+ isIncomplete,
3402
+ }, usage, 0 /* None */);
3403
+ }
3404
+ break;
3354
3405
  }
3355
3406
  case 7 /* Class */: {
3356
3407
  if (types_1.TypeBase.isInstantiable(baseType)) {
@@ -3767,7 +3818,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
3767
3818
  // a descriptor protocol, only 'get' operations are allowed. If it's accessed
3768
3819
  // through the object, all access methods are supported.
3769
3820
  if (isAccessedThroughObject || usage.method === 'get') {
3770
- lookupClass = (0, typeUtils_1.convertToInstance)(concreteSubtype.details.effectiveMetaclass);
3821
+ lookupClass = types_1.ClassType.cloneAsInstance(concreteSubtype.details.effectiveMetaclass);
3771
3822
  isAccessedThroughMetaclass = true;
3772
3823
  }
3773
3824
  else {
@@ -3821,7 +3872,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
3821
3872
  type: types_1.ClassType.isClassProperty(lookupClass)
3822
3873
  ? baseTypeClass
3823
3874
  : isAccessedThroughObject
3824
- ? bindToType || types_1.ClassType.cloneAsInstance(baseTypeClass)
3875
+ ? bindToType !== null && bindToType !== void 0 ? bindToType : types_1.ClassType.cloneAsInstance(baseTypeClass)
3825
3876
  : types_1.NoneType.createInstance(),
3826
3877
  },
3827
3878
  },
@@ -3970,8 +4021,20 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
3970
4021
  // If this function is an instance member (e.g. a lambda that was
3971
4022
  // assigned to an instance variable), don't perform any binding.
3972
4023
  if (!isAccessedThroughObject || (memberInfo && !memberInfo.isInstanceMember)) {
4024
+ let effectiveBindToType = bindToType;
4025
+ if (bindToType && !(0, typeUtils_1.isInstantiableMetaclass)(baseTypeClass)) {
4026
+ // If bindToType is an instantiable class or TypeVar but we're targeting
4027
+ // an instance method (in a non-metaclass), we need to convert
4028
+ // the bindToType to an instance.
4029
+ const targetMethod = (0, types_1.isFunction)(concreteSubtype)
4030
+ ? concreteSubtype
4031
+ : concreteSubtype.overloads[0];
4032
+ if (types_1.FunctionType.isInstanceMethod(targetMethod) && !types_1.TypeBase.isInstance(bindToType)) {
4033
+ effectiveBindToType = (0, typeUtils_1.convertToInstance)(bindToType);
4034
+ }
4035
+ }
3973
4036
  return bindFunctionToClassOrObject(isAccessedThroughObject ? types_1.ClassType.cloneAsInstance(baseTypeClass) : baseTypeClass, concreteSubtype, memberInfo && (0, types_1.isInstantiableClass)(memberInfo.classType) ? memberInfo.classType : undefined, errorNode,
3974
- /* recursionCount */ undefined, treatConstructorAsClassMember, bindToType);
4037
+ /* recursionCount */ undefined, treatConstructorAsClassMember, effectiveBindToType);
3975
4038
  }
3976
4039
  }
3977
4040
  if (usage.method === 'set') {
@@ -4578,7 +4641,9 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
4578
4641
  const isFinalAnnotation = (0, types_1.isInstantiableClass)(concreteSubtype) && types_1.ClassType.isBuiltIn(concreteSubtype, 'Final');
4579
4642
  const isClassVarAnnotation = (0, types_1.isInstantiableClass)(concreteSubtype) && types_1.ClassType.isBuiltIn(concreteSubtype, 'ClassVar');
4580
4643
  // Inlined TypedDicts are supported only for 'dict' (and not for 'Dict').
4581
- const supportsTypedDictTypeArg = (0, types_1.isInstantiableClass)(concreteSubtype) &&
4644
+ // This feature is currently experimental.
4645
+ const supportsTypedDictTypeArg = AnalyzerNodeInfo.getFileInfo(node).diagnosticRuleSet.enableExperimentalFeatures &&
4646
+ (0, types_1.isInstantiableClass)(concreteSubtype) &&
4582
4647
  types_1.ClassType.isBuiltIn(concreteSubtype, 'dict') &&
4583
4648
  !concreteSubtype.aliasName;
4584
4649
  let typeArgs = getTypeArgs(node, flags, {
@@ -5263,6 +5328,9 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
5263
5328
  function getTypeOfCall(node, flags, inferenceContext) {
5264
5329
  var _a;
5265
5330
  let baseTypeResult;
5331
+ // Check for the use of `type(x)` within a type annotation. This isn't
5332
+ // allowed, and it's a common mistake, so we want to emit a diagnostic
5333
+ // that guides the user to the right solution.
5266
5334
  if ((flags & 256 /* ExpectingTypeAnnotation */) !== 0 &&
5267
5335
  node.leftExpression.nodeType === 38 /* Name */ &&
5268
5336
  node.leftExpression.value === 'type') {
@@ -5324,20 +5392,6 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
5324
5392
  }
5325
5393
  }
5326
5394
  else {
5327
- // Check for an attempt to invoke an abstract static or class method.
5328
- if ((0, types_1.isFunction)(baseTypeResult.type) &&
5329
- baseTypeResult.type.boundToType &&
5330
- (0, types_1.isInstantiableClass)(baseTypeResult.type.boundToType) &&
5331
- !baseTypeResult.type.boundToType.includeSubclasses) {
5332
- if (types_1.FunctionType.isAbstractMethod(baseTypeResult.type)) {
5333
- if (types_1.FunctionType.isStaticMethod(baseTypeResult.type) ||
5334
- types_1.FunctionType.isClassMethod(baseTypeResult.type)) {
5335
- addDiagnostic(AnalyzerNodeInfo.getFileInfo(node).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.abstractMethodInvocation().format({
5336
- method: baseTypeResult.type.details.name,
5337
- }), node.leftExpression);
5338
- }
5339
- }
5340
- }
5341
5395
  const callResult = validateCallArguments(node, argList, baseTypeResult,
5342
5396
  /* typeVarContext */ undefined,
5343
5397
  /* skipUnknownArgCheck */ false, inferenceContext);
@@ -5776,7 +5830,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
5776
5830
  // If there were multiple possible matches, evaluate the type as
5777
5831
  // Unknown, but include the "possible types" to allow for completion
5778
5832
  // suggestions.
5779
- if (!isDefinitiveMatchFound) {
5833
+ if (!isDefinitiveMatchFound && possibleMatchResults.length > 0) {
5780
5834
  possibleMatchResults = filterOverloadMatchesForAnyArgs(possibleMatchResults);
5781
5835
  // Did the filtering produce a single result? If so, we're done.
5782
5836
  if (possibleMatchResults.length === 1) {
@@ -5984,24 +6038,28 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
5984
6038
  }
5985
6039
  return { argumentErrors: true, isTypeIncomplete: false, overloadsUsedForCall: [] };
5986
6040
  }
5987
- // Create a helper function that evaluates the overload that matches
5988
- // the arg/param lists.
5989
- function evaluateUsingLastMatchingOverload(skipUnknownArgCheck) {
5990
- // Find the match with the largest overload index (i.e. the last overload
5991
- // that was in the overload list).
5992
- const lastMatch = filteredMatchResults.reduce((previous, current) => {
5993
- return current.overloadIndex > previous.overloadIndex ? current : previous;
6041
+ // Create a helper function that evaluates the overload that best
6042
+ // matches the arg/param lists.
6043
+ function evaluateUsingBestMatchingOverload(skipUnknownArgCheck) {
6044
+ // Find the match with the smallest argument match score. If there
6045
+ // are more than one with the same score, use the one with the
6046
+ // largest index. Later overloads tend to be more general.
6047
+ const bestMatch = filteredMatchResults.reduce((previous, current) => {
6048
+ if (current.argumentMatchScore === previous.argumentMatchScore) {
6049
+ return current.overloadIndex > previous.overloadIndex ? current : previous;
6050
+ }
6051
+ return current.argumentMatchScore < previous.argumentMatchScore ? current : previous;
5994
6052
  });
5995
6053
  const effectiveTypeVarContext = typeVarContext !== null && typeVarContext !== void 0 ? typeVarContext : new typeVarContext_1.TypeVarContext();
5996
- effectiveTypeVarContext.addSolveForScope((0, typeUtils_1.getTypeVarScopeIds)(lastMatch.overload));
6054
+ effectiveTypeVarContext.addSolveForScope((0, typeUtils_1.getTypeVarScopeIds)(bestMatch.overload));
5997
6055
  effectiveTypeVarContext.unlock();
5998
- return validateFunctionArgumentTypesWithContext(errorNode, lastMatch, effectiveTypeVarContext, skipUnknownArgCheck, inferenceContext);
6056
+ return validateFunctionArgumentTypesWithContext(errorNode, bestMatch, effectiveTypeVarContext, skipUnknownArgCheck, inferenceContext);
5999
6057
  }
6000
6058
  // If there is only one possible arg/param match among the overloads,
6001
6059
  // use the normal type matching mechanism because it is faster and
6002
6060
  // will provide a clearer error message.
6003
6061
  if (filteredMatchResults.length === 1) {
6004
- return evaluateUsingLastMatchingOverload(/* skipUnknownArgCheck */ false);
6062
+ return evaluateUsingBestMatchingOverload(/* skipUnknownArgCheck */ false);
6005
6063
  }
6006
6064
  let expandedArgTypes = [argList.map((arg) => undefined)];
6007
6065
  let isTypeIncomplete = !!typeResult.isIncomplete;
@@ -6044,7 +6102,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
6044
6102
  // in speculative mode because it's very expensive, and we're going to
6045
6103
  // suppress the diagnostic anyway.
6046
6104
  if (!isDiagnosticSuppressedForNode(errorNode) && !isTypeIncomplete) {
6047
- const result = evaluateUsingLastMatchingOverload(/* skipUnknownArgCheck */ true);
6105
+ const result = evaluateUsingBestMatchingOverload(/* skipUnknownArgCheck */ true);
6048
6106
  // Replace the result with an unknown type since we don't know
6049
6107
  // what overload should have been used.
6050
6108
  result.returnType = types_1.UnknownType.create();
@@ -6120,334 +6178,23 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
6120
6178
  return { returnType: types_1.UnknownType.create(), argumentErrors: true, overloadsUsedForCall };
6121
6179
  }
6122
6180
  let returnType = mapSubtypesExpandTypeVars(callTypeResult.type,
6123
- /* conditionFilter */ undefined, (expandedSubtype, unexpandedSubtype) => {
6124
- var _a, _b, _c, _d, _e, _f, _g;
6125
- switch (expandedSubtype.category) {
6126
- case 1 /* Unknown */:
6127
- case 2 /* Any */: {
6128
- // Touch all of the args so they're marked accessed. Don't bother
6129
- // doing this if the call type is incomplete because this will need
6130
- // to be done again once it is complete.
6131
- if (!callTypeResult.isIncomplete) {
6132
- argList.forEach((arg) => {
6133
- if (arg.valueExpression && !isSpeculativeModeInUse(arg.valueExpression)) {
6134
- getTypeOfArgument(arg);
6135
- }
6136
- });
6137
- }
6138
- return expandedSubtype;
6139
- }
6140
- case 5 /* Function */: {
6141
- if (types_1.TypeBase.isInstantiable(expandedSubtype)) {
6142
- addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.callableNotInstantiable().format({
6143
- type: printType(expandedSubtype),
6144
- }), errorNode);
6145
- argumentErrors = true;
6146
- return undefined;
6147
- }
6148
- // The stdlib collections/__init__.pyi stub file defines namedtuple
6149
- // as a function rather than a class, so we need to check for it here.
6150
- if (expandedSubtype.details.builtInName === 'namedtuple') {
6151
- addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportUntypedNamedTuple, diagnosticRules_1.DiagnosticRule.reportUntypedNamedTuple, localize_1.Localizer.Diagnostic.namedTupleNoTypes(), errorNode);
6152
- return (0, namedTuples_1.createNamedTupleType)(evaluatorInterface, errorNode, argList,
6153
- /* includesTypes */ false);
6154
- }
6155
- // Handle the NewType specially, replacing the normal return type.
6156
- if (expandedSubtype.details.builtInName === 'NewType') {
6157
- return createNewType(errorNode, argList);
6158
- }
6159
- let effectiveTypeVarContext = typeVarContext;
6160
- if (!effectiveTypeVarContext) {
6161
- // If a typeVarContext wasn't provided by the caller, allocate one here.
6162
- effectiveTypeVarContext = new typeVarContext_1.TypeVarContext((0, typeUtils_1.getTypeVarScopeIds)(expandedSubtype));
6163
- // There are certain cases, such as with super().__new__(cls) calls where
6164
- // the call is a constructor but the proper TypeVar scope has been lost.
6165
- // We'll add a wildcard TypeVar scope here. This is a bit of a hack and
6166
- // we may need to revisit this in the future.
6167
- if (types_1.FunctionType.isConstructorMethod(expandedSubtype)) {
6168
- effectiveTypeVarContext.addSolveForScope(types_1.WildcardTypeVarScopeId);
6169
- }
6170
- }
6171
- const functionResult = validateFunctionArguments(errorNode, argList, { type: expandedSubtype, isIncomplete: callTypeResult.isIncomplete }, effectiveTypeVarContext, skipUnknownArgCheck, inferenceContext);
6172
- if (functionResult.isTypeIncomplete) {
6173
- isTypeIncomplete = true;
6174
- }
6175
- (0, collectionUtils_1.appendArray)(overloadsUsedForCall, functionResult.overloadsUsedForCall);
6176
- if (functionResult.argumentErrors) {
6177
- argumentErrors = true;
6178
- }
6179
- else {
6180
- specializedInitSelfType = functionResult.specializedInitSelfType;
6181
- // Call the function transform logic to handle special-cased functions.
6182
- const transformed = (0, functionTransform_1.applyFunctionTransform)(evaluatorInterface, errorNode, argList, expandedSubtype, {
6183
- argumentErrors: functionResult.argumentErrors,
6184
- returnType: (_a = functionResult.returnType) !== null && _a !== void 0 ? _a : types_1.UnknownType.create(isTypeIncomplete),
6185
- isTypeIncomplete,
6186
- });
6187
- functionResult.returnType = transformed.returnType;
6188
- if (transformed.isTypeIncomplete) {
6189
- isTypeIncomplete = true;
6190
- }
6191
- if (transformed.argumentErrors) {
6192
- argumentErrors = true;
6193
- }
6194
- }
6195
- if (expandedSubtype.details.builtInName === '__import__') {
6196
- // For the special __import__ type, we'll override the return type to be "Any".
6197
- // This is required because we don't know what module was imported, and we don't
6198
- // want to fail type checks when accessing members of the resulting module type.
6199
- return types_1.AnyType.create();
6200
- }
6201
- return functionResult.returnType;
6202
- }
6203
- case 6 /* OverloadedFunction */: {
6204
- // Handle the 'cast' call as a special case.
6205
- if (expandedSubtype.overloads[0].details.builtInName === 'cast' && argList.length === 2) {
6206
- return evaluateCastCall(argList, errorNode);
6207
- }
6208
- const functionResult = validateOverloadedFunctionArguments(errorNode, argList, { type: expandedSubtype, isIncomplete: callTypeResult.isIncomplete }, typeVarContext, skipUnknownArgCheck, inferenceContext);
6209
- (0, collectionUtils_1.appendArray)(overloadsUsedForCall, functionResult.overloadsUsedForCall);
6210
- if (functionResult.isTypeIncomplete) {
6211
- isTypeIncomplete = true;
6212
- }
6213
- if (functionResult.argumentErrors) {
6214
- argumentErrors = true;
6215
- }
6216
- else {
6217
- specializedInitSelfType = functionResult.specializedInitSelfType;
6218
- // Call the function transform logic to handle special-cased functions.
6219
- const transformed = (0, functionTransform_1.applyFunctionTransform)(evaluatorInterface, errorNode, argList, expandedSubtype, {
6220
- argumentErrors: functionResult.argumentErrors,
6221
- returnType: (_b = functionResult.returnType) !== null && _b !== void 0 ? _b : types_1.UnknownType.create(isTypeIncomplete),
6222
- isTypeIncomplete,
6223
- });
6224
- functionResult.returnType = transformed.returnType;
6225
- if (transformed.isTypeIncomplete) {
6226
- isTypeIncomplete = true;
6227
- }
6228
- if (transformed.argumentErrors) {
6229
- argumentErrors = true;
6230
- }
6231
- }
6232
- return (_c = functionResult.returnType) !== null && _c !== void 0 ? _c : types_1.UnknownType.create();
6233
- }
6234
- case 7 /* Class */: {
6235
- if (types_1.TypeBase.isInstantiable(expandedSubtype)) {
6236
- if (expandedSubtype.literalValue !== undefined) {
6237
- addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.literalNotCallable(), errorNode);
6238
- argumentErrors = true;
6239
- return types_1.UnknownType.create();
6240
- }
6241
- if (types_1.ClassType.isBuiltIn(expandedSubtype)) {
6242
- const className = expandedSubtype.aliasName || expandedSubtype.details.name;
6243
- if (className === 'type') {
6244
- // Validate the constructor arguments.
6245
- (0, constructors_1.validateConstructorArguments)(evaluatorInterface, errorNode, argList, expandedSubtype, skipUnknownArgCheck, inferenceContext);
6246
- // Handle the 'type' call specially.
6247
- if (argList.length === 1) {
6248
- // The one-parameter form of "type" returns the class
6249
- // for the specified object.
6250
- const argType = getTypeOfArgument(argList[0]).type;
6251
- return (0, typeUtils_1.mapSubtypes)(argType, (subtype) => {
6252
- if ((0, types_1.isClassInstance)(subtype) ||
6253
- ((0, types_1.isTypeVar)(subtype) && types_1.TypeBase.isInstance(subtype)) ||
6254
- (0, types_1.isNoneInstance)(subtype)) {
6255
- return (0, typeUtils_1.convertToInstantiable)(stripLiteralValue(subtype));
6256
- }
6257
- else if ((0, types_1.isFunction)(subtype) && types_1.TypeBase.isInstance(subtype)) {
6258
- return types_1.FunctionType.cloneAsInstantiable(subtype);
6259
- }
6260
- return types_1.AnyType.create();
6261
- });
6262
- }
6263
- else if (argList.length >= 2) {
6264
- // The two-parameter form of "type" returns a new class type
6265
- // built from the specified base types.
6266
- return createType(errorNode, argList) || types_1.AnyType.create();
6267
- }
6268
- // If the parameter to type() is not statically known,
6269
- // fall back to Any.
6270
- return types_1.AnyType.create();
6271
- }
6272
- if (className === 'TypeVar') {
6273
- return createTypeVarType(errorNode, expandedSubtype, argList);
6274
- }
6275
- if (className === 'TypeVarTuple') {
6276
- return createTypeVarTupleType(errorNode, expandedSubtype, argList);
6277
- }
6278
- if (className === 'ParamSpec') {
6279
- return createParamSpecType(errorNode, expandedSubtype, argList);
6280
- }
6281
- if (className === 'TypeAliasType') {
6282
- const newTypeAlias = createTypeAliasType(errorNode, argList);
6283
- if (newTypeAlias) {
6284
- return newTypeAlias;
6285
- }
6286
- }
6287
- if (className === 'NamedTuple') {
6288
- return (0, namedTuples_1.createNamedTupleType)(evaluatorInterface, errorNode, argList,
6289
- /* includesTypes */ true);
6290
- }
6291
- if (className === 'NewType') {
6292
- return createNewType(errorNode, argList);
6293
- }
6294
- if (className === 'Protocol' ||
6295
- className === 'Generic' ||
6296
- className === 'Callable' ||
6297
- className === 'Concatenate' ||
6298
- className === 'Type') {
6299
- const fileInfo = AnalyzerNodeInfo.getFileInfo(errorNode);
6300
- addDiagnostic(fileInfo.diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.typeNotIntantiable().format({ type: className }), errorNode);
6301
- return types_1.AnyType.create();
6302
- }
6303
- if ((0, types_1.isClass)(unexpandedSubtype) && (0, enums_1.isKnownEnumType)(className)) {
6304
- return ((_d = (0, enums_1.createEnumType)(evaluatorInterface, errorNode, expandedSubtype, argList)) !== null && _d !== void 0 ? _d : types_1.UnknownType.create());
6305
- }
6306
- if (className === 'TypedDict') {
6307
- return (0, typedDicts_1.createTypedDictType)(evaluatorInterface, errorNode, expandedSubtype, argList);
6308
- }
6309
- if (className === 'auto' && argList.length === 0) {
6310
- return (0, enums_1.getEnumAutoValueType)(evaluatorInterface, errorNode);
6311
- }
6312
- }
6313
- if (types_1.ClassType.supportsAbstractMethods(expandedSubtype)) {
6314
- const abstractMethods = getAbstractMethods(expandedSubtype);
6315
- if (abstractMethods.length > 0 &&
6316
- !expandedSubtype.includeSubclasses &&
6317
- !(0, types_1.isTypeVar)(unexpandedSubtype)) {
6318
- // If the class is abstract, it can't be instantiated.
6319
- const diagAddendum = new diagnostic_1.DiagnosticAddendum();
6320
- const errorsToDisplay = 2;
6321
- abstractMethods.forEach((abstractMethod, index) => {
6322
- if (index === errorsToDisplay) {
6323
- diagAddendum.addMessage(localize_1.Localizer.DiagnosticAddendum.memberIsAbstractMore().format({
6324
- count: abstractMethods.length - errorsToDisplay,
6325
- }));
6326
- }
6327
- else if (index < errorsToDisplay) {
6328
- if ((0, types_1.isInstantiableClass)(abstractMethod.classType)) {
6329
- const className = abstractMethod.classType.details.name;
6330
- diagAddendum.addMessage(localize_1.Localizer.DiagnosticAddendum.memberIsAbstract().format({
6331
- type: className,
6332
- name: abstractMethod.symbolName,
6333
- }));
6334
- }
6335
- }
6336
- });
6337
- addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet
6338
- .reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.instantiateAbstract().format({
6339
- type: expandedSubtype.details.name,
6340
- }) + diagAddendum.getString(), errorNode);
6341
- }
6342
- }
6343
- if (types_1.ClassType.isProtocolClass(expandedSubtype) && !expandedSubtype.includeSubclasses) {
6344
- // If the class is a protocol, it can't be instantiated.
6345
- addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.instantiateProtocol().format({
6346
- type: expandedSubtype.details.name,
6347
- }), errorNode);
6348
- }
6349
- // Assume this is a call to the constructor.
6350
- const constructorResult = (0, constructors_1.validateConstructorArguments)(evaluatorInterface, errorNode, argList, expandedSubtype, skipUnknownArgCheck, inferenceContext);
6351
- (0, collectionUtils_1.appendArray)(overloadsUsedForCall, constructorResult.overloadsUsedForCall);
6352
- if (constructorResult.argumentErrors) {
6353
- argumentErrors = true;
6354
- }
6355
- if (constructorResult.isTypeIncomplete) {
6356
- isTypeIncomplete = true;
6357
- }
6358
- let returnType = constructorResult.returnType;
6359
- // If the expandedSubtype originated from a TypeVar, convert
6360
- // the constructed type back to the TypeVar. For example, if
6361
- // we have `cls: Type[_T]` followed by `_T()`.
6362
- if ((0, types_1.isTypeVar)(unexpandedSubtype)) {
6363
- returnType = (0, typeUtils_1.convertToInstance)(unexpandedSubtype);
6364
- }
6365
- // If we instantiated a type, transform it into a class.
6366
- // This can happen if someone directly instantiates a metaclass
6367
- // deriving from type.
6368
- if (returnType &&
6369
- (0, types_1.isClassInstance)(returnType) &&
6370
- returnType.details.mro.some((baseClass) => (0, types_1.isInstantiableClass)(baseClass) && types_1.ClassType.isBuiltIn(baseClass, 'type'))) {
6371
- let newClassName = '__class_' + returnType.details.name;
6372
- if (argList.length === 3) {
6373
- const firstArgType = getTypeOfArgument(argList[0]).type;
6374
- if ((0, types_1.isClassInstance)(firstArgType) &&
6375
- types_1.ClassType.isBuiltIn(firstArgType, 'str') &&
6376
- typeof firstArgType.literalValue === 'string') {
6377
- newClassName = firstArgType.literalValue;
6378
- }
6379
- }
6380
- const newClassType = types_1.ClassType.createInstantiable(newClassName, '', '', AnalyzerNodeInfo.getFileInfo(errorNode).filePath, 0 /* None */, ParseTreeUtils.getTypeSourceId(errorNode), types_1.ClassType.cloneAsInstantiable(returnType), types_1.ClassType.cloneAsInstantiable(returnType));
6381
- newClassType.details.baseClasses.push(getBuiltInType(errorNode, 'object'));
6382
- newClassType.details.effectiveMetaclass = expandedSubtype;
6383
- (0, typeUtils_1.computeMroLinearization)(newClassType);
6384
- return newClassType;
6385
- }
6386
- return returnType;
6387
- }
6388
- else {
6389
- const memberType = (_e = getTypeOfObjectMember(errorNode, expandedSubtype, '__call__',
6390
- /* usage */ undefined,
6391
- /* diag */ undefined, 64 /* SkipAttributeAccessOverride */)) === null || _e === void 0 ? void 0 : _e.type;
6392
- if (memberType) {
6393
- const functionResult = validateCallArguments(errorNode, argList, { type: memberType }, typeVarContext, skipUnknownArgCheck, inferenceContext, recursionCount);
6394
- (0, collectionUtils_1.appendArray)(overloadsUsedForCall, functionResult.overloadsUsedForCall);
6395
- if (functionResult.argumentErrors) {
6396
- argumentErrors = true;
6397
- }
6398
- if ((0, types_1.isTypeVar)(unexpandedSubtype) &&
6399
- types_1.TypeBase.isInstantiable(unexpandedSubtype) &&
6400
- (0, types_1.isClass)(expandedSubtype) &&
6401
- types_1.ClassType.isBuiltIn(expandedSubtype, 'type')) {
6402
- // Handle the case where a Type[T] is being called. We presume this
6403
- // will instantiate an object of type T.
6404
- return (0, typeUtils_1.convertToInstance)(unexpandedSubtype);
6405
- }
6406
- return (_f = functionResult.returnType) !== null && _f !== void 0 ? _f : types_1.UnknownType.create();
6407
- }
6408
- if (!memberType || !(0, types_1.isAnyOrUnknown)(memberType)) {
6409
- addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.objectNotCallable().format({
6410
- type: printType(expandedSubtype),
6411
- }), errorNode);
6412
- }
6413
- return types_1.UnknownType.create();
6414
- }
6181
+ /* conditionFilter */ undefined, (expandedSubtype, unexpandedSubtype, isLastIteration) => {
6182
+ return useSpeculativeMode(isLastIteration ? undefined : errorNode, () => {
6183
+ const callResult = validateCallArgumentsForSubtype(errorNode, argList, expandedSubtype, unexpandedSubtype, !!callTypeResult.isIncomplete, typeVarContext, skipUnknownArgCheck, inferenceContext, recursionCount);
6184
+ if (callResult.argumentErrors) {
6185
+ argumentErrors = true;
6415
6186
  }
6416
- case 3 /* None */: {
6417
- if (types_1.TypeBase.isInstantiable(expandedSubtype)) {
6418
- if (noneType && (0, types_1.isInstantiableClass)(noneType)) {
6419
- const functionResult = validateCallArguments(errorNode, argList, { type: noneType }, typeVarContext, skipUnknownArgCheck, inferenceContext, recursionCount);
6420
- if (functionResult.isTypeIncomplete) {
6421
- isTypeIncomplete = true;
6422
- }
6423
- if (functionResult.argumentErrors) {
6424
- argumentErrors = true;
6425
- }
6426
- }
6427
- return types_1.NoneType.createInstance();
6428
- }
6429
- addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportOptionalCall, diagnosticRules_1.DiagnosticRule.reportOptionalCall, localize_1.Localizer.Diagnostic.noneNotCallable(), errorNode);
6430
- return undefined;
6187
+ if (callResult.isTypeIncomplete) {
6188
+ isTypeIncomplete = true;
6431
6189
  }
6432
- // TypeVars should have been expanded in most cases,
6433
- // but we still need to handle the case of Type[T] where
6434
- // T is a constrained type that contains a union. We also
6435
- // need to handle recursive type aliases.
6436
- case 10 /* TypeVar */: {
6437
- expandedSubtype = (0, typeUtils_1.transformPossibleRecursiveTypeAlias)(expandedSubtype);
6438
- const callResult = validateCallArguments(errorNode, argList, { type: expandedSubtype }, typeVarContext, skipUnknownArgCheck, inferenceContext, recursionCount);
6190
+ if (callResult.overloadsUsedForCall) {
6439
6191
  (0, collectionUtils_1.appendArray)(overloadsUsedForCall, callResult.overloadsUsedForCall);
6440
- if (callResult.argumentErrors) {
6441
- argumentErrors = true;
6442
- }
6443
- return (_g = callResult.returnType) !== null && _g !== void 0 ? _g : types_1.UnknownType.create();
6444
- }
6445
- case 8 /* Module */: {
6446
- addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.moduleNotCallable(), errorNode);
6447
- return undefined;
6448
6192
  }
6449
- }
6450
- return undefined;
6193
+ specializedInitSelfType = callResult.specializedInitSelfType;
6194
+ return callResult.returnType;
6195
+ }, {
6196
+ allowDiagnostics: true,
6197
+ });
6451
6198
  });
6452
6199
  // If we ended up with a "Never" type because all code paths returned
6453
6200
  // undefined due to argument errors, transform the result into an Unknown
@@ -6463,10 +6210,350 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
6463
6210
  overloadsUsedForCall,
6464
6211
  };
6465
6212
  }
6213
+ function validateCallArgumentsForSubtype(errorNode, argList, expandedCallType, unexpandedCallType, isCallTypeIncomplete, typeVarContext, skipUnknownArgCheck, inferenceContext, recursionCount) {
6214
+ switch (expandedCallType.category) {
6215
+ case 4 /* Never */:
6216
+ case 1 /* Unknown */:
6217
+ case 2 /* Any */: {
6218
+ // Touch all of the args so they're marked accessed. Don't bother
6219
+ // doing this if the call type is incomplete because this will need
6220
+ // to be done again once it is complete.
6221
+ if (!isCallTypeIncomplete) {
6222
+ argList.forEach((arg) => {
6223
+ if (arg.valueExpression && !isSpeculativeModeInUse(arg.valueExpression)) {
6224
+ getTypeOfArgument(arg);
6225
+ }
6226
+ });
6227
+ }
6228
+ return { returnType: expandedCallType };
6229
+ }
6230
+ case 5 /* Function */: {
6231
+ return validateCallForFunction(errorNode, argList, expandedCallType, isCallTypeIncomplete, typeVarContext, skipUnknownArgCheck, inferenceContext);
6232
+ }
6233
+ case 6 /* OverloadedFunction */: {
6234
+ return validateCallForOverloadedFunction(errorNode, argList, expandedCallType, isCallTypeIncomplete, typeVarContext, skipUnknownArgCheck, inferenceContext);
6235
+ }
6236
+ case 7 /* Class */: {
6237
+ if (types_1.TypeBase.isInstantiable(expandedCallType)) {
6238
+ return validateCallForInstantiableClass(errorNode, argList, expandedCallType, unexpandedCallType, skipUnknownArgCheck, inferenceContext);
6239
+ }
6240
+ return validateCallForClassInstance(errorNode, argList, expandedCallType, unexpandedCallType, typeVarContext, skipUnknownArgCheck, inferenceContext, recursionCount);
6241
+ }
6242
+ case 3 /* None */: {
6243
+ if (types_1.TypeBase.isInstantiable(expandedCallType)) {
6244
+ if (noneType && (0, types_1.isInstantiableClass)(noneType)) {
6245
+ const callResult = validateCallForInstantiableClass(errorNode, argList, noneType, noneType, skipUnknownArgCheck, inferenceContext);
6246
+ return { ...callResult, returnType: types_1.NoneType.createInstance() };
6247
+ }
6248
+ return { returnType: types_1.NoneType.createInstance() };
6249
+ }
6250
+ addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportOptionalCall, diagnosticRules_1.DiagnosticRule.reportOptionalCall, localize_1.Localizer.Diagnostic.noneNotCallable(), errorNode);
6251
+ return { argumentErrors: true };
6252
+ }
6253
+ // TypeVars should have been expanded in most cases,
6254
+ // but we still need to handle the case of Type[T] where
6255
+ // T is a constrained type that contains a union. We also
6256
+ // need to handle recursive type aliases.
6257
+ case 10 /* TypeVar */: {
6258
+ return validateCallArguments(errorNode, argList, { type: (0, typeUtils_1.transformPossibleRecursiveTypeAlias)(expandedCallType), isIncomplete: isCallTypeIncomplete }, typeVarContext, skipUnknownArgCheck, inferenceContext, recursionCount);
6259
+ }
6260
+ case 8 /* Module */: {
6261
+ addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.moduleNotCallable(), errorNode);
6262
+ return { argumentErrors: true };
6263
+ }
6264
+ }
6265
+ return { argumentErrors: true };
6266
+ }
6267
+ function validateCallForFunction(errorNode, argList, expandedCallType, isCallTypeIncomplete, typeVarContext, skipUnknownArgCheck, inferenceContext) {
6268
+ var _a;
6269
+ if (types_1.TypeBase.isInstantiable(expandedCallType)) {
6270
+ addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.callableNotInstantiable().format({
6271
+ type: printType(expandedCallType),
6272
+ }), errorNode);
6273
+ return { returnType: undefined, argumentErrors: true };
6274
+ }
6275
+ // Check for an attempt to invoke an abstract static or class method.
6276
+ if (expandedCallType.boundToType &&
6277
+ (0, types_1.isInstantiableClass)(expandedCallType.boundToType) &&
6278
+ !expandedCallType.boundToType.includeSubclasses) {
6279
+ if (types_1.FunctionType.isAbstractMethod(expandedCallType)) {
6280
+ if (types_1.FunctionType.isStaticMethod(expandedCallType) || types_1.FunctionType.isClassMethod(expandedCallType)) {
6281
+ addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.abstractMethodInvocation().format({
6282
+ method: expandedCallType.details.name,
6283
+ }), errorNode.nodeType === 9 /* Call */ ? errorNode.leftExpression : errorNode);
6284
+ }
6285
+ }
6286
+ }
6287
+ // The stdlib collections/__init__.pyi stub file defines namedtuple
6288
+ // as a function rather than a class, so we need to check for it here.
6289
+ if (expandedCallType.details.builtInName === 'namedtuple') {
6290
+ addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportUntypedNamedTuple, diagnosticRules_1.DiagnosticRule.reportUntypedNamedTuple, localize_1.Localizer.Diagnostic.namedTupleNoTypes(), errorNode);
6291
+ return {
6292
+ returnType: (0, namedTuples_1.createNamedTupleType)(evaluatorInterface, errorNode, argList, /* includesTypes */ false),
6293
+ };
6294
+ }
6295
+ // Handle the NewType specially, replacing the normal return type.
6296
+ if (expandedCallType.details.builtInName === 'NewType') {
6297
+ return { returnType: createNewType(errorNode, argList) };
6298
+ }
6299
+ let effectiveTypeVarContext = typeVarContext;
6300
+ if (!effectiveTypeVarContext) {
6301
+ // If a typeVarContext wasn't provided by the caller, allocate one here.
6302
+ effectiveTypeVarContext = new typeVarContext_1.TypeVarContext((0, typeUtils_1.getTypeVarScopeIds)(expandedCallType));
6303
+ }
6304
+ const functionResult = validateFunctionArguments(errorNode, argList, { type: expandedCallType, isIncomplete: isCallTypeIncomplete }, effectiveTypeVarContext, skipUnknownArgCheck, inferenceContext);
6305
+ let isTypeIncomplete = !!functionResult.isTypeIncomplete;
6306
+ let returnType = functionResult.returnType;
6307
+ let argumentErrors = !!functionResult.argumentErrors;
6308
+ if (!argumentErrors) {
6309
+ // Call the function transform logic to handle special-cased functions.
6310
+ const transformed = (0, functionTransform_1.applyFunctionTransform)(evaluatorInterface, errorNode, argList, expandedCallType, {
6311
+ argumentErrors: !!functionResult.argumentErrors,
6312
+ returnType: (_a = functionResult.returnType) !== null && _a !== void 0 ? _a : types_1.UnknownType.create(isTypeIncomplete),
6313
+ isTypeIncomplete,
6314
+ });
6315
+ returnType = transformed.returnType;
6316
+ if (transformed.isTypeIncomplete) {
6317
+ isTypeIncomplete = true;
6318
+ }
6319
+ if (transformed.argumentErrors) {
6320
+ argumentErrors = true;
6321
+ }
6322
+ }
6323
+ if (expandedCallType.details.builtInName === '__import__') {
6324
+ // For the special __import__ type, we'll override the return type to be "Any".
6325
+ // This is required because we don't know what module was imported, and we don't
6326
+ // want to fail type checks when accessing members of the resulting module type.
6327
+ returnType = types_1.AnyType.create();
6328
+ }
6329
+ return {
6330
+ returnType,
6331
+ isTypeIncomplete,
6332
+ argumentErrors,
6333
+ overloadsUsedForCall: functionResult.overloadsUsedForCall,
6334
+ specializedInitSelfType: functionResult.specializedInitSelfType,
6335
+ };
6336
+ }
6337
+ function validateCallForOverloadedFunction(errorNode, argList, expandedCallType, isCallTypeIncomplete, typeVarContext, skipUnknownArgCheck, inferenceContext) {
6338
+ var _a, _b;
6339
+ // Handle the 'cast' call as a special case.
6340
+ if (expandedCallType.overloads[0].details.builtInName === 'cast' && argList.length === 2) {
6341
+ return { returnType: evaluateCastCall(argList, errorNode) };
6342
+ }
6343
+ const callResult = validateOverloadedFunctionArguments(errorNode, argList, { type: expandedCallType, isIncomplete: isCallTypeIncomplete }, typeVarContext, skipUnknownArgCheck, inferenceContext);
6344
+ let returnType = (_a = callResult.returnType) !== null && _a !== void 0 ? _a : types_1.UnknownType.create();
6345
+ let isTypeIncomplete = !!callResult.isTypeIncomplete;
6346
+ let argumentErrors = !!callResult.argumentErrors;
6347
+ if (!argumentErrors) {
6348
+ // Call the function transform logic to handle special-cased functions.
6349
+ const transformed = (0, functionTransform_1.applyFunctionTransform)(evaluatorInterface, errorNode, argList, expandedCallType, {
6350
+ argumentErrors: !!callResult.argumentErrors,
6351
+ returnType: (_b = callResult.returnType) !== null && _b !== void 0 ? _b : types_1.UnknownType.create(isTypeIncomplete),
6352
+ isTypeIncomplete,
6353
+ });
6354
+ returnType = transformed.returnType;
6355
+ if (transformed.isTypeIncomplete) {
6356
+ isTypeIncomplete = true;
6357
+ }
6358
+ if (transformed.argumentErrors) {
6359
+ argumentErrors = true;
6360
+ }
6361
+ }
6362
+ return {
6363
+ returnType,
6364
+ isTypeIncomplete,
6365
+ argumentErrors,
6366
+ overloadsUsedForCall: callResult.overloadsUsedForCall,
6367
+ specializedInitSelfType: callResult.specializedInitSelfType,
6368
+ };
6369
+ }
6370
+ function validateCallForInstantiableClass(errorNode, argList, expandedCallType, unexpandedCallType, skipUnknownArgCheck, inferenceContext) {
6371
+ var _a;
6372
+ if (expandedCallType.literalValue !== undefined) {
6373
+ addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.literalNotCallable(), errorNode);
6374
+ return { returnType: types_1.UnknownType.create(), argumentErrors: true };
6375
+ }
6376
+ if (types_1.ClassType.isBuiltIn(expandedCallType)) {
6377
+ const className = expandedCallType.aliasName || expandedCallType.details.name;
6378
+ if (className === 'type') {
6379
+ // Validate the constructor arguments.
6380
+ (0, constructors_1.validateConstructorArguments)(evaluatorInterface, errorNode, argList, expandedCallType, skipUnknownArgCheck, inferenceContext);
6381
+ // Handle the 'type' call specially.
6382
+ if (argList.length === 1) {
6383
+ // The one-parameter form of "type" returns the class
6384
+ // for the specified object.
6385
+ const argType = getTypeOfArgument(argList[0]).type;
6386
+ const returnType = (0, typeUtils_1.mapSubtypes)(argType, (subtype) => {
6387
+ if ((0, types_1.isClassInstance)(subtype) ||
6388
+ ((0, types_1.isTypeVar)(subtype) && types_1.TypeBase.isInstance(subtype)) ||
6389
+ (0, types_1.isNoneInstance)(subtype)) {
6390
+ return (0, typeUtils_1.convertToInstantiable)(stripLiteralValue(subtype));
6391
+ }
6392
+ else if ((0, types_1.isFunction)(subtype) && types_1.TypeBase.isInstance(subtype)) {
6393
+ return types_1.FunctionType.cloneAsInstantiable(subtype);
6394
+ }
6395
+ return types_1.AnyType.create();
6396
+ });
6397
+ return { returnType };
6398
+ }
6399
+ if (argList.length >= 2) {
6400
+ // The two-parameter form of "type" returns a new class type
6401
+ // built from the specified base types.
6402
+ return { returnType: createType(errorNode, argList) || types_1.AnyType.create() };
6403
+ }
6404
+ // If the parameter to type() is not statically known,
6405
+ // fall back to Any.
6406
+ return { returnType: types_1.AnyType.create() };
6407
+ }
6408
+ if (className === 'TypeVar') {
6409
+ return {
6410
+ returnType: createTypeVarType(errorNode, expandedCallType, argList),
6411
+ };
6412
+ }
6413
+ if (className === 'TypeVarTuple') {
6414
+ return {
6415
+ returnType: createTypeVarTupleType(errorNode, expandedCallType, argList),
6416
+ };
6417
+ }
6418
+ if (className === 'ParamSpec') {
6419
+ return {
6420
+ returnType: createParamSpecType(errorNode, expandedCallType, argList),
6421
+ };
6422
+ }
6423
+ if (className === 'TypeAliasType') {
6424
+ const newTypeAlias = createTypeAliasType(errorNode, argList);
6425
+ if (newTypeAlias) {
6426
+ return { returnType: newTypeAlias };
6427
+ }
6428
+ }
6429
+ if (className === 'NamedTuple') {
6430
+ return {
6431
+ returnType: (0, namedTuples_1.createNamedTupleType)(evaluatorInterface, errorNode, argList, /* includesTypes */ true),
6432
+ };
6433
+ }
6434
+ if (className === 'NewType') {
6435
+ return { returnType: createNewType(errorNode, argList) };
6436
+ }
6437
+ if (className === 'Protocol' ||
6438
+ className === 'Generic' ||
6439
+ className === 'Callable' ||
6440
+ className === 'Concatenate' ||
6441
+ className === 'Type') {
6442
+ const fileInfo = AnalyzerNodeInfo.getFileInfo(errorNode);
6443
+ addDiagnostic(fileInfo.diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.typeNotIntantiable().format({ type: className }), errorNode);
6444
+ return { returnType: types_1.AnyType.create() };
6445
+ }
6446
+ if ((0, types_1.isClass)(unexpandedCallType) && (0, enums_1.isKnownEnumType)(className)) {
6447
+ return {
6448
+ returnType: (_a = (0, enums_1.createEnumType)(evaluatorInterface, errorNode, expandedCallType, argList)) !== null && _a !== void 0 ? _a : types_1.UnknownType.create(),
6449
+ };
6450
+ }
6451
+ if (className === 'TypedDict') {
6452
+ return { returnType: (0, typedDicts_1.createTypedDictType)(evaluatorInterface, errorNode, expandedCallType, argList) };
6453
+ }
6454
+ if (className === 'auto' && argList.length === 0) {
6455
+ return { returnType: (0, enums_1.getEnumAutoValueType)(evaluatorInterface, errorNode) };
6456
+ }
6457
+ }
6458
+ if (types_1.ClassType.supportsAbstractMethods(expandedCallType)) {
6459
+ const abstractMethods = getAbstractMethods(expandedCallType);
6460
+ if (abstractMethods.length > 0 && !expandedCallType.includeSubclasses && !(0, types_1.isTypeVar)(unexpandedCallType)) {
6461
+ // If the class is abstract, it can't be instantiated.
6462
+ const diagAddendum = new diagnostic_1.DiagnosticAddendum();
6463
+ const errorsToDisplay = 2;
6464
+ abstractMethods.forEach((abstractMethod, index) => {
6465
+ if (index === errorsToDisplay) {
6466
+ diagAddendum.addMessage(localize_1.Localizer.DiagnosticAddendum.memberIsAbstractMore().format({
6467
+ count: abstractMethods.length - errorsToDisplay,
6468
+ }));
6469
+ }
6470
+ else if (index < errorsToDisplay) {
6471
+ if ((0, types_1.isInstantiableClass)(abstractMethod.classType)) {
6472
+ const className = abstractMethod.classType.details.name;
6473
+ diagAddendum.addMessage(localize_1.Localizer.DiagnosticAddendum.memberIsAbstract().format({
6474
+ type: className,
6475
+ name: abstractMethod.symbolName,
6476
+ }));
6477
+ }
6478
+ }
6479
+ });
6480
+ addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.instantiateAbstract().format({
6481
+ type: expandedCallType.details.name,
6482
+ }) + diagAddendum.getString(), errorNode);
6483
+ }
6484
+ }
6485
+ if (types_1.ClassType.isProtocolClass(expandedCallType) && !expandedCallType.includeSubclasses) {
6486
+ // If the class is a protocol, it can't be instantiated.
6487
+ addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.instantiateProtocol().format({
6488
+ type: expandedCallType.details.name,
6489
+ }), errorNode);
6490
+ }
6491
+ // Assume this is a call to the constructor.
6492
+ const constructorResult = (0, constructors_1.validateConstructorArguments)(evaluatorInterface, errorNode, argList, expandedCallType, skipUnknownArgCheck, inferenceContext);
6493
+ const overloadsUsedForCall = constructorResult.overloadsUsedForCall;
6494
+ const argumentErrors = constructorResult.argumentErrors;
6495
+ const isTypeIncomplete = constructorResult.isTypeIncomplete;
6496
+ let returnType = constructorResult.returnType;
6497
+ // If the expandedCallType originated from a TypeVar, convert
6498
+ // the constructed type back to the TypeVar. For example, if
6499
+ // we have `cls: Type[_T]` followed by `_T()`.
6500
+ if ((0, types_1.isTypeVar)(unexpandedCallType)) {
6501
+ returnType = (0, typeUtils_1.convertToInstance)(unexpandedCallType);
6502
+ }
6503
+ // If we instantiated a type, transform it into a class.
6504
+ // This can happen if someone directly instantiates a metaclass
6505
+ // deriving from type.
6506
+ if (returnType &&
6507
+ (0, types_1.isClassInstance)(returnType) &&
6508
+ returnType.details.mro.some((baseClass) => (0, types_1.isInstantiableClass)(baseClass) && types_1.ClassType.isBuiltIn(baseClass, 'type'))) {
6509
+ let newClassName = '__class_' + returnType.details.name;
6510
+ if (argList.length === 3) {
6511
+ const firstArgType = getTypeOfArgument(argList[0]).type;
6512
+ if ((0, types_1.isClassInstance)(firstArgType) &&
6513
+ types_1.ClassType.isBuiltIn(firstArgType, 'str') &&
6514
+ typeof firstArgType.literalValue === 'string') {
6515
+ newClassName = firstArgType.literalValue;
6516
+ }
6517
+ }
6518
+ const newClassType = types_1.ClassType.createInstantiable(newClassName, '', '', AnalyzerNodeInfo.getFileInfo(errorNode).filePath, 0 /* None */, ParseTreeUtils.getTypeSourceId(errorNode), types_1.ClassType.cloneAsInstantiable(returnType), types_1.ClassType.cloneAsInstantiable(returnType));
6519
+ newClassType.details.baseClasses.push(getBuiltInType(errorNode, 'object'));
6520
+ newClassType.details.effectiveMetaclass = expandedCallType;
6521
+ (0, typeUtils_1.computeMroLinearization)(newClassType);
6522
+ returnType = newClassType;
6523
+ }
6524
+ return { returnType, overloadsUsedForCall, argumentErrors, isTypeIncomplete };
6525
+ }
6526
+ function validateCallForClassInstance(errorNode, argList, expandedCallType, unexpandedCallType, typeVarContext, skipUnknownArgCheck, inferenceContext, recursionCount) {
6527
+ var _a, _b;
6528
+ const memberType = (_a = getTypeOfObjectMember(errorNode, expandedCallType, '__call__',
6529
+ /* usage */ undefined,
6530
+ /* diag */ undefined, 64 /* SkipAttributeAccessOverride */)) === null || _a === void 0 ? void 0 : _a.type;
6531
+ if (!memberType) {
6532
+ addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.objectNotCallable().format({
6533
+ type: printType(expandedCallType),
6534
+ }), errorNode);
6535
+ return { returnType: types_1.UnknownType.create(), argumentErrors: true };
6536
+ }
6537
+ const callResult = validateCallArguments(errorNode, argList, { type: memberType }, typeVarContext, skipUnknownArgCheck, inferenceContext, recursionCount);
6538
+ let returnType = (_b = callResult.returnType) !== null && _b !== void 0 ? _b : types_1.UnknownType.create();
6539
+ if ((0, types_1.isTypeVar)(unexpandedCallType) &&
6540
+ types_1.TypeBase.isInstantiable(unexpandedCallType) &&
6541
+ (0, types_1.isClass)(expandedCallType) &&
6542
+ types_1.ClassType.isBuiltIn(expandedCallType, 'type')) {
6543
+ // Handle the case where a Type[T] is being called. We presume this
6544
+ // will instantiate an object of type T.
6545
+ returnType = (0, typeUtils_1.convertToInstance)(unexpandedCallType);
6546
+ }
6547
+ return {
6548
+ returnType,
6549
+ argumentErrors: callResult.argumentErrors,
6550
+ overloadsUsedForCall: callResult.overloadsUsedForCall,
6551
+ };
6552
+ }
6466
6553
  // Evaluates the type of the "cast" call.
6467
6554
  function evaluateCastCall(argList, errorNode) {
6468
6555
  // Verify that the cast is necessary.
6469
- const castToType = getTypeOfArgumentExpectingType(argList[0]).type;
6556
+ const castToType = getTypeOfArgumentExpectingType(argList[0], { enforceTypeAnnotationRules: true }).type;
6470
6557
  const castFromType = getTypeOfArgument(argList[1]).type;
6471
6558
  if (types_1.TypeBase.isInstantiable(castToType) && !(0, types_1.isUnknown)(castToType)) {
6472
6559
  if ((0, types_1.isTypeSame)((0, typeUtils_1.convertToInstance)(castToType), castFromType, {
@@ -7328,6 +7415,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
7328
7415
  paramSpecArgList,
7329
7416
  activeParam,
7330
7417
  relevance,
7418
+ argumentMatchScore: 0,
7331
7419
  };
7332
7420
  }
7333
7421
  // After having matched arguments with parameters, this function evaluates the
@@ -7403,7 +7491,9 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
7403
7491
  const genericReturnType = types_1.ClassType.cloneForSpecialization(effectiveReturnType,
7404
7492
  /* typeArguments */ undefined,
7405
7493
  /* isTypeArgumentExplicit */ false);
7406
- effectiveExpectedType = (0, typeUtils_1.applySolvedTypeVars)(genericReturnType, tempTypeVarContext);
7494
+ effectiveExpectedType = (0, typeUtils_1.applySolvedTypeVars)(genericReturnType, tempTypeVarContext, {
7495
+ unknownIfNotFound: true,
7496
+ });
7407
7497
  }
7408
7498
  }
7409
7499
  else if ((0, types_1.isFunction)(effectiveReturnType)) {
@@ -7426,6 +7516,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
7426
7516
  const type = matchResults.overload;
7427
7517
  let isTypeIncomplete = matchResults.isTypeIncomplete;
7428
7518
  let argumentErrors = false;
7519
+ let argumentMatchScore = 0;
7429
7520
  let specializedInitSelfType;
7430
7521
  let anyOrUnknownArgument;
7431
7522
  const typeCondition = (0, typeUtils_1.getTypeCondition)(type);
@@ -7527,7 +7618,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
7527
7618
  let sawParamSpecKwargs = false;
7528
7619
  let condition = [];
7529
7620
  const argResults = [];
7530
- matchResults.argParams.forEach((argParam) => {
7621
+ matchResults.argParams.forEach((argParam, argParamIndex) => {
7531
7622
  var _a;
7532
7623
  const argResult = validateArgType(argParam, typeVarContext, signatureTracker, { type, isIncomplete: matchResults.isTypeIncomplete }, {
7533
7624
  skipUnknownArgCheck,
@@ -7536,6 +7627,10 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
7536
7627
  argResults.push(argResult);
7537
7628
  if (!argResult.isCompatible) {
7538
7629
  argumentErrors = true;
7630
+ // Add the inverse index so earlier parameters represent larger errors.
7631
+ // This will help the heuristics in the overload error paths to pick the
7632
+ // most likely intended overload if none of them match.
7633
+ argumentMatchScore += 1 + (matchResults.argParams.length - argParamIndex);
7539
7634
  }
7540
7635
  if (argResult.isTypeIncomplete) {
7541
7636
  isTypeIncomplete = true;
@@ -7561,11 +7656,15 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
7561
7656
  }
7562
7657
  }
7563
7658
  });
7659
+ let paramSpecTypeVarContext = [];
7564
7660
  // Handle the assignment of additional arguments that map to a param spec.
7565
7661
  if (matchResults.paramSpecArgList && matchResults.paramSpecTarget) {
7566
- if (!validateFunctionArgumentsForParamSpec(errorNode, matchResults.paramSpecArgList, matchResults.paramSpecTarget, typeVarContext, typeCondition)) {
7662
+ const paramSpecArgResult = validateFunctionArgumentsForParamSpec(errorNode, matchResults.paramSpecArgList, matchResults.paramSpecTarget, typeVarContext, typeCondition);
7663
+ if (paramSpecArgResult.argumentErrors) {
7567
7664
  argumentErrors = true;
7665
+ argumentMatchScore += 1;
7568
7666
  }
7667
+ paramSpecTypeVarContext = paramSpecArgResult.typeVarContexts;
7569
7668
  }
7570
7669
  else if (type.details.paramSpec) {
7571
7670
  if (!sawParamSpecArgs || !sawParamSpecKwargs) {
@@ -7573,6 +7672,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
7573
7672
  addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.paramSpecArgsMissing().format({ type: printType(type.details.paramSpec) }), errorNode);
7574
7673
  }
7575
7674
  argumentErrors = true;
7675
+ argumentMatchScore += 1;
7576
7676
  }
7577
7677
  }
7578
7678
  // Calculate the return type.
@@ -7618,17 +7718,28 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
7618
7718
  applyInScopePlaceholders: true,
7619
7719
  });
7620
7720
  specializedReturnType = (0, typeUtils_1.addConditionToType)(specializedReturnType, typeCondition);
7721
+ // If the function includes a ParamSpec and the captured signature(s) includes
7722
+ // generic types, we may need to apply those solved TypeVars.
7723
+ if (paramSpecTypeVarContext.length > 0) {
7724
+ paramSpecTypeVarContext.forEach((paramSpecTypeVarContext) => {
7725
+ if (paramSpecTypeVarContext) {
7726
+ specializedReturnType = (0, typeUtils_1.applySolvedTypeVars)(specializedReturnType, paramSpecTypeVarContext);
7727
+ }
7728
+ });
7729
+ }
7621
7730
  // If the final return type is an unpacked tuple, turn it into a normal (unpacked) tuple.
7622
7731
  if ((0, types_1.isUnpackedClass)(specializedReturnType)) {
7623
7732
  specializedReturnType = types_1.ClassType.cloneForUnpacked(specializedReturnType, /* isUnpackedTuple */ false);
7624
7733
  }
7625
- // Handle 'TypeGuard' and 'StrictTypeGuard' specially. We'll transform the
7626
- // return type into a 'bool' object with a type argument that reflects the
7627
- // narrowed type.
7734
+ // Handle 'TypeGuard' specially. We'll transform the return type into a 'bool'
7735
+ // object with a type argument that reflects the narrowed type.
7628
7736
  if ((0, types_1.isClassInstance)(specializedReturnType) &&
7629
- types_1.ClassType.isBuiltIn(specializedReturnType, ['TypeGuard', 'StrictTypeGuard']) &&
7737
+ types_1.ClassType.isBuiltIn(specializedReturnType, 'TypeGuard') &&
7630
7738
  specializedReturnType.typeArguments &&
7631
- specializedReturnType.typeArguments.length > 0) {
7739
+ specializedReturnType.typeArguments.length > 0 &&
7740
+ (0, types_1.isClassInstance)(returnType) &&
7741
+ returnType.typeArguments &&
7742
+ returnType.typeArguments.length > 0) {
7632
7743
  if (boolClassType && (0, types_1.isInstantiableClass)(boolClassType)) {
7633
7744
  let typeGuardType = specializedReturnType.typeArguments[0];
7634
7745
  // If the first argument is a simple (non-constrained) TypeVar,
@@ -7647,13 +7758,28 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
7647
7758
  ]);
7648
7759
  }
7649
7760
  }
7650
- specializedReturnType = types_1.ClassType.cloneAsInstance(types_1.ClassType.cloneForTypeGuard(boolClassType, typeGuardType, types_1.ClassType.isBuiltIn(specializedReturnType, 'StrictTypeGuard')));
7761
+ let useStrictTypeGuardSemantics = false;
7762
+ if (AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.enableExperimentalFeatures) {
7763
+ // Determine the type of the first parameter.
7764
+ const paramIndex = type.boundToType ? 1 : 0;
7765
+ if (paramIndex < type.details.parameters.length) {
7766
+ const paramType = types_1.FunctionType.getEffectiveParameterType(type, paramIndex);
7767
+ // If the type guard meets the requirements that the first parameter
7768
+ // type is a proper subtype of the return type, we can use strict
7769
+ // type guard semantics.
7770
+ if (assignType(paramType, returnType.typeArguments[0])) {
7771
+ useStrictTypeGuardSemantics = true;
7772
+ }
7773
+ }
7774
+ }
7775
+ specializedReturnType = types_1.ClassType.cloneAsInstance(types_1.ClassType.cloneForTypeGuard(boolClassType, typeGuardType, useStrictTypeGuardSemantics));
7651
7776
  }
7652
7777
  }
7653
7778
  specializedReturnType = adjustCallableReturnType(specializedReturnType);
7654
7779
  if (specializedInitSelfType) {
7655
7780
  specializedInitSelfType = (0, typeUtils_1.applySolvedTypeVars)(specializedInitSelfType, typeVarContext);
7656
7781
  }
7782
+ matchResults.argumentMatchScore = argumentMatchScore;
7657
7783
  return {
7658
7784
  argumentErrors,
7659
7785
  argResults,
@@ -7698,7 +7824,13 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
7698
7824
  // specific use case. We may need to make this more sophisticated in
7699
7825
  // the future.
7700
7826
  if ((0, types_1.isFunction)(returnType) && !returnType.details.name) {
7701
- return types_1.FunctionType.cloneWithNewTypeVarScopeId(returnType, types_1.WildcardTypeVarScopeId);
7827
+ const typeVarsInReturnType = (0, typeUtils_1.getTypeVarArgumentsRecursive)(returnType);
7828
+ // If there are no unsolved type variables, we're done. If there are
7829
+ // unsolved type parameters, treat them as though they are rescoped
7830
+ // to the callable.
7831
+ if (typeVarsInReturnType.length > 0) {
7832
+ return types_1.FunctionType.cloneWithNewTypeVarScopeId(returnType, types_1.WildcardTypeVarScopeId, typeVarsInReturnType);
7833
+ }
7702
7834
  }
7703
7835
  return returnType;
7704
7836
  }
@@ -7735,12 +7867,15 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
7735
7867
  return validateFunctionArgumentsForParamSpecSignature(errorNode, argList, paramSpec, signatureContexts[0], conditionFilter);
7736
7868
  }
7737
7869
  const filteredSignatureContexts = [];
7870
+ const typeVarContexts = [];
7738
7871
  signatureContexts.forEach((context) => {
7739
7872
  // Use speculative mode to avoid emitting errors or caching types.
7740
7873
  useSpeculativeMode(errorNode, () => {
7741
- if (validateFunctionArgumentsForParamSpecSignature(errorNode, argList, paramSpec, context, conditionFilter)) {
7874
+ const paramSpecArgResult = validateFunctionArgumentsForParamSpecSignature(errorNode, argList, paramSpec, context, conditionFilter);
7875
+ if (!paramSpecArgResult.argumentErrors) {
7742
7876
  filteredSignatureContexts.push(context);
7743
7877
  }
7878
+ (0, collectionUtils_1.appendArray)(typeVarContexts, paramSpecArgResult.typeVarContexts);
7744
7879
  });
7745
7880
  });
7746
7881
  // Copy back any compatible signature contexts if any were compatible.
@@ -7748,109 +7883,121 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
7748
7883
  destTypeVarContext.copySignatureContexts(filteredSignatureContexts);
7749
7884
  }
7750
7885
  // Evaluate non-speculatively to produce a final result and cache types.
7751
- return validateFunctionArgumentsForParamSpecSignature(errorNode, argList, paramSpec, filteredSignatureContexts.length > 0 ? filteredSignatureContexts[0] : signatureContexts[0], conditionFilter);
7886
+ const paramSpecArgResult = validateFunctionArgumentsForParamSpecSignature(errorNode, argList, paramSpec, filteredSignatureContexts.length > 0 ? filteredSignatureContexts[0] : signatureContexts[0], conditionFilter);
7887
+ return { argumentErrors: paramSpecArgResult.argumentErrors, typeVarContexts };
7752
7888
  }
7753
7889
  function validateFunctionArgumentsForParamSpecSignature(errorNode, argList, paramSpec, typeVarContext, conditionFilter) {
7754
7890
  var _a;
7755
7891
  const paramSpecType = typeVarContext.getParamSpecType(paramSpec);
7756
7892
  if (!paramSpecType) {
7757
7893
  addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.paramSpecNotBound().format({ type: printType(paramSpec) }), ((_a = argList[0]) === null || _a === void 0 ? void 0 : _a.valueExpression) || errorNode);
7758
- return false;
7894
+ return { argumentErrors: true, typeVarContexts: [undefined] };
7759
7895
  }
7760
7896
  const liveTypeVarScopes = ParseTreeUtils.getTypeVarScopesForNode(errorNode);
7761
7897
  const srcTypeVarContext = new typeVarContext_1.TypeVarContext((0, typeUtils_1.getTypeVarScopeIds)(paramSpecType));
7762
7898
  let reportedArgError = false;
7763
- // Build a map of all named parameters.
7764
- const paramMap = new Map();
7765
- const paramSpecParams = paramSpecType.details.parameters;
7766
- paramSpecParams.forEach((param) => {
7767
- if (param.name) {
7768
- paramMap.set(param.name, param);
7769
- }
7770
- });
7771
- let positionalIndex = 0;
7772
- let positionalIndexLimit = paramSpecParams.findIndex((paramInfo) => paramInfo.category !== 0 /* Simple */);
7773
- if (positionalIndexLimit < 0) {
7774
- positionalIndexLimit = paramSpecParams.length;
7775
- }
7776
- const argsParam = paramSpecParams.find((paramInfo) => paramInfo.category === 1 /* ArgsList */);
7777
- const kwargsParam = paramSpecParams.find((paramInfo) => paramInfo.category === 2 /* KwargsDict */);
7778
- const signatureTracker = new typeUtils_1.UniqueSignatureTracker();
7779
7899
  let sawUnpackedListArgument = false;
7780
7900
  let sawUnpackedDictArgument = false;
7781
- argList.forEach((arg) => {
7782
- var _a;
7783
- if (arg.argumentCategory === 0 /* Simple */) {
7784
- let paramType;
7785
- if (arg.name) {
7786
- const paramInfo = paramMap.get(arg.name.value);
7787
- if (paramInfo) {
7788
- paramType = paramInfo.type;
7789
- paramMap.delete(arg.name.value);
7790
- }
7791
- else if (kwargsParam) {
7792
- paramType = kwargsParam.type;
7793
- }
7794
- else {
7795
- addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.paramNameMissing().format({ name: arg.name.value }), arg.name || errorNode);
7796
- reportedArgError = true;
7901
+ let paramMap = new Map();
7902
+ // We'll use two passes in case there are type variables that depend
7903
+ // on later arguments.
7904
+ const passCount = 2;
7905
+ for (let i = 0; i < passCount; i++) {
7906
+ // Unless we're on the last pass, use speculative mode to suppress
7907
+ // any diagnostics.
7908
+ useSpeculativeMode(i < passCount - 1 ? errorNode : undefined, () => {
7909
+ // Build a map of all named parameters.
7910
+ paramMap = new Map();
7911
+ const paramSpecParams = paramSpecType.details.parameters;
7912
+ paramSpecParams.forEach((param) => {
7913
+ if (param.name) {
7914
+ paramMap.set(param.name, param);
7797
7915
  }
7798
- }
7799
- else {
7800
- if (positionalIndex < positionalIndexLimit) {
7801
- const paramInfo = paramSpecParams[positionalIndex];
7802
- paramType = paramInfo.type;
7803
- if (paramInfo.name) {
7804
- paramMap.delete(paramInfo.name);
7916
+ });
7917
+ let positionalIndex = 0;
7918
+ let positionalIndexLimit = paramSpecParams.findIndex((paramInfo) => paramInfo.category !== 0 /* Simple */);
7919
+ if (positionalIndexLimit < 0) {
7920
+ positionalIndexLimit = paramSpecParams.length;
7921
+ }
7922
+ const argsParam = paramSpecParams.find((paramInfo) => paramInfo.category === 1 /* ArgsList */);
7923
+ const kwargsParam = paramSpecParams.find((paramInfo) => paramInfo.category === 2 /* KwargsDict */);
7924
+ const signatureTracker = new typeUtils_1.UniqueSignatureTracker();
7925
+ argList.forEach((arg) => {
7926
+ var _a;
7927
+ if (arg.argumentCategory === 0 /* Simple */) {
7928
+ let paramType;
7929
+ if (arg.name) {
7930
+ const paramInfo = paramMap.get(arg.name.value);
7931
+ if (paramInfo) {
7932
+ paramType = paramInfo.type;
7933
+ paramMap.delete(arg.name.value);
7934
+ }
7935
+ else if (kwargsParam) {
7936
+ paramType = kwargsParam.type;
7937
+ }
7938
+ else {
7939
+ addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.paramNameMissing().format({ name: arg.name.value }), arg.name || errorNode);
7940
+ reportedArgError = true;
7941
+ }
7942
+ }
7943
+ else {
7944
+ if (positionalIndex < positionalIndexLimit) {
7945
+ const paramInfo = paramSpecParams[positionalIndex];
7946
+ paramType = paramInfo.type;
7947
+ if (paramInfo.name) {
7948
+ paramMap.delete(paramInfo.name);
7949
+ }
7950
+ }
7951
+ else if (argsParam) {
7952
+ paramType = argsParam.type;
7953
+ }
7954
+ else {
7955
+ addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, paramSpecParams.length === 1
7956
+ ? localize_1.Localizer.Diagnostic.argPositionalExpectedOne()
7957
+ : localize_1.Localizer.Diagnostic.argPositionalExpectedCount().format({
7958
+ expected: paramSpecParams.length,
7959
+ }), (_a = arg.valueExpression) !== null && _a !== void 0 ? _a : errorNode);
7960
+ reportedArgError = true;
7961
+ }
7962
+ positionalIndex++;
7963
+ }
7964
+ if (paramType) {
7965
+ const argResult = validateArgType({
7966
+ paramCategory: 0 /* Simple */,
7967
+ paramType: (0, typeUtils_1.transformExpectedType)(paramType, liveTypeVarScopes,
7968
+ /* usageOffset */ undefined),
7969
+ requiresTypeVarMatching: false,
7970
+ argument: arg,
7971
+ errorNode: arg.valueExpression || errorNode,
7972
+ }, srcTypeVarContext, signatureTracker,
7973
+ /* functionType */ undefined, { conditionFilter });
7974
+ if (!argResult.isCompatible) {
7975
+ reportedArgError = true;
7976
+ }
7805
7977
  }
7806
7978
  }
7807
- else if (argsParam) {
7808
- paramType = argsParam.type;
7979
+ else if (arg.argumentCategory === 1 /* UnpackedList */) {
7980
+ sawUnpackedListArgument = true;
7981
+ // See if there is an *args parameter.
7982
+ const argsParam = paramSpecParams.find((param) => param.category === 1 /* ArgsList */ && param.name);
7983
+ if (argsParam && paramMap.has(argsParam.name)) {
7984
+ // TODO - validate args type
7985
+ paramMap.delete(argsParam.name);
7986
+ }
7809
7987
  }
7810
7988
  else {
7811
- addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, paramSpecParams.length === 1
7812
- ? localize_1.Localizer.Diagnostic.argPositionalExpectedOne()
7813
- : localize_1.Localizer.Diagnostic.argPositionalExpectedCount().format({
7814
- expected: paramSpecParams.length,
7815
- }), (_a = arg.valueExpression) !== null && _a !== void 0 ? _a : errorNode);
7816
- reportedArgError = true;
7817
- }
7818
- positionalIndex++;
7819
- }
7820
- if (paramType) {
7821
- const argResult = validateArgType({
7822
- paramCategory: 0 /* Simple */,
7823
- paramType: (0, typeUtils_1.transformExpectedType)(paramType, liveTypeVarScopes, /* usageOffset */ undefined),
7824
- requiresTypeVarMatching: false,
7825
- argument: arg,
7826
- errorNode: arg.valueExpression || errorNode,
7827
- }, srcTypeVarContext, signatureTracker,
7828
- /* functionType */ undefined, { conditionFilter });
7829
- if (!argResult.isCompatible) {
7830
- reportedArgError = true;
7989
+ sawUnpackedDictArgument = true;
7990
+ (0, debug_1.assert)(arg.argumentCategory === 2 /* UnpackedDictionary */);
7991
+ // See if there is an *kwargs parameter.
7992
+ const kwargsParam = paramSpecParams.find((param) => param.category === 2 /* KwargsDict */);
7993
+ if (kwargsParam && paramMap.has(kwargsParam.name)) {
7994
+ // TODO - validate kwargs type
7995
+ paramMap.delete(kwargsParam.name);
7996
+ }
7831
7997
  }
7832
- }
7833
- }
7834
- else if (arg.argumentCategory === 1 /* UnpackedList */) {
7835
- sawUnpackedListArgument = true;
7836
- // See if there is an *args parameter.
7837
- const argsParam = paramSpecParams.find((param) => param.category === 1 /* ArgsList */ && param.name);
7838
- if (argsParam && paramMap.has(argsParam.name)) {
7839
- // TODO - validate args type
7840
- paramMap.delete(argsParam.name);
7841
- }
7842
- }
7843
- else {
7844
- sawUnpackedDictArgument = true;
7845
- (0, debug_1.assert)(arg.argumentCategory === 2 /* UnpackedDictionary */);
7846
- // See if there is an *kwargs parameter.
7847
- const kwargsParam = paramSpecParams.find((param) => param.category === 2 /* KwargsDict */);
7848
- if (kwargsParam && paramMap.has(kwargsParam.name)) {
7849
- // TODO - validate kwargs type
7850
- paramMap.delete(kwargsParam.name);
7851
- }
7852
- }
7853
- });
7998
+ });
7999
+ });
8000
+ }
7854
8001
  // Report any missing parameters.
7855
8002
  if (!reportedArgError) {
7856
8003
  let unassignedParams = Array.from(paramMap.keys());
@@ -7873,7 +8020,10 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
7873
8020
  if (!reportedArgError) {
7874
8021
  (0, typeUtils_1.applySourceContextTypeVarsToSignature)(typeVarContext, srcTypeVarContext);
7875
8022
  }
7876
- return !reportedArgError;
8023
+ return {
8024
+ argumentErrors: reportedArgError,
8025
+ typeVarContexts: [reportedArgError ? srcTypeVarContext : undefined],
8026
+ };
7877
8027
  }
7878
8028
  function validateArgType(argParam, typeVarContext, signatureTracker, typeResult, options) {
7879
8029
  var _a;
@@ -8816,9 +8966,15 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
8816
8966
  // Dict and MutableMapping types have invariant value types, so they
8817
8967
  // cannot be narrowed further. Other super-types like Mapping, Collection,
8818
8968
  // and Iterable use covariant value types, so they can be narrowed.
8819
- const isValueTypeInvariant = (0, types_1.isClassInstance)(inferenceContext.expectedType) &&
8820
- (types_1.ClassType.isBuiltIn(inferenceContext.expectedType, 'dict') ||
8821
- types_1.ClassType.isBuiltIn(inferenceContext.expectedType, 'MutableMapping'));
8969
+ let isValueTypeInvariant = false;
8970
+ if ((0, types_1.isClassInstance)(inferenceContext.expectedType)) {
8971
+ if (inferenceContext.expectedType.details.typeParameters.length >= 2) {
8972
+ const valueTypeParam = inferenceContext.expectedType.details.typeParameters[1];
8973
+ if (types_1.TypeVarType.getVariance(valueTypeParam) === 2 /* Invariant */) {
8974
+ isValueTypeInvariant = true;
8975
+ }
8976
+ }
8977
+ }
8822
8978
  // Infer the key and value types if possible.
8823
8979
  if (getKeyAndValueTypesFromDictionary(node, keyTypes, valueTypes,
8824
8980
  /* forceStrictInference */ true, isValueTypeInvariant, expectedKeyType, expectedValueType, undefined, expectedDiagAddendum)) {
@@ -9416,7 +9572,9 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
9416
9572
  if (returnTypeResult.isIncomplete) {
9417
9573
  isIncomplete = true;
9418
9574
  }
9419
- }, inferenceContext === null || inferenceContext === void 0 ? void 0 : inferenceContext.expectedType);
9575
+ }, {
9576
+ dependentType: inferenceContext === null || inferenceContext === void 0 ? void 0 : inferenceContext.expectedType,
9577
+ });
9420
9578
  // Mark the function type as no longer being evaluated.
9421
9579
  functionType.details.flags &= ~131072 /* PartiallyEvaluated */;
9422
9580
  return { type: functionType, isIncomplete };
@@ -9642,13 +9800,11 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
9642
9800
  }
9643
9801
  return true;
9644
9802
  }
9645
- // Converts the type parameters for a Callable type. It should
9646
- // have zero to two parameters. The first parameter, if present, should be
9647
- // either an ellipsis or a list of parameter types. The second parameter, if
9648
- // present, should specify the return type.
9803
+ // Evaluates the type arguments for a Callable type. It should have zero
9804
+ // to two arguments.The first argument, if present, should be an ellipsis,
9805
+ // a ParamSpec, a Concatenate, or a list of positional parameter types.
9806
+ // The second argument, if present, should specify the return type.
9649
9807
  function createCallableType(typeArgs, errorNode) {
9650
- // Create a new function that is marked as "static" so there is later
9651
- // no attempt to bind it as though it's an instance or class method.
9652
9808
  const functionType = types_1.FunctionType.createInstantiable(0 /* None */);
9653
9809
  types_1.TypeBase.setSpecialForm(functionType);
9654
9810
  functionType.details.declaredReturnType = types_1.UnknownType.create();
@@ -10342,12 +10498,9 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
10342
10498
  // Determine if there are any generic type parameters associated
10343
10499
  // with this type alias.
10344
10500
  typeParameters = [];
10345
- // Skip this for a simple TypeVar (one that's not part of a union).
10346
- if (!(0, types_1.isTypeVar)(type) || types_1.TypeBase.isAnnotated(type)) {
10347
- (0, typeUtils_1.doForEachSubtype)(type, (subtype) => {
10348
- (0, typeUtils_1.addTypeVarsToListIfUnique)(typeParameters, (0, typeUtils_1.getTypeVarArgumentsRecursive)(subtype));
10349
- });
10350
- }
10501
+ (0, typeUtils_1.doForEachSubtype)(type, (subtype) => {
10502
+ (0, typeUtils_1.addTypeVarsToListIfUnique)(typeParameters, (0, typeUtils_1.getTypeVarArgumentsRecursive)(subtype));
10503
+ });
10351
10504
  // Don't include any synthesized type variables.
10352
10505
  typeParameters = typeParameters.filter((typeVar) => !typeVar.details.isSynthesized);
10353
10506
  }
@@ -10458,7 +10611,6 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
10458
10611
  ['TypeAlias', { alias: '', module: 'builtins' }],
10459
10612
  ['Concatenate', { alias: '', module: 'builtins' }],
10460
10613
  ['TypeGuard', { alias: '', module: 'builtins' }],
10461
- ['StrictTypeGuard', { alias: '', module: 'builtins' }],
10462
10614
  ['Unpack', { alias: '', module: 'builtins' }],
10463
10615
  ['Required', { alias: '', module: 'builtins' }],
10464
10616
  ['NotRequired', { alias: '', module: 'builtins' }],
@@ -10468,7 +10620,12 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
10468
10620
  ['LiteralString', { alias: '', module: 'builtins' }],
10469
10621
  ['ReadOnly', { alias: '', module: 'builtins' }],
10470
10622
  ]);
10471
- const aliasMapEntry = specialTypes.get(assignedName);
10623
+ let aliasMapEntry = specialTypes.get(assignedName);
10624
+ // Support ReadOnly only as an experimental feature.
10625
+ if (assignedName === 'ReadOnly' &&
10626
+ !AnalyzerNodeInfo.getFileInfo(node).diagnosticRuleSet.enableExperimentalFeatures) {
10627
+ aliasMapEntry = undefined;
10628
+ }
10472
10629
  if (aliasMapEntry) {
10473
10630
  const cachedType = readTypeCache(node, 0 /* None */);
10474
10631
  if (cachedType) {
@@ -10881,10 +11038,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
10881
11038
  // If the base class is partially evaluated, install a callback
10882
11039
  // so we can fix up this class (e.g. compute the MRO) when the
10883
11040
  // dependent class is completed.
10884
- classTypeHooks.push({
10885
- dependency: argType,
10886
- callback: () => completeClassTypeDeferred(classType, node, node.name),
10887
- });
11041
+ registerDeferredClassCompletion(node, argType);
10888
11042
  }
10889
11043
  if (types_1.ClassType.isBuiltIn(argType, 'Protocol')) {
10890
11044
  if (!fileInfo.isStubFile &&
@@ -11200,8 +11354,12 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
11200
11354
  (0, dataClasses_1.applyDataClassDefaultBehaviors)(classType, dataClassBehaviors);
11201
11355
  (0, dataClasses_1.applyDataClassClassBehaviorOverrides)(evaluatorInterface, node.name, classType, initSubclassArgs, dataClassBehaviors);
11202
11356
  }
11203
- // Run any class hooks that depend on this class.
11204
- runClassTypeHooks(classType);
11357
+ // Run any deferred class completions that depend on this class.
11358
+ runDeferredClassCompletions(classType);
11359
+ // If there are any outstanding deferred class completions registered that
11360
+ // were not removed by the call to runDeferredClassCompletions, assume that
11361
+ // the current class may depend on them and register for deferred completion.
11362
+ registerDeferredClassCompletion(node, /* dependsUpon */ undefined);
11205
11363
  // Synthesize TypedDict methods.
11206
11364
  if (types_1.ClassType.isTypedDictClass(classType)) {
11207
11365
  (0, typedDicts_1.synthesizeTypedDictClassMethods)(evaluatorInterface, node, classType, (0, types_1.isClass)(decoratedType) && types_1.ClassType.isFinal(decoratedType));
@@ -11434,21 +11592,47 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
11434
11592
  addDiagnostic(AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.typeVarsNotInGenericOrProtocol() + diag.getString(), errorNode);
11435
11593
  }
11436
11594
  }
11437
- // Runs any registered "callback hooks" that depend on the specified class type.
11438
- // This allows us to complete any work that requires dependent classes to be
11439
- // completed.
11440
- function runClassTypeHooks(type) {
11441
- classTypeHooks.forEach((hook) => {
11442
- if (types_1.ClassType.isSameGenericClass(hook.dependency, type)) {
11443
- hook.callback();
11595
+ // Records the fact that the specified class requires "deferred completion" because
11596
+ // one of its base classes has not yet been fully evaluated. If the caller passes
11597
+ // undefined for "dependsUpon", then the class is added to all outstanding deferred
11598
+ // completions.
11599
+ function registerDeferredClassCompletion(classToComplete, dependsUpon) {
11600
+ if (dependsUpon) {
11601
+ // See if there is an existing entry for this dependency.
11602
+ const entry = deferredClassCompletions.find((e) => types_1.ClassType.isSameGenericClass(e.dependsUpon, dependsUpon));
11603
+ if (entry) {
11604
+ entry.classesToComplete.push(classToComplete);
11605
+ }
11606
+ else {
11607
+ deferredClassCompletions.push({ dependsUpon, classesToComplete: [classToComplete] });
11608
+ }
11609
+ }
11610
+ else {
11611
+ deferredClassCompletions.forEach((e) => {
11612
+ e.classesToComplete.push(classToComplete);
11613
+ });
11614
+ }
11615
+ }
11616
+ // Runs any registered "deferred class completions" that depend on the specified
11617
+ // class type. This allows us to complete any work that requires dependent classes
11618
+ // to be completed.
11619
+ function runDeferredClassCompletions(type) {
11620
+ deferredClassCompletions.forEach((e) => {
11621
+ if (types_1.ClassType.isSameGenericClass(e.dependsUpon, type)) {
11622
+ e.classesToComplete.forEach((classNode) => {
11623
+ const classType = readTypeCache(classNode.name, 0 /* None */);
11624
+ if (classType) {
11625
+ completeClassTypeDeferred(classType, classNode.name);
11626
+ }
11627
+ });
11444
11628
  }
11445
11629
  });
11446
- // Remove any hooks that depend on this type.
11447
- classTypeHooks = classTypeHooks.filter((hook) => !types_1.ClassType.isSameGenericClass(hook.dependency, type));
11630
+ // Remove any completions that depend on this type.
11631
+ deferredClassCompletions = deferredClassCompletions.filter((e) => !types_1.ClassType.isSameGenericClass(e.dependsUpon, type));
11448
11632
  }
11449
11633
  // Recomputes the MRO and effective metaclass for the class after dependent
11450
11634
  // classes have been fully constructed.
11451
- function completeClassTypeDeferred(type, node, errorNode) {
11635
+ function completeClassTypeDeferred(type, errorNode) {
11452
11636
  // Recompute the MRO linearization.
11453
11637
  if (!(0, typeUtils_1.computeMroLinearization)(type)) {
11454
11638
  addError(localize_1.Localizer.Diagnostic.methodOrdering(), errorNode);
@@ -12322,9 +12506,9 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
12322
12506
  }
12323
12507
  return inferredReturnType ? { type: inferredReturnType, isIncomplete } : undefined;
12324
12508
  }
12325
- // Determines whether the function consists only of a "raise" statement
12326
- // and the exception type raised is a NotImplementedError. This is commonly
12327
- // used for abstract methods that
12509
+ // Determines whether the method consists only of a "raise" statement
12510
+ // and the exception type raised is a NotImplementedError or a subclass
12511
+ // thereof. This is commonly used for abstract methods.
12328
12512
  function methodAlwaysRaisesNotImplemented(functionDecl) {
12329
12513
  if (!functionDecl ||
12330
12514
  !functionDecl.isMethod ||
@@ -12343,7 +12527,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
12343
12527
  : (0, types_1.isClassInstance)(raiseType)
12344
12528
  ? raiseType
12345
12529
  : undefined;
12346
- if (!classType || !types_1.ClassType.isBuiltIn(classType, 'NotImplementedError')) {
12530
+ if (!classType || !(0, typeUtils_1.derivesFromStdlibClass)(classType, 'NotImplementedError')) {
12347
12531
  return false;
12348
12532
  }
12349
12533
  }
@@ -13245,18 +13429,22 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
13245
13429
  case 'Concatenate': {
13246
13430
  return { type: createConcatenateType(errorNode, classType, typeArgs) };
13247
13431
  }
13248
- case 'TypeGuard':
13249
- case 'StrictTypeGuard': {
13432
+ case 'TypeGuard': {
13250
13433
  return { type: createTypeGuardType(errorNode, classType, typeArgs, flags) };
13251
13434
  }
13252
13435
  case 'Unpack': {
13253
13436
  return { type: createUnpackType(classType, errorNode, typeArgs, flags) };
13254
13437
  }
13255
13438
  case 'Required':
13256
- case 'NotRequired':
13257
- case 'ReadOnly': {
13439
+ case 'NotRequired': {
13258
13440
  return createRequiredOrReadOnlyType(classType, errorNode, typeArgs, flags);
13259
13441
  }
13442
+ case 'ReadOnly': {
13443
+ if (AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.enableExperimentalFeatures) {
13444
+ return createRequiredOrReadOnlyType(classType, errorNode, typeArgs, flags);
13445
+ }
13446
+ break;
13447
+ }
13260
13448
  case 'Self': {
13261
13449
  return { type: createSelfType(classType, errorNode, typeArgs) };
13262
13450
  }
@@ -13273,10 +13461,17 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
13273
13461
  // Handle "type" specially, since it needs to act like "Type"
13274
13462
  // in Python 3.9 and newer.
13275
13463
  if (types_1.ClassType.isBuiltIn(classType, 'type') && typeArgs) {
13276
- // PEP 484 says that type[Any] should be considered
13277
- // equivalent to type.
13278
- if (typeArgs.length === 1 && (0, types_1.isAnyOrUnknown)(typeArgs[0].type)) {
13279
- return { type: classType };
13464
+ if (typeArgs.length >= 1) {
13465
+ // PEP 484 says that type[Any] should be considered
13466
+ // equivalent to type.
13467
+ if ((0, types_1.isAnyOrUnknown)(typeArgs[0].type)) {
13468
+ return { type: classType };
13469
+ }
13470
+ // Treat type[function] as illegal.
13471
+ if ((0, types_1.isFunction)(typeArgs[0].type) || (0, types_1.isOverloadedFunction)(typeArgs[0].type)) {
13472
+ addDiagnostic(fileInfo.diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.typeAnnotationWithCallable(), typeArgs[0].node);
13473
+ return { type: types_1.UnknownType.create() };
13474
+ }
13280
13475
  }
13281
13476
  const typeClass = getTypingType(errorNode, 'Type');
13282
13477
  if (typeClass && (0, types_1.isInstantiableClass)(typeClass)) {
@@ -13528,13 +13723,13 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
13528
13723
  // used in cases where the argument is expected to be a type
13529
13724
  // and therefore follows the normal rules of types (e.g. they
13530
13725
  // can be forward-declared in stubs, etc.).
13531
- function getTypeOfArgumentExpectingType(arg) {
13726
+ function getTypeOfArgumentExpectingType(arg, options) {
13532
13727
  if (arg.typeResult) {
13533
13728
  return { type: arg.typeResult.type, isIncomplete: arg.typeResult.isIncomplete };
13534
13729
  }
13535
13730
  // If there was no defined type provided, there should always
13536
13731
  // be a value expression from which we can retrieve the type.
13537
- return getTypeOfExpressionExpectingType(arg.valueExpression);
13732
+ return getTypeOfExpressionExpectingType(arg.valueExpression, options);
13538
13733
  }
13539
13734
  function getTypeOfExpressionExpectingType(node, options) {
13540
13735
  let flags = 128 /* ExpectingInstantiableType */ |
@@ -13565,6 +13760,9 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
13565
13760
  if (!(options === null || options === void 0 ? void 0 : options.allowParamSpec)) {
13566
13761
  flags |= 32 /* DisallowParamSpec */;
13567
13762
  }
13763
+ if (options === null || options === void 0 ? void 0 : options.enforceTypeAnnotationRules) {
13764
+ flags |= 256 /* ExpectingTypeAnnotation */;
13765
+ }
13568
13766
  return getTypeOfExpression(node, flags);
13569
13767
  }
13570
13768
  function getBuiltInType(node, name) {
@@ -13695,11 +13893,11 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
13695
13893
  // types, under the assumption that we're performing speculative evaluations.
13696
13894
  // If speculativeNode is undefined, speculative mode is not used. This is
13697
13895
  // useful in cases where we conditionally want to use speculative mode.
13698
- function useSpeculativeMode(speculativeNode, callback, dependentType) {
13896
+ function useSpeculativeMode(speculativeNode, callback, options) {
13699
13897
  if (!speculativeNode) {
13700
13898
  return callback();
13701
13899
  }
13702
- speculativeTypeTracker.enterSpeculativeContext(speculativeNode, dependentType);
13900
+ speculativeTypeTracker.enterSpeculativeContext(speculativeNode, options);
13703
13901
  try {
13704
13902
  const result = callback();
13705
13903
  speculativeTypeTracker.leaveSpeculativeContext();
@@ -15118,8 +15316,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
15118
15316
  const typeVarContext = new typeVarContext_1.TypeVarContext();
15119
15317
  let isAssignable = true;
15120
15318
  destType.details.fields.forEach((symbol, name) => {
15121
- var _a;
15122
- if (!isAssignable || !symbol.isClassMember() || symbol.isIgnoredForProtocolMatch()) {
15319
+ if (!isAssignable || symbol.isIgnoredForProtocolMatch()) {
15123
15320
  return;
15124
15321
  }
15125
15322
  // Constructor methods are exempt from variance calculations.
@@ -15128,34 +15325,42 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
15128
15325
  }
15129
15326
  const memberInfo = (0, typeUtils_1.lookUpClassMember)(srcType, name);
15130
15327
  (0, debug_1.assert)(memberInfo !== undefined);
15131
- let destMemberType = (_a = getDeclaredTypeOfSymbol(symbol)) === null || _a === void 0 ? void 0 : _a.type;
15132
- if (destMemberType) {
15133
- const srcMemberType = getTypeOfMember(memberInfo);
15134
- destMemberType = (0, typeUtils_1.partiallySpecializeType)(destMemberType, destType);
15135
- // Properties require special processing.
15136
- if ((0, types_1.isClassInstance)(destMemberType) &&
15137
- types_1.ClassType.isPropertyClass(destMemberType) &&
15138
- (0, types_1.isClassInstance)(srcMemberType) &&
15139
- types_1.ClassType.isPropertyClass(srcMemberType)) {
15140
- if (!(0, properties_1.assignProperty)(evaluatorInterface, types_1.ClassType.cloneAsInstantiable(destMemberType), types_1.ClassType.cloneAsInstantiable(srcMemberType), destType, srcType, diag, typeVarContext,
15141
- /* selfTypeVarContext */ undefined, recursionCount)) {
15142
- isAssignable = false;
15143
- }
15328
+ let destMemberType = getEffectiveTypeOfSymbol(symbol);
15329
+ const srcMemberType = getTypeOfMember(memberInfo);
15330
+ destMemberType = (0, typeUtils_1.partiallySpecializeType)(destMemberType, destType);
15331
+ // Properties require special processing.
15332
+ if ((0, types_1.isClassInstance)(destMemberType) &&
15333
+ types_1.ClassType.isPropertyClass(destMemberType) &&
15334
+ (0, types_1.isClassInstance)(srcMemberType) &&
15335
+ types_1.ClassType.isPropertyClass(srcMemberType)) {
15336
+ if (!(0, properties_1.assignProperty)(evaluatorInterface, types_1.ClassType.cloneAsInstantiable(destMemberType), types_1.ClassType.cloneAsInstantiable(srcMemberType), destType, srcType, diag, typeVarContext,
15337
+ /* selfTypeVarContext */ undefined, recursionCount)) {
15338
+ isAssignable = false;
15144
15339
  }
15145
- else {
15146
- const primaryDecl = symbol.getDeclarations()[0];
15340
+ }
15341
+ else {
15342
+ const primaryDecl = symbol.getDeclarations()[0];
15343
+ let flags = 0 /* Default */;
15344
+ if ((primaryDecl === null || primaryDecl === void 0 ? void 0 : primaryDecl.type) === 1 /* Variable */ &&
15345
+ !isFinalVariableDeclaration(primaryDecl) &&
15346
+ !types_1.ClassType.isFrozenDataClass(destType)) {
15147
15347
  // Class and instance variables that are mutable need to
15148
- // enforce invariance.
15149
- const flags = (primaryDecl === null || primaryDecl === void 0 ? void 0 : primaryDecl.type) === 1 /* Variable */ && !isFinalVariableDeclaration(primaryDecl)
15150
- ? 1 /* EnforceInvariance */
15151
- : 0 /* Default */;
15152
- if (!assignType(destMemberType, srcMemberType, diag, typeVarContext,
15153
- /* srcTypeVarContext */ undefined, flags, recursionCount)) {
15154
- isAssignable = false;
15348
+ // enforce invariance. We will exempt variables that are
15349
+ // private or protected, since these are presumably
15350
+ // not modifiable outside of the class.
15351
+ if (!(0, symbolNameUtils_1.isPrivateOrProtectedName)(name)) {
15352
+ flags |= 1 /* EnforceInvariance */;
15155
15353
  }
15156
15354
  }
15355
+ if (!assignType(destMemberType, srcMemberType, diag, typeVarContext,
15356
+ /* srcTypeVarContext */ undefined, flags, recursionCount)) {
15357
+ isAssignable = false;
15358
+ }
15157
15359
  }
15158
15360
  });
15361
+ if (!isAssignable) {
15362
+ return false;
15363
+ }
15159
15364
  // Now handle generic base classes.
15160
15365
  destType.details.baseClasses.forEach((baseClass) => {
15161
15366
  if ((0, types_1.isInstantiableClass)(baseClass) &&
@@ -15401,63 +15606,50 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
15401
15606
  srcTypeArgs = srcType.typeArguments;
15402
15607
  }
15403
15608
  let isCompatible = true;
15404
- if (srcTypeArgs) {
15405
- for (let srcArgIndex = 0; srcArgIndex < srcTypeArgs.length; srcArgIndex++) {
15406
- const srcTypeArg = srcTypeArgs[srcArgIndex];
15407
- // In most cases, the number of type args should match the number
15408
- // of type arguments, but there are a few special cases where this
15409
- // isn't true (e.g. assigning a Tuple[X, Y, Z] to a tuple[W]).
15410
- const destArgIndex = srcArgIndex >= destTypeArgs.length ? destTypeArgs.length - 1 : srcArgIndex;
15411
- const destTypeArg = destArgIndex >= 0 ? destTypeArgs[destArgIndex] : types_1.UnknownType.create();
15412
- const destTypeParam = destArgIndex < destTypeParams.length ? destTypeParams[destArgIndex] : undefined;
15413
- const assignmentDiag = new diagnostic_1.DiagnosticAddendum();
15414
- if (!destTypeParam || types_1.TypeVarType.getVariance(destTypeParam) === 3 /* Covariant */) {
15415
- if (!assignType(destTypeArg, srcTypeArg, assignmentDiag, destTypeVarContext, srcTypeVarContext, flags | 128 /* RetainLiteralsForTypeVar */, recursionCount)) {
15416
- if (diag) {
15417
- if (destTypeParam) {
15418
- const childDiag = diag.createAddendum();
15419
- childDiag.addMessage(localize_1.Localizer.DiagnosticAddendum.typeVarIsCovariant().format({
15420
- name: types_1.TypeVarType.getReadableName(destTypeParam),
15421
- }));
15422
- childDiag.addAddendum(assignmentDiag);
15423
- }
15424
- else {
15425
- diag.addAddendum(assignmentDiag);
15426
- }
15427
- }
15428
- isCompatible = false;
15429
- }
15430
- }
15431
- else if (types_1.TypeVarType.getVariance(destTypeParam) === 4 /* Contravariant */) {
15432
- if (!assignType(srcTypeArg, destTypeArg, assignmentDiag, srcTypeVarContext, destTypeVarContext, (flags ^ 2 /* ReverseTypeVarMatching */) | 128 /* RetainLiteralsForTypeVar */, recursionCount)) {
15433
- if (diag) {
15609
+ srcTypeArgs === null || srcTypeArgs === void 0 ? void 0 : srcTypeArgs.forEach((srcTypeArg, srcArgIndex) => {
15610
+ // In most cases, the number of type args should match the number
15611
+ // of type arguments, but there are a few special cases where this
15612
+ // isn't true (e.g. assigning a Tuple[X, Y, Z] to a tuple[W]).
15613
+ const destArgIndex = srcArgIndex >= destTypeArgs.length ? destTypeArgs.length - 1 : srcArgIndex;
15614
+ const destTypeArg = destArgIndex >= 0 ? destTypeArgs[destArgIndex] : types_1.UnknownType.create();
15615
+ const destTypeParam = destArgIndex < destTypeParams.length ? destTypeParams[destArgIndex] : undefined;
15616
+ const assignmentDiag = new diagnostic_1.DiagnosticAddendum();
15617
+ const variance = destTypeParam ? types_1.TypeVarType.getVariance(destTypeParam) : 3 /* Covariant */;
15618
+ let effectiveFlags;
15619
+ let errorSource;
15620
+ if (variance === 3 /* Covariant */) {
15621
+ effectiveFlags = flags | 128 /* RetainLiteralsForTypeVar */;
15622
+ errorSource = localize_1.Localizer.DiagnosticAddendum.typeVarIsCovariant;
15623
+ }
15624
+ else if (variance === 4 /* Contravariant */) {
15625
+ effectiveFlags =
15626
+ (flags ^ 2 /* ReverseTypeVarMatching */) | 128 /* RetainLiteralsForTypeVar */;
15627
+ errorSource = localize_1.Localizer.DiagnosticAddendum.typeVarIsContravariant;
15628
+ }
15629
+ else {
15630
+ effectiveFlags = flags | 1 /* EnforceInvariance */ | 128 /* RetainLiteralsForTypeVar */;
15631
+ errorSource = localize_1.Localizer.DiagnosticAddendum.typeVarIsInvariant;
15632
+ }
15633
+ if (!assignType(variance === 4 /* Contravariant */ ? srcTypeArg : destTypeArg, variance === 4 /* Contravariant */ ? destTypeArg : srcTypeArg, assignmentDiag, variance === 4 /* Contravariant */ ? srcTypeVarContext : destTypeVarContext, variance === 4 /* Contravariant */ ? destTypeVarContext : srcTypeVarContext, effectiveFlags, recursionCount)) {
15634
+ // Don't report errors with type variables in "pseudo-random"
15635
+ // classes since these type variables are not real.
15636
+ if (!types_1.ClassType.isPseudoGenericClass(destType)) {
15637
+ if (diag) {
15638
+ if (destTypeParam) {
15434
15639
  const childDiag = diag.createAddendum();
15435
- childDiag.addMessage(localize_1.Localizer.DiagnosticAddendum.typeVarIsContravariant().format({
15640
+ childDiag.addMessage(errorSource().format({
15436
15641
  name: types_1.TypeVarType.getReadableName(destTypeParam),
15642
+ ...printSrcDestTypes(srcTypeArg, destTypeArg),
15437
15643
  }));
15438
- childDiag.addAddendum(assignmentDiag);
15439
15644
  }
15440
- isCompatible = false;
15441
- }
15442
- }
15443
- else {
15444
- if (!assignType(destTypeArg, srcTypeArg, assignmentDiag, destTypeVarContext, srcTypeVarContext, flags | 1 /* EnforceInvariance */ | 128 /* RetainLiteralsForTypeVar */, recursionCount)) {
15445
- // Don't report errors with type variables in "pseudo-random"
15446
- // classes since these type variables are not real.
15447
- if (!types_1.ClassType.isPseudoGenericClass(destType)) {
15448
- if (diag) {
15449
- const childDiag = diag.createAddendum();
15450
- childDiag.addMessage(localize_1.Localizer.DiagnosticAddendum.typeVarIsInvariant().format({
15451
- name: types_1.TypeVarType.getReadableName(destTypeParam),
15452
- }));
15453
- childDiag.addAddendum(assignmentDiag);
15454
- }
15455
- isCompatible = false;
15645
+ else {
15646
+ diag.addAddendum(assignmentDiag);
15456
15647
  }
15457
15648
  }
15649
+ isCompatible = false;
15458
15650
  }
15459
15651
  }
15460
- }
15652
+ });
15461
15653
  return isCompatible;
15462
15654
  }
15463
15655
  // Determines if the source type can be assigned to the dest type.
@@ -15647,8 +15839,10 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
15647
15839
  destType.details.parameters.length <= 2) {
15648
15840
  return true;
15649
15841
  }
15650
- diag === null || diag === void 0 ? void 0 : diag.addMessage(localize_1.Localizer.DiagnosticAddendum.typeAssignmentMismatch().format(printSrcDestTypes(srcType, destType)));
15651
- return false;
15842
+ if (!(0, types_1.isUnion)(destType)) {
15843
+ diag === null || diag === void 0 ? void 0 : diag.addMessage(localize_1.Localizer.DiagnosticAddendum.typeAssignmentMismatch().format(printSrcDestTypes(srcType, destType)));
15844
+ return false;
15845
+ }
15652
15846
  }
15653
15847
  }
15654
15848
  if ((0, types_1.isAnyOrUnknown)(destType)) {
@@ -15678,25 +15872,23 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
15678
15872
  return true;
15679
15873
  }
15680
15874
  if ((0, types_1.isUnion)(destType)) {
15875
+ // If both the source and dest are unions, use assignFromUnionType which has
15876
+ // special-case logic to handle this case.
15681
15877
  if ((0, types_1.isUnion)(srcType)) {
15682
- if (assignFromUnionType(destType, srcType,
15683
- /* diag */ undefined, destTypeVarContext, srcTypeVarContext, originalFlags, recursionCount)) {
15684
- return true;
15685
- }
15878
+ return assignFromUnionType(destType, srcType,
15879
+ /* diag */ undefined, destTypeVarContext, srcTypeVarContext, originalFlags, recursionCount);
15686
15880
  }
15687
- else {
15688
- const clonedDestTypeVarContext = destTypeVarContext === null || destTypeVarContext === void 0 ? void 0 : destTypeVarContext.clone();
15689
- const clonedSrcTypeVarContext = srcTypeVarContext === null || srcTypeVarContext === void 0 ? void 0 : srcTypeVarContext.clone();
15690
- if (assignToUnionType(destType, srcType,
15691
- /* diag */ undefined, clonedDestTypeVarContext, clonedSrcTypeVarContext, originalFlags, recursionCount)) {
15692
- if (destTypeVarContext && clonedDestTypeVarContext) {
15693
- destTypeVarContext.copyFromClone(clonedDestTypeVarContext);
15694
- }
15695
- if (srcTypeVarContext && clonedSrcTypeVarContext) {
15696
- srcTypeVarContext.copyFromClone(clonedSrcTypeVarContext);
15697
- }
15698
- return true;
15881
+ const clonedDestTypeVarContext = destTypeVarContext === null || destTypeVarContext === void 0 ? void 0 : destTypeVarContext.clone();
15882
+ const clonedSrcTypeVarContext = srcTypeVarContext === null || srcTypeVarContext === void 0 ? void 0 : srcTypeVarContext.clone();
15883
+ if (assignToUnionType(destType, srcType,
15884
+ /* diag */ undefined, clonedDestTypeVarContext, clonedSrcTypeVarContext, originalFlags, recursionCount)) {
15885
+ if (destTypeVarContext && clonedDestTypeVarContext) {
15886
+ destTypeVarContext.copyFromClone(clonedDestTypeVarContext);
15699
15887
  }
15888
+ if (srcTypeVarContext && clonedSrcTypeVarContext) {
15889
+ srcTypeVarContext.copyFromClone(clonedSrcTypeVarContext);
15890
+ }
15891
+ return true;
15700
15892
  }
15701
15893
  }
15702
15894
  const expandedSrcType = makeTopLevelTypeVarsConcrete(srcType);
@@ -15795,7 +15987,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
15795
15987
  return !isLiteral;
15796
15988
  }
15797
15989
  }
15798
- else if (types_1.ClassType.isBuiltIn(destType, ['TypeGuard', 'StrictTypeGuard'])) {
15990
+ else if (types_1.ClassType.isBuiltIn(destType, 'TypeGuard')) {
15799
15991
  // All the source to be a "bool".
15800
15992
  if ((originalFlags & 64 /* AllowBoolTypeGuard */) !== 0) {
15801
15993
  if ((0, types_1.isClassInstance)(srcType) && types_1.ClassType.isBuiltIn(srcType, 'bool')) {
@@ -16047,6 +16239,9 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
16047
16239
  // whose primary type matches.
16048
16240
  remainingSrcSubtypes.forEach((srcSubtype) => {
16049
16241
  const destTypeIndex = remainingDestSubtypes.findIndex((destSubtype) => {
16242
+ if ((0, types_1.isTypeSame)(destSubtype, srcSubtype)) {
16243
+ return true;
16244
+ }
16050
16245
  if ((0, types_1.isClass)(srcSubtype) &&
16051
16246
  (0, types_1.isClass)(destSubtype) &&
16052
16247
  types_1.TypeBase.isInstance(srcSubtype) === types_1.TypeBase.isInstance(destSubtype) &&
@@ -16071,6 +16266,14 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
16071
16266
  // If there is are remaining dest subtypes and they're all type variables,
16072
16267
  // attempt to assign the remaining source subtypes to them.
16073
16268
  if (canUseFastPath && (remainingDestSubtypes.length !== 0 || remainingSrcSubtypes.length !== 0)) {
16269
+ if ((flags & 1 /* EnforceInvariance */) !== 0) {
16270
+ // If we have no src subtypes remaining but not all dest types have been subsumed
16271
+ // by other dest types, then the types are not compatible if we're enforcing invariance.
16272
+ if (remainingSrcSubtypes.length === 0) {
16273
+ return remainingDestSubtypes.every((destSubtype) => isTypeSubsumedByOtherType(destSubtype, destType.subtypes,
16274
+ /* allowAnyToSubsume */ true, recursionCount));
16275
+ }
16276
+ }
16074
16277
  const isReversed = (flags & 2 /* ReverseTypeVarMatching */) !== 0;
16075
16278
  const effectiveDestSubtypes = isReversed ? remainingSrcSubtypes : remainingDestSubtypes;
16076
16279
  if (effectiveDestSubtypes.length === 0 || effectiveDestSubtypes.some((t) => !(0, types_1.isTypeVar)(t))) {
@@ -16122,21 +16325,13 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
16122
16325
  }
16123
16326
  if (!assignType(destType, subtype,
16124
16327
  /* diag */ undefined, destTypeVarContext, srcTypeVarContext, flags, recursionCount)) {
16125
- const concreteSubtype = makeTopLevelTypeVarsConcrete(subtype);
16126
16328
  // Determine if the current subtype is subsumed by another subtype
16127
16329
  // in the same union. If so, we can ignore this.
16128
- let isSubtypeSubsumed = false;
16129
- srcType.subtypes.forEach((innerSubtype) => {
16130
- if (!isSubtypeSubsumed &&
16131
- !(0, types_1.isTypeSame)(innerSubtype, subtype) &&
16132
- !(0, types_1.isAnyOrUnknown)(innerSubtype) &&
16133
- isProperSubtype(innerSubtype, concreteSubtype, recursionCount)) {
16134
- isSubtypeSubsumed = true;
16135
- }
16136
- });
16330
+ const isSubtypeSubsumed = isTypeSubsumedByOtherType(subtype, srcType.subtypes,
16331
+ /* allowAnyToSubsume */ false, recursionCount);
16137
16332
  // Try again with a concrete version of the subtype.
16138
16333
  if (!isSubtypeSubsumed &&
16139
- !assignType(destType, concreteSubtype, diag === null || diag === void 0 ? void 0 : diag.createAddendum(), destTypeVarContext, srcTypeVarContext, flags, recursionCount)) {
16334
+ !assignType(destType, subtype, diag === null || diag === void 0 ? void 0 : diag.createAddendum(), destTypeVarContext, srcTypeVarContext, flags, recursionCount)) {
16140
16335
  isIncompatible = true;
16141
16336
  }
16142
16337
  }
@@ -16147,6 +16342,25 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
16147
16342
  }
16148
16343
  return true;
16149
16344
  }
16345
+ // Determines whether a type is "subsumed by" (i.e. is a proper subtype of) one
16346
+ // of the other types in a list.
16347
+ function isTypeSubsumedByOtherType(type, otherTypes, allowAnyToSubsume, recursionCount = 0) {
16348
+ const concreteType = makeTopLevelTypeVarsConcrete(type);
16349
+ for (const otherType of otherTypes) {
16350
+ if ((0, types_1.isTypeSame)(otherType, type)) {
16351
+ continue;
16352
+ }
16353
+ if ((0, types_1.isAnyOrUnknown)(otherType)) {
16354
+ if (allowAnyToSubsume) {
16355
+ return true;
16356
+ }
16357
+ }
16358
+ else if (isProperSubtype(otherType, concreteType, recursionCount)) {
16359
+ return true;
16360
+ }
16361
+ }
16362
+ return false;
16363
+ }
16150
16364
  // Determines whether the srcType is a subtype of destType but the converse
16151
16365
  // is not true. It's important that we check both directions to avoid
16152
16366
  // matches for types like `tuple[Any]` and `tuple[int]` from being considered
@@ -16914,7 +17128,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
16914
17128
  // Handle the special case where the return type is a TypeGuard[T].
16915
17129
  // This should also act as a bool, since that's its type at runtime.
16916
17130
  if ((0, types_1.isClassInstance)(srcReturnType) &&
16917
- types_1.ClassType.isBuiltIn(srcReturnType, ['TypeGuard', 'StrictTypeGuard']) &&
17131
+ types_1.ClassType.isBuiltIn(srcReturnType, 'TypeGuard') &&
16918
17132
  boolClassType &&
16919
17133
  (0, types_1.isInstantiableClass)(boolClassType)) {
16920
17134
  if (assignType(destReturnType, types_1.ClassType.cloneAsInstance(boolClassType), returnDiag === null || returnDiag === void 0 ? void 0 : returnDiag.createAddendum(), destTypeVarContext, srcTypeVarContext, flags, recursionCount)) {
@@ -16964,7 +17178,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
16964
17178
  const typeParam = assignedType.details.typeParameters[index];
16965
17179
  const expectedTypeArgType = typeVarContext.getPrimarySignature().getTypeVarType(typeParam);
16966
17180
  if (expectedTypeArgType) {
16967
- if ((0, types_1.isAny)(expectedTypeArgType) || (0, types_1.isAnyOrUnknown)(typeArg)) {
17181
+ if ((0, typeUtils_1.containsAnyRecursive)(expectedTypeArgType) || (0, types_1.isAnyOrUnknown)(typeArg)) {
16968
17182
  replacedTypeArg = true;
16969
17183
  return expectedTypeArgType;
16970
17184
  }
@@ -16991,12 +17205,12 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
16991
17205
  const narrowedType = (0, typeUtils_1.mapSubtypes)(assignedType, (assignedSubtype) => {
16992
17206
  const narrowedSubtype = (0, typeUtils_1.mapSubtypes)(declaredType, (declaredSubtype) => {
16993
17207
  // We can't narrow "Any".
16994
- if ((0, types_1.isAnyOrUnknown)(declaredType)) {
16995
- return declaredType;
17208
+ if ((0, types_1.isAnyOrUnknown)(declaredSubtype)) {
17209
+ return declaredSubtype;
16996
17210
  }
16997
17211
  if (assignType(declaredSubtype, assignedSubtype)) {
16998
17212
  // If the source is generic and has unspecified type arguments,
16999
- // see if we can determine then based on the declared type.
17213
+ // see if we can determine them based on the declared type.
17000
17214
  if ((0, types_1.isInstantiableClass)(declaredSubtype) && (0, types_1.isInstantiableClass)(assignedSubtype)) {
17001
17215
  const result = replaceTypeArgsWithAny(node, declaredSubtype, assignedSubtype);
17002
17216
  if (result) {
@@ -17014,6 +17228,15 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
17014
17228
  // use the concrete type.
17015
17229
  return declaredSubtype;
17016
17230
  }
17231
+ // If the assigned subtype is Any, stick with the declared type.
17232
+ if ((0, types_1.isAny)(assignedSubtype)) {
17233
+ return declaredSubtype;
17234
+ }
17235
+ // If the declared type doesn't contain any `Any` but the assigned
17236
+ // type does, stick with the declared type.
17237
+ if ((0, typeUtils_1.containsAnyRecursive)(assignedSubtype) && !(0, typeUtils_1.containsAnyRecursive)(declaredSubtype)) {
17238
+ return declaredSubtype;
17239
+ }
17017
17240
  return assignedSubtype;
17018
17241
  }
17019
17242
  return undefined;
@@ -17025,16 +17248,12 @@ function createTypeEvaluator(importLookup, evaluatorOptions) {
17025
17248
  }
17026
17249
  return narrowedSubtype;
17027
17250
  });
17028
- // If the result of narrowing is Any, stick with the declared (unnarrowed) type.
17029
17251
  // If the result of narrowing is an Unknown that is incomplete, propagate the
17030
17252
  // incomplete type for the benefit of code flow analysis.
17031
17253
  // If the result of narrowing is a complete Unknown, combine the Unknown type
17032
17254
  // with the declared type. In strict mode, this will retain the "unknown type"
17033
17255
  // diagnostics while still providing reasonable completion suggestions.
17034
- if ((0, types_1.isAny)(narrowedType)) {
17035
- return declaredType;
17036
- }
17037
- else if ((0, typeUtils_1.isIncompleteUnknown)(narrowedType)) {
17256
+ if ((0, typeUtils_1.isIncompleteUnknown)(narrowedType)) {
17038
17257
  return narrowedType;
17039
17258
  }
17040
17259
  else if ((0, types_1.isUnknown)(narrowedType)) {