Skip to content

Commit 54c4b66

Browse files
authored
Make [<CallerMemberName; Struct>] combination work (dotnet#18444)
* Fix IL mismatch - Some() was created for a ValueOption method * notes
1 parent b847758 commit 54c4b66

File tree

5 files changed

+68
-13
lines changed

5 files changed

+68
-13
lines changed

docs/release-notes/.FSharp.Compiler.Service/9.0.300.md

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
* Reenable β-reduction and subsequent reoptimization of immediately-invoked F#-defined generic delegates. ([PR #18401](https://github.com/dotnet/fsharp/pull/18401))
2525
* Fixed [#18433](https://github.com/dotnet/fsharp/issues/18433), a rare case of an internal error in xml comment processing. ([PR #18436](https://github.com/dotnet/fsharp/pull/18436))
2626
* Fix missing `null` highlighting in tooltips ([PR #18457](https://github.com/dotnet/fsharp/pull/18457))
27+
* Make `[<CallerMemberName; Struct>]` combination work([PR #18444](https://github.com/dotnet/fsharp/pull/18444/))
2728

2829
### Added
2930
* Added missing type constraints in FCS. ([PR #18241](https://github.com/dotnet/fsharp/pull/18241))

src/Compiler/Checking/MethodCalls.fs

+9-3
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,12 @@ let inline mkOptionalNone (g: TcGlobals) ty calledArgTy mMethExpr =
348348
else
349349
mkNone g calledArgTy mMethExpr
350350

351+
let inline mkOptionalSome (g: TcGlobals) outerOptTy innerNonOptionalType expr mMethExpr =
352+
if g.langVersion.SupportsFeature LanguageFeature.SupportValueOptionsAsOptionalParameters && isValueOptionTy g outerOptTy then
353+
mkValueSome g innerNonOptionalType expr mMethExpr
354+
else
355+
mkSome g innerNonOptionalType expr mMethExpr
356+
351357

352358
/// Adjust the called argument type to take into account whether the caller's argument is CSharpMethod(?arg=Some(3)) or CSharpMethod(arg=1)
353359
let AdjustCalledArgTypeForOptionals (infoReader: InfoReader) ad enforceNullableOptionalsKnownTypes (calledArg: CalledArg) calledArgTy (callerArg: CallerArg<_>) =
@@ -1502,14 +1508,14 @@ let GetDefaultExpressionForCalleeSideOptionalArg g (calledArg: CalledArg) eCalle
15021508
match calledArg.CallerInfo, eCallerMemberName with
15031509
| CallerLineNumber, _ when typeEquiv g calledNonOptTy g.int_ty ->
15041510
let lineExpr = Expr.Const(Const.Int32 mMethExpr.StartLine, mMethExpr, calledNonOptTy)
1505-
mkSome g calledNonOptTy lineExpr mMethExpr
1511+
mkOptionalSome g calledArgTy calledNonOptTy lineExpr mMethExpr
15061512
| CallerFilePath, _ when typeEquiv g calledNonOptTy g.string_ty ->
15071513
let fileName = mMethExpr.FileName |> FileSystem.GetFullPathShim |> PathMap.apply g.pathMap
15081514
let filePathExpr = Expr.Const (Const.String(fileName), mMethExpr, calledNonOptTy)
1509-
mkSome g calledNonOptTy filePathExpr mMethExpr
1515+
mkOptionalSome g calledArgTy calledNonOptTy filePathExpr mMethExpr
15101516
| CallerMemberName, Some(callerName) when typeEquiv g calledNonOptTy g.string_ty ->
15111517
let memberNameExpr = Expr.Const (Const.String callerName, mMethExpr, calledNonOptTy)
1512-
mkSome g calledNonOptTy memberNameExpr mMethExpr
1518+
mkOptionalSome g calledArgTy calledNonOptTy memberNameExpr mMethExpr
15131519
| _ ->
15141520
mkOptionalNone g calledArgTy calledNonOptTy mMethExpr
15151521

src/Compiler/Checking/PostInferenceChecks.fs

+18-8
Original file line numberDiff line numberDiff line change
@@ -2398,13 +2398,25 @@ let CheckEntityDefn cenv env (tycon: Entity) =
23982398
errorR(Error(FSComp.SR.chkCurriedMethodsCantHaveOutParams(), m))
23992399

24002400
if numCurriedArgSets = 1 then
2401-
let errorIfNotStringTy m ty callerInfo =
2401+
2402+
let inline tryDestOptionalTy g ty =
2403+
if isOptionTy g ty then
2404+
destOptionTy g ty |> ValueSome
2405+
elif g.langVersion.SupportsFeature LanguageFeature.SupportValueOptionsAsOptionalParameters && isValueOptionTy g ty then
2406+
destValueOptionTy g ty |> ValueSome
2407+
else
2408+
ValueNone
2409+
2410+
let errorIfNotStringTy m ty callerInfo =
24022411
if not (typeEquiv g g.string_ty ty) then
24032412
errorR(Error(FSComp.SR.tcCallerInfoWrongType(callerInfo |> string, "string", NicePrint.minimalStringOfType cenv.denv ty), m))
2413+
2414+
let errorIfNotOptional tyToCompare desiredTyName m ty callerInfo =
24042415

2405-
let errorIfNotStringOptionTy m ty callerInfo =
2406-
if not ((isOptionTy g ty) && (typeEquiv g g.string_ty (destOptionTy g ty))) then
2407-
errorR(Error(FSComp.SR.tcCallerInfoWrongType(callerInfo |> string, "string", NicePrint.minimalStringOfType cenv.denv (destOptionTy g ty)), m))
2416+
match tryDestOptionalTy g ty with
2417+
| ValueSome t when typeEquiv g tyToCompare t -> ()
2418+
| ValueSome innerTy -> errorR(Error(FSComp.SR.tcCallerInfoWrongType(callerInfo |> string, desiredTyName, NicePrint.minimalStringOfType cenv.denv innerTy), m))
2419+
| ValueNone -> errorR(Error(FSComp.SR.tcCallerInfoWrongType(callerInfo |> string, desiredTyName, NicePrint.minimalStringOfType cenv.denv ty), m))
24082420

24092421
minfo.GetParamDatas(cenv.amap, m, minfo.FormalMethodInst)
24102422
|> List.iterSquared (fun (ParamData(_, isInArg, _, optArgInfo, callerInfo, nameOpt, _, ty)) ->
@@ -2421,11 +2433,9 @@ let CheckEntityDefn cenv env (tycon: Entity) =
24212433
| CallerSide _, CallerLineNumber ->
24222434
if not (typeEquiv g g.int32_ty ty) then
24232435
errorR(Error(FSComp.SR.tcCallerInfoWrongType(callerInfo |> string, "int", NicePrint.minimalStringOfType cenv.denv ty), m))
2424-
| CalleeSide, CallerLineNumber ->
2425-
if not ((isOptionTy g ty) && (typeEquiv g g.int32_ty (destOptionTy g ty))) then
2426-
errorR(Error(FSComp.SR.tcCallerInfoWrongType(callerInfo |> string, "int", NicePrint.minimalStringOfType cenv.denv (destOptionTy g ty)), m))
2436+
| CalleeSide, CallerLineNumber -> errorIfNotOptional g.int32_ty "int" m ty callerInfo
24272437
| CallerSide _, (CallerFilePath | CallerMemberName) -> errorIfNotStringTy m ty callerInfo
2428-
| CalleeSide, (CallerFilePath | CallerMemberName) -> errorIfNotStringOptionTy m ty callerInfo
2438+
| CalleeSide, (CallerFilePath | CallerMemberName) -> errorIfNotOptional g.string_ty "string" m ty callerInfo
24292439
)
24302440

24312441
for pinfo in immediateProps do

tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OptionalArguments/OptionalArguments.fs

+38-1
Original file line numberDiff line numberDiff line change
@@ -609,4 +609,41 @@ but here has type
609609
''T option'
610610
but here has type
611611
''a voption' "
612-
]
612+
]
613+
614+
[<Fact>]
615+
let ``Struct optional args can have caller member name`` () =
616+
617+
let source = """module TestLib
618+
open System.Runtime.CompilerServices
619+
620+
let printItOut x =
621+
printf "%s" $"{x};"
622+
623+
type Ab() =
624+
625+
static member aa ([<CallerMemberName; Struct>]?b: string) =
626+
printItOut b
627+
628+
static member bb ([<CallerLineNumber; Struct>]?i: int) =
629+
printItOut i
630+
631+
[<EntryPoint>]
632+
let main _args =
633+
Ab.aa()
634+
Ab.bb()
635+
Ab.aa("hello")
636+
Ab.bb(42)
637+
0
638+
"""
639+
640+
source
641+
|> FSharp
642+
|> withLangVersionPreview
643+
|> withNoWarn 25
644+
|> asExe
645+
|> compile
646+
|> ILVerifierModule.verifyPEFileWithSystemDlls
647+
|> run
648+
|> verifyOutputContains [|"main;18;hello;42;"|]
649+

tests/FSharp.Test.Utilities/Compiler.fs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1640,7 +1640,8 @@ Actual:
16401640
| Some (ExecutionOutput {Outcome = Failure ex }) ->
16411641
failwithf $"Eval or Execution has failed (expected to succeed): %A{ex}\n{diagnostics}"
16421642
| _ ->
1643-
failwithf $"Operation failed (expected to succeed).\n{diagnostics}"
1643+
1644+
failwithf $"Operation failed (expected to succeed).\n{diagnostics} \n OUTPUTs: %A{r.Output}"
16441645

16451646
let shouldFail (result: CompilationResult) : CompilationResult =
16461647
match result with

0 commit comments

Comments
 (0)