Skip to content

Commit

Permalink
Work around dotnet#75002
Browse files Browse the repository at this point in the history
  • Loading branch information
cston committed Sep 5, 2024
1 parent 572ec2f commit a79c157
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5019,7 +5019,6 @@ private void AddNonTypeMembers(

AddAccessorIfAvailable(builder.NonTypeMembers, property.GetMethod);
AddAccessorIfAvailable(builder.NonTypeMembers, property.SetMethod);

FieldSymbol? backingField = property.DeclaredAutoPropertyInfo.BackingField;

// TODO: can we leave this out of the member list?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -682,13 +682,13 @@ internal bool IsAutoPropertyOrUsesFieldKeyword
=> IsAutoProperty || UsesFieldKeyword;

internal bool UsesFieldKeyword
=> _lazyMergedAutoPropertyInfo.UsesFieldKeyword;
=> _Safe_MergedAutoPropertyInfo.UsesFieldKeyword;

protected bool HasExplicitAccessModifier
=> (_propertyFlags & Flags.HasExplicitAccessModifier) != 0;

internal bool IsAutoProperty
=> _lazyMergedAutoPropertyInfo.IsAutoProperty;
=> _Safe_MergedAutoPropertyInfo.IsAutoProperty;

protected bool AccessorsHaveImplementation
=> (_propertyFlags & Flags.AccessorsHaveImplementation) != 0;
Expand All @@ -698,7 +698,23 @@ protected bool AccessorsHaveImplementation
/// a property with an accessor using the 'field' keyword, or
/// a property with an initializer.
/// </summary>
internal SynthesizedBackingFieldSymbol BackingField => _lazyMergedAutoPropertyInfo.BackingField;
internal SynthesizedBackingFieldSymbol BackingField => _Safe_MergedAutoPropertyInfo.BackingField;

private AutoPropertyInfo _Safe_MergedAutoPropertyInfo
{
get
{
var autoPropertyInfo = _lazyMergedAutoPropertyInfo;
// When calling through the SemanticModel, partial members are not
// necessarily merged when the containing type includes a primary
// constructor - see https://github.com/dotnet/roslyn/issues/75002.
if (autoPropertyInfo is null && _containingType.PrimaryConstructor is { })
{
autoPropertyInfo = DeclaredAutoPropertyInfo;
}
return autoPropertyInfo;
}
}

#nullable enable
internal AutoPropertyInfo DeclaredAutoPropertyInfo
Expand Down
123 changes: 123 additions & 0 deletions src/Compilers/CSharp/Test/Emit2/Semantics/PrimaryConstructorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19777,6 +19777,129 @@ class C(int p)
AssertEx.Equal("System.Int32 C.this[System.Int32 i] { get; }", info.Symbol.ToTestDisplayString());
}

[WorkItem("https://github.com/dotnet/roslyn/issues/75002")]
[Fact]
public void PartialMembers_01()
{
var source1 = """
C c = null;
c.M();
_ = c.P;
""";
var source2 = """
partial class C(int p)
{
public partial void M() { }
public partial void M();
public partial object P { get; }
public partial object P { get => null; }
}
""";
var comp = CreateCompilation([source1, source2]);
var tree = comp.SyntaxTrees[0];
var model = comp.GetSemanticModel(tree);
model.GetDiagnostics().Verify(
// (2,3): error CS0121: The call is ambiguous between the following methods or properties: 'C.M()' and 'C.M()'
// c.M();
Diagnostic(ErrorCode.ERR_AmbigCall, "M").WithArguments("C.M()", "C.M()").WithLocation(2, 3),
// (3,7): error CS0229: Ambiguity between 'C.P' and 'C.P'
// _ = c.P;
Diagnostic(ErrorCode.ERR_AmbigMember, "P").WithArguments("C.P", "C.P").WithLocation(3, 7));
}

[Fact]
public void NullableAttributes_01()
{
var source1 = """
#nullable enable
C c = null!;
object o;
o = c.M();
o = c.P;
""";
var source2 = """
#nullable enable
using System.Diagnostics.CodeAnalysis;
class C(int p)
{
[return: MaybeNull] public object M() => new();
[MaybeNull] public object P { get => new(); }
}
""";
var comp = CreateCompilation([source1, source2]);
var tree = comp.SyntaxTrees[0];
var model = comp.GetSemanticModel(tree);
model.GetDiagnostics().Verify();
}

[WorkItem("https://github.com/dotnet/roslyn/issues/75002")]
[Fact]
public void NullableAttributes_PartialMembers_01()
{
var source1 = """
#nullable enable
C c = null!;
object o;
o = c.M();
o = c.P;
""";
var source2 = """
#nullable enable
using System.Diagnostics.CodeAnalysis;
partial class C(int p)
{
public partial object M() => new();
[return: MaybeNull] public partial object M();
[MaybeNull] public partial object P { get; }
public partial object P { get => new(); }
}
""";
var comp = CreateCompilation([source1, source2]);
var tree = comp.SyntaxTrees[0];
var model = comp.GetSemanticModel(tree);
model.GetDiagnostics().Verify(
// (4,7): error CS0121: The call is ambiguous between the following methods or properties: 'C.M()' and 'C.M()'
// o = c.M();
Diagnostic(ErrorCode.ERR_AmbigCall, "M").WithArguments("C.M()", "C.M()").WithLocation(4, 7),
// (5,7): error CS0229: Ambiguity between 'C.P' and 'C.P'
// o = c.P;
Diagnostic(ErrorCode.ERR_AmbigMember, "P").WithArguments("C.P", "C.P").WithLocation(5, 7));
}

[WorkItem("https://github.com/dotnet/roslyn/issues/75002")]
[Fact]
public void NullableAttributes_PartialMembers_02()
{
var source1 = """
#nullable enable
C c = null!;
object o;
o = c.M();
o = c.P;
""";
var source2 = """
#nullable enable
using System.Diagnostics.CodeAnalysis;
partial class C(int p)
{
[return: MaybeNull] public partial object M() => new();
public partial object M();
public partial object P { get; }
[MaybeNull] public partial object P { get => new(); }
}
""";
var comp = CreateCompilation([source1, source2]);
var tree = comp.SyntaxTrees[0];
var model = comp.GetSemanticModel(tree);
model.GetDiagnostics().Verify(
// (4,7): error CS0121: The call is ambiguous between the following methods or properties: 'C.M()' and 'C.M()'
// o = c.M();
Diagnostic(ErrorCode.ERR_AmbigCall, "M").WithArguments("C.M()", "C.M()").WithLocation(4, 7),
// (5,7): error CS0229: Ambiguity between 'C.P' and 'C.P'
// o = c.P;
Diagnostic(ErrorCode.ERR_AmbigMember, "P").WithArguments("C.P", "C.P").WithLocation(5, 7));
}

[Fact]
public void IllegalCapturingInStruct_01()
{
Expand Down

0 comments on commit a79c157

Please sign in to comment.