Skip to content

[AST] Introduce ArgumentList #38836

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

Merged
merged 14 commits into from
Sep 4, 2021
Merged

Conversation

hamishknight
Copy link
Contributor

Introduce the ArgumentList type, which represents a set of call arguments for a function or subscript. This supersedes the use of tuple and paren exprs as argument lists, a relic from when tuple splatting was a language feature.

For now, paren and tuple types retain their ParameterTypeFlags, as both the constraint system and a small amount of diagnostic logic is still relying on converting argument lists into tuple or paren types, this will be removed in a follow-up. This then sets the stage for the removal of InOutExpr and InOutType.

I've split the commits up based on the part of the compiler they touch, please feel free to review the bits of the compiler you're most familiar with.

@hamishknight
Copy link
Contributor Author

@nathawes Mind taking a look at the changes specifically in Formatting.cpp?

@slavapestov
Copy link
Contributor

Nice work!

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.

Taken a few passes over this and I haven't seen anything so far. Sema, AST, Parse, and SIL changes all LGTM. CS LGTM but would prefer @hborla and @xedin give their rubber stamp there.

Copy link
Contributor

@nathawes nathawes left a comment

Choose a reason for hiding this comment

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

The Formatting.cpp changes LGTM. It's so great this is finally happening – thanks a lot!

@swift-ci

This comment has been minimized.

Copy link
Contributor

@xedin xedin left a comment

Choose a reason for hiding this comment

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

Looks great! I have left a small comment about ArgumentLists that could be addressed separately.

/// that locator.
llvm::DenseMap<ConstraintLocator *, ArgumentInfo> ArgumentInfos;
/// constructions) to the argument lists for the call to that locator.
llvm::DenseMap<ConstraintLocator *, ArgumentList *> ArgumentLists;
Copy link
Contributor

Choose a reason for hiding this comment

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

While we are at it I think we need to do change this to behave like addNodeTypes and record ArgumentLists in the solution as well. Since constraint generation for result builders happens during solving this list would effectively get rewritten multiple times with the out-of-scope ArgumentList objects just to keep them around until constraint system lifetime ends.

