Skip to content

Commit

Permalink
Merge pull request #21553 from cston/21518-dev15.3.x
Browse files Browse the repository at this point in the history
Use default tuple fields in conversion since fields from inferred names are marked not usable in C#7
  • Loading branch information
agocke authored Aug 19, 2017
2 parents aca31f6 + 8026894 commit b735460
Show file tree
Hide file tree
Showing 6 changed files with 321 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -649,16 +649,8 @@ private BoundExpression RewriteTupleConversion(

for (int i = 0; i < numElements; i++)
{
var field = srcElementFields[i];

DiagnosticInfo useSiteInfo = field.GetUseSiteDiagnostic();
if ((object)useSiteInfo != null && useSiteInfo.Severity == DiagnosticSeverity.Error)
{
Symbol.ReportUseSiteDiagnostic(useSiteInfo, _diagnostics, syntax.Location);
}
var fieldAccess = MakeTupleFieldAccess(syntax, field, savedTuple, null, LookupResultKind.Empty);
var fieldAccess = MakeTupleFieldAccessAndReportUseSiteDiagnostics(savedTuple, syntax, srcElementFields[i]);
var convertedFieldAccess = MakeConversionNode(syntax, fieldAccess, elementConversions[i], destElementTypes[i], @checked, explicitCastInCode);

fieldAccessorsBuilder.Add(convertedFieldAccess);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,14 +189,7 @@ private ImmutableArray<BoundExpression> AccessTupleFields(BoundExpression expres
var builder = ArrayBuilder<BoundExpression>.GetInstance(numElements);
for (int i = 0; i < numElements; i++)
{
var field = fields[i];

DiagnosticInfo useSiteInfo = field.GetUseSiteDiagnostic();
if ((object)useSiteInfo != null && useSiteInfo.Severity == DiagnosticSeverity.Error)
{
Symbol.ReportUseSiteDiagnostic(useSiteInfo, _diagnostics, expression.Syntax.Location);
}
var fieldAccess = MakeTupleFieldAccess(expression.Syntax, field, tuple, null, LookupResultKind.Empty);
var fieldAccess = MakeTupleFieldAccessAndReportUseSiteDiagnostics(tuple, expression.Syntax, fields[i]);
builder.Add(fieldAccess);
}
return builder.ToImmutableAndFree();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using Microsoft.CodeAnalysis.CSharp.Symbols;
using System.Diagnostics;

namespace Microsoft.CodeAnalysis.CSharp
{
Expand Down Expand Up @@ -92,5 +91,20 @@ private BoundExpression MakeTupleFieldAccess(
// make a field access for the most local access
return _factory.Field(rewrittenReceiver, underlyingField);
}

private BoundExpression MakeTupleFieldAccessAndReportUseSiteDiagnostics(BoundExpression tuple, SyntaxNode syntax, FieldSymbol field)
{
// Use default field rather than implicitly named fields since
// fields from inferred names are not usable in C# 7.0.
field = field.CorrespondingTupleField ?? field;

DiagnosticInfo useSiteInfo = field.GetUseSiteDiagnostic();
if ((object)useSiteInfo != null && useSiteInfo.Severity == DiagnosticSeverity.Error)
{
Symbol.ReportUseSiteDiagnostic(useSiteInfo, _diagnostics, syntax.Location);
}

return MakeTupleFieldAccess(syntax, field, tuple, null, LookupResultKind.Empty);
}
}
}
257 changes: 257 additions & 0 deletions src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7366,5 +7366,262 @@ public static explicit operator (byte, byte)(C c)
}";
CompileAndVerify(source, expectedOutput: @"3 4", additionalRefs: s_valueTupleRefs);
}

