Skip to content

Commit 6cbc181

Browse files
committed
fix: WIP: allow using nullable strings in template literals
We basically compile nullable strings down to a ternary: `expr ? expr.toString() : "null"` I didn't test or write tests for this yet; this is a WIP.
1 parent 44b658d commit 6cbc181

File tree

1 file changed

+24
-8
lines changed

1 file changed

+24
-8
lines changed

src/compiler.ts

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10145,6 +10145,7 @@ export class Compiler extends DiagnosticEmitter {
1014510145

1014610146
/** Makes a string conversion of the given expression. */
1014710147
makeToString(expr: ExpressionRef, type: Type, reportNode: Node): ExpressionRef {
10148+
let module = this.module;
1014810149
let stringType = this.program.stringInstance.type;
1014910150
if (type == stringType) {
1015010151
return expr;
@@ -10161,15 +10162,30 @@ export class Compiler extends DiagnosticEmitter {
1016110162
reportNode
1016210163
)) {
1016310164
this.currentType = stringType;
10164-
return this.module.unreachable();
10165+
return module.unreachable();
1016510166
}
1016610167
if (!type.isStrictlyAssignableTo(assert(toStringSignature.thisType))) {
10167-
this.errorRelated(
10168-
DiagnosticCode.The_this_types_of_each_signature_are_incompatible,
10169-
reportNode.range, toStringInstance.identifierAndSignatureRange
10168+
if (!type.is(TypeFlags.Nullable)) {
10169+
this.errorRelated(
10170+
DiagnosticCode.The_this_types_of_each_signature_are_incompatible,
10171+
reportNode.range, toStringInstance.identifierAndSignatureRange
10172+
);
10173+
this.currentType = stringType;
10174+
return module.unreachable();
10175+
}
10176+
10177+
// Attempt to retry on the non-nullable form of the type, wrapped in a ternary:
10178+
// `expr ? expr.toString() : "null"`
10179+
const tempLocal = this.currentFlow.getTempLocal(type);
10180+
return module.if(
10181+
module.local_tee(tempLocal.index, expr, type.isManaged),
10182+
this.makeToString(
10183+
module.local_get(tempLocal.index, type.toRef()),
10184+
type.nonNullableType,
10185+
reportNode
10186+
),
10187+
this.ensureStaticString("null")
1017010188
);
10171-
this.currentType = stringType;
10172-
return this.module.unreachable();
1017310189
}
1017410190
let toStringReturnType = toStringSignature.returnType;
1017510191
if (!toStringReturnType.isStrictlyAssignableTo(stringType)) {
@@ -10178,7 +10194,7 @@ export class Compiler extends DiagnosticEmitter {
1017810194
reportNode.range, toStringInstance.identifierAndSignatureRange, toStringReturnType.toString(), stringType.toString()
1017910195
);
1018010196
this.currentType = stringType;
10181-
return this.module.unreachable();
10197+
return module.unreachable();
1018210198
}
1018310199
return this.makeCallDirect(toStringInstance, [ expr ], reportNode);
1018410200
}
@@ -10188,7 +10204,7 @@ export class Compiler extends DiagnosticEmitter {
1018810204
reportNode.range, type.toString(), stringType.toString()
1018910205
);
1019010206
this.currentType = stringType;
10191-
return this.module.unreachable();
10207+
return module.unreachable();
1019210208
}
1019310209

1019410210
/** Makes an allocation suitable to hold the data of an instance of the given class. */

0 commit comments

Comments
 (0)