rescript-compiler icon indicating copy to clipboard operation
rescript-compiler copied to clipboard

GADT is not scoped properly in react component

Open shulhi opened this issue 2 years ago • 5 comments

Here's the reproduction

type text_tag<'a>

type heading
type text
type image

type rec block_like<'a> =
  | BlockHeading: block_like<text_tag<heading>>
  | BlockText: block_like<text_tag<text>>
  | BlockImage: block_like<image>

type text_like<'a> = block_like<text_tag<'a>>

// good
let h = (block: block_like<text_tag<heading>>) => {
  switch block {
  | BlockHeading => "I'm a heading"
  }
}

// good
let g = (type a, block: text_like<a>) => {
  switch block {
  | BlockText => "I'm a text"
  | BlockHeading => "I'm a heading"
  }
}

// Bug?
// Pattern match will give the proper error if this react component is in the same file as the GADT
//
// Move this component to a different module, and uncomment the BlockImage line. It still compiles
@react.component
let make = (~block: block_like<text_tag<heading>>) => {
  let _ = switch block {
  | BlockHeading => ()
//  | BlockImage => ()
  }

I'm using Rescript 10.1.4, and Rescript-React 0.11.0.

The GADT for some reason, is not scoped properly when used with react component outside the module where the GADT is defined.

shulhi avatar Jul 31 '23 10:07 shulhi

This is not exclusive to React.

let k = (block: block_like<text_tag<heading>>) => {
  let _ = switch block {
  | BlockHeading => ()
  | BlockImage => () // Error if this function is defined in the same module as the GADT (Good), but no error outside of the module (BAD)
  }
}

shulhi avatar Jul 31 '23 11:07 shulhi

Is this an issue you can reproduce in v11?

mununki avatar Jul 31 '23 12:07 mununki

@react.component
let make = (type a, ~block: text_like<a>) => {
  let _ = switch block {
  | BlockHeading => ()
  | BlockText => () // BlockText would be fine to compile
  }
}

It makes sense to me. What do you think?

mununki avatar Jul 31 '23 12:07 mununki

Is this an issue you can reproduce in v11?

I'll report back with v11.

@react.component
let make = (type a, ~block: text_like<a>) => {
  let _ = switch block {
  | BlockHeading => ()
  | BlockText => () // BlockText would be fine to compile
  }
}

It makes sense to me. What do you think?

That makes sense. I have that in my example above too. The bug only happens when the function is not within the same module as the GADT.

So, using block_like<text_tag<heading>> should still give out error because BlockText is of type block_like<text_tag<text>>. It correctly throws error when the function is inside the same module as the GADT.

shulhi avatar Aug 01 '23 01:08 shulhi

Sorry for the late update, I've tested recently with the latest version of rescript (v11-rc5) and this is still happening.

shulhi avatar Oct 28 '23 08:10 shulhi