Skip to content

Commit b735460

Browse files
authored
Merge pull request #21553 from cston/21518-dev15.3.x
Use default tuple fields in conversion since fields from inferred names are marked not usable in C#7
2 parents aca31f6 + 8026894 commit b735460

File tree

6 files changed

+321
-20
lines changed

6 files changed

+321
-20
lines changed

src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Conversion.cs

+1-9
Original file line numberDiff line numberDiff line change
@@ -649,16 +649,8 @@ private BoundExpression RewriteTupleConversion(
649649

650650
for (int i = 0; i < numElements; i++)
651651
{
652-
var field = srcElementFields[i];
653-
654-
DiagnosticInfo useSiteInfo = field.GetUseSiteDiagnostic();
655-
if ((object)useSiteInfo != null && useSiteInfo.Severity == DiagnosticSeverity.Error)
656-
{
657-
Symbol.ReportUseSiteDiagnostic(useSiteInfo, _diagnostics, syntax.Location);
658-
}
659-
var fieldAccess = MakeTupleFieldAccess(syntax, field, savedTuple, null, LookupResultKind.Empty);
652+
var fieldAccess = MakeTupleFieldAccessAndReportUseSiteDiagnostics(savedTuple, syntax, srcElementFields[i]);
660653
var convertedFieldAccess = MakeConversionNode(syntax, fieldAccess, elementConversions[i], destElementTypes[i], @checked, explicitCastInCode);
661-
662654
fieldAccessorsBuilder.Add(convertedFieldAccess);
663655
}
664656

src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_DeconstructionAssignmentOperator.cs

+1-8
Original file line numberDiff line numberDiff line change
@@ -189,14 +189,7 @@ private ImmutableArray<BoundExpression> AccessTupleFields(BoundExpression expres
189189
var builder = ArrayBuilder<BoundExpression>.GetInstance(numElements);
190190
for (int i = 0; i < numElements; i++)
191191
{
192-
var field = fields[i];
193-
194-
DiagnosticInfo useSiteInfo = field.GetUseSiteDiagnostic();
195-
if ((object)useSiteInfo != null && useSiteInfo.Severity == DiagnosticSeverity.Error)
196-
{
197-
Symbol.ReportUseSiteDiagnostic(useSiteInfo, _diagnostics, expression.Syntax.Location);
198-
}
199-
var fieldAccess = MakeTupleFieldAccess(expression.Syntax, field, tuple, null, LookupResultKind.Empty);
192+
var fieldAccess = MakeTupleFieldAccessAndReportUseSiteDiagnostics(tuple, expression.Syntax, fields[i]);
200193
builder.Add(fieldAccess);
201194
}
202195
return builder.ToImmutableAndFree();

src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Field.cs

+15-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
22

33
using Microsoft.CodeAnalysis.CSharp.Symbols;
4-
using System.Diagnostics;
54

65
namespace Microsoft.CodeAnalysis.CSharp
76
{
@@ -92,5 +91,20 @@ private BoundExpression MakeTupleFieldAccess(
9291
// make a field access for the most local access
9392
return _factory.Field(rewrittenReceiver, underlyingField);
9493
}
94+
95+
private BoundExpression MakeTupleFieldAccessAndReportUseSiteDiagnostics(BoundExpression tuple, SyntaxNode syntax, FieldSymbol field)
96+
{
97+
// Use default field rather than implicitly named fields since
98+
// fields from inferred names are not usable in C# 7.0.
99+
field = field.CorrespondingTupleField ?? field;
100+
101+
DiagnosticInfo useSiteInfo = field.GetUseSiteDiagnostic();
102+
if ((object)useSiteInfo != null && useSiteInfo.Severity == DiagnosticSeverity.Error)
103+
{
104+
Symbol.ReportUseSiteDiagnostic(useSiteInfo, _diagnostics, syntax.Location);
105+
}
106+
107+
return MakeTupleFieldAccess(syntax, field, tuple, null, LookupResultKind.Empty);
108+
}
95109
}
96110
}

src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs

+257
Original file line numberDiff line numberDiff line change
@@ -7366,5 +7366,262 @@ public static explicit operator (byte, byte)(C c)
73667366
}";
73677367
CompileAndVerify(source, expectedOutput: @"3 4", additionalRefs: s_valueTupleRefs);
73687368
}
7369+
7370+
[Fact, WorkItem(19398, "https://github.com/dotnet/roslyn/issues/19398")]
7371+
public void DeconstructionLoweredToNothing()
7372+
{
7373+
var source = @"
7374+
class C
7375+
{
7376+
static void M()
7377+
{
7378+
for (var(_, _) = (1, 2); ; (_, _) = (3, 4))
7379+
{
7380+
}
7381+
}
7382+
}";
7383+
var comp = CreateStandardCompilation(source, parseOptions: TestOptions.Regular7, references: s_valueTupleRefs);
7384+
comp.VerifyDiagnostics();
7385+
var verifier = CompileAndVerify(comp);
7386+
verifier.VerifyIL("C.M", @"
7387+
{
7388+
// Code size 2 (0x2)
7389+
.maxstack 0
7390+
IL_0000: br.s IL_0000
7391+
}");
7392+
}
7393+
7394+
[Fact, WorkItem(19398, "https://github.com/dotnet/roslyn/issues/19398")]
7395+
public void DeconstructionLoweredToNothing2()
7396+
{
7397+
var source = @"
7398+
class C
7399+
{
7400+
static void M()
7401+
{
7402+
(_, _) = (1, 2);
7403+
}
7404+
}";
7405+
var comp = CreateStandardCompilation(source, parseOptions: TestOptions.Regular7, references: s_valueTupleRefs);
7406+
comp.VerifyDiagnostics();
7407+
var verifier = CompileAndVerify(comp);
7408+
verifier.VerifyIL("C.M", @"
7409+
{
7410+
// Code size 1 (0x1)
7411+
.maxstack 0
7412+
IL_0000: ret
7413+
}");
7414+
}
7415+
7416+
[Fact, WorkItem(19398, "https://github.com/dotnet/roslyn/issues/19398")]
7417+
public void DeconstructionLoweredToNothing3()
7418+
{
7419+
var source = @"
7420+
class C
7421+
{
7422+
static void Main()
7423+
{
7424+
foreach (var(_, _) in new[] { (1, 2) })
7425+
{
7426+
System.Console.Write(""once"");
7427+
}
7428+
}
7429+
}";
7430+
var comp = CreateStandardCompilation(source, parseOptions: TestOptions.Regular7, references: s_valueTupleRefs, options: TestOptions.DebugExe);
7431+
comp.VerifyDiagnostics();
7432+
CompileAndVerify(comp, expectedOutput: "once");
7433+
}
7434+
7435+
[WorkItem(21028, "https://github.com/dotnet/roslyn/issues/21028")]
7436+
[Fact]
7437+
public void InferredName()
7438+
{
7439+
var source =
7440+
@"class C
7441+
{
7442+
static void Main()
7443+
{
7444+
int x = 0, y = 1;
7445+
var t = (x, y);
7446+
var (a, b) = t;
7447+
}
7448+
}";
7449+
// C# 7.0
7450+
var comp = CreateStandardCompilation(
7451+
source,
7452+
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7),
7453+
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
7454+
comp.VerifyEmitDiagnostics();
7455+
// C# 7.1
7456+
comp = CreateStandardCompilation(
7457+
source,
7458+
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_1),
7459+
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
7460+
comp.VerifyEmitDiagnostics();
7461+
}
7462+
7463+
[WorkItem(21028, "https://github.com/dotnet/roslyn/issues/21028")]
7464+
[Fact]
7465+
public void InferredName_ConditionalOperator()
7466+
{
7467+
var source =
7468+
@"class C
7469+
{
7470+
static void M(int a, int b, bool c)
7471+
{
7472+
(var x, var y) = c ? (a, default(object)) : (b, null);
7473+
(x, y) = c ? (a, default(string)) : (b, default(object));
7474+
}
7475+
}";
7476+
// C# 7.0
7477+
var comp = CreateStandardCompilation(
7478+
source,
7479+
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7),
7480+
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
7481+
comp.VerifyEmitDiagnostics();
7482+
// C# 7.1
7483+
comp = CreateStandardCompilation(
7484+
source,
7485+
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_1),
7486+
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
7487+
comp.VerifyEmitDiagnostics();
7488+
}
7489+
7490+
[WorkItem(21028, "https://github.com/dotnet/roslyn/issues/21028")]
7491+
[Fact]
7492+
public void InferredName_ImplicitArray()
7493+
{
7494+
var source =
7495+
@"class C
7496+
{
7497+
static void M(int x)
7498+
{
7499+
int y;
7500+
object z;
7501+
(y, z) = (new [] { (x, default(object)), (2, 3) })[0];
7502+
}
7503+
}";
7504+
// C# 7.0
7505+
var comp = CreateStandardCompilation(
7506+
source,
7507+
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7),
7508+
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
7509+
comp.VerifyEmitDiagnostics();
7510+
// C# 7.1
7511+
comp = CreateStandardCompilation(
7512+
source,
7513+
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_1),
7514+
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
7515+
comp.VerifyEmitDiagnostics();
7516+
}
7517+
7518+
[WorkItem(21028, "https://github.com/dotnet/roslyn/issues/21028")]
7519+
[Fact]
7520+
public void InferredName_Lambda()
7521+
{
7522+
var source =
7523+
@"class C
7524+
{
7525+
static T F<T>(System.Func<object, bool, T> f)
7526+
{
7527+
return f(null, false);
7528+
}
7529+
static void M()
7530+
{
7531+
var (x, y) = F((a, b) =>
7532+
{
7533+
if (b) return (default(object), a);
7534+
return (null, null);
7535+
});
7536+
}
7537+
}";
7538+
// C# 7.0
7539+
var comp = CreateStandardCompilation(
7540+
source,
7541+
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7),
7542+
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
7543+
comp.VerifyEmitDiagnostics();
7544+
// C# 7.1
7545+
comp = CreateStandardCompilation(
7546+
source,
7547+
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_1),
7548+
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
7549+
comp.VerifyEmitDiagnostics();
7550+
}
7551+
7552+
[WorkItem(21028, "https://github.com/dotnet/roslyn/issues/21028")]
7553+
[Fact]
7554+
public void InferredName_ConditionalOperator_LongTuple()
7555+
{
7556+
var source =
7557+
@"class C
7558+
{
7559+
static void M(object a, object b, bool c)
7560+
{
7561+
var (_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) = c ?
7562+
(1, 2, 3, 4, 5, 6, 7, a, b, 10) :
7563+
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
7564+
}
7565+
}";
7566+
// C# 7.0
7567+
var comp = CreateStandardCompilation(
7568+
source,
7569+
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7),
7570+
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
7571+
comp.VerifyEmitDiagnostics();
7572+
// C# 7.1
7573+
comp = CreateStandardCompilation(
7574+
source,
7575+
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_1),
7576+
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
7577+
comp.VerifyEmitDiagnostics();
7578+
}
7579+
7580+
[WorkItem(21028, "https://github.com/dotnet/roslyn/issues/21028")]
7581+
[Fact]
7582+
public void InferredName_ConditionalOperator_UseSite()
7583+
{
7584+
var source =
7585+
@"class C
7586+
{
7587+
static void M(int a, int b, bool c)
7588+
{
7589+
var (x, y) = c ? ((object)1, a) : (b, 2);
7590+
}
7591+
}
7592+
namespace System
7593+
{
7594+
struct ValueTuple<T1, T2>
7595+
{
7596+
public T1 Item1;
7597+
private T2 Item2;
7598+
public ValueTuple(T1 item1, T2 item2)
7599+
{
7600+
Item1 = item1;
7601+
Item2 = item2;
7602+
}
7603+
}
7604+
}";
7605+
// C# 7.0
7606+
var comp = CreateStandardCompilation(
7607+
source,
7608+
assemblyName: "39f5d0e8-2935-4207-a74d-517a8e55af08",
7609+
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7),
7610+
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
7611+
comp.VerifyEmitDiagnostics(
7612+
// (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'.
7613+
// var (x, y) = c ? ((object)1, a) : (b, 2);
7614+
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));
7615+
// C# 7.1
7616+
comp = CreateStandardCompilation(
7617+
source,
7618+
assemblyName: "39f5d0e8-2935-4207-a74d-517a8e55af08",
7619+
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_1),
7620+
references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
7621+
comp.VerifyEmitDiagnostics(
7622+
// (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'.
7623+
// var (x, y) = c ? ((object)1, a) : (b, 2);
7624+
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));
7625+
}
73697626
}
73707627
}

src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs

+23
Original file line numberDiff line numberDiff line change
@@ -3938,6 +3938,29 @@ static class Extension
39383938
verifier7_1.VerifyDiagnostics();
39393939
}
39403940

3941+
[WorkItem(21518, "https://github.com/dotnet/roslyn/issues/21518")]
3942+
[Fact]
3943+
public void InferredName_Conversion()
3944+
{
3945+
var source =
3946+
@"using System.Collections.Generic;
3947+
class C
3948+
{
3949+
static void F((int, IList<object>) items)
3950+
{
3951+
}
3952+
static void Test()
3953+
{
3954+
var items = new List<object>();
3955+
var group = (1, items);
3956+
F(group);
3957+
}
3958+
}";
3959+
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7),
3960+
references: new[] { MscorlibRef, ValueTupleRef, SystemRuntimeFacadeRef, SystemCoreRef });
3961+
comp.VerifyEmitDiagnostics();
3962+
}
3963+
39413964
[Fact]
39423965
public void LongTupleWithArgumentEvaluation()
39433966
{

0 commit comments

Comments
 (0)