Skip to content

Print better errors for unusual void, null and undefined types #1303

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/diagnosticMessages.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export enum DiagnosticCode {
Conversion_from_type_0_to_1_will_require_an_explicit_cast_when_switching_between_32_64_bit = 201,
Type_0_cannot_be_changed_to_type_1 = 202,
Operation_0_cannot_be_applied_to_type_1 = 203,
Basic_type_0_cannot_be_nullable = 204,
Type_0_cannot_be_nullable = 204,
Cannot_export_a_mutable_global = 205,
Mutable_value_cannot_be_inlined = 206,
Unmanaged_classes_cannot_extend_managed_classes_and_vice_versa = 207,
Expand Down Expand Up @@ -193,7 +193,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
case 201: return "Conversion from type '{0}' to '{1}' will require an explicit cast when switching between 32/64-bit.";
case 202: return "Type '{0}' cannot be changed to type '{1}'.";
case 203: return "Operation '{0}' cannot be applied to type '{1}'.";
case 204: return "Basic type '{0}' cannot be nullable.";
case 204: return "Type '{0}' cannot be nullable.";
case 205: return "Cannot export a mutable global.";
case 206: return "Mutable value cannot be inlined.";
case 207: return "Unmanaged classes cannot extend managed classes and vice-versa.";
Expand Down
2 changes: 1 addition & 1 deletion src/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"Conversion from type '{0}' to '{1}' will require an explicit cast when switching between 32/64-bit.": 201,
"Type '{0}' cannot be changed to type '{1}'.": 202,
"Operation '{0}' cannot be applied to type '{1}'.": 203,
"Basic type '{0}' cannot be nullable.": 204,
"Type '{0}' cannot be nullable.": 204,
"Cannot export a mutable global.": 205,
"Mutable value cannot be inlined.": 206,
"Unmanaged classes cannot extend managed classes and vice-versa.": 207,
Expand Down
47 changes: 29 additions & 18 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,11 @@ export class Parser extends DiagnosticEmitter {
var statements = source.statements;
while (!tn.skip(Token.ENDOFFILE)) {
let statement = this.parseTopLevelStatement(tn, null);
if (statement) statements.push(statement);
if (statement) {
statements.push(statement);
} else {
this.skipStatement(tn);
}
}
}

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

// 'null'
} else if (token == Token.NULL) {
type = Node.createNamedType(
Node.createSimpleTypeName("null", tn.range()), [], false, tn.range(startPos, tn.pos)
);

// StringLiteral
} else if (token == Token.STRINGLITERAL) {
tn.readString();
Expand All @@ -550,7 +560,6 @@ export class Parser extends DiagnosticEmitter {
let name = this.parseTypeName(tn);
if (!name) return null;
let parameters: TypeNode[] | null = null;
let nullable = false;

// Name<T>
if (tn.skip(Token.LESSTHAN)) {
Expand All @@ -570,31 +579,33 @@ export class Parser extends DiagnosticEmitter {
return null;
}
}
// ... | null
while (tn.skip(Token.BAR)) {
if (tn.skip(Token.NULL)) {
nullable = true;
} else {
if (!suppressErrors) {
this.error(
DiagnosticCode._0_expected,
tn.range(tn.pos), "null"
);
}
return null;
}
}
if (!parameters) parameters = [];
type = Node.createNamedType(name, parameters, nullable, tn.range(startPos, tn.pos));
type = Node.createNamedType(name, parameters, false, tn.range(startPos, tn.pos));
} else {
if (!suppressErrors) {
this.error(
DiagnosticCode.Identifier_expected,
DiagnosticCode.Type_expected,
tn.range()
);
}
return null;
}
// ... | null
while (tn.skip(Token.BAR)) {
if (tn.skip(Token.NULL)) {
type.isNullable = true;
} else {
let notNullStart = tn.pos;
let notNull = this.parseType(tn, false, true);
if (!suppressErrors) {
this.error(
DiagnosticCode._0_expected,
notNull ? notNull.range : tn.range(notNullStart), "null"
);
}
return null;
}
}
// ... [][]
while (tn.skip(Token.OPENBRACKET)) {
let bracketStart = tn.tokenPos;
Expand Down
26 changes: 22 additions & 4 deletions src/resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ export class Resolver extends DiagnosticEmitter {
if (type.is(TypeFlags.REFERENCE)) return type.asNullable();
if (reportMode == ReportMode.REPORT) {
this.error(
DiagnosticCode.Basic_type_0_cannot_be_nullable,
DiagnosticCode.Type_0_cannot_be_nullable,
node.range, type.toString()
);
}
Expand Down Expand Up @@ -238,7 +238,7 @@ export class Resolver extends DiagnosticEmitter {
if (node.isNullable) {
if (reportMode == ReportMode.REPORT) {
this.error(
DiagnosticCode.Basic_type_0_cannot_be_nullable,
DiagnosticCode.Type_0_cannot_be_nullable,
node.range, element.name + "/i32"
);
}
Expand Down Expand Up @@ -283,7 +283,7 @@ export class Resolver extends DiagnosticEmitter {
if (!type.is(TypeFlags.REFERENCE)) {
if (reportMode == ReportMode.REPORT) {
this.error(
DiagnosticCode.Basic_type_0_cannot_be_nullable,
DiagnosticCode.Type_0_cannot_be_nullable,
nameNode.range, nameNode.identifier.text
);
}
Expand Down Expand Up @@ -333,7 +333,7 @@ export class Resolver extends DiagnosticEmitter {
if (!type.is(TypeFlags.REFERENCE)) {
if (reportMode == ReportMode.REPORT) {
this.error(
DiagnosticCode.Basic_type_0_cannot_be_nullable,
DiagnosticCode.Type_0_cannot_be_nullable,
nameNode.range, nameNode.identifier.text
);
}
Expand Down Expand Up @@ -2716,6 +2716,15 @@ export class Resolver extends DiagnosticEmitter {
reportMode
);
if (!parameterType) return null;
if (parameterType == Type.void) {
if (reportMode == ReportMode.REPORT) {
this.error(
DiagnosticCode.Type_expected,
typeNode.range
);
}
return null;
}
parameterTypes[i] = parameterType;
parameterNames[i] = parameterDeclaration.name.text;
}
Expand Down Expand Up @@ -3078,6 +3087,15 @@ export class Resolver extends DiagnosticEmitter {
instance.contextualTypeArguments,
reportMode
);
if (fieldType == Type.void) {
if (reportMode == ReportMode.REPORT) {
this.error(
DiagnosticCode.Type_expected,
fieldTypeNode.range
);
}
break;
}
}
if (!fieldType) break; // did report above
let fieldInstance = new Field(fieldPrototype, instance, fieldType);
Expand Down
38 changes: 20 additions & 18 deletions std/assembly/builtins.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
type auto = i32;

// @ts-ignore: decorator
@builtin
export declare function isInteger<T>(value?: T): bool;
Expand Down Expand Up @@ -40,11 +42,11 @@ export declare function isNullable<T>(value?: T): bool;

// @ts-ignore: decorator
@builtin
export declare function isDefined(expression: void): bool;
export declare function isDefined(expression: auto): bool;

// @ts-ignore: decorator
@builtin
export declare function isConstant(expression: void): bool;
export declare function isConstant(expression: auto): bool;

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

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

// @ts-ignore: decorator
@builtin
Expand Down Expand Up @@ -156,7 +158,7 @@ export declare function unreachable(): void;

// @ts-ignore: decorator
@builtin
export declare function changetype<T>(value: void): T;
export declare function changetype<T>(value: auto): T;

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

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

export namespace atomic {
// @ts-ignore: decorator
Expand Down Expand Up @@ -230,7 +232,7 @@ export const enum AtomicWaitResult {

// @ts-ignore: decorator
@builtin
export declare function i8(value: void): i8;
export declare function i8(value: auto): i8;

export namespace i8 {

Expand All @@ -245,7 +247,7 @@ export namespace i8 {

// @ts-ignore: decorator
@builtin
export declare function i16(value: void): i16;
export declare function i16(value: auto): i16;

export namespace i16 {

Expand All @@ -260,7 +262,7 @@ export namespace i16 {

// @ts-ignore: decorator
@builtin
export declare function i32(value: void): i32;
export declare function i32(value: auto): i32;

export namespace i32 {

Expand Down Expand Up @@ -455,7 +457,7 @@ export namespace i32 {

// @ts-ignore: decorator
@builtin
export declare function i64(value: void): i64;
export declare function i64(value: auto): i64;

export namespace i64 {

Expand Down Expand Up @@ -701,7 +703,7 @@ export namespace i64 {

// @ts-ignore: decorator
@builtin
export declare function isize(value: void): isize;
export declare function isize(value: auto): isize;

export namespace isize {

Expand All @@ -720,7 +722,7 @@ export namespace isize {

// @ts-ignore: decorator
@builtin
export declare function u8(value: void): u8;
export declare function u8(value: auto): u8;

export namespace u8 {

Expand All @@ -735,7 +737,7 @@ export namespace u8 {

// @ts-ignore: decorator
@builtin
export declare function u16(value: void): u16;
export declare function u16(value: auto): u16;

export namespace u16 {

Expand All @@ -750,7 +752,7 @@ export namespace u16 {

// @ts-ignore: decorator
@builtin
export declare function u32(value: void): u32;
export declare function u32(value: auto): u32;

export namespace u32 {

Expand All @@ -765,7 +767,7 @@ export namespace u32 {

// @ts-ignore: decorator
@builtin
export declare function u64(value: void): u64;
export declare function u64(value: auto): u64;

export namespace u64 {

Expand All @@ -780,7 +782,7 @@ export namespace u64 {

// @ts-ignore: decorator
@builtin
export declare function usize(value: void): usize;
export declare function usize(value: auto): usize;

export namespace usize {

Expand All @@ -797,7 +799,7 @@ export namespace usize {

// @ts-ignore: decorator
@builtin
export declare function bool(value: void): bool;
export declare function bool(value: auto): bool;

export namespace bool {

Expand All @@ -812,7 +814,7 @@ export namespace bool {

// @ts-ignore: decorator
@builtin
export declare function f32(value: void): f32;
export declare function f32(value: auto): f32;

export namespace f32 {

Expand Down Expand Up @@ -891,7 +893,7 @@ export namespace f32 {

// @ts-ignore: decorator
@builtin
export declare function f64(value: void): f64;
export declare function f64(value: auto): f64;

export namespace f64 {

Expand Down
2 changes: 1 addition & 1 deletion tests/compiler/basic-nullable.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"--runtime none"
],
"stderr": [
"AS204: Basic type 'i32' cannot be nullable.",
"AS204: Type 'i32' cannot be nullable.",
"EOF"
]
}
4 changes: 0 additions & 4 deletions tests/parser/continue-on-error.ts.fixture.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
;
a;
from;
"./other";
do {
;
} while (false);
Expand Down
1 change: 0 additions & 1 deletion tests/parser/regexp.ts.fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
/(abc)\//;
var re = /(abc)\//ig;
var noRe = !/(abc)\//i;
b / ig;
/(abc)\//iig;
/(abc)\//iX;
false && /abc/gX.test(someString) || true;
Expand Down