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 5e1ce2c8ed7..46aaa3057c3 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 `MethodAccessException` under `--realsig+` when a closure (inner `let rec`, `task`/`async` state machine, or quotation splice) inside a member defined in an intrinsic type augmentation (`type C with member ...`) accesses a `private` member of `C`. The synthesized closure is now nested inside the declaring type instead of beside it in the module class. ([Issue #19933](https://github.com/dotnet/fsharp/issues/19933), [PR #19955](https://github.com/dotnet/fsharp/pull/19955)) * Preserve source range for type errors on empty-bodied computation expressions (e.g. `foo {}`) in pipelines, function arguments, and type-annotated contexts, instead of reporting `unknown(1,1)`. ([Issue #19550](https://github.com/dotnet/fsharp/issues/19550), [PR #19849](https://github.com/dotnet/fsharp/pull/19849)) * Tooltip "Full name" now shows demangled companion module names (e.g. `MyType.func` instead of `MyTypeModule.func`). ([Issue #17335](https://github.com/dotnet/fsharp/issues/17335), [PR #19867](https://github.com/dotnet/fsharp/pull/19867)) 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..42c4b37e522 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 + """ + |> asExe + |> 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