MergeSimilarTypes: add support for more kinds of types

This commit is contained in:
Daniel Grunwald
2026-08-30 12:09:40 +02:00
parent 26f2a22367
commit fa3de7bfa4
2 changed files with 75 additions and 0 deletions
@@ -23,6 +23,7 @@ using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.CSharp.Resolver;
using ICSharpCode.Decompiler.Metadata;
@@ -713,6 +714,15 @@ namespace ICSharpCode.Decompiler.Tests.Semantics
ImmutableArray.CreateRange(elementNames));
}
FunctionPointerType MakeFunctionPointerType(ICompilation comp, IType returnType)
{
return new FunctionPointerType(
(MetadataModule)comp.MainModule,
SignatureCallingConvention.Default, ImmutableArray<IType>.Empty,
returnType, returnIsRefReadOnly: false,
ImmutableArray<IType>.Empty, ImmutableArray<ReferenceKind>.Empty);
}
[Test]
public void BestCommonTypeMergesTupleElementNames()
{
@@ -730,6 +740,21 @@ namespace ICSharpCode.Decompiler.Tests.Semantics
Assert.That(success);
}
[Test]
public void BestCommonTypeMergesFunctionPointerTupleElementNames()
{
var comp = RefAssemblyCompilation.Instance;
var inference = new TypeInference(comp);
Assert.That(
inference.GetBestCommonType(new[] {
new ResolveResult(MakeFunctionPointerType(comp, MakeTupleType(comp, "a", "b"))),
new ResolveResult(MakeFunctionPointerType(comp, MakeTupleType(comp, "a", "c")))
}, out bool success),
Is.EqualTo(MakeFunctionPointerType(comp, MakeTupleType(comp, "a", null))));
Assert.That(success);
}
[Test]
public void FixingMergesTupleElementNamesOfExactAndLowerBounds()
{
@@ -1101,6 +1101,15 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
var nullability = MergeNullability(arrA.Nullability, arrB.Nullability, variance);
return new ArrayType(arrA.Compilation, mergedElem, arrA.Dimensions, nullability);
}
if (a is ByReferenceType refA && b is ByReferenceType refB)
{
var mergedElem = MergeSimilarTypes(
refA.ElementType, refB.ElementType,
variance.Combine(VarianceModifier.Invariant));
if (mergedElem == null)
return null;
return new ByReferenceType(mergedElem);
}
if (a is PointerType ptrA && b is PointerType ptrB)
{
var mergedElem = MergeSimilarTypes(
@@ -1110,6 +1119,47 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
return null;
return new PointerType(mergedElem);
}
if (a is FunctionPointerType fnPtrA && b is FunctionPointerType fnPtrB
&& fnPtrA.CallingConvention == fnPtrB.CallingConvention
&& fnPtrA.CustomCallingConventions.SequenceEqual(fnPtrB.CustomCallingConventions)
&& fnPtrA.ReturnIsRefReadOnly == fnPtrB.ReturnIsRefReadOnly
&& fnPtrA.ParameterTypes.Length == fnPtrB.ParameterTypes.Length
&& fnPtrA.ParameterReferenceKinds.SequenceEqual(fnPtrB.ParameterReferenceKinds))
{
var mergedReturn = MergeSimilarTypes(
fnPtrA.ReturnType, fnPtrB.ReturnType,
variance.Combine(VarianceModifier.Covariant));
if (mergedReturn == null)
return null;
var mergedParameters = ImmutableArray.CreateBuilder<IType>(fnPtrA.ParameterTypes.Length);
for (int i = 0; i < fnPtrA.ParameterTypes.Length; i++)
{
var mergedParameter = MergeSimilarTypes(
fnPtrA.ParameterTypes[i], fnPtrB.ParameterTypes[i],
variance.Combine(VarianceModifier.Contravariant));
if (mergedParameter == null)
return null;
mergedParameters.Add(mergedParameter);
}
return fnPtrA.WithSignature(mergedReturn, mergedParameters.MoveToImmutable());
}
if (a is ModifiedType modA && b is ModifiedType modB
&& modA.Kind == modB.Kind
&& modA.Modifier.Equals(modB.Modifier))
{
var mergedElem = MergeSimilarTypes(modA.ElementType, modB.ElementType, variance);
if (mergedElem == null)
return null;
return new ModifiedType(modA.Modifier, mergedElem, modA.Kind == TypeKind.ModReq);
}
if (a is UnknownType unknownTypeA && b is UnknownType unknownTypeB
&& unknownTypeA.FullTypeName == unknownTypeB.FullTypeName)
{
if (unknownTypeA.IsReferenceType == unknownTypeB.IsReferenceType)
return unknownTypeA;
else
return unknownTypeA.WithoutReferenceTypeKnowledge();
}
return null;
}