提交 ce88d76b 编写于 作者: V VSadov

Fixes: #14708

Fixes: #14709
上级 039a7978
......@@ -48,24 +48,24 @@ internal static class CustomModifierUtils
TypeSymbol returnTypeWithCustomModifiers = constructedSourceMethod.ReturnType;
if (returnType.Equals(returnTypeWithCustomModifiers, TypeCompareKind.AllIgnoreOptions))
{
returnType = CopyTypeCustomModifiers(returnTypeWithCustomModifiers, returnType, RefKind.None, destinationMethod.ContainingAssembly);
returnType = CopyTypeCustomModifiers(returnTypeWithCustomModifiers, returnType, destinationMethod.ContainingAssembly);
}
}
/// <param name="sourceType">Type that already has custom modifiers.</param>
/// <param name="destinationType">Same as <paramref name="sourceType"/>, but without custom modifiers. May differ in object/dynamic.</param>
/// <param name="refKind"><see cref="RefKind"/> of the parameter of which this is the type (or <see cref="RefKind.None"/> for a return type.</param>
/// <param name="containingAssembly">The assembly containing the signature referring to the destination type.</param>
/// <returns><paramref name="destinationType"/> with custom modifiers copied from <paramref name="sourceType"/>.</returns>
internal static TypeSymbol CopyTypeCustomModifiers(TypeSymbol sourceType, TypeSymbol destinationType, RefKind refKind, AssemblySymbol containingAssembly)
internal static TypeSymbol CopyTypeCustomModifiers(TypeSymbol sourceType, TypeSymbol destinationType, AssemblySymbol containingAssembly)
{
Debug.Assert(sourceType.Equals(destinationType, TypeCompareKind.AllIgnoreOptions));
// NOTE: overrides can differ by object/dynamic. If they do, we'll need to tweak newType before
// we can use it in place of this.Type. We do so by computing the dynamic transform flags that
// code gen uses and then passing them to the dynamic type decoder that metadata reading uses.
ImmutableArray<bool> flags = CSharpCompilation.DynamicTransformsEncoder.EncodeWithoutCustomModifierFlags(destinationType, refKind);
TypeSymbol typeWithDynamic = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(sourceType, containingAssembly, refKind, flags);
// NOTE: ref is irrelevant here since we are just encoding/decoding the type out of the signature context
ImmutableArray<bool> flags = CSharpCompilation.DynamicTransformsEncoder.EncodeWithoutCustomModifierFlags(destinationType, RefKind.None);
TypeSymbol typeWithDynamic = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(sourceType, containingAssembly, RefKind.None, flags);
TypeSymbol resultType;
if (destinationType.ContainsTuple() && !sourceType.Equals(destinationType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds | TypeCompareKind.IgnoreDynamic))
......
......@@ -533,7 +533,7 @@ protected static void CopyEventCustomModifiers(EventSymbol eventWithCustomModifi
// we want to retain the original (incorrect) type to avoid hiding the type given in source.
if (type.Equals(overriddenEventType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds | TypeCompareKind.IgnoreDynamic))
{
type = CustomModifierUtils.CopyTypeCustomModifiers(overriddenEventType, type, RefKind.None, containingAssembly);
type = CustomModifierUtils.CopyTypeCustomModifiers(overriddenEventType, type, containingAssembly);
}
}
......
......@@ -113,7 +113,7 @@ internal override ParameterSymbol WithCustomModifiersAndParams(TypeSymbol newTyp
internal SourceParameterSymbol WithCustomModifiersAndParamsCore(TypeSymbol newType, ImmutableArray<CustomModifier> newCustomModifiers, ushort countOfCustomModifiersPrecedingByRef, bool newIsParams)
{
newType = CustomModifierUtils.CopyTypeCustomModifiers(newType, this.Type, _refKind, this.ContainingAssembly);
newType = CustomModifierUtils.CopyTypeCustomModifiers(newType, this.Type, this.ContainingAssembly);
if (newCustomModifiers.IsDefaultOrEmpty)
{
......
......@@ -281,7 +281,7 @@ protected override void MethodChecks(DiagnosticBag diagnostics)
else if (_lazyReturnType.SpecialType != SpecialType.System_Void)
{
PropertySymbol associatedProperty = _property;
_lazyReturnType = CustomModifierUtils.CopyTypeCustomModifiers(associatedProperty.Type, _lazyReturnType, RefKind.None, this.ContainingAssembly);
_lazyReturnType = CustomModifierUtils.CopyTypeCustomModifiers(associatedProperty.Type, _lazyReturnType, this.ContainingAssembly);
_lazyReturnTypeCustomModifiers = associatedProperty.TypeCustomModifiers;
}
}
......
......@@ -245,7 +245,7 @@ internal sealed class SourcePropertySymbol : PropertySymbol, IAttributeTargetSym
// we want to retain the original (incorrect) type to avoid hiding the type given in source.
if (_lazyType.Equals(overriddenPropertyType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds | TypeCompareKind.IgnoreDynamic))
{
_lazyType = CustomModifierUtils.CopyTypeCustomModifiers(overriddenPropertyType, _lazyType, RefKind.None, this.ContainingAssembly);
_lazyType = CustomModifierUtils.CopyTypeCustomModifiers(overriddenPropertyType, _lazyType, this.ContainingAssembly);
}
_lazyParameters = CustomModifierUtils.CopyParameterCustomModifiers(overriddenOrImplementedProperty.Parameters, _lazyParameters, alsoCopyParamsModifier: isOverride);
......
......@@ -19385,8 +19385,10 @@ public class B1
comp1.VerifyDiagnostics();
}
[WorkItem(14708, "https://github.com/dotnet/roslyn/issues/14708")]
[WorkItem(14709, "https://github.com/dotnet/roslyn/issues/14709")]
[Fact]
public void Regress001()
public void RefTupleDynamicDecode001()
{
string lib = @"
......@@ -19431,8 +19433,10 @@ public override ref (int, object) Foo(int arg)
var comp = CompileAndVerify(source, expectedOutput: "42qq", additionalRefs: new[] { libComp.ToMetadataReference() }.Concat(s_valueTupleRefs), options: TestOptions.DebugExe, verify: false);
}
[WorkItem(14708, "https://github.com/dotnet/roslyn/issues/14708")]
[WorkItem(14709, "https://github.com/dotnet/roslyn/issues/14709")]
[Fact]
public void Regress002()
public void RefTupleDynamicDecode002()
{
string lib = @"
......@@ -19721,5 +19725,117 @@ struct BB<T>
--
--");
}
[WorkItem(14708, "https://github.com/dotnet/roslyn/issues/14708")]
[WorkItem(14709, "https://github.com/dotnet/roslyn/issues/14709")]
[Fact]
public void RefTupleDynamicDecode003()
{
string lib = @"
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly extern System.Core
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly extern System.ValueTuple
{
.publickeytoken = (CC 7B 13 FF CD 2D DD 51 ) // .{...-.Q
.ver 4:0:1:0
}
// =============== CLASS MEMBERS DECLARATION ===================
.class public auto ansi beforefieldinit ClassLibrary1.C1
extends [mscorlib]System.Object
{
.method public hidebysig newslot virtual
instance valuetype [System.ValueTuple]System.ValueTuple`2<int32,object>&
Foo(int32 arg) cil managed
{
.param [0]
// the dynamic flags array is too short - decoder expects a flag matching ""ref"", but it is missing here.
.custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor(bool[]) = ( 01 00 03 00 00 00 00 00 01 00 00 )
// Code size 37 (0x25)
.maxstack 5
.locals init (valuetype [System.ValueTuple]System.ValueTuple`2<int32,object>& V_0)
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: newarr valuetype [System.ValueTuple]System.ValueTuple`2<int32,object>
IL_0007: dup
IL_0008: ldc.i4.0
IL_0009: ldc.i4.1
IL_000a: ldarg.1
IL_000b: box [mscorlib]System.Int32
IL_0010: newobj instance void valuetype [System.ValueTuple]System.ValueTuple`2<int32,object>::.ctor(!0,
!1)
IL_0015: stelem valuetype [System.ValueTuple]System.ValueTuple`2<int32,object>
IL_001a: ldc.i4.0
IL_001b: ldelema valuetype [System.ValueTuple]System.ValueTuple`2<int32,object>
IL_0020: stloc.0
IL_0021: br.s IL_0023
IL_0023: ldloc.0
IL_0024: ret
} // end of method C1::Foo
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method C1::.ctor
} // end of class ClassLibrary1.C1
";
var libCompRef = CompileIL(lib);
var source = @"
namespace ConsoleApplication5
{
class Program
{
static void Main(string[] args)
{
ref var x = ref new C2().Foo(42);
System.Console.Write(x.Item2);
x.Item2 = ""qq"";
System.Console.WriteLine(x.Item2);
}
}
class C2: ClassLibrary1.C1
{
public override ref (int, dynamic) Foo(int arg)
{
return ref base.Foo(arg);
}
}
}
";
var comp = CreateCompilationWithMscorlib45AndCSruntime(source, additionalRefs: new[] { libCompRef }.Concat(s_valueTupleRefs).ToArray(), options: TestOptions.DebugExe);
CompileAndVerify(comp, expectedOutput: "42qq", verify: false);
var m = (MethodSymbol)(comp.GetTypeByMetadataName("ConsoleApplication5.C2").GetMembers("Foo").First());
Assert.Equal("ref (System.Int32, dynamic) ConsoleApplication5.C2.Foo(System.Int32 arg)", m.ToTestDisplayString());
var b = m.OverriddenMethod;
// not (int, dynamic),
// since dynamic flags were not aligned we ignored flags
Assert.Equal("ref (System.Int32, System.Object) ClassLibrary1.C1.Foo(System.Int32 arg)", b.ToTestDisplayString());
}
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册