Skip to content

Commit 3c59bd4

Browse files
authored
Infer array type from elements in auto context (#1021)
1 parent fc3ee10 commit 3c59bd4

File tree

5 files changed

+2353
-13
lines changed

5 files changed

+2353
-13
lines changed

src/compiler.ts

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7455,17 +7455,33 @@ export class Compiler extends DiagnosticEmitter {
74557455
switch (expression.literalKind) {
74567456
case LiteralKind.ARRAY: {
74577457
assert(!implicitlyNegate);
7458-
let classType = contextualType.classReference;
7459-
if (classType) {
7460-
if (classType.prototype == this.program.arrayPrototype) {
7461-
return this.compileArrayLiteral(
7462-
assert(classType.typeArguments)[0],
7463-
(<ArrayLiteralExpression>expression).elementExpressions,
7464-
constraints,
7465-
expression
7466-
);
7458+
let elementExpressions = (<ArrayLiteralExpression>expression).elementExpressions;
7459+
7460+
// Infer from first element in auto contexts
7461+
if (contextualType == Type.auto) {
7462+
return this.compileArrayLiteral(
7463+
Type.auto,
7464+
elementExpressions,
7465+
constraints,
7466+
expression
7467+
);
7468+
}
7469+
7470+
// Use contextual type if an array
7471+
if (contextualType.is(TypeFlags.REFERENCE)) {
7472+
let classType = contextualType.classReference;
7473+
if (classType) {
7474+
if (classType.prototype == this.program.arrayPrototype) {
7475+
return this.compileArrayLiteral(
7476+
assert(classType.typeArguments)[0],
7477+
elementExpressions,
7478+
constraints,
7479+
expression
7480+
);
7481+
}
74677482
}
74687483
}
7484+
74697485
this.error(
74707486
DiagnosticCode.The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly,
74717487
expression.range, "T"
@@ -7544,17 +7560,42 @@ export class Compiler extends DiagnosticEmitter {
75447560
var module = this.module;
75457561
var program = this.program;
75467562
var arrayPrototype = assert(program.arrayPrototype);
7547-
var arrayInstance = assert(this.resolver.resolveClass(arrayPrototype, [ elementType ]));
75487563
var arrayBufferInstance = assert(program.arrayBufferInstance);
7549-
var arrayType = arrayInstance.type;
75507564
var flow = this.currentFlow;
75517565

75527566
// block those here so compiling expressions doesn't conflict
7553-
var tempThis = flow.getTempLocal(arrayType);
7567+
var tempThis = flow.getTempLocal(this.options.usizeType);
75547568
var tempDataStart = flow.getTempLocal(arrayBufferInstance.type);
75557569

7556-
// compile value expressions and find out whether all are constant
7570+
// infer common element type in auto contexts
75577571
var length = expressions.length;
7572+
if (elementType == Type.auto) {
7573+
for (let i = 0; i < length; ++i) {
7574+
let expression = expressions[i];
7575+
if (expression) {
7576+
let currentType = this.resolver.resolveExpression(expression, this.currentFlow, elementType);
7577+
if (!currentType) return module.unreachable();
7578+
if (elementType == Type.auto) elementType = currentType;
7579+
else if (currentType != elementType) {
7580+
let commonType = Type.commonDenominator(elementType, currentType, false);
7581+
if (commonType) elementType = commonType;
7582+
// otherwise triggers error further down
7583+
}
7584+
}
7585+
}
7586+
if (elementType /* still */ == Type.auto) {
7587+
this.error(
7588+
DiagnosticCode.The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly,
7589+
reportNode.range, "T"
7590+
);
7591+
return module.unreachable();
7592+
}
7593+
}
7594+
7595+
var arrayInstance = assert(this.resolver.resolveClass(arrayPrototype, [ elementType ]));
7596+
var arrayType = arrayInstance.type;
7597+
7598+
// compile value expressions and find out whether all are constant
75587599
var values = new Array<ExpressionRef>(length);
75597600
var isStatic = true;
75607601
var nativeElementType = elementType.toNativeType();

tests/compiler/infer-array.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"asc_flags": [
3+
"--runtime none"
4+
]
5+
}

0 commit comments

Comments
 (0)