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.93k stars 787 forks source link

After upgrading to SDK 2.1.401 compilation of solution using implicit FSharp.Core references fails #5595

Closed dsyme closed 5 years ago

dsyme commented 6 years ago

Repro steps:

  1. With VS 15.7

    a. create F# library project (implicitly referencing FSharp.Core 4.3.4) b. reference it from C# project and add explicit FSharp.Core reference in C# project using right-click manage nuget package tooling (C# project explicitly references FSharp.Core 4.3.4)

  2. Upgrade to 15.8 (i.e. upgrade your .NET SDK).

Expected: Your project compiles

Actual: Your project no longer compiles with the error below, and you have little no idea why, since there is no mention of FSharp.Core 4.5.2 anywhere in your project files. The user will probably just upgrade everything to 4.5.2, but there are plenty of situations where that will inflict pain further down the line (e.g. perhaps there were other reasons why the C# app was using 4.3.4).

F# project file prior to .NET SDK upgrade:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Compile Include="Library.fs" />
  </ItemGroup>

</Project>

C# project file prior to .NET SDK upgrade:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="FSharp.Core" Version="4.3.4" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\ClassLibrary3\ClassLibrary3.fsproj" />
  </ItemGroup>

</Project>

Workarounds

Always make the FSharp.Core version explicit in all your F# projects by using, for example:

<PackageReference Update="FSharp.Core" Version="4.3.4" />

You can also use

<DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>

<PackageReference Include="FSharp.Core" Version="4.3.4" />

Old text

After upgrading to Visual Studio 15.8 and .NET SDK 2.1.401, FSharp.Data no longer compiled, https://github.com/fsharp/FSharp.Data/pull/1200 and https://github.com/fsharp/FSharp.Data/pull/1195

Previously the F# project files just had

<PackageReference Include="FSharp.Core" Version="4.3.*" />

We assumed this was enough to cause the implicit FSharp.Core reference to be disabled. Anyway, upgrading to 15.8 caused a confusing build failure because suddenly 4.5.0 was referenced.

The solution was to add

<DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>

I'd appreciate confirmation that this was always necessary and that there hasn't been a change here.

As an aside, some of the best people in the F# community were flummoxed by this. It makes me sceptical that implicit FSharp.Core references for libraries (as opposed to applications and test projects) are worth it for the build failures they inevitably cause on tooling upgrade.

cartermp commented 6 years ago

This has never disabled the reference in the F# targets:

<PackageReference Include="FSharp.Core" Version="4.3.*" />

It needs to be this:

<PackageReference Update="FSharp.Core" Version="VERSION" /> as specified in the FSharp.Core guidance.

As an aside, there should never be a * in the version (even if it's the patch version). We always have a fully-specified version in the targets as well.

I'm not personally opposed to making the reference explicit in templates; the version would still have to live in the targets file just so that we don't go insane every time there's an update.

KevinRansom commented 6 years ago

Phillip has it mostly right.

The correct syntax is using

<PackageReference Update="FSharp.Core" Version="4.3.*" />

However, what you had used to work, because we would run a buildtask that explicitly removed the implicit reference. That buildtask didn't run in the IDE causing that yellow triangle warning in the Solution Explorer.

It turns out that if you packagereference include different versions of the same nuget package you may get two references passed to the compiler when using the net sdk, which is why they added the 'Update=' mechanism.

I'm not certain I agree with never having wildcards, but the tooling makes upgrade to a specific version easy enough that wildcards should seldom be needed.

Kevin

dsyme commented 6 years ago

I was wrong, the version reference actually had no *, so that's kind of irrelevant.

Both C# and F# projects had

<PackageReference Include="FSharp.Core" Version="4.3.4" />

However the F# projects were getting FSharp.Core from nuget 4.5.2 (the implicit reference) and the C# projects from nuget 4.3.4.

So as I understand it the current guidance is to either use

<DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>

or

<PackageReference Update="FSharp.Core" Version="4.3.4" />

? And we are certain that the (simple and most obvious):

<PackageReference Include="FSharp.Core" Version="4.3.4" />

is no longer intended to work? In that case I do agree we should pin down the FSharp.Core in library templates, it is just wrong for us to put users in a position where

  1. F# libraries which C# projects depend on to magically upgrade their FSharp.Core references on tooling upgrade, and

  2. copying the explicit reference across from the C# project doesn't fix the problem.

By default library projects should just have explicit FSharp.Core that does not auto-upgrade.

cartermp commented 6 years ago

And we are certain that the (simple and most obvious) ... is no longer intended to work?

Yes. It was a bug in the F# targets files that allowed this to "work" (where work means not at design time in Visual Studio).

The mechanism for .NET Core is <PackageReference Update="" Version=""/>, and this has been documented in the FSharp.Core guidance for a while. It just appears that FSharp.Data was still implicitly relying on the bug in the targets files.

cartermp commented 6 years ago

As for a split between app/library project file, it's not exactly a win-win to do what you suggest. It's quite likely that people would be confused why a console app doesn't explicitly reference FSharp.Core, but a library does. That means that people who use such a library in their solution (which likely does not produce a package at all, based on the majority of our users not being library authors) would now be on the hook for having to upgrade their class libraries manually, even if they only support an application.

The other issue is that FSharp.Core and a given compiler effectively go hand-in-hand. And some new SDK versions will contain a new compiler, thus a new FSharp.Core that was tested with that compiler. People would have to reason about when to upgrade their binary or not. A potential resolution to this would be to explicitly set a <LangVer> in a project file and implicitly tie the FSharp.Core reference to that, but this is further machinery to build.

Whereas the current state of the world is that package authors must add a single line to their project.

KevinRansom commented 6 years ago

@dsyme

R.e.

<PackageReference Include="FSharp.Core" Version="4.3.4" />

Msbuild allows multiple PackageReference Include="SomeName", when that is specified you may/will get multiple references passed to the compiler.

The correct way to update an already specified reference is to use:

<PackageReference Update="FSharp.Core" Version="4.3.4" />

We could choose to not have an implicit reference, in which case either the developer would add a PackageReference each time a new project was created or ... the tooling would hard code the <Package Include = in the project on creation. This will require the developer to manually update each time a new set of tooling was retrieved or they will continue to use an old FSharp.Core whilst upgrading their tools continuously.

The alternative is where we are now, which is to implicitly select the FSharp.Core that matches the build tooling, and allowing the developer to easily pin to a specific version when their scenarios require it.

The Implicit reference is usefull while developing when the developer is happy to let the installed compiler make the decision. DisableImplicitFSharpCoreReference is usefull in scenarios where you are using a tool such as paket to manage your references. <Package Update = is usefull in scenarios where you want to pin the FSharp.Core to a specific version.

Unfortunately the msbuild team haven't properly documented Update= yet. It would be handy if they would get around to that.

Kevin

dsyme commented 6 years ago

Whereas the current state of the world is that package authors must add a single line to their project.

Right now, upgrading tooling breaks builds whenever F# libraries are referenced by C# projects. (After upgrade, an F# library suddenly depends on 4.5.0, while a C# library consumes that F# library explicitly refers to 4.3.4. Bang.)

The Implicit reference is useful while developing when the developer is happy to let the installed compiler make the decision....

I don't think the developer goes close to understanding what this means. Using implicit references for libraries is effectively saying "For my F# projects, FSharp.Core is chosen by the tooling, but for my C# projects it's explicit, and there is no way to keep these in sync. Let's cross our fingers and hope this keeps working!" That's never, ever, ever a good idea. We should never put the developer in such a situation.

Honestly, we should go explicit, at least for libraries, anything else is unsound if those libraries are referenced by C# projects (or referenced by any F# projects making the FSharp.Core version explicit).

cartermp commented 6 years ago

Right now, upgrading tooling breaks builds whenever F# libraries are referenced by C# projects.

I don't think I quite understand the situation. There was a bug that FSharp.Data depended on, and since that bug has been fixed, they were broken. But that bug has been resolved, and if they use the Update mechanism with PackageReference, it's not a problem. We have also had the correct guidance on using this for some time.

If C# does not respect this, then that is a bug in the .NET SDK C# support, and it needs to be fixed. Is it the case that today, with .NET SDK version 2.1.400+, what you described occurs?

This problem you describe:

"For my F# projects, FSharp.Core is chosen by the tooling, but for my C# projects it's explicit, and there is no way to keep these in sync. Let's cross our fingers and hope this keeps working!"

Is only traded for a different problem if the reference were made explicit. Because the .NET Core muxer picks the latest SDK if you don't have a global.json file, you will likely be compiling against whatever later version of F# that came with the newest SDK you have on your machine, but depending on a core library that wasn't actually built with that compiler. This would be even stranger if it were only for library projects, especially since the majority of library projects in the world are not NuGet packages and are built in lockstep with app projects.

KevinRansom commented 6 years ago

@dsyme, @cartermp.

This is one of those versioning discussions where you can like one choice or the other. I get it:

Preference 1; picking the runtime library version when the project is created and updating only on the rare occasions where you decide a higher version is needed. That is a perfectly sound and reasonable preference.

Preference 2; an equally valid preference is to update the runtime library whenever the tooling is updated.

This is pretty much the tension that has always existed, and different, well meaning, people have fallen firmly on either side of this argument.

The scenario described by Don is that a C# developer referencing an F# project in which the developer has not expressed a preference, in the same solution. After upgrade the tooling and the F# project now builds with the FSharp.Core that matches that tooling, she should be unsurprised that now he is getting FSharp.Core 4.5. If she has a reason to pin FSharp.Core to a specific version she should do so, otherwise going with the flow seems to work quite well.

The current tooling we have supports either approach, so now we are merely discussing what should the default be?

Should it be: flow with tooling unless the developer has specified a specific version to load or not?

I happen to think our current defaults are more explainable.

If you express no preference, the version matches the tooling you used to build. The advantage to this approach is, when a developer uses the latest tooling she gets access to all of the latest F# features that are in F# Core, unless she has said. "I need to settle on version X.Y.Z because I don't need the new features and I want it to be usable by my customers, without requiring them to update their compilers to the latest version.

Kevin

KevinRansom commented 6 years ago

The reason I prefer our defaults is I would hate to have to deal with "Bug reports" along the lines of "Span doesn't work for me; I got the latest tooling and started using Span in my project but when I compile I get error saying it can't find some types; and yet when I made a standalone project the same code compiles great, what am I doing wrong?"

cartermp commented 6 years ago

FYI I just confirmed that the C# project referencing an F# project will respect that F# project's FSharp.Core reference if it is explicitly pinned with <PackageReference Update="FSharp.Core" Version="..."/>. So there is no bug here anymore, and the discussion is about if we want to go all explicit or all implicit.

To be clear, I will not be okay with some F# projects being implicit and some being explicit. We either go one way or the other, optimizing for one set of users or a different one. Some halfway solution would just make it a bad experience for all users, IMO.

forki commented 6 years ago

Paket is always trying to go the explicit route.

dsyme commented 6 years ago

FYI I just confirmed that the C# project referencing an F# project will respect that F# project's FSharp.Core reference if it is explicitly pinned with . So there is no bug here anymore, and the discussion is about if we want to go all explicit or all implicit.

The bug repro is as follows:

  1. With VS 15.7

    a. create F# library project (implicitly referencing FSharp.Core 4.3.4) b. reference it from C# project and add explicit FSharp.Core reference in C# project using right-click manage nuget package tooling (C# project explicitly references FSharp.Core 4.3.4)

  2. Upgrade to 15.8 (i.e. upgrade your .NET SDK).

Expected: Your project compiles

Actual: Your project no longer compiles with the error below, and you have little no idea why, since there is no mention of FSharp.Core 4.5.2 anywhere in your project files. The user will probably just upgrade everything to 4.5.2, but there are plenty of situations where that will inflict pain further down the line (e.g. perhaps there were other reasons why the C# app was using 4.3.4).

Detected package downgrade: FSharp.Core from 4.5.2 to 4.3.4. Reference the package directly from the project to select a different version. ConsoleApp1 -> ClassLibrary3 -> FSharp.Core (>= 4.5.2) ConsoleApp1 -> FSharp.Core (>= 4.3.4) ConsoleApp1

IMHO implicit FSharp.Core references are just busted and we should never be inflicting them on our users, just as we never generate project file text:

<PackageReference Include="SomeLibrary" />

without a version number. Upgrading the .NET SDK tooling should never lead the user down a path where he/she tries to push through a wave of package upgrades or has to look up some obscure F# stuff to pint the package version. That's the kind of implicit stuff which has gotten a generation of C# users very frustrated with F# libraries to the point that they start eliminating any F# projects from their solution.

I'm fine with handling user questions like the above, it's perfectly normal that upgrading tooling won't automatically get you all the latest and greatest features: features have pre-requisites before they light up - that will always be the case and probably increasingly so. We should simply document those pre-requisites in the core blog posts that announce the features.

dsyme commented 6 years ago

@cartermp I've added the repro and listed the workaround.

cartermp commented 6 years ago

@dsyme Sorry, but I think we've crossed streams here. This is not a valid bug.

There was a bug, but it happened to produce what seemed like correct behavior at the time. There is not a bug here anymore. VS 15.7 is not supported, and the resolution to the past bad behavior is to upgrade the .NET SDK that has the correct targets. The resolution to that repro is to upgrade to an SDK with the bug fixed and adjust your PackageReference to be correct as-specified in documentation.

cartermp commented 6 years ago

Perhaps it's also not clear that one of the explicit goals of the .NET SDK is to roll forward with updates to things that are intrinsic to the SDK, such as compilers and core library references. When you upgrade your SDK, you compile against an upgraded BCL as well.

We already roll forward with the compiler, so even if you pinned FSharp.Core, you get an upgraded compiler when you upgrade your SDK.

If we want to be explicit (and thus not roll forward), we need to also pin the F# compiler and/or language version in the project file, otherwise you're going to be in a situation where you get a new compiler but no FSharp.Core reference it was tested against. That's not ideal at all.

Note that if you pin your SDK version with global.json, you opt out of this behavior.

That's the kind of implicit stuff which has gotten a generation of C# users very frustrated with F# libraries to the point that they start eliminating any F# projects from their solution.

This sort of thing already happens with C# today. If you upgrade your SDK, you get an upgraded BCL to compile against, unless you pin your SDK version.

0x53A commented 6 years ago

The big difference between updating a compiler and updating a reference is that (excluding bugs in the compiler) there should be no observable difference in the output when updating a compiler.

So even if a newer SDK pulls in a newer csc/fsc, it shouldn't be noticeable.

This sort of thing already happens with C# today. If you upgrade your SDK, you get an upgraded BCL to compile against, unless you pin your SDK version.

How?

All project files contain <TargetFramework>, which specifies against which BCL I compile.


The nearest thing C# has is System.ValueTuple, and AFAIK they don't implicitly reference it. If you try to use tuples without it, you get a compiler error.

cartermp commented 6 years ago

So even if a newer SDK pulls in a newer csc/fsc, it shouldn't be noticeable.

It very much is, though. New codegen, bugs fixed, deprecation warnings for constructs, disabling certain invalid code (e.g., F# 4.5 disallows replacing a struct by calling itself and modifying the this pointer) are all fair game when a new compiler comes in, especially if it involves a new language version. How is this different than concerns with a package reference?

How?

I think I may be mistaken here (but this would be true if you're on a new machine, or cleaned out any old SDKs).

0x53A commented 6 years ago

How is this different than concerns with a package reference?

Because it does not affect consumers. And if it fails, it fails loudly. If I use deprecated constructs, I get an error.

Simplest example:

Create a new F# project with an old .NET SDK and call dotnet pack. Update the SDK. Call dotnet pack again.

These two packages have different references to FSharp.Core.

For me, that is unexpected.

I think our difference is still (like a year ago, when that discussion started ...) that you see FSharp.Core as part of the framework and I see it more as a Lib. As a Lib, it should be controlled by the user.

But IMO FSharp.Core is so intrusive that it shouldn't be swept under the carpet and hidden.

cartermp commented 6 years ago

Correct, we see FSharp.Core as a part of the framework. I'm not necessarily opposed to being explicit, but that does mean two things:

  1. We are going against the design principles of the .NET SDK in general, which is to roll forward and offer knobs to pin yourself (which are documented both for .NET Core and for FSharp.Core)
  2. I believe very strongly that we cannot have newer compilers being used to build things, but lagging FSharp.Core references that were built by and for older compilers.
auduchinok commented 6 years ago

Given the fact FSharp.Core is a signed assembly and you have to use binding redirects when you somehow reference an old assembly in your apps, I feel very against of these silent updates to the library whenever SDK changes.

dsyme commented 6 years ago

Correct, we see FSharp.Core as a part of the framework.

I don't see FSharp.Core as part of any particular .NET SDK "framework", in part because the C# projects/targets don't understand it in the same way as F# projects/targets, and in part because I'm not sure what this definition of framework is. AFAIK netcoreapp2.0 etc. assembly version numbers don't get updated by an SDK update?

In any case this repro captures the problem exactly. This is just incorrect behavior.

Create a new F# project with an old .NET SDK and call dotnet pack. Update the SDK. Call dotnet pack again. These two packages have different references to FSharp.Core.

KevinRansom commented 6 years ago

With all due respect, when you want a particular version of FSharp.Core specify it in the project file, there are mechanisms allowing you to do that. If you don't specify what you want, then be prepared to get what the SDK thinks is appropriate. For sure it ain't rocket science … there is even tooling that allows you to pick the value.

dsyme commented 6 years ago

3 of the best F# library developers I know were flummoxed by the effects of implicit version upgrade in Fsharp.Data. No web search helps, no VSCode tooling helps (and in the days of netsdk we can't be relying on VS tooling to make libraries with reliable dependences), there was just runtime failure.

Anyone who had to deal with that build bug would have come to the same conclusion: whatever micro-gains exist from implicit references are outweighed by the pain and feeling of unsoundness that is generally so absent from F# programming. I just don't understand why we are we setting people up for failure like this.

Re in-the-framework: C# projects compute version logic differently to F# projects (no implicit reference) so Fsharp.Core is clearly not "part of the framework" as far as mixed C#/F# projects are concerned. That is the source of the bug with repro above.

If we follow the design principle of "in the framework" then let's at least be consistent and make all C# projects reference a consistent FSharp.Core implicitly, just like all other framework assemblies... Anything else is inconsistent.

KevinRansom commented 6 years ago

@dsyme I don't really know how to answer your points.

All that I can say is "If a developer cares about the version of "FSharp.Core" then she should specify it. otherwise she gets what the tooling picks. In an ideal world, a developer would never care about the FSharp.Core version, anymore than they care about the mscorlib version, unfortunately we don't live there yet.

You seem to prioritise library developers who have the extra step of specifying an "FSharp.Core" version when they care about the version and dismiss developers who don't care about the FSharp.Core version number.

Specifying the version is easy, using a standard .NET mechanism and supported by VS tooling. Paket developers will use whatever mechanism paket uses for specifying assembly version info. I think the F# community has all of the tools it needs to achieve the scenarios it desires.

ctaggart commented 6 years ago

I find the current implicit FSharp.Core behavior to be a bit strange. If you don't explicitly set the FSharp.Core version in a library, you end up with a dependency on 4.5.2.

image

I'm confused about the guidance https://github.com/fsharp/fsharp.github.io/pull/89, but since I'm targeting netstandard2.0, I think I want the latest 4.3.*, so 4.3.4.

If you go to use a library referencing 4.5.2 from a project, you end up with this warning:

warning NU1605: Detected package downgrade: FSharp.Core from 4.5.2 to 4.3.4. Reference the package directly from the project to select a different version.

It is confusing to me why a library ends up implicitly referencing 4.5.2 and then a console app end up with this warning. If we are going to have implicit version, I'd prefer the version be upgraded to the latest with the tooling. I am now setting the version explicitly in all my projects that I oversee. I'd actually prefer not to have an implicit version, but I think that ship has sailed.

What is the implicit version for each shipped Visual Studio version and type of project?

cartermp commented 6 years ago

@ctaggart The version is upgraded if you use a new toolset (i.e., a new SDK). Each version is pinned in the SDK. If you don't upgrade your toolset, or use global.json to pin the SDK used by your solution, then the referenced version will never change.

Targeting .NET Standard 2.0 is orthogonal to the FSharp.Core library. 4.5.2 and 4.3.4 both target .NET Standard 1.6, which means they are consumable from any project that is compatible with .NET Standard 1.6, which includes .NET Standard 2.0.

KevinRansom commented 6 years ago

@ctaggert can you provide the repro steps that resulted in the warning please? I am unable to make that happen.

Thanks

Kevin

ctaggart commented 6 years ago

@KevinRansom The issue was occurring on builds using a 2.1.30x sdk. I confirmed that is not the case with a 2.1.40x sdk because the implicit version is different:

image

The steps to reproduce are here, but you need to use a 2.1.30x sdk. I used a global.json to reproduce:

{
  "sdk": {
    "version": "2.1.302"
  }
}

Why would it downgrade FSharp.Core to 4.3.4 instead of update it to 4.5.2?

cartermp commented 6 years ago

Why would it downgrade FSharp.Core to 4.3.4 instead of update it to 4.5.2?

This is NuGet behavior: https://docs.microsoft.com/en-us/nuget/consume-packages/dependency-resolution#nearest-wins

In this case, because 4.3.4 is referenced in the targets (or if it were specified explicitly in the project file with <PackageReference Update="..." Version="..."/>), then that's what wins over the reference in the package that depends on 4.5.2.

The proper recourse in this case is to update the SDK that builds the F# project.

dsyme commented 6 years ago

You seem to prioritise library developers who have the extra step of specifying an "FSharp.Core" version when they care about the version and dismiss developers who don't care about the FSharp.Core version number.

Yes that is definitely true. Anyone who is designing a library package for public consumption (i.e. outside their solution) should definitely be forced to care about the minimal FSharp.Core version they require of downstream consumers. Just as they are forced to care about the types of their code and API. We aren't Javascript.

That's a basic summary of my position: the minimal required FSharp.Core version is part of the design of a library, just like the types of the API are part of the design. Heck, nuget.org even reports those dependencies for you and they are is stored in the package metadata. That's a pretty strong hint that the minimal required FSharp.Core should never, ever be a random result of the tools you happen to have installed on your machine.

I've personally suffered far too much pain and complexification from implicit treatment of FSharp.Core references in the F# ecosystem over the years to support their continued use in the context of package development. Especially just for the sake of "developers who don't care". And in any case package developers have to care about the minimal required versions of every other package they depend on, what makes FSharp.Core so special?

cartermp commented 6 years ago

@dsyme The large majority of F# projects/users are applications/app developers, not packages/package authors. The guidance currently states:

Generally, when writing an application, you want to use the highest version of FSharp.Core available for the platform you are targeting.

This is what the implicit reference does, and it is for the majority audience.

For package authors, there is a simple addition to a project (in addition to the guidance to target the lowest applicable version of FSharp.Core) and then everything Just Works ™️ from there on out, including if C# projects are at play. Misauthored projects or older SDKs aren't a part of this.

What I would actually like to do is find a way to make FSharp.Core a part of the metapackage you reference when targeting .NET Standard (which is also referenced implicitly when targeting netcoreapp). This is where the C# and VB equivalent .dlls live, their usage and versions are governed by what you target, and aren't really a concern beyond that. I think FSharp.Core should be treated similarly, if it's possible.

dsyme commented 6 years ago

What I would actually like to do is find a way to make FSharp.Core a part of the metapackage you reference when targeting .NET Standard (which is also referenced implicitly when targeting netcoreapp). This is where the C# and VB equivalent .dlls live, their usage and versions are governed by what you target, and aren't really a concern beyond that. I think FSharp.Core should be treated similarly, if it's possible.

That would be great

cartermp commented 5 years ago

Closing old discussion

geoeo commented 5 years ago

I just upgraded to DotNet Core 2.2 on my mac and I am getting this error. I have to manually "Update" my fsharp version to 2.3.4

error NU1102: Unable to find package FSharp.Core with version (>= 4.5.2)

error NU1102: - Found 23 version(s) in nuget.org [ Nearest version: 4.3.4 ]

KevinRansom commented 5 years ago

@geoeo

Hi,

I think we need a bit more information, what version of the dotnet cli did you install?

And what list of dotnet cli's are installed: use dotnet --info to get a list of them

E.g. this is from my macbook pro.

~/temp/fsharpcore>dotnet --info
.NET Core SDK (reflecting any global.json):
 Version:   2.1.600-preview-009472
 Commit:    acb7c55cbf

Runtime Environment:
 OS Name:     Mac OS X
 OS Version:  10.14
 OS Platform: Darwin
 RID:         osx.10.14-x64
 Base Path:   /usr/local/share/dotnet/sdk/2.1.600-preview-009472/

Host (useful for support):
  Version: 3.0.0-preview-27218-01
  Commit:  d40b87f29d

.NET Core SDKs installed:
  2.1.500 [/usr/local/share/dotnet/sdk]
  2.1.600-preview-009472 [/usr/local/share/dotnet/sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.6 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.7 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.6 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.7 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.0.0-preview-18579-0056 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.1.6 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.7 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.0.0-preview-27218-01 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]

To install additional .NET Core runtimes or SDKs:
  https://aka.ms/dotnet-download
~/temp/fsharpcore>
geoeo commented 5 years ago

Sure.

.NET Core SDK (reflecting any global.json):
 Version:   2.2.103
 Commit:    8edbc2570a

Runtime Environment:
 OS Name:     Mac OS X
 OS Version:  10.13
 OS Platform: Darwin
 RID:         osx.10.13-x64
 Base Path:   /usr/local/share/dotnet/sdk/2.2.103/

Host (useful for support):
  Version: 2.2.1
  Commit:  878dd11e62

.NET Core SDKs installed:
  2.1.4 [/usr/local/share/dotnet/sdk]
  2.1.300 [/usr/local/share/dotnet/sdk]
  2.1.301 [/usr/local/share/dotnet/sdk]
  2.1.302 [/usr/local/share/dotnet/sdk]
  2.1.403 [/usr/local/share/dotnet/sdk]
  2.2.103 [/usr/local/share/dotnet/sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.0 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.1 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.2 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.5 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.1 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.0 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.1 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.2 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.5 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.1 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.0.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.0 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.1 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.2 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.1 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
cartermp commented 5 years ago

@geoeo Are you using <PackageReference Update="FSharp.Core" Version="..." />?

In past SDKs there was a bug where Include would coincidentally work (but not in an IDE like VS), but this has been all fixed and Update is now required if you wish to specify FSharp.Core explicitly.

KevinRansom commented 5 years ago

@geoeo and also your project file please … Elide the source file names if they are in anyway sensitive.

thanks

Kevin

geoeo commented 5 years ago

@cartermp Yes, see below

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <ProjectReference Include="../Henzai.Core/Henzai.Core.csproj" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Numerics.fs" />
    <Compile Include="Camera.fs" />
    <Compile Include="Material.fs" />
    <Compile Include="Geometry/Core.fs" />
    <Compile Include="Geometry/Sphere.fs" />
    <Compile Include="Geometry/Plane.fs" />
    <Compile Include="Geometry/AABB.fs" />
    <Compile Include="Geometry/Triangle.fs" />
    <Compile Include="Surface.fs" />
    <Compile Include="SceneDefinitions.fs" />
    <Compile Include="Scene.fs" />
    <Compile Include="Program.fs" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="SixLabors.ImageSharp" Version="1.0.0-beta0006" />
    <PackageReference Include="BenchmarkDotNet" Version="0.10.14" />
    <PackageReference Update="FSharp.Core" Version="4.3.4" />
  </ItemGroup>
</Project>
KevinRansom commented 5 years ago

@geoeo , well that is quite mystifying. Could you please remove the line updating fsharp.core, so that it fails again.

and then build the project with the /bl switch

This will generate a msbuild.binlog file.

If you could attach that to this thread I will take a look and see if I can figure out why it can't the 4.5.2, despite that being public on nuget.org.

geoeo commented 5 years ago

Sure thing. msbuild.binlog.zip

KevinRansom commented 5 years ago

@geoeo

I can't reproduce this and can't explain the behavior you have. It seems as if there is some kind of Nuget issue.

The really weird thing is this: image

It went to nuget.org and got back a list of 23 items for FSharp.Core, for reasons I can't fathom or reproduce it rejects 4.5.2 and selects 4.3.4 as the best match.

What is remarkable, is that 4.3.4 is pretty close to the only FSharp.Core package that will actually compile your source.

When compiled with the correct FSharp.Core, the build produces these errors:

  Restoring packages for /Users/kevinr/repos/kevinransom/henzai/Raytracer/raytracer.fsproj...
  Restore completed in 42.22 ms for /Users/kevinr/repos/kevinransom/henzai/Henzai.Core/Henzai.Core.csproj.
  Restore completed in 248.94 ms for /Users/kevinr/repos/kevinransom/henzai/Raytracer/raytracer.fsproj.
/usr/local/share/dotnet/sdk/2.2.103-rtm-009655/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.RuntimeIdentifierInference.targets(143,5): message NETSDK1057: You are using a preview version of .NET Core. See: https://aka.ms/dotnet-core-preview [/Users/kevinr/repos/kevinransom/henzai/Raytracer/raytracer.fsproj]
  Henzai.Core -> /Users/kevinr/repos/kevinransom/henzai/Henzai.Core/bin/Debug/netcoreapp2.0/Henzai.Core.dll
/Users/kevinr/repos/kevinransom/henzai/Raytracer/Geometry/Core.fs(21,97): error FS0001: The type 'ByRefKinds.InOut' does not match the type 'ByRefKinds.In' [/Users/kevinr/repos/kevinransom/henzai/Raytracer/raytracer.fsproj]
/Users/kevinr/repos/kevinransom/henzai/Raytracer/Geometry/Core.fs(22,101): error FS0001: The type 'ByRefKinds.InOut' does not match the type 'ByRefKinds.In' [/Users/kevinr/repos/kevinransom/henzai/Raytracer/raytracer.fsproj]
/Users/kevinr/repos/kevinransom/henzai/Raytracer/Geometry/Plane.fs(28,78): error FS0001: Type mismatch. Expecting a    'byref<Vector3>'    but given a    'inref<Vector3>'    The type 'ByRefKinds.InOut' does not match the type 'ByRefKinds.In' [/Users/kevinr/repos/kevinransom/henzai/Raytracer/raytracer.fsproj]
/Users/kevinr/repos/kevinransom/henzai/Raytracer/Geometry/Plane.fs(32,86): error FS0001: Type mismatch. Expecting a    'byref<Vector3>'    but given a    'inref<Vector3>'    The type 'ByRefKinds.InOut' does not match the type 'ByRefKinds.In' [/Users/kevinr/repos/kevinransom/henzai/Raytracer/raytracer.fsproj]
/Users/kevinr/repos/kevinransom/henzai/Raytracer/Geometry/Plane.fs(33,88): error FS0001: Type mismatch. Expecting a    'byref<Vector3>'    but given a    'inref<Vector3>'    The type 'ByRefKinds.InOut' does not match the type 'ByRefKinds.In' [/Users/kevinr/repos/kevinransom/henzai/Raytracer/raytracer.fsproj]
/Users/kevinr/repos/kevinransom/henzai/Raytracer/Geometry/Plane.fs(34,32): error FS0041: No overloads match for method 'ToVec3'. The available overloads are shown below. [/Users/kevinr/repos/kevinransom/henzai/Raytracer/raytracer.fsproj]
/Users/kevinr/repos/kevinransom/henzai/Raytracer/Geometry/Plane.fs(35,32): error FS0041: No overloads match for method 'ToVec3'. The available overloads are shown below. [/Users/kevinr/repos/kevinransom/henzai/Raytracer/raytracer.fsproj]
/Users/kevinr/repos/kevinransom/henzai/Raytracer/Geometry/Triangle.fs(65,82): error FS0001: Type mismatch. Expecting a    'byref<Vector3>'    but given a    'inref<Vector3>'    The type 'ByRefKinds.InOut' does not match the type 'ByRefKinds.In' [/Users/kevinr/repos/kevinransom/henzai/Raytracer/raytracer.fsproj]
/Users/kevinr/repos/kevinransom/henzai/Raytracer/Geometry/Triangle.fs(67,107): error FS0001: Type mismatch. Expecting a    'byref<Vector3>'    but given a    'inref<Vector3>'    The type 'ByRefKinds.InOut' does not match the type 'ByRefKinds.In' [/Users/kevinr/repos/kevinransom/henzai/Raytracer/raytracer.fsproj]
/Users/kevinr/repos/kevinransom/henzai/Raytracer/Surface.fs(78,40): error FS0041: No overloads match for method 'ToVec3'. The available overloads are shown below. [/Users/kevinr/repos/kevinransom/henzai/Raytracer/raytracer.fsproj]
/Users/kevinr/repos/kevinransom/henzai/Raytracer/Surface.fs(104,28): error FS0041: No overloads match for method 'ToVec3'. The available overloads are shown below. [/Users/kevinr/repos/kevinransom/henzai/Raytracer/raytracer.fsproj]
/Users/kevinr/repos/kevinransom/henzai/Raytracer/Scene.fs(100,58): error FS0001: Type mismatch. Expecting a    'byref<Matrix4x4>'    but given a    'inref<Matrix4x4>'    The type 'ByRefKinds.InOut' does not match the type 'ByRefKinds.In' [/Users/kevinr/repos/kevinransom/henzai/Raytracer/raytracer.fsproj]

Build FAILED.

When we implemented ref returns for FSharp, we added a couple of new types to FSharp.Core, when the compiler is passed a version of FSharp.Core which doesn't contain those types it incorrectly maps the types to a byref. Originally code like this would have failed with error messages similar to:

C:\kevinransom\henzai\Raytracer\Geometry\Core.fs(21,98): error FS0256: A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...' [C:\kevinransom\henzai\Raytracer\Raytracer.fsproj]
C:\kevinransom\henzai\Raytracer\Geometry\Core.fs(22,102): error FS0256: A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...' [C:\kevinransom\henzai\Raytracer\Raytracer.fsproj]
C:\kevinransom\henzai\Raytracer\Geometry\Plane.fs(28,79): error FS0256: A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...' [C:\kevinransom\henzai\Raytracer\Raytracer.fsproj]
C:\kevinransom\henzai\Raytracer\Geometry\Plane.fs(32,87): error FS0256: A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...' [C:\kevinransom\henzai\Raytracer\Raytracer.fsproj]
C:\kevinransom\henzai\Raytracer\Geometry\Plane.fs(33,89): error FS0256: A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...' [C:\kevinransom\henzai\Raytracer\Raytracer.fsproj]
C:\kevinransom\henzai\Raytracer\Geometry\Plane.fs(34,68): error FS0256: A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...' [C:\kevinransom\henzai\Raytracer\Raytracer.fsproj]
C:\kevinransom\henzai\Raytracer\Geometry\Plane.fs(35,68): error FS0256: A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...' [C:\kevinransom\henzai\Raytracer\Raytracer.fsproj]
C:\kevinransom\henzai\Raytracer\Geometry\Triangle.fs(65,82): error FS0257: Invalid mutation of a constant expression. Consider copying the expression to a mutable local, e.g. 'let mutable x = ...'. [C:\kevinransom\henzai\Raytracer\Raytracer.fsproj]
C:\kevinransom\henzai\Raytracer\Geometry\Triangle.fs(67,107): error FS0257: Invalid mutation of a constant expression. Consider copying the expression to a mutable local, e.g. 'let mutable x = ...'. [C:\kevinransom\henzai\Raytracer\Raytracer.fsproj]
C:\kevinransom\henzai\Raytracer\Surface.fs(78,76): error FS0256: A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...' [C:\kevinransom\henzai\Raytracer\Raytracer.fsproj]
C:\kevinransom\henzai\Raytracer\Surface.fs(104,64): error FS0256: A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...' [C:\kevinransom\henzai\Raytracer\Raytracer.fsproj]
C:\kevinransom\henzai\Raytracer\Scene.fs(100,58): error FS0001: This expression was expected to have type    'Matrix4x4 ref'    but here has type    'byref<'a>' [C:\kevinransom\henzai\Raytracer\Raytracer.fsproj]
C:\kevinransom\henzai\Raytracer\Scene.fs(100,59): error FS0256: A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...' [C:\kevinransom\henzai\Raytracer\Raytracer.fsproj]

Build FAILED.

As for your reported issue, I am unable to reproduce it, it seems as if the issue is in the nuget restore task. @rrelyea may be able to advise you why this is happening. @tihan will be able to more fully explain the issues with the ref return code.

@rrelyea,

hi there are several issues here, but one seems to be impacted by the Nuget RestoreTask. With the dotnet cli version 2.2.1. The build targets contain a package reference to FSharp.Core, Version "4.5.2", the retore fails with the message:

> error NU1102: Unable to find package FSharp.Core with version (>= 4.5.2)

> error NU1102:   - Found 23 version(s) in nuget.org [ Nearest version: 4.3.4 ]

FSharp.Core, Version 4.5.2, is published and publicly listed on nuget.org so why it didn't find it is a problem.

However, I have tried to repro this on a couple of windows machines, and also on my macbook, and I am unable to reproduce the error.

I hope you can help @geoeo get this project building on his machine with correct dependencies, thank you.

Kevin

KevinRansom commented 5 years ago

@rrelyea here is the msbuild.binlog with the restore failure: https://github.com/Microsoft/visualfsharp/files/2838406/msbuild.binlog.zip

geoeo commented 5 years ago

Thanks a lot. I have tried this on a vanilla fsharp project as well and I get the same error. So its definitely something with the infrastructure.

vanilla-msbuild.binlog.zip

Edit:

I get the same behaviour when trying to create a new project

Marc-Pro:Desktop marchaubenstock$ dotnet new console -lang F# -o fs-test_2
The template "Console Application" was created successfully.

Processing post-creation actions...
Running 'dotnet restore' on fs-test_2/fs-test_2.fsproj...
  Restoring packages for /Users/marchaubenstock/Desktop/fs-test_2/fs-test_2.fsproj...
/Users/marchaubenstock/Desktop/fs-test_2/fs-test_2.fsproj : error NU1102: Unable to find package FSharp.Core with version (>= 4.5.2)
/Users/marchaubenstock/Desktop/fs-test_2/fs-test_2.fsproj : error NU1102:   - Found 23 version(s) in nuget.org [ Nearest version: 4.3.4 ]
  Generating MSBuild file /Users/marchaubenstock/Desktop/fs-test_2/obj/fs-test_2.fsproj.nuget.g.props.
  Generating MSBuild file /Users/marchaubenstock/Desktop/fs-test_2/obj/fs-test_2.fsproj.nuget.g.targets.
  Restore failed in 1.11 sec for /Users/marchaubenstock/Desktop/fs-test_2/fs-test_2.fsproj.

Restore failed.
Post action failed.
Description: Restore NuGet packages required by this project.
Manual instructions: Run 'dotnet restore'

@KevinRansom I noticed you are running Mojave OS version while I am still on High Sierra.

akeeton commented 5 years ago

@dsyme I can confirm that this was a huge pain for me.

rrelyea commented 5 years ago

Just did a quick test about some of the issues mentioned above. Looks like the packages are downloading fine now... ( i realize you have many other things you are discussing )

C:\temp>dotnet new classlib -o fsharpRepro The template "Class library" was created successfully.

Processing post-creation actions... Running 'dotnet restore' on fsharpRepro\fsharpRepro.csproj... Restore completed in 736.33 ms for C:\temp\fsharpRepro\fsharpRepro.csproj.

Restore succeeded.

C:\temp>cd fsharpRepro

C:\temp\fsharpRepro>dotnet add package FSharp.Core --version 4.5.2 info : Adding PackageReference for package 'FSharp.Core' into project 'C:\temp\fsharpRepro\fsharpRepro.csproj'. info : Restoring packages for C:\temp\fsharpRepro\fsharpRepro.csproj... info : Package 'FSharp.Core' is compatible with all the specified frameworks in project 'C:\temp\fsharpRepro\fsharpRepro.csproj'. info : PackageReference for package 'FSharp.Core' version '4.5.2' added to file 'C:\temp\fsharpRepro\fsharpRepro.csproj'. info : Committing restore... info : Writing assets file to disk. Path: C:\temp\fsharpRepro\obj\project.assets.json log : Restore completed in 728.5 ms for C:\temp\fsharpRepro\fsharpRepro.csproj.

cartermp commented 5 years ago

@rrelyea Yes, there used to be a bug in the F# targets that gave the impression that an incorrect gesture would work correctly (provided you were only using F#). This was broken once we fixed our targets (to enable updating your FSharp.Core in an IDE), and the package in question was using that older way to specify an explicit FSharp.Core dependency. Generally things should be straightforward when referenced from C# now as well, provided there isn't some misauthoring in the rest of the dependency graph going on.