dotnet / fsharp

The F# compiler, F# core library, F# language service, and F# tooling integration for Visual Studio
https://dotnet.microsoft.com/languages/fsharp
MIT License
3.94k stars 788 forks source link

#r "nuget: .." doesn't set ResolutionFolder correctly when instantiating type providers #10865

Open dsyme opened 3 years ago

dsyme commented 3 years ago

See https://github.com/fsharp/FSharp.Data/issues/1340

When referencing a package containing type providers using #r "nuget: ..." from a script, the ResolutionFolder of the TypeProviderConfig is not set correctly - it should be set to the directory of the script making the origininating reference, but is instead set to the directory the temporary hidden script generated through the resolution of the #r "nuget: ..."

Some type providers provide override mechanism for the ResolutionFolder which can be used as a workaround. For example this works:

#r "nuget: FSharp.Data"

open FSharp.Data

type Stocks = CsvProvider<"data/MSFT.csv", ResolutionFolder= __SOURCE_DIRECTORY__ >
let msft = Stocks.GetSample()

msft.Rows |> Seq.head

but this does not:

#r "nuget: FSharp.Data"

open FSharp.Data

type Stocks = CsvProvider<"data/MSFT.csv">
let msft = Stocks.GetSample()

msft.Rows |> Seq.head
dsyme commented 3 years ago

Note I haven't fully validated that it's the F# compiler causing the incorrect instantiation, the above is based on reviewing the relevant code in FSHarp.Data and concluding that it must be an incorrect value for ResolutionFolder

dsyme commented 3 years ago

Notes using dotnet/fsharp main

  1. Script editing, Project editing, Project compilation

These seems to set ResolutionFolder correctly

  1. Interactive execution

e.g. artifacts\bin\fsi\Debug\net472\fsi.exe c:\misc\a.fsx

This is setting ResolutionFolder to C:\\Users\\Administrator\\AppData\\Local\\Temp\\nuget\\27164--ec6048ac-4d32-4dec-bdda-205b40cc3455" - this is one part of the bug. The is related to this used in ProcessMetaCommandsFromInputAsInteractiveCommands

let internal WithImplicitHome (tcConfigB, dir) f = 
    let old = tcConfigB.implicitIncludeDir 
    tcConfigB.implicitIncludeDir <- dir;
    try f() 
    finally tcConfigB.implicitIncludeDir <- old

This "change of implied working directory" is not correct for most #load but is not correct for scripts generated from package loading which, logically speaking, should be processed as if they were in the same directory as the script doing the #r "nuget: ..."

dsyme commented 3 years ago

OK, I can see a fix to propose

@KevinRansom I'll catch you on teams

cartermp commented 3 years ago

@dsyme @KevinRansom I will put this into 16.10 because we should get this done and unblock critical pieces of the TP ecosystem like fsharp.data

cartermp commented 3 years ago

This also impacts SqlProvider I believe: https://devblogs.microsoft.com/dotnet/f-and-f-tools-update-for-visual-studio-16-9/#comment-8793