Skip to content

Fix issues with overlapping argument name and default value, using alias and default value together #5989

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

Merged
merged 11 commits into from
Feb 8, 2023

Conversation

mununki
Copy link
Member

@mununki mununki commented Feb 7, 2023

This PR fixes #5977, #5979

Comment on lines +14 to +18
function make$1(_props) {
while(true) {
_props = {};
continue ;
};
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 why this js output diff has made after running make test

Copy link
Collaborator

Choose a reason for hiding this comment

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

It should not happen. Try make clean and make test again.

@@ -0,0 +1,18 @@
@@jsxConfig({version: 4})
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you add this under jscomp/test instead? So it's compiler any time make lib is run, and you get normal error messages instead of a failed build test.

It would look like this:

@@bs.config({
  flags: ["-bs-jsx", "4"],
})


module C0 = {
  @react.component
  let make = (~a=2, ~b=a + 2) => {
    React.int(a + b)
  }
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

To me it gives "The module or file props can't be found.".

Copy link
Collaborator

Choose a reason for hiding this comment

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

And same error if I write it in some other project that installs this version of the compiler.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Notice @@bs.config, as @@jsxVersion would not be picked up by a single bsc invocation used to run tests.

let make = (props: props<'a, 'b>) => {
let b = switch props.b {
| Some(b) => b
| None => a * 2
Copy link
Collaborator

@cristianoc cristianoc Feb 7, 2023

Choose a reason for hiding this comment

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

If you copy paste this, you'll get a a not found.
The oder should be: first let a then b.
Also, it should not be let ... and but let ... let or it won't compile.

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually, a should refer to the outside scope of make function. The original code is this:

@react.component
let make = (~a=2, ~b=a*2) => <div />

So, a in (a* 2) is referring to out of this make function.

Copy link
Member Author

Choose a reason for hiding this comment

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

This is quite tricky than I guess. It has to be affected by the order, but it should not.

let make = (props) => {
  let a = 2 // 1
  let b = a * 2 // <- a should be reference to the outside of make function, but it refers to 1

Copy link
Member Author

Choose a reason for hiding this comment

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

We transform the optional labelled argument to nolabel argument props. So there no where to handle the default value that is the root cause of this issue, I guess.

type props<'a, 'b> = {a?: 'a, b?: 'b}
@react.component
let make = (props: props<'a, 'b>) => {
let b = switch props.b {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Given the error message I'm getting "The module or file props can't be found." this is probably a path A.foo where A happens to be props and not a field access, which it should be.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Field access is Pexp_field.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oops! Correct.

Copy link
Collaborator

@cristianoc cristianoc left a comment

Choose a reason for hiding this comment

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

Left a few comments.
First, to move the test so you get normal user-level error messages.
Then the first error indicated props.b is not done right.
Once that's fixed you should get "a not found".

@mununki
Copy link
Member Author

mununki commented Feb 8, 2023

Left a few comments. First, to move the test so you get normal user-level error messages. Then the first error indicated props.b is not done right. Once that's fixed you should get "a not found".

Fixed now.

@mununki
Copy link
Member Author

mununki commented Feb 8, 2023

module C0 = {
  let a = 1 // 2
  type props<'a, 'b> = {a?: 'a, b?: 'b}

  let make = (props: props<'a, 'b>) => {
    let b = switch props.b {
    | Some(b) => b
    | None => a * 2 // 1
    }
    and a = switch props.a {
    | Some(a) => a
    | None => 2
    }

    React.int(a + b)
  }
  let make = {
    let \"DefaultValueProp$C0" = (props: props<_>) => make(props)

    \"DefaultValueProp$C0"
  }
}

Due to the list of value bindings, 1 is referring to 2. It doesn't matter the order:

module C0 = {
  let a = 1 // 2
  type props<'a, 'b> = {a?: 'a, b?: 'b}

  let make = (props: props<'a, 'b>) => {
    let a = switch props.a {
    | Some(a) => a
    | None => 2
    }
    and b = switch props.b {
    | Some(b) => b
    | None => a * 2 // 1
    }

    React.int(a + b)
  }
  let make = {
    let \"DefaultValueProp$C0" = (props: props<_>) => make(props)

    \"DefaultValueProp$C0"
  }
}

Copy link
Collaborator

@cristianoc cristianoc left a comment

Choose a reason for hiding this comment

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

Still does not apply the fix I was mentioning.
See how this compiles:

let foo = (~a=2, ~b=a * 2) => a + b

but this does not:

module C0 = {
  @react.component
  let make = (~a=2, ~b=a * 2) => {
    React.int(a + b)
  }
}

It's not true that a comes from the outside. And the order does matter. First let a then let b.
That's how default args work.

@mununki
Copy link
Member Author

mununki commented Feb 8, 2023

Still does not apply the fix I was mentioning. See how this compiles:

let foo = (~a=2, ~b=a * 2) => a + b

but this does not:

module C0 = {
  @react.component
  let make = (~a=2, ~b=a * 2) => {
    React.int(a + b)
  }
}

It's not true that a comes from the outside. And the order does matter. First let a then let b. That's how default args work.

Sorry, I didn't know how the default value works as same name of argument exactly before:

let f = (~a=2, ~b=a*2, ()) => a + b
// vs.
let f = (~b=a*2, ~a=2, ()) => a + b // error: can't find a

I fixed it edcf127

Copy link
Collaborator

@cristianoc cristianoc left a comment

Choose a reason for hiding this comment

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

Looks great.
Added a couple of comments to the examples.

})

module C0 = {
let a = 1
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you remove this line. as it's not needed.

Copy link
Member Author

Choose a reason for hiding this comment

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

Got it 6c0a0bb

@@ -0,0 +1,10 @@
module C0 = {
let a = 1
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you remove this line, as it's not needed.

Copy link
Member Author

Choose a reason for hiding this comment

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

Got it 6c0a0bb

@mununki
Copy link
Member Author

mununki commented Feb 8, 2023

Now I understand that it is self-evident because it is curried.

let f = (~a=1) => { (~b=a*2) => { a + b } }

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.

JSXv4: Unable to use argument with default value in other default arguments
2 participants