Skip to content

[Sema] Requestify default argument type checking #27756

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 4 commits into from
Nov 14, 2019

Conversation

hamishknight
Copy link
Contributor

@hamishknight hamishknight commented Oct 17, 2019

This PR introduces two new requests, one to compute initializer contexts for default arguments, and another to type-check default arguments within this context.

This PR then splits getDefaultValue into 2 accessors:

  • getStructuralDefaultExpr which retrieves the potentially un-type-checked default argument expression.

  • getTypeCheckedDefaultExpr which retrieves a fully type-checked default argument expression.

And also adds hasDefaultExpr, which allows checking for the presence of a default expr without kicking off a request.

On its own, this isn't enough to resolve SR-11085, I'm going to tackle that in a follow-up to keep the size of this PR down.

@hamishknight
Copy link
Contributor Author

@swift-ci please test

@CodaFi
Copy link
Contributor

CodaFi commented Oct 17, 2019

A high level comment: Why do we need to keep around a trichotomy of "parsed/typechecked/unchecked" if all of the callers before don't really care about the distinction between parsed and typechecked? I think you can get away with "definitely typechecked" and "potentially typechecked - no requests".

@hamishknight
Copy link
Contributor Author

@CodaFi My understanding was that we were aiming to eventually get rid of that mutable state within the AST, so the result of getParsedDefaultExpr doesn't change if we happen to trigger the type-checking of the default.

@CodaFi
Copy link
Contributor

CodaFi commented Oct 17, 2019

I guess I'm wondering what's stopping us from doing it now?

@hamishknight
Copy link
Contributor Author

@CodaFi From removing the mutable state? Things like the AST walker currently still need to set it (until it is changed to return a new AST), and as I understand it, it's currently more efficient to access the state from the AST than the evaluator's cache.

@hamishknight hamishknight force-pushed the carpe-default branch 2 times, most recently from 262d08a to c5a65eb Compare October 22, 2019 22:31
@hamishknight
Copy link
Contributor Author

Ping @slavapestov

@hamishknight hamishknight force-pushed the carpe-default branch 3 times, most recently from 6bc4abd to e3a53ce Compare November 6, 2019 00:48
@hamishknight
Copy link
Contributor Author

@swift-ci please test

@swift-ci
Copy link
Contributor

swift-ci commented Nov 6, 2019

Build failed
Swift Test OS X Platform
Git Sha - e3a53cebe5265999f7157c9757ca74c4e3764bbc

@hamishknight hamishknight force-pushed the carpe-default branch 2 times, most recently from d68d9c6 to c28bbd7 Compare November 6, 2019 15:59
@slavapestov
Copy link
Contributor

Sorry, I’ll review this today.

@@ -5208,7 +5211,8 @@ class ParamDecl : public VarDecl {
TypeRepr *TyRepr = nullptr;

struct StoredDefaultArgument {
PointerUnion<Expr *, VarDecl *> DefaultArg;
PointerUnion<Expr *, VarDecl *> ParsedExprOrVar;
Optional<Expr *> TypeCheckedExpr;
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure it makes sense to split these up currently. Type checking an expression mutates it, destroying the original value.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@slavapestov Ah right, I guess in that case we should just expose something like getStructuralDefaultExpr and getTypeCheckedDefaultExpr where the former returns either an un-type-checked or a type-checked expr?

@@ -1744,6 +1744,47 @@ class ValueWitnessRequest
void cacheResult(Witness value) const;
};

/// Computes initializer contexts for each of the parameters with default
/// arguments within a parameter list.
class DefaultArgumentInitContextsRequest
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it really worth making this a request? It looks like a request that's run for its side effects, which is something we would like to avoid having. Maybe it should at least be per-ParamDecl and not per-ParameterList?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@slavapestov The reasoning for putting at the level of ParameterList is to allow us to access the parameter index when creating the contexts. We could make it per-ParamDecl, but then we'd need to iterate over the parameter list for each param to find its own index. Either that or start storing the index on ParamDecl. 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.

@slavapestov On second thought, we can totally make this per-ParamDecl, we can just cache the other parameter's init contexts while we iterate. Does the updated code look good?

@hamishknight
Copy link
Contributor Author

@swift-ci please test

@CodaFi
Copy link
Contributor

CodaFi commented Nov 11, 2019

Sorry in advance @hamishknight, #28179 is gonna cause a bunch of merge conflicts here.

@hamishknight
Copy link
Contributor Author

@CodaFi No worries, it's worth it :)

This commit adds a request that computes
the initializer context for a parameter with a
default expr or stored property default.

This avoids having to compute them for synthesized
decls and is a step towards requestifying default
argument parsing.
This commit introduces a request to type-check a
default argument expression and splits
`getDefaultValue` into 2 accessors:

- `getStructuralDefaultExpr` which retrieves the
potentially un-type-checked default argument
expression.

- `getTypeCheckedDefaultExpr` which retrieves a
fully type-checked default argument expression.

In addition, this commit adds `hasDefaultExpr`,
which allows checking for a default expr without
kicking off a request.
@hamishknight
Copy link
Contributor Author

@swift-ci please smoke test

@hamishknight
Copy link
Contributor Author

@swift-ci please smoke test Linux platform

lib/AST/Decl.cpp Outdated
@@ -6046,15 +6046,79 @@ AnyFunctionType::Param ParamDecl::toFunctionParam(Type type) const {
return AnyFunctionType::Param(type, label, flags);
}

void ParamDecl::setDefaultValue(Expr *E) {
Initializer *ParamDecl::getDefaultArgumentInitContextCached() const {
Copy link
Contributor

Choose a reason for hiding this comment

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

This could return an Optional<> I think. Also typically we name these methods "getCached...()"

Rename getDefaultArgumentInitContextCached,
and have it return an Optional<Initializer *>.
@hamishknight
Copy link
Contributor Author

@swift-ci please smoke test

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.

4 participants