Skip to content

Compiler error Constructor on type 'FSharp.DependencyManager.Nuget.FSharpDependencyManager' not found. #13923

@roboz0r

Description

@roboz0r

I am building a tool to enable F# scripting within a native windows application. I've run into an issue with the ability to use #r nuget directives.

I have two different ways I am calling the compiler against the script files:

  1. Producing a dynamic assembly

    let tryCompile scriptPath = 
        let compilerArgs (scriptPath:string) = 
            [|
                "-a"; scriptPath
                "--targetprofile:netcore"
                "--target:module"
            |]
        async {
            let compilerArgs = compilerArgs scriptPath
            let! errors, retCode, maybeAssembly = 
                checker.CompileToDynamicAssembly(compilerArgs, None)
    
            return
                match maybeAssembly with
                | Some a -> 
                    Ok (a, errors)
                | None -> 
                    Error (retCode, scriptPath, errors)
        }
  2. Producing a dll (to enable debugging)

    let private compilerArgs (scriptPath:string) = 
        let dll = Path.Combine(Path.GetDirectoryName(scriptPath), "bin", $"%O{Guid.NewGuid()}.dll")
        [|
            "-a"; scriptPath
            $"-o:%s{dll}"
            "--targetprofile:netcore"
            "--target:library"
            "--debug:full"
        |], dll
    
    let tryCompileCtx (loadCtx:AssemblyLoadContext) scriptPath = 
        async {
            let compilerArgs, dllPath = compilerArgs scriptPath
    
            let! errors, retCode = checker.Compile(compilerArgs)
            let maybeAssembly = 
                match retCode with
                | 0 -> loadCtx.LoadFromAssemblyPath(dllPath) |> Some
                | _ -> None
    
            return
                match maybeAssembly with
                | Some a -> 
                    Ok (a, errors)
                | None -> 
                    Error (retCode, scriptPath, errors)
        }

Both of these versions of the code pass basic tests to compile and run the following script in the test environment (running with Visual Studio):

#r "nuget: FSharp.Data, 4.2.8" 

open FSharp.Data

let getSomeData() : string =
    let resp = Http.Request "https://en.wikipedia.org/wiki/F_Sharp_(programming_language)"
    match resp.Body with
    | Text text -> 
        text.[0..100]
    | Binary _ -> "Shouldn't be binary"

However, when attempting to compile the same script calling tryCompileCtx in the native hosted environment I get the following errors (using tryCompile works as expected):

  1. Using FSharp.Core 6.0.3, FSharp.Compiler.Service 41.0.3

    18:45:08.2591: Compilation of ...\main.fsx failed with code: 1
    18:45:08.2654: ...\main.fsx (1,1)-(1,31) parse error Constructor on type 'FSharp.DependencyManager.Nuget.FSharpDependencyManager' not found.
    
    
  2. Using FSharp.Core 6.0.6, FSharp.Compiler.Service 41.0.6

    18:55:10.5977: Compilation of ...\main.fsx failed with code: 1
    18:55:10.6025: ...\main.fsx (1,1)-(1,31) parse error Constructor on type 'FSharp.DependencyManager.Nuget.FSharpDependencyManager' not found.
    18:55:10.6030: ...\main.fsx (1,1)-(1,31) parse error Invalid directive. Expected '#r "<file-or-assembly>"'.
    

Based on the phrasing of the errors and the fact that it is different between 41.0.3 and 41.0.6 I'm fairly confident the error originates from an exception thrown in DependencyProvider.fs. However I have no idea how to track it down further than that or what to do about it.

```fsharp
let instance = Activator.CreateInstance(theType, [| outputDir :> obj |]) // on 41.0.3
let instance = // on 41.0.6
    if not(isNull (theType.GetConstructor([|typeof<string option>; typeof<bool>|]))) then
        Activator.CreateInstance(theType, [| outputDir :> obj; useResultsCache :> obj |])
    else
        Activator.CreateInstance(theType, [| outputDir :> obj |])
```

Compiling a simple script like let hello name = $"Hello, %s{name}" works as expected in all cases.

Is this a bug or is there some additional configuration I need to provide so that #r nuget directives will work as expected?

If it's relevant, I'm running:

  • Windows 10 21H2 19044.2006
  • dotnet --version 6.0.401.

Metadata

Metadata

Assignees

Type

Projects

Status

New

Relationships

None yet

Development

No branches or pull requests

Issue actions