Skip to content

Preserve extension SRTP witnesses across files and inline calls - #20717

Open
T-Gro wants to merge 5 commits into
mainfrom
t-gro-extension-srtp-fixes
Open

T-Gro wants to merge 5 commits into
mainfrom
t-gro-extension-srtp-fixes

Conversation

@T-Gro

@T-Gro T-Gro commented Oct 6, 2026

Copy link
Copy Markdown
Member

Description

Fixes #20683
Fixes #20684
Fixes #20685

Inline calls keep their extension constraints and selected witnesses. Generic extension forwarding also compiles without optimization.

Checklist

  • Test cases added

  • Performance benchmarks added in case of performance changes

  • Release notes entry updated:

    Please make sure to add an entry with short succinct description of the change as well as link to this pull request to the respective release notes file, if applicable.

    Release notes files:

    • If anything under src/Compiler has been changed, please make sure to make an entry in docs/release-notes/.FSharp.Compiler.Service/<version>.md, where <version> is usually "highest" one, e.g. 42.8.200
    • If language feature was added (i.e. LanguageFeatures.fsi was changed), please add it to docs/release-notes/.Language/preview.md
    • If a change to FSharp.Core was made, please make sure to edit docs/release-notes/.FSharp.Core/<version>.md where version is "highest" one, e.g. 8.0.200.

    Information about the release notes entries format can be found in the documentation.
    Example:

    If you believe that release notes are not necessary for this PR, please add NO_RELEASE_NOTES label to the pull request.

Fixes #20683
Fixes #20684
Fixes #20685

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@T-Gro
T-Gro requested a review from a team as a code owner October 6, 2026 15:04
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

@T-Gro T-Gro left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These deletions remove source-position replay from the August implementation in #19602. RFC FS-1043 remains supported.

| _ -> None)
| _ -> None)

let GetTraitConstraintForCodegen (g: TcGlobals) (traitInfo: TraitConstraintInfo) =

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This replaces the source-position replay from #19602 with witnesses in each call's existing constraint cells. RFC FS-1043 remains supported.

let css = CreateCodegenState tcVal g amap
let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m (DisplayEnv.Empty g)
// Failed probes must not persist provisional solutions in generic inline bodies.
NoTrace.CollectThenUndoOrCommit

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Failed codegen probes now undo provisional solutions. Generic forwarding keeps its witness arguments without optimization.

minfo.IsExtensionMember ||
// The fallback must not expose explicit interface implementations as ordinary operators.
not (IsTraitMethodOnSupportType g traitInfo minfo))
CreateTraitContext selectExtensionMethods nenv AccessibleFromEverywhere

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normal extension lookup replaces the manual fallback from #19602. Earlier files supply signature values, which code generation can bind.

and OptimizeTraitCall cenv env (traitInfo, args, m) =

let g = cenv.g
let traitInfo = ConstraintSolver.GetTraitConstraintForCodegen g traitInfo

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This removes the replay recovery from #19602. The optimizer uses the retained witness before fallback lookup.

OptimizeExpr cenv env specLambda |> fst

// Equal types do not imply equal consumer-selected extension witnesses.
let canCacheSpecialization =

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When imported traits lack a captured scope, equal types can select different extension witnesses. These specializations skip cache reuse, not recursion protection.

// The outer ConditionalWeakTable partitions the record by the CCU being compiled so nothing leaks or
// cross-contaminates when a single shared (framework) TcGlobals serves many projects under FCS.
// Not serialized (consistent with traitCtxt): purely intra-compilation.
let extensionOperatorSolutions =

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This removes the replay table from #19602 and its FSI reset hooks. Each call's constraint cells now retain the witness.


member _.AccessRights = ad

member _.Remap(remapType, remapValRef, remapStamp) =

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The captured scope from #19602 now follows normal identity remapping through signatures and inline copies. NameResolution stays unchanged.

Keep exception-safe rollback. Refresh the exact neg45 baseline and run the existing case on every runtime and in Debug.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@T-Gro
T-Gro requested a review from abonie October 7, 2026 13:40

@T-Gro T-Gro left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 🕵️ LGTM

@T-Gro T-Gro added the AI-reviewed PR reviewed by AI review council label Oct 7, 2026
@T-Gro

T-Gro commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

/azp run fsharp-ci

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@abonie
abonie self-requested a review October 8, 2026 12:12
let canCacheSpecialization =
allTyargsAreConcrete &&
(not (g.langVersion.SupportsFeature LanguageFeature.ExtensionConstraintSolutions) ||
traits |> List.forall (fun traitInfo -> traitInfo.TraitContext.IsSome))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖🕵️ Silent wrong-code under --langversion:preview --optimize-: a captured context still allows a specialization with B's witness to be reused for an independent A call.

module A =
    type System.String with
        static member (*) (x: string, y: string) = x + y
    let inline combine x y = x * y

module B =
    type System.String with
        static member (*) (x: string, y: string) = y + x
    let inline combineTwice x y =
        let first = x * y
        first, A.combine x y

[<EntryPoint>]
let main _ =
    printfn "B=%A" (B.combineTwice "a" "b")
    printfn "A=%s" (A.combine "a" "b")
    0

--optimize-: B=("ba", "ba"), A=ba. --optimize+, or removing the preceding B call: A=ab. Reproduced with both realsig modes. The base compiler rejects the unoptimized case; this PR newly accepts it with the wrong result. Cache eligibility needs to account for the effective selected witnesses, not just the presence of TraitContext.

Keep intrinsic candidates separate from scope-provided operators. Prefer applicable primitive built-ins while preserving heterogeneous extension solutions and witness transport.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@T-Gro
T-Gro requested a review from abonie October 8, 2026 13:18
Use a struct tuple instead of an anonymous struct record for the internal lookup result. Preserve candidate origin, order and built-in arbitration without adding generated public types or changing the API baseline.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI-reviewed PR reviewed by AI review council

Projects

Status: In Progress

2 participants