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

[SR-14095] Improve diagnostic on incorrect usage of ^ and ** operators #56481

Open
typesanitizer opened this issue Jan 24, 2021 · 13 comments
Open
Labels
compiler The Swift compiler in itself improvement

Comments

@typesanitizer
Copy link

Previous ID SR-14095
Radar rdar://problem/73544956
Original Reporter @typesanitizer
Type Improvement
Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Improvement
Assignee mininny (JIRA)
Priority Medium

md5: 964ecd16cb126ad8ae4be3edb64d207f

Sub-Tasks:

  • SR-14196 Add a diagnostic for using unexisting "**" operator in Swift.

Issue Description:

// tmp.swift
import Foundation
let x: Double = 3.0
let y: Double = exp(x^2.0)
let z: Double = 3.0
let w: Double = exp(x**2.0) 

The error message in both cases is not that great.

tmp.swift:4:17: error: cannot convert value of type 'CGFloat' to specified type 'Double'
let y: Double = exp(x^2.0)
                ^~~~~~~~~~
                Double(   )
tmp.swift:4:22: error: referencing operator function '^' on 'SIMD' requires that 'CGFloat' conform to 'SIMD'
let y: Double = exp(x^2.0)
                     ^
Swift.SIMD:1:11: note: where 'Self' = 'CGFloat'
extension SIMD where Self.Scalar : FixedWidthInteger {
          ^
tmp.swift:6:22: error: cannot find operator '**' in scope
let w: Double = exp(x**2.0)
                     ^~ 

The first one is very confusing, why is it talking about CGFloat and SIMD. Many languages either have ^ or ** be the exponentiation operators. I think we should special-case diagnostics for ^ and ** for a better experience. For example: we could add a special case for ** to suggest that exponentiation can be done using the pow function if Foundation has been loaded.

I don't know what is going wrong with ^, but it would be nice to have a clearer diagnostic.

@typesanitizer
Copy link
Author

@swift-ci create

@swift-ci
Copy link
Collaborator

swift-ci commented Feb 7, 2021

Comment by Minhyuk Kim (JIRA)

I think this can be separated into 2 tasks:

  • Adding a special diagnostics for changing ** to Foundation.pow

  • Fix the weird diagnostics with ^ operator

What do you think? Is it okay if I create another ticket and separate this into two?

@typesanitizer
Copy link
Author

For the{{^}}/CGFloat case, I think we can delay making a change until #34401 lands, since that might affect type-checking for this particular error, and maybe change the diagnostic emitted.

Slava suggested that for **, we can add an unavailable operator in the standard library and have the message there point out that you can use {{Foundation.pow}}. kylemacomber (JIRA User) does that sound reasonable?

Splitting this bug report into sub-tasks makes sense. 👍

@stephentyrone
Copy link
Member

Sounds about right, though adding `**` just to make it unavailable might be an issue for projects that define that operator with different fixity or priority?

@typesanitizer
Copy link
Author

Hmm, naively, I would expect fixity and precedence to be shadowed (and hence not cause an issue), but I don't know if that's actually the case in practice.

@stephentyrone
Copy link
Member

Yup. That's my expectation of correct behavior as well, but I don't think we have a lot of test coverage exercising that particular corner of the language.

@swift-ci
Copy link
Collaborator

Comment by Minhyuk Kim (JIRA)

I created a draft PR here adding an error for "**" and it doesn't seem to cause an issue with custom operators. I may have missed something that I don't know; if there's any, please let me know! 🙂

@typesanitizer
Copy link
Author

mininny (JIRA User) are you planning to address the ^ as well? If not, we can unassign this JIRA.

@swift-ci
Copy link
Collaborator

Comment by Minhyuk Kim (JIRA)

theindigamer (JIRA User) I didn't know #34401 this PR was merged yet. I will look at the ^ issue as well soon 🙂

@typesanitizer
Copy link
Author

Awesome! Looking forward to it. 🙂

@swift-ci
Copy link
Collaborator

Comment by Minhyuk Kim (JIRA)

theindigamer (JIRA User)

I think I have a clue on what was wrong with the '^' and the SIMD diagnostic(looking up from all possible candidates outside of scope?) and how to circumvent it.

However, I have a question about what should be the correct behavior here.

let a: Double = 1.0
let b: Double = 2.0
let c = a^b

Assuming that the error about `SIMD` is removed, should the diagnostics be

  • Did you mean to use pow(::)? (For power operation suggestion)

or

  • Binary operator '^' cannot be applied to two 'Double' operands. (Which is the current behavior when Swift.SIMD is not imported. This would be for binary operator suggestion)

I guess both would make sense, but I do prefer the first diagnostics as it provides consistency with the '**' operator and is friendlier to swift beginners.

What do you think?

@typesanitizer
Copy link
Author

I think maybe the two could be combined. First would be to show a more useful diagnostic describing what the problem is. In this case, that is "Binary operator '^' cannot be applied to two 'Double' values" which is potentially useful as the Double may have been inferred. Then you provide a suggestion, which is "Did you mean to use pow(:🙂?" and offer a fix-it.

If the error is missing and there's only the suggestion, it is not super clear what the problem is, why the suggestion came up. If the error is present but the suggestion is missing, then it's not clear what the fix is (someone needs to google it).

@swift-ci
Copy link
Collaborator

Comment by Minhyuk Kim (JIRA)

theindigamer (JIRA User)

I created a draft PR here 🙂 I simply added a diagnostic note to be generated when '^' operator was unresolved and 'pow(*:*🙂' exists.

I wasn't able to find a way to suppress

referencing operator function '^' on 'SIMD' requires that 'CGFloat' conform to 'SIMD'

this diagnostic because it indeed was a proper lookup for '^' in the current context which should be allowed(i think?).

So similar code like this also results in the same error:

infix operator ^
protocol ASDF {
  static func ^(lhs: Self, rhs: Self) -> Double
}
let x: Double = 3.0^2.0

>> Referencing operator function '^' on 'ASDF' requires that 'Double' conform to 'ASDF'
add >> did you mean to use 'pow(_:_:)'?

Instead of silencing such error, as you mentioned, I figured it would be better to just offer an alternative option!

I'm not sure if the diagnostic is in the most optimal location, but I would appreciate any pointers!

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler The Swift compiler in itself improvement
Projects
None yet
Development

No branches or pull requests

3 participants