Skip to content

[DiagnosticsQoI] SR-6272 Tailored diagnostics with fixits for numerical conversions#13272

Merged
xedin merged 8 commits intoswiftlang:masterfrom
chuganzy:SR-6272
Jan 12, 2018
Merged

[DiagnosticsQoI] SR-6272 Tailored diagnostics with fixits for numerical conversions#13272
xedin merged 8 commits intoswiftlang:masterfrom
chuganzy:SR-6272

Conversation

@chuganzy
Copy link
Contributor

@chuganzy chuganzy commented Dec 5, 2017

If there's an explicit numeric conversion that could make the system type-check, suggest "fix it".

Resolves https://bugs.swift.org/browse/SR-6272

@chuganzy chuganzy changed the title SR-6272 Tailored diagnostics with fixits for numerical conversions [Compiler] SR-6272 Tailored diagnostics with fixits for numerical conversions Dec 5, 2017
@chuganzy chuganzy changed the title [Compiler] SR-6272 Tailored diagnostics with fixits for numerical conversions [DiagnosticsQoI] SR-6272 Tailored diagnostics with fixits for numerical conversions Dec 6, 2017
@CodaFi
Copy link
Contributor

CodaFi commented Dec 16, 2017

So sorry this got left by the wayside

@@ -4,7 +4,7 @@ protocol P {
associatedtype SomeType
Copy link
Contributor

Choose a reason for hiding this comment

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

All the little whitespace changes in this file should be reverted.

enum Foo: Int {
case bar
}
// expected-error@+2 {{binary operator '*' cannot be applied to operands of type 'Int' and 'Float'}} {{22-28=}} {{29-30=}}
Copy link
Contributor

Choose a reason for hiding this comment

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

This technically changed a whole lot more tests than just this one. I'm not sure if it's worth it to go through and update them all, but it would be nice to pull some non-integral/floating types into this test just to make sure we don't accidentally try to, say, cast a string to a Float or something.

Copy link
Contributor Author

@chuganzy chuganzy Dec 16, 2017

Choose a reason for hiding this comment

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

Makes sense! Will do!

Copy link
Contributor

@CodaFi CodaFi left a comment

Choose a reason for hiding this comment

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

It's a great first start. Comments inline.

@chuganzy
Copy link
Contributor Author

@CodaFi Addressed your comments. Thanks!

}
// expected-error@+2 {{binary operator '*' cannot be applied to operands of type 'Int' and 'Float'}} {{22-28=}} {{29-30=}}
// expected-note@+1 {{overloads for '*' exist with these partially matching parameter lists: (Float, Float), (Int, Int)}}
Foo.bar.rawValue * Float(0)
Copy link
Contributor

Choose a reason for hiding this comment

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

How does this fare with a contextual type?

let x: Float = Foo.bar.rawValue * Float(0)

Copy link
Contributor Author

@chuganzy chuganzy Dec 16, 2017

Choose a reason for hiding this comment

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

Good point..
It suggests to fix Float(0) to 0 so far..
Will fix it.

Copy link
Contributor

@CodaFi CodaFi Dec 16, 2017

Choose a reason for hiding this comment

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

tryIntegerCastFixIts treats the toType as a contextual type, always. You may want to try calling it on the LHS and RHS expressions of the binary operation and pass along their respective types and the contextual type. tryIntegerCastFixIts tells you if it succeeds in diagnosing part of the expression or not.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed with 72cf158.

@CodaFi
Copy link
Contributor

CodaFi commented Dec 16, 2017

@swift-ci please smoke test

@rudkx rudkx requested a review from xedin December 16, 2017 10:47
.highlight(rhsExpr->getSourceRange());

auto contextualType = CS.getContextualType();
if (contextualType && contextualType->isEqual(rhsType)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for the patch, @chuganzy! Unfortunately it's not always correct to use contextual type this way because it applies to the whole expression, while the problem could be local to sub-expression that might have some other type different from (or equal to) contextual type e.g.

struct A: ExpressibleByIntegerLiteral {
 typealias IntegerLiteralType = Int
 init(integerLiteral: Int) {}
 static func +(lhs: A, rhs: Int) -> Float { return 42.0 }
}
let x: Float = 1.0
let _: Float = A(integerLiteral: 42) + x
let _: Float = A(integerLiteral: 42) + 42.0
let _: Float = A(integerLiteral: 42) + x + 1.0

Most of the cases here are going to get suggestion to wrap x into A but there is no overload like that, or in case of first example is going to suggest wrapping A into Float which also might be incorrect because it's going to call a different overload all together.

Even without contextual type, I think we shouldn't try to suggest fix-its like that without taking into account more information e.g. what overloads are available for sub-expression and if suggestion is going to result in different overload choice or not.

Copy link
Contributor Author

@chuganzy chuganzy Dec 17, 2017

Choose a reason for hiding this comment

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

Hmm, makes sense.

Copy link
Contributor Author

@chuganzy chuganzy Dec 17, 2017

Choose a reason for hiding this comment

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

Addressed!
c80b569
5c37ccf

.highlight(rhsExpr->getSourceRange());

for (auto &candidate : calleeInfo.candidates) {
auto tupleType = dyn_cast<TupleType>(candidate.getArgumentType().getPointer());
Copy link
Contributor

Choose a reason for hiding this comment

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

It would be better to use:

if (auto *fnType = candidate.getUncurriedFunctionType()) {
   auto params = fnType->getParams();
}

here since we are trying to move away from using parameter types directly.

Copy link
Contributor

Choose a reason for hiding this comment

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

The problem though is that even though we could diagnose one of the candidates with cast fix-it it doesn't necessarily mean that we should do that... E.g. if I had +(A, Int) -> Float and +(A, Double) -> Float and I have A() + x where x: Float expression like in my previous example, the question is which fix-it should I suggest, Int or Double? IMHO none, because it's ambiguous what the user wanted to do here...

Copy link
Contributor Author

@chuganzy chuganzy Dec 18, 2017

Choose a reason for hiding this comment

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

So what is supposed to do in following case?

let x: Int = 0
let y: Float = 0
x * y

We have 2 candidates to suggest "fix-it" - x * Int(y) or Float(x) * y.

You think we should not suggest in this case?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, that's right, I don't think it makes sense to suggest fix-it in this case because it's unclear what is intended.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed 0df987a

@xedin
Copy link
Contributor

xedin commented Jan 11, 2018

@chuganzy I haven't forgotten about this, will take a look soon!

@xedin
Copy link
Contributor

xedin commented Jan 11, 2018

@swift-ci please smoke test

@xedin xedin merged commit ce847cc into swiftlang:master Jan 12, 2018
@xedin
Copy link
Contributor

xedin commented Jan 12, 2018

Thank you, @chuganzy!

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.

3 participants