return getAsExpr(simplifyLocatorToAnchor(argListLoc));
ArgumentList *
FailureDiagnostic::getArgumentListFor(ConstraintLocator *locator) const {
return getConstraintSystem().getArgumentList(locator);
Copy link
Contributor

Choose a reason for hiding this comment

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

See my comment about ArgumentLists - It'd be great if we could extract this information for Solution instead because we can't reply on constraint system having solution applied always e.g. ambiguity cases.

Copy link
Contributor

@bnbarham bnbarham left a comment

Choose a reason for hiding this comment

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

Awesome 😍! The refactoring changes look good to me (two comments but it's fine as is).

@swift-ci

This comment has been minimized.

@hamishknight
Copy link
Contributor Author

Compiler performance numbers are just noise, Jenkins is sporadically crashing during some of the source compat suite runs. Previous performance runs didn't show any meaningful differences though, only a slim decrease in AST memory allocation.

Copy link
Contributor

@benlangmuir benlangmuir left a comment

Choose a reason for hiding this comment

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

🎉 lib/Index, lib/IDE, ASTWalker, and SourceKit all LGTM. I made one suggestion in SyntaxModel, but it doesn't need to block the PR, I think. I love how much horrible code this removed.

Copy link
Member

@rintaro rintaro left a comment

Choose a reason for hiding this comment

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

lib/Parse, lib/IDE, SourceKit changes LGTM!

lpLoc, yieldElts, rpLoc, SyntaxKind::ExprList);
for (auto &elt : yieldElts) {
assert(elt.Label.empty());
assert(elt.LabelLoc.isInvalid());
Copy link
Member

@rintaro rintaro Aug 13, 2021

Choose a reason for hiding this comment

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

(Unrelated to this PR)
Hmm, I just noticed the following code hits these assertion even with current main.

struct S {
  var property: String {
    _read {
      yield(x: "test")
    }
  }
}

Instead of skipping parsing labels in parseExprList(), we probably should diagnose parsed labels here. Or, we should not use parseExprList. (Filed https://bugs.swift.org/browse/SR-15066)

Copy link
Contributor Author

@hamishknight hamishknight Aug 16, 2021

Choose a reason for hiding this comment

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

Good catch! Looks like the logic in parseExprList is trying to handle this case, but isn't working as SyntaxKind::ExprList is being passed (though looking at the git history, this seems to have been changed to fix the syntax tree). I can take a look at this in a follow-up.

@hamishknight
Copy link
Contributor Author

Stress tester run uncovered a nasty bug in the ASTWalker logic, now fixed

Copy link
Contributor

@beccadax beccadax left a comment

Choose a reason for hiding this comment

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

This is going to be great! I've only looked at ArgumentList.h so far, but here are some initial thoughts. Sorry if you've already addressed some of this previously.

/// Note that in type-checked AST, this may return \c true for an index of a
/// variadic expansion which contains a trailing closure (and it may not
/// necessarily be the first argument of the expansion).
bool isRawTrailingClosureIndex(unsigned i) const {
Copy link
Contributor

Choose a reason for hiding this comment

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

isTrailingClosureArgument()?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm, I think calling out the fact that it's a "raw" index is important, as it's not what you may expect in type-checked AST, in particular it might return true for default arguments or arguments that have been re-ordered after the trailing closure.

Alternatively we may just want to completely ban calling this on a type-checked argument list, what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

With the original arguments update this becomes isTrailingClosureIndex. Personally I prefer that over isTrailingClosureArgument, as that sounds like it would expect an Argument parameter, but I'm happy to change it over

Introduce the ArgumentList type, which represents
a set of call arguments for a function or
subscript. This will supersede the use of tuple
and paren exprs as argument lists.
Switch out the representation of argument lists
in various AST nodes with ArgumentList.
Split up the expr list parsing members such that
there are separate entry points for tuple and
argument list parsing, and start using the argument
list parsing member for call and subscripts.
With the removal of TupleExpr and ParenExpr argument
lists, it's no longer sufficient to check whether
a given parent expr has a possible chain sub-expr,
as it might be a child that's unrelated to the chain
under consideration. For example, for a chain that's
an argument to a function call, we don't want to
walk up and consider the call expr to be an extension
of the chain just because it has a function expr.

Tighten up the check by comparing whether the given
sub-expr of a possible chain parent matches the
current expr in the chain.
- Explicitly limit favoring logic to only handle
unary args, this seems to have always been the
case, but needs to be handled explicitly now that
argument lists aren't exprs
- Update the ConstraintLocator simplification to
handle argument lists
- Store a mapping of locators to argument lists
in the constraint system
- Abstract more logic into a getArgumentLocator
method which retrieves an argument-to-param locator
from an argument anchor expr
Most of this should be fairly mechanical, the
changes in PlaygroundTransform are a little more
involved though.
Track the depth and clear out the map when it
reaches 0 to save memory.
We were accidentally continuing to walk the old
argument list even if the caller had returned a
new one.
- Remove OriginalArguments in favor of storing the
pre-rewritten argument list, which simplifies things
nicely
- Adopt llvm::indexed_accessor_iterator
@hamishknight
Copy link
Contributor Author

@ahoppen Mind taking a look at a1f127f?

@hamishknight
Copy link
Contributor Author

@swift-ci please test

@hamishknight
Copy link
Contributor Author

@swift-ci please test source compatibility

@hamishknight
Copy link
Contributor Author

@swift-ci please test compiler performance

@hamishknight
Copy link
Contributor Author

@swift-ci please SourceKit stress test

@hamishknight
Copy link
Contributor Author

Stress tester result is a UPASS:

05:31:20 SourceKit Stress Tester summary:
05:31:20   failed underlying source compatibility build
05:31:20       > treat this as a source compatibility failure
05:31:20   4 XFails not processed
05:31:20   0 unexpected stress tester failures
05:31:20   135 expected stress tester failures tracked by 17 issues

The source compat failures are already known

Copy link
Member

@ahoppen ahoppen left a comment

Choose a reason for hiding this comment

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

a1f127f LGTM.

@swift-ci

This comment has been minimized.

@hamishknight
Copy link
Contributor Author

🚢

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.