Skip to content

Commit c77153c

Browse files
author
msftbot[bot]
authored
Merge pull request #43151 from dotnet/merges/release/dev16.6-to-release/dev16.6-vs-deps
Merge release/dev16.6 to release/dev16.6-vs-deps
2 parents 0a9cda3 + de59c37 commit c77153c

File tree

9 files changed

+440
-17
lines changed

9 files changed

+440
-17
lines changed

src/Compilers/CSharp/Portable/FlowAnalysis/UnassignedFieldsWalker.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,11 @@ public override BoundNode VisitPropertyAccess(BoundPropertyAccess node)
142142
if (property.IsStatic || node.ReceiverOpt is BoundThisReference)
143143
{
144144
var accessor = property.GetMethod;
145-
146-
ApplyMemberPostConditions(property.ContainingType,
147-
accessor.NotNullMembers, accessor.NotNullWhenTrueMembers, accessor.NotNullWhenFalseMembers);
145+
if (!(accessor is null))
146+
{
147+
ApplyMemberPostConditions(property.ContainingType,
148+
accessor.NotNullMembers, accessor.NotNullWhenTrueMembers, accessor.NotNullWhenFalseMembers);
149+
}
148150
}
149151

150152
return result;

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,7 @@ private BoundExpression RewriteLiftedBinaryOperator(SyntaxNode syntax, BinaryOpe
495495
// by including it as a part of whenNull, but there is a concern
496496
// that it can lead to code duplication
497497
var optimize = conditionalLeft != null &&
498+
operatorKind != BinaryOperatorKind.LiftedBoolOr && operatorKind != BinaryOperatorKind.LiftedBoolAnd &&
498499
!ReadIsSideeffecting(loweredRight) &&
499500
(conditionalLeft.WhenNullOpt == null || conditionalLeft.WhenNullOpt.IsDefaultValue());
500501

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

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using Microsoft.CodeAnalysis.Test.Utilities;
1010
using Roslyn.Test.Utilities;
1111
using System.Collections.Immutable;
12+
using System.Text;
1213
using Xunit;
1314

1415
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen
@@ -5828,5 +5829,178 @@ void M<T>(T t1, T t2)
58285829
// t1 = t1 ?? t2;
58295830
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "t1 ?? t2").WithArguments("unconstrained type parameters in null coalescing operator", "8.0").WithLocation(6, 14));
58305831
}
5832+
5833+
[Fact, WorkItem(41760, "https://github.com/dotnet/roslyn/issues/41760")]
5834+
public void NullableBoolOperatorSemantics_01()
5835+
{
5836+
// The C# specification has a section outlining the behavior of the bool operators `|` and `&`
5837+
// on operands of type `bool?`. We check that these are the semantics obeyed by the compiler.
5838+
var sourceStart = @"
5839+
using System;
5840+
5841+
public class C
5842+
{
5843+
bool T => true;
5844+
bool F => false;
5845+
static bool? True => true;
5846+
static bool? False => false;
5847+
static bool? Null => null;
5848+
5849+
static void Main()
5850+
{
5851+
C n = null;
5852+
C c = new C();
5853+
bool t = true;
5854+
bool f = false;
5855+
bool? nt = true;
5856+
bool? nf = false;
5857+
bool? nn = null;
5858+
";
5859+
var sourceEnd =
5860+
@" Console.WriteLine(""Done."");
5861+
}
5862+
5863+
static bool? And(bool? x, bool? y)
5864+
{
5865+
if (x == false || y == false)
5866+
return false;
5867+
if (x == null || y == null)
5868+
return null;
5869+
return true;
5870+
}
5871+
5872+
static bool? Or(bool? x, bool? y)
5873+
{
5874+
if (x == true || y == true)
5875+
return true;
5876+
if (x == null || y == null)
5877+
return null;
5878+
return false;
5879+
}
5880+
5881+
static bool? Xor(bool? x, bool? y)
5882+
{
5883+
if (x == null || y == null)
5884+
return null;
5885+
return x.Value != y.Value;
5886+
}
5887+
}
5888+
5889+
static class Assert
5890+
{
5891+
public static void Equal<T>(T expected, T actual, string message)
5892+
{
5893+
if (!object.Equals(expected, actual))
5894+
Console.WriteLine($""Wrong for {message,-15} Expected: {expected?.ToString() ?? ""null"",-5} Actual: {actual?.ToString() ?? ""null""}"");
5895+
}
5896+
}
5897+
";
5898+
var builder = new StringBuilder();
5899+
var forms = new string[]
5900+
{
5901+
"null",
5902+
"nn",
5903+
"true",
5904+
"t",
5905+
"nt",
5906+
"false",
5907+
"f",
5908+
"nf",
5909+
"c?.T",
5910+
"c?.F",
5911+
"n?.T",
5912+
"Null",
5913+
"True",
5914+
"False",
5915+
};
5916+
foreach (var left in forms)
5917+
{
5918+
foreach (var right in forms)
5919+
{
5920+
if (left == "null" && right == "null")
5921+
continue;
5922+
builder.AppendLine(@$" Assert.Equal<bool?>(Or({left}, {right}), {left} | {right}, ""{left} | {right}"");");
5923+
builder.AppendLine(@$" Assert.Equal<bool?>(And({left}, {right}), {left} & {right}, ""{left} & {right}"");");
5924+
if (left != "null" && right != "null")
5925+
builder.AppendLine(@$" Assert.Equal<bool?>(Xor({left}, {right}), {left} ^ {right}, ""{left} ^ {right}"");");
5926+
}
5927+
}
5928+
var source = sourceStart + builder.ToString() + sourceEnd;
5929+
var comp = CreateCompilation(source, options: TestOptions.ReleaseExe);
5930+
comp.VerifyDiagnostics(
5931+
);
5932+
CompileAndVerify(comp, expectedOutput: @"Done.");
5933+
}
5934+
5935+
[Fact, WorkItem(41760, "https://github.com/dotnet/roslyn/issues/41760")]
5936+
public void NullableBoolOperatorSemantics_02()
5937+
{
5938+
var source = @"
5939+
using System;
5940+
5941+
public class C
5942+
{
5943+
public bool BoolValue;
5944+
5945+
static void Main()
5946+
{
5947+
C obj = null;
5948+
Console.Write(obj?.BoolValue | true);
5949+
Console.Write(obj?.BoolValue & false);
5950+
}
5951+
}
5952+
";
5953+
var comp = CreateCompilation(source, options: TestOptions.ReleaseExe);
5954+
comp.VerifyDiagnostics(
5955+
);
5956+
var cv = CompileAndVerify(comp, expectedOutput: @"TrueFalse");
5957+
cv.VerifyIL("C.Main", @"
5958+
{
5959+
// Code size 99 (0x63)
5960+
.maxstack 3
5961+
.locals init (bool? V_0,
5962+
bool? V_1)
5963+
IL_0000: ldnull
5964+
IL_0001: dup
5965+
IL_0002: dup
5966+
IL_0003: brtrue.s IL_0011
5967+
IL_0005: pop
5968+
IL_0006: ldloca.s V_1
5969+
IL_0008: initobj ""bool?""
5970+
IL_000e: ldloc.1
5971+
IL_000f: br.s IL_001b
5972+
IL_0011: ldfld ""bool C.BoolValue""
5973+
IL_0016: newobj ""bool?..ctor(bool)""
5974+
IL_001b: stloc.0
5975+
IL_001c: ldc.i4.1
5976+
IL_001d: brtrue.s IL_0022
5977+
IL_001f: ldloc.0
5978+
IL_0020: br.s IL_0028
5979+
IL_0022: ldc.i4.1
5980+
IL_0023: newobj ""bool?..ctor(bool)""
5981+
IL_0028: box ""bool?""
5982+
IL_002d: call ""void System.Console.Write(object)""
5983+
IL_0032: dup
5984+
IL_0033: brtrue.s IL_0041
5985+
IL_0035: pop
5986+
IL_0036: ldloca.s V_1
5987+
IL_0038: initobj ""bool?""
5988+
IL_003e: ldloc.1
5989+
IL_003f: br.s IL_004b
5990+
IL_0041: ldfld ""bool C.BoolValue""
5991+
IL_0046: newobj ""bool?..ctor(bool)""
5992+
IL_004b: stloc.0
5993+
IL_004c: ldc.i4.0
5994+
IL_004d: brtrue.s IL_0057
5995+
IL_004f: ldc.i4.0
5996+
IL_0050: newobj ""bool?..ctor(bool)""
5997+
IL_0055: br.s IL_0058
5998+
IL_0057: ldloc.0
5999+
IL_0058: box ""bool?""
6000+
IL_005d: call ""void System.Console.Write(object)""
6001+
IL_0062: ret
6002+
}
6003+
");
6004+
}
58316005
}
58326006
}

src/Compilers/CSharp/Test/Semantic/Semantics/UninitializedNonNullableFieldTests.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,5 +1346,42 @@ internal C(char c)
13461346
// internal C(char c)
13471347
Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "C").WithArguments("field", "_f").WithLocation(28, 14));
13481348
}
1349+
1350+
[Fact]
1351+
[WorkItem(1090263, "https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems/edit/1090263")]
1352+
public void PropertyNoGetter()
1353+
{
1354+
var comp = CreateCompilation(@"
1355+
using System;
1356+
class C
1357+
{
1358+
public string P { }
1359+
public string P2 { set { } }
1360+
public string P3 { } = string.Empty;
1361+
public C()
1362+
{
1363+
P = """";
1364+
Console.WriteLine(P2);
1365+
P2 += """";
1366+
}
1367+
}", options: WithNonNullTypesTrue());
1368+
comp.VerifyDiagnostics(
1369+
// (5,19): error CS0548: 'C.P': property or indexer must have at least one accessor
1370+
// public string P { }
1371+
Diagnostic(ErrorCode.ERR_PropertyWithNoAccessors, "P").WithArguments("C.P").WithLocation(5, 19),
1372+
// (7,19): error CS0548: 'C.P3': property or indexer must have at least one accessor
1373+
// public string P3 { } = string.Empty;
1374+
Diagnostic(ErrorCode.ERR_PropertyWithNoAccessors, "P3").WithArguments("C.P3").WithLocation(7, 19),
1375+
// (10,9): error CS0200: Property or indexer 'C.P' cannot be assigned to -- it is read only
1376+
// P = "";
1377+
Diagnostic(ErrorCode.ERR_AssgReadonlyProp, "P").WithArguments("C.P").WithLocation(10, 9),
1378+
// (11,27): error CS0154: The property or indexer 'C.P2' cannot be used in this context because it lacks the get accessor
1379+
// Console.WriteLine(P2);
1380+
Diagnostic(ErrorCode.ERR_PropertyLacksGet, "P2").WithArguments("C.P2").WithLocation(11, 27),
1381+
// (12,9): error CS0154: The property or indexer 'C.P2' cannot be used in this context because it lacks the get accessor
1382+
// P2 += "";
1383+
Diagnostic(ErrorCode.ERR_PropertyLacksGet, "P2").WithArguments("C.P2").WithLocation(12, 9)
1384+
);
1385+
}
13491386
}
13501387
}

0 commit comments

Comments
 (0)