Skip to content

Commit 01c4df8

Browse files
committed
[CodeCompletion] Propagate "skipping body" flag per request basis
Instead of using a global type checker flag.
1 parent e2b3114 commit 01c4df8

12 files changed

+66
-48
lines changed

include/swift/Basic/LangOptions.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -508,9 +508,6 @@ namespace swift {
508508
/// function bodies.
509509
bool SkipNonInlinableFunctionBodies = false;
510510

511-
/// Single statement (ASTNode) type checking mode for IDE tooling.
512-
bool TypeCheckSingleASTNode = false;
513-
514511
///
515512
/// Flags for developers
516513
///

lib/IDE/CompletionInstance.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -520,9 +520,6 @@ bool CompletionInstance::performNewOperation(
520520

521521
Invocation.setCodeCompletionPoint(completionBuffer, Offset);
522522

523-
// Enable single ASTNode type checking mode.
524-
Invocation.getTypeCheckerOptions().TypeCheckSingleASTNode = true;
525-
526523
if (CI.setup(Invocation)) {
527524
Error = "failed to setup compiler instance";
528525
return false;

lib/Sema/CSApply.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4133,6 +4133,10 @@ namespace {
41334133
// If we end up here, we should have diagnosed somewhere else
41344134
// already.
41354135
Expr *simplified = simplifyExprType(expr);
4136+
// Invalidate 'VarDecl's inside the pattern.
4137+
expr->getSubPattern()->forEachVariable([](VarDecl *VD) {
4138+
VD->setInvalid();
4139+
});
41364140
if (!SuppressDiagnostics
41374141
&& !cs.getType(simplified)->is<UnresolvedType>()) {
41384142
auto &de = cs.getASTContext().Diags;
@@ -8271,7 +8275,7 @@ Optional<SolutionApplicationTarget> ConstraintSystem::applySolution(
82718275
if (!resultTarget)
82728276
return None;
82738277

8274-
if (!getASTContext().TypeCheckerOpts.TypeCheckSingleASTNode) {
8278+
if (!Options.contains(ConstraintSystemFlags::LeaveClosureBodyUnchecked)) {
82758279
bool hadError = false;
82768280

82778281
// Visit closures that have non-single expression bodies.

lib/Sema/ConstraintSystem.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,6 +1225,10 @@ enum class ConstraintSystemFlags {
12251225
/// for a pre-configured set of expressions on line numbers by setting
12261226
/// \c DebugConstraintSolverOnLines.
12271227
DebugConstraints = 0x10,
1228+
1229+
/// Don't try to type check closure bodies, and leave them unchecked. This is
1230+
/// used for source tooling functionalities.
1231+
LeaveClosureBodyUnchecked = 0x20,
12281232
};
12291233

12301234
/// Options that affect the constraint system as a whole.

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2120,6 +2120,9 @@ TypeChecker::typeCheckExpression(
21202120
if (options.contains(TypeCheckExprFlags::AllowUnresolvedTypeVariables))
21212121
csOptions |= ConstraintSystemFlags::AllowUnresolvedTypeVariables;
21222122

2123+
if (options.contains(TypeCheckExprFlags::LeaveClosureBodyUnchecked))
2124+
csOptions |= ConstraintSystemFlags::LeaveClosureBodyUnchecked;
2125+
21232126
ConstraintSystem cs(dc, csOptions);
21242127

21252128
// Tell the constraint system what the contextual type is. This informs

lib/Sema/TypeCheckDecl.cpp

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2239,12 +2239,8 @@ InterfaceTypeRequest::evaluate(Evaluator &eval, ValueDecl *D) const {
22392239
}
22402240

22412241
// Try type checking the closure if it hasn't.
2242-
// NOTE: Do this only in 'TypeCheckSingleASTNode' mode. Otherwise, the
2243-
// parent closure should have been type checked before.
2244-
if (Context.TypeCheckerOpts.TypeCheckSingleASTNode &&
2245-
isa<ClosureExpr>(PD->getDeclContext())) {
2246-
auto *closure = cast<ClosureExpr>(PD->getDeclContext());
2247-
if (!closure->getType()) {
2242+
if (auto *closure = dyn_cast<ClosureExpr>(PD->getDeclContext())) {
2243+
if (!closure->getType() && !closure->hasSingleExpressionBody()) {
22482244
swift::typeCheckASTNodeAtLoc(closure->getParent(), closure->getLoc());
22492245
if (PD->hasInterfaceType())
22502246
return PD->getInterfaceType();
@@ -2259,10 +2255,10 @@ InterfaceTypeRequest::evaluate(Evaluator &eval, ValueDecl *D) const {
22592255
auto *VD = cast<VarDecl>(D);
22602256
Type interfaceType;
22612257
if (auto *parentE = VD->getParentExpr()) {
2262-
if (Context.TypeCheckerOpts.TypeCheckSingleASTNode &&
2263-
!parentE->getType()) {
2258+
// Type check the ASTNode that contains the parent 'TapExpr' if it
2259+
// hasn't.
2260+
if (!parentE->getType())
22642261
swift::typeCheckASTNodeAtLoc(VD->getDeclContext(), parentE->getLoc());
2265-
}
22662262
interfaceType = parentE->getType();
22672263
} else if (auto *namingPattern = VD->getNamingPattern()) {
22682264
interfaceType = namingPattern->getType();
@@ -2425,16 +2421,14 @@ NamingPatternRequest::evaluate(Evaluator &evaluator, VarDecl *VD) const {
24252421
namingPattern = canVD->NamingPattern;
24262422
}
24272423

2428-
if (!namingPattern &&
2429-
VD->getASTContext().TypeCheckerOpts.TypeCheckSingleASTNode) {
2424+
if (!namingPattern) {
24302425
// Try type checking parent control statement.
2431-
// NOTE: Do this only in 'TypeCheckSingleASTNode' mode. Otherwise, the
2432-
// parent control statement should have been type checked before.
24332426
if (auto parentStmt = VD->getParentPatternStmt()) {
24342427
if (auto CS = dyn_cast<CaseStmt>(parentStmt))
24352428
parentStmt = CS->getParentStmt();
24362429
ASTNode node(parentStmt);
2437-
TypeChecker::typeCheckASTNode(node, VD->getDeclContext());
2430+
TypeChecker::typeCheckASTNode(node, VD->getDeclContext(),
2431+
/*LeaveBodyUnchecked=*/true);
24382432
namingPattern = VD->getCanonicalVarDecl()->NamingPattern;
24392433
}
24402434
}

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,6 +1279,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
12791279
public:
12801280
ASTContext &Ctx;
12811281
SourceFile *SF;
1282+
bool LeaveFunctionBodyUnchecked;
12821283

12831284
explicit DeclChecker(ASTContext &ctx, SourceFile *SF) : Ctx(ctx), SF(SF) {}
12841285

@@ -2243,7 +2244,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
22432244
}
22442245
}
22452246

2246-
if (getASTContext().TypeCheckerOpts.TypeCheckSingleASTNode) {
2247+
if (LeaveFunctionBodyUnchecked) {
22472248
// DO nothing.
22482249
} else if (requiresDefinition(FD) && !FD->hasBody()) {
22492250
// Complain if we should have a body.
@@ -2578,7 +2579,9 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
25782579

25792580
checkAccessControl(CD);
25802581

2581-
if (requiresDefinition(CD) && !CD->hasBody()) {
2582+
if (LeaveFunctionBodyUnchecked) {
2583+
// Do nothing.
2584+
} else if (requiresDefinition(CD) && !CD->hasBody()) {
25822585
// Complain if we should have a body.
25832586
CD->diagnose(diag::missing_initializer_def);
25842587
} else if (CD->getDeclContext()->isLocalContext()) {
@@ -2596,8 +2599,8 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
25962599
void visitDestructorDecl(DestructorDecl *DD) {
25972600
TypeChecker::checkDeclAttributes(DD);
25982601

2599-
if (getASTContext().TypeCheckerOpts.TypeCheckSingleASTNode) {
2600-
// DO nothing.
2602+
if (LeaveFunctionBodyUnchecked) {
2603+
// Do nothing.
26012604
} else if (DD->getDeclContext()->isLocalContext()) {
26022605
// Check local function bodies right away.
26032606
TypeChecker::typeCheckAbstractFunctionBody(DD);
@@ -2610,7 +2613,9 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
26102613
};
26112614
} // end anonymous namespace
26122615

2613-
void TypeChecker::typeCheckDecl(Decl *D) {
2616+
void TypeChecker::typeCheckDecl(Decl *D, bool LeaveBodyUnchecked) {
26142617
auto *SF = D->getDeclContext()->getParentSourceFile();
2615-
DeclChecker(D->getASTContext(), SF).visit(D);
2618+
DeclChecker declChecker(D->getASTContext(), SF);
2619+
declChecker.LeaveFunctionBodyUnchecked = LeaveBodyUnchecked;
2620+
declChecker.visit(D);
26162621
}

lib/Sema/TypeCheckPattern.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,6 +1319,9 @@ Pattern *TypeChecker::coercePatternToType(ContextualPattern pattern,
13191319
diags.diagnose(IP->getLoc(),
13201320
diag::isa_collection_downcast_pattern_value_unimplemented,
13211321
IP->getCastType());
1322+
IP->setType(ErrorType::get(Context));
1323+
if (Pattern *sub = IP->getSubPattern())
1324+
sub->forEachVariable([](VarDecl *VD) { VD->setInvalid(); });
13221325
return P;
13231326
}
13241327

lib/Sema/TypeCheckStmt.cpp

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,10 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
322322
/// Used to distinguish the first BraceStmt that starts a TopLevelCodeDecl.
323323
bool IsBraceStmtFromTopLevelDecl;
324324

325+
/// Skip type checking any elements inside 'BraceStmt', also this is
326+
/// propagated to DeclChecker and ConstraintSystem.
327+
bool LeaveBraceStmtBodyUnchecked = false;
328+
325329
ASTContext &getASTContext() const { return Ctx; };
326330

327331
struct AddLabeledStmt {
@@ -428,13 +432,9 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
428432
}
429433

430434
// Try type checking the closure if it hasn't.
431-
// NOTE: Do this only in 'TypeCheckSingleASTNode' mode. Otherwise, the
432-
// parent closure should have been type checked before.
433-
if (getASTContext().TypeCheckerOpts.TypeCheckSingleASTNode) {
434-
if (auto *closure = TheFunc->getAbstractClosureExpr()) {
435-
if (!closure->getType())
436-
swift::typeCheckASTNodeAtLoc(closure->getParent(), closure->getLoc());
437-
}
435+
if (auto *closure = TheFunc->getAbstractClosureExpr()) {
436+
if (!closure->getType() && !closure->hasSingleExpressionBody())
437+
swift::typeCheckASTNodeAtLoc(closure->getParent(), closure->getLoc());
438438
}
439439

440440
Type ResultTy = TheFunc->getBodyResultType();
@@ -509,9 +509,10 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
509509

510510
TypeCheckExprOptions options = {};
511511

512-
if (getASTContext().TypeCheckerOpts.TypeCheckSingleASTNode) {
512+
if (LeaveBraceStmtBodyUnchecked) {
513513
assert(DiagnosticSuppression::isEnabled(getASTContext().Diags) &&
514514
"Diagnosing and AllowUnresolvedTypeVariables don't seem to mix");
515+
options |= TypeCheckExprFlags::LeaveClosureBodyUnchecked;
515516
options |= TypeCheckExprFlags::AllowUnresolvedTypeVariables;
516517
}
517518

@@ -623,7 +624,8 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
623624
}
624625

625626
Stmt *visitDeferStmt(DeferStmt *DS) {
626-
TypeChecker::typeCheckDecl(DS->getTempDecl());
627+
TypeChecker::typeCheckDecl(
628+
DS->getTempDecl(), /*LeaveBodyUnchecked=*/LeaveBraceStmtBodyUnchecked);
627629

628630
Expr *theCall = DS->getCallExpr();
629631
TypeChecker::typeCheckExpression(theCall, DC);
@@ -1556,8 +1558,10 @@ void StmtChecker::typeCheckASTNode(ASTNode &node) {
15561558
(!ctx.LangOpts.Playground && !ctx.LangOpts.DebuggerSupport);
15571559
if (isDiscarded)
15581560
options |= TypeCheckExprFlags::IsDiscarded;
1559-
if (getASTContext().TypeCheckerOpts.TypeCheckSingleASTNode)
1561+
if (LeaveBraceStmtBodyUnchecked) {
1562+
options |= TypeCheckExprFlags::LeaveClosureBodyUnchecked;
15601563
options |= TypeCheckExprFlags::AllowUnresolvedTypeVariables;
1564+
}
15611565

15621566
auto resultTy =
15631567
TypeChecker::typeCheckExpression(E, DC, Type(), CTP_Unused, options);
@@ -1590,15 +1594,16 @@ void StmtChecker::typeCheckASTNode(ASTNode &node) {
15901594

15911595
// Type check the declaration.
15921596
if (auto *D = node.dyn_cast<Decl *>()) {
1593-
TypeChecker::typeCheckDecl(D);
1597+
TypeChecker::typeCheckDecl(
1598+
D, /*LeaveBodyUnchecked=*/LeaveBraceStmtBodyUnchecked);
15941599
return;
15951600
}
15961601

15971602
llvm_unreachable("Type checking null ASTNode");
15981603
}
15991604

16001605
Stmt *StmtChecker::visitBraceStmt(BraceStmt *BS) {
1601-
if (getASTContext().TypeCheckerOpts.TypeCheckSingleASTNode)
1606+
if (LeaveBraceStmtBodyUnchecked)
16021607
return BS;
16031608

16041609
// Diagnose defer statement being last one in block (only if
@@ -1622,11 +1627,13 @@ Stmt *StmtChecker::visitBraceStmt(BraceStmt *BS) {
16221627
return BS;
16231628
}
16241629

1625-
void TypeChecker::typeCheckASTNode(ASTNode &node, DeclContext *DC) {
1630+
void TypeChecker::typeCheckASTNode(ASTNode &node, DeclContext *DC,
1631+
bool LeaveBodyUnchecked) {
16261632
StmtChecker stmtChecker(DC);
16271633
// FIXME: 'ActiveLabeledStmts', 'SwitchLevel', etc. in StmtChecker are not
16281634
// populated. Since they don't affect "type checking", it's doesn't cause
16291635
// any issue for now. But it should be populated nonetheless.
1636+
stmtChecker.LeaveBraceStmtBodyUnchecked = LeaveBodyUnchecked;
16301637
stmtChecker.typeCheckASTNode(node);
16311638
}
16321639

@@ -1960,7 +1967,8 @@ bool TypeCheckASTNodeAtLocRequest::evaluate(Evaluator &evaluator,
19601967
return false;
19611968
}
19621969

1963-
TypeChecker::typeCheckASTNode(finder.getRef(), DC);
1970+
TypeChecker::typeCheckASTNode(finder.getRef(), DC,
1971+
/*LeaveBodyUnchecked=*/true);
19641972
return false;
19651973
}
19661974

lib/Sema/TypeChecker.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -444,8 +444,6 @@ void swift::typeCheckPatternBinding(PatternBindingDecl *PBD,
444444

445445
bool swift::typeCheckASTNodeAtLoc(DeclContext *DC, SourceLoc TargetLoc) {
446446
auto &Ctx = DC->getASTContext();
447-
assert(Ctx.TypeCheckerOpts.TypeCheckSingleASTNode &&
448-
"typeCheckASTNodeAtLoc is only supported in TypeCheckSingleASTNode");
449447
DiagnosticSuppression suppression(Ctx.Diags);
450448
return !evaluateOrDefault(Ctx.evaluator,
451449
TypeCheckASTNodeAtLocRequest{DC, TargetLoc},

0 commit comments

Comments
 (0)