From ce88d76bd50ecbd8d79912bff4af5eacb7a816e3 Mon Sep 17 00:00:00 2001 From: VSadov Date: Mon, 24 Oct 2016 14:26:15 -0700 Subject: [PATCH] Fixes: #14708 Fixes: #14709 --- .../Symbols/Source/CustomModifierUtils.cs | 10 +- .../Symbols/Source/SourceEventSymbol.cs | 2 +- .../Symbols/Source/SourceParameterSymbol.cs | 2 +- .../Source/SourcePropertyAccessorSymbol.cs | 2 +- .../Symbols/Source/SourcePropertySymbol.cs | 2 +- .../Test/Emit/CodeGen/CodeGenTupleTest.cs | 120 +++++++++++++++++- 6 files changed, 127 insertions(+), 11 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/CustomModifierUtils.cs b/src/Compilers/CSharp/Portable/Symbols/Source/CustomModifierUtils.cs index 9a29c285437..141809ba95f 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/CustomModifierUtils.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/CustomModifierUtils.cs @@ -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); } } /// Type that already has custom modifiers. /// Same as , but without custom modifiers. May differ in object/dynamic. - /// of the parameter of which this is the type (or for a return type. /// The assembly containing the signature referring to the destination type. /// with custom modifiers copied from . - 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 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 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)) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs index aaddddb6deb..d4e037438f4 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs @@ -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); } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceParameterSymbol.cs index c5e3bd55283..d081bd7af0e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceParameterSymbol.cs @@ -113,7 +113,7 @@ internal override ParameterSymbol WithCustomModifiersAndParams(TypeSymbol newTyp internal SourceParameterSymbol WithCustomModifiersAndParamsCore(TypeSymbol newType, ImmutableArray 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) { diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs index 9547cf7a41c..0d5e8efe4ad 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs @@ -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; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs index 78cf0766b88..b8471a8b77f 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs @@ -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); diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs index ad346d16787..efd6c8fb24c 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs @@ -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 -- --"); } + [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& + 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& V_0) + IL_0000: nop + IL_0001: ldc.i4.1 + IL_0002: newarr valuetype [System.ValueTuple]System.ValueTuple`2 + 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::.ctor(!0, + !1) + IL_0015: stelem valuetype [System.ValueTuple]System.ValueTuple`2 + IL_001a: ldc.i4.0 + IL_001b: ldelema valuetype [System.ValueTuple]System.ValueTuple`2 + 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 -- GitLab