Skip to content

Commit 451dd4d

Browse files
authored
Print better errors for unusual void, null and undefined types (#1303)
1 parent 47e42b5 commit 451dd4d

8 files changed

+75
-49
lines changed

src/diagnosticMessages.generated.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export enum DiagnosticCode {
2020
Conversion_from_type_0_to_1_will_require_an_explicit_cast_when_switching_between_32_64_bit = 201,
2121
Type_0_cannot_be_changed_to_type_1 = 202,
2222
Operation_0_cannot_be_applied_to_type_1 = 203,
23-
Basic_type_0_cannot_be_nullable = 204,
23+
Type_0_cannot_be_nullable = 204,
2424
Cannot_export_a_mutable_global = 205,
2525
Mutable_value_cannot_be_inlined = 206,
2626
Unmanaged_classes_cannot_extend_managed_classes_and_vice_versa = 207,
@@ -193,7 +193,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
193193
case 201: return "Conversion from type '{0}' to '{1}' will require an explicit cast when switching between 32/64-bit.";
194194
case 202: return "Type '{0}' cannot be changed to type '{1}'.";
195195
case 203: return "Operation '{0}' cannot be applied to type '{1}'.";
196-
case 204: return "Basic type '{0}' cannot be nullable.";
196+
case 204: return "Type '{0}' cannot be nullable.";
197197
case 205: return "Cannot export a mutable global.";
198198
case 206: return "Mutable value cannot be inlined.";
199199
case 207: return "Unmanaged classes cannot extend managed classes and vice-versa.";

src/diagnosticMessages.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"Conversion from type '{0}' to '{1}' will require an explicit cast when switching between 32/64-bit.": 201,
1414
"Type '{0}' cannot be changed to type '{1}'.": 202,
1515
"Operation '{0}' cannot be applied to type '{1}'.": 203,
16-
"Basic type '{0}' cannot be nullable.": 204,
16+
"Type '{0}' cannot be nullable.": 204,
1717
"Cannot export a mutable global.": 205,
1818
"Mutable value cannot be inlined.": 206,
1919
"Unmanaged classes cannot extend managed classes and vice-versa.": 207,

src/parser.ts

+29-18
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,11 @@ export class Parser extends DiagnosticEmitter {
155155
var statements = source.statements;
156156
while (!tn.skip(Token.ENDOFFILE)) {
157157
let statement = this.parseTopLevelStatement(tn, null);
158-
if (statement) statements.push(statement);
158+
if (statement) {
159+
statements.push(statement);
160+
} else {
161+
this.skipStatement(tn);
162+
}
159163
}
160164
}
161165

@@ -538,6 +542,12 @@ export class Parser extends DiagnosticEmitter {
538542
Node.createSimpleTypeName("bool", tn.range()), [], false, tn.range(startPos, tn.pos)
539543
);
540544

545+
// 'null'
546+
} else if (token == Token.NULL) {
547+
type = Node.createNamedType(
548+
Node.createSimpleTypeName("null", tn.range()), [], false, tn.range(startPos, tn.pos)
549+
);
550+
541551
// StringLiteral
542552
} else if (token == Token.STRINGLITERAL) {
543553
tn.readString();
@@ -550,7 +560,6 @@ export class Parser extends DiagnosticEmitter {
550560
let name = this.parseTypeName(tn);
551561
if (!name) return null;
552562
let parameters: TypeNode[] | null = null;
553-
let nullable = false;
554563

555564
// Name<T>
556565
if (tn.skip(Token.LESSTHAN)) {
@@ -570,31 +579,33 @@ export class Parser extends DiagnosticEmitter {
570579
return null;
571580
}
572581
}
573-
// ... | null
574-
while (tn.skip(Token.BAR)) {
575-
if (tn.skip(Token.NULL)) {
576-
nullable = true;
577-
} else {
578-
if (!suppressErrors) {
579-
this.error(
580-
DiagnosticCode._0_expected,
581-
tn.range(tn.pos), "null"
582-
);
583-
}
584-
return null;
585-
}
586-
}
587582
if (!parameters) parameters = [];
588-
type = Node.createNamedType(name, parameters, nullable, tn.range(startPos, tn.pos));
583+
type = Node.createNamedType(name, parameters, false, tn.range(startPos, tn.pos));
589584
} else {
590585
if (!suppressErrors) {
591586
this.error(
592-
DiagnosticCode.Identifier_expected,
587+
DiagnosticCode.Type_expected,
593588
tn.range()
594589
);
595590
}
596591
return null;
597592
}
593+
// ... | null
594+
while (tn.skip(Token.BAR)) {
595+
if (tn.skip(Token.NULL)) {
596+
type.isNullable = true;
597+
} else {
598+
let notNullStart = tn.pos;
599+
let notNull = this.parseType(tn, false, true);
600+
if (!suppressErrors) {
601+
this.error(
602+
DiagnosticCode._0_expected,
603+
notNull ? notNull.range : tn.range(notNullStart), "null"
604+
);
605+
}
606+
return null;
607+
}
608+
}
598609
// ... [][]
599610
while (tn.skip(Token.OPENBRACKET)) {
600611
let bracketStart = tn.tokenPos;

src/resolver.ts

+22-4
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ export class Resolver extends DiagnosticEmitter {
205205
if (type.is(TypeFlags.REFERENCE)) return type.asNullable();
206206
if (reportMode == ReportMode.REPORT) {
207207
this.error(
208-
DiagnosticCode.Basic_type_0_cannot_be_nullable,
208+
DiagnosticCode.Type_0_cannot_be_nullable,
209209
node.range, type.toString()
210210
);
211211
}
@@ -238,7 +238,7 @@ export class Resolver extends DiagnosticEmitter {
238238
if (node.isNullable) {
239239
if (reportMode == ReportMode.REPORT) {
240240
this.error(
241-
DiagnosticCode.Basic_type_0_cannot_be_nullable,
241+
DiagnosticCode.Type_0_cannot_be_nullable,
242242
node.range, element.name + "/i32"
243243
);
244244
}
@@ -283,7 +283,7 @@ export class Resolver extends DiagnosticEmitter {
283283
if (!type.is(TypeFlags.REFERENCE)) {
284284
if (reportMode == ReportMode.REPORT) {
285285
this.error(
286-
DiagnosticCode.Basic_type_0_cannot_be_nullable,
286+
DiagnosticCode.Type_0_cannot_be_nullable,
287287
nameNode.range, nameNode.identifier.text
288288
);
289289
}
@@ -333,7 +333,7 @@ export class Resolver extends DiagnosticEmitter {
333333
if (!type.is(TypeFlags.REFERENCE)) {
334334
if (reportMode == ReportMode.REPORT) {
335335
this.error(
336-
DiagnosticCode.Basic_type_0_cannot_be_nullable,
336+
DiagnosticCode.Type_0_cannot_be_nullable,
337337
nameNode.range, nameNode.identifier.text
338338
);
339339
}
@@ -2716,6 +2716,15 @@ export class Resolver extends DiagnosticEmitter {
27162716
reportMode
27172717
);
27182718
if (!parameterType) return null;
2719+
if (parameterType == Type.void) {
2720+
if (reportMode == ReportMode.REPORT) {
2721+
this.error(
2722+
DiagnosticCode.Type_expected,
2723+
typeNode.range
2724+
);
2725+
}
2726+
return null;
2727+
}
27192728
parameterTypes[i] = parameterType;
27202729
parameterNames[i] = parameterDeclaration.name.text;
27212730
}
@@ -3078,6 +3087,15 @@ export class Resolver extends DiagnosticEmitter {
30783087
instance.contextualTypeArguments,
30793088
reportMode
30803089
);
3090+
if (fieldType == Type.void) {
3091+
if (reportMode == ReportMode.REPORT) {
3092+
this.error(
3093+
DiagnosticCode.Type_expected,
3094+
fieldTypeNode.range
3095+
);
3096+
}
3097+
break;
3098+
}
30813099
}
30823100
if (!fieldType) break; // did report above
30833101
let fieldInstance = new Field(fieldPrototype, instance, fieldType);

std/assembly/builtins.ts

+20-18
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
type auto = i32;
2+
13
// @ts-ignore: decorator
24
@builtin
35
export declare function isInteger<T>(value?: T): bool;
@@ -40,11 +42,11 @@ export declare function isNullable<T>(value?: T): bool;
4042

4143
// @ts-ignore: decorator
4244
@builtin
43-
export declare function isDefined(expression: void): bool;
45+
export declare function isDefined(expression: auto): bool;
4446

4547
// @ts-ignore: decorator
4648
@builtin
47-
export declare function isConstant(expression: void): bool;
49+
export declare function isConstant(expression: auto): bool;
4850

4951
// @ts-ignore: decorator
5052
@builtin
@@ -124,7 +126,7 @@ export declare function load<T>(ptr: usize, immOffset?: usize, immAlign?: usize)
124126

125127
// @ts-ignore: decorator
126128
@unsafe @builtin
127-
export declare function store<T>(ptr: usize, value: void, immOffset?: usize, immAlign?: usize): void;
129+
export declare function store<T>(ptr: usize, value: auto, immOffset?: usize, immAlign?: usize): void;
128130

129131
// @ts-ignore: decorator
130132
@builtin
@@ -156,7 +158,7 @@ export declare function unreachable(): void;
156158

157159
// @ts-ignore: decorator
158160
@builtin
159-
export declare function changetype<T>(value: void): T;
161+
export declare function changetype<T>(value: auto): T;
160162

161163
// @ts-ignore: decorator
162164
@builtin
@@ -168,7 +170,7 @@ export declare function unchecked<T>(expr: T): T;
168170

169171
// @ts-ignore: decorator
170172
@builtin
171-
export declare function instantiate<T>(...args: void[]): T;
173+
export declare function instantiate<T>(...args: auto[]): T;
172174

173175
export namespace atomic {
174176
// @ts-ignore: decorator
@@ -230,7 +232,7 @@ export const enum AtomicWaitResult {
230232

231233
// @ts-ignore: decorator
232234
@builtin
233-
export declare function i8(value: void): i8;
235+
export declare function i8(value: auto): i8;
234236

235237
export namespace i8 {
236238

@@ -245,7 +247,7 @@ export namespace i8 {
245247

246248
// @ts-ignore: decorator
247249
@builtin
248-
export declare function i16(value: void): i16;
250+
export declare function i16(value: auto): i16;
249251

250252
export namespace i16 {
251253

@@ -260,7 +262,7 @@ export namespace i16 {
260262

261263
// @ts-ignore: decorator
262264
@builtin
263-
export declare function i32(value: void): i32;
265+
export declare function i32(value: auto): i32;
264266

265267
export namespace i32 {
266268

@@ -455,7 +457,7 @@ export namespace i32 {
455457

456458
// @ts-ignore: decorator
457459
@builtin
458-
export declare function i64(value: void): i64;
460+
export declare function i64(value: auto): i64;
459461

460462
export namespace i64 {
461463

@@ -701,7 +703,7 @@ export namespace i64 {
701703

702704
// @ts-ignore: decorator
703705
@builtin
704-
export declare function isize(value: void): isize;
706+
export declare function isize(value: auto): isize;
705707

706708
export namespace isize {
707709

@@ -720,7 +722,7 @@ export namespace isize {
720722

721723
// @ts-ignore: decorator
722724
@builtin
723-
export declare function u8(value: void): u8;
725+
export declare function u8(value: auto): u8;
724726

725727
export namespace u8 {
726728

@@ -735,7 +737,7 @@ export namespace u8 {
735737

736738
// @ts-ignore: decorator
737739
@builtin
738-
export declare function u16(value: void): u16;
740+
export declare function u16(value: auto): u16;
739741

740742
export namespace u16 {
741743

@@ -750,7 +752,7 @@ export namespace u16 {
750752

751753
// @ts-ignore: decorator
752754
@builtin
753-
export declare function u32(value: void): u32;
755+
export declare function u32(value: auto): u32;
754756

755757
export namespace u32 {
756758

@@ -765,7 +767,7 @@ export namespace u32 {
765767

766768
// @ts-ignore: decorator
767769
@builtin
768-
export declare function u64(value: void): u64;
770+
export declare function u64(value: auto): u64;
769771

770772
export namespace u64 {
771773

@@ -780,7 +782,7 @@ export namespace u64 {
780782

781783
// @ts-ignore: decorator
782784
@builtin
783-
export declare function usize(value: void): usize;
785+
export declare function usize(value: auto): usize;
784786

785787
export namespace usize {
786788

@@ -797,7 +799,7 @@ export namespace usize {
797799

798800
// @ts-ignore: decorator
799801
@builtin
800-
export declare function bool(value: void): bool;
802+
export declare function bool(value: auto): bool;
801803

802804
export namespace bool {
803805

@@ -812,7 +814,7 @@ export namespace bool {
812814

813815
// @ts-ignore: decorator
814816
@builtin
815-
export declare function f32(value: void): f32;
817+
export declare function f32(value: auto): f32;
816818

817819
export namespace f32 {
818820

@@ -891,7 +893,7 @@ export namespace f32 {
891893

892894
// @ts-ignore: decorator
893895
@builtin
894-
export declare function f64(value: void): f64;
896+
export declare function f64(value: auto): f64;
895897

896898
export namespace f64 {
897899

tests/compiler/basic-nullable.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"--runtime none"
44
],
55
"stderr": [
6-
"AS204: Basic type 'i32' cannot be nullable.",
6+
"AS204: Type 'i32' cannot be nullable.",
77
"EOF"
88
]
99
}

tests/parser/continue-on-error.ts.fixture.ts

-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
;
2-
a;
3-
from;
4-
"./other";
51
do {
62
;
73
} while (false);

tests/parser/regexp.ts.fixture.ts

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
/(abc)\//;
33
var re = /(abc)\//ig;
44
var noRe = !/(abc)\//i;
5-
b / ig;
65
/(abc)\//iig;
76
/(abc)\//iX;
87
false && /abc/gX.test(someString) || true;

0 commit comments

Comments
 (0)