mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[AST] Add a enum for type checking state of ClosureExpr's body
This commit is contained in:
@@ -3759,7 +3759,25 @@ public:
|
|||||||
/// { [weak c] (a : Int) -> Int in a + c!.getFoo() }
|
/// { [weak c] (a : Int) -> Int in a + c!.getFoo() }
|
||||||
/// \endcode
|
/// \endcode
|
||||||
class ClosureExpr : public AbstractClosureExpr {
|
class ClosureExpr : public AbstractClosureExpr {
|
||||||
|
public:
|
||||||
|
enum class BodyState {
|
||||||
|
/// The body was parsed, but not ready for type checking because
|
||||||
|
/// the closure parameters haven't been type checked.
|
||||||
|
Parsed,
|
||||||
|
|
||||||
|
/// The type of the closure itself was type checked. But the body has not
|
||||||
|
/// been type checked yet.
|
||||||
|
ReadyForTypeChecking,
|
||||||
|
|
||||||
|
/// The body was typechecked with the enclosing closure.
|
||||||
|
/// i.e. single expression closure or function builder closure.
|
||||||
|
TypeCheckedAtOnce,
|
||||||
|
|
||||||
|
/// The body was type checked separately from the enclosing closure.
|
||||||
|
SeparatelyTypeChecked,
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
/// The range of the brackets of the capture list, if present.
|
/// The range of the brackets of the capture list, if present.
|
||||||
SourceRange BracketRange;
|
SourceRange BracketRange;
|
||||||
|
|
||||||
@@ -3783,8 +3801,7 @@ class ClosureExpr : public AbstractClosureExpr {
|
|||||||
SourceLoc InLoc;
|
SourceLoc InLoc;
|
||||||
|
|
||||||
/// The explicitly-specified result type.
|
/// The explicitly-specified result type.
|
||||||
llvm::PointerIntPair<TypeExpr *, 1, bool>
|
llvm::PointerIntPair<TypeExpr *, 2, BodyState> ExplicitResultTypeAndBodyState;
|
||||||
ExplicitResultTypeAndSeparatelyChecked;
|
|
||||||
|
|
||||||
/// The body of the closure, along with a bit indicating whether it
|
/// The body of the closure, along with a bit indicating whether it
|
||||||
/// was originally just a single expression.
|
/// was originally just a single expression.
|
||||||
@@ -3799,7 +3816,7 @@ public:
|
|||||||
BracketRange(bracketRange),
|
BracketRange(bracketRange),
|
||||||
CapturedSelfDecl(capturedSelfDecl),
|
CapturedSelfDecl(capturedSelfDecl),
|
||||||
ThrowsLoc(throwsLoc), ArrowLoc(arrowLoc), InLoc(inLoc),
|
ThrowsLoc(throwsLoc), ArrowLoc(arrowLoc), InLoc(inLoc),
|
||||||
ExplicitResultTypeAndSeparatelyChecked(explicitResultType, false),
|
ExplicitResultTypeAndBodyState(explicitResultType, BodyState::Parsed),
|
||||||
Body(nullptr) {
|
Body(nullptr) {
|
||||||
setParameterList(params);
|
setParameterList(params);
|
||||||
Bits.ClosureExpr.HasAnonymousClosureVars = false;
|
Bits.ClosureExpr.HasAnonymousClosureVars = false;
|
||||||
@@ -3854,15 +3871,13 @@ public:
|
|||||||
|
|
||||||
Type getExplicitResultType() const {
|
Type getExplicitResultType() const {
|
||||||
assert(hasExplicitResultType() && "No explicit result type");
|
assert(hasExplicitResultType() && "No explicit result type");
|
||||||
return ExplicitResultTypeAndSeparatelyChecked.getPointer()
|
return ExplicitResultTypeAndBodyState.getPointer()->getInstanceType();
|
||||||
->getInstanceType();
|
|
||||||
}
|
}
|
||||||
void setExplicitResultType(Type ty);
|
void setExplicitResultType(Type ty);
|
||||||
|
|
||||||
TypeRepr *getExplicitResultTypeRepr() const {
|
TypeRepr *getExplicitResultTypeRepr() const {
|
||||||
assert(hasExplicitResultType() && "No explicit result type");
|
assert(hasExplicitResultType() && "No explicit result type");
|
||||||
return ExplicitResultTypeAndSeparatelyChecked.getPointer()
|
return ExplicitResultTypeAndBodyState.getPointer()->getTypeRepr();
|
||||||
->getTypeRepr();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determine whether the closure has a single expression for its
|
/// Determine whether the closure has a single expression for its
|
||||||
@@ -3904,14 +3919,20 @@ public:
|
|||||||
/// captured non-weakly).
|
/// captured non-weakly).
|
||||||
bool capturesSelfEnablingImplictSelf() const;
|
bool capturesSelfEnablingImplictSelf() const;
|
||||||
|
|
||||||
/// Whether this closure's body was type checked separately from its
|
|
||||||
/// enclosing expression.
|
/// Get the type checking state of this closure's body.
|
||||||
bool wasSeparatelyTypeChecked() const {
|
BodyState getBodyState() const {
|
||||||
return ExplicitResultTypeAndSeparatelyChecked.getInt();
|
return ExplicitResultTypeAndBodyState.getInt();
|
||||||
|
}
|
||||||
|
void setBodyState(BodyState v) {
|
||||||
|
ExplicitResultTypeAndBodyState.setInt(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSeparatelyTypeChecked(bool flag = true) {
|
/// Whether this closure's body is/was type checked separately from its
|
||||||
ExplicitResultTypeAndSeparatelyChecked.setInt(flag);
|
/// enclosing expression.
|
||||||
|
bool isSeparatelyTypeChecked() const {
|
||||||
|
return getBodyState() == BodyState::SeparatelyTypeChecked ||
|
||||||
|
getBodyState() == BodyState::ReadyForTypeChecking;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool classof(const Expr *E) {
|
static bool classof(const Expr *E) {
|
||||||
|
|||||||
@@ -825,7 +825,7 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
|
|||||||
|
|
||||||
// If the closure was separately type checked and we don't want to
|
// If the closure was separately type checked and we don't want to
|
||||||
// visit separately-checked closure bodies, bail out now.
|
// visit separately-checked closure bodies, bail out now.
|
||||||
if (expr->wasSeparatelyTypeChecked() &&
|
if (expr->isSeparatelyTypeChecked() &&
|
||||||
!Walker.shouldWalkIntoSeparatelyCheckedClosure(expr))
|
!Walker.shouldWalkIntoSeparatelyCheckedClosure(expr))
|
||||||
return expr;
|
return expr;
|
||||||
|
|
||||||
|
|||||||
@@ -1975,7 +1975,7 @@ bool ClosureExpr::capturesSelfEnablingImplictSelf() const {
|
|||||||
|
|
||||||
void ClosureExpr::setExplicitResultType(Type ty) {
|
void ClosureExpr::setExplicitResultType(Type ty) {
|
||||||
assert(ty && !ty->hasTypeVariable());
|
assert(ty && !ty->hasTypeVariable());
|
||||||
ExplicitResultTypeAndSeparatelyChecked.getPointer()
|
ExplicitResultTypeAndBodyState.getPointer()
|
||||||
->setType(MetatypeType::get(ty));
|
->setType(MetatypeType::get(ty));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -345,11 +345,13 @@ SolutionApplicationToFunctionResult ConstraintSystem::applySolution(
|
|||||||
ClosureConstraintApplication application(
|
ClosureConstraintApplication application(
|
||||||
solution, closure, closureFnType->getResult(), rewriteTarget);
|
solution, closure, closureFnType->getResult(), rewriteTarget);
|
||||||
application.visit(fn.getBody());
|
application.visit(fn.getBody());
|
||||||
|
closure->setBodyState(ClosureExpr::BodyState::TypeCheckedAtOnce);
|
||||||
|
|
||||||
return SolutionApplicationToFunctionResult::Success;
|
return SolutionApplicationToFunctionResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, we need to delay type checking of the closure until later.
|
// Otherwise, we need to delay type checking of the closure until later.
|
||||||
solution.setExprTypes(closure);
|
solution.setExprTypes(closure);
|
||||||
|
closure->setBodyState(ClosureExpr::BodyState::ReadyForTypeChecking);
|
||||||
return SolutionApplicationToFunctionResult::Delay;
|
return SolutionApplicationToFunctionResult::Delay;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
|
|||||||
|
|
||||||
bool walkToDeclPre(Decl *D) override {
|
bool walkToDeclPre(Decl *D) override {
|
||||||
if (auto *closure = dyn_cast<ClosureExpr>(D->getDeclContext()))
|
if (auto *closure = dyn_cast<ClosureExpr>(D->getDeclContext()))
|
||||||
return !closure->wasSeparatelyTypeChecked();
|
return !closure->isSeparatelyTypeChecked();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1497,7 +1497,7 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
|
|||||||
// Don't walk into nested decls.
|
// Don't walk into nested decls.
|
||||||
bool walkToDeclPre(Decl *D) override {
|
bool walkToDeclPre(Decl *D) override {
|
||||||
if (auto *closure = dyn_cast<ClosureExpr>(D->getDeclContext()))
|
if (auto *closure = dyn_cast<ClosureExpr>(D->getDeclContext()))
|
||||||
return !closure->wasSeparatelyTypeChecked();
|
return !closure->isSeparatelyTypeChecked();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1136,7 +1136,7 @@ static void findAvailabilityFixItNodes(SourceRange ReferenceRange,
|
|||||||
if (Expr *ParentExpr = Parent.getAsExpr()) {
|
if (Expr *ParentExpr = Parent.getAsExpr()) {
|
||||||
auto *ParentClosure = dyn_cast<ClosureExpr>(ParentExpr);
|
auto *ParentClosure = dyn_cast<ClosureExpr>(ParentExpr);
|
||||||
if (!ParentClosure ||
|
if (!ParentClosure ||
|
||||||
ParentClosure->wasSeparatelyTypeChecked()) {
|
ParentClosure->isSeparatelyTypeChecked()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (auto *ParentStmt = Parent.getAsStmt()) {
|
} else if (auto *ParentStmt = Parent.getAsStmt()) {
|
||||||
|
|||||||
@@ -2008,7 +2008,7 @@ public:
|
|||||||
performSyntacticExprDiagnostics(expr, dcStack.back(), /*isExprStmt=*/false);
|
performSyntacticExprDiagnostics(expr, dcStack.back(), /*isExprStmt=*/false);
|
||||||
|
|
||||||
if (auto closure = dyn_cast<ClosureExpr>(expr)) {
|
if (auto closure = dyn_cast<ClosureExpr>(expr)) {
|
||||||
if (closure->wasSeparatelyTypeChecked()) {
|
if (closure->isSeparatelyTypeChecked()) {
|
||||||
dcStack.push_back(closure);
|
dcStack.push_back(closure);
|
||||||
return {true, expr};
|
return {true, expr};
|
||||||
}
|
}
|
||||||
@@ -2019,7 +2019,7 @@ public:
|
|||||||
|
|
||||||
Expr *walkToExprPost(Expr *expr) override {
|
Expr *walkToExprPost(Expr *expr) override {
|
||||||
if (auto closure = dyn_cast<ClosureExpr>(expr)) {
|
if (auto closure = dyn_cast<ClosureExpr>(expr)) {
|
||||||
if (closure->wasSeparatelyTypeChecked()) {
|
if (closure->isSeparatelyTypeChecked()) {
|
||||||
assert(dcStack.back() == closure);
|
assert(dcStack.back() == closure);
|
||||||
dcStack.pop_back();
|
dcStack.pop_back();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ namespace {
|
|||||||
// If the closure was type checked within its enclosing context,
|
// If the closure was type checked within its enclosing context,
|
||||||
// we need to walk into it with a new sequence.
|
// we need to walk into it with a new sequence.
|
||||||
// Otherwise, it'll have been separately type-checked.
|
// Otherwise, it'll have been separately type-checked.
|
||||||
if (!CE->wasSeparatelyTypeChecked())
|
if (!CE->isSeparatelyTypeChecked())
|
||||||
CE->getBody()->walk(ContextualizeClosures(CE));
|
CE->getBody()->walk(ContextualizeClosures(CE));
|
||||||
|
|
||||||
TypeChecker::computeCaptures(CE);
|
TypeChecker::computeCaptures(CE);
|
||||||
@@ -1976,7 +1976,7 @@ bool TypeChecker::typeCheckClosureBody(ClosureExpr *closure) {
|
|||||||
if (body) {
|
if (body) {
|
||||||
closure->setBody(body, closure->hasSingleExpressionBody());
|
closure->setBody(body, closure->hasSingleExpressionBody());
|
||||||
}
|
}
|
||||||
closure->setSeparatelyTypeChecked();
|
closure->setBodyState(ClosureExpr::BodyState::SeparatelyTypeChecked);
|
||||||
return HadError;
|
return HadError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user