From 88fd618daafcecea91353018f063536e5b5fe290 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Fri, 13 Sep 2019 14:39:54 -0700 Subject: [PATCH] Fix crash when Nullable creation takes dynamic argument (#38647) --- .../Portable/FlowAnalysis/NullableWalker.cs | 12 ++++++----- .../Semantics/NullableReferenceTypesTests.cs | 21 +++++++++++++++++++ 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs index e3c158f0061..d64965ed60d 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs @@ -1712,6 +1712,7 @@ public override BoundNode VisitObjectCreationExpression(BoundObjectCreationExpre return null; } +#nullable enable private void VisitObjectOrDynamicObjectCreation( BoundExpression node, ImmutableArray arguments, @@ -1724,9 +1725,9 @@ public override BoundNode VisitObjectCreationExpression(BoundObjectCreationExpre var argumentTypes = argumentResults.SelectAsArray(ar => ar.RValueType); int slot = -1; - TypeSymbol type = node.Type; - NullableFlowState resultState = NullableFlowState.NotNull; - if ((object)type != null) + var type = node.Type; + var resultState = NullableFlowState.NotNull; + if (type is object) { slot = GetOrCreatePlaceholderSlot(node); if (slot > 0) @@ -1737,7 +1738,7 @@ public override BoundNode VisitObjectCreationExpression(BoundObjectCreationExpre if (EmptyStructTypeCache.IsTrackableStructType(type)) { var tupleType = constructor?.ContainingType as TupleTypeSymbol; - if ((object)tupleType != null && !isDefaultValueTypeConstructor) + if (tupleType is object && !isDefaultValueTypeConstructor) { // new System.ValueTuple(e1, ..., eN) TrackNullableStateOfTupleElements(slot, tupleType, arguments, argumentTypes, useRestField: true); @@ -1758,7 +1759,7 @@ public override BoundNode VisitObjectCreationExpression(BoundObjectCreationExpre // a nullable value type created with its default constructor is by definition null resultState = NullableFlowState.MaybeNull; } - else if (constructor.ParameterCount == 1) + else if (constructor?.ParameterCount == 1) { // if we deal with one-parameter ctor that takes underlying, then Value state is inferred from the argument. var parameterType = constructor.ParameterTypesWithAnnotations[0]; @@ -1785,6 +1786,7 @@ public override BoundNode VisitObjectCreationExpression(BoundObjectCreationExpre SetResultType(node, TypeWithState.Create(type, resultState)); } +#nullable restore private void VisitObjectCreationInitializer(Symbol containingSymbol, int containingSlot, BoundExpression node) { diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs index 5bcfd771ba3..ef78fb1d5fa 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs @@ -102676,6 +102676,27 @@ static void F() Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z.Value.F").WithLocation(20, 9)); } + [Fact, WorkItem(38575, "https://github.com/dotnet/roslyn/issues/38575")] + public void NullableCtor_Dynamic() + { + var source = @" +using System; + +class C +{ + void M() + { + var value = GetValue((dynamic)""""); + _ = new DateTime?(value); + } + + DateTime GetValue(object o) => default; +} +"; + var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); + comp.VerifyDiagnostics(); + } + [Fact] public void NullableT_AlwaysTrueOrFalse() { -- GitLab