Skip to content

AttachMembers doesn't work with operators #2825

Closed

Description

@texastoland

Description

Incorrect function name is used at operator call site.

Repro code

REPL

open Fable.Core

[<AttachMembers>]
type Number =
  | Float of float
  | Int of int
  static member (+)(n1: Number, n2: Number) =
    match (n1, n2) with
    | (Float f1, Float f2) -> Float(f1 + f2)
    | (Float f, Int i) -> Float(f + float i)
    | (Int i, Float f) -> Float(float i + f)
    | (Int i1, Int i2) -> Int(i1 + i2)

Int 2 + Float 2 |> printfn "%O"

Expected

Number$.op_Addition(new Number$(1, 2), new Number$(0, 2))

Actual

Number$["+"](new Number$(1, 2), new Number$(0, 2))

export class Number$ extends Union {
    constructor(tag, ...fields) {
        super();
        this.tag = (tag | 0);
        this.fields = fields;
    }
    cases() {
        return ["Float", "Int"];
    }
    static op_Addition(n1, n2) {
        let i1, i2, f_1, i_1, f, i, f1, f2;
        const matchValue = [n1, n2];
        return (matchValue[0].tag === 1) ? ((matchValue[1].tag === 1) ? ((i1 = (matchValue[0].fields[0] | 0), (i2 = (matchValue[1].fields[0] | 0), new Number$(1, i1 + i2)))) : ((f_1 = matchValue[1].fields[0], (i_1 = (matchValue[0].fields[0] | 0), new Number$(0, i_1 + f_1))))) : ((matchValue[1].tag === 1) ? ((f = matchValue[0].fields[0], (i = (matchValue[1].fields[0] | 0), new Number$(0, f + i)))) : ((f1 = matchValue[0].fields[0], (f2 = matchValue[1].fields[0], new Number$(0, f1 + f2)))));
    }
}

(function () {
    const arg10 = Number$["+"](new Number$(1, 2), new Number$(0, 2));
    toConsole(printf("%O"))(arg10);
})();

Related information

  • REPL: 3.7.0
  • Fable: 3.7.0-beta-015

Activity

  1. github-actions commented on Apr 21, 2026

    @github-actions
    Contributor

    🤖 This is an automated response from Repo Assist.

    This issue was filed against Fable 3.7.0-beta. Based on a code review of the current Fable 4.x source, this bug appears to have been fixed.

    Root cause (3.7.0-beta): The call path for a static operator on an [<AttachMembers>] type used getMemberDisplayName(memb) to look up the member name, which returns the F# operator symbol "+" for op_Addition. This caused the wrong property access Number$["+"] to be generated at the call site, while the declaration correctly used op_Addition.

    Current behaviour (4.x): getAbstractMemberInfo in FSharp2Fable.Util.fs now uses memb.CompiledName (which returns "op_Addition") for non-getter/setter attached members. Both the declaration path (transformExplicitlyAttachedMember via FsMemberFunctionOrValue.CompiledName(memb)) and the call path now agree on "op_Addition", so the generated code uses the correct identifier.

    If you're still seeing this with a current Fable release, please reopen and share a minimal repro. Otherwise, feel free to close this issue.

    Generated by 🌈 Repo Assist, see workflow run. Learn more.

    To install this agentic workflow, run

    gh aw add githubnext/agentics/workflows/repo-assist.md@51c8f6ad4357d2ecc06e47120031b3d75e80227d
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions