@@ -8135,24 +8135,91 @@ export function createTypeEvaluator(
81358135 } else {
81368136 // Package up all of the positionals into a tuple.
81378137 const tupleTypeArgs: TupleTypeArg[] = [];
8138- positionalArgs.forEach((arg) => {
8139- const typeResult = getTypeOfExpression(arg.d.valueExpr);
8140- tupleTypeArgs.push({ type: typeResult.type, isUnbounded: false });
8141- if (typeResult.isIncomplete) {
8142- isPositionalIndexTypeIncomplete = true;
8138+
8139+ const getDeterministicTupleEntries = (type: Type): TupleTypeArg[] | undefined => {
8140+ let aggregatedArgs: TupleTypeArg[] | undefined;
8141+ let isDeterministic = true;
8142+
8143+ doForEachSubtype(type, (subtype) => {
8144+ if (!isDeterministic) {
8145+ return;
8146+ }
8147+
8148+ const tupleType = getSpecializedTupleType(subtype);
8149+ const tupleTypeArgs = tupleType?.priv.tupleTypeArgs;
8150+
8151+ if (
8152+ !tupleTypeArgs ||
8153+ tupleTypeArgs.some((entry) => entry.isUnbounded || isTypeVarTuple(entry.type))
8154+ ) {
8155+ isDeterministic = false;
8156+ return;
8157+ }
8158+
8159+ if (!aggregatedArgs) {
8160+ aggregatedArgs = tupleTypeArgs.map((entry) => ({ type: entry.type, isUnbounded: false }));
8161+ return;
8162+ }
8163+
8164+ if (aggregatedArgs.length !== tupleTypeArgs.length) {
8165+ isDeterministic = false;
8166+ return;
8167+ }
8168+
8169+ for (let i = 0; i < aggregatedArgs.length; i++) {
8170+ aggregatedArgs[i] = {
8171+ type: combineTypes([aggregatedArgs[i].type, tupleTypeArgs[i].type]),
8172+ isUnbounded: false,
8173+ };
8174+ }
8175+ });
8176+
8177+ if (!isDeterministic || !aggregatedArgs) {
8178+ return undefined;
81438179 }
8144- });
81458180
8146- unpackedListArgs.forEach((arg) => {
8147- const typeResult = getTypeOfExpression(arg.d.valueExpr);
8148- if (typeResult.isIncomplete) {
8149- isPositionalIndexTypeIncomplete = true;
8181+ return aggregatedArgs;
8182+ };
8183+
8184+ node.d.items.forEach((arg) => {
8185+ if (arg.d.argCategory === ArgCategory.Simple) {
8186+ const typeResult = getTypeOfExpression(arg.d.valueExpr);
8187+ tupleTypeArgs.push({ type: typeResult.type, isUnbounded: false });
8188+ if (typeResult.isIncomplete) {
8189+ isPositionalIndexTypeIncomplete = true;
8190+ }
8191+ return;
8192+ }
8193+
8194+ if (arg.d.argCategory === ArgCategory.UnpackedList) {
8195+ const typeResult = getTypeOfExpression(arg.d.valueExpr);
8196+ if (typeResult.isIncomplete) {
8197+ isPositionalIndexTypeIncomplete = true;
8198+ }
8199+
8200+ const deterministicEntries = getDeterministicTupleEntries(typeResult.type);
8201+ if (deterministicEntries) {
8202+ appendArray(tupleTypeArgs, deterministicEntries);
8203+ return;
8204+ }
8205+
8206+ const iterableType =
8207+ getTypeOfIterator(typeResult, /* isAsync */ false, arg.d.valueExpr)?.type ??
8208+ UnknownType.create();
8209+ tupleTypeArgs.push({ type: iterableType, isUnbounded: true });
81508210 }
8151- const iterableType =
8152- getTypeOfIterator(typeResult, /* isAsync */ false, arg.d.valueExpr)?.type ?? UnknownType.create();
8153- tupleTypeArgs.push({ type: iterableType, isUnbounded: true });
81548211 });
81558212
8213+ const unboundedCount = tupleTypeArgs.filter((typeArg) => typeArg.isUnbounded).length;
8214+ if (unboundedCount > 1) {
8215+ const firstUnboundedIndex = tupleTypeArgs.findIndex((typeArg) => typeArg.isUnbounded);
8216+ const removedEntries = tupleTypeArgs.splice(firstUnboundedIndex);
8217+ tupleTypeArgs.push({
8218+ type: combineTypes(removedEntries.map((entry) => entry.type)),
8219+ isUnbounded: true,
8220+ });
8221+ }
8222+
81568223 positionalIndexType = makeTupleObject(evaluatorInterface, tupleTypeArgs);
81578224 }
81588225
0 commit comments