Skip to content
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

Add error tcActivePatternArgumentCountNotMatch #16846

Merged
merged 32 commits into from
May 2, 2024

Conversation

ijklam
Copy link
Contributor

@ijklam ijklam commented Mar 9, 2024

Description

Add a new error to improve readability for active pattern case argument count mismatch.

This active pattern case needs %d argument(s) and %d return value, but here has %d argument(s) and %d return value.

QUESTION: what is the best name for the "return value" of an active pattern case?

before:

图片

after:

图片

Fixes # (issue, if applicable)

Checklist

  • Test cases added

  • Performance benchmarks added in case of performance changes

  • Release notes entry updated:

    Please make sure to add an entry with short succinct description of the change as well as link to this pull request to the respective release notes file, if applicable.

    Release notes files:

    • If anything under src/Compiler has been changed, please make sure to make an entry in docs/release-notes/.FSharp.Compiler.Service/<version>.md, where <version> is usually "highest" one, e.g. 42.8.200
    • If language feature was added (i.e. LanguageFeatures.fsi was changed), please add it to docs/releae-notes/.Language/preview.md
    • If a change to FSharp.Core was made, please make sure to edit docs/release-notes/.FSharp.Core/<version>.md where version is "highest" one, e.g. 8.0.200.

    Information about the release notes entries format can be found in the documentation.
    Example:

    If you believe that release notes are not necessary for this PR, please add NO_RELEASE_NOTES label to the pull request.

Copy link
Contributor

github-actions bot commented Mar 9, 2024

❗ Release notes required


✅ Found changes and release notes in following paths:

Change path Release notes path Description
src/Compiler docs/release-notes/.FSharp.Compiler.Service/8.0.400.md

@ijklam
Copy link
Contributor Author

ijklam commented Mar 11, 2024

Should we allow this?

let (|T2|) a b = ()
match 2 with T2 1 -> ();;

This is an error now
图片

@ijklam ijklam marked this pull request as ready for review March 11, 2024 23:14
@ijklam ijklam requested a review from a team as a code owner March 11, 2024 23:14
@vzarytovskii
Copy link
Member

Should we allow this?

let (|T2|) a b = ()
match 2 with T2 1 -> ();;

This is an error now 图片

I think this shouldn't be explicitly allowed.

@vzarytovskii
Copy link
Member

QUESTION: what is the best name for the "return value" of an active pattern case?

I think "return value" works, however "1 return value" in the error message looks a bit awkward.

@T-Gro
Copy link
Member

T-Gro commented Mar 12, 2024

My feedback for the wording:
For parametrized active patterns, the message should say "parameters" when there is a mismatch.
For non-parametrized actived patterns (will be a majority), the 0 parameters/arguments would be better not mentioned at all in the message.

For the return value, I would use the wording:
This active pattern returns 1 value, but the usage here matches 0 values

@ijklam
Copy link
Contributor Author

ijklam commented Mar 12, 2024

What about this?

For parametrized single case active pattern and partial active pattern:

This active pattern requires %d parameter(s) and returns %d value, but the usage here matches %d argument(s) and %d return value.

For else:

This active pattern returns %d value, but the usage here matches %d return value(s).

@vzarytovskii @T-Gro

@T-Gro
Copy link
Member

T-Gro commented Mar 18, 2024

value(s).

That looks better to me.
But anywhere you had "%d value", I would suggest to apply "value(s)".
Otherwise it would just look bad in the case of 0,2 or more.

@psfinaki
Copy link
Member

It's a good idea to improve this error. At the same time, as a non-user of active patterns, I got lost even with the new message.
"Return value(s)" sound very misleading to me, how about "captured value(s)"?

@brianrourkeboll
Copy link
Contributor

That is not a partial active pattern. And before this PR, the usage also cannot compile without a (). This PR will not change that.

Right. Although it's arguably somewhat unfortunate that total active patterns differ from partial/Boolean-returning ones in this way.

