Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
9b82fcd1
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,发现更多精彩内容 >>
未验证
提交
9b82fcd1
编写于
6月 05, 2020
作者:
C
Charles Stoner
提交者:
GitHub
6月 05, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Records: Support EqualityContract in Equals (#44882)
上级
c9adb9f7
变更
12
展开全部
隐藏空白更改
内联
并排
Showing
12 changed file
with
1814 addition
and
263 deletion
+1814
-263
src/Compilers/CSharp/Portable/Compiler/MethodBodySynthesizer.Lowered.cs
...CSharp/Portable/Compiler/MethodBodySynthesizer.Lowered.cs
+4
-5
src/Compilers/CSharp/Portable/Symbols/LexicalSortKey.cs
src/Compilers/CSharp/Portable/Symbols/LexicalSortKey.cs
+3
-12
src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs
...rp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs
+80
-6
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordCopyCtor.cs
.../Symbols/Synthesized/Records/SynthesizedRecordCopyCtor.cs
+6
-10
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordEqualityContractProperty.cs
...ized/Records/SynthesizedRecordEqualityContractProperty.cs
+182
-0
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordEquals.cs
...le/Symbols/Synthesized/Records/SynthesizedRecordEquals.cs
+138
-46
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordGetHashCode.cs
...mbols/Synthesized/Records/SynthesizedRecordGetHashCode.cs
+5
-3
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordObjEquals.cs
...Symbols/Synthesized/Records/SynthesizedRecordObjEquals.cs
+9
-10
src/Compilers/CSharp/Test/Semantic/Semantics/InitOnlyMemberTests.cs
...ers/CSharp/Test/Semantic/Semantics/InitOnlyMemberTests.cs
+6
-4
src/Compilers/CSharp/Test/Semantic/Semantics/LookupPositionTests.cs
...ers/CSharp/Test/Semantic/Semantics/LookupPositionTests.cs
+14
-2
src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
+1202
-32
src/Compilers/CSharp/Test/Symbol/Symbols/Source/RecordTests.cs
...ompilers/CSharp/Test/Symbol/Symbols/Source/RecordTests.cs
+165
-133
未找到文件。
src/Compilers/CSharp/Portable/Compiler/MethodBodySynthesizer.Lowered.cs
浏览文件 @
9b82fcd1
...
...
@@ -4,7 +4,6 @@
#
nullable
enable
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Diagnostics
;
using
Microsoft.CodeAnalysis.PooledObjects
;
...
...
@@ -249,18 +248,18 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState,
/// Contains methods related to synthesizing bound nodes in lowered form
/// that does not need any processing before passing to codegen
/// </summary>
internal
static
partial
class
MethodBodySynthesizer
internal
static
class
MethodBodySynthesizer
{
/// <summary>
/// Given a set of fields, produce an expression that is true when all of the given fields on
/// `this` are equal to the fields on <paramref name="otherReceiver" /> according to the
/// default EqualityComparer.
/// </summary>
public
static
BoundExpression
GenerateFieldEquals
<
TList
>
(
public
static
BoundExpression
GenerateFieldEquals
(
BoundExpression
?
initialExpression
,
BoundExpression
otherReceiver
,
TList
fields
,
SyntheticBoundNodeFactory
F
)
where
TList
:
IReadOnlyList
<
FieldSymbol
>
ArrayBuilder
<
FieldSymbol
>
fields
,
SyntheticBoundNodeFactory
F
)
{
Debug
.
Assert
(
fields
.
Count
>
0
);
...
...
src/Compilers/CSharp/Portable/Symbols/LexicalSortKey.cs
浏览文件 @
9b82fcd1
...
...
@@ -2,20 +2,15 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using
System
;
using
System.Collections.Generic
;
using
System.Diagnostics
;
using
System.Threading
;
using
Microsoft.CodeAnalysis.CSharp.Symbols
;
using
Microsoft.CodeAnalysis.CSharp.Syntax
;
using
Microsoft.CodeAnalysis.Text
;
namespace
Microsoft.CodeAnalysis.CSharp.Symbols
{
/// <summary>
/// A structure used to lexically order symbols. For performance, it's important that this be
/// a STRUCTURE, and be able to be returned from a symbol without doing any additional allocations (even
/// if nothing is cached yet
.)
/// if nothing is cached yet
).
/// </summary>
internal
struct
LexicalSortKey
{
...
...
@@ -43,18 +38,14 @@ public int Position
public
static
readonly
LexicalSortKey
NotInitialized
=
new
LexicalSortKey
()
{
_treeOrdinal
=
-
1
,
_position
=
-
1
};
// Put Record Equals right before synthesized constructors.
public
static
LexicalSortKey
SynthesizedRecordEquals
=>
new
LexicalSortKey
()
{
_treeOrdinal
=
int
.
MaxValue
,
_position
=
int
.
MaxValue
-
5
};
public
static
LexicalSortKey
SynthesizedRecordObjEquals
=>
new
LexicalSortKey
()
{
_treeOrdinal
=
int
.
MaxValue
,
_position
=
int
.
MaxValue
-
4
};
// Put other synthesized members right before synthesized constructors.
public
static
LexicalSortKey
GetSynthesizedMemberKey
(
int
offset
)
=>
new
LexicalSortKey
()
{
_treeOrdinal
=
int
.
MaxValue
,
_position
=
int
.
MaxValue
-
2
-
offset
};
// Dev12 compiler adds synthetic constructors to the child list after adding all other members.
// Methods are emitted in the children order, but synthetic cctors would be deferred
// until later when it is known if they can be optimized or not.
// As a result the last emitted method tokens are synthetic ctor and then synthetic cctor (if not optimized)
// Since it is not too hard, we will try keeping the same order just to be easy on metadata diffing tools and such.
public
static
readonly
LexicalSortKey
SynthesizedRecordCopyCtor
=
new
LexicalSortKey
()
{
_treeOrdinal
=
int
.
MaxValue
,
_position
=
int
.
MaxValue
-
3
};
public
static
readonly
LexicalSortKey
SynthesizedRecordCtor
=
new
LexicalSortKey
()
{
_treeOrdinal
=
int
.
MaxValue
,
_position
=
int
.
MaxValue
-
2
};
public
static
readonly
LexicalSortKey
SynthesizedCtor
=
new
LexicalSortKey
()
{
_treeOrdinal
=
int
.
MaxValue
,
_position
=
int
.
MaxValue
-
1
};
public
static
readonly
LexicalSortKey
SynthesizedCCtor
=
new
LexicalSortKey
()
{
_treeOrdinal
=
int
.
MaxValue
,
_position
=
int
.
MaxValue
};
...
...
src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs
浏览文件 @
9b82fcd1
...
...
@@ -2989,10 +2989,16 @@ private void AddSynthesizedRecordMembersIfNecessary(MembersAndInitializersBuilde
addCopyCtor
();
addCloneMethod
();
var
thisEquals
=
addThisEquals
();
PropertySymbol
equalityContract
=
addEqualityContract
();
var
otherEqualsMethods
=
ArrayBuilder
<
MethodSymbol
>.
GetInstance
();
getOtherEquals
(
otherEqualsMethods
,
equalityContract
);
var
thisEquals
=
addThisEquals
(
equalityContract
,
otherEqualsMethod
:
otherEqualsMethods
.
Count
==
0
?
null
:
otherEqualsMethods
[
0
]);
addOtherEquals
(
otherEqualsMethods
,
equalityContract
,
thisEquals
);
addObjectEquals
(
thisEquals
);
addHashCode
();
otherEqualsMethods
.
Free
();
memberSignatures
.
Free
();
return
;
...
...
@@ -3015,7 +3021,7 @@ SynthesizedRecordConstructor addCtor(RecordDeclarationSyntax declWithParameters)
void
addCopyCtor
()
{
var
ctor
=
new
SynthesizedRecordCopyCtor
(
this
,
diagnostics
);
var
ctor
=
new
SynthesizedRecordCopyCtor
(
this
,
memberOffset
:
members
.
Count
);
if
(!
memberSignatures
.
ContainsKey
(
ctor
))
{
members
.
Add
(
ctor
);
...
...
@@ -3087,7 +3093,7 @@ static bool hidesInheritedMember(Symbol symbol, NamedTypeSymbol type)
void
addObjectEquals
(
MethodSymbol
thisEquals
)
{
var
objEquals
=
new
SynthesizedRecordObjEquals
(
this
,
thisEquals
);
var
objEquals
=
new
SynthesizedRecordObjEquals
(
this
,
thisEquals
,
memberOffset
:
members
.
Count
);
if
(!
memberSignatures
.
ContainsKey
(
objEquals
))
{
// https://github.com/dotnet/roslyn/issues/44617: Don't add if the overridden method is sealed
...
...
@@ -3097,7 +3103,7 @@ void addObjectEquals(MethodSymbol thisEquals)
void
addHashCode
()
{
var
hashCode
=
new
SynthesizedRecordGetHashCode
(
this
);
var
hashCode
=
new
SynthesizedRecordGetHashCode
(
this
,
memberOffset
:
members
.
Count
);
if
(!
memberSignatures
.
ContainsKey
(
hashCode
))
{
// https://github.com/dotnet/roslyn/issues/44617: Don't add if the overridden method is sealed
...
...
@@ -3105,9 +3111,35 @@ void addHashCode()
}
}
MethodSymbol
addThisEquals
(
)
static
PropertySymbol
?
getInheritedEqualityContract
(
NamedTypeSymbol
type
)
{
var
thisEquals
=
new
SynthesizedRecordEquals
(
this
);
while
((
type
=
type
.
BaseTypeNoUseSiteDiagnostics
)
is
object
)
{
var
members
=
type
.
GetMembers
(
SynthesizedRecordEqualityContractProperty
.
PropertyName
);
// https://github.com/dotnet/roslyn/issues/44903: Check explicit member has expected signature.
if
(
members
.
FirstOrDefault
(
m
=>
m
is
PropertySymbol
property
&&
property
.
ParameterCount
==
0
)
is
PropertySymbol
property
)
{
return
property
;
}
}
return
null
;
}
PropertySymbol
addEqualityContract
()
{
var
property
=
new
SynthesizedRecordEqualityContractProperty
(
this
,
isOverride
:
getInheritedEqualityContract
(
this
)
is
object
);
// https://github.com/dotnet/roslyn/issues/44903: Check explicit member has expected signature.
if
(!
memberSignatures
.
ContainsKey
(
property
))
{
members
.
Add
(
property
);
members
.
Add
(
property
.
GetMethod
);
}
return
property
;
}
MethodSymbol
addThisEquals
(
PropertySymbol
equalityContract
,
MethodSymbol
?
otherEqualsMethod
)
{
var
thisEquals
=
new
SynthesizedRecordEquals
(
this
,
parameterType
:
this
,
isOverride
:
false
,
equalityContract
,
otherEqualsMethod
,
memberOffset
:
members
.
Count
);
if
(!
memberSignatures
.
TryGetValue
(
thisEquals
,
out
var
existing
))
{
members
.
Add
(
thisEquals
);
...
...
@@ -3115,6 +3147,48 @@ MethodSymbol addThisEquals()
}
return
(
MethodSymbol
)
existing
;
}
static
void
getOtherEquals
(
ArrayBuilder
<
MethodSymbol
>
otherEqualsMethods
,
PropertySymbol
equalityContract
)
{
while
((
equalityContract
=
equalityContract
.
OverriddenProperty
)
is
object
)
{
var
member
=
equalityContract
.
ContainingType
.
GetMembers
(
"Equals"
).
FirstOrDefault
(
m
=>
{
if
(
m
is
MethodSymbol
method
)
{
var
parameters
=
method
.
Parameters
;
if
(
parameters
.
Length
==
1
&&
parameters
[
0
].
Type
.
Equals
(
m
.
ContainingType
,
TypeCompareKind
.
AllIgnoreOptions
))
{
return
true
;
}
}
return
false
;
});
// https://github.com/dotnet/roslyn/issues/44903: Check explicit member has expected signature.
if
(
member
is
MethodSymbol
method
)
{
otherEqualsMethods
.
Add
(
method
);
}
}
}
void
addOtherEquals
(
ArrayBuilder
<
MethodSymbol
>
otherEqualsMethods
,
PropertySymbol
equalityContract
,
MethodSymbol
thisEquals
)
{
foreach
(
var
otherEqualsMethod
in
otherEqualsMethods
)
{
var
method
=
new
SynthesizedRecordEquals
(
this
,
parameterType
:
otherEqualsMethod
.
Parameters
[
0
].
Type
,
isOverride
:
true
,
equalityContract
,
otherEqualsMethod
:
thisEquals
,
memberOffset
:
members
.
Count
);
if
(!
memberSignatures
.
ContainsKey
(
method
))
{
members
.
Add
(
method
);
}
}
}
}
private
void
AddSynthesizedConstructorsIfNecessary
(
ArrayBuilder
<
Symbol
>
members
,
ArrayBuilder
<
ArrayBuilder
<
FieldOrPropertyInitializer
.
Builder
>>
staticInitializers
,
DiagnosticBag
diagnostics
)
...
...
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordCopyCtor.cs
浏览文件 @
9b82fcd1
// 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.
#
nullable
enable
using
System.Collections.Immutable
;
using
System.Diagnostics
;
using
Microsoft.CodeAnalysis.CSharp.Syntax
;
using
Microsoft.CodeAnalysis.PooledObjects
;
namespace
Microsoft.CodeAnalysis.CSharp.Symbols
{
internal
sealed
class
SynthesizedRecordCopyCtor
:
SynthesizedInstanceConstructor
{
private
readonly
int
_memberOffset
;
public
SynthesizedRecordCopyCtor
(
SourceMemberContainerTypeSymbol
containingType
,
DiagnosticBag
diagnostics
)
int
memberOffset
)
:
base
(
containingType
)
{
_memberOffset
=
memberOffset
;
Parameters
=
ImmutableArray
.
Create
(
SynthesizedParameterSymbol
.
Create
(
this
,
TypeWithAnnotations
.
Create
(
...
...
@@ -29,12 +30,7 @@ internal sealed class SynthesizedRecordCopyCtor : SynthesizedInstanceConstructor
public
override
ImmutableArray
<
ParameterSymbol
>
Parameters
{
get
;
}
internal
override
LexicalSortKey
GetLexicalSortKey
()
{
// We need a separate sort key because struct records will have two synthesized
// constructors: the record constructor, and the parameterless constructor
return
LexicalSortKey
.
SynthesizedRecordCopyCtor
;
}
internal
override
LexicalSortKey
GetLexicalSortKey
()
=>
LexicalSortKey
.
GetSynthesizedMemberKey
(
_memberOffset
);
internal
override
void
GenerateMethodBodyStatements
(
SyntheticBoundNodeFactory
F
,
ArrayBuilder
<
BoundStatement
>
statements
,
DiagnosticBag
diagnostics
)
{
...
...
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordEqualityContractProperty.cs
0 → 100644
浏览文件 @
9b82fcd1
// 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.
#
nullable
enable
using
System
;
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Reflection
;
using
Microsoft.Cci
;
namespace
Microsoft.CodeAnalysis.CSharp.Symbols
{
internal
sealed
class
SynthesizedRecordEqualityContractProperty
:
PropertySymbol
{
internal
const
string
PropertyName
=
"EqualityContract"
;
public
SynthesizedRecordEqualityContractProperty
(
NamedTypeSymbol
containingType
,
bool
isOverride
)
{
ContainingType
=
containingType
;
IsOverride
=
isOverride
;
TypeWithAnnotations
=
TypeWithAnnotations
.
Create
(
containingType
.
DeclaringCompilation
.
GetWellKnownType
(
WellKnownType
.
System_Type
),
NullableAnnotation
.
NotAnnotated
);
GetMethod
=
new
GetAccessorSymbol
(
this
);
}
public
override
NamedTypeSymbol
ContainingType
{
get
;
}
public
override
MethodSymbol
GetMethod
{
get
;
}
public
override
MethodSymbol
?
SetMethod
=>
null
;
public
override
RefKind
RefKind
=>
RefKind
.
None
;
public
override
TypeWithAnnotations
TypeWithAnnotations
{
get
;
}
public
override
ImmutableArray
<
CustomModifier
>
RefCustomModifiers
=>
ImmutableArray
<
CustomModifier
>.
Empty
;
public
override
ImmutableArray
<
ParameterSymbol
>
Parameters
=>
ImmutableArray
<
ParameterSymbol
>.
Empty
;
public
override
bool
IsIndexer
=>
false
;
public
override
bool
IsImplicitlyDeclared
=>
true
;
public
override
ImmutableArray
<
PropertySymbol
>
ExplicitInterfaceImplementations
=>
ImmutableArray
<
PropertySymbol
>.
Empty
;
public
override
Symbol
ContainingSymbol
=>
ContainingType
;
public
override
ImmutableArray
<
Location
>
Locations
=>
ContainingType
.
Locations
;
public
override
ImmutableArray
<
SyntaxReference
>
DeclaringSyntaxReferences
=>
ImmutableArray
<
SyntaxReference
>.
Empty
;
public
override
Accessibility
DeclaredAccessibility
=>
Accessibility
.
Protected
;
public
override
bool
IsStatic
=>
false
;
public
override
bool
IsVirtual
=>
true
;
public
override
bool
IsOverride
{
get
;
}
public
override
bool
IsAbstract
=>
false
;
public
override
bool
IsSealed
=>
false
;
public
override
bool
IsExtern
=>
false
;
internal
override
bool
HasSpecialName
=>
false
;
internal
override
CallingConvention
CallingConvention
=>
CallingConvention
.
HasThis
;
internal
override
bool
MustCallMethodsDirectly
=>
false
;
internal
override
ObsoleteAttributeData
?
ObsoleteAttributeData
=>
null
;
public
override
string
Name
=>
PropertyName
;
public
override
ImmutableArray
<
CSharpAttributeData
>
GetAttributes
()
=>
ImmutableArray
<
CSharpAttributeData
>.
Empty
;
private
sealed
class
GetAccessorSymbol
:
SynthesizedInstanceMethodSymbol
{
private
readonly
SynthesizedRecordEqualityContractProperty
_property
;
public
GetAccessorSymbol
(
SynthesizedRecordEqualityContractProperty
property
)
{
_property
=
property
;
Name
=
SourcePropertyAccessorSymbol
.
GetAccessorName
(
PropertyName
,
getNotSet
:
true
,
isWinMdOutput
:
false
/* unused for getters */
);
}
public
override
string
Name
{
get
;
}
public
override
MethodKind
MethodKind
=>
MethodKind
.
PropertyGet
;
public
override
int
Arity
=>
0
;
public
override
bool
IsExtensionMethod
=>
false
;
public
override
bool
HidesBaseMethodsByName
=>
false
;
public
override
bool
IsVararg
=>
false
;
public
override
bool
ReturnsVoid
=>
false
;
public
override
bool
IsAsync
=>
false
;
public
override
RefKind
RefKind
=>
RefKind
.
None
;
public
override
TypeWithAnnotations
ReturnTypeWithAnnotations
=>
_property
.
TypeWithAnnotations
;
public
override
FlowAnalysisAnnotations
ReturnTypeFlowAnalysisAnnotations
=>
FlowAnalysisAnnotations
.
None
;
public
override
ImmutableArray
<
TypeWithAnnotations
>
TypeArgumentsWithAnnotations
=>
ImmutableArray
<
TypeWithAnnotations
>.
Empty
;
public
override
ImmutableArray
<
TypeParameterSymbol
>
TypeParameters
=>
ImmutableArray
<
TypeParameterSymbol
>.
Empty
;
public
override
ImmutableArray
<
ParameterSymbol
>
Parameters
=>
_property
.
Parameters
;
public
override
ImmutableArray
<
MethodSymbol
>
ExplicitInterfaceImplementations
=>
ImmutableArray
<
MethodSymbol
>.
Empty
;
public
override
ImmutableArray
<
CustomModifier
>
RefCustomModifiers
=>
_property
.
RefCustomModifiers
;
public
override
Symbol
AssociatedSymbol
=>
_property
;
public
override
Symbol
ContainingSymbol
=>
_property
.
ContainingSymbol
;
public
override
ImmutableArray
<
Location
>
Locations
=>
_property
.
Locations
;
public
override
Accessibility
DeclaredAccessibility
=>
_property
.
DeclaredAccessibility
;
public
override
bool
IsStatic
=>
_property
.
IsStatic
;
public
override
bool
IsVirtual
=>
_property
.
IsVirtual
;
public
override
bool
IsOverride
=>
_property
.
IsOverride
;
public
override
bool
IsAbstract
=>
_property
.
IsAbstract
;
public
override
bool
IsSealed
=>
_property
.
IsSealed
;
public
override
bool
IsExtern
=>
_property
.
IsExtern
;
public
override
ImmutableHashSet
<
string
>
ReturnNotNullIfParameterNotNull
=>
ImmutableHashSet
<
string
>.
Empty
;
internal
override
bool
HasSpecialName
=>
_property
.
HasSpecialName
;
internal
override
MethodImplAttributes
ImplementationAttributes
=>
MethodImplAttributes
.
Managed
;
internal
override
bool
HasDeclarativeSecurity
=>
false
;
internal
override
MarshalPseudoCustomAttributeData
?
ReturnValueMarshallingInformation
=>
null
;
internal
override
bool
RequiresSecurityObject
=>
false
;
internal
override
CallingConvention
CallingConvention
=>
CallingConvention
.
HasThis
;
internal
override
bool
GenerateDebugInfo
=>
false
;
public
override
DllImportData
?
GetDllImportData
()
=>
null
;
internal
override
ImmutableArray
<
string
>
GetAppliedConditionalSymbols
()
=>
ImmutableArray
<
string
>.
Empty
;
internal
override
IEnumerable
<
SecurityAttribute
>
GetSecurityInformation
()
=>
Array
.
Empty
<
SecurityAttribute
>();
internal
override
bool
IsMetadataNewSlot
(
bool
ignoreInterfaceImplementationChanges
=
false
)
=>
!
IsOverride
;
internal
override
bool
IsMetadataVirtual
(
bool
ignoreInterfaceImplementationChanges
=
false
)
=>
true
;
internal
override
bool
SynthesizesLoweredBoundBody
=>
true
;
internal
override
void
GenerateMethodBody
(
TypeCompilationState
compilationState
,
DiagnosticBag
diagnostics
)
{
var
F
=
new
SyntheticBoundNodeFactory
(
this
,
this
.
GetNonNullSyntaxNode
(),
compilationState
,
diagnostics
);
F
.
CurrentFunction
=
this
;
F
.
CloseMethod
(
F
.
Block
(
F
.
Return
(
F
.
Typeof
(
ContainingType
))));
}
}
}
}
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordEquals.cs
浏览文件 @
9b82fcd1
// 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.
...
...
@@ -13,17 +13,48 @@
namespace
Microsoft.CodeAnalysis.CSharp.Symbols
{
/// <summary>
/// A strongly-typed `public bool Equals(T other)` method.
/// There are two types of strongly-typed Equals methods:
/// the strongly-typed virtual method where T is the containing type; and
/// overrides of the strongly-typed virtual methods from base record types.
/// </summary>
internal
sealed
class
SynthesizedRecordEquals
:
SynthesizedInstanceMethodSymbol
{
private
readonly
PropertySymbol
_equalityContract
;
private
readonly
MethodSymbol
?
_otherEqualsMethod
;
private
readonly
int
_memberOffset
;
public
override
NamedTypeSymbol
ContainingType
{
get
;
}
public
SynthesizedRecordEquals
(
NamedTypeSymbol
containingType
)
public
SynthesizedRecordEquals
(
NamedTypeSymbol
containingType
,
TypeSymbol
parameterType
,
bool
isOverride
,
PropertySymbol
equalityContract
,
MethodSymbol
?
otherEqualsMethod
,
int
memberOffset
)
{
var
compilation
=
containingType
.
DeclaringCompilation
;
bool
isStruct
=
parameterType
.
IsStructType
();
_equalityContract
=
equalityContract
;
_otherEqualsMethod
=
otherEqualsMethod
;
_memberOffset
=
memberOffset
;
ContainingType
=
containingType
;
if
(
containingType
.
IsStructType
())
IsOverride
=
isOverride
;
Parameters
=
ImmutableArray
.
Create
(
SynthesizedParameterSymbol
.
Create
(
this
,
TypeWithAnnotations
.
Create
(
parameterType
,
nullableAnnotation
:
isStruct
?
NullableAnnotation
.
NotAnnotated
:
NullableAnnotation
.
Annotated
),
ordinal
:
0
,
isStruct
?
RefKind
.
In
:
RefKind
.
None
));
ReturnTypeWithAnnotations
=
TypeWithAnnotations
.
Create
(
compilation
.
GetSpecialType
(
SpecialType
.
System_Boolean
));
if
(
isStruct
)
{
// If the record type is a struct, the parameter is marked 'in'
co
ntainingType
.
DeclaringCo
mpilation
.
EnsureIsReadOnlyAttributeExists
(
compilation
.
EnsureIsReadOnlyAttributeExists
(
diagnostics
:
null
,
location
:
Location
.
None
,
modifyCompilation
:
true
);
...
...
@@ -48,19 +79,9 @@ public SynthesizedRecordEquals(NamedTypeSymbol containingType)
public
override
RefKind
RefKind
=>
RefKind
.
None
;
public
override
ImmutableArray
<
ParameterSymbol
>
Parameters
=>
ImmutableArray
.
Create
<
ParameterSymbol
>(
SynthesizedParameterSymbol
.
Create
(
this
,
TypeWithAnnotations
.
Create
(
isNullableEnabled
:
true
,
ContainingType
,
isAnnotated
:
true
),
ordinal
:
0
,
ContainingType
.
IsStructType
()
?
RefKind
.
In
:
RefKind
.
None
));
public
override
ImmutableArray
<
ParameterSymbol
>
Parameters
{
get
;
}
public
override
TypeWithAnnotations
ReturnTypeWithAnnotations
=>
TypeWithAnnotations
.
Create
(
isNullableEnabled
:
true
,
ContainingType
.
DeclaringCompilation
.
GetSpecialType
(
SpecialType
.
System_Boolean
));
public
override
TypeWithAnnotations
ReturnTypeWithAnnotations
{
get
;
}
public
override
FlowAnalysisAnnotations
ReturnTypeFlowAnalysisAnnotations
=>
FlowAnalysisAnnotations
.
None
;
...
...
@@ -85,9 +106,9 @@ public override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotations
public
override
bool
IsStatic
=>
false
;
public
override
bool
IsVirtual
=>
fals
e
;
public
override
bool
IsVirtual
=>
tru
e
;
public
override
bool
IsOverride
=>
false
;
public
override
bool
IsOverride
{
get
;
}
public
override
bool
IsAbstract
=>
false
;
...
...
@@ -97,7 +118,7 @@ public override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotations
internal
override
bool
HasSpecialName
=>
false
;
internal
override
LexicalSortKey
GetLexicalSortKey
()
=>
LexicalSortKey
.
SynthesizedRecordEquals
;
internal
override
LexicalSortKey
GetLexicalSortKey
()
=>
LexicalSortKey
.
GetSynthesizedMemberKey
(
_memberOffset
)
;
internal
override
MethodImplAttributes
ImplementationAttributes
=>
MethodImplAttributes
.
Managed
;
...
...
@@ -119,48 +140,119 @@ internal override ImmutableArray<string> GetAppliedConditionalSymbols()
internal
override
IEnumerable
<
SecurityAttribute
>
GetSecurityInformation
()
=>
Array
.
Empty
<
SecurityAttribute
>();
internal
override
bool
IsMetadataNewSlot
(
bool
ignoreInterfaceImplementationChanges
=
false
)
=>
fals
e
;
internal
override
bool
IsMetadataNewSlot
(
bool
ignoreInterfaceImplementationChanges
=
false
)
=>
!
IsOverrid
e
;
internal
override
bool
IsMetadataVirtual
(
bool
ignoreInterfaceImplementationChanges
=
false
)
=>
fals
e
;
internal
override
bool
IsMetadataVirtual
(
bool
ignoreInterfaceImplementationChanges
=
false
)
=>
tru
e
;
internal
override
bool
SynthesizesLoweredBoundBody
=>
true
;
// Consider the following types:
// record A(int X);
// record B(int X, int Y) : A(X);
// record C(int X, int Y, int Z) : B(X, Y);
//
// Each record class defines a strongly-typed Equals method, with derived
// types overriding the methods from base classes:
// class A
// {
// public virtual bool Equals(A other) => other != null && EqualityContract == other.EqualityContract && X == other.X;
// }
// class B : A
// {
// public virtual bool Equals(B other) => base.Equals((A)other) && Y == other.Y;
// public override bool Equals(A other) => Equals(other as B);
// }
// class C : B
// {
// public virtual bool Equals(C other) => base.Equals((B)other) && Z == other.Z;
// public override bool Equals(B other) => Equals(other as C);
// public override bool Equals(A other) => Equals(other as C);
// }
internal
override
void
GenerateMethodBody
(
TypeCompilationState
compilationState
,
DiagnosticBag
diagnostics
)
{
var
F
=
new
SyntheticBoundNodeFactory
(
this
,
ContainingType
.
GetNonNullSyntaxNode
(),
compilationState
,
diagnostics
);
// Compare all of the record properties in this class with the argument properties
// Body:
// {
// return other != null && `comparisons`;
// }
var
other
=
F
.
Parameter
(
Parameters
[
0
]);
BoundExpression
?
retExpr
=
null
;
if
(!
ContainingType
.
IsStructType
())
BoundExpression
?
retExpr
;
if
(
IsOverride
)
{
retExpr
=
F
.
ObjectNotEqual
(
other
,
F
.
Null
(
F
.
SpecialType
(
SpecialType
.
System_Object
)));
// This method is an override of a strongly-typed Equals method from a base record type.
// The definition of the method is as follows, and _otherEqualsMethod
// is the method to delegate to (see B.Equals(A), C.Equals(A), C.Equals(B) above):
//
// override bool Equals(Base other) => Equals(other as Derived);
retExpr
=
F
.
Call
(
F
.
This
(),
_otherEqualsMethod
!,
F
.
As
(
other
,
ContainingType
));
}
var
fields
=
ArrayBuilder
<
FieldSymbol
>.
GetInstance
();
foreach
(
var
f
in
ContainingType
.
GetFieldsToEmit
())
else
{
if
(!
f
.
IsStatic
)
// This method is the strongly-typed Equals method where the parameter type is
// the containing type.
if
(
_otherEqualsMethod
is
null
)
{
fields
.
Add
(
f
);
// There are no base record types.
// The definition of the method is as follows (see A.Equals(A) above):
//
// virtual bool Equals(T other) =>
// other != null &&
// EqualityContract == other.EqualityContract &&
// field1 == other.field1 && ... && fieldN == other.fieldN;
// other != null
retExpr
=
other
.
Type
.
IsStructType
()
?
null
:
F
.
ObjectNotEqual
(
other
,
F
.
Null
(
F
.
SpecialType
(
SpecialType
.
System_Object
)));
// EqualityContract == other.EqualityContract
var
contractsEqual
=
F
.
Binary
(
BinaryOperatorKind
.
ObjectEqual
,
F
.
SpecialType
(
SpecialType
.
System_Boolean
),
F
.
Property
(
F
.
This
(),
_equalityContract
),
F
.
Property
(
other
,
_equalityContract
));
retExpr
=
retExpr
is
null
?
contractsEqual
:
F
.
LogicalAnd
(
retExpr
,
contractsEqual
);
}
else
{
// There are base record types.
// The definition of the method is as follows, and _otherEqualsMethod
// is the corresponding method on the nearest base record type to
// delegate to (see B.Equals(B), C.Equals(C) above):
//
// virtual bool Equals(Derived other) =>
// base.Equals((Base)other) &&
// field1 == other.field1 && ... && fieldN == other.fieldN;
retExpr
=
F
.
Call
(
F
.
Base
(
_otherEqualsMethod
.
ContainingType
),
_otherEqualsMethod
!,
F
.
Convert
(
_otherEqualsMethod
.
Parameters
[
0
].
Type
,
other
));
}
// field1 == other.field1 && ... && fieldN == other.fieldN
// https://github.com/dotnet/roslyn/issues/44895: Should compare fields from non-record base classes.
var
fields
=
ArrayBuilder
<
FieldSymbol
>.
GetInstance
();
foreach
(
var
f
in
ContainingType
.
GetFieldsToEmit
())
{
if
(!
f
.
IsStatic
)
{
fields
.
Add
(
f
);
}
}
if
(
fields
.
Count
>
0
)
{
retExpr
=
MethodBodySynthesizer
.
GenerateFieldEquals
(
retExpr
,
other
,
fields
,
F
);
}
fields
.
Free
();
}
if
(
fields
.
Count
>
0
)
{
retExpr
=
MethodBodySynthesizer
.
GenerateFieldEquals
(
retExpr
,
other
,
fields
,
F
);
}
fields
.
Free
();
F
.
CloseMethod
(
F
.
Block
(
F
.
Return
(
retExpr
)));
}
}
}
\ No newline at end of file
}
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordGetHashCode.cs
浏览文件 @
9b82fcd1
...
...
@@ -14,11 +14,13 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
internal
sealed
class
SynthesizedRecordGetHashCode
:
SynthesizedInstanceMethodSymbol
{
p
ublic
override
NamedTypeSymbol
ContainingType
{
get
;
}
p
rivate
readonly
int
_memberOffset
;
public
override
NamedTypeSymbol
ContainingType
{
get
;
}
public
SynthesizedRecordGetHashCode
(
NamedTypeSymbol
containingType
)
public
SynthesizedRecordGetHashCode
(
NamedTypeSymbol
containingType
,
int
memberOffset
)
{
_memberOffset
=
memberOffset
;
ContainingType
=
containingType
;
}
...
...
@@ -42,7 +44,7 @@ public SynthesizedRecordGetHashCode(NamedTypeSymbol containingType)
public
override
RefKind
RefKind
=>
RefKind
.
None
;
internal
override
LexicalSortKey
GetLexicalSortKey
()
=>
LexicalSortKey
.
SynthesizedRecordObjEquals
;
internal
override
LexicalSortKey
GetLexicalSortKey
()
=>
LexicalSortKey
.
GetSynthesizedMemberKey
(
_memberOffset
)
;
public
override
TypeWithAnnotations
ReturnTypeWithAnnotations
=>
TypeWithAnnotations
.
Create
(
isNullableEnabled
:
true
,
...
...
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordObjEquals.cs
浏览文件 @
9b82fcd1
...
...
@@ -15,23 +15,24 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols
internal
sealed
class
SynthesizedRecordObjEquals
:
SynthesizedInstanceMethodSymbol
{
private
readonly
MethodSymbol
_typedRecordEquals
;
private
readonly
int
_memberOffset
;
public
override
NamedTypeSymbol
ContainingType
{
get
;
}
public
override
ImmutableArray
<
ParameterSymbol
>
Parameters
{
get
;
}
public
SynthesizedRecordObjEquals
(
NamedTypeSymbol
containingType
,
MethodSymbol
typedRecordEquals
)
public
SynthesizedRecordObjEquals
(
NamedTypeSymbol
containingType
,
MethodSymbol
typedRecordEquals
,
int
memberOffset
)
{
var
compilation
=
containingType
.
DeclaringCompilation
;
_typedRecordEquals
=
typedRecordEquals
;
_memberOffset
=
memberOffset
;
ContainingType
=
containingType
;
Parameters
=
ImmutableArray
.
Create
<
ParameterSymbol
>(
SynthesizedParameterSymbol
.
Create
(
this
,
TypeWithAnnotations
.
Create
(
isNullableEnabled
:
true
,
containingType
.
DeclaringCompilation
.
GetSpecialType
(
SpecialType
.
System_Object
),
isAnnotated
:
true
),
TypeWithAnnotations
.
Create
(
compilation
.
GetSpecialType
(
SpecialType
.
System_Object
),
NullableAnnotation
.
Annotated
),
ordinal
:
0
,
RefKind
.
None
));
ReturnTypeWithAnnotations
=
TypeWithAnnotations
.
Create
(
compilation
.
GetSpecialType
(
SpecialType
.
System_Boolean
));
}
public
override
string
Name
=>
"Equals"
;
...
...
@@ -52,11 +53,9 @@ public SynthesizedRecordObjEquals(NamedTypeSymbol containingType, MethodSymbol t
public
override
RefKind
RefKind
=>
RefKind
.
None
;
internal
override
LexicalSortKey
GetLexicalSortKey
()
=>
LexicalSortKey
.
SynthesizedRecordObjEquals
;
internal
override
LexicalSortKey
GetLexicalSortKey
()
=>
LexicalSortKey
.
GetSynthesizedMemberKey
(
_memberOffset
)
;
public
override
TypeWithAnnotations
ReturnTypeWithAnnotations
=>
TypeWithAnnotations
.
Create
(
isNullableEnabled
:
true
,
ContainingType
.
DeclaringCompilation
.
GetSpecialType
(
SpecialType
.
System_Boolean
));
public
override
TypeWithAnnotations
ReturnTypeWithAnnotations
{
get
;
}
public
override
FlowAnalysisAnnotations
ReturnTypeFlowAnalysisAnnotations
=>
FlowAnalysisAnnotations
.
None
;
...
...
@@ -145,7 +144,7 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState,
{
// For classes:
// return this.Equals(param as ContainingType);
expression
=
F
.
InstanceCall
(
F
.
This
(),
"Equals"
,
F
.
As
(
paramAccess
,
ContainingType
));
expression
=
F
.
Call
(
F
.
This
(),
_typedRecordEquals
,
F
.
As
(
paramAccess
,
ContainingType
));
}
F
.
CloseMethod
(
F
.
Block
(
ImmutableArray
.
Create
<
BoundStatement
>(
F
.
Return
(
expression
))));
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/InitOnlyMemberTests.cs
浏览文件 @
9b82fcd1
...
...
@@ -2174,16 +2174,18 @@ public record C(int i)
var
cMembers
=
comp
.
GlobalNamespace
.
GetMember
<
NamedTypeSymbol
>(
"C"
).
GetMembers
();
AssertEx
.
SetEqual
(
new
[]
{
"C C.Clone()"
,
"System.Type C.EqualityContract.get"
,
"System.Type C.EqualityContract { get; }"
,
"C..ctor(System.Int32 i)"
,
"System.Int32 C.<i>k__BackingField"
,
"System.Int32 C.i.get"
,
"void modreq(System.Runtime.CompilerServices.IsExternalInit) C.i.init"
,
"System.Int32 C.i { get; init; }"
,
"void C.M()"
,
"System.Boolean C.Equals(C? )"
,
"System.Boolean C.Equals(System.Object? )"
,
"System.Int32 C.GetHashCode()"
,
"C..ctor(C )"
,
"C..ctor(System.Int32 i)"
},
cMembers
.
ToTestDisplayStrings
());
"System.Boolean C.Equals(System.Object? )"
,
"System.Boolean C.Equals(C? )"
,
"C..ctor(C )"
},
cMembers
.
ToTestDisplayStrings
());
foreach
(
var
member
in
cMembers
)
{
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/LookupPositionTests.cs
浏览文件 @
9b82fcd1
...
...
@@ -6,10 +6,8 @@
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Text
;
using
Microsoft.CodeAnalysis.CSharp.Syntax
;
using
Microsoft.CodeAnalysis.PooledObjects
;
using
Microsoft.CodeAnalysis.Test.Extensions
;
using
Microsoft.CodeAnalysis.Text
;
using
Roslyn.Test.Utilities
;
using
Xunit
;
using
Microsoft.CodeAnalysis.CSharp.Test.Utilities
;
...
...
@@ -49,6 +47,7 @@ record C(int x, int y)
"System.Int32 System.Object.GetHashCode()"
,
"System.Object System.Object.MemberwiseClone()"
,
"System.String System.Object.ToString()"
,
"System.Type C.EqualityContract { get; }"
,
"System.Type System.Object.GetType()"
,
"void System.Object.Finalize()"
),
s_pop
...
...
@@ -83,6 +82,7 @@ public void PositionalRecord2()
"System.Object System.Object.MemberwiseClone()"
,
"void System.Object.Finalize()"
,
"System.String System.Object.ToString()"
,
"System.Type C<T>.EqualityContract { get; }"
,
"System.Type System.Object.GetType()"
),
s_pop
);
...
...
@@ -113,6 +113,7 @@ public void NominalRecord()
"System.Object System.Object.MemberwiseClone()"
,
"void System.Object.Finalize()"
,
"System.String System.Object.ToString()"
,
"System.Type C<T>.EqualityContract { get; }"
,
"System.Type System.Object.GetType()"
,
};
var
expectedNames
=
MakeExpectedSymbols
(
...
...
@@ -1718,6 +1719,7 @@ record C(int X) : Base`(X`)
"System.Int32 X"
,
"System.Object System.Object.MemberwiseClone()"
,
"System.String System.Object.ToString()"
,
"System.Type C.EqualityContract { get; }"
,
"System.Type System.Object.GetType()"
,
"void System.Object.Finalize()"
),
s_pop
,
...
...
@@ -1733,6 +1735,7 @@ record C(int X) : Base`(X`)
"System.Int32 System.Object.GetHashCode()"
,
"System.Object System.Object.MemberwiseClone()"
,
"System.String System.Object.ToString()"
,
"System.Type C.EqualityContract { get; }"
,
"System.Type System.Object.GetType()"
,
"void System.Object.Finalize()"
),
s_pop
...
...
@@ -1765,6 +1768,7 @@ public void RecordBaseArguments_02()
"System.Int32 System.Object.GetHashCode()"
,
"System.Object System.Object.MemberwiseClone()"
,
"System.String System.Object.ToString()"
,
"System.Type C.EqualityContract { get; }"
,
"System.Type System.Object.GetType()"
,
"void System.Object.Finalize()"
),
s_pop
...
...
@@ -1802,6 +1806,7 @@ public void RecordBaseArguments_03()
"System.Int32 System.Object.GetHashCode()"
,
"System.Object System.Object.MemberwiseClone()"
,
"System.String System.Object.ToString()"
,
"System.Type C.EqualityContract { get; }"
,
"System.Type System.Object.GetType()"
,
"void System.Object.Finalize()"
),
s_pop
,
...
...
@@ -1817,6 +1822,7 @@ public void RecordBaseArguments_03()
"System.Int32 System.Object.GetHashCode()"
,
"System.Object System.Object.MemberwiseClone()"
,
"System.String System.Object.ToString()"
,
"System.Type C.EqualityContract { get; }"
,
"System.Type System.Object.GetType()"
,
"void System.Object.Finalize()"
),
s_pop
...
...
@@ -1855,6 +1861,7 @@ public void RecordBaseArguments_04()
"System.Int32 X"
,
"System.Object System.Object.MemberwiseClone()"
,
"System.String System.Object.ToString()"
,
"System.Type C.EqualityContract { get; }"
,
"System.Type System.Object.GetType()"
,
"void System.Object.Finalize()"
),
s_pop
,
...
...
@@ -1870,6 +1877,7 @@ public void RecordBaseArguments_04()
"System.Int32 System.Object.GetHashCode()"
,
"System.Object System.Object.MemberwiseClone()"
,
"System.String System.Object.ToString()"
,
"System.Type C.EqualityContract { get; }"
,
"System.Type System.Object.GetType()"
,
"void System.Object.Finalize()"
),
s_pop
,
...
...
@@ -1885,6 +1893,7 @@ public void RecordBaseArguments_04()
"System.Int32 System.Object.GetHashCode()"
,
"System.Object System.Object.MemberwiseClone()"
,
"System.String System.Object.ToString()"
,
"System.Type C.EqualityContract { get; }"
,
"System.Type System.Object.GetType()"
,
"void System.Object.Finalize()"
),
s_pop
...
...
@@ -1922,6 +1931,7 @@ public void RecordBaseArguments_05()
"System.Int32 System.Object.GetHashCode()"
,
"System.Object System.Object.MemberwiseClone()"
,
"System.String System.Object.ToString()"
,
"System.Type C.EqualityContract { get; }"
,
"System.Type System.Object.GetType()"
,
"void System.Object.Finalize()"
),
s_pop
,
...
...
@@ -1937,6 +1947,7 @@ public void RecordBaseArguments_05()
"System.Int32 X"
,
"System.Object System.Object.MemberwiseClone()"
,
"System.String System.Object.ToString()"
,
"System.Type C.EqualityContract { get; }"
,
"System.Type System.Object.GetType()"
,
"void System.Object.Finalize()"
),
s_pop
,
...
...
@@ -1952,6 +1963,7 @@ public void RecordBaseArguments_05()
"System.Int32 System.Object.GetHashCode()"
,
"System.Object System.Object.MemberwiseClone()"
,
"System.String System.Object.ToString()"
,
"System.Type C.EqualityContract { get; }"
,
"System.Type System.Object.GetType()"
,
"void System.Object.Finalize()"
),
s_pop
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
浏览文件 @
9b82fcd1
此差异已折叠。
点击以展开。
src/Compilers/CSharp/Test/Symbol/Symbols/Source/RecordTests.cs
浏览文件 @
9b82fcd1
...
...
@@ -313,31 +313,36 @@ .maxstack 2
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: isinst ""C""
IL_0007: call
""bool C.Equals(C)""
IL_0007: call
virt
""bool C.Equals(C)""
IL_000c: ret
}"
);
verifier
.
VerifyIL
(
"C.Equals(C)"
,
@"
{
// Code size
52 (0x34
)
// Code size
66 (0x42
)
.maxstack 3
IL_0000: ldarg.1
IL_0001: brfalse.s IL_0032
IL_0003: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_0008: ldarg.0
IL_0009: ldfld ""int C.<X>k__BackingField""
IL_000e: ldarg.1
IL_000f: ldfld ""int C.<X>k__BackingField""
IL_0014: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_0019: brfalse.s IL_0032
IL_001b: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_0020: ldarg.0
IL_0021: ldfld ""int C.<Y>k__BackingField""
IL_0026: ldarg.1
IL_0027: ldfld ""int C.<Y>k__BackingField""
IL_002c: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_0031: ret
IL_0032: ldc.i4.0
IL_0033: ret
IL_0001: brfalse.s IL_0040
IL_0003: ldarg.0
IL_0004: callvirt ""System.Type C.EqualityContract.get""
IL_0009: ldarg.1
IL_000a: callvirt ""System.Type C.EqualityContract.get""
IL_000f: bne.un.s IL_0040
IL_0011: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_0016: ldarg.0
IL_0017: ldfld ""int C.<X>k__BackingField""
IL_001c: ldarg.1
IL_001d: ldfld ""int C.<X>k__BackingField""
IL_0022: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_0027: brfalse.s IL_0040
IL_0029: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_002e: ldarg.0
IL_002f: ldfld ""int C.<Y>k__BackingField""
IL_0034: ldarg.1
IL_0035: ldfld ""int C.<Y>k__BackingField""
IL_003a: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_003f: ret
IL_0040: ldc.i4.0
IL_0041: ret
}"
);
}
...
...
@@ -406,33 +411,38 @@ public static void Main()
True"
);
verifier
.
VerifyIL
(
"C.Equals(C)"
,
@"
{
// Code size
76 (0x4c
)
// Code size
90 (0x5a
)
.maxstack 3
IL_0000: ldarg.1
IL_0001: brfalse.s IL_004a
IL_0003: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_0008: ldarg.0
IL_0009: ldfld ""int C.<X>k__BackingField""
IL_000e: ldarg.1
IL_000f: ldfld ""int C.<X>k__BackingField""
IL_0014: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_0019: brfalse.s IL_004a
IL_001b: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_0020: ldarg.0
IL_0021: ldfld ""int C.<Y>k__BackingField""
IL_0026: ldarg.1
IL_0027: ldfld ""int C.<Y>k__BackingField""
IL_002c: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_0031: brfalse.s IL_004a
IL_0033: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_0038: ldarg.0
IL_0039: ldfld ""int C.Z""
IL_003e: ldarg.1
IL_003f: ldfld ""int C.Z""
IL_0044: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_0049: ret
IL_004a: ldc.i4.0
IL_004b: ret
IL_0001: brfalse.s IL_0058
IL_0003: ldarg.0
IL_0004: callvirt ""System.Type C.EqualityContract.get""
IL_0009: ldarg.1
IL_000a: callvirt ""System.Type C.EqualityContract.get""
IL_000f: bne.un.s IL_0058
IL_0011: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_0016: ldarg.0
IL_0017: ldfld ""int C.<X>k__BackingField""
IL_001c: ldarg.1
IL_001d: ldfld ""int C.<X>k__BackingField""
IL_0022: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_0027: brfalse.s IL_0058
IL_0029: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_002e: ldarg.0
IL_002f: ldfld ""int C.<Y>k__BackingField""
IL_0034: ldarg.1
IL_0035: ldfld ""int C.<Y>k__BackingField""
IL_003a: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_003f: brfalse.s IL_0058
IL_0041: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_0046: ldarg.0
IL_0047: ldfld ""int C.Z""
IL_004c: ldarg.1
IL_004d: ldfld ""int C.Z""
IL_0052: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_0057: ret
IL_0058: ldc.i4.0
IL_0059: ret
}"
);
}
...
...
@@ -488,26 +498,31 @@ public static void Main()
True"
);
verifier
.
VerifyIL
(
"C.Equals(C)"
,
@"
{
// Code size
52 (0x34
)
// Code size
66 (0x42
)
.maxstack 3
IL_0000: ldarg.1
IL_0001: brfalse.s IL_0032
IL_0003: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_0008: ldarg.0
IL_0009: ldfld ""int C.<X>k__BackingField""
IL_000e: ldarg.1
IL_000f: ldfld ""int C.<X>k__BackingField""
IL_0014: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_0019: brfalse.s IL_0032
IL_001b: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_0020: ldarg.0
IL_0021: ldfld ""int C.<Y>k__BackingField""
IL_0026: ldarg.1
IL_0027: ldfld ""int C.<Y>k__BackingField""
IL_002c: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_0031: ret
IL_0032: ldc.i4.0
IL_0033: ret
IL_0001: brfalse.s IL_0040
IL_0003: ldarg.0
IL_0004: callvirt ""System.Type C.EqualityContract.get""
IL_0009: ldarg.1
IL_000a: callvirt ""System.Type C.EqualityContract.get""
IL_000f: bne.un.s IL_0040
IL_0011: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_0016: ldarg.0
IL_0017: ldfld ""int C.<X>k__BackingField""
IL_001c: ldarg.1
IL_001d: ldfld ""int C.<X>k__BackingField""
IL_0022: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_0027: brfalse.s IL_0040
IL_0029: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_002e: ldarg.0
IL_002f: ldfld ""int C.<Y>k__BackingField""
IL_0034: ldarg.1
IL_0035: ldfld ""int C.<Y>k__BackingField""
IL_003a: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_003f: ret
IL_0040: ldc.i4.0
IL_0041: ret
}"
);
}
...
...
@@ -539,26 +554,31 @@ public static void Main()
True"
);
verifier
.
VerifyIL
(
"C.Equals(C)"
,
@"
{
// Code size
52 (0x34
)
// Code size
66 (0x42
)
.maxstack 3
IL_0000: ldarg.1
IL_0001: brfalse.s IL_0032
IL_0003: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_0008: ldarg.0
IL_0009: ldfld ""int C.<X>k__BackingField""
IL_000e: ldarg.1
IL_000f: ldfld ""int C.<X>k__BackingField""
IL_0014: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_0019: brfalse.s IL_0032
IL_001b: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_0020: ldarg.0
IL_0021: ldfld ""int C.<Y>k__BackingField""
IL_0026: ldarg.1
IL_0027: ldfld ""int C.<Y>k__BackingField""
IL_002c: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_0031: ret
IL_0032: ldc.i4.0
IL_0033: ret
IL_0001: brfalse.s IL_0040
IL_0003: ldarg.0
IL_0004: callvirt ""System.Type C.EqualityContract.get""
IL_0009: ldarg.1
IL_000a: callvirt ""System.Type C.EqualityContract.get""
IL_000f: bne.un.s IL_0040
IL_0011: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_0016: ldarg.0
IL_0017: ldfld ""int C.<X>k__BackingField""
IL_001c: ldarg.1
IL_001d: ldfld ""int C.<X>k__BackingField""
IL_0022: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_0027: brfalse.s IL_0040
IL_0029: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_002e: ldarg.0
IL_002f: ldfld ""int C.<Y>k__BackingField""
IL_0034: ldarg.1
IL_0035: ldfld ""int C.<Y>k__BackingField""
IL_003a: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_003f: ret
IL_0040: ldc.i4.0
IL_0041: ret
}"
);
}
...
...
@@ -589,33 +609,38 @@ public static void Main()
True"
);
verifier
.
VerifyIL
(
"C.Equals(C)"
,
@"
{
// Code size
76 (0x4c
)
// Code size
90 (0x5a
)
.maxstack 3
IL_0000: ldarg.1
IL_0001: brfalse.s IL_004a
IL_0003: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_0008: ldarg.0
IL_0009: ldfld ""int C.<X>k__BackingField""
IL_000e: ldarg.1
IL_000f: ldfld ""int C.<X>k__BackingField""
IL_0014: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_0019: brfalse.s IL_004a
IL_001b: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_0020: ldarg.0
IL_0021: ldfld ""int C.<Y>k__BackingField""
IL_0026: ldarg.1
IL_0027: ldfld ""int C.<Y>k__BackingField""
IL_002c: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_0031: brfalse.s IL_004a
IL_0033: call ""System.Collections.Generic.EqualityComparer<System.Action> System.Collections.Generic.EqualityComparer<System.Action>.Default.get""
IL_0038: ldarg.0
IL_0039: ldfld ""System.Action C.E""
IL_003e: ldarg.1
IL_003f: ldfld ""System.Action C.E""
IL_0044: callvirt ""bool System.Collections.Generic.EqualityComparer<System.Action>.Equals(System.Action, System.Action)""
IL_0049: ret
IL_004a: ldc.i4.0
IL_004b: ret
IL_0001: brfalse.s IL_0058
IL_0003: ldarg.0
IL_0004: callvirt ""System.Type C.EqualityContract.get""
IL_0009: ldarg.1
IL_000a: callvirt ""System.Type C.EqualityContract.get""
IL_000f: bne.un.s IL_0058
IL_0011: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_0016: ldarg.0
IL_0017: ldfld ""int C.<X>k__BackingField""
IL_001c: ldarg.1
IL_001d: ldfld ""int C.<X>k__BackingField""
IL_0022: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_0027: brfalse.s IL_0058
IL_0029: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_002e: ldarg.0
IL_002f: ldfld ""int C.<Y>k__BackingField""
IL_0034: ldarg.1
IL_0035: ldfld ""int C.<Y>k__BackingField""
IL_003a: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_003f: brfalse.s IL_0058
IL_0041: call ""System.Collections.Generic.EqualityComparer<System.Action> System.Collections.Generic.EqualityComparer<System.Action>.Default.get""
IL_0046: ldarg.0
IL_0047: ldfld ""System.Action C.E""
IL_004c: ldarg.1
IL_004d: ldfld ""System.Action C.E""
IL_0052: callvirt ""bool System.Collections.Generic.EqualityComparer<System.Action>.Equals(System.Action, System.Action)""
IL_0057: ret
IL_0058: ldc.i4.0
IL_0059: ret
}"
);
}
...
...
@@ -894,38 +919,43 @@ .maxstack 2
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: isinst ""C""
IL_0007: call
""bool C.Equals(C)""
IL_0007: call
virt
""bool C.Equals(C)""
IL_000c: ret
}"
);
verifier
.
VerifyIL
(
"C.Equals(C)"
,
@"
{
// Code size
76 (0x4c
)
// Code size
90 (0x5a
)
.maxstack 3
IL_0000: ldarg.1
IL_0001: brfalse.s IL_004a
IL_0003: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_0008: ldarg.0
IL_0009: ldfld ""int C.X""
IL_000e: ldarg.1
IL_000f: ldfld ""int C.X""
IL_0014: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_0019: brfalse.s IL_004a
IL_001b: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_0020: ldarg.0
IL_0021: ldfld ""int C.<Y>k__BackingField""
IL_0026: ldarg.1
IL_0027: ldfld ""int C.<Y>k__BackingField""
IL_002c: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_0031: brfalse.s IL_004a
IL_0033: call ""System.Collections.Generic.EqualityComparer<System.Action> System.Collections.Generic.EqualityComparer<System.Action>.Default.get""
IL_0038: ldarg.0
IL_0039: ldfld ""System.Action C.E""
IL_003e: ldarg.1
IL_003f: ldfld ""System.Action C.E""
IL_0044: callvirt ""bool System.Collections.Generic.EqualityComparer<System.Action>.Equals(System.Action, System.Action)""
IL_0049: ret
IL_004a: ldc.i4.0
IL_004b: ret
IL_0001: brfalse.s IL_0058
IL_0003: ldarg.0
IL_0004: callvirt ""System.Type C.EqualityContract.get""
IL_0009: ldarg.1
IL_000a: callvirt ""System.Type C.EqualityContract.get""
IL_000f: bne.un.s IL_0058
IL_0011: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_0016: ldarg.0
IL_0017: ldfld ""int C.X""
IL_001c: ldarg.1
IL_001d: ldfld ""int C.X""
IL_0022: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_0027: brfalse.s IL_0058
IL_0029: call ""System.Collections.Generic.EqualityComparer<int> System.Collections.Generic.EqualityComparer<int>.Default.get""
IL_002e: ldarg.0
IL_002f: ldfld ""int C.<Y>k__BackingField""
IL_0034: ldarg.1
IL_0035: ldfld ""int C.<Y>k__BackingField""
IL_003a: callvirt ""bool System.Collections.Generic.EqualityComparer<int>.Equals(int, int)""
IL_003f: brfalse.s IL_0058
IL_0041: call ""System.Collections.Generic.EqualityComparer<System.Action> System.Collections.Generic.EqualityComparer<System.Action>.Default.get""
IL_0046: ldarg.0
IL_0047: ldfld ""System.Action C.E""
IL_004c: ldarg.1
IL_004d: ldfld ""System.Action C.E""
IL_0052: callvirt ""bool System.Collections.Generic.EqualityComparer<System.Action>.Equals(System.Action, System.Action)""
IL_0057: ret
IL_0058: ldc.i4.0
IL_0059: ret
}"
);
}
...
...
@@ -964,6 +994,8 @@ record C
var
members
=
comp
.
GlobalNamespace
.
GetTypeMember
(
"C"
).
GetMembers
();
AssertEx
.
Equal
(
new
[]
{
"C! C.Clone()"
,
"System.Type! C.EqualityContract.get"
,
"System.Type! C.EqualityContract { get; }"
,
"System.Int32 C.<X>k__BackingField"
,
"System.Int32 C.X { get; init; }"
,
"System.Int32 C.X.get"
,
...
...
@@ -972,9 +1004,9 @@ record C
"System.String! C.Y { get; init; }"
,
"System.String! C.Y.get"
,
"void C.Y.init"
,
"System.Boolean C.Equals(C? )"
,
"System.Boolean C.Equals(System.Object? )"
,
"System.Int32 C.GetHashCode()"
,
"System.Boolean C.Equals(System.Object? )"
,
"System.Boolean C.Equals(C? )"
,
"C.C(C! )"
,
"C.C()"
,
},
members
.
Select
(
m
=>
m
.
ToTestDisplayString
(
includeNonNullable
:
true
)));
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录