Skip to content

NativeAOT: Type.BaseType throws exeption when there is no basetype in reflection-free-mode #66810

Closed
@josephmoresena

Description

@josephmoresena

Description

I am trying to check if a type is or inherits from another. Type.IsAssignableTo(Type) and Type.IsSubclassOf(Type) are not on the list of working APIs, but Type.BaseType is.
The problem occurs when I try to get the base type of a type that doesn't have one.

Reproduction Steps

Classes.cs

public abstract class A { }
public class B : A { }
public class C : A { }
public abstract class Z : B { }
public class Y : Z { }
public class X : C { }

public static class Extensions
{
    public static Boolean IsOrInheritsFrom(this Type type, Type expectedType)
    {
        Type? baseType = type;
        while (baseType is not null)
        {
            if (baseType.Equals(expectedType))
                return true;
            baseType = baseType?.BaseType;
        }
        return false;
    }
}

Program.cs

Dictionary<Type, String> types = new()
{
    { typeof(A), nameof(A) },
    { typeof(B), nameof(B) },
    { typeof(C), nameof(C) },
    { typeof(Z), nameof(Z) },
    { typeof(Y), nameof(Y) },
    { typeof(X), nameof(X) },
};

foreach (Type type in types.Keys)
    foreach (Type type2 in types.Keys)
        Console.WriteLine($"{types[type]} -> {type.IsOrInheritsFrom(type2)} <- {types[type2]}");

NativeAOTIssue.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.DotNet.ILCompiler" Version="7.0.0-*" />
  </ItemGroup>
	
</Project>

Compile the project using NativeAOT dotnet publish -r win-x64 /p:IlcDisableReflection=true
Execute native binary .\bin\Debug\net6.0\win-x64\publish\NativeAOTIssue.exe

Expected behavior

A -> True <- A
A -> False <- B
A -> False <- C
A -> False <- Z
A -> False <- Y
A -> False <- X
B -> True <- A
B -> True <- B
B -> False <- C
B -> False <- Z
B -> False <- Y
B -> False <- X
C -> True <- A
C -> False <- B
C -> True <- C
C -> False <- Z
C -> False <- Y
C -> False <- X
Z -> True <- A
Z -> True <- B
Z -> False <- C
Z -> True <- Z
Z -> False <- Y
Z -> False <- X
Y -> True <- A
Y -> True <- B
Y -> False <- C
Y -> True <- Z
Y -> True <- Y
Y -> False <- X
X -> True <- A
X -> False <- B
X -> True <- C
X -> False <- Z
X -> False <- Y
X -> True <- X

Actual behavior

A -> True <- A
Unhandled Exception: EETypeRva:0x0021E3B8: Arg_NullReferenceException
   at Internal.Runtime.MethodTable.get_Kind() + 0xf
   at Internal.Runtime.MethodTable.get_IsGenericTypeDefinition() + 0x18
   at System.EETypePtr.get_IsGenericTypeDefinition() + 0x1b
   at Internal.Runtime.Augments.RuntimeAugments.TryGetBaseType(RuntimeTypeHandle, RuntimeTypeHandle&) + 0x45
   at Internal.Reflection.RuntimeTypeInfo.get_BaseType() + 0x29
   at Extensions.IsOrInheritsFrom(Type, Type) + 0x91
   at Program.<Main>$(String[]) + 0x3bc
   at NativeAOTIssue!<BaseAddress>+0x1c6907
   at NativeAOTIssue!<BaseAddress>+0x1c6995

Regression?

No response

Known Workarounds

No response

Configuration

.NET: 6.0
OS: Windows 10 21H2
Arch: x64

Other information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions