fsharp icon indicating copy to clipboard operation
fsharp copied to clipboard

TypeLoadException when accessing CustomAttributeData.ConstructorArguments in fsi

Open Jand42 opened this issue 4 months ago • 2 comments

Repro steps

Simple reproduction, in dotnet fsi with multiemit on (as by default)

// run this in one prompt:

type MyCustomLogic() =
    member this.DoSomething() = ()

type MyAnnotation(typ: System.Type) =
    inherit System.Attribute()

// run this in another prompt:

[<MyAnnotation(typeof<MyCustomLogic>)>]
let getValue() = 42 

match <@ getValue() @> with
| FSharp.Quotations.Patterns.Call(_, methodInfo, _) ->
    methodInfo.GetCustomAttributesData() 
    |> Seq.iter (fun a -> a.ConstructorArguments |> Seq.iter (printfn "%A")) // fails with System.TypeLoadException
| _ -> ()

Expected behavior

If the referenced type and the attribute usage is in the same prompt, then there is no error. IL generation should correctly recognize which transient assembly a type referenced via typeof used for an attribute constructor is defined in.

Actual behavior

Error is like System.TypeLoadException: Could not resolve type 'FSI_0003+MyCustomLogic' in assembly 'FSI-ASSEMBLY, Version=0.0.0.32763, Culture=neutral, PublicKeyToken=null'. This shows that the MyCustomLogic type is tried to be resolved from the transient assembly where the attribute is used, not where it is properly defined.

Known workarounds

Using --multiemit- argument for starting fsi.

Related information

Tested on dotnet SDKs 9.0.305 and 10.0.100-rc.1.25451.107 on Windows 11, both within and outside of Visual Studio.

Jand42 avatar Sep 19 '25 14:09 Jand42

I assume the issue is that each submission is a new assembly emitted (hence the version bump you see).

Not entirely sure what will the fix be.

vzarytovskii avatar Sep 19 '25 17:09 vzarytovskii

Yes, the problem is the version mismatch between two transient assemblies. The type reference on the attribute is created pointing to the current one, even though it should be the earlier one where the referenced type is actually defined.

Jand42 avatar Sep 20 '25 08:09 Jand42