[Fact, WorkItem(19398, "https://github.com/dotnet/roslyn/issues/19398")]
public void DeconstructionLoweredToNothing()
{
var source = @"
class C
{
static void M()
{
for (var(_, _) = (1, 2); ; (_, _) = (3, 4))
{
}
}
}";
var comp = CreateStandardCompilation(source, parseOptions: TestOptions.Regular7, references: s_valueTupleRefs);
comp.VerifyDiagnostics();
var verifier = CompileAndVerify(comp);
verifier.VerifyIL("C.M", @"
{
// Code size 2 (0x2)
.maxstack 0
IL_0000: br.s IL_0000
}");
}

[Fact, WorkItem(19398, "https://github.com/dotnet/roslyn/issues/19398")]
public void DeconstructionLoweredToNothing2()
{
var source = @"
class C
{
static void M()
{
(_, _) = (1, 2);
}
}";
var comp = CreateStandardCompilation(source, parseOptions: TestOptions.Regular7, references: s_valueTupleRefs);
comp.VerifyDiagnostics();
var verifier = CompileAndVerify(comp);
verifier.VerifyIL("C.M", @"
{
// Code size 1 (0x1)
.maxstack 0
IL_0000: ret
}");
}

[Fact, WorkItem(19398, "https://github.com/dotnet/roslyn/issues/19398")]
public void DeconstructionLoweredToNothing3()
{
var source = @"
class C
{
static void Main()
{
foreach (var(_, _) in new[] { (1, 2) })
{
System.Console.Write(""once"");
}
}
}";
var comp = CreateStandardCompilation(source, parseOptions: TestOptions.Regular7, references: s_valueTupleRefs, options: TestOptions.DebugExe);
comp.VerifyDiagnostics();
CompileAndVerify(comp, expectedOutput: "once");
}

[WorkItem(21028, "https://github.com/dotnet/roslyn/issues/21028")]
[Fact]
public void InferredName()
{
var source =
@"class C
{
static void Main()
{
int x = 0, y = 1;
var t = (x, y);
var (a, b) = t;
}
}";
// C# 7.0
var comp = CreateStandardCompilation(
source,
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7),
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyEmitDiagnostics();
// C# 7.1
comp = CreateStandardCompilation(
source,
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_1),
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyEmitDiagnostics();
}

[WorkItem(21028, "https://github.com/dotnet/roslyn/issues/21028")]
[Fact]
public void InferredName_ConditionalOperator()
{
var source =
@"class C
{
static void M(int a, int b, bool c)
{
(var x, var y) = c ? (a, default(object)) : (b, null);
(x, y) = c ? (a, default(string)) : (b, default(object));
}
}";
// C# 7.0
var comp = CreateStandardCompilation(
source,
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7),
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyEmitDiagnostics();
// C# 7.1
comp = CreateStandardCompilation(
source,
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_1),
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyEmitDiagnostics();
}

[WorkItem(21028, "https://github.com/dotnet/roslyn/issues/21028")]
[Fact]
public void InferredName_ImplicitArray()
{
var source =
@"class C
{
static void M(int x)
{
int y;
object z;
(y, z) = (new [] { (x, default(object)), (2, 3) })[0];
}
}";
// C# 7.0
var comp = CreateStandardCompilation(
source,
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7),
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyEmitDiagnostics();
// C# 7.1
comp = CreateStandardCompilation(
source,
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_1),
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyEmitDiagnostics();
}

[WorkItem(21028, "https://github.com/dotnet/roslyn/issues/21028")]
[Fact]
public void InferredName_Lambda()
{
var source =
@"class C
{
static T F<T>(System.Func<object, bool, T> f)
{
return f(null, false);
}
static void M()
{
var (x, y) = F((a, b) =>
{
if (b) return (default(object), a);
return (null, null);
});
}
}";
// C# 7.0
var comp = CreateStandardCompilation(
source,
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7),
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyEmitDiagnostics();
// C# 7.1
comp = CreateStandardCompilation(
source,
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_1),
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyEmitDiagnostics();
}

[WorkItem(21028, "https://github.com/dotnet/roslyn/issues/21028")]
[Fact]
public void InferredName_ConditionalOperator_LongTuple()
{
var source =
@"class C
{
static void M(object a, object b, bool c)
{
var (_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) = c ?
(1, 2, 3, 4, 5, 6, 7, a, b, 10) :
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
}
}";
// C# 7.0
var comp = CreateStandardCompilation(
source,
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7),
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyEmitDiagnostics();
// C# 7.1
comp = CreateStandardCompilation(
source,
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_1),
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyEmitDiagnostics();
}

[WorkItem(21028, "https://github.com/dotnet/roslyn/issues/21028")]
[Fact]
public void InferredName_ConditionalOperator_UseSite()
{
var source =
@"class C
{
static void M(int a, int b, bool c)
{
var (x, y) = c ? ((object)1, a) : (b, 2);
}
}
namespace System
{
struct ValueTuple<T1, T2>
{
public T1 Item1;
private T2 Item2;
public ValueTuple(T1 item1, T2 item2)
{
Item1 = item1;
Item2 = item2;
}
}
}";
// C# 7.0
var comp = CreateStandardCompilation(
source,
assemblyName: "39f5d0e8-2935-4207-a74d-517a8e55af08",
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7),
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyEmitDiagnostics(
// (5,22): error CS8128: Member 'Item2' was not found on type 'ValueTuple<T1, T2>' from assembly '39f5d0e8-2935-4207-a74d-517a8e55af08, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
// var (x, y) = c ? ((object)1, a) : (b, 2);
Diagnostic(ErrorCode.ERR_PredefinedTypeMemberNotFoundInAssembly, "c ? ((object)1, a) : (b, 2)").WithArguments("Item2", "System.ValueTuple<T1, T2>", "39f5d0e8-2935-4207-a74d-517a8e55af08, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(5, 22));
// C# 7.1
comp = CreateStandardCompilation(
source,
assemblyName: "39f5d0e8-2935-4207-a74d-517a8e55af08",
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_1),
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyEmitDiagnostics(
// (5,22): error CS8128: Member 'Item2' was not found on type 'ValueTuple<T1, T2>' from assembly '39f5d0e8-2935-4207-a74d-517a8e55af08, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
// var (x, y) = c ? ((object)1, a) : (b, 2);
Diagnostic(ErrorCode.ERR_PredefinedTypeMemberNotFoundInAssembly, "c ? ((object)1, a) : (b, 2)").WithArguments("Item2", "System.ValueTuple<T1, T2>", "39f5d0e8-2935-4207-a74d-517a8e55af08, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(5, 22));
}
}
}
23 changes: 23 additions & 0 deletions src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3938,6 +3938,29 @@ static class Extension
verifier7_1.VerifyDiagnostics();
}

[WorkItem(21518, "https://github.com/dotnet/roslyn/issues/21518")]
[Fact]
public void InferredName_Conversion()
{
var source =
@"using System.Collections.Generic;
class C
{
static void F((int, IList<object>) items)
{
}
static void Test()
{
var items = new List<object>();
var group = (1, items);
F(group);
}
}";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7),
references: new[] { MscorlibRef, ValueTupleRef, SystemRuntimeFacadeRef, SystemCoreRef });
comp.VerifyEmitDiagnostics();
}

[Fact]
public void LongTupleWithArgumentEvaluation()
{
Expand Down
Loading

0 comments on commit b735460

Please sign in to comment.