Browse Source

Fix tuple type in 'new List<(int, string)>'.

pull/1030/head
Daniel Grunwald 7 years ago
parent
commit
8f588208b9
  1. 28
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TupleTests.cs
  2. 168
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TupleTests.opt.roslyn.il
  3. 192
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TupleTests.roslyn.il
  4. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  5. 12
      ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs
  6. 1
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs
  7. 278
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeReference.cs
  8. 30
      ICSharpCode.Decompiler/TypeSystem/MetadataAssembly.cs

28
ICSharpCode.Decompiler.Tests/TestCases/Pretty/TupleTests.cs

@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -111,20 +112,31 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void Foreach(IEnumerable<(int, string)> input) public void Foreach(IEnumerable<(int, string)> input)
{ {
foreach (var item3 in input) { foreach (var item in input) {
int item = item3.Item1; Console.WriteLine($"{item.Item1}: {item.Item2}");
string item2 = item3.Item2;
Console.WriteLine($"{item}: {item2}");
} }
} }
public void ForeachNamedElements(IEnumerable<(int Index, string Data)> input) public void ForeachNamedElements(IEnumerable<(int Index, string Data)> input)
{ {
foreach (var item3 in input) { foreach (var item in input) {
int item = item3.Index; Console.WriteLine($"{item.Index}: {item.Data}");
string item2 = item3.Data;
Console.WriteLine($"{item}: {item2}");
} }
} }
public void NonGenericForeach(IEnumerable input)
{
foreach ((string, int) item in input) {
Console.WriteLine($"{item.Item1}: {item.Item2}");
}
}
public void CallForeach()
{
Foreach(new List<(int, string)> {
(1, "a"),
(2, "b")
});
}
} }
} }

168
ICSharpCode.Decompiler.Tests/TestCases/Pretty/TupleTests.opt.roslyn.il

