You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Fact]
[WorkItem("https://github.com/dotnet/roslyn/issues/72750")]
[WorkItem("https://github.com/dotnet/roslyn/issues/33011")]
public void SingleCandidate_ResultIsDynamic_Property_Assignment_Deconstruction_Method_01()
{
string source = @"
#nullable enable
public class C
{
public static void Main()
{
dynamic d = 1;
var c = new C();
var a = (c[d], _) = new C2();
System.Console.Write(a);
Print(a.Item1);
System.Console.Write("" "");
System.Console.Write(c._test1);
}
int _test1 = 0;
int this[int x]
{
get => _test1;
set => _test1 = value;
}
static void Print(dynamic b)
{
}
}
class C2
{
public void Deconstruct(out int x, out int y)
{
(x, y) = (2, 123);
}
}
";
var comp = CreateCompilation(source, options: TestOptions.DebugExe, targetFramework: TargetFramework.StandardAndCSharp);
var tree = comp.SyntaxTrees.Single();
var node = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "a").First();
var model = comp.GetSemanticModel(tree);
var symbolInfo = model.GetSymbolInfo(node);
Assert.Equal("(dynamic, System.Int32) a", symbolInfo.Symbol.ToTestDisplayString());
node = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "Item1").Single();
symbolInfo = model.GetSymbolInfo(node);
Assert.Equal("dynamic (dynamic, System.Int32).Item1", symbolInfo.Symbol.ToTestDisplayString());
var typeInfo = model.GetTypeInfo(node);
AssertEx.Equal("dynamic", typeInfo.Type.ToTestDisplayString());
Assert.Equal(CodeAnalysis.NullableFlowState.NotNull, typeInfo.Nullability.FlowState);
var elementAccess = tree.GetRoot().DescendantNodes().OfType<ElementAccessExpressionSyntax>().Single();
symbolInfo = model.GetSymbolInfo(elementAccess);
AssertEx.Equal("System.Int32 C.this[System.Int32 x] { get; set; }", symbolInfo.Symbol.ToTestDisplayString());
typeInfo = model.GetTypeInfo(elementAccess);
AssertEx.Equal("System.Int32", typeInfo.Type.ToTestDisplayString());
AssertEx.Equal("System.Int32", typeInfo.ConvertedType.ToTestDisplayString());
AssertEx.Equal("dynamic", typeInfo.Type.ToTestDisplayString());
AssertEx.Equal("dynamic", typeInfo.ConvertedType.ToTestDisplayString());
var propertyRef = (IPropertyReferenceOperation)model.GetOperation(elementAccess);
AssertEx.Equal(symbolInfo.Symbol.ToTestDisplayString(), propertyRef.Property.ToTestDisplayString());
var propertyRef = (IDynamicIndexerAccessOperation)model.GetOperation(elementAccess);
Assert.Equal(typeInfo.Type, propertyRef.Type);
var left = (TupleExpressionSyntax)elementAccess.Parent.Parent;
var tupleTypeInfo = model.GetTypeInfo(left);
AssertEx.Equal("(System.Int32, System.Int32)", tupleTypeInfo.Type.ToTestDisplayString());
AssertEx.Equal("(System.Int32, System.Int32)", tupleTypeInfo.ConvertedType.ToTestDisplayString());
AssertEx.Equal("(dynamic, System.Int32)", tupleTypeInfo.Type.ToTestDisplayString());
AssertEx.Equal("(dynamic, System.Int32)", tupleTypeInfo.ConvertedType.ToTestDisplayString());
var assignment = (AssignmentExpressionSyntax)left.Parent;
typeInfo = model.GetTypeInfo(assignment);
AssertEx.Equal("(dynamic, System.Int32)", typeInfo.Type.ToTestDisplayString());
AssertEx.Equal("(dynamic, System.Int32)", typeInfo.ConvertedType.ToTestDisplayString());
Assert.True(model.GetDeconstructionInfo(assignment) is { Method: not null, Conversion: null, Nested: [{ Method: null, Conversion: { IsIdentity: true }, Nested: [] }, _] });
Assert.True(model.GetDeconstructionInfo(assignment) is { Method: not null, Conversion: null, Nested: [{ Method: null, Conversion: { IsBoxing: true }, Nested: [] }, _] });
var operation = (IDeconstructionAssignmentOperation)model.GetOperation(assignment);
Assert.Equal(tupleTypeInfo.Type, operation.Target.Type);
Assert.Equal("C2", operation.Value.Type.ToTestDisplayString());
Assert.Equal(typeInfo.Type, operation.Type);
var right = assignment.Right;
typeInfo = model.GetTypeInfo(right);
AssertEx.Equal("C2", typeInfo.Type.ToTestDisplayString());
AssertEx.Equal("C2", typeInfo.ConvertedType.ToTestDisplayString());
CompileAndVerify(comp, expectedOutput: "(2, 123) 2").VerifyDiagnostics();
CompileAndVerify(comp, expectedOutput: "(2, 123) 2").VerifyDiagnostics(
// (10,18): warning CS8624: Argument of type 'dynamic' cannot be used as an output of type 'int' for parameter 'x' in 'void C2.Deconstruct(out int x, out int y)' due to differences in the nullability of reference types.
// var a = (c[d], _) = new C2();
Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "c[d]").WithArguments("dynamic", "int", "x", "void C2.Deconstruct(out int x, out int y)").WithLocation(10, 18)
);
string source3 = @"
#nullable enable
public class C
{
public static void Main()
{
dynamic d = 1;
var c = new C();
var a = (c[d], _) = new C2();
Print(a.Item1);
}
int? _test1 = 0;
int? this[int x]
{
get => _test1;
set => _test1 = value;
}
static void Print(dynamic b)
{
}
}
class C2
{
public void Deconstruct(out int? x, out int y)
{
(x, y) = (2, 123);
}
}
";
var comp3 = CreateCompilation(source3, targetFramework: TargetFramework.StandardAndCSharp);
// Nullability is not tracked across deconstruction, this is a pre-existing condition - https://github.com/dotnet/roslyn/issues/33011
comp3.VerifyDiagnostics();
comp3.VerifyDiagnostics(
// (10,18): warning CS8624: Argument of type 'dynamic' cannot be used as an output of type 'int?' for parameter 'x' in 'void C2.Deconstruct(out int? x, out int y)' due to differences in the nullability of reference types.
// var a = (c[d], _) = new C2();
Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "c[d]").WithArguments("dynamic", "int?", "x", "void C2.Deconstruct(out int? x, out int y)").WithLocation(10, 18)
);
tree = comp3.SyntaxTrees.Single();
node = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "Item1").Single();
model = comp3.GetSemanticModel(tree);
typeInfo = model.GetTypeInfo(node);
AssertEx.Equal("dynamic", typeInfo.Type.ToTestDisplayString());
Assert.Equal(CodeAnalysis.NullableFlowState.NotNull, typeInfo.Nullability.FlowState);
}
Observed confusing warning:
// (10,18): warning CS8624: Argument of type 'dynamic' cannot be used as an output of type 'int' for parameter 'x' in 'void C2.Deconstruct(out int x, out int y)' due to differences in the nullability of reference types.
// var a = (c[d], _) = new C2();
Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgumentForOutput, "c[d]").WithArguments("dynamic", "int", "x", "void C2.Deconstruct(out int x, out int y)").WithLocation(10, 18)
The text was updated successfully, but these errors were encountered:
Observed confusing warning:
The text was updated successfully, but these errors were encountered: