Skip to content

Commit 107b608

Browse files
committed
Add missing conversions
1 parent 7674a00 commit 107b608

File tree

6 files changed

+179
-72
lines changed

6 files changed

+179
-72
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ protected BoundExpression LowerEvaluation(BoundDagEvaluation evaluation)
152152
PropertySymbol property = p.Property;
153153
var outputTemp = new BoundDagTemp(p.Syntax, property.Type, p);
154154
BoundExpression output = _tempAllocator.GetTemp(outputTemp);
155+
input = _factory.ConvertReceiverForExtensionMemberIfNeeded(property, input);
155156
return _factory.AssignmentExpression(output, _localRewriter.MakePropertyAccess(_factory.Syntax, input, property, LookupResultKind.Viable, property.Type, isLeftOfAssignment: false));
156157
}
157158

@@ -190,6 +191,7 @@ void addArg(RefKind refKind, BoundExpression expression)
190191
addArg(RefKind.Out, _tempAllocator.GetTemp(outputTemp));
191192
}
192193

194+
receiver = _factory.ConvertReceiverForExtensionMemberIfNeeded(method, receiver);
193195
return _factory.Call(receiver, method, refKindBuilder.ToImmutableAndFree(), argBuilder.ToImmutableAndFree());
194196
}
195197

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ private BoundStatement InitializeFixedStatementGetPinnable(
355355
}
356356

357357
// .GetPinnable()
358+
callReceiver = factory.ConvertReceiverForExtensionMemberIfNeeded(getPinnableMethod, callReceiver);
358359
var getPinnableCall = getPinnableMethod.IsStatic ?
359360
factory.Call(null, getPinnableMethod, callReceiver) :
360361
factory.Call(callReceiver, getPinnableMethod);

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -702,8 +702,7 @@ private BoundExpression MakeObjectInitializerMemberAccess(
702702
_compilation.Conversions.HasImplicitConversionToOrImplementsVarianceCompatibleInterface(rewrittenReceiver.Type, memberSymbol.ContainingType, ref discardedUseSiteInfo, out _));
703703
// It is possible there are use site diagnostics from the above, but none that we need report as we aren't generating code for the conversion
704704
#endif
705-
// Tracked by https://github.com/dotnet/roslyn/issues/76130 : handle creating a conversion on receiver
706-
// TODO2
705+
rewrittenReceiver = _factory.ConvertReceiverForExtensionMemberIfNeeded(memberSymbol, rewrittenReceiver);
707706

708707
switch (memberSymbol.Kind)
709708
{

src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,23 @@ public BoundExpression AssignmentExpression(BoundExpression left, BoundExpressio
431431
return AssignmentExpression(Syntax, left, right, isRef: isRef, wasCompilerGenerated: true);
432432
}
433433

434+
public BoundExpression ConvertReceiverForExtensionMemberIfNeeded(Symbol member, BoundExpression receiver)
435+
{
436+
if (member.GetIsNewExtensionMember())
437+
{
438+
ParameterSymbol? extensionParameter = member.ContainingType.ExtensionParameter;
439+
Debug.Assert(extensionParameter is not null);
440+
#if DEBUG
441+
var discardedUseSiteInfo = CompoundUseSiteInfo<AssemblySymbol>.Discarded;
442+
Debug.Assert(Conversions.IsValidExtensionMethodThisArgConversion(this.Compilation.Conversions.ClassifyConversionFromType(receiver.Type, extensionParameter.Type, isChecked: false, ref discardedUseSiteInfo)));
443+
#endif
444+
445+
return this.Convert(extensionParameter.Type, receiver);
446+
}
447+
448+
return receiver;
449+
}
450+
434451
/// <summary>
435452
/// Creates a general assignment that might be instrumented.
436453
/// </summary>

src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs

Lines changed: 113 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -12871,17 +12871,17 @@ static class E
1287112871
}
1287212872
}
1287312873
""";
12874-
// Tracked by https://github.com/dotnet/roslyn/issues/76130 : handle conversion on receiver
1287512874
try
1287612875
{
12876+
// Tracked by https://github.com/dotnet/roslyn/issues/76130 : assertion in NullableWalker
1287712877
var comp = CreateCompilation(src);
1287812878
CompileAndVerify(comp, expectedOutput: "42").VerifyDiagnostics();
1287912879
}
1288012880
catch (InvalidOperationException)
1288112881
{
1288212882
return;
1288312883
}
12884-
Assert.False(true);
12884+
Assert.True(false);
1288512885
}
1288612886

1288712887
[Fact]
@@ -20926,17 +20926,8 @@ static class E
2092620926
}
2092720927
}
2092820928
""";
20929-
// Tracked by https://github.com/dotnet/roslyn/issues/76130 : handle conversion on receiver
20930-
try
20931-
{
20932-
var comp = CreateCompilation(text, options: TestOptions.UnsafeReleaseExe);
20933-
CompileAndVerify(comp, expectedOutput: "pin 2", verify: Verification.Skipped).VerifyDiagnostics();
20934-
}
20935-
catch (InvalidOperationException)
20936-
{
20937-
return;
20938-
}
20939-
Assert.False(true);
20929+
var comp = CreateCompilation(text, options: TestOptions.UnsafeReleaseExe);
20930+
CompileAndVerify(comp, expectedOutput: "pin 2", verify: Verification.Skipped).VerifyDiagnostics();
2094020931
}
2094120932

2094220933
[Fact]
@@ -22136,7 +22127,6 @@ public void ExtensionMemberLookup_Patterns()
2213622127
{
2213722128
var src = """
2213822129
var c = new C();
22139-
2214022130
_ = c is { Property: 42 };
2214122131

2214222132
class C { }
@@ -22166,7 +22156,6 @@ public void ExtensionMemberLookup_Patterns_Conversion()
2216622156
{
2216722157
var src = """
2216822158
var c = new C();
22169-
2217022159
_ = c is { Property: 42 };
2217122160

2217222161
class C { }
@@ -22182,17 +22171,8 @@ public int Property
2218222171
}
2218322172
}
2218422173
""";
22185-
// Tracked by https://github.com/dotnet/roslyn/issues/76130 : handle conversion on receiver
22186-
try
22187-
{
22188-
var comp = CreateCompilation(src);
22189-
CompileAndVerify(comp, expectedOutput: "property").VerifyDiagnostics();
22190-
}
22191-
catch (InvalidOperationException)
22192-
{
22193-
return;
22194-
}
22195-
Assert.False(true);
22174+
var comp = CreateCompilation(src);
22175+
CompileAndVerify(comp, expectedOutput: "property").VerifyDiagnostics();
2219622176
}
2219722177

2219822178
[Fact]
@@ -22230,6 +22210,66 @@ static class E2
2223022210
Assert.Equal("System.Int32 E2.<>E__0.Property2 { get; }", model.GetSymbolInfo(expressionColon.Expression).Symbol.ToTestDisplayString());
2223122211
}
2223222212

22213+
[Fact]
22214+
public void ExtensionMemberLookup_Patterns_ExtendedPropertyPattern_Conversion()
22215+
{
22216+
var src = """
22217+
var c = new C();
22218+
22219+
_ = c is { Property.Property2: 43 };
22220+
22221+
class C { }
22222+
22223+
static class E1
22224+
{
22225+
extension(object o)
22226+
{
22227+
public int Property { get { System.Console.Write("property "); return 42; } }
22228+
}
22229+
}
22230+
22231+
static class E2
22232+
{
22233+
extension(int i)
22234+
{
22235+
public int Property2 { get { System.Console.Write("property2"); return 43; } }
22236+
}
22237+
}
22238+
""";
22239+
var comp = CreateCompilation(src);
22240+
CompileAndVerify(comp, expectedOutput: "property property2").VerifyDiagnostics();
22241+
}
22242+
22243+
[Fact]
22244+
public void ExtensionMemberLookup_Patterns_ExtendedPropertyPattern_Conversion_02()
22245+
{
22246+
var src = """
22247+
var c = new C();
22248+
22249+
_ = c is { Property.Property2: 43 };
22250+
22251+
class C { }
22252+
22253+
static class E1
22254+
{
22255+
extension(C c)
22256+
{
22257+
public C Property { get { System.Console.Write("property "); return c; } }
22258+
}
22259+
}
22260+
22261+
static class E2
22262+
{
22263+
extension(object o)
22264+
{
22265+
public int Property2 { get { System.Console.Write("property2"); return 43; } }
22266+
}
22267+
}
22268+
""";
22269+
var comp = CreateCompilation(src);
22270+
CompileAndVerify(comp, expectedOutput: "property property2").VerifyDiagnostics();
22271+
}
22272+
2223322273
[Fact]
2223422274
public void ExtensionMemberLookup_Patterns_ListPattern_NoInstanceLength()
2223522275
{
@@ -22269,9 +22309,7 @@ public int Length
2226922309
public void ExtensionMemberLookup_ObjectInitializer()
2227022310
{
2227122311
var src = """
22272-
/*<bind>*/
2227322312
_ = new C() { Property = 42 };
22274-
/*</bind>*/
2227522313

2227622314
class C { }
2227722315

@@ -22297,9 +22335,7 @@ static class E
2229722335
public void ExtensionMemberLookup_ObjectInitializer_Conversion()
2229822336
{
2229922337
var src = """
22300-
/*<bind>*/
2230122338
_ = new C() { Property = 42 };
22302-
/*</bind>*/
2230322339

2230422340
class C { }
2230522341

@@ -22312,17 +22348,8 @@ static class E
2231222348
}
2231322349
""";
2231422350

22315-
// Tracked by https://github.com/dotnet/roslyn/issues/76130 : handle conversion on receiver
22316-
try
22317-
{
22318-
var comp = CreateCompilation(src);
22319-
CompileAndVerify(comp, expectedOutput: "property").VerifyDiagnostics();
22320-
}
22321-
catch (InvalidOperationException)
22322-
{
22323-
return;
22324-
}
22325-
Assert.False(true);
22351+
var comp = CreateCompilation(src);
22352+
CompileAndVerify(comp, expectedOutput: "property").VerifyDiagnostics();
2232622353
}
2232722354

2232822355
[Fact]
@@ -38561,15 +38588,17 @@ public class MyCollection : IEnumerable<object>
3856138588
IEnumerator IEnumerable.GetEnumerator() => throw null!;
3856238589
}
3856338590
""";
38591+
// Tracked by https://github.com/dotnet/roslyn/issues/78452 : assertion hit during nullability analysis
3856438592
try
3856538593
{
38566-
// Assertion tracked by https://github.com/dotnet/roslyn/issues/78452
3856738594
comp = CreateCompilation(src);
3856838595
comp.VerifyEmitDiagnostics();
3856938596
}
3857038597
catch (InvalidOperationException)
3857138598
{
38599+
return;
3857238600
}
38601+
Assert.True(false);
3857338602
}
3857438603

3857538604
[Fact]
@@ -38649,17 +38678,11 @@ public object Property { set { } }
3864938678
}
3865038679
""";
3865138680

38652-
// Tracked by https://github.com/dotnet/roslyn/issues/76130 : handle conversion on receiver
38653-
try
38654-
{
38655-
var comp = CreateCompilation(src);
38656-
comp.VerifyEmitDiagnostics();
38657-
}
38658-
catch (InvalidOperationException)
38659-
{
38660-
return;
38661-
}
38662-
Assert.False(true);
38681+
var comp = CreateCompilation(src);
38682+
comp.VerifyEmitDiagnostics(
38683+
// (4,31): warning CS8601: Possible null reference assignment.
38684+
// _ = new S() with { Property = oNull };
38685+
Diagnostic(ErrorCode.WRN_NullReferenceAssignment, "oNull").WithLocation(4, 31));
3866338686
}
3866438687

3866538688
[Fact]
@@ -38685,17 +38708,11 @@ public int Property { set { } }
3868538708
}
3868638709
""";
3868738710

38688-
// Tracked by https://github.com/dotnet/roslyn/issues/76130 : handle conversion on receiver
38689-
try
38690-
{
38691-
var comp = CreateCompilation(src);
38692-
comp.VerifyEmitDiagnostics();
38693-
}
38694-
catch (InvalidOperationException)
38695-
{
38696-
return;
38697-
}
38698-
Assert.False(true);
38711+
var comp = CreateCompilation(src);
38712+
comp.VerifyEmitDiagnostics(
38713+
// (4,5): warning CS8602: Dereference of a possibly null reference.
38714+
// _ = cNull with { Property = 42 };
38715+
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "cNull").WithLocation(4, 5));
3869938716
}
3870038717

3870138718
[Fact]
@@ -38712,6 +38729,37 @@ public void Nullability_With_03()
3871238729

3871338730
record C { }
3871438731

38732+
static class E
38733+
{
38734+
extension(object? o)
38735+
{
38736+
public int Property { set { } }
38737+
}
38738+
}
38739+
""";
38740+
38741+
// Tracked by https://github.com/dotnet/roslyn/issues/76130 : unexpected nullability warning
38742+
var comp = CreateCompilation(src);
38743+
comp.VerifyEmitDiagnostics(
38744+
// (4,5): warning CS8602: Dereference of a possibly null reference.
38745+
// _ = cNull with { Property = 42 };
38746+
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "cNull").WithLocation(4, 5));
38747+
}
38748+
38749+
[Fact]
38750+
public void Nullability_With_04()
38751+
{
38752+
var src = """
38753+
#nullable enable
38754+
38755+
C? cNull = null;
38756+
_ = cNull with { Property = 42 };
38757+
38758+
C cNotNull = new C();
38759+
_ = cNotNull with { Property = 42 };
38760+
38761+
record C { }
38762+
3871538763
static class E
3871638764
{
3871738765
extension<T>(T t)
@@ -38729,7 +38777,7 @@ public int Property { set { } }
3872938777
}
3873038778

3873138779
[Fact]
38732-
public void Nullability_With_04()
38780+
public void Nullability_With_05()
3873338781
{
3873438782
var src = """
3873538783
#nullable enable

0 commit comments

Comments
 (0)