@ -492,50 +492,47 @@
.method public hidebysig instance void .method public hidebysig instance void
Foreach(class [mscorlib]System.Collections.Generic.IEnumerable`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>> input) cil managed Foreach(class [mscorlib]System.Collections.Generic.IEnumerable`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>> input) cil managed
{ {
// Code size 71 (0x47) // Code size 69 (0x45)
.maxstack 3 .maxstack 3
.locals init (class [mscorlib]System.Collections.Generic.IEnumerator`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>> V_0, .locals init (class [mscorlib]System.Collections.Generic.IEnumerator`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>> V_0,
int32 V_1, valuetype [mscorlib]System.ValueTuple`2<int32,string> V_1)
string V_2)
IL_0000: ldarg.1 IL_0000: ldarg.1
IL_0001: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> class [mscorlib]System.Collections.Generic.IEnumerable`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>>::GetEnumerator() IL_0001: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> class [mscorlib]System.Collections.Generic.IEnumerable`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>>::GetEnumerator()
IL_0006: stloc.0 IL_0006: stloc.0
.try .try
{ {
IL_0007: br.s IL_0032 IL_0007: br.s IL_0030
IL_0009: ldloc.0 IL_0009: ldloc.0
IL_000a: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>>::get_Current() IL_000a: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>>::get_Current()
IL_000f: dup IL_000f: stloc.1
IL_0010: ldfld !0 valuetype [mscorlib]System.ValueTuple`2<int32,string>::Item1 IL_0010: ldstr "{0}: {1}"
IL_0015: stloc.1 IL_0015: ldloc.1
IL_0016: ldfld !1 valuetype [mscorlib]System.ValueTuple`2<int32,string>::Item2 IL_0016: ldfld !0 valuetype [mscorlib]System.ValueTuple`2<int32,string>::Item1
IL_001b: stloc.2 IL_001b: box [mscorlib]System.Int32
IL_001c: ldstr "{0}: {1}" IL_0020: ldloc.1
IL_0021: ldloc.1 IL_0021: ldfld !1 valuetype [mscorlib]System.ValueTuple`2<int32,string>::Item2
IL_0022: box [mscorlib]System.Int32 IL_0026: call string [mscorlib]System.String::Format(string,
IL_0027: ldloc.2
IL_0028: call string [mscorlib]System.String::Format(string,
object, object,
object) object)
IL_002d: call void [mscorlib]System.Console::WriteLine(string) IL_002b: call void [mscorlib]System.Console::WriteLine(string)
IL_0032: ldloc.0 IL_0030: ldloc.0
IL_0033: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() IL_0031: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
IL_0038: brtrue.s IL_0009 IL_0036: brtrue.s IL_0009
IL_003a: leave.s IL_0046 IL_0038: leave.s IL_0044
} // end .try } // end .try
finally finally
{ {
IL_003c: ldloc.0 IL_003a: ldloc.0
IL_003d: brfalse.s IL_0045 IL_003b: brfalse.s IL_0043
IL_003f: ldloc.0 IL_003d: ldloc.0
IL_0040: callvirt instance void [mscorlib]System.IDisposable::Dispose() IL_003e: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0045: endfinally IL_0043: endfinally
} // end handler } // end handler
IL_0046: ret IL_0044: ret
} // end of method TupleTests::Foreach } // end of method TupleTests::Foreach
.method public hidebysig instance void .method public hidebysig instance void
@ -544,52 +541,123 @@
.param [1] .param [1]
.custom instance void [mscorlib]System.Runtime.CompilerServices.TupleElementNamesAttribute::.ctor(string[]) = ( 01 00 02 00 00 00 05 49 6E 64 65 78 04 44 61 74 // .......Index.Dat .custom instance void [mscorlib]System.Runtime.CompilerServices.TupleElementNamesAttribute::.ctor(string[]) = ( 01 00 02 00 00 00 05 49 6E 64 65 78 04 44 61 74 // .......Index.Dat
61 00 00 ) // a.. 61 00 00 ) // a..
// Code size 71 (0x47) // Code size 69 (0x45)
.maxstack 3 .maxstack 3
.locals init (class [mscorlib]System.Collections.Generic.IEnumerator`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>> V_0, .locals init (class [mscorlib]System.Collections.Generic.IEnumerator`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>> V_0,
int32 V_1, valuetype [mscorlib]System.ValueTuple`2<int32,string> V_1)
string V_2)
IL_0000: ldarg.1 IL_0000: ldarg.1
IL_0001: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> class [mscorlib]System.Collections.Generic.IEnumerable`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>>::GetEnumerator() IL_0001: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> class [mscorlib]System.Collections.Generic.IEnumerable`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>>::GetEnumerator()
IL_0006: stloc.0 IL_0006: stloc.0
.try .try
{ {
IL_0007: br.s IL_0032 IL_0007: br.s IL_0030
IL_0009: ldloc.0 IL_0009: ldloc.0
IL_000a: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>>::get_Current() IL_000a: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>>::get_Current()
IL_000f: dup IL_000f: stloc.1
IL_0010: ldfld !0 valuetype [mscorlib]System.ValueTuple`2<int32,string>::Item1 IL_0010: ldstr "{0}: {1}"
IL_0015: stloc.1 IL_0015: ldloc.1
IL_0016: ldfld !1 valuetype [mscorlib]System.ValueTuple`2<int32,string>::Item2 IL_0016: ldfld !0 valuetype [mscorlib]System.ValueTuple`2<int32,string>::Item1
IL_001b: stloc.2 IL_001b: box [mscorlib]System.Int32
IL_001c: ldstr "{0}: {1}" IL_0020: ldloc.1
IL_0021: ldloc.1 IL_0021: ldfld !1 valuetype [mscorlib]System.ValueTuple`2<int32,string>::Item2
IL_0022: box [mscorlib]System.Int32 IL_0026: call string [mscorlib]System.String::Format(string,
IL_0027: ldloc.2
IL_0028: call string [mscorlib]System.String::Format(string,
object, object,
object) object)
IL_002d: call void [mscorlib]System.Console::WriteLine(string) IL_002b: call void [mscorlib]System.Console::WriteLine(string)
IL_0032: ldloc.0 IL_0030: ldloc.0
IL_0033: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() IL_0031: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
IL_0038: brtrue.s IL_0009 IL_0036: brtrue.s IL_0009
IL_003a: leave.s IL_0046 IL_0038: leave.s IL_0044
} // end .try } // end .try
finally finally
{ {
IL_003c: ldloc.0 IL_003a: ldloc.0
IL_003d: brfalse.s IL_0045 IL_003b: brfalse.s IL_0043
IL_003f: ldloc.0 IL_003d: ldloc.0
IL_0040: callvirt instance void [mscorlib]System.IDisposable::Dispose() IL_003e: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0045: endfinally IL_0043: endfinally
} // end handler } // end handler
IL_0046: ret IL_0044: ret
} // end of method TupleTests::ForeachNamedElements } // end of method TupleTests::ForeachNamedElements
.method public hidebysig instance void
NonGenericForeach(class [mscorlib]System.Collections.IEnumerable input) cil managed
{
// Code size 81 (0x51)
.maxstack 3
.locals init (class [mscorlib]System.Collections.IEnumerator V_0,
valuetype [mscorlib]System.ValueTuple`2<string,int32> V_1,
class [mscorlib]System.IDisposable V_2)
IL_0000: ldarg.1
IL_0001: callvirt instance class [mscorlib]System.Collections.IEnumerator [mscorlib]System.Collections.IEnumerable::GetEnumerator()
IL_0006: stloc.0
.try
{
IL_0007: br.s IL_0035
IL_0009: ldloc.0
IL_000a: callvirt instance object [mscorlib]System.Collections.IEnumerator::get_Current()
IL_000f: unbox.any valuetype [mscorlib]System.ValueTuple`2<string,int32>
IL_0014: stloc.1
IL_0015: ldstr "{0}: {1}"
IL_001a: ldloc.1
IL_001b: ldfld !0 valuetype [mscorlib]System.ValueTuple`2<string,int32>::Item1
IL_0020: ldloc.1
IL_0021: ldfld !1 valuetype [mscorlib]System.ValueTuple`2<string,int32>::Item2
IL_0026: box [mscorlib]System.Int32
IL_002b: call string [mscorlib]System.String::Format(string,
object,
object)
IL_0030: call void [mscorlib]System.Console::WriteLine(string)
IL_0035: ldloc.0
IL_0036: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
IL_003b: brtrue.s IL_0009
IL_003d: leave.s IL_0050
} // end .try
finally
{
IL_003f: ldloc.0
IL_0040: isinst [mscorlib]System.IDisposable
IL_0045: stloc.2
IL_0046: ldloc.2
IL_0047: brfalse.s IL_004f
IL_0049: ldloc.2
IL_004a: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_004f: endfinally
} // end handler
IL_0050: ret
} // end of method TupleTests::NonGenericForeach
.method public hidebysig instance void
CallForeach() cil managed
{
// Code size 46 (0x2e)
.maxstack 8
IL_0000: ldarg.0
IL_0001: newobj instance void class [mscorlib]System.Collections.Generic.List`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>>::.ctor()
IL_0006: dup
IL_0007: ldc.i4.1
IL_0008: ldstr "a"
IL_000d: newobj instance void valuetype [mscorlib]System.ValueTuple`2<int32,string>::.ctor(!0,
!1)
IL_0012: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>>::Add(!0)
IL_0017: dup
IL_0018: ldc.i4.2
IL_0019: ldstr "b"
IL_001e: newobj instance void valuetype [mscorlib]System.ValueTuple`2<int32,string>::.ctor(!0,
!1)
IL_0023: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>>::Add(!0)
IL_0028: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests::Foreach(class [mscorlib]System.Collections.Generic.IEnumerable`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>>)
IL_002d: ret
} // end of method TupleTests::CallForeach
.method public hidebysig specialname rtspecialname .method public hidebysig specialname rtspecialname
instance void .ctor() cil managed instance void .ctor() cil managed
{ {

192
ICSharpCode.Decompiler.Tests/TestCases/Pretty/TupleTests.roslyn.il

@ -517,12 +517,10 @@
.method public hidebysig instance void .method public hidebysig instance void
Foreach(class [mscorlib]System.Collections.Generic.IEnumerable`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>> input) cil managed Foreach(class [mscorlib]System.Collections.Generic.IEnumerable`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>> input) cil managed
{ {
// Code size 79 (0x4f) // Code size 75 (0x4b)
.maxstack 3 .maxstack 3
.locals init (class [mscorlib]System.Collections.Generic.IEnumerator`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>> V_0, .locals init (class [mscorlib]System.Collections.Generic.IEnumerator`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>> V_0,
valuetype [mscorlib]System.ValueTuple`2<int32,string> V_1, valuetype [mscorlib]System.ValueTuple`2<int32,string> V_1)
int32 V_2,
string V_3)
IL_0000: nop IL_0000: nop
IL_0001: nop IL_0001: nop
IL_0002: ldarg.1 IL_0002: ldarg.1
@ -530,46 +528,42 @@
IL_0008: stloc.0 IL_0008: stloc.0
.try .try
{ {
IL_0009: br.s IL_0039 IL_0009: br.s IL_0035
IL_000b: ldloc.0 IL_000b: ldloc.0
IL_000c: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>>::get_Current() IL_000c: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>>::get_Current()
IL_0011: stloc.1 IL_0011: stloc.1
IL_0012: nop IL_0012: nop
IL_0013: ldloc.1 IL_0013: ldstr "{0}: {1}"
IL_0014: ldfld !0 valuetype [mscorlib]System.ValueTuple`2<int32,string>::Item1 IL_0018: ldloc.1
IL_0019: stloc.2 IL_0019: ldfld !0 valuetype [mscorlib]System.ValueTuple`2<int32,string>::Item1
IL_001a: ldloc.1 IL_001e: box [mscorlib]System.Int32
IL_001b: ldfld !1 valuetype [mscorlib]System.ValueTuple`2<int32,string>::Item2 IL_0023: ldloc.1
IL_0020: stloc.3 IL_0024: ldfld !1 valuetype [mscorlib]System.ValueTuple`2<int32,string>::Item2
IL_0021: ldstr "{0}: {1}" IL_0029: call string [mscorlib]System.String::Format(string,
IL_0026: ldloc.2
IL_0027: box [mscorlib]System.Int32
IL_002c: ldloc.3
IL_002d: call string [mscorlib]System.String::Format(string,
object, object,
object) object)
IL_0032: call void [mscorlib]System.Console::WriteLine(string) IL_002e: call void [mscorlib]System.Console::WriteLine(string)
IL_0037: nop IL_0033: nop
IL_0038: nop IL_0034: nop
IL_0039: ldloc.0 IL_0035: ldloc.0
IL_003a: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() IL_0036: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
IL_003f: brtrue.s IL_000b IL_003b: brtrue.s IL_000b
IL_0041: leave.s IL_004e IL_003d: leave.s IL_004a
} // end .try } // end .try
finally finally
{ {
IL_0043: ldloc.0 IL_003f: ldloc.0
IL_0044: brfalse.s IL_004d IL_0040: brfalse.s IL_0049
IL_0046: ldloc.0 IL_0042: ldloc.0
IL_0047: callvirt instance void [mscorlib]System.IDisposable::Dispose() IL_0043: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_004c: nop IL_0048: nop
IL_004d: endfinally IL_0049: endfinally
} // end handler } // end handler
IL_004e: ret IL_004a: ret
} // end of method TupleTests::Foreach } // end of method TupleTests::Foreach
.method public hidebysig instance void .method public hidebysig instance void
@ -578,12 +572,10 @@
.param [1] .param [1]
.custom instance void [mscorlib]System.Runtime.CompilerServices.TupleElementNamesAttribute::.ctor(string[]) = ( 01 00 02 00 00 00 05 49 6E 64 65 78 04 44 61 74 // .......Index.Dat .custom instance void [mscorlib]System.Runtime.CompilerServices.TupleElementNamesAttribute::.ctor(string[]) = ( 01 00 02 00 00 00 05 49 6E 64 65 78 04 44 61 74 // .......Index.Dat
61 00 00 ) // a.. 61 00 00 ) // a..
// Code size 79 (0x4f) // Code size 75 (0x4b)
.maxstack 3 .maxstack 3
.locals init (class [mscorlib]System.Collections.Generic.IEnumerator`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>> V_0, .locals init (class [mscorlib]System.Collections.Generic.IEnumerator`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>> V_0,
valuetype [mscorlib]System.ValueTuple`2<int32,string> V_1, valuetype [mscorlib]System.ValueTuple`2<int32,string> V_1)
int32 V_2,
string V_3)
IL_0000: nop IL_0000: nop
IL_0001: nop IL_0001: nop
IL_0002: ldarg.1 IL_0002: ldarg.1
@ -591,48 +583,128 @@
IL_0008: stloc.0 IL_0008: stloc.0
.try .try
{ {
IL_0009: br.s IL_0039 IL_0009: br.s IL_0035
IL_000b: ldloc.0 IL_000b: ldloc.0
IL_000c: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>>::get_Current() IL_000c: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>>::get_Current()
IL_0011: stloc.1 IL_0011: stloc.1
IL_0012: nop IL_0012: nop
IL_0013: ldloc.1 IL_0013: ldstr "{0}: {1}"
IL_0014: ldfld !0 valuetype [mscorlib]System.ValueTuple`2<int32,string>::Item1 IL_0018: ldloc.1
IL_0019: stloc.2 IL_0019: ldfld !0 valuetype [mscorlib]System.ValueTuple`2<int32,string>::Item1
IL_001a: ldloc.1 IL_001e: box [mscorlib]System.Int32
IL_001b: ldfld !1 valuetype [mscorlib]System.ValueTuple`2<int32,string>::Item2 IL_0023: ldloc.1
IL_0020: stloc.3 IL_0024: ldfld !1 valuetype [mscorlib]System.ValueTuple`2<int32,string>::Item2
IL_0021: ldstr "{0}: {1}" IL_0029: call string [mscorlib]System.String::Format(string,
IL_0026: ldloc.2
IL_0027: box [mscorlib]System.Int32
IL_002c: ldloc.3
IL_002d: call string [mscorlib]System.String::Format(string,
object, object,
object) object)
IL_0032: call void [mscorlib]System.Console::WriteLine(string) IL_002e: call void [mscorlib]System.Console::WriteLine(string)
IL_0037: nop IL_0033: nop
IL_0038: nop IL_0034: nop
IL_0039: ldloc.0 IL_0035: ldloc.0
IL_003a: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() IL_0036: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
IL_003f: brtrue.s IL_000b IL_003b: brtrue.s IL_000b
IL_0041: leave.s IL_004e IL_003d: leave.s IL_004a
} // end .try } // end .try
finally finally
{ {
IL_0043: ldloc.0 IL_003f: ldloc.0
IL_0044: brfalse.s IL_004d IL_0040: brfalse.s IL_0049
IL_0046: ldloc.0 IL_0042: ldloc.0
IL_0047: callvirt instance void [mscorlib]System.IDisposable::Dispose() IL_0043: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_004c: nop IL_0048: nop
IL_004d: endfinally IL_0049: endfinally
} // end handler } // end handler
IL_004e: ret IL_004a: ret
} // end of method TupleTests::ForeachNamedElements } // end of method TupleTests::ForeachNamedElements
.method public hidebysig instance void
NonGenericForeach(class [mscorlib]System.Collections.IEnumerable input) cil managed
{
// Code size 87 (0x57)
.maxstack 3
.locals init (class [mscorlib]System.Collections.IEnumerator V_0,
valuetype [mscorlib]System.ValueTuple`2<string,int32> V_1,
class [mscorlib]System.IDisposable V_2)
IL_0000: nop
IL_0001: nop
IL_0002: ldarg.1
IL_0003: callvirt instance class [mscorlib]System.Collections.IEnumerator [mscorlib]System.Collections.IEnumerable::GetEnumerator()
IL_0008: stloc.0
.try
{
IL_0009: br.s IL_003a
IL_000b: ldloc.0
IL_000c: callvirt instance object [mscorlib]System.Collections.IEnumerator::get_Current()
IL_0011: unbox.any valuetype [mscorlib]System.ValueTuple`2<string,int32>
IL_0016: stloc.1
IL_0017: nop
IL_0018: ldstr "{0}: {1}"
IL_001d: ldloc.1
IL_001e: ldfld !0 valuetype [mscorlib]System.ValueTuple`2<string,int32>::Item1
IL_0023: ldloc.1
IL_0024: ldfld !1 valuetype [mscorlib]System.ValueTuple`2<string,int32>::Item2
IL_0029: box [mscorlib]System.Int32
IL_002e: call string [mscorlib]System.String::Format(string,
object,
object)
IL_0033: call void [mscorlib]System.Console::WriteLine(string)
IL_0038: nop
IL_0039: nop
IL_003a: ldloc.0
IL_003b: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
IL_0040: brtrue.s IL_000b
IL_0042: leave.s IL_0056
} // end .try
finally
{
IL_0044: ldloc.0
IL_0045: isinst [mscorlib]System.IDisposable
IL_004a: stloc.2
IL_004b: ldloc.2
IL_004c: brfalse.s IL_0055
IL_004e: ldloc.2
IL_004f: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0054: nop
IL_0055: endfinally
} // end handler
IL_0056: ret
} // end of method TupleTests::NonGenericForeach
.method public hidebysig instance void
CallForeach() cil managed
{
// Code size 50 (0x32)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: newobj instance void class [mscorlib]System.Collections.Generic.List`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>>::.ctor()
IL_0007: dup
IL_0008: ldc.i4.1
IL_0009: ldstr "a"
IL_000e: newobj instance void valuetype [mscorlib]System.ValueTuple`2<int32,string>::.ctor(!0,
!1)
IL_0013: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>>::Add(!0)
IL_0018: nop
IL_0019: dup
IL_001a: ldc.i4.2
IL_001b: ldstr "b"
IL_0020: newobj instance void valuetype [mscorlib]System.ValueTuple`2<int32,string>::.ctor(!0,
!1)
IL_0025: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>>::Add(!0)
IL_002a: nop
IL_002b: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests::Foreach(class [mscorlib]System.Collections.Generic.IEnumerable`1<valuetype [mscorlib]System.ValueTuple`2<int32,string>>)
IL_0030: nop
IL_0031: ret
} // end of method TupleTests::CallForeach
.method public hidebysig specialname rtspecialname .method public hidebysig specialname rtspecialname
instance void .ctor() cil managed instance void .ctor() cil managed
{ {

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -359,7 +359,6 @@
<Compile Include="TypeSystem\Implementation\MetadataProperty.cs" /> <Compile Include="TypeSystem\Implementation\MetadataProperty.cs" />
<Compile Include="TypeSystem\Implementation\MetadataTypeDefinition.cs" /> <Compile Include="TypeSystem\Implementation\MetadataTypeDefinition.cs" />
<Compile Include="TypeSystem\Implementation\MetadataTypeParameter.cs" /> <Compile Include="TypeSystem\Implementation\MetadataTypeParameter.cs" />
<Compile Include="TypeSystem\Implementation\MetadataTypeReference.cs" />
<Compile Include="TypeSystem\Implementation\SpecializedParameter.cs" /> <Compile Include="TypeSystem\Implementation\SpecializedParameter.cs" />
<Compile Include="TypeSystem\MetadataAssembly.cs" /> <Compile Include="TypeSystem\MetadataAssembly.cs" />
<Compile Include="TypeSystem\ModifiedType.cs" /> <Compile Include="TypeSystem\ModifiedType.cs" />

12
ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs

@ -36,7 +36,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
ICompilation compilation, ICompilation compilation,
SRM.CustomAttributeHandleCollection? attributes, SRM.CustomAttributeHandleCollection? attributes,
SRM.MetadataReader metadata, SRM.MetadataReader metadata,
TypeSystemOptions options) TypeSystemOptions options,
bool typeChildrenOnly = false)
{ {
if ((options & (TypeSystemOptions.Dynamic | TypeSystemOptions.Tuple)) == TypeSystemOptions.None) { if ((options & (TypeSystemOptions.Dynamic | TypeSystemOptions.Tuple)) == TypeSystemOptions.None) {
return inputType; return inputType;
@ -73,9 +74,14 @@ namespace ICSharpCode.Decompiler.TypeSystem
} }
} }
if (hasDynamicAttribute || useTupleTypes) { if (hasDynamicAttribute || useTupleTypes) {
return inputType.AcceptVisitor(new ApplyAttributeTypeVisitor( var visitor = new ApplyAttributeTypeVisitor(
compilation, hasDynamicAttribute, dynamicAttributeData, useTupleTypes, tupleElementNames compilation, hasDynamicAttribute, dynamicAttributeData, useTupleTypes, tupleElementNames
)); );
if (typeChildrenOnly) {
return inputType.VisitChildren(visitor);
} else {
return inputType.AcceptVisitor(visitor);
}
} else { } else {
return inputType; return inputType;
} }

1
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs

@ -34,7 +34,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
readonly GenericParameterAttributes attr; readonly GenericParameterAttributes attr;
// lazy-loaded: // lazy-loaded:
IReadOnlyList<IAttribute> customAttributes;
IReadOnlyList<IType> constraints; IReadOnlyList<IType> constraints;
public static ITypeParameter[] Create(MetadataAssembly assembly, ITypeDefinition copyFromOuter, IEntity owner, GenericParameterHandleCollection handles) public static ITypeParameter[] Create(MetadataAssembly assembly, ITypeDefinition copyFromOuter, IEntity owner, GenericParameterHandleCollection handles)

278
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeReference.cs

@ -1,278 +0,0 @@
// Copyright (c) 2018 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using SRM = System.Reflection.Metadata;
using System.Diagnostics;
using System;
using ICSharpCode.Decompiler.Util;
using System.Linq;
using System.Collections.Immutable;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
sealed class MetadataTypeReference : ITypeReference
{
readonly SRM.EntityHandle type;
readonly SRM.MetadataReader metadata;
readonly SRM.CustomAttributeHandleCollection? typeAttributes;
readonly TypeSystemOptions options;
public MetadataTypeReference(SRM.EntityHandle type,
SRM.MetadataReader metadata,
SRM.CustomAttributeHandleCollection? typeAttributes,
TypeSystemOptions options)
{
this.type = type;
this.metadata = metadata;
this.typeAttributes = typeAttributes;
this.options = options;
}
public IType Resolve(ITypeResolveContext context)
{
return Resolve(type, metadata,
new TypeProvider(context.CurrentAssembly),
new GenericContext(context),
options, typeAttributes);
}
public static IType Resolve(SRM.EntityHandle type,
SRM.MetadataReader metadata,
TypeProvider typeProvider,
GenericContext genericContext,
TypeSystemOptions options,
SRM.CustomAttributeHandleCollection? typeAttributes = null)
{
if (type.IsNil)
return SpecialType.UnknownType;
IType ty;
switch (type.Kind) {
case SRM.HandleKind.TypeDefinition:
ty = typeProvider.GetTypeFromDefinition(metadata, (SRM.TypeDefinitionHandle)type, 0);
break;
case SRM.HandleKind.TypeReference:
ty = typeProvider.GetTypeFromReference(metadata, (SRM.TypeReferenceHandle)type, 0);
break;
case SRM.HandleKind.TypeSpecification:
var typeSpec = metadata.GetTypeSpecification((SRM.TypeSpecificationHandle)type);
ty = typeSpec.DecodeSignature(typeProvider, genericContext);
break;
default:
Debug.Fail("Not a type handle");
ty = SpecialType.UnknownType;
break;
}
ty = ApplyAttributeTypeVisitor.ApplyAttributesToType(ty, typeProvider.Compilation,
typeAttributes, metadata, options);
return ty;
}
}
sealed class FieldTypeReference : ITypeReference
{
readonly SRM.EntityHandle fieldHandle;
readonly SRM.MetadataReader metadata;
readonly TypeSystemOptions options;
public FieldTypeReference(SRM.FieldDefinitionHandle fieldHandle,
SRM.MetadataReader metadata,
TypeSystemOptions options)
{
this.fieldHandle = fieldHandle;
this.metadata = metadata;
this.options = options;
}
public FieldTypeReference(SRM.MemberReferenceHandle fieldReferenceHandle,
SRM.MetadataReader metadata,
TypeSystemOptions attributeOptions)
{
this.fieldHandle = fieldReferenceHandle;
this.metadata = metadata;
this.options = attributeOptions;
}
IType ITypeReference.Resolve(ITypeResolveContext context)
{
if (fieldHandle.Kind == SRM.HandleKind.FieldDefinition) {
return Resolve((SRM.FieldDefinitionHandle)fieldHandle, metadata, context, options);
} else {
var memberRef = metadata.GetMemberReference((SRM.MemberReferenceHandle)fieldHandle);
IType ty = memberRef.DecodeFieldSignature(new TypeProvider(context.CurrentAssembly), new GenericContext(context));
ty = ApplyAttributeTypeVisitor.ApplyAttributesToType(ty, context.Compilation,
memberRef.GetCustomAttributes(), metadata, options);
return ty;
}
}
public static IType Resolve(SRM.FieldDefinitionHandle fieldHandle,
SRM.MetadataReader metadata,
ITypeResolveContext context,
TypeSystemOptions options)
{
var fieldDef = metadata.GetFieldDefinition(fieldHandle);
IType ty = fieldDef.DecodeSignature(new TypeProvider(context.CurrentAssembly), new GenericContext(context));
ty = ApplyAttributeTypeVisitor.ApplyAttributesToType(ty, context.Compilation,
fieldDef.GetCustomAttributes(), metadata, options);
return ty;
}
}
/// <summary>
/// Represents an unresolved method signature.
/// </summary>
sealed class UnresolvedMethodSignature
{
readonly SRM.EntityHandle handle;
readonly SRM.MetadataReader metadata;
readonly TypeSystemOptions options;
public UnresolvedMethodSignature(SRM.MethodDefinitionHandle handle, SRM.MetadataReader metadata,
TypeSystemOptions options)
{
this.handle = handle;
this.metadata = metadata;
this.options = options;
}
public UnresolvedMethodSignature(SRM.PropertyDefinitionHandle handle, SRM.MetadataReader metadata,
TypeSystemOptions attributeOptions)
{
this.handle = handle;
this.metadata = metadata;
this.options = attributeOptions;
}
public SRM.MethodSignature<IType> Resolve(ITypeResolveContext context)
{
return (SRM.MethodSignature<IType>)context.Compilation.CacheManager.GetOrAddShared(
this, key => {
Debug.Assert(key == this);
switch (handle.Kind) {
case SRM.HandleKind.MethodDefinition:
return GetSignature(
metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)handle),
metadata, context, options
);
case SRM.HandleKind.PropertyDefinition:
return GetSignature(
metadata.GetPropertyDefinition((SRM.PropertyDefinitionHandle)handle),
metadata, context, options
);
default:
throw new InvalidOperationException();
}
}
);
}
public static SRM.MethodSignature<IType> GetSignature(SRM.MethodDefinition methodDef,
SRM.MetadataReader metadata, ITypeResolveContext context,
TypeSystemOptions options)
{
var typeProvider = new TypeProvider(context.CurrentAssembly);
var signature = methodDef.DecodeSignature(typeProvider, new GenericContext(context));
return ApplyAttributes(signature, methodDef.GetParameters(), context.Compilation, metadata, options);
}
public static SRM.MethodSignature<IType> GetSignature(SRM.PropertyDefinition propertyDef,
SRM.MetadataReader metadata, ITypeResolveContext context,
TypeSystemOptions options)
{
var typeProvider = new TypeProvider(context.CurrentAssembly);
var signature = propertyDef.DecodeSignature(typeProvider, new GenericContext(context));
var accessors = propertyDef.GetAccessors();
SRM.ParameterHandleCollection? parameterHandles = null;
if (!accessors.Getter.IsNil) {
var getter = metadata.GetMethodDefinition(accessors.Getter);
parameterHandles = getter.GetParameters();
} else {
if (!accessors.Setter.IsNil) {
var setter = metadata.GetMethodDefinition(accessors.Setter);
parameterHandles = setter.GetParameters();
}
}
return ApplyAttributes(signature, parameterHandles, context.Compilation, metadata, options);
}
static SRM.MethodSignature<IType> ApplyAttributes(SRM.MethodSignature<IType> signature, SRM.ParameterHandleCollection? parameterHandles, ICompilation compilation, SRM.MetadataReader metadata, TypeSystemOptions options)
{
SRM.CustomAttributeHandleCollection? returnTypeAttributes = null;
var parameterAttributes = new SRM.CustomAttributeHandleCollection?[signature.ParameterTypes.Length];
if (parameterHandles != null) {
foreach (var parameterHandle in parameterHandles) {
var par = metadata.GetParameter(parameterHandle);
if (par.SequenceNumber == 0) {
returnTypeAttributes = par.GetCustomAttributes();
} else if (par.SequenceNumber <= parameterAttributes.Length) {
parameterAttributes[par.SequenceNumber - 1] = par.GetCustomAttributes();
}
}
}
IType returnType = ApplyAttributeTypeVisitor.ApplyAttributesToType(
signature.ReturnType, compilation, returnTypeAttributes, metadata, options
);
var parameterTypes = signature.ParameterTypes.SelectWithIndex(
(i, p) => ApplyAttributeTypeVisitor.ApplyAttributesToType(
p, compilation, parameterAttributes[i], metadata, options
)
).ToImmutableArray();
return new SRM.MethodSignature<IType>(
signature.Header, returnType,
signature.RequiredParameterCount, signature.GenericParameterCount,
parameterTypes
);
}
}
sealed class SignatureParameterTypeReference : ITypeReference
{
readonly UnresolvedMethodSignature unresolvedSig;
readonly int index;
public SignatureParameterTypeReference(UnresolvedMethodSignature unresolvedSig, int index)
{
this.unresolvedSig = unresolvedSig;
this.index = index;
}
public IType Resolve(ITypeResolveContext context)
{
var sig = unresolvedSig.Resolve(context);
if (index < sig.ParameterTypes.Length)
return sig.ParameterTypes[index];
else
return SpecialType.UnknownType;
}
}
sealed class SignatureReturnTypeReference : ITypeReference
{
readonly UnresolvedMethodSignature unresolvedSig;
public SignatureReturnTypeReference(UnresolvedMethodSignature unresolvedSig)
{
this.unresolvedSig = unresolvedSig;
}
public IType Resolve(ITypeResolveContext context)
{
return unresolvedSig.Resolve(context).ReturnType;
}
}
}

30
ICSharpCode.Decompiler/TypeSystem/MetadataAssembly.cs

@ -237,17 +237,39 @@ namespace ICSharpCode.Decompiler.TypeSystem
public IType ResolveType(EntityHandle typeRefDefSpec, GenericContext context, TypeSystemOptions customOptions, CustomAttributeHandleCollection? typeAttributes = null) public IType ResolveType(EntityHandle typeRefDefSpec, GenericContext context, TypeSystemOptions customOptions, CustomAttributeHandleCollection? typeAttributes = null)
{ {
if (typeRefDefSpec.Kind == HandleKind.ExportedType) { if (typeRefDefSpec.IsNil)
return ResolveForwardedType(metadata.GetExportedType((ExportedTypeHandle)typeRefDefSpec)); return SpecialType.UnknownType;
IType ty;
switch (typeRefDefSpec.Kind) {
case HandleKind.TypeDefinition:
ty = TypeProvider.GetTypeFromDefinition(metadata, (TypeDefinitionHandle)typeRefDefSpec, 0);
break;
case HandleKind.TypeReference:
ty = TypeProvider.GetTypeFromReference(metadata, (TypeReferenceHandle)typeRefDefSpec, 0);
break;
case HandleKind.TypeSpecification:
var typeSpec = metadata.GetTypeSpecification((TypeSpecificationHandle)typeRefDefSpec);
ty = typeSpec.DecodeSignature(TypeProvider, context);
break;
case HandleKind.ExportedType:
return ResolveForwardedType(metadata.GetExportedType((ExportedTypeHandle)typeRefDefSpec));
default:
Debug.Fail("Not a type handle");
ty = SpecialType.UnknownType;
break;
} }
return MetadataTypeReference.Resolve(typeRefDefSpec, metadata, TypeProvider, context, customOptions, typeAttributes); ty = ApplyAttributeTypeVisitor.ApplyAttributesToType(ty, Compilation, typeAttributes, metadata, customOptions);
return ty;
} }
IType ResolveDeclaringType(EntityHandle declaringTypeReference, GenericContext context) IType ResolveDeclaringType(EntityHandle declaringTypeReference, GenericContext context)
{ {
// resolve without substituting dynamic/tuple types // resolve without substituting dynamic/tuple types
return ResolveType(declaringTypeReference, context, var ty = ResolveType(declaringTypeReference, context,
options & ~(TypeSystemOptions.Dynamic | TypeSystemOptions.Tuple)); options & ~(TypeSystemOptions.Dynamic | TypeSystemOptions.Tuple));
// but substitute tuple types in type arguments:
ty = ApplyAttributeTypeVisitor.ApplyAttributesToType(ty, Compilation, null, metadata, options, typeChildrenOnly: true);
return ty;
} }
#endregion #endregion

Loading…
Cancel
Save