Skip to content

Conversation

cknitt
Copy link
Member

@cknitt cknitt commented Oct 4, 2025

Fixes #7722

@cknitt cknitt force-pushed the return-jsx-element branch from 5bf383c to 64dc1a2 Compare October 4, 2025 08:19
@cknitt cknitt force-pushed the return-jsx-element branch from 64dc1a2 to 80b9809 Compare October 4, 2025 08:25
Copy link

pkg-pr-new bot commented Oct 4, 2025

Open in StackBlitz

rescript

npm i https://pkg.pr.new/rescript-lang/rescript@7939

@rescript/darwin-arm64

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/darwin-arm64@7939

@rescript/darwin-x64

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/darwin-x64@7939

@rescript/linux-arm64

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/linux-arm64@7939

@rescript/linux-x64

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/linux-x64@7939

@rescript/runtime

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/runtime@7939

@rescript/win32-x64

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/win32-x64@7939

commit: d55db81

This has type: int
But it's expected to have type: Jsx.element

In JSX, all content must be JSX elements. You can convert int to a JSX element with React.int. No newline at end of file
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error messages could be further improved for this special case.
Leaving that to @zth. 🙂

| Nonrecursive ->
Some
(make_new_binding ~loc:empty_loc ~full_module_name modified_binding)
(make_new_binding ~loc:binding_loc ~full_module_name modified_binding)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about this change that Codex made or about the loc handling in general.
/cc @zth

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be wary of changing locs from empty to something else. Since it's used by the editor tooling. But maybe there's a reason for this change? Could you ask Codex?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex says:

That change happened when I added the Jsx.element return constraint in compiler/syntax/src/jsx_v4.ml:919. The new constraint uses the loc you pass into make_new_binding, and with the old empty_loc everything was reported as coming from “line 1, char 0” of the file. Switching to binding.pvb_loc makes the generated wrapper carry the component’s real location, so any type error (or merlin focus) now points back to the actual let make definition instead of the dummy top-of-file location.

I do not see any effect of this change in the tests. When I revert it, tests still give the same result.

@cknitt cknitt requested a review from zth October 4, 2025 13:02
Comment on lines -25 to +28
{"contents": {"kind": "markdown", "value": "```rescript\nstring\n```"}}
{"contents": {"kind": "markdown", "value": "```rescript\nJsx.element\n```\n\n---\n\n```\n \n```\n```rescript\ntype Jsx.element\n```\nGo to: [Type definition](command:rescript-vscode.go_to_location?%5B%22Jsx.res%22%2C25%2C0%5D)\n"}}

Hover src/Hover.res 42:15
{"contents": {"kind": "markdown", "value": "```rescript\nstring\n```"}}
{"contents": {"kind": "markdown", "value": "```rescript\nJsx.element\n```\n\n---\n\n```\n \n```\n```rescript\ntype Jsx.element\n```\nGo to: [Type definition](command:rescript-vscode.go_to_location?%5B%22Jsx.res%22%2C25%2C0%5D)\n"}}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change expected?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, maybe not

@react.component
let make = (~name) => React.string(name)
//           ^hov

module C2 = {
  @react.component
  let make2 = (~name: string) => React.string(name)
  //           ^hov
}

Comment on lines 1 to +2
Hover src/Jsx2.resi 1:4
{"contents": {"kind": "markdown", "value": "```rescript\nprops<string>\n```\n\n---\n\n```\n \n```\n```rescript\ntype props<'first> = {first: 'first}\n```\nGo to: [Type definition](command:rescript-vscode.go_to_location?%5B%22Jsx2.resi%22%2C0%2C0%5D)\n"}}
{"contents": {"kind": "markdown", "value": "```rescript\nJsx.element\n```\n\n---\n\n```\n \n```\n```rescript\ntype Jsx.element\n```\nGo to: [Type definition](command:rescript-vscode.go_to_location?%5B%22Jsx.res%22%2C25%2C0%5D)\n"}}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, is this expected? If so, why?

module M4: {
@react.component
let make: (~first: string, ~fun: string=?, ~second: string=?) => React.element
let make: (~first: string, ~fun: string=?, ~second: string=?) => Jsx.element
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting change. I would assume we'd still want it to be React.element?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As the return type of all Jsx component functions is now constrained to Jsx.element, it makes sense that that's also what turns up when generating the interface.

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

Successfully merging this pull request may close these issues.

JSX PPX - add Jsx.element return constraint
2 participants