Skip to content

Commit 485f1b5

Browse files
committed
Fix
1 parent 06b4c09 commit 485f1b5

4 files changed

Lines changed: 71 additions & 2 deletions

File tree

src/Compiler/CodeGen/IlxGen.fs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,8 @@ type IlxGenOptions =
269269

270270
/// When set to true, the IlxGen will delay generation of method bodies and generated them later in parallel (parallelized across files)
271271
parallelIlxGenEnabled: bool
272+
273+
inlineNamedFunctions: bool
272274
}
273275

274276
/// Compilation environment for compiling a fragment of an assembly
@@ -5586,8 +5588,13 @@ and GenTraitCall (cenv: cenv) cgbuf eenv (traitInfo: TraitConstraintInfo, argExp
55865588

55875589
| None ->
55885590

5589-
// If witnesses are available, we should now always find trait witnesses in scope
5590-
assert not generateWitnesses
5591+
// When inlineNamedFunctions is true, all trait calls should be resolved via witnesses in scope.
5592+
// When inlineNamedFunctions is false, inline functions are kept as calls rather than inlined.
5593+
// Their witness arguments may contain TraitCall operations for constraints that were resolved
5594+
// without a witness (e.g., when the constraint is satisfied by a known concrete type).
5595+
// In such cases, generateWitnesses can be true (because other witnesses are in scope) but
5596+
// the specific trait's witness is not found. Fall through to the constraint solver to resolve it.
5597+
assert (not generateWitnesses || not cenv.options.inlineNamedFunctions)
55915598

55925599
let exprOpt =
55935600
CommitOperationResult(ConstraintSolver.CodegenWitnessExprForTraitConstraint cenv.tcVal g cenv.amap m traitInfo argExprs)

src/Compiler/CodeGen/IlxGen.fsi

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ type internal IlxGenOptions =
6161

6262
/// When set to true, the IlxGen will delay generation of method bodies and generate them later in parallel (parallelized across files)
6363
parallelIlxGenEnabled: bool
64+
65+
/// Indicates if inline named functions are being inlined or emitted as calls
66+
inlineNamedFunctions: bool
6467
}
6568

6669
/// The results of the ILX compilation of one fragment of an assembly

src/Compiler/Driver/OptimizeInputs.fs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,9 @@ let GenerateIlxCode
582582
isInteractiveItExpr = isInteractiveItExpr
583583
alwaysCallVirt = tcConfig.alwaysCallVirt
584584
parallelIlxGenEnabled = tcConfig.parallelIlxGen
585+
inlineNamedFunctions =
586+
tcConfig.inlineNamedFunctions
587+
|> Option.defaultValue (not tcConfig.debuginfo || tcConfig.optSettings.LocalOptimizationsEnabled)
585588
}
586589

587590
ilxGenerator.GenerateCode(ilxGenOpts, optimizedImpls, topAttrs.assemblyAttrs, topAttrs.netModuleAttrs)

tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,62 @@ let main _ =
539539
|> compileAndRun
540540
|> shouldSucceed
541541

542+
[<Fact>]
543+
let ``SRTP 14 - StateMachine with unresolved trait from composed inline function`` () =
544+
FSharp """
545+
open Microsoft.FSharp.Core.CompilerServices
546+
open Microsoft.FSharp.Core.CompilerServices.StateMachineHelpers
547+
open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators
548+
549+
[<Struct>]
550+
type S<'T> = member _.M(_: 'T) = ()
551+
552+
let inline f<'A, 'R, 'B when 'A: (member M: int -> 'R) and 'B: (member M: 'R -> unit)> (_a: 'A) : 'B = Unchecked.defaultof<_>
553+
554+
let inline g (_: S<'T>) =
555+
if __useResumableCode then
556+
__stateMachine<S<'T>, int>
557+
(MoveNextMethodImpl<_>(fun _ -> ()))
558+
(SetStateMachineMethodImpl<_>(fun _ _ -> ()))
559+
(AfterCode<_, _>(fun _ -> 0))
560+
else 0
561+
562+
let inline h a = g (f a)
563+
564+
[<EntryPoint>]
565+
let main _ =
566+
let _ = h (S<int>())
567+
0
568+
"""
569+
|> withDebug
570+
|> withNoOptimize
571+
|> asExe
572+
|> compileAndRun
573+
|> shouldSucceed
574+
575+
[<Fact>]
576+
let ``SRTP 15 - Composed inline with linked constraints`` () =
577+
FSharp """
578+
[<Struct>]
579+
type S<'T> = member _.M(_: 'T) = ()
580+
581+
let inline f<'A, 'R, 'B when 'A: (member M: int -> 'R) and 'B: (member M: 'R -> unit)> (_a: 'A) : 'B = Unchecked.defaultof<_>
582+
583+
let inline g (_: S<'T>) = 42
584+
585+
let inline h a = g (f a)
586+
587+
[<EntryPoint>]
588+
let main _ =
589+
let i = h (S<int>())
590+
if i = 42 then 0 else 1
591+
"""
592+
|> withDebug
593+
|> withNoOptimize
594+
|> asExe
595+
|> compileAndRun
596+
|> shouldSucceed
597+
542598
[<Fact>]
543599
let ``Member 01 - Non-generic`` () =
544600
FSharp """

0 commit comments

Comments
 (0)