Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
dotNET
Roslyn
提交
f5eb00c0
R
Roslyn
项目概览
dotNET
/
Roslyn
通知
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,发现更多精彩内容 >>
未验证
提交
f5eb00c0
编写于
3月 29, 2018
作者:
J
Julien Couvreur
提交者:
GitHub
3月 29, 2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Struct this should be saved to temp in tuple equality (#25390)
上级
d977f620
变更
4
显示空白变更内容
内联
并排
Showing
4 changed file
with
92 addition
and
7 deletion
+92
-7
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CompoundAssignmentOperator.cs
...LocalRewriter/LocalRewriter_CompoundAssignmentOperator.cs
+7
-2
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_DeconstructionAssignmentOperator.cs
...ewriter/LocalRewriter_DeconstructionAssignmentOperator.cs
+1
-1
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs
...ilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs
+50
-0
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleEqualityTests.cs
...ers/CSharp/Test/Emit/CodeGen/CodeGenTupleEqualityTests.cs
+34
-4
未找到文件。
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CompoundAssignmentOperator.cs
浏览文件 @
f5eb00c0
...
...
@@ -662,10 +662,13 @@ private BoundExpression BoxReceiver(BoundExpression rewrittenReceiver, NamedType
///
/// even though l is a local, we must access it via a temp since "goo(ref l)" may change it
/// on between accesses.
///
/// Note: In `this.x++`, `this` cannot change between reads. But in `(this, ...) == (..., this.Mutate())` it can.
/// </summary>
internal
static
bool
CanChangeValueBetweenReads
(
BoundExpression
expression
,
bool
localsMayBeAssignedOrCaptured
=
true
)
bool
localsMayBeAssignedOrCaptured
=
true
,
bool
structThisCanChangeValueBetweenReads
=
false
)
{
if
(
expression
.
IsDefaultValue
())
{
...
...
@@ -681,6 +684,8 @@ private BoundExpression BoxReceiver(BoundExpression rewrittenReceiver, NamedType
switch
(
expression
.
Kind
)
{
case
BoundKind
.
ThisReference
:
return
structThisCanChangeValueBetweenReads
&&
((
BoundThisReference
)
expression
).
Type
.
IsStructType
();
case
BoundKind
.
BaseReference
:
return
false
;
...
...
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_DeconstructionAssignmentOperator.cs
浏览文件 @
f5eb00c0
...
...
@@ -271,7 +271,7 @@ private static bool IsTupleExpression(BoundKind kind)
private
BoundExpression
EvaluateSideEffectingArgumentToTemp
(
BoundExpression
arg
,
ArrayBuilder
<
BoundExpression
>
effects
,
ref
ArrayBuilder
<
LocalSymbol
>
temps
)
{
if
(
CanChangeValueBetweenReads
(
arg
,
localsMayBeAssignedOrCaptured
:
true
))
if
(
CanChangeValueBetweenReads
(
arg
,
localsMayBeAssignedOrCaptured
:
true
,
structThisCanChangeValueBetweenReads
:
true
))
{
BoundAssignmentOperator
store
;
var
temp
=
_factory
.
StoreToTemp
(
arg
,
out
store
);
...
...
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs
浏览文件 @
f5eb00c0
...
...
@@ -8279,5 +8279,55 @@ class C
Assert
.
Null
(
info
.
Method
);
Assert
.
Empty
(
info
.
Nested
);
}
[
Fact
]
public
void
TestDeconstructStructThis
()
{
string
source
=
@"
public struct S
{
int I;
public static void Main()
{
S s = new S();
s.M();
}
public void M()
{
this.I = 42;
var (x, (y, z)) = (this, this /* mutating deconstruction */);
System.Console.Write($""{x.I} {y} {z}"");
}
void Deconstruct(out int x1, out int x2) { x1 = I++; x2 = I++; }
}
"
;
var
comp
=
CreateCompilation
(
source
,
options
:
TestOptions
.
DebugExe
);
CompileAndVerify
(
comp
,
expectedOutput
:
"42 42 43"
);
}
[
Fact
]
public
void
TestDeconstructClassThis
()
{
string
source
=
@"
public class C
{
int I;
public static void Main()
{
C c = new C();
c.M();
}
public void M()
{
this.I = 42;
var (x, (y, z)) = (this, this /* mutating deconstruction */);
System.Console.Write($""{x.I} {y} {z}"");
}
void Deconstruct(out int x1, out int x2) { x1 = I++; x2 = I++; }
}
"
;
var
comp
=
CreateCompilation
(
source
,
options
:
TestOptions
.
DebugExe
);
CompileAndVerify
(
comp
,
expectedOutput
:
"44 42 43"
);
}
}
}
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleEqualityTests.cs
浏览文件 @
f5eb00c0
...
...
@@ -648,13 +648,43 @@ S Mutate()
public static implicit operator S(int value) { return new S() { I = value }; }
public static bool operator==(S s1, S s2) { System.Console.Write($""{s1.I} == {s2.I}, ""); return s1.I == s2.I; }
public static bool operator!=(S s1, S s2) { throw null; }
public override bool Equals(object o) { throw null; }
public override int GetHashCode() { throw null; }
}"
;
var
comp
=
CompileAndVerify
(
source
,
expectedOutput
:
"1 == 1, 2 == 2, True"
);
comp
.
VerifyDiagnostics
();
}
// https://github.com/dotnet/roslyn/issues/25488
// We need to create a temp for `this`, otherwise it gets mutated
[
Fact
]
public
void
TestThisClass
()
{
var
source
=
@"
public class C
{
public int I;
public static void Main()
{
C c = new C() { I = 1 };
c.M();
}
void M()
{
System.Console.Write((this, 2) == (2, this.Mutate()));
}
var
comp
=
CompileAndVerify
(
source
,
expectedOutput
:
"2 == 1, False"
);
//comp.VerifyDiagnostics();
C Mutate()
{
I++;
return this;
}
public static implicit operator C(int value) { return new C() { I = value }; }
public static bool operator==(C c1, C c2) { System.Console.Write($""{c1.I} == {c2.I}, ""); return c1.I == c2.I; }
public static bool operator!=(C c1, C c2) { throw null; }
public override bool Equals(object o) { throw null; }
public override int GetHashCode() { throw null; }
}"
;
var
comp
=
CompileAndVerify
(
source
,
expectedOutput
:
"2 == 2, 2 == 2, True"
);
comp
.
VerifyDiagnostics
();
}
[
Fact
]
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录