Browse Source

Use target typing for tuples, where possible.

pull/1134/head
Daniel Grunwald 7 years ago
parent
commit
5cdd5ecdbc
  1. 6
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TupleTests.cs
  2. 105
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TupleTests.opt.roslyn.il
  3. 108
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TupleTests.roslyn.il
  4. 23
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  5. 31
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs
  6. 21
      ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs
  7. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  8. 57
      ICSharpCode.Decompiler/Semantics/TupleResolveResult.cs

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

@ -79,6 +79,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -79,6 +79,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public (int, int) AccessRest => (1, 2, 3, 4, 5, 6, 7, 8, 9).Rest;
public (string, object, Action) TargetTyping => (null, 1, delegate {
});
public object NotTargetTyping => ((string)null, (object)1, (Action)delegate {
});
public void UseDict()
{
if (TupleDict.Count > 10) {

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

@ -78,6 +78,51 @@ @@ -78,6 +78,51 @@
} // end of class OverloadResolution
.class auto ansi serializable sealed nested private beforefieldinit '<>c'
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.field public static initonly class ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c' '<>9'
.field public static class [mscorlib]System.Action '<>9__45_0'
.field public static class [mscorlib]System.Action '<>9__47_0'
.method private hidebysig specialname rtspecialname static
void .cctor() cil managed
{
// Code size 11 (0xb)
.maxstack 8
IL_0000: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c'::.ctor()
IL_0005: stsfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c' ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c'::'<>9'
IL_000a: ret
} // end of method '<>c'::.cctor
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method '<>c'::.ctor
.method assembly hidebysig instance void
'<get_TargetTyping>b__45_0'() cil managed
{
// Code size 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method '<>c'::'<get_TargetTyping>b__45_0'
.method assembly hidebysig instance void
'<get_NotTargetTyping>b__47_0'() cil managed
{
// Code size 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method '<>c'::'<get_NotTargetTyping>b__47_0'
} // end of class '<>c'
.field public valuetype [mscorlib]System.ValueTuple VT0
.field public valuetype [mscorlib]System.ValueTuple`1<int32> VT1
.field public valuetype [mscorlib]System.ValueTuple`8<int32,int32,int32,int32,int32,int32,int32,valuetype [mscorlib]System.ValueTuple> VT7EmptyRest
@ -307,6 +352,57 @@ @@ -307,6 +352,57 @@
IL_0019: ret
} // end of method TupleTests::get_AccessRest
.method public hidebysig specialname instance valuetype [mscorlib]System.ValueTuple`3<string,object,class [mscorlib]System.Action>
get_TargetTyping() cil managed
{
// Code size 44 (0x2c)
.maxstack 8
IL_0000: ldnull
IL_0001: ldc.i4.1
IL_0002: box [mscorlib]System.Int32
IL_0007: ldsfld class [mscorlib]System.Action ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c'::'<>9__45_0'
IL_000c: dup
IL_000d: brtrue.s IL_0026
IL_000f: pop
IL_0010: ldsfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c' ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c'::'<>9'
IL_0015: ldftn instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c'::'<get_TargetTyping>b__45_0'()
IL_001b: newobj instance void [mscorlib]System.Action::.ctor(object,
native int)
IL_0020: dup
IL_0021: stsfld class [mscorlib]System.Action ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c'::'<>9__45_0'
IL_0026: newobj instance void valuetype [mscorlib]System.ValueTuple`3<string,object,class [mscorlib]System.Action>::.ctor(!0,
!1,
!2)
IL_002b: ret
} // end of method TupleTests::get_TargetTyping
.method public hidebysig specialname instance object
get_NotTargetTyping() cil managed
{
// Code size 49 (0x31)
.maxstack 8
IL_0000: ldnull
IL_0001: ldc.i4.1
IL_0002: box [mscorlib]System.Int32
IL_0007: ldsfld class [mscorlib]System.Action ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c'::'<>9__47_0'
IL_000c: dup
IL_000d: brtrue.s IL_0026
IL_000f: pop
IL_0010: ldsfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c' ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c'::'<>9'
IL_0015: ldftn instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c'::'<get_NotTargetTyping>b__47_0'()
IL_001b: newobj instance void [mscorlib]System.Action::.ctor(object,
native int)
IL_0020: dup
IL_0021: stsfld class [mscorlib]System.Action ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c'::'<>9__47_0'
IL_0026: newobj instance void valuetype [mscorlib]System.ValueTuple`3<string,object,class [mscorlib]System.Action>::.ctor(!0,
!1,
!2)
IL_002b: box valuetype [mscorlib]System.ValueTuple`3<string,object,class [mscorlib]System.Action>
IL_0030: ret
} // end of method TupleTests::get_NotTargetTyping
.method public hidebysig instance void
UseDict() cil managed
{
@ -406,6 +502,15 @@ @@ -406,6 +502,15 @@
{
.get instance valuetype [mscorlib]System.ValueTuple`2<int32,int32> ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests::get_AccessRest()
} // end of property TupleTests::AccessRest
.property instance valuetype [mscorlib]System.ValueTuple`3<string,object,class [mscorlib]System.Action>
TargetTyping()
{
.get instance valuetype [mscorlib]System.ValueTuple`3<string,object,class [mscorlib]System.Action> ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests::get_TargetTyping()
} // end of property TupleTests::TargetTyping
.property instance object NotTargetTyping()
{
.get instance object ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests::get_NotTargetTyping()
} // end of property TupleTests::NotTargetTyping
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests

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

@ -81,6 +81,54 @@ @@ -81,6 +81,54 @@
} // end of class OverloadResolution
.class auto ansi serializable sealed nested private beforefieldinit '<>c'
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.field public static initonly class ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c' '<>9'
.field public static class [mscorlib]System.Action '<>9__45_0'
.field public static class [mscorlib]System.Action '<>9__47_0'
.method private hidebysig specialname rtspecialname static
void .cctor() cil managed
{
// Code size 11 (0xb)
.maxstack 8
IL_0000: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c'::.ctor()
IL_0005: stsfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c' ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c'::'<>9'
IL_000a: ret
} // end of method '<>c'::.cctor
.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 '<>c'::.ctor
.method assembly hidebysig instance void
'<get_TargetTyping>b__45_0'() cil managed
{
// Code size 2 (0x2)
.maxstack 8
IL_0000: nop
IL_0001: ret
} // end of method '<>c'::'<get_TargetTyping>b__45_0'
.method assembly hidebysig instance void
'<get_NotTargetTyping>b__47_0'() cil managed
{
// Code size 2 (0x2)
.maxstack 8
IL_0000: nop
IL_0001: ret
} // end of method '<>c'::'<get_NotTargetTyping>b__47_0'
} // end of class '<>c'
.field public valuetype [mscorlib]System.ValueTuple VT0
.field public valuetype [mscorlib]System.ValueTuple`1<int32> VT1
.field public valuetype [mscorlib]System.ValueTuple`8<int32,int32,int32,int32,int32,int32,int32,valuetype [mscorlib]System.ValueTuple> VT7EmptyRest
@ -310,6 +358,57 @@ @@ -310,6 +358,57 @@
IL_0019: ret
} // end of method TupleTests::get_AccessRest
.method public hidebysig specialname instance valuetype [mscorlib]System.ValueTuple`3<string,object,class [mscorlib]System.Action>
get_TargetTyping() cil managed
{
// Code size 44 (0x2c)
.maxstack 8
IL_0000: ldnull
IL_0001: ldc.i4.1
IL_0002: box [mscorlib]System.Int32
IL_0007: ldsfld class [mscorlib]System.Action ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c'::'<>9__45_0'
IL_000c: dup
IL_000d: brtrue.s IL_0026
IL_000f: pop
IL_0010: ldsfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c' ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c'::'<>9'
IL_0015: ldftn instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c'::'<get_TargetTyping>b__45_0'()
IL_001b: newobj instance void [mscorlib]System.Action::.ctor(object,
native int)
IL_0020: dup
IL_0021: stsfld class [mscorlib]System.Action ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c'::'<>9__45_0'
IL_0026: newobj instance void valuetype [mscorlib]System.ValueTuple`3<string,object,class [mscorlib]System.Action>::.ctor(!0,
!1,
!2)
IL_002b: ret
} // end of method TupleTests::get_TargetTyping
.method public hidebysig specialname instance object
get_NotTargetTyping() cil managed
{
// Code size 49 (0x31)
.maxstack 8
IL_0000: ldnull
IL_0001: ldc.i4.1
IL_0002: box [mscorlib]System.Int32
IL_0007: ldsfld class [mscorlib]System.Action ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c'::'<>9__47_0'
IL_000c: dup
IL_000d: brtrue.s IL_0026
IL_000f: pop
IL_0010: ldsfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c' ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c'::'<>9'
IL_0015: ldftn instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c'::'<get_NotTargetTyping>b__47_0'()
IL_001b: newobj instance void [mscorlib]System.Action::.ctor(object,
native int)
IL_0020: dup
IL_0021: stsfld class [mscorlib]System.Action ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests/'<>c'::'<>9__47_0'
IL_0026: newobj instance void valuetype [mscorlib]System.ValueTuple`3<string,object,class [mscorlib]System.Action>::.ctor(!0,
!1,
!2)
IL_002b: box valuetype [mscorlib]System.ValueTuple`3<string,object,class [mscorlib]System.Action>
IL_0030: ret
} // end of method TupleTests::get_NotTargetTyping
.method public hidebysig instance void
UseDict() cil managed
{
@ -424,6 +523,15 @@ @@ -424,6 +523,15 @@
{
.get instance valuetype [mscorlib]System.ValueTuple`2<int32,int32> ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests::get_AccessRest()
} // end of property TupleTests::AccessRest
.property instance valuetype [mscorlib]System.ValueTuple`3<string,object,class [mscorlib]System.Action>
TargetTyping()
{
.get instance valuetype [mscorlib]System.ValueTuple`3<string,object,class [mscorlib]System.Action> ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests::get_TargetTyping()
} // end of property TupleTests::TargetTyping
.property instance object NotTargetTyping()
{
.get instance object ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests::get_NotTargetTyping()
} // end of property TupleTests::NotTargetTyping
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.TupleTests

23
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.Decompiler.CSharp.Resolver;
@ -57,17 +58,21 @@ namespace ICSharpCode.Decompiler.CSharp @@ -57,17 +58,21 @@ namespace ICSharpCode.Decompiler.CSharp
return HandleDelegateConstruction(newobj);
}
if (settings.TupleTypes && TupleTransform.MatchTupleConstruction(inst as NewObj, out var tupleElements) && tupleElements.Length >= 2) {
var tupleType = TupleType.FromUnderlyingType(typeSystem.Compilation, inst.Method.DeclaringType);
Debug.Assert(tupleType != null, "MatchTupleConstruction should not success unless we got a valid tuple type.");
Debug.Assert(tupleType.ElementTypes.Length == tupleElements.Length);
var elementTypes = TupleType.GetTupleElementTypes(inst.Method.DeclaringType);
Debug.Assert(!elementTypes.IsDefault, "MatchTupleConstruction should not success unless we got a valid tuple type.");
Debug.Assert(elementTypes.Length == tupleElements.Length);
var tuple = new TupleExpression();
foreach (var (element, elementType) in tupleElements.Zip(tupleType.ElementTypes)) {
tuple.Elements.Add(
expressionBuilder.Translate(element, elementType)
.ConvertTo(elementType, expressionBuilder)
);
var elementRRs = new List<ResolveResult>();
foreach (var (element, elementType) in tupleElements.Zip(elementTypes)) {
var translatedElement = expressionBuilder.Translate(element, elementType)
.ConvertTo(elementType, expressionBuilder, allowImplicitConversion: true);
tuple.Elements.Add(translatedElement.Expression);
elementRRs.Add(translatedElement.ResolveResult);
}
return tuple.WithRR(new ResolveResult(tupleType)).WithILInstruction(inst);
return tuple.WithRR(new TupleResolveResult(
expressionBuilder.compilation,
elementRRs.ToImmutableArray()
)).WithILInstruction(inst);
}
return Build(inst.OpCode, inst.Method, inst.Arguments, inst.ConstrainedTo).WithILInstruction(inst);
}

31
ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs

@ -110,6 +110,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -110,6 +110,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
if (c != Conversion.None) return c;
}
} else {
if (allowTuple && resolveResult is TupleResolveResult tupleRR) {
c = TupleConversion(tupleRR, toType, isExplicit: false);
if (c != Conversion.None)
return c;
}
if (allowUserDefined && allowTuple) {
// if allowUserDefined and allowTuple are true, we might as well use the cache
c = ImplicitConversion(resolveResult.Type, toType);
@ -244,6 +249,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -244,6 +249,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
Conversion c = ImplicitConversion(resolveResult, toType, allowUserDefined: false, allowTuple: false);
if (c != Conversion.None)
return c;
if (resolveResult is TupleResolveResult tupleRR) {
c = TupleConversion(tupleRR, toType, isExplicit: true);
if (c != Conversion.None)
return c;
}
c = ExplicitConversionImpl(resolveResult.Type, toType);
if (c != Conversion.None)
return c;
@ -1127,6 +1137,27 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -1127,6 +1137,27 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
#endregion
#region Tuple Conversion
Conversion TupleConversion(TupleResolveResult fromRR, IType toType, bool isExplicit)
{
var fromElements = fromRR.Elements;
var toElements = TupleType.GetTupleElementTypes(toType);
if (toElements.IsDefault || fromElements.Length != toElements.Length)
return Conversion.None;
Conversion[] elementConversions = new Conversion[fromElements.Length];
for (int i = 0; i < elementConversions.Length; i++) {
Conversion c;
if (isExplicit) {
c = ExplicitConversion(fromElements[i], toElements[i]);
} else {
c = ImplicitConversion(fromElements[i], toElements[i]);
}
if (!c.IsValid)
return Conversion.None;
elementConversions[i] = c;
}
return Conversion.TupleConversion(elementConversions.ToImmutableArray());
}
Conversion TupleConversion(IType fromType, IType toType, bool isExplicit)
{
var fromElements = TupleType.GetTupleElementTypes(fromType);

21
ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.Decompiler.CSharp.Syntax;
@ -25,6 +26,7 @@ using ICSharpCode.Decompiler.CSharp.Transforms; @@ -25,6 +26,7 @@ using ICSharpCode.Decompiler.CSharp.Transforms;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.CSharp
{
@ -198,9 +200,24 @@ namespace ICSharpCode.Decompiler.CSharp @@ -198,9 +200,24 @@ namespace ICSharpCode.Decompiler.CSharp
}
return this;
}
if (targetType.Kind == TypeKind.Unknown || targetType.Kind == TypeKind.Void) {
if (targetType.Kind == TypeKind.Unknown || targetType.Kind == TypeKind.Void || targetType.Kind == TypeKind.None) {
return this; // don't attempt to insert cast to '?' or 'void' as these are not valid.
}
if (Expression is TupleExpression tupleExpr && targetType is TupleType targetTupleType
&& tupleExpr.Elements.Count == targetTupleType.ElementTypes.Length)
{
// Conversion of a tuple literal: convert element-wise
var newTupleExpr = new TupleExpression();
var newElementRRs = new List<ResolveResult>();
foreach (var (elementExpr, elementTargetType) in tupleExpr.Elements.Zip(targetTupleType.ElementTypes)) {
var newElementExpr = new TranslatedExpression(elementExpr.Detach())
.ConvertTo(elementTargetType, expressionBuilder, checkForOverflow, allowImplicitConversion);
newTupleExpr.Elements.Add(newElementExpr.Expression);
newElementRRs.Add(newElementExpr.ResolveResult);
}
return newTupleExpr.WithILInstruction(this.ILInstructions)
.WithRR(new TupleResolveResult(expressionBuilder.compilation, newElementRRs.ToImmutableArray()));
}
var compilation = expressionBuilder.compilation;
var conversions = Resolver.CSharpConversions.Get(compilation);
if (ResolveResult is ConversionResolveResult conv && Expression is CastExpression cast2 && conv.Conversion.IsBoxingConversion && conversions.IsBoxingConversion(conv.Input.Type, targetType)) {
@ -357,7 +374,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -357,7 +374,7 @@ namespace ICSharpCode.Decompiler.CSharp
.WithILInstruction(this.ILInstructions)
.WithRR(new ConstantResolveResult(targetType, null));
}
if (allowImplicitConversion && conversions.ImplicitConversion(type, targetType).IsValid) {
if (allowImplicitConversion && conversions.ImplicitConversion(ResolveResult, targetType).IsValid) {
return this;
}
var castExpr = new CastExpression(expressionBuilder.ConvertType(targetType), Expression);

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -326,6 +326,7 @@ @@ -326,6 +326,7 @@
<Compile Include="IL\Transforms\StatementTransform.cs" />
<Compile Include="IL\Transforms\TransformCollectionAndObjectInitializers.cs" />
<Compile Include="Output\TextTokenWriter.cs" />
<Compile Include="Semantics\TupleResolveResult.cs" />
<Compile Include="TypeSystem\NormalizeTypeVisitor.cs" />
<Compile Include="TypeSystem\TupleType.cs" />
<Compile Include="Util\GraphVizGraph.cs" />

57
ICSharpCode.Decompiler/Semantics/TupleResolveResult.cs

@ -0,0 +1,57 @@ @@ -0,0 +1,57 @@
// 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 System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.Semantics
{
/// <summary>
/// Resolve result for a C# 7 tuple literal.
/// </summary>
public class TupleResolveResult : ResolveResult
{
public ImmutableArray<ResolveResult> Elements { get; }
public TupleResolveResult(ICompilation compilation,
ImmutableArray<ResolveResult> elements,
ImmutableArray<string> elementNames = default(ImmutableArray<string>))
: base(GetTupleType(compilation, elements, elementNames))
{
this.Elements = elements;
}
public override IEnumerable<ResolveResult> GetChildResults()
{
return Elements;
}
static IType GetTupleType(ICompilation compilation, ImmutableArray<ResolveResult> elements, ImmutableArray<string> elementNames)
{
if (elements.Any(e => e.Type.Kind == TypeKind.None || e.Type.Kind == TypeKind.Null))
return SpecialType.NoType;
else
return new TupleType(compilation, elements.Select(e => e.Type).ToImmutableArray(), elementNames);
}
}
}
Loading…
Cancel
Save