singulink / runtimenullables Goto Github PK
View Code? Open in Web Editor NEWAutomatic null check injection for runtime C# 8+ Nullable Reference Type (NRT) contract validation.
License: MIT License
Automatic null check injection for runtime C# 8+ Nullable Reference Type (NRT) contract validation.
License: MIT License
Stepping into source code of libraries that use source link and RuntimeNullables does not work.
Hey, very nice project :) it really helps out on filling the gap with nullable reference types.
There seems to be an issue with C# 9 init only properties on record types, any property setter (nullable or not) throws InvalidProgramException.
Stack trace:
System.InvalidProgramException
Common Language Runtime detected an invalid program.
at Sample.Tests.Commands.CreateDocumentCommand.set_DocumentNumber(String value)
at Sample.Tests.CreateDocumentCommandTests.Should_fail_create_command_when_duplicate_found() in D:\Dev\dotnet\Projects\nrttests\test\Sample.Tests\CreateDocumentCommandTests.cs:line 246
Unhandled exception. System.NullReferenceException: Task result nullability contract was broken.
at RuntimeNullables.ThrowHelpers.ThrowOutputNull(String message)
at FodyTest.Program.DoSomethingAsync() in /home/andrii/development/FodyTest/FodyTest/Program.cs:line 17
at FodyTest.Program.Main(String[] args) in /home/andrii/development/FodyTest/FodyTest/Program.cs:line 9
at FodyTest.Program.<Main>(String[] args)
Minimal reproducible example:
using System.Threading.Tasks;
namespace FodyTest
{
class Program
{
static Task Main(string[] args)
{
return DoSomethingAsync();
}
static Task<bool> DoSomethingAsync()
{
// Returning False throws the exception
// Returning True works fine
return Task.FromResult(false);
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<WeaverConfiguration>
<Weavers>
<RuntimeNullables CheckOutputs="true" CheckNonPublic="true" />
</Weavers>
</WeaverConfiguration>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="RuntimeNullables.Fody" Version="0.9.3" />
</ItemGroup>
</Project>
Unhandled exception. System.InvalidProgramException: Common Language Runtime detected an invalid program.
at FodyTest.Program.DoSomethingAsync()
at FodyTest.Program.Main(String[] args) in /home/andrii/development/FodyTest/FodyTest/Program.cs:line 9
at FodyTest.Program.<Main>(String[] args)
using System.Threading.Tasks;
namespace FodyTest
{
class Program
{
static Task Main(string[] args)
{
return DoSomethingAsync();
}
// Works fine with reference types (e.g. string)
// But throws the exception with value types (e.g. bool)
static Task<bool?> DoSomethingAsync()
{
return Task.FromResult((bool?) null);
}
}
}
Hi! I've got an issue with the package along with ValueTask<T>
return types.
If nullable checks are enabled, and you have a method with return type ValueTask<anything>
(with anything not nullable), executing that method crashes the process with an Fatal error. Internal CLR error. (0x80131506)
message.
How to reproduce (xunit test):
using RuntimeNullables;
using Xunit;
namespace ValueTaskIssue;
public class TestedClass
{
[NullChecks(true)]
public ValueTask<string> TestedMethod1()
{
return new ValueTask<string>("");
}
[NullChecks(false)]
public ValueTask<string> TestedMethod2()
{
return new ValueTask<string>("");
}
}
public class UnitTest1
{
private readonly TestedClass _testedClass = new TestedClass();
// this fails with: Fatal error. Internal CLR error. (0x80131506)
[Fact]
public async Task Test1()
{
var value = await _testedClass.TestedMethod1();
Assert.Empty(value);
}
// this works:
[Fact]
public async Task Test2()
{
var value = await _testedClass.TestedMethod2();
Assert.Empty(value);
}
}
I'm not super sure, but I suppose it could be related to the weaver trying to add nullable checks to the value of the ValueTask
I encountered a weird issue when using RuntimeNullables: apparently it does not generate null checks for primitive arrays (e.g. byte[]
) as can be seen in the example below.
Is this expected behavior?
Source code:
namespace Namespace
{
public class NullabilityTest
{
private readonly string _s;
private readonly string[] _stringArray;
private readonly byte[] _byteArray;
private readonly int _i;
public NullabilityTest (string s, string[] stringArray, byte[] byteArray, int i)
{
_s = s;
_stringArray = stringArray;
_byteArray = byteArray;
_i = i;
}
}
}
IL:
.method public hidebysig specialname rtspecialname instance void
.ctor(
string s,
string[] stringArray,
unsigned int8[] byteArray,
int32 i
) cil managed
{
.maxstack 2
// [10 5 - 10 85]
IL_0000: ldarg.1 // s
IL_0001: brtrue.s IL_000d
IL_0003: ldstr "s"
IL_0008: call void RuntimeNullables.ThrowHelpers::ThrowArgumentNull(string)
IL_000d: ldarg.2 // stringArray
IL_000e: brtrue.s IL_001a
IL_0010: ldstr "stringArray"
IL_0015: call void RuntimeNullables.ThrowHelpers::ThrowArgumentNull(string)
IL_001a: ldarg.0 // this
IL_001b: call instance void [mscorlib]System.Object::.ctor()
IL_0020: nop
// [11 5 - 11 6]
IL_0021: nop
// [12 7 - 12 14]
IL_0022: ldarg.0 // this
IL_0023: ldarg.1 // s
IL_0024: stfld string SignPath.Application.Domain.Common.NullabilityTest::_s
// [13 7 - 13 34]
IL_0029: ldarg.0 // this
IL_002a: ldarg.2 // stringArray
IL_002b: stfld string[] SignPath.Application.Domain.Common.NullabilityTest::_stringArray
// [14 7 - 14 30]
IL_0030: ldarg.0 // this
IL_0031: ldarg.3 // byteArray
IL_0032: stfld unsigned int8[] SignPath.Application.Domain.Common.NullabilityTest::_byteArray
// [15 7 - 15 14]
IL_0037: ldarg.0 // this
IL_0038: ldarg.s i
IL_003a: stfld int32 SignPath.Application.Domain.Common.NullabilityTest::_i
// [16 5 - 16 6]
IL_003f: ret
} // end of method NullabilityTest::.ctor
First of all thank you very much for a great library!
Here is a case:
RuntimeNullables
package[Post]
public IActionResult Auth(AuthRequest request)
{
//logic
}
public record AuthRequest(string Something);
{ "Something": null }
Something
cannot be null), but had to return 400 (Bad Request). So, as you see this is kind of a bug actually.Of course we can add [NullChecks(false)]
attribute to the request class and the bug will disappear, but what if we forget to do that? Again 500? And it's actually not so convenient to add NullChecks
to requests explicitly all times.
I suggest to add an ability to automatically skip null checking for requests DTO in ASP.NET Core. Let's discuss an implementation here.
PS. It's interesting that NullGuard.Fody
just crashed my app at all when I sent an incorrect request like in the example, but RuntimeNullables
only throws an exception and generates 500 (and also customizable). So, I fully migrated from NullGuard.Fody
to RuntimeNullables
. Thanks again for your work!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.