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-1261] Swift incorrectly identifies passing a tuple to a function as a tuple splat #43869

Closed
swift-ci opened this issue Apr 18, 2016 · 12 comments
Assignees
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself type checker Area → compiler: Semantic analysis

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-1261
Radar None
Original Reporter Dave (JIRA User)
Type Bug
Status Resolved
Resolution Done

Attachment: Download

Environment

Xcode 7.3 (7D175), OS X 10.11.4, Mac Pro 2008

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, TypeChecker
Assignee @slavapestov
Priority Medium

md5: 6f10fb16a9469ba513311d1018d6e633

relates to:

  • SR-2135 Multiple Tuple Parameters to a Closure cannot be Decomposed in the Parameter List
  • SR-1297 Method parameters list interpreted as a single tuple (tuple "unsplat"), making behavior disturbing

Issue Description:

In the Swift 2.2 toolchain distributed with Xcode 7.3, the compiler incorrectly flags a function which takes one argument of a generic type as "passing 2 arguments ... as a single tuple value" when the generic type is itself a tuple. The generic type in question is bounced around as generic parameters through class inheritance, so maybe that's part of the problem

I've attached a .swift file with the code needed to generate the warning.

FWIW, Jordan Rose thinks it might be "an issue with the diagnostic".
(https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20160418/001733.html)

@belkadan
Copy link
Contributor

cc cwillmore (JIRA User), though note that Dave mentioned he'd be interested in learning about the issue and possibly taking it on himself.

@swift-ci
Copy link
Collaborator Author

Comment by David Sweeris (JIRA)

I'm quite interested, but everything I know about compilers is a vague recollection about BNF and YACC from some class I took over a decade ago, so I won't be able to fix it today or anything.

Edit: More precisely, I don't even know how long it'll be before I'd know enough to give an ETA, so I don't know if that works with how y'all schedule stuff.

@swift-ci
Copy link
Collaborator Author

swift-ci commented May 5, 2016

Comment by David Sweeris (JIRA)

I'm finally gotten a chance to dive into this a bit.

I think I know where the bug is (or at least where it’s manifesting itself), but I haven't figured out how to fix it yet. In the function `void checkTupleSplat(ApplyExpr *Call)`, in MiscDiagnostics.cpp (which starts on line 388, at least in the version I'm using), the diagnostic message is triggered when `(TT -> getNumElements() > 1)`, rather than when the # of elements passed in isn't the same as the # that's expected. I believe the preceding line (395) is intended to solve the problem by just returning early if `arg` (which is equal to `Call->getArg()->getSemanticsProvidingExpr()`) is a `TupleExpr`, `TupleShuffleExpr`, or one of a couple other non-tuple-related things. In any case, I think the root bug is that `isa<TupleExpr>(arg) || isa<TupleShuffleExpr>(arg)` is returning false when it should be returning true.

I’m currently investigating what values of x in `isa<x>(arg)` will come back as true. I’m hoping that it's something related to typealiases, because it seems that the likely problem would then be that compiler just isn’t peeling back the onion enough, so to speak, which seems like an easy fix.

@belkadan
Copy link
Contributor

belkadan commented May 5, 2016

Backslashes escape formatting characters in JIRA.

I don't think it's a typealias thing. That would affect the Type of the Expr but not the Expr itself. What's more likely is that, as a single-arg no-label argument list, it's being treated as a ParenExpr…which normally would be a tuple splat.

My guess is there's nothing currently trying to distinguish these cases: (A, B) -> R (a two-argument function) vs. X -> R where X gets substituted with (A, B) (a one-argument function). You could probably do it in an ad hoc manner by looking at the called function's type.

@swift-ci
Copy link
Collaborator Author

swift-ci commented May 5, 2016

Comment by David Sweeris (JIRA)

Yeah, `isa<ParenExpr>(Call->getArg())` returns true.

And thanks for the JIRA tip. I should probably read the manual or something :-)

@swift-ci
Copy link
Collaborator Author

swift-ci commented May 5, 2016

Comment by David Sweeris (JIRA)

Oh![]( I've found a work-around) If you put the tuple in an extra set of parens, like

class BinaryOp<A1, A2, R> : Op<((A1, A2)), R> {//class def}

then the problem goes away.

I think that means the bug is maybe in the specializer?

@swift-ci
Copy link
Collaborator Author

swift-ci commented May 5, 2016

Comment by David Sweeris (JIRA)

In the RefinedNotASplat.swift file, I duplicate some functionality between two sets of classes, one with typealiases declared as late as possible (which works as expected) and the other declaring them as early as possible (which requires the extra set of parens around the generic tuple in the inheritance clause in order to work).

I'm still trying to pin down exactly where the compiler goes wrong.

@swift-ci
Copy link
Collaborator Author

swift-ci commented May 5, 2016

Comment by David Sweeris (JIRA)

I think this might be related to the ambiguity Joe Groff noted in this message regarding SE-0066: Standardize function type argument syntax to require parentheses.
I've uploaded another file, "SE0066Connection.swift" demonstrating that adopting SE-0066's syntax helps in some cases. I can't help but wonder if this ambiguity might be the root of the issue.

@swift-ci
Copy link
Collaborator Author

Comment by David Sweeris (JIRA)

I need to amend my earlier claim that the "problem goes away" if you use an extra set of parens. The "workaround" does prevent the compiler from complaining about tuple splats, but if you try to actually compile the code in question, the compiler crashes with a segfault: 11 error

@swift-ci
Copy link
Collaborator Author

Comment by David Sweeris (JIRA)

It seems to depend on where the overloaded function is declared. I've uploaded "CompilesOK.swift" and "CrashesCompiler.swift" to illustrate the difference.

@slavapestov
Copy link
Member

Swift on master has a better implementation of SE-0110 than Swift 3, where it was completely broken.

It looks like the NotASplat and RefinedNotASplat examples now typecheck on master, but CrashesCompiler.swift still crashes. I'll take a look.

@slavapestov
Copy link
Member

... and the testcase now passes on master. I'll add it as a regression test.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
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 type checker Area → compiler: Semantic analysis
Projects
None yet
Development

No branches or pull requests

3 participants