Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
4be66fea
R
roslyn
项目概览
lwm1986
/
roslyn
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
roslyn
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
4be66fea
编写于
6月 06, 2020
作者:
C
Charles Stoner
提交者:
GitHub
6月 06, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Misc. changes following recent records PR (#44912)
上级
7adb2a76
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
139 addition
and
55 deletion
+139
-55
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordClone.cs
...ble/Symbols/Synthesized/Records/SynthesizedRecordClone.cs
+1
-3
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordEqualityContractProperty.cs
...ized/Records/SynthesizedRecordEqualityContractProperty.cs
+2
-1
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordEquals.cs
...le/Symbols/Synthesized/Records/SynthesizedRecordEquals.cs
+11
-16
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordGetHashCode.cs
...mbols/Synthesized/Records/SynthesizedRecordGetHashCode.cs
+1
-1
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordObjEquals.cs
...Symbols/Synthesized/Records/SynthesizedRecordObjEquals.cs
+1
-1
src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
+123
-33
未找到文件。
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordClone.cs
浏览文件 @
4be66fea
// Licensed to the .NET Foundation under one or more agreements.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
...
...
@@ -9,8 +9,6 @@
using
System.Collections.Immutable
;
using
System.Reflection
;
using
Microsoft.Cci
;
using
Microsoft.CodeAnalysis.CSharp.Emit
;
using
Microsoft.CodeAnalysis.PooledObjects
;
using
Roslyn.Utilities
;
namespace
Microsoft.CodeAnalysis.CSharp.Symbols
...
...
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordEqualityContractProperty.cs
浏览文件 @
4be66fea
...
...
@@ -19,6 +19,7 @@ internal sealed class SynthesizedRecordEqualityContractProperty : PropertySymbol
public
SynthesizedRecordEqualityContractProperty
(
NamedTypeSymbol
containingType
,
bool
isOverride
)
{
ContainingType
=
containingType
;
IsVirtual
=
!
isOverride
;
IsOverride
=
isOverride
;
TypeWithAnnotations
=
TypeWithAnnotations
.
Create
(
containingType
.
DeclaringCompilation
.
GetWellKnownType
(
WellKnownType
.
System_Type
),
NullableAnnotation
.
NotAnnotated
);
GetMethod
=
new
GetAccessorSymbol
(
this
);
...
...
@@ -54,7 +55,7 @@ public SynthesizedRecordEqualityContractProperty(NamedTypeSymbol containingType,
public
override
bool
IsStatic
=>
false
;
public
override
bool
IsVirtual
=>
true
;
public
override
bool
IsVirtual
{
get
;
}
public
override
bool
IsOverride
{
get
;
}
...
...
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordEquals.cs
浏览文件 @
4be66fea
...
...
@@ -7,6 +7,7 @@
using
System
;
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Diagnostics
;
using
System.Reflection
;
using
Microsoft.Cci
;
using
Microsoft.CodeAnalysis.PooledObjects
;
...
...
@@ -35,30 +36,25 @@ internal sealed class SynthesizedRecordEquals : SynthesizedInstanceMethodSymbol
MethodSymbol
?
otherEqualsMethod
,
int
memberOffset
)
{
// If the parameter is a struct type, it should be declared `in`
// and we need to call EnsureIsReadOnlyAttributeExists().
Debug
.
Assert
(!
parameterType
.
IsStructType
());
var
compilation
=
containingType
.
DeclaringCompilation
;
bool
isStruct
=
parameterType
.
IsStructType
();
_equalityContract
=
equalityContract
;
_otherEqualsMethod
=
otherEqualsMethod
;
_memberOffset
=
memberOffset
;
ContainingType
=
containingType
;
IsVirtual
=
!
isOverride
;
IsOverride
=
isOverride
;
Parameters
=
ImmutableArray
.
Create
(
SynthesizedParameterSymbol
.
Create
(
this
,
TypeWithAnnotations
.
Create
(
parameterType
,
nullableAnnotation
:
isStruct
?
NullableAnnotation
.
NotAnnotated
:
NullableAnnotation
.
Annotated
),
TypeWithAnnotations
.
Create
(
parameterType
,
nullableAnnotation
:
NullableAnnotation
.
Annotated
),
ordinal
:
0
,
isStruct
?
RefKind
.
In
:
RefKind
.
None
));
RefKind
.
None
));
ReturnTypeWithAnnotations
=
TypeWithAnnotations
.
Create
(
compilation
.
GetSpecialType
(
SpecialType
.
System_Boolean
));
if
(
isStruct
)
{
// If the record type is a struct, the parameter is marked 'in'
compilation
.
EnsureIsReadOnlyAttributeExists
(
diagnostics
:
null
,
location
:
Location
.
None
,
modifyCompilation
:
true
);
}
}
public
override
string
Name
=>
"Equals"
;
...
...
@@ -106,7 +102,7 @@ public override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotations
public
override
bool
IsStatic
=>
false
;
public
override
bool
IsVirtual
=>
true
;
public
override
bool
IsVirtual
{
get
;
}
public
override
bool
IsOverride
{
get
;
}
...
...
@@ -202,9 +198,8 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState,
// field1 == other.field1 && ... && fieldN == other.fieldN;
// other != null
retExpr
=
other
.
Type
.
IsStructType
()
?
null
:
F
.
ObjectNotEqual
(
other
,
F
.
Null
(
F
.
SpecialType
(
SpecialType
.
System_Object
)));
Debug
.
Assert
(!
other
.
Type
.
IsStructType
());
retExpr
=
F
.
ObjectNotEqual
(
other
,
F
.
Null
(
F
.
SpecialType
(
SpecialType
.
System_Object
)));
// EqualityContract == other.EqualityContract
var
contractsEqual
=
F
.
Binary
(
...
...
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordGetHashCode.cs
浏览文件 @
4be66fea
...
...
@@ -73,7 +73,7 @@ public override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotations
public
override
bool
IsStatic
=>
false
;
public
override
bool
IsVirtual
=>
tru
e
;
public
override
bool
IsVirtual
=>
fals
e
;
public
override
bool
IsOverride
=>
true
;
...
...
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordObjEquals.cs
浏览文件 @
4be66fea
...
...
@@ -80,7 +80,7 @@ public override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotations
public
override
bool
IsStatic
=>
false
;
public
override
bool
IsVirtual
=>
tru
e
;
public
override
bool
IsVirtual
=>
fals
e
;
public
override
bool
IsOverride
=>
true
;
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
浏览文件 @
4be66fea
...
...
@@ -5178,8 +5178,8 @@ public void Equality_04()
}
class Program
{
static B1 NewB1(int p) => new B1 { P = p }; //
PROTOTYPE: Replace with new B1(P)
static B2 NewB2(int p) => new B2 { P = p }; //
PROTOTYPE: Replace with new B2(P)
static B1 NewB1(int p) => new B1 { P = p }; //
Use record base call syntax instead
static B2 NewB2(int p) => new B2 { P = p }; //
Use record base call syntax instead
static void Main()
{
WriteLine(new A().Equals(NewB1(1)));
...
...
@@ -5256,9 +5256,9 @@ record A(int P)
}
class Program
{
static A NewA(int p) => new A { P = p }; //
PROTOTYPE: Replace with new A(P)
static B1 NewB1(int p) => new B1 { P = p }; //
PROTOTYPE: Replace with new B1(P)
static B2 NewB2(int p) => new B2 { P = p }; //
PROTOTYPE: Replace with new B2(P)
static A NewA(int p) => new A { P = p }; //
Use record base call syntax instead
static B1 NewB1(int p) => new B1 { P = p }; //
Use record base call syntax instead
static B2 NewB2(int p) => new B2 { P = p }; //
Use record base call syntax instead
static void Main()
{
WriteLine(NewA(1).Equals(NewB1(1)));
...
...
@@ -5508,32 +5508,38 @@ .maxstack 2
IL_0007: ret
}"
);
verify
Method
(
comp
.
GetMember
<
MethodSymbol
>(
"A.get_EqualityContract"
),
isOverride
:
false
);
verify
Method
(
comp
.
GetMember
<
MethodSymbol
>(
"B.get_EqualityContract"
),
isOverride
:
true
);
verify
Method
(
comp
.
GetMember
<
MethodSymbol
>(
"C.get_EqualityContract"
),
isOverride
:
true
);
VerifyVirtual
Method
(
comp
.
GetMember
<
MethodSymbol
>(
"A.get_EqualityContract"
),
isOverride
:
false
);
VerifyVirtual
Method
(
comp
.
GetMember
<
MethodSymbol
>(
"B.get_EqualityContract"
),
isOverride
:
true
);
VerifyVirtual
Method
(
comp
.
GetMember
<
MethodSymbol
>(
"C.get_EqualityContract"
),
isOverride
:
true
);
verifyMethods
(
comp
.
GetMembers
(
"A.Equals"
),
(
"System.Boolean A.Equals(A? )"
,
false
),
(
"System.Boolean A.Equals(System.Object? )"
,
true
));
verifyMethods
(
comp
.
GetMembers
(
"B.Equals"
),
(
"System.Boolean B.Equals(B? )"
,
false
),
(
"System.Boolean B.Equals(A? )"
,
true
),
(
"System.Boolean B.Equals(System.Object? )"
,
true
));
verifyMethods
(
comp
.
GetMembers
(
"C.Equals"
),
(
"System.Boolean C.Equals(C? )"
,
false
),
(
"System.Boolean C.Equals(B? )"
,
true
),
(
"System.Boolean C.Equals(A? )"
,
true
),
(
"System.Boolean C.Equals(System.Object? )"
,
true
));
// Should include <>Clone.
static
void
verifyMethods
(
ImmutableArray
<
Symbol
>
members
,
params
(
string
,
bool
)[]
values
)
{
Assert
.
Equal
(
members
.
Length
,
values
.
Length
);
for
(
int
i
=
0
;
i
<
members
.
Length
;
i
++)
{
var
method
=
(
MethodSymbol
)
members
[
i
];
(
string
name
,
bool
isOverride
)
=
values
[
i
];
Assert
.
Equal
(
name
,
method
.
ToTestDisplayString
(
includeNonNullable
:
true
));
verifyMethod
(
method
,
isOverride
);
}
}
VerifyVirtualMethod
(
comp
.
GetMember
<
MethodSymbol
>(
"A.GetHashCode"
),
isOverride
:
true
);
VerifyVirtualMethod
(
comp
.
GetMember
<
MethodSymbol
>(
"B.GetHashCode"
),
isOverride
:
true
);
VerifyVirtualMethod
(
comp
.
GetMember
<
MethodSymbol
>(
"C.GetHashCode"
),
isOverride
:
true
);
static
void
verifyMethod
(
MethodSymbol
method
,
bool
isOverride
)
VerifyVirtualMethods
(
comp
.
GetMembers
(
"A.Equals"
),
(
"System.Boolean A.Equals(A? )"
,
false
),
(
"System.Boolean A.Equals(System.Object? )"
,
true
));
VerifyVirtualMethods
(
comp
.
GetMembers
(
"B.Equals"
),
(
"System.Boolean B.Equals(B? )"
,
false
),
(
"System.Boolean B.Equals(A? )"
,
true
),
(
"System.Boolean B.Equals(System.Object? )"
,
true
));
VerifyVirtualMethods
(
comp
.
GetMembers
(
"C.Equals"
),
(
"System.Boolean C.Equals(C? )"
,
false
),
(
"System.Boolean C.Equals(B? )"
,
true
),
(
"System.Boolean C.Equals(A? )"
,
true
),
(
"System.Boolean C.Equals(System.Object? )"
,
true
));
}
private
static
void
VerifyVirtualMethod
(
MethodSymbol
method
,
bool
isOverride
)
{
Assert
.
Equal
(!
isOverride
,
method
.
IsVirtual
);
Assert
.
Equal
(
isOverride
,
method
.
IsOverride
);
Assert
.
True
(
method
.
IsMetadataVirtual
());
Assert
.
Equal
(!
isOverride
,
method
.
IsMetadataNewSlot
());
}
private
static
void
VerifyVirtualMethods
(
ImmutableArray
<
Symbol
>
members
,
params
(
string
displayString
,
bool
isOverride
)[]
values
)
{
Assert
.
Equal
(
members
.
Length
,
values
.
Length
);
for
(
int
i
=
0
;
i
<
members
.
Length
;
i
++)
{
Assert
.
True
(
method
.
IsVirtual
)
;
Assert
.
Equal
(
isOverride
,
method
.
IsOverride
)
;
Assert
.
True
(
method
.
IsMetadataVirtual
(
));
Assert
.
Equal
(!
isOverride
,
method
.
IsMetadataNewSlot
()
);
var
method
=
(
MethodSymbol
)
members
[
i
]
;
(
string
displayString
,
bool
isOverride
)
=
values
[
i
]
;
Assert
.
Equal
(
displayString
,
method
.
ToTestDisplayString
(
includeNonNullable
:
true
));
VerifyVirtualMethod
(
method
,
isOverride
);
}
}
...
...
@@ -5566,7 +5572,7 @@ record A(int X)
}
class Program
{
static A NewA(int x) => new A { X = x }; //
PROTOTYPE: Replace with new A(X), etc.
static A NewA(int x) => new A { X = x }; //
Use record base call syntax instead
static B NewB(int x, int y) => new B { X = x, Y = y };
static C NewC(int x, int y, int z) => new C { X = x, Y = y, Z = z };
static void Main()
...
...
@@ -5693,7 +5699,7 @@ record A(int X)
}
class Program
{
static A NewA(int x) => new A { X = x }; //
PROTOTYPE: Replace with new A(X), etc.
static A NewA(int x) => new A { X = x }; //
Use record base call syntax instead
static B NewB(int x, int y) => new B { X = x, Y = y };
static C NewC(int x, int y, int z) => new C { X = x, Y = y, Z = z };
static void Main()
...
...
@@ -5962,14 +5968,14 @@ public void Equality_15()
record B1 : A
{
public B1(int p) { P = p; }
public int P { get; set;
}
public int P { get; set; }
protected override Type EqualityContract => typeof(A);
public virtual bool Equals(B1 o) => base.Equals((A)o);
}
record B2 : A
{
public B2(int p) { P = p; }
public int P { get; set;
}
public int P { get; set; }
protected override Type EqualityContract => typeof(B2);
public virtual bool Equals(B2 o) => base.Equals((A)o);
}
...
...
@@ -5997,7 +6003,7 @@ public void Equality_16()
record B1 : A
{
public B1(int p) { P = p; }
public int P { get; set;
}
public int P { get; set; }
protected override Type EqualityContract => typeof(string);
public override bool Equals(A a) => base.Equals(a);
public virtual bool Equals(B1 b) => base.Equals((A)b);
...
...
@@ -6005,7 +6011,7 @@ public void Equality_16()
record B2 : A
{
public B2(int p) { P = p; }
public int P { get; set;
}
public int P { get; set; }
protected override Type EqualityContract => typeof(string);
public override bool Equals(A a) => base.Equals(a);
public virtual bool Equals(B2 b) => base.Equals((A)b);
...
...
@@ -6086,5 +6092,89 @@ static void Main()
};
AssertEx
.
Equal
(
expectedMembers
,
actualMembers
);
}
[
Theory
]
[
InlineData
(
false
)]
[
InlineData
(
true
)]
public
void
Equality_18
(
bool
useCompilationReference
)
{
var
sourceA
=
@"public record A;"
;
var
comp
=
CreateCompilation
(
sourceA
);
VerifyVirtualMethod
(
comp
.
GetMember
<
MethodSymbol
>(
"A.get_EqualityContract"
),
isOverride
:
false
);
VerifyVirtualMethods
(
comp
.
GetMembers
(
"A.Equals"
),
(
"System.Boolean A.Equals(A? )"
,
false
),
(
"System.Boolean A.Equals(System.Object? )"
,
true
));
var
refA
=
useCompilationReference
?
comp
.
ToMetadataReference
()
:
comp
.
EmitToImageReference
();
var
sourceB
=
@"record B : A;"
;
comp
=
CreateCompilation
(
sourceB
,
references
:
new
[]
{
refA
},
parseOptions
:
TestOptions
.
RegularPreview
);
comp
.
VerifyDiagnostics
();
VerifyVirtualMethod
(
comp
.
GetMember
<
MethodSymbol
>(
"B.get_EqualityContract"
),
isOverride
:
true
);
VerifyVirtualMethods
(
comp
.
GetMembers
(
"B.Equals"
),
(
"System.Boolean B.Equals(B? )"
,
false
),
(
"System.Boolean B.Equals(A? )"
,
true
),
(
"System.Boolean B.Equals(System.Object? )"
,
true
));
}
[
Fact
]
public
void
Equality_19
()
{
var
source
=
@"using static System.Console;
record A<T>;
record B : A<int>;
class Program
{
static void Main()
{
WriteLine(new A<int>().Equals(new A<int>()));
WriteLine(new A<int>().Equals(new B()));
WriteLine(new B().Equals(new A<int>()));
WriteLine(new B().Equals(new B()));
WriteLine(((A<int>)new B()).Equals(new A<int>()));
WriteLine(((A<int>)new B()).Equals(new B()));
WriteLine(new B().Equals((A<int>)new B()));
}
}"
;
var
comp
=
CreateCompilation
(
new
[]
{
source
,
IsExternalInitTypeDefinition
},
parseOptions
:
TestOptions
.
RegularPreview
,
options
:
TestOptions
.
ReleaseExe
);
comp
.
VerifyDiagnostics
();
var
verifier
=
CompileAndVerify
(
comp
,
expectedOutput
:
@"True
False
False
True
False
True
True"
);
verifier
.
VerifyIL
(
"A<T>.Equals(A<T>)"
,
@"{
// Code size 20 (0x14)
.maxstack 2
IL_0000: ldarg.1
IL_0001: brfalse.s IL_0012
IL_0003: ldarg.0
IL_0004: callvirt ""System.Type A<T>.EqualityContract.get""
IL_0009: ldarg.1
IL_000a: callvirt ""System.Type A<T>.EqualityContract.get""
IL_000f: ceq
IL_0011: ret
IL_0012: ldc.i4.0
IL_0013: ret
}"
);
verifier
.
VerifyIL
(
"B.Equals(A<int>)"
,
@"{
// Code size 13 (0xd)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: isinst ""B""
IL_0007: callvirt ""bool B.Equals(B)""
IL_000c: ret
}"
);
verifier
.
VerifyIL
(
"B.Equals(B)"
,
@"{
// Code size 8 (0x8)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: call ""bool A<int>.Equals(A<int>)""
IL_0007: ret
}"
);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录