These were the four messages I originally had in my comment, the third of which sounds like it would be used for partial/Boolean-returning parameterized patterns:

  1. This active pattern does not expect any arguments, i.e., it should be used like 'P' instead of 'P x'.
  2. This active pattern expects exactly one pattern argument, e.g., 'P x'.
  3. This active pattern expects %d expression argument(s), e.g., 'P e1...'.
  4. This active pattern expects %d expression argument(s) and a pattern argument, e.g., 'P e1... pat'.

I.e., (3) would be used for:

// Expects: 1 expression argument, 0 pattern arguments.
let (|P|_|) expr2 expr1 = Some P

match expr1 with P ->//               ↑
//               This active pattern expects 1 expression argument(s), e.g., 'P e1...'.

match expr1 with P expr2 expr3 ->//               ↑
//               This active pattern expects 1 expression argument(s), e.g., 'P e1...'.

@ijklam
Copy link
Contributor Author

ijklam commented Apr 23, 2024

图片
the four situation @brianrourkeboll

@brianrourkeboll
Copy link
Contributor

@Tangent-90

the four situation

I think this is a pretty solid improvement over the status quo.

I guess since we do have the expected number of expression and pattern arguments available to us, we could in theory even offer something like P e1 e2 e3, P e1 e2 pat, etc., in the examples, rather than using e1... as a stand-in for $n$ expressions.

I wonder whether it would be worth doing something like:

// Use a prebuilt expr args string for these that has an example with the actual number of args.
"This active pattern expects %d expression argument(s), e.g., '%s%s'."
"This active pattern expects %d expression argument(s) and a pattern argument, e.g., '%s%s pat'."

and

let fmtExprArgs paramCount =
    let rec loop i (sb: StringBuilder) =
        let cutoff = 10
        if i > paramCount then sb.ToString()
        elif i > cutoff then sb.Append("...").ToString()
        else loop (i + 1) (sb.Append(" e").Append i)

    loop 1 (StringBuilder())

let msg =
    match paramCount, returnCount with
    | 0, 0 -> FSComp.SR.tcActivePatternArgsCountNotMatchNoArgsNoPat(caseName, caseName)
    | 0, _ -> FSComp.SR.tcActivePatternArgsCountNotMatchOnlyPat(caseName)
    | _, 0 -> FSComp.SR.tcActivePatternArgsCountNotMatchArgs(paramCount, fmtExprArgs paramCount, caseName)
    | _, _ -> FSComp.SR.tcActivePatternArgsCountNotMatchArgsAndPat(paramCount, fmtExprArgs paramCount, caseName)

giving

This active pattern expects 2 expression argument(s), e.g., 'P e1 e2'.
This active pattern expects 3 expression argument(s) and a pattern argument, e.g., 'P e1 e2 e3 pat'.

etc.

Or would that be overkill? What do you think @psfinaki?

@psfinaki
Copy link
Member

In the topic of diagnostics, it's hard to do an overkill, it's more about perfectionism here now :)

The current state of the art is definitely an improvement compared to the main. "Use 'IsEven' instead of 'IsEven x' probably captures most of the usecases and make the error very clear. The other errors importantly contain the expected number of "things" (arguments, expressions, patterns) and also list all these terms, like hey, there are all these capabilities of active patterns, read the docs if you're interested.

So @Tangent-90 if you're not tired yet, feel free to use Brian's addition. If you are tired, feel free to leave things as they are. I'd just ask to add the tests for the new errors, among other things they can serve as documentation for the time being.

@ijklam
Copy link
Contributor Author

ijklam commented Apr 26, 2024

message updated and test added @brianrourkeboll @psfinaki

Copy link
Member

@psfinaki psfinaki left a comment

Choose a reason for hiding this comment

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

Good stuff, thanks for this. Active patterns are much more usable now :)

@psfinaki psfinaki enabled auto-merge (squash) May 2, 2024 13:16
@psfinaki
Copy link
Member

psfinaki commented May 2, 2024

Build errors are unrelated, we hope to resolve those soon, sorry.

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

Successfully merging this pull request may close these issues.

7 participants