Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

F# interactive fails to load proper project "version" when using multiple scripts load #13866

Closed
jkone27 opened this issue Sep 9, 2022 · 9 comments
Assignees
Labels
Area-FSI Bug Impact-Low (Internal MS Team use only) Describes an issue with limited impact on existing code.
Milestone

Comments

@jkone27
Copy link
Contributor

jkone27 commented Sep 9, 2022

image

I get this behaviour when referencing multiple scripts from different files

image

i have a single Domain.fsx which i load in multiple files and then open as open Domain

// Domain.fsx
type Account = {
    Email: string
    Name: string
    Password : string
}

I am not sure why is not possible to load Domain, ionide in vscode shows no errors.

//Script.fsx


//load other scripts
#load "Domain.fsx"
#load "Dto.fsx"
#load "Infrastructure.fsx"

//..

open Domain
open Dto
open Infrastructure

note: restarting ionide - closing/reopening vscode doesnt help

@jkone27 jkone27 added the Bug label Sep 9, 2022
@jkone27 jkone27 changed the title F# interactive fails to load proper project "version" when r F# interactive fails to load proper project "version" when using multiple scripts load Sep 9, 2022
@vzarytovskii vzarytovskii added this to the Backlog milestone Sep 9, 2022
@abonie
Copy link
Member

abonie commented Sep 12, 2022

I could not repro this issue with information provided.

@jkone27: Would it be possible for you to narrow it down to a minimal sequence of steps that can reproduce this bug?

@jkone27
Copy link
Contributor Author

jkone27 commented Sep 13, 2022

reproduce-load-issue.zip

@abonie abonie self-assigned this Sep 14, 2022
@abonie
Copy link
Member

abonie commented Sep 14, 2022

So far I got it down to a fairly small repro, four script files still needed:

A.fsx:
#load "Domain.fsx"

let a = Domain.T

B.fsx:
#load "Domain.fsx"

let b = Domain.T

Domain.fsx:
type T = T

Script.fsx:
#load "A.fsx"
#load "B.fsx"

A.a = B.b

~same error:

> dotnet fsi Script.fsx
Script.fsx(4,7): error FS0001: This expression was expected to have type
    'FSI_0001.Domain.T'
but here has type
    'FSI_0002.Domain.T'

@abonie
Copy link
Member

abonie commented Sep 16, 2022

This unfortunately seems to currently be by design for fsi - each time a script is loaded it gets wrapped in a new outer namespace. It seems to have been this way since dotnet 5 at least, maybe forever.

Fixing this would significantly improve fsi scripting story IMO, but it is more of a feature request that would have to be submitted as a proposal at fslang-suggestions. And it would have to account for both interactive sessions with fsi and running a script with fsi ScriptName.fsx as well as for a case when script file has changed in between loads. @jkone27 I encourage you to submit a suggestion there if you have time to write it up.


Sidenote: F# language specification describes how scripts should behave when compiled and that includes loading same script file multiple times:

Script files may add other signature, implementation, and script files to the list of sources by using
the #load directive. Files are compiled in the same order that was passed to the compiler, except
that each script is searched for #load directives and the loaded files are placed before the script, in
the order they appear in the script. If a filename appears in more than one #load directive, the file is
placed in the list only once, at the position it first appeared.

and in fact, when compiled with fsc.exe Script.fsx, the code I pasted above runs without this type error. However, that's not even a suitable work around as far as I am concerned. And there's nothing about semantics of running scripts with fsi in the spec.

@abonie
Copy link
Member

abonie commented Sep 20, 2022

I believe I've found a viable workaround:
In Script.fsx replace multiple #loads:

#load "Domain.fsx"
#load "Dto.fsx"
#load "Infrastructure.fsx"

with one:

#load "Domain.fsx" "Dto.fsx" "Infrastructure.fsx"

I am not yet convinced if this is always a feasible solution to these kinds of issues, but @jkone27, let me know if it works for you

@jkone27
Copy link
Contributor Author

jkone27 commented Sep 20, 2022

Yes this workaround works! thanks a LOT 👍 💚

@abonie abonie added Impact-Low (Internal MS Team use only) Describes an issue with limited impact on existing code. and removed Needs-Repro labels Sep 21, 2022
@dsyme
Copy link
Contributor

dsyme commented Sep 23, 2022

Please note the above is the correct approach

Closing as by-design.

@dsyme dsyme closed this as completed Sep 23, 2022
@jkone27
Copy link
Contributor Author

jkone27 commented Sep 30, 2022

Thanks, @abonie just suggesting also for new users, maybe the compiler error should make this design decision more explicit to the user, or suggest this option if there is a multiline load

#load
#load 

--> compiler fail with

please replace multiline #load directives with a single load# directive in your script file ,  
#load supports multiple scripts in the same line, example: `#load "first.fsx" "second.fsx"`

@smoothdeveloper
Copy link
Contributor

@jkone27 I believe there are subtleties about how those directives impact the evaluation, that would make such adjustment problematic, on top of backward compatibility.

Adjusting https://learn.microsoft.com/en-us/dotnet/fsharp/tools/fsharp-interactive/#f-interactive-directive-reference so it shows that several files can be loaded seems to be a good solution to make it explicit, what can be done with this directive.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-FSI Bug Impact-Low (Internal MS Team use only) Describes an issue with limited impact on existing code.
Projects
Archived in project
Development

No branches or pull requests

5 participants