Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specialization vs Indirections #7907

Open
vicuna opened this Issue Feb 2, 2019 · 1 comment

Comments

Projects
None yet
1 participant
@vicuna
Copy link
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.

@vicuna

This comment has been minimized.

Copy link
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.

@vicuna vicuna added the middle-end label Mar 14, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.