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

Bad diagnostic when pattern matching nil that cannot be inferred #64279

Open
hamishknight opened this issue Mar 10, 2023 · 7 comments
Open

Bad diagnostic when pattern matching nil that cannot be inferred #64279

hamishknight opened this issue Mar 10, 2023 · 7 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself diagnostics QoI Bug: Diagnostics Quality of Implementation expressions Feature: expressions operators Feature: operators swift 5.9 type checker Area → compiler: Semantic analysis type inference Feature: type inference

Comments

@hamishknight
Copy link
Collaborator

The following gives a bad diagnostic:

func foo<T>() -> T { fatalError() }
if nil ~= foo() {} // error: Expression pattern of type 'String' cannot match values of type 'Substring'
@hamishknight hamishknight added bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself diagnostics QoI Bug: Diagnostics Quality of Implementation type checker Area → compiler: Semantic analysis labels Mar 10, 2023
@AnthonyLatsis AnthonyLatsis added operators Feature: operators expressions Feature: expressions type inference Feature: type inference swift 5.9 labels Mar 10, 2023
@Rajveer100
Copy link
Contributor

@hamishknight If I correctly understand the issue, the function foo<T>() -> T is a generic function with type T and throws a fatalError().

Next, the if block checks if nil contains the function foo() (which I am unsure of, but am aware of the operator ~= used as range).

Let me know to what I am missing out, and some brief description to get an idea!

@AnthonyLatsis
Copy link
Collaborator

Next, the if block checks if nil contains the function foo()

Not quite. See Expression Pattern.

@Rajveer100
Copy link
Contributor

Ok, I changed the snippet code this way, now it does throw fatalError():

import UIKit

func foo<T>() -> T { fatalError() }
if "nil" ~= foo() {} // error: Fatal Error

@hamishknight
Copy link
Collaborator Author

hamishknight commented Apr 17, 2023

Indeed, but the nil case is invalid because there's no valid type to infer for it, and we should ideally diagnose as such. What's currently happening is that the constraint system is trying each overload of ~=, and coming up with a bunch of bad solutions, and it just so happens that the func ~= (lhs: Substring, rhs: String) -> Bool solution is the least bad one, and we attempt to diagnose based on that.

@Rajveer100
Copy link
Contributor

I see!

@Rajveer100
Copy link
Contributor

After some finding, I managed to find the call point in ConstraintSystem.h under this if condition:

else if (operatorName == ctx.Id_MatchOperator) {
      DE.diagnose(anchor->getLoc(), diag::cannot_match_expr_pattern_with_value,
                  lhsType, rhsType);
    }

So we could probably add an check inside this to first check for the nil case as in the issue and add a more specific message?

@Rajveer100
Copy link
Contributor

@hamishknight What do you suggest?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself diagnostics QoI Bug: Diagnostics Quality of Implementation expressions Feature: expressions operators Feature: operators swift 5.9 type checker Area → compiler: Semantic analysis type inference Feature: type inference
Projects
None yet
Development

No branches or pull requests

3 participants