fsharp
fsharp copied to clipboard
[Regression] `FsiEvaluationSession` can't find method in hosting assembly
A console app that uses FsiEvaluationSession
can't execute a method defined in the console app. The behavior worked in FSharp.Compiler.Service
version 41.0.2 and started to fail in version 41.0.3. I've traced the failure back to commit 45518d21e1e135693ad3d9d32744792ba151aef4 from #12722.
Full repro. N.b., the repro as given here passes and shows the output of
value: "3"
and if you simply update the FSharp.Compiler.Service
package version to 41.0.3 then the output becomes:
exception: System.MissingMethodException: Method not found: 'System.Int32 FSharpMissingMethod.MyModule.add(System.Int32, System.Int32)'.
at <StartupCode$FSI_0001>.$FSI_0001.main@()
Project.fsproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="MyModule.fs" />
<Compile Include="Program.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="FSharp.Compiler.Service" Version="41.0.2" />
</ItemGroup>
</Project>
MyModule.fs:
namespace FSharpMissingMethod
type Sentinel () =
let x = ()
module MyModule =
let add a b = a + b
Program.fs:
module Main
open FSharp.Compiler.Interactive.Shell
open System.IO
open System.Threading
[<EntryPoint>]
let main args =
let config = FsiEvaluationSession.GetDefaultConfiguration()
let argv = [|
typeof<FSharpMissingMethod.Sentinel>.Assembly.Location
"--noninteractive"
"--targetprofile:netcore"
"--langversion:preview"
"/usesdkrefs-"
|]
let fsi = FsiEvaluationSession.Create(config, argv, TextReader.Null, TextWriter.Null, TextWriter.Null)
let assemblyPath = typeof<FSharpMissingMethod.Sentinel>.Assembly.Location.Replace("\\", "/")
let code = $@"
#r ""{assemblyPath}""
FSharpMissingMethod.MyModule.add 1 2"
let ch, errors = fsi.EvalInteractionNonThrowing(code, CancellationToken.None)
errors
|> Array.iter (fun e -> printfn "error: %A" e)
match ch with
| Choice1Of2 v ->
let v =
match v with
| Some v -> sprintf "%A" v.ReflectionValue
| None -> "(none)"
printfn "value: %A" v
| Choice2Of2 e -> printfn "exception: %A" e
0
@brettfo will adding --multiemit-
to the FsiEvaluationSession
's args work for you as a workaround, while we investigating? This will is pretty much a fallback to the "old" way of emitting assemblies.
Indeed --multiemit-
allows us to work around the issue for now.
We have run into the same issue, and --multiemit-
worked for us as well. Interestingly, it only happened once deployed via docker - running it on development machines (even using release builds) worked without that flag.
The disadvantage of using --multiemit-
is that you lose the error line number in stack traces of the script itself:
Change the code to evaluate: let code = "1/0"
the first run was using --multiemit-
, the second not:
Here is a discussion on that topic https://github.com/dotnet/fsharp/discussions/13293