Skip to content

Commit af53c48

Browse files
authored
feat: Fall back to default type when inferring generic calls (AssemblyScript#1759)
1 parent 639d5e0 commit af53c48

File tree

6 files changed

+4127
-68
lines changed

6 files changed

+4127
-68
lines changed

src/common.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ export namespace CommonNames {
200200
export const I31ref = "I31ref";
201201
export const Dataref = "Dataref";
202202
export const String = "String";
203+
export const Object = "Object";
203204
export const Array = "Array";
204205
export const StaticArray = "StaticArray";
205206
export const Set = "Set";

src/program.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,14 @@ export class Program extends DiagnosticEmitter {
631631
}
632632
private _stringInstance: Class | null = null;
633633

634+
/** Gets the standard `Object` instance. */
635+
get objectInstance(): Class {
636+
var cached = this._objectInstance;
637+
if (!cached) this._objectInstance = cached = this.requireClass(CommonNames.Object);
638+
return cached;
639+
}
640+
private _objectInstance: Class | null = null;
641+
634642
/** Gets the standard `TemplateStringsArray` instance. */
635643
get templateStringsArrayInstance(): Class {
636644
var cached = this._templateStringsArrayInstance;

src/resolver.ts

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -770,13 +770,21 @@ export class Resolver extends DiagnosticEmitter {
770770
// apply concrete types to the generic function signature
771771
let resolvedTypeArguments = new Array<Type>(numTypeParameters);
772772
for (let i = 0; i < numTypeParameters; ++i) {
773-
let name = typeParameterNodes[i].name.text;
773+
let typeParameterNode = typeParameterNodes[i];
774+
let name = typeParameterNode.name.text;
774775
if (contextualTypeArguments.has(name)) {
775776
let inferredType = assert(contextualTypeArguments.get(name));
776777
if (inferredType != Type.auto) {
777778
resolvedTypeArguments[i] = inferredType;
778779
continue;
779780
}
781+
let defaultType = typeParameterNode.defaultType;
782+
if (defaultType) {
783+
let resolvedDefaultType = this.resolveType(defaultType, ctxFlow.actualFunction, contextualTypeArguments, reportMode);
784+
if (!resolvedDefaultType) return null;
785+
resolvedTypeArguments[i] = resolvedDefaultType;
786+
continue;
787+
}
780788
}
781789
// unused template, e.g. `function test<T>(): void {...}` called as `test()`
782790
// invalid because the type is effectively unknown inside the function body
@@ -2249,10 +2257,12 @@ export class Resolver extends DiagnosticEmitter {
22492257
if (numNullLiterals == length) { // all nulls infers as usize
22502258
elementType = this.program.options.usizeType;
22512259
} else {
2252-
this.error(
2253-
DiagnosticCode.The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly,
2254-
node.range, "T"
2255-
);
2260+
if (reportMode == ReportMode.REPORT) {
2261+
this.error(
2262+
DiagnosticCode.The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly,
2263+
node.range, "T"
2264+
);
2265+
}
22562266
return null;
22572267
}
22582268
}
@@ -2264,6 +2274,16 @@ export class Resolver extends DiagnosticEmitter {
22642274
}
22652275
return assert(this.resolveClass(this.program.arrayPrototype, [ elementType ]));
22662276
}
2277+
case LiteralKind.OBJECT: {
2278+
if (ctxType.isClass) return ctxType.classReference;
2279+
if (reportMode == ReportMode.REPORT) {
2280+
this.error(
2281+
DiagnosticCode.Expression_cannot_be_represented_by_a_type,
2282+
node.range
2283+
);
2284+
}
2285+
return null;
2286+
}
22672287
}
22682288
assert(false);
22692289
return null;

0 commit comments

Comments
 (0)