Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ class NullPropagation
static void Main()
{
new NullPropagation().TestNotCoalescing();
#if CS72
new NullPropagation().TestRefStructNotCoalescing();
#endif
}

class MyClass
Expand All @@ -25,5 +28,36 @@ string NotCoalescing(MyClass c)
{
return c != null ? c.Text : "Hello";
}

#if CS72
ref struct ByRefLikeStruct
{
public int Value;
}

class RefStructHolder
{
public ByRefLikeStruct Get()
{
ByRefLikeStruct result = default(ByRefLikeStruct);
result.Value = 42;
return result;
}
}

void TestRefStructNotCoalescing()
{
Console.WriteLine("TestRefStructNotCoalescing:");
Console.WriteLine(RefStructNotCoalescing(null).Value);
Console.WriteLine(RefStructNotCoalescing(new RefStructHolder()).Value);
}

// A by-ref-like return type cannot be turned into a ?. / ?? null-propagation: a ref struct
// cannot be wrapped in Nullable<T>, so that form does not compile.
ByRefLikeStruct RefStructNotCoalescing(RefStructHolder holder)
{
return holder != null ? holder.Get() : default(ByRefLikeStruct);
}
#endif
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,14 @@ ILInstruction TryNullPropagation(ILVariable testedVar, ILInstruction nonNullInst
IntroduceUnwrap(testedVar, varLoad, mode);
return new NullableRewrap(nonNullInst);
}
else if (!removedRewrapOrNullableCtor && NullableType.IsNonNullableValueType(returnType))
else if (!removedRewrapOrNullableCtor && NullableType.IsNonNullableValueType(returnType)
&& !returnType.IsByRefLike)
{
context.Step($"Null propagation (mode={mode}, output=null coalescing)", nonNullInst);
// testedVar != null ? testedVar.AccessChain : nullInst
// => testedVar?.AccessChain ?? nullInst
// (only valid if AccessChain returns a non-nullable value)
// (only valid if AccessChain returns a non-nullable value; a by-ref-like type such as
// Span<T> is excluded because it cannot be wrapped in Nullable<T> for the ?. / ?? form)
IntroduceUnwrap(testedVar, varLoad, mode);
return new NullCoalescingInstruction(
NullCoalescingKind.NullableWithValueFallback,
Expand Down
Loading