diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
index fd61f68cd2ae926e490918147f3dd5bf3f207878..0d48f18d0d45e9189c46468592e5ad6d886e6297 100644
--- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
+++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
@@ -130,6 +130,14 @@ private TypeWithState ResultType
}
}
+ ///
+ /// Force the inference of the LValueResultType from ResultType.
+ ///
+ private void UseRvalueOnly()
+ {
+ ResultType = ResultType;
+ }
+
private TypeSymbolWithAnnotations LvalueResultType
{
get => _visitResult.LValueType;
@@ -139,6 +147,14 @@ private TypeSymbolWithAnnotations LvalueResultType
}
}
+ ///
+ /// Force the inference of the ResultType from LValueResultType.
+ ///
+ private void UseLvalueOnly()
+ {
+ LvalueResultType = LvalueResultType;
+ }
+
private void SetResult(TypeWithState resultType, TypeSymbolWithAnnotations lvalueType)
{
_visitResult = new VisitResult(resultType, lvalueType);
@@ -455,7 +471,7 @@ private Symbol GetBackingFieldIfStructProperty(Symbol symbol)
protected override int GetOrCreateSlot(Symbol symbol, int containingSlot = 0)
{
symbol = GetBackingFieldIfStructProperty(symbol);
- if ((object)symbol == null)
+ if (symbol is null)
{
return -1;
}
@@ -605,7 +621,7 @@ protected override void VisitRvalue(BoundExpression node)
{
Visit(node);
Unsplit();
- ResultType = ResultType; // drop lvalue part
+ UseRvalueOnly(); // drop lvalue part
}
private TypeWithState VisitRvalueWithState(BoundExpression node)
@@ -1434,7 +1450,7 @@ private int GetOrCreateObjectCreationPlaceholderSlot(BoundExpression node)
_placeholderLocalsOpt.TryGetValue(node, out placeholder);
}
- if ((object)placeholder == null)
+ if (placeholder is null)
{
placeholder = new ObjectCreationPlaceholderLocal(_symbol, node);
_placeholderLocalsOpt.Add(node, placeholder);
@@ -2632,7 +2648,7 @@ private VisitResult VisitArgumentEvaluate(ImmutableArray argume
{
Visit(argument);
// No Unsplit
- ResultType = ResultType; // force use of flow result
+ UseRvalueOnly(); // force use of flow result
}
else
{
@@ -2645,7 +2661,7 @@ private VisitResult VisitArgumentEvaluate(ImmutableArray argume
Visit(argument);
// We'll want to use the l-value type, rather than the result type, for method re-inference
- LvalueResultType = LvalueResultType;
+ UseLvalueOnly();
break;
}
@@ -3241,7 +3257,7 @@ private static Symbol AsMemberOfType(TypeSymbol type, Symbol symbol)
Debug.Assert((object)symbol != null);
var containingType = type as NamedTypeSymbol;
- if ((object)containingType == null || containingType.IsErrorType() || symbol is ErrorMethodSymbol)
+ if (containingType is null || containingType.IsErrorType() || symbol is ErrorMethodSymbol)
{
return symbol;
}
@@ -3281,7 +3297,7 @@ private static Symbol AsMemberOfType(TypeSymbol type, Symbol symbol)
return result;
}
containingType = containingType.BaseTypeNoUseSiteDiagnostics;
- if ((object)containingType == null)
+ if (containingType is null)
{
break;
}
@@ -3430,7 +3446,7 @@ private void VisitTupleExpression(BoundTupleExpression node)
{
var arguments = node.Arguments;
ImmutableArray elementTypes = arguments.SelectAsArray((a, w) => w.VisitRvalueWithState(a), this);
- ImmutableArray elementTypesWithAnnotations = elementTypes.SelectAsArray((a, w) => a.ToTypeSymbolWithAnnotations(), this);
+ ImmutableArray elementTypesWithAnnotations = elementTypes.SelectAsArray(a => a.ToTypeSymbolWithAnnotations());
var tupleOpt = (TupleTypeSymbol)node.Type;
if (tupleOpt is null)
{
@@ -4401,7 +4417,7 @@ public override BoundNode VisitIncrementOperator(BoundIncrementOperator node)
}
TypeWithState resultOfIncrementType;
- if ((object)incrementOperator == null)
+ if (incrementOperator is null)
{
resultOfIncrementType = resultOfOperandConversionType;
}
@@ -4918,7 +4934,7 @@ protected override void AfterLeftChildOfBinaryLogicalOperatorHasBeenVisited(Boun
throw ExceptionUtilities.UnexpectedValue(node.Kind);
}
- Debug.Assert((object)trueFalseOperator == null || ((object)logicalOperator != null && left != null));
+ Debug.Assert(trueFalseOperator is null || ((object)logicalOperator != null && left != null));
if ((object)trueFalseOperator != null)
{
@@ -4961,7 +4977,7 @@ public override BoundNode VisitAwaitExpression(BoundAwaitExpression node)
{
var result = base.VisitAwaitExpression(node);
CheckPossibleNullReceiver(node.Expression);
- if (node.Type.IsValueType || node.HasErrors || (object)node.AwaitableInfo.GetResult == null)
+ if (node.Type.IsValueType || node.HasErrors || node.AwaitableInfo.GetResult is null)
{
SetNotNullResult(node);
}
@@ -5058,28 +5074,13 @@ public override BoundNode VisitAsOperator(BoundAsOperator node)
if (type.CanContainNull())
{
- var operandType = argumentType;
switch (node.Conversion.Kind)
{
case ConversionKind.Identity:
- // Inherit nullability from the operand
- resultState = operandType.State;
- break;
-
case ConversionKind.ImplicitReference:
- // Inherit nullability from the operand
- resultState = operandType.State;
- break;
-
case ConversionKind.Boxing:
- // Inherit nullability from the operand
- resultState = operandType.State;
- break;
-
case ConversionKind.ImplicitNullable:
- // conversion of a value of type `X` to the type `Nullable`
- // conversion of a value of type `int?` to the type `long?`
- resultState = operandType.State;
+ resultState = argumentType.State;
break;
default:
@@ -5114,7 +5115,7 @@ public override BoundNode VisitArgList(BoundArgList node)
public override BoundNode VisitArgListOperator(BoundArgListOperator node)
{
VisitArgumentsEvaluate(node.Arguments, node.ArgumentRefKindsOpt);
- Debug.Assert((object)node.Type == null);
+ Debug.Assert(node.Type is null);
SetNotNullResult(node);
return null;
}
@@ -5293,7 +5294,7 @@ private void SetUnknownResultNullability()
public override BoundNode VisitStackAllocArrayCreation(BoundStackAllocArrayCreation node)
{
var result = base.VisitStackAllocArrayCreation(node);
- Debug.Assert((object)node.Type == null || node.Type.IsPointerType() || node.Type.IsRefLikeType);
+ Debug.Assert(node.Type is null || node.Type.IsPointerType() || node.Type.IsRefLikeType);
SetNotNullResult(node);
return result;
}
@@ -5313,8 +5314,7 @@ public override BoundNode VisitDynamicIndexerAccess(BoundDynamicIndexerAccess no
NullableAnnotation nullableAnnotation = (object)node.Type != null && !node.Type.IsValueType ?
InferResultNullabilityFromApplicableCandidates(StaticCast.From(node.ApplicableIndexers)) :
NullableAnnotation.Unknown;
- var result = TypeSymbolWithAnnotations.Create(node.Type, nullableAnnotation);
- LvalueResultType = result;
+ LvalueResultType = TypeSymbolWithAnnotations.Create(node.Type, nullableAnnotation);
return null;
}
@@ -5323,18 +5323,18 @@ private void CheckPossibleNullReceiver(BoundExpression receiverOpt, bool checkNu
Debug.Assert(!this.IsConditionalState);
if (receiverOpt != null && this.State.Reachable)
{
- var resultType = ResultType.Type;
- if (resultType is null)
+ var resultTypeSymbol = ResultType.Type;
+ if (resultTypeSymbol is null)
{
return;
}
#if DEBUG
- Debug.Assert(receiverOpt.Type is null || AreCloseEnough(receiverOpt.Type, resultType));
+ Debug.Assert(receiverOpt.Type is null || AreCloseEnough(receiverOpt.Type, resultTypeSymbol));
#endif
if (ResultType.MaybeNull)
{
- bool isValueType = resultType.IsValueType;
- if (isValueType && (!checkNullableValueType || !resultType.IsNullableTypeOrTypeParameter() || resultType.GetNullableUnderlyingType().IsErrorType()))
+ bool isValueType = resultTypeSymbol.IsValueType;
+ if (isValueType && (!checkNullableValueType || !resultTypeSymbol.IsNullableTypeOrTypeParameter() || resultTypeSymbol.GetNullableUnderlyingType().IsErrorType()))
{
return;
}
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
index 9468a3ab72a256021289514937b89ece509f5cbe..0dee767e9823008933dbd6a7edef6b9ca273be17 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
@@ -38351,6 +38351,9 @@ static void F1(T1 t1)
}";
var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue());
comp.VerifyDiagnostics(
+ // (5,9): warning CS8653: A default expression introduces a null value when 'T1' is a non-nullable reference type.
+ // default(T1).ToString(); // 1
+ Diagnostic(ErrorCode.WRN_DefaultExpressionMayIntroduceNullT, "default(T1)").WithArguments("T1").WithLocation(5, 9),
// (5,9): warning CS8602: Possible dereference of a null reference.
// default(T1).ToString(); // 1
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "default(T1)").WithLocation(5, 9),
@@ -65919,7 +65922,7 @@ class Outer
void M0(T x0, T y0)
{
if (y0 == null) return;
- (x0 ?? y0)?.ToString();
+ (x0 ?? y0).ToString();
}
}
";
@@ -77949,8 +77952,9 @@ public void BestType_DifferentTupleNullability_10()
comp.VerifyTypes();
}
- [Fact(Skip = "https://github.com/dotnet/roslyn/issues/33344")]
+ [Fact]
[WorkItem(32575, "https://github.com/dotnet/roslyn/issues/32575")]
+ [WorkItem(33344, "https://github.com/dotnet/roslyn/issues/33344")]
public void BestType_DifferentTupleNullability_11()
{
var source =
@@ -77959,23 +77963,19 @@ public void BestType_DifferentTupleNullability_11()
static void F(T t, U u)
where U : class
{
- var x = new[] { (t, u), default }[0]/*T:(T t, U? u)*/;
+ var x = new[] { (t, u), default }[0]/*T:(T t, U u)*/; // should be (T t, U? u)
x.Item1.ToString(); // 1
x.Item2.ToString(); // 2
- var y = new[] { default, (t, u) }[0]/*T:(T t, U? u)*/;
+ var y = new[] { default, (t, u) }[0]/*T:(T t, U u)*/; // should be (T t, U? u)
y.Item1.ToString(); // 3
y.Item2.ToString(); // 4
}
}";
var comp = CreateCompilation(source, options: WithNonNullTypesTrue());
- // https://github.com/dotnet/roslyn/issues/32575: Not handling default for U.
comp.VerifyDiagnostics(
- // (7,9): warning CS8602: Possible dereference of a null reference.
- // x.Item1.ToString(); // 1
- Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x.Item1").WithLocation(7, 9),
- // (10,9): warning CS8602: Possible dereference of a null reference.
- // y.Item1.ToString(); // 3
- Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y.Item1").WithLocation(10, 9));
+ // https://github.com/dotnet/roslyn/issues/32575: Not handling default for U.
+ // SHOULD BE 4 diagnostics.
+ );
comp.VerifyTypes();
}