-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[TypeChecker] SE-0213: Implement literal init via coercion #17860
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
Conversation
@swift-ci please smoke test compiler performance |
@swift-ci please benchmark |
// Note that the error here is because of an implicit conversion of the input | ||
// literal to 'Int'. | ||
_blackHole(Float80(18_446_744_073_709_551_617)) // expected-error {{integer literal '18446744073709551617' overflows when stored into 'Int'}} | ||
_blackHole(Float80(18_446_744_073_709_551_617)) // Ok |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@xedin Nice to see that the above FIXME's are addressed by this fix. Thanks!
test/Sema/diag_erroneous_iuo.swift
Outdated
let _: Optional<Int!> = nil // expected-error {{'!' is not allowed here; perhaps '?' was intended?}}{{20-21=?}} | ||
_ = Int!?(0) // expected-error {{'!' is not allowed here; perhaps '?' was intended?}}{{8-9=?}} | ||
_ = Int!?(0) // expected-error 3 {{'!' is not allowed here; perhaps '?' was intended?}}{{8-9=?}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like we're processing the type multiple times…
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, we have that in a couple of places already unfortunately, because we don't track if we produced the same diagnostic multiple times...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the TypeLoc, we should see it has already been resolved to a Type, and not resolve the TypeRepr again. Where is the diagnostic being emitted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see, it's probably my calls to resolveType which caused this, I'll try to fix it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, just needed to cache the type in a couple of places :)
Build comment file:Optimized (O)Regression (4)
Improvement (21)
No Changes (433)
Unoptimized (Onone)Regression (1)
Improvement (9)
No Changes (448)
Hardware Overview
|
@swift-ci please benchmark |
@swift-ci please smoke test compiler performance |
Build comment file:Summary for master smoketestUnexpected test results, excluded stats for ReactiveCocoa No regressions above thresholds Debugdebug briefRegressed (0)
Improved (0)
Unchanged (delta < 1.0% or delta < 100.0ms) (2)
debug detailedRegressed (0)
Improved (0)
Unchanged (delta < 1.0% or delta < 100.0ms) (23)
Releaserelease briefRegressed (0)
Improved (0)
Unchanged (delta < 1.0% or delta < 100.0ms) (2)
release detailedRegressed (0)
Improved (0)
Unchanged (delta < 1.0% or delta < 100.0ms) (23)
|
Build comment file:Optimized (O)Regression (7)
Improvement (7)
No Changes (444)
Unoptimized (Onone)Regression (5)
Improvement (3)
No Changes (450)
Hardware Overview
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
stdlib change looks innocent. 👍
@swift-ci please test |
Oops, looks like I missed one 32-bit test. |
@swift-ci please test |
@swift-ci please test source compatibility |
lib/Sema/TypeCheckConstraints.cpp
Outdated
auto *parent = ExprStack.back(); | ||
if (isa<BindOptionalExpr>(parent) || isa<ForceValueExpr>(parent)) | ||
return nullptr; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This semantic change isn't described in the proposal, and I think we wouldn't deviate from it. The rule as specified in SE-0213 is a clean syntactic rule that users can reason about. This tweak would come as a surprise.
If we need it for source compatibility, perhaps it would be best to put it behind !isSwiftVersionAtLeast(5)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was just trying to avoid breaking existing code like https://github.com/apple/swift/pull/17860/files#diff-de58b3c2866a24533bc39d1bfd40fc3cR276 but maybe I shouldn't do it at all then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, this check is hidden under !isSwiftVersionAtLeast(5)
now.
return nullptr; | ||
|
||
// Don't bother to convert deprecated selector syntax. | ||
if (auto selectorTy = TC.getObjCSelectorType(DC)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the use of string literals for selectors? I wonder if we can (separately) kill that now...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right, it's #selector(...)
vs. Selector("...")
let base = U${Self}(_value) | ||
return self < (0 as ${Self}) ? ~base + 1 : base | ||
@inline(__always) | ||
get { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems unrelated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is needed because constant propagation now looks at both branches, so as a way to work around that behavior @ravikandhadai and @moiseev told me that it would be appropriate to switch from @_transparent
to @inlineable
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is, unfortunately. @_transparent
here causes the compile-time overflow on a branch that would not be taken at runtime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to clarify. The changes to how initializers are resolved, as a side-effect, makes constant propagation more precise as it can now propagate through more initializers. While in general it is a good thing, in this specific case, it resulted in a false positive due to mandatory inlining.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not write return self < (0 as ${Self}) ? ~base &+ 1 : base
? You are, after all, performing a bit twiddling operation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is very much possible (and probably reasonable) to try the &+
approach in a separate PR once this lands.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@moiseev @xwu there is one other issue with "magnitude" (besides the +) that could trigger static errors if it is made @_transparent. It is passing a potentially negative (builtin Int) into a UInt : let base = U${Self}(_value)
. This could trigger a static error on negative values like (-1).magnitude etc. So perhaps keeping it @inline is better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, _value
is the same type regardless of whether it's Int
or UInt
, and that initializer simply assigns self._value = other._value
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@xwu Ah okay, this initializer should not be a problem for constant prop. There will no static errors here. Okay we can try making + to &+
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to open follow up PR for this and run the benchmarks
Implementation is as follows: In `preCheckExpression` try to detect if there is `T(literal)` call in the AST, replace it with implicit `literal as T`, while trying to form type-checked AST, after constraint solving, restore source information and drop unnecessary coercion expression. Resolves: rdar://problem/17088188 Resolves: rdar://problem/39120081 Resolves: rdar://problem/23672697 Resolves: rdar://problem/40379985
…ons in Swift < 5 Maintain source compatibility, but only when Swift < 5, in cases when type declares conformance to literal protocol and at the same time has failable initializer with the same parameter type, see `Source compatibility` of the proposal for more details.
@swift-ci please test |
@swift-ci please test source compatibility |
Build failed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
@swift-ci please test |
Build failed |
@swift-ci please test source compatibility |
Build failed |
|
Implementation is as follows: In
preCheckExpression
try todetect if there is
T(literal)
call in the AST, replace it withimplicit
literal as T
, while trying to form type-checked AST,after constraint solving, restore source information and drop unnecessary
coercion expression.
Resolves: rdar://problem/17088188
Resolves: rdar://problem/39120081
Resolves: rdar://problem/23672697
Resolves: rdar://problem/40379985