-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[DNM][requires-evolution] Explicit varargs expansion expression #25997
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
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.
Great to see this being implemented!
lib/Sema/CSDiag.cpp
Outdated
@@ -2296,6 +2297,34 @@ bool FailureDiagnosis::diagnoseContextualConversionError( | |||
} | |||
} | |||
|
|||
// Diagnose passing '[T]' instead of a sequence of 'T' to a variadic argument | |||
// of type 'T...'. |
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 would be nice if we could implement this using the new diagnostics framework (see CSFix & CSDiagnostics), as we're currently trying to move stuff out of CSDiag.cpp.
What you'll want to do is add a new constraint fix to CSFix.h, and then add it as a viable fix within repairFailures
when the locator's last element is an ApplyArgToParam
and you're dealing with an array type being passed to a variadic param. Unfortunately I don't believe there's currently an easy way of accessing the parameter flags from repairFailures
, the simplest solution would probably be to store them on the constraint locator – see hamishknight@7e3a601 for an example of that (feel free to cherry-pick!).
Then you'll want to add a case to simplifyFixConstraint
where you try to match the array element types and record the fix if successful.
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.
@hamishknight sounds good, I'll look into doing that. Thanks for the example!
16abe55
to
edb093d
Compare
…a VarargExpansionExpr
This implementation isn't quite right yet because we're not yet checking the parameter flags to see if the param is actually variadic.
Cherry-picks hamishknight@7e3a601 with some deletions This is needed to support the ExpandArrayIntoVarargs ConstraintFix, which needs to be able to determine whether a parameter is variadic
edb093d
to
4e4a88b
Compare
This still needs some work, but if anyone with CI privileges is following along, mind starting a test run w/ the standard & validation suites? I see a lot of failures in the validation suite right now that read |
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.
Thanks for working on those changes! I just have a few minor comments, I'll leave the rest for the folks at Apple.
lib/Sema/CSSimplify.cpp
Outdated
|
||
auto elementTy = lhs->getArrayElementType(); | ||
if (elt.getKind() == ConstraintLocator::ApplyArgToParam && | ||
elementTy && elt.getParameterFlags().isVariadic()) { |
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.
You could use ConstraintSystem::isArrayType
here instead, which saves you from having to introduce isArrayDecl
& getArrayElementType
.
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.
Also you no longer need to check for elt.getKind() == ConstraintLocator::ApplyArgToParam
now, as there's an early exit for all other cases a few lines above.
ERROR(expr_varargs_expansion_expected_expr,PointsToFirstBadToken, | ||
"expected expression within '#variadic(...)'", ()) | ||
ERROR(expr_varargs_expansion_expected_rparen,PointsToFirstBadToken, | ||
"expected ')' to complete '#variadic' expression", ()) |
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.
Nit: Strings should be indented by one more character to align with expr_[...]
.
"#variadic cannot be used alongside additional variadic arguments", | ||
()) | ||
ERROR(pound_variadic_outside_arg_position,none, | ||
"#variadic can only be used in an argument position", |
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.
Same here
"remove brackets to pass array elements directly", ()) | ||
NOTE(suggest_pass_elements_using_pound_variadic,none, | ||
"wrap the expression in '#variadic(...)' to pass array elements as " | ||
"variadic arguments", ()) |
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.
And here
lib/Sema/CSSimplify.cpp
Outdated
if (elt.getKind() == ConstraintLocator::ApplyArgToParam && | ||
elementTy && elt.getParameterFlags().isVariadic()) { | ||
conversionsOrFixes.push_back(ExpandArrayIntoVarargs::create( | ||
*this, lhs, rhs, getConstraintLocator(locator))); |
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.
Nit: You can use loc
instead of getConstraintLocator(locator)
.
variadic(arrayWithOtherEltType) // expected-error {{cannot convert value of type '[String]' to expected argument type 'Int'}} | ||
variadic(1, arrayWithOtherEltType) // expected-error {{cannot convert value of type '[String]' to expected argument type 'Int'}} | ||
variadic(["hello", "world"]) // expected-error 2 {{cannot convert value of type 'String' to expected element type 'Int'}} | ||
// expected-error@-1 {{cannot pass an array of type '[Int]' as variadic arguments of type 'Int'}} |
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.
Hmm, that's unfortunate. The good news at least is that it's not a specific problem with the fix you've introduced, it's a more general problem when we have multiple contextual fixes in play. I've filed a bug to track that: https://bugs.swift.org/browse/SR-11104.
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.
Thanks for taking the time to file this!
…gs coercion - The diags and tests have not yet been updated to reflect the new syntax - The old syntax hasn't been removed yet - But, some type checking hacks the old syntax used have been removed.
…on-variadic argument
lib/Parse/ParseExpr.cpp
Outdated
parsed = new (Context) CoerceExpr(asLoc, type.get()); | ||
bool includesVarargExpansion = false; | ||
auto typeRepr = type.get(); | ||
if (Tok.isEllipsis()) { |
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.
You'll want to keep the Tok.is(tok::oper_postfix)
check here to make sure we reject things like:
func foo(_ x: Int...) {}
foo([0] as Int ...)
In addition, it'll allow us to continue accepting the following:
let r = 0 as Int8...5
which calls the infix ...
operator.
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.
🤦♂ Good catch, thanks. Going to work on adding some more parsing tests
…maintain source compatibility with the infix ... operattor
…or vararg expansion
Closing this since it's pretty hopelessly out of date and the diagnostics improvements have landed elsewhere. |
This is a WIP prototype of a new expression, #variadic, which can be used to pass array elements as variadic arguments. I should have a post with the corresponding proposal pitch up on the forums shortly.
This isn’t meant to be a finalized implementation, just enough to demo the pitched feature and collect feedback. It’s been working well for me so far and passing tests, but still needs: