提交 43267174 编写于 作者: V VSadov

New T() should call Activator.CreateInstance unconditionally.

This is consistent with behavior of "new" when used with structs in general - we should call public parameterless constructor if present, which Activator.CreateInstance does.
It is also consistent with VB and F#

***NO_CI***
 (changeset 1330480)
上级 6b074424
......@@ -150,18 +150,14 @@ public override BoundNode VisitNewT(BoundNewT node)
private BoundExpression MakeNewT(CSharpSyntaxNode syntax, TypeParameterSymbol typeParameter)
{
// How "new T()" is rewritten depends on whether T is known to be a value
// type, a reference type, or neither (see OperatorRewriter::VisitNEWTYVAR).
if (typeParameter.IsValueType)
{
// "new T()" rewritten as: "default(T)".
return new BoundDefaultOperator(syntax, type: typeParameter);
}
// For types not known to be value types, "new T()" requires
// Activator.CreateInstance<T>().
// "new T()" is rewritten as: "Activator.CreateInstance<T>()".
// NOTE: DIFFERENCE FROM DEV12
// Dev12 tried to statically optimize this and would emit default(T) if T happens to be struct
// However semantics of "new" in C# requires that parameterless constructor be called
// if struct defines one.
// Since we cannot know if T has a parameterless constructor statically,
// we must call Activator.CreateInstance unconditionally.
MethodSymbol method;
if (!this.TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Activator__CreateInstance_T, out method))
......@@ -186,31 +182,7 @@ private BoundExpression MakeNewT(CSharpSyntaxNode syntax, TypeParameterSymbol ty
resultKind: LookupResultKind.Viable,
type: typeParameter);
if (typeParameter.IsReferenceType)
{
// "new T()" is rewritten as: "Activator.CreateInstance<T>()".
return createInstanceCall;
}
else
{
// "new T()" is rewritten as: "(null == (object)default(T)) ? Activator.CreateInstance<T>() : default(T)".
var defaultT = new BoundDefaultOperator(syntax, type: typeParameter);
return new BoundConditionalOperator(
syntax,
MakeNullCheck(
syntax: syntax,
rewrittenExpr: MakeConversion(
syntax: syntax,
rewrittenOperand: defaultT,
conversionKind: ConversionKind.Boxing,
rewrittenType: this.compilation.GetSpecialType(SpecialType.System_Object),
@checked: false),
operatorKind: BinaryOperatorKind.Equal),
createInstanceCall,
defaultT,
constantValueOpt: null,
type: typeParameter);
}
return createInstanceCall;
}
public override BoundNode VisitNoPiaObjectCreationExpression(BoundNoPiaObjectCreationExpression node)
......
......@@ -190,32 +190,22 @@ struct S : I
var compVerifier = CompileAndVerify(source, emitOptions: EmitOptions.CCI, expectedOutput: expectedOutput);
compVerifier.VerifyIL("MemberInitializerTest.Foo<T>", @"
{
// Code size 63 (0x3f)
// Code size 36 (0x24)
.maxstack 2
.locals init (T V_0, //b
T V_1,
T V_2)
IL_0000: ldloca.s V_2
IL_0002: initobj ""T""
IL_0008: ldloc.2
IL_0009: box ""T""
IL_000e: brfalse.s IL_001b
IL_0010: ldloca.s V_2
IL_0012: initobj ""T""
IL_0018: ldloc.2
IL_0019: br.s IL_0020
IL_001b: call ""T System.Activator.CreateInstance<T>()""
IL_0020: stloc.1
IL_0021: ldloca.s V_1
IL_0023: ldc.i4.1
IL_0024: constrained. ""T""
IL_002a: callvirt ""void I.X.set""
IL_002f: ldloc.1
IL_0030: stloc.0
IL_0031: ldloca.s V_0
IL_0033: constrained. ""T""
IL_0039: callvirt ""byte I.X.get""
IL_003e: ret
T V_1)
IL_0000: call ""T System.Activator.CreateInstance<T>()""
IL_0005: stloc.1
IL_0006: ldloca.s V_1
IL_0008: ldc.i4.1
IL_0009: constrained. ""T""
IL_000f: callvirt ""void I.X.set""
IL_0014: ldloc.1
IL_0015: stloc.0
IL_0016: ldloca.s V_0
IL_0018: constrained. ""T""
IL_001e: callvirt ""byte I.X.get""
IL_0023: ret
}");
}
......@@ -253,38 +243,28 @@ struct S : I
var compVerifier = CompileAndVerify(source, emitOptions: EmitOptions.CCI, expectedOutput: expectedOutput);
compVerifier.VerifyIL("MemberInitializerTest.Foo<T>", @"
{
// Code size 78 (0x4e)
// Code size 51 (0x33)
.maxstack 6
.locals init (T V_0, //b
T V_1,
T V_2)
IL_0000: ldloca.s V_2
IL_0002: initobj ""T""
IL_0008: ldloc.2
IL_0009: box ""T""
IL_000e: brfalse.s IL_001b
IL_0010: ldloca.s V_2
IL_0012: initobj ""T""
IL_0018: ldloc.2
IL_0019: br.s IL_0020
IL_001b: call ""T System.Activator.CreateInstance<T>()""
IL_0020: stloc.1
IL_0021: ldloca.s V_1
IL_0023: ldc.i4.s 11
IL_0025: ldc.i4.0
IL_0026: ldc.i4.0
IL_0027: ldc.i4.0
IL_0028: ldc.i4.1
IL_0029: newobj ""decimal..ctor(int, int, int, bool, byte)""
IL_002e: newobj ""decimal?..ctor(decimal)""
IL_0033: constrained. ""T""
IL_0039: callvirt ""void I.X.set""
IL_003e: ldloc.1
IL_003f: stloc.0
IL_0040: ldloca.s V_0
IL_0042: constrained. ""T""
IL_0048: callvirt ""decimal? I.X.get""
IL_004d: ret
T V_1)
IL_0000: call ""T System.Activator.CreateInstance<T>()""
IL_0005: stloc.1
IL_0006: ldloca.s V_1
IL_0008: ldc.i4.s 11
IL_000a: ldc.i4.0
IL_000b: ldc.i4.0
IL_000c: ldc.i4.0
IL_000d: ldc.i4.1
IL_000e: newobj ""decimal..ctor(int, int, int, bool, byte)""
IL_0013: newobj ""decimal?..ctor(decimal)""
IL_0018: constrained. ""T""
IL_001e: callvirt ""void I.X.set""
IL_0023: ldloc.1
IL_0024: stloc.0
IL_0025: ldloca.s V_0
IL_0027: constrained. ""T""
IL_002d: callvirt ""decimal? I.X.get""
IL_0032: ret
}");
}
......
......@@ -1285,21 +1285,12 @@ static void Main()
C
S");
compilation.VerifyIL("C.F1<T>()",
@"{
// Code size 32 (0x20)
@"
{
// Code size 6 (0x6)
.maxstack 1
.locals init (T V_0)
IL_0000: ldloca.s V_0
IL_0002: initobj ""T""
IL_0008: ldloc.0
IL_0009: box ""T""
IL_000e: brfalse.s IL_001a
IL_0010: ldloca.s V_0
IL_0012: initobj ""T""
IL_0018: ldloc.0
IL_0019: ret
IL_001a: call ""T System.Activator.CreateInstance<T>()""
IL_001f: ret
IL_0000: call ""T System.Activator.CreateInstance<T>()""
IL_0005: ret
}");
compilation.VerifyIL("C.F2<T>()",
@"{
......@@ -1309,14 +1300,12 @@ .maxstack 1
IL_0005: ret
}");
compilation.VerifyIL("C.F3<T>()",
@"{
// Code size 10 (0xa)
@"
{
// Code size 6 (0x6)
.maxstack 1
.locals init (T V_0)
IL_0000: ldloca.s V_0
IL_0002: initobj ""T""
IL_0008: ldloc.0
IL_0009: ret
IL_0000: call ""T System.Activator.CreateInstance<T>()""
IL_0005: ret
}");
}
......@@ -1348,24 +1337,21 @@ class C
}";
var compilation = CompileAndVerify(source);
compilation.VerifyIL("C.M<T, U, V>()",
@"{
// Code size 41 (0x29)
@"
{
// Code size 31 (0x1f)
.maxstack 1
.locals init (U V_0)
IL_0000: newobj ""A..ctor()""
IL_0005: pop
IL_0006: newobj ""B..ctor()""
IL_000b: pop
IL_000c: ldloca.s V_0
IL_000e: initobj ""U""
IL_0014: ldloc.0
IL_0015: box ""U""
IL_001a: brtrue.s IL_0022
IL_001c: call ""U System.Activator.CreateInstance<U>()""
IL_0021: pop
IL_0022: call ""V System.Activator.CreateInstance<V>()""
IL_0027: pop
IL_0028: ret
IL_000c: call ""T System.Activator.CreateInstance<T>()""
IL_0011: pop
IL_0012: call ""U System.Activator.CreateInstance<U>()""
IL_0017: pop
IL_0018: call ""V System.Activator.CreateInstance<V>()""
IL_001d: pop
IL_001e: ret
}");
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册