# Specialization vs Indirections #7907

Open
opened this Issue Feb 2, 2019 · 1 comment

Projects
None yet
1 participant
Collaborator

### vicuna commented Feb 2, 2019

Original bug ID: 7907
Reporter: @Drup
Status: new
Resolution: open
Priority: normal
Severity: minor
Category: middle end (typedtree to clambda)
Monitored by: @hcarty

## Bug description

Several people proposed to have functors that would easily introduce infix operators based on given primitives. That scheme is also used in the monomorphic library (https://github.com/kit-ty-kate/ocaml-monomorphic) and a few others.

We already know that specialization of primitives and abstraction don't play particularly well together (#7440), but apparently, basic indirections are really bad too:

module Make (A : sig type t end) : sig
val (=) : A.t -> A.t -> bool
(* external ( = ) : A.t -> A.t -> bool = "%equal" (* SPECIALIZE IF UNCOMENTED *) *)
end = struct
external ( = ) : A.t -> A.t -> bool = "%equal"
end

module F = Make(Float)
let equal1 (a : float) b = F.(=) a b (* NOT SPECIALIZED )
let equal2 (a : float) b = (=) a b (
SPECIALIZED *)

inlining often doesn't help at all with functors, but sometime does in less complex examples. The result is the same with clambda and flambda.

Collaborator Author

### vicuna commented Feb 5, 2019

 Comment author: @stedolan Internally, this issue is the same as #7440. When an external is exposed by a signature using "val" rather than "external", it is eta-expanded. In other words, the module: module Make (A : sig type t end) : sig val (=) : A.t -> A.t -> bool end = struct external ( = ) : A.t -> A.t -> bool = "%equal" end is internally converted to: module Make (A : sig type t end) : sig val (=) : A.t -> A.t -> bool end = struct external ( eq ) : A.t -> A.t -> bool = "%equal" let (=) a b = eq a b end This turns it into the same pattern as #7440.