Skip to content

Commit a1ae921

Browse files
committed
[cs] Emit null-forgiving operator.
Fixes: warning CS8604: Possible null reference argument for parameter
1 parent b1ab32c commit a1ae921

6 files changed

Lines changed: 70 additions & 29 deletions

File tree

‎GenCs.fu‎

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,16 @@ public class GenCs : GenTyped
462462
}
463463
}
464464

465+
void WriteNotNullArgument!(FuExpr expr)
466+
{
467+
if (expr.Type.Nullable) {
468+
expr.Accept(this, FuPriority.Primary);
469+
WriteChar('!');
470+
}
471+
else
472+
expr.Accept(this, FuPriority.Argument);
473+
}
474+
465475
void WriteJsonElementIs!(FuExpr obj, string name, FuPriority parent)
466476
{
467477
if (parent > FuPriority.Equality)
@@ -548,7 +558,7 @@ public class GenCs : GenTyped
548558
case FuId.DoubleTryParse:
549559
WriteType(obj.Type, false);
550560
Write(".TryParse(");
551-
args[0].Accept(this, FuPriority.Argument);
561+
WriteNotNullArgument(args[0]);
552562
if (args.Count == 2) {
553563
if (!(args[1] is FuLiteralLong radix) || radix.Value != 16)
554564
NotSupported(args[1], "Radix");
@@ -570,7 +580,7 @@ public class GenCs : GenTyped
570580
case FuId.ArrayBinarySearchPart:
571581
Include("System");
572582
Write("Array.BinarySearch(");
573-
obj.Accept(this, FuPriority.Argument);
583+
WriteNotNullArgument(obj);
574584
Write(", ");
575585
if (args.Count == 3) {
576586
args[1].Accept(this, FuPriority.Argument);
@@ -588,7 +598,7 @@ public class GenCs : GenTyped
588598
case FuId.ArrayCopyTo:
589599
Include("System");
590600
Write("Array.Copy(");
591-
obj.Accept(this, FuPriority.Argument);
601+
WriteNotNullArgument(obj);
592602
Write(", ");
593603
WriteCoercedArgs(method, args);
594604
WriteChar(')');
@@ -598,7 +608,7 @@ public class GenCs : GenTyped
598608
Include("System");
599609
if (args[0] is FuLiteral literal && literal.IsDefaultValue()) {
600610
Write("Array.Clear(");
601-
obj.Accept(this, FuPriority.Argument);
611+
WriteNotNullArgument(obj);
602612
if (args.Count == 1) {
603613
// .NET Framework compatibility
604614
Write(", 0, ");
@@ -607,7 +617,7 @@ public class GenCs : GenTyped
607617
}
608618
else {
609619
Write("Array.Fill(");
610-
obj.Accept(this, FuPriority.Argument);
620+
WriteNotNullArgument(obj);
611621
Write(", ");
612622
WriteNotPromoted(obj.Type.AsClassType().GetElementType(), args[0]);
613623
}
@@ -716,7 +726,7 @@ public class GenCs : GenTyped
716726
case FuId.UTF8GetBytesCopy:
717727
Include("System.Text");
718728
Write("Encoding.UTF8.GetBytes(");
719-
args[0].Accept(this, FuPriority.Argument);
729+
WriteNotNullArgument(args[0]);
720730
Write(", 0, ");
721731
WritePostfix(args[0], ".Length, "); // FIXME: side effect
722732
args[1].Accept(this, FuPriority.Argument);
@@ -775,7 +785,7 @@ public class GenCs : GenTyped
775785
break;
776786
case FuId.JsonElementParse:
777787
Write("JsonDocument.Parse(");
778-
args[0].Accept(this, FuPriority.Argument);
788+
WriteNotNullArgument(args[0]);
779789
Write(").RootElement");
780790
break;
781791
case FuId.JsonElementIsObject:

‎libfut.cpp‎

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18591,6 +18591,16 @@ void GenCs::visitSymbolReference(const FuSymbolReference * expr, FuPriority pare
1859118591
}
1859218592
}
1859318593

18594+
void GenCs::writeNotNullArgument(const FuExpr * expr)
18595+
{
18596+
if (expr->type->nullable) {
18597+
expr->accept(this, FuPriority::primary);
18598+
writeChar('!');
18599+
}
18600+
else
18601+
expr->accept(this, FuPriority::argument);
18602+
}
18603+
1859418604
void GenCs::writeJsonElementIs(const FuExpr * obj, std::string_view name, FuPriority parent)
1859518605
{
1859618606
if (parent > FuPriority::equality)
@@ -18677,7 +18687,7 @@ void GenCs::writeCallExpr(const FuType * type, const FuExpr * obj, const FuMetho
1867718687
case FuId::doubleTryParse:
1867818688
writeType(obj->type.get(), false);
1867918689
write(".TryParse(");
18680-
(*args)[0]->accept(this, FuPriority::argument);
18690+
writeNotNullArgument((*args)[0].get());
1868118691
if (std::ssize(*args) == 2) {
1868218692
const FuLiteralLong * radix;
1868318693
if (!(radix = dynamic_cast<const FuLiteralLong *>((*args)[1].get())) || radix->value != 16)
@@ -18700,7 +18710,7 @@ void GenCs::writeCallExpr(const FuType * type, const FuExpr * obj, const FuMetho
1870018710
case FuId::arrayBinarySearchPart:
1870118711
include("System");
1870218712
write("Array.BinarySearch(");
18703-
obj->accept(this, FuPriority::argument);
18713+
writeNotNullArgument(obj);
1870418714
write(", ");
1870518715
if (std::ssize(*args) == 3) {
1870618716
(*args)[1]->accept(this, FuPriority::argument);
@@ -18718,7 +18728,7 @@ void GenCs::writeCallExpr(const FuType * type, const FuExpr * obj, const FuMetho
1871818728
case FuId::arrayCopyTo:
1871918729
include("System");
1872018730
write("Array.Copy(");
18721-
obj->accept(this, FuPriority::argument);
18731+
writeNotNullArgument(obj);
1872218732
write(", ");
1872318733
writeCoercedArgs(method, args);
1872418734
writeChar(')');
@@ -18730,15 +18740,15 @@ void GenCs::writeCallExpr(const FuType * type, const FuExpr * obj, const FuMetho
1873018740
const FuLiteral * literal;
1873118741
if ((literal = dynamic_cast<const FuLiteral *>((*args)[0].get())) && literal->isDefaultValue()) {
1873218742
write("Array.Clear(");
18733-
obj->accept(this, FuPriority::argument);
18743+
writeNotNullArgument(obj);
1873418744
if (std::ssize(*args) == 1) {
1873518745
write(", 0, ");
1873618746
writeArrayStorageLength(obj, FuPriority::argument);
1873718747
}
1873818748
}
1873918749
else {
1874018750
write("Array.Fill(");
18741-
obj->accept(this, FuPriority::argument);
18751+
writeNotNullArgument(obj);
1874218752
write(", ");
1874318753
writeNotPromoted(obj->type->asClassType()->getElementType().get(), (*args)[0].get());
1874418754
}
@@ -18851,7 +18861,7 @@ void GenCs::writeCallExpr(const FuType * type, const FuExpr * obj, const FuMetho
1885118861
case FuId::uTF8GetBytesCopy:
1885218862
include("System.Text");
1885318863
write("Encoding.UTF8.GetBytes(");
18854-
(*args)[0]->accept(this, FuPriority::argument);
18864+
writeNotNullArgument((*args)[0].get());
1885518865
write(", 0, ");
1885618866
writePostfix((*args)[0].get(), ".Length, ");
1885718867
(*args)[1]->accept(this, FuPriority::argument);
@@ -18910,7 +18920,7 @@ void GenCs::writeCallExpr(const FuType * type, const FuExpr * obj, const FuMetho
1891018920
break;
1891118921
case FuId::jsonElementParse:
1891218922
write("JsonDocument.Parse(");
18913-
(*args)[0]->accept(this, FuPriority::argument);
18923+
writeNotNullArgument((*args)[0].get());
1891418924
write(").RootElement");
1891518925
break;
1891618926
case FuId::jsonElementIsObject:

‎libfut.cs‎

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18162,6 +18162,16 @@ internal override void VisitSymbolReference(FuSymbolReference expr, FuPriority p
1816218162
}
1816318163
}
1816418164

18165+
void WriteNotNullArgument(FuExpr expr)
18166+
{
18167+
if (expr.Type!.Nullable) {
18168+
expr.Accept(this, FuPriority.Primary);
18169+
WriteChar('!');
18170+
}
18171+
else
18172+
expr.Accept(this, FuPriority.Argument);
18173+
}
18174+
1816518175
void WriteJsonElementIs(FuExpr obj, string name, FuPriority parent)
1816618176
{
1816718177
if (parent > FuPriority.Equality)
@@ -18248,7 +18258,7 @@ protected override void WriteCallExpr(FuType type, FuExpr? obj, FuMethod method,
1824818258
case FuId.DoubleTryParse:
1824918259
WriteType(obj!.Type!, false);
1825018260
Write(".TryParse(");
18251-
args[0].Accept(this, FuPriority.Argument);
18261+
WriteNotNullArgument(args[0]);
1825218262
if (args.Count == 2) {
1825318263
if (!(args[1] is FuLiteralLong radix) || radix.Value != 16)
1825418264
NotSupported(args[1], "Radix");
@@ -18270,7 +18280,7 @@ protected override void WriteCallExpr(FuType type, FuExpr? obj, FuMethod method,
1827018280
case FuId.ArrayBinarySearchPart:
1827118281
Include("System");
1827218282
Write("Array.BinarySearch(");
18273-
obj!.Accept(this, FuPriority.Argument);
18283+
WriteNotNullArgument(obj!);
1827418284
Write(", ");
1827518285
if (args.Count == 3) {
1827618286
args[1].Accept(this, FuPriority.Argument);
@@ -18288,7 +18298,7 @@ protected override void WriteCallExpr(FuType type, FuExpr? obj, FuMethod method,
1828818298
case FuId.ArrayCopyTo:
1828918299
Include("System");
1829018300
Write("Array.Copy(");
18291-
obj!.Accept(this, FuPriority.Argument);
18301+
WriteNotNullArgument(obj!);
1829218302
Write(", ");
1829318303
WriteCoercedArgs(method, args);
1829418304
WriteChar(')');
@@ -18298,15 +18308,15 @@ protected override void WriteCallExpr(FuType type, FuExpr? obj, FuMethod method,
1829818308
Include("System");
1829918309
if (args[0] is FuLiteral literal && literal.IsDefaultValue()) {
1830018310
Write("Array.Clear(");
18301-
obj!.Accept(this, FuPriority.Argument);
18311+
WriteNotNullArgument(obj!);
1830218312
if (args.Count == 1) {
1830318313
Write(", 0, ");
1830418314
WriteArrayStorageLength(obj!, FuPriority.Argument);
1830518315
}
1830618316
}
1830718317
else {
1830818318
Write("Array.Fill(");
18309-
obj!.Accept(this, FuPriority.Argument);
18319+
WriteNotNullArgument(obj!);
1831018320
Write(", ");
1831118321
WriteNotPromoted(obj!.Type!.AsClassType().GetElementType(), args[0]);
1831218322
}
@@ -18415,7 +18425,7 @@ protected override void WriteCallExpr(FuType type, FuExpr? obj, FuMethod method,
1841518425
case FuId.UTF8GetBytesCopy:
1841618426
Include("System.Text");
1841718427
Write("Encoding.UTF8.GetBytes(");
18418-
args[0].Accept(this, FuPriority.Argument);
18428+
WriteNotNullArgument(args[0]);
1841918429
Write(", 0, ");
1842018430
WritePostfix(args[0], ".Length, ");
1842118431
args[1].Accept(this, FuPriority.Argument);
@@ -18474,7 +18484,7 @@ protected override void WriteCallExpr(FuType type, FuExpr? obj, FuMethod method,
1847418484
break;
1847518485
case FuId.JsonElementParse:
1847618486
Write("JsonDocument.Parse(");
18477-
args[0].Accept(this, FuPriority.Argument);
18487+
WriteNotNullArgument(args[0]);
1847818488
Write(").RootElement");
1847918489
break;
1848018490
case FuId.JsonElementIsObject:

‎libfut.hpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3294,6 +3294,7 @@ class GenCs : public GenTyped
32943294
void writeVisibility(FuVisibility visibility);
32953295
void writeCallType(FuCallType callType, std::string_view sealedString);
32963296
void writeElementType(const FuType * elementType);
3297+
void writeNotNullArgument(const FuExpr * expr);
32973298
void writeJsonElementIs(const FuExpr * obj, std::string_view name, FuPriority parent);
32983299
void writeLib();
32993300
void writeResources(const std::map<std::string, std::vector<uint8_t>> * resources);

‎libfut.js‎

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18844,6 +18844,16 @@ export class GenCs extends GenTyped
1884418844
}
1884518845
}
1884618846

18847+
#writeNotNullArgument(expr)
18848+
{
18849+
if (expr.type.nullable) {
18850+
expr.accept(this, FuPriority.PRIMARY);
18851+
this.writeChar(33);
18852+
}
18853+
else
18854+
expr.accept(this, FuPriority.ARGUMENT);
18855+
}
18856+
1884718857
#writeJsonElementIs(obj, name, parent)
1884818858
{
1884918859
if (parent > FuPriority.EQUALITY)
@@ -18930,7 +18940,7 @@ export class GenCs extends GenTyped
1893018940
case FuId.DOUBLE_TRY_PARSE:
1893118941
this.writeType(obj.type, false);
1893218942
this.write(".TryParse(");
18933-
args[0].accept(this, FuPriority.ARGUMENT);
18943+
this.#writeNotNullArgument(args[0]);
1893418944
if (args.length == 2) {
1893518945
let radix;
1893618946
if (!((radix = args[1]) instanceof FuLiteralLong) || radix.value != 16)
@@ -18953,7 +18963,7 @@ export class GenCs extends GenTyped
1895318963
case FuId.ARRAY_BINARY_SEARCH_PART:
1895418964
this.include("System");
1895518965
this.write("Array.BinarySearch(");
18956-
obj.accept(this, FuPriority.ARGUMENT);
18966+
this.#writeNotNullArgument(obj);
1895718967
this.write(", ");
1895818968
if (args.length == 3) {
1895918969
args[1].accept(this, FuPriority.ARGUMENT);
@@ -18971,7 +18981,7 @@ export class GenCs extends GenTyped
1897118981
case FuId.ARRAY_COPY_TO:
1897218982
this.include("System");
1897318983
this.write("Array.Copy(");
18974-
obj.accept(this, FuPriority.ARGUMENT);
18984+
this.#writeNotNullArgument(obj);
1897518985
this.write(", ");
1897618986
this.writeCoercedArgs(method, args);
1897718987
this.writeChar(41);
@@ -18982,15 +18992,15 @@ export class GenCs extends GenTyped
1898218992
let literal;
1898318993
if ((literal = args[0]) instanceof FuLiteral && literal.isDefaultValue()) {
1898418994
this.write("Array.Clear(");
18985-
obj.accept(this, FuPriority.ARGUMENT);
18995+
this.#writeNotNullArgument(obj);
1898618996
if (args.length == 1) {
1898718997
this.write(", 0, ");
1898818998
this.writeArrayStorageLength(obj, FuPriority.ARGUMENT);
1898918999
}
1899019000
}
1899119001
else {
1899219002
this.write("Array.Fill(");
18993-
obj.accept(this, FuPriority.ARGUMENT);
19003+
this.#writeNotNullArgument(obj);
1899419004
this.write(", ");
1899519005
this.writeNotPromoted(obj.type.asClassType().getElementType(), args[0]);
1899619006
}
@@ -19100,7 +19110,7 @@ export class GenCs extends GenTyped
1910019110
case FuId.U_T_F8_GET_BYTES_COPY:
1910119111
this.include("System.Text");
1910219112
this.write("Encoding.UTF8.GetBytes(");
19103-
args[0].accept(this, FuPriority.ARGUMENT);
19113+
this.#writeNotNullArgument(args[0]);
1910419114
this.write(", 0, ");
1910519115
this.writePostfix(args[0], ".Length, ");
1910619116
args[1].accept(this, FuPriority.ARGUMENT);
@@ -19159,7 +19169,7 @@ export class GenCs extends GenTyped
1915919169
break;
1916019170
case FuId.JSON_ELEMENT_PARSE:
1916119171
this.write("JsonDocument.Parse(");
19162-
args[0].accept(this, FuPriority.ARGUMENT);
19172+
this.#writeNotNullArgument(args[0]);
1916319173
this.write(").RootElement");
1916419174
break;
1916519175
case FuId.JSON_ELEMENT_IS_OBJECT:

‎test/ArrayFill.fu‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
public static class Test
22
{
3-
public static void FillInts(int[]! a, int value, int startIndex, nint count)
3+
public static void FillInts(int[]!? a, int value, int startIndex, nint count)
44
{
55
a.Fill(value, startIndex, count);
66
}

0 commit comments

Comments
 (0)