diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index 785eccfd126..678324382d0 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -1,5 +1,6 @@ ### Fixed +* Fix FS3236 when taking the address of an untyped generalized `let` binding (e.g. `let ffff = ValueNone`) passed to an `inref` parameter. ([Issue #19608](https://github.com/dotnet/fsharp/issues/19608), [PR #19948](https://github.com/dotnet/fsharp/pull/19948)) * Fix IntelliSense not suggesting later named arguments after the first one is autocompleted, for methods (including overloaded methods like `Task.Factory.StartNew`). ([Issue #19906](https://github.com/dotnet/fsharp/issues/19906), [PR #19940](https://github.com/dotnet/fsharp/pull/19940)) * Restore packaging of an F# design-time type provider that is activated via a `ProjectReference` carrying `IsFSharpDesignTimeProvider="true"`. The provider assembly is again included under `fsharp41` when packing (including `pack --no-build`); `PackageFSharpDesignTimeTools` now resolves the provider via `GetTargetPath`, which works in `dotnet pack`'s `BuildProjectReferences=false` content build without forcing an early `ResolveReferences`. ([Issue #18924](https://github.com/dotnet/fsharp/issues/18924), [PR #19979](https://github.com/dotnet/fsharp/pull/19979)) * Provided types used from multiple files no longer produce spurious FS0001 type mismatches under parallel compilation; provided-type entities are now interned so every file linking a given provided type shares one entity. ([PR #19969](https://github.com/dotnet/fsharp/pull/19969)) diff --git a/src/Compiler/TypedTree/TypedTreeOps.ExprOps.fs b/src/Compiler/TypedTree/TypedTreeOps.ExprOps.fs index bdebaf40ff5..91ed02ee1a3 100644 --- a/src/Compiler/TypedTree/TypedTreeOps.ExprOps.fs +++ b/src/Compiler/TypedTree/TypedTreeOps.ExprOps.fs @@ -192,8 +192,10 @@ module internal AddressOps = None, exprForValRef m vref, readonly, writeonly // LVALUE of "x" where "x" is mutable local, mutable intra-assembly module/static binding, or operation doesn't mutate. - // Note: we can always take the address of mutable intra-assembly values - | Expr.Val(vref, _, m) when MustTakeAddressOfVal g vref || CanTakeAddressOfImmutableVal g m vref mut -> + // Note: we can always take the address of mutable intra-assembly values. + // The second pattern matches a type-instantiated local value reference produced by TcVal for generalized let bindings. + | Expr.Val(vref, _, m) + | Expr.App(Expr.Val(vref, _, _), _, _, [], m) when MustTakeAddressOfVal g vref || CanTakeAddressOfImmutableVal g m vref mut -> let readonly = not (MustTakeAddressOfVal g vref) let writeonly = false checkTakeNativeAddress readonly diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/DataExpressions/AddressOf/AddressOf.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/DataExpressions/AddressOf/AddressOf.fs index 4005d80bf5d..b19f397fc57 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/DataExpressions/AddressOf/AddressOf.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/DataExpressions/AddressOf/AddressOf.fs @@ -131,19 +131,32 @@ let test () = |> shouldSucceed [] - let ``Issue 18841 - plain let discard with no address-of still compiles`` () = + let ``Issue 19608 - address of untyped ValueNone compiles`` () = Fsx """ module Test -type S = - struct - val Field: int - end +let x (y: inref>) = () let test () = - let s = S() - let _ = s + let ffff = ValueNone + x &ffff + """ + |> asLibrary + |> compile + |> shouldSucceed + + [] + let ``Issue 19608 - native address of untyped ValueNone binding fails`` () = + Fsx """ +#nowarn "51" + +module Test + +let test () = + let ffff = ValueNone + let _ = &&ffff () """ |> typecheck - |> shouldSucceed + |> shouldFail + |> withErrorCode 256