提交 2bd86a00 编写于 作者: V vsadov

Adjustment of the fix for #4471

Old compiler did not insert casts for interface peoperty accesses on generic receiver when receiver was constrained to be a class.
上级 44b2028f
......@@ -935,7 +935,8 @@ private BoundExpression VisitPropertyAccess(BoundPropertyAccess node)
// the implementation of the getter must make observable mutations to the instance.
//
// At this point it seems more appropriate to continue adding these casts.
if (node.ReceiverOpt?.Type.IsTypeParameter() == true)
if (node.ReceiverOpt?.Type.IsTypeParameter() == true &&
!node.ReceiverOpt.Type.IsReferenceType)
{
receiver = this.Convert(receiver, getMethod.ReceiverType, isChecked: false);
}
......
......@@ -4308,6 +4308,226 @@ public static void Main()
Console.WriteLine(expr.Dump());
}
}";
string expectedOutput = "Equal(MemberAccess(Convert(MemberAccess(Constant(Test+<>c__DisplayClass3_0`1[Test+C1] Type:Test+<>c__DisplayClass3_0`1[Test+C1]).x Type:Test+C1) Type:Test+IDeletedID).DeletedID Type:System.Int32) Constant(1 Type:System.Int32) Type:System.Boolean)";
CompileAndVerify(
new[] { source, ExpressionTestLibrary },
new[] { ExpressionAssemblyRef },
expectedOutput: expectedOutput);
}
[Fact, WorkItem(4471, "https://github.com/dotnet/roslyn/issues/4471")]
public void GenericPropertyReceiverCastClass()
{
string source =
@"using System;
using System.Linq.Expressions;
class Test
{
public interface IDeletedID
{
int DeletedID { get; }
}
public class C1 : IDeletedID
{
int IDeletedID.DeletedID
{
get
{
return 1;
}
}
}
public static void Main()
{
Test1(new C1());
}
public static void Test1<T>(T x) where T: class, IDeletedID
{
Expression<Func<bool>> expr = () => x.DeletedID == 1;
Console.WriteLine(expr.Dump());
}
}";
string expectedOutput = "Equal(MemberAccess(MemberAccess(Constant(Test+<>c__DisplayClass3_0`1[Test+C1] Type:Test+<>c__DisplayClass3_0`1[Test+C1]).x Type:Test+C1).DeletedID Type:System.Int32) Constant(1 Type:System.Int32) Type:System.Boolean)";
CompileAndVerify(
new[] { source, ExpressionTestLibrary },
new[] { ExpressionAssemblyRef },
expectedOutput: expectedOutput);
}
[Fact, WorkItem(4471, "https://github.com/dotnet/roslyn/issues/4471")]
public void GenericPropertyReceiverCastClass1()
{
string source =
@"using System;
using System.Linq.Expressions;
class Test
{
public interface IDeletedID
{
int DeletedID { get; }
}
public class C1 : IDeletedID
{
int IDeletedID.DeletedID
{
get
{
return 1;
}
}
}
public static void Main()
{
Test1(new C1());
}
public static void Test1<T>(T x) where T: C1, IDeletedID
{
Expression<Func<bool>> expr = () => x.DeletedID == 1;
Console.WriteLine(expr.Dump());
}
}";
string expectedOutput = "Equal(MemberAccess(MemberAccess(Constant(Test+<>c__DisplayClass3_0`1[Test+C1] Type:Test+<>c__DisplayClass3_0`1[Test+C1]).x Type:Test+C1).DeletedID Type:System.Int32) Constant(1 Type:System.Int32) Type:System.Boolean)";
CompileAndVerify(
new[] { source, ExpressionTestLibrary },
new[] { ExpressionAssemblyRef },
expectedOutput: expectedOutput);
}
[Fact, WorkItem(4471, "https://github.com/dotnet/roslyn/issues/4471")]
public void GenericPropertyReceiverCastClass2()
{
string source =
@"using System;
using System.Linq.Expressions;
class Test
{
public interface IDeletedID
{
int DeletedID { get; }
}
public class C1 : IDeletedID
{
int IDeletedID.DeletedID
{
get
{
return 1;
}
}
}
public static void Main()
{
Test1(new C1(), new C1());
}
public static void Test1<T, U>(T x, U u)
where T: U, IDeletedID
where U: C1
{
Expression<Func<bool>> expr = () => x.DeletedID == 1;
Console.WriteLine(expr.Dump());
}
}";
string expectedOutput = "Equal(MemberAccess(MemberAccess(Constant(Test+<>c__DisplayClass3_0`2[Test+C1,Test+C1] Type:Test+<>c__DisplayClass3_0`2[Test+C1,Test+C1]).x Type:Test+C1).DeletedID Type:System.Int32) Constant(1 Type:System.Int32) Type:System.Boolean)";
CompileAndVerify(
new[] { source, ExpressionTestLibrary },
new[] { ExpressionAssemblyRef },
expectedOutput: expectedOutput);
}
[Fact, WorkItem(4471, "https://github.com/dotnet/roslyn/issues/4471")]
public void GenericPropertyReceiverCastClass3()
{
string source =
@"using System;
using System.Linq.Expressions;
class Test
{
public interface IDeletedID
{
int DeletedID { get; }
}
public class C1 : IDeletedID
{
int IDeletedID.DeletedID
{
get
{
return 1;
}
}
}
public static void Main()
{
Test1(new C1(), new C1());
}
public static void Test1<T, U>(T x, U u)
where T: U, IDeletedID
where U: class
{
Expression<Func<bool>> expr = () => x.DeletedID == 1;
Console.WriteLine(expr.Dump());
}
}";
string expectedOutput = "Equal(MemberAccess(Convert(MemberAccess(Constant(Test+<>c__DisplayClass3_0`2[Test+C1,Test+C1] Type:Test+<>c__DisplayClass3_0`2[Test+C1,Test+C1]).x Type:Test+C1) Type:Test+IDeletedID).DeletedID Type:System.Int32) Constant(1 Type:System.Int32) Type:System.Boolean)";
CompileAndVerify(
new[] { source, ExpressionTestLibrary },
new[] { ExpressionAssemblyRef },
expectedOutput: expectedOutput);
}
[Fact, WorkItem(4471, "https://github.com/dotnet/roslyn/issues/4471")]
public void GenericPropertyReceiverCastStruct()
{
string source =
@"using System;
using System.Linq.Expressions;
class Test
{
public interface IDeletedID
{
int DeletedID { get; }
}
public struct C1 : IDeletedID
{
int IDeletedID.DeletedID
{
get
{
return 1;
}
}
}
public static void Main()
{
Test1(new C1());
}
public static void Test1<T>(T x) where T: struct, IDeletedID
{
Expression<Func<bool>> expr = () => x.DeletedID == 1;
Console.WriteLine(expr.Dump());
}
}";
string expectedOutput = "Equal(MemberAccess(Convert(MemberAccess(Constant(Test+<>c__DisplayClass3_0`1[Test+C1] Type:Test+<>c__DisplayClass3_0`1[Test+C1]).x Type:Test+C1) Type:Test+IDeletedID).DeletedID Type:System.Int32) Constant(1 Type:System.Int32) Type:System.Boolean)";
CompileAndVerify(
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册