Skip to content

Commit

Permalink
Avoid synthesizing the parameterless struct constructor unnecessarily (
Browse files Browse the repository at this point in the history
  • Loading branch information
cston authored Feb 28, 2024
1 parent 1d9ee7f commit d765b8b
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -4663,7 +4663,9 @@ private void AddSynthesizedConstructorsIfNecessary(MembersAndInitializersBuilder
}

//kick out early if we've seen everything we're looking for
if (hasInstanceConstructor && hasStaticConstructor)
if (hasInstanceConstructor &&
hasParameterlessInstanceConstructor &&
hasStaticConstructor)
{
break;
}
Expand Down
106 changes: 106 additions & 0 deletions src/Compilers/CSharp/Test/Semantic/Semantics/StructConstructorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4792,5 +4792,111 @@ .maxstack 2
}
");
}

[Theory]
[InlineData("class")]
[InlineData("struct")]
[WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1598252")]
public void StaticAndInstanceConstructors_01(string type)
{
string source = $$"""
using System;
{{type}} S
{
static S()
{
Console.WriteLine("static constructor");
}
public S(int p)
{
Console.WriteLine("instance constructor: {0}", p);
}
public S() : this(0)
{
}
}
class Program
{
static void Main()
{
_ = new S();
}
}
""";

var comp = CreateCompilation(source, options: TestOptions.ReleaseExe);
VerifyExplicitlyDeclaredInstanceConstructors(
comp.GlobalNamespace.GetTypeMember("S"),
"S..ctor(System.Int32 p)",
"S..ctor()");
VerifyExplicitlyDeclaredInstanceConstructors(
((Compilation)comp).GlobalNamespace.GetTypeMember("S"),
"S..ctor(System.Int32 p)",
"S..ctor()");

CompileAndVerify(comp, expectedOutput: """
static constructor
instance constructor: 0
""");
}

[Theory]
[InlineData("class")]
[InlineData("struct")]
public void StaticAndInstanceConstructors_02(string type)
{
string source = $$"""
using System;
{{type}} S
{
static S()
{
Console.WriteLine("static constructor");
}
public S()
{
Console.WriteLine("instance constructor");
}
}
class Program
{
static void Main()
{
_ = new S();
}
}
""";

var comp = CreateCompilation(source, options: TestOptions.ReleaseExe);
VerifyExplicitlyDeclaredInstanceConstructors(
comp.GlobalNamespace.GetTypeMember("S"),
"S..ctor()");
VerifyExplicitlyDeclaredInstanceConstructors(
((Compilation)comp).GlobalNamespace.GetTypeMember("S"),
"S..ctor()");

CompileAndVerify(comp, expectedOutput: """
static constructor
instance constructor
""");
}

private static void VerifyExplicitlyDeclaredInstanceConstructors(NamedTypeSymbol type, params string[] expectedConstructors)
{
var constructors = type.InstanceConstructors;
var members = type.GetMembers(".ctor");
Assert.True(members.SequenceEqual(constructors));
Assert.True(constructors.All(c => c is { IsStatic: false, IsImplicitConstructor: false }));
Assert.Equal(expectedConstructors, constructors.ToTestDisplayStrings());
}

private static void VerifyExplicitlyDeclaredInstanceConstructors(INamedTypeSymbol type, params string[] expectedConstructors)
{
var constructors = type.InstanceConstructors;
var members = type.GetMembers(".ctor");
Assert.True(members.SequenceEqual(constructors));
Assert.True(constructors.All(c => c is { IsStatic: false, IsImplicitlyDeclared: false }));
Assert.Equal(expectedConstructors, constructors.ToTestDisplayStrings());
}
}
}

0 comments on commit d765b8b

Please sign in to comment.