Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* Improve let-rec codegen: reorder bindings to allocate lambda closures before non-lambda values that reference them. ([PR #19339](https://github.com/dotnet/fsharp/pull/19339))
* Fix `YieldFromFinal`/`ReturnFromFinal` being incorrectly called in non-tail positions (`for`, `use`, `use!`, `try/with` handler). ([Issue #19402](https://github.com/dotnet/fsharp/issues/19402), [PR #19403](https://github.com/dotnet/fsharp/pull/19403))
* Fixed how the source ranges of warn directives are reported (as trivia) in the parser output (by not reporting leading spaces). ([Issue #19405](https://github.com/dotnet/fsharp/issues/19405), [PR #19408]((https://github.com/dotnet/fsharp/pull/19408)))
* Fix UoM value type `ToString()` returning garbage values when `--checknulls+` is enabled, caused by double address-taking in codegen. ([Issue #19435](https://github.com/dotnet/fsharp/issues/19435), [PR #19440](https://github.com/dotnet/fsharp/pull/19440))

### Added

Expand Down
12 changes: 9 additions & 3 deletions src/Compiler/Checking/MethodCalls.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1231,11 +1231,17 @@ let rec BuildMethodCall tcVal g amap isMutable m isProp minfo valUseFlags minst
let vExpr, vExprTy = tcVal vref valUseFlags (minfo.DeclaringTypeInst @ minst) m
BuildFSharpMethodApp g m vref vExpr vExprTy allArgs

| MethInfoWithModifiedReturnType(mi,retTy) ->
let expr, exprTy = BuildMethodCall tcVal g amap isMutable m isProp mi valUseFlags minst objArgs args staticTyOpt
let expr = mkCoerceExpr(expr, retTy, m, exprTy)
| MethInfoWithModifiedReturnType(ILMeth(_, ilMethInfo, _), retTy) ->
// Build the inner call directly, without re-invoking TakeObjAddrForMethodCall.
let expr, exprTy =
BuildILMethInfoCall g amap m isProp ilMethInfo valUseFlags minst direct allArgs

let expr = mkCoerceExpr (expr, retTy, m, exprTy)
expr, retTy

| MethInfoWithModifiedReturnType _ ->
failwith "MethInfoWithModifiedReturnType: unexpected inner method kind"

// Build a 'call' to a struct default constructor
| DefaultStructCtor (g, ty) ->
if g.langFeatureNullness && g.checkNullness then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,29 @@ let processAlias (x:mykgalias) =
|> typeCheckWithStrictNullness
|> shouldSucceed

// https://github.com/dotnet/fsharp/issues/19435
[<Theory>]
[<InlineData("42<mykg>", "42")>]
[<InlineData("42.0<mykg>", "42")>]
[<InlineData("42M<mykg>", "42")>]
let ``ToString on value type with UoM does not produce garbage at runtime`` (valueExpr: string, expected: string) =
FSharp $"""
module MyProgram

[<Measure>]
type mykg

[<EntryPoint>]
let main _ =
let x = {valueExpr}
System.Console.Write(x.ToString())
0
"""
|> withCheckNulls
|> compileExeAndRun
|> shouldSucceed
|> withStdOutContains expected

[<Fact>]
let ``Printing a nullable string should pass`` () =
FSharp """module MyLibrary
Expand Down
Loading