Skip to content

ReScript 9.1: weird error message if optional prop has no type annotation #5071

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

Closed
cknitt opened this issue Apr 14, 2021 · 6 comments
Closed

Comments

@cknitt
Copy link
Member

cknitt commented Apr 14, 2021

Consider the following React component:

Test.resi:

@react.component
let make: (~s: string=?) => React.element

Test.res:

@react.component
let make = (~s=?) =>
  switch s {
  | Some(s) => React.string(s)
  | None => React.null
  }

This compiles fine in ReScript 9.0.

In ReScript 9.1, it gives me the following weird error message:

  The implementation /Users/christoph/projects/cca/xxx/src/navigation/Test.res
       does not match the interface src/navigation/test.cmi:
       Values do not match:
         external makeProps: (~?s: 's, ~?key: string, unit) => {"s": option<'s>} =
  "" "
      A!s@A#keyA@@@"
       is not included in
         external makeProps: (~?s: string, ~?key: string, unit) => {
  "s": option<string>,
} =
  "" "
      A!sAA#keyA@@@"
       File "/Users/christoph/projects/cca/xxx/src/navigation/Test.resi", line 1, characters 0-58:
         Expected declaration
       File "Test", line 1: Actual declaration

If I change Test.res to

@react.component
let make = (~s: option<string>=?) =>
  switch s {
  | Some(s) => React.string(s)
  | None => React.null
  }

it compiles fine with ReScript 9.1.

@bobzhang
Copy link
Member

this maybe related to jsx cc @IwanKaramazow @rickyvetter

@anmonteiro
Copy link
Contributor

anmonteiro commented Apr 14, 2021

This was introduced in #4960.

It only happens if there's an interface file. ReScript started trying to unbox options by checking whether it has been inferred to option<_>, but in this case the inference just says 'a.

@rickyvetter
Copy link
Contributor

rickyvetter commented Apr 14, 2021

Definitely has to do with the obj tags that ReScript React generates under the hood. I can reproduce with this code:

module Test: {
  @obj
  external makeProps: (~s: string=?, unit) => Js.t<{"s": string}> = ""
} = {
  @obj
  external makeProps: (~s: 's=?, unit) => Js.t<{"s": 's}> = ""
}

dsource with 9.0.2:

[@@@config { flags = [|"-dsource"|] }]
module Test :
  sig
    external makeProps :
      ?s:((string)[@ns.namedArgLoc ]) -> unit -> < s: string   >  Js.t Js.t =
        ""
        "\132\149\166\190\000\000\000\012\000\000\000\007\000\000\000\018\000\000\000\018\145\160\160A\145!s\160\160@@@"
  end =
  struct
    external makeProps :
      ?s:(('s)[@ns.namedArgLoc ]) -> unit -> < s: 's   >  Js.t Js.t = ""
        "\132\149\166\190\000\000\000\012\000\000\000\007\000\000\000\018\000\000\000\018\145\160\160A\145!s\160\160@@@"
  end

dsource with e3371bd (note the differences in the external string - before they were identical):

[@@@config { flags = [|"-dsource"|] }]
module Test :
  sig
    external makeProps :
      ?s:((string)[@ns.namedArgLoc ]) -> unit -> < s: string   >  Js.t = ""
        "\132\149\166\190\000\000\000\r\000\000\000\007\000\000\000\019\000\000\000\019\145\160\160A\161!sA\160\160@@@"
  end =
  struct
    external makeProps :
      ?s:(('s)[@ns.namedArgLoc ]) -> unit -> < s: 's   >  Js.t = ""
        "\132\149\166\190\000\000\000\r\000\000\000\007\000\000\000\019\000\000\000\019\145\160\160A\161!s@\160\160@@@"
  end

@bobzhang
Copy link
Member

This is indeed fragile, we may change the encoding in the future

@rickyvetter
Copy link
Contributor

Is there a good way to avoid the breakage? Happy to modify the ppx but we don't have the info in the impl ast.

@bobzhang
Copy link
Member

@rickyvetter I am going to fix on my side, thanks for checking

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants