Semantic Diff

#9077 Print types from applied functors in created interfaces

3 commits

beb423d9411b3e39f7c07cd8bed109d485f33339..pr-9077

a06459296 · cknitt + Claude · Oct 27, 2026, 12:40 UTC

Print types from applied functors in created interfaces

Why

Create interface copied each type declaration from the source file at the declaration's location. A type of an applied functor or of an included module is located in the functor's body, possibly in another file, so the interface got the unsubstituted body type or whatever lines of the current file happened to be there. Types declared elsewhere are now printed from the signature.

modifiedDiagnostic create interface

module StrSet = CreateInterfaceFunctor.MakeSet({  type t = string  let compare = (a: string, b) => a < b ? -1 : a > b ? 1 : 0})
rescript
Before tests/analysis_tests/tests/src/CreateInterfaceFunctorUse.res
After tests/analysis_tests/tests/src/CreateInterfaceFunctorUse.res
module StrSet: {module StrSet: { type t = array<string> let add: (t, string) => array<string> let add: (t, string) => array<string>}}

Review

  • Are types declared in the module itself still copied verbatim? Yes. A type is copied when its location is in the source file and, inside a nested module, within that module's declaration, so attributes on local declarations are kept as before.
de88a9c01 · cknitt + Claude · Oct 27, 2026, 17:33 UTC

Copy same-file types outside functors verbatim in created interfaces

Codex review on #9077: a type of the same file reached through module type of or include was printed from the signature, which drops field attributes such as @as, so the interface no longer matched. Only types inside a functor body other than the module being printed, and types of other files, are printed from the signature now.

8a9ddb546 · cknitt + Claude · Oct 28, 2026, 07:39 UTC

Print the runtime names of record fields from signatures

Review on #9077: a type of an applied functor is printed from its signature, and the printed record dropped @as on its fields, so the created interface for module M = F({}) with type t = {@as("wire") field: int} in F's body didn't match. Record fields in the outcome tree now carry their runtime name, and the printer writes it as @as, which also shows it in hover and error messages.

modifiedDiagnostic created interface of an applied functor

module WithWire = (X: {}) => {  type t = {@as("wire") field: int}} module Applied = WithWire({})
rescript
Before
After
module Applied: {module Applied: { type t = {field: int} type t = {@as("wire") field: int}}}