Skip to content

Commit d324969

Browse files
committed
[Diagnostics] Transfer previously resolved types directly from expressions
While trying to diagnose the problem with previously type-checked sub-expression, use its type-checked variant as a source of type information, instead of transferring from its original constraint system, because if expression was type-checked successfully it would have all of the required information in AST, and that doesn't rely on associated constraint system being present. Resolves: rdar://problem/42056741
1 parent 6ecfe7a commit d324969

File tree

3 files changed

+33
-20
lines changed

3 files changed

+33
-20
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2356,22 +2356,15 @@ Expr *FailureDiagnosis::typeCheckChildIndependently(
23562356
// telling us that it knows what it is doing, then believe it.
23572357
if (!options.contains(TCC_ForceRecheck)) {
23582358
if (CS.TC.isExprBeingDiagnosed(subExpr)) {
2359-
auto exprAndCS = CS.TC.getExprBeingDiagnosed(subExpr);
2360-
auto *savedExpr = exprAndCS.first;
2359+
auto *savedExpr = CS.TC.getExprBeingDiagnosed(subExpr);
23612360
if (subExpr == savedExpr)
23622361
return subExpr;
23632362

2364-
auto *oldCS = exprAndCS.second;
2365-
2366-
// The types on the result might have already been cached into
2367-
// another CS, but likely not this one.
2368-
if (oldCS != &CS)
2369-
CS.transferExprTypes(oldCS, savedExpr);
2370-
2363+
CS.cacheExprTypes(savedExpr);
23712364
return savedExpr;
23722365
}
23732366

2374-
CS.TC.addExprForDiagnosis(subExpr, std::make_pair(subExpr, &CS));
2367+
CS.TC.addExprForDiagnosis(subExpr, subExpr);
23752368
}
23762369

23772370
// Validate contextual type before trying to use it.
@@ -2457,7 +2450,8 @@ Expr *FailureDiagnosis::typeCheckChildIndependently(
24572450
SavedTypeData.restore();
24582451
}
24592452

2460-
CS.TC.addExprForDiagnosis(preCheckedExpr, std::make_pair(subExpr, &CS));
2453+
if (preCheckedExpr != subExpr)
2454+
CS.TC.addExprForDiagnosis(preCheckedExpr, subExpr);
24612455

24622456
return subExpr;
24632457
}

lib/Sema/TypeChecker.h

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,6 @@ namespace constraints {
5757
using ConformanceMap =
5858
llvm::DenseMap<SubstitutableType *, SmallVector<ProtocolConformance *, 2>>;
5959

60-
/// \brief Used for recursive lookups into an expr that is already
61-
/// being type-checked and the constraint system in which its type is
62-
/// stored.
63-
using ExprAndConstraintSystem =
64-
std::pair<Expr *, constraints::ConstraintSystem *>;
65-
6660
/// Special-case type checking semantics for certain declarations.
6761
enum class DeclTypeCheckingSemantics {
6862
/// A normal declaration.
@@ -783,7 +777,7 @@ class TypeChecker final : public LazyResolver {
783777
Optional<NominalTypeDecl *> ArrayDecl;
784778

785779
/// The set of expressions currently being analyzed for failures.
786-
llvm::DenseMap<Expr*, ExprAndConstraintSystem> DiagnosedExprs;
780+
llvm::DenseMap<Expr*, Expr*> DiagnosedExprs;
787781

788782
ModuleDecl *StdlibModule = nullptr;
789783

@@ -2315,13 +2309,13 @@ class TypeChecker final : public LazyResolver {
23152309
void checkInitializerErrorHandling(Initializer *I, Expr *E);
23162310
void checkEnumElementErrorHandling(EnumElementDecl *D);
23172311

2318-
void addExprForDiagnosis(Expr *E1, ExprAndConstraintSystem Result) {
2312+
void addExprForDiagnosis(Expr *E1, Expr *Result) {
23192313
DiagnosedExprs[E1] = Result;
23202314
}
23212315
bool isExprBeingDiagnosed(Expr *E) {
23222316
return DiagnosedExprs.count(E);
23232317
}
2324-
ExprAndConstraintSystem getExprBeingDiagnosed(Expr *E) {
2318+
Expr *getExprBeingDiagnosed(Expr *E) {
23252319
return DiagnosedExprs[E];
23262320
}
23272321

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -code-completion-token=COMPLETE -source-filename=%s
2+
3+
// REQUIRES: objc_interop
4+
5+
import Foundation
6+
7+
8+
class A {
9+
static var `default` = A()
10+
11+
func foo(arg: String) -> Bool {
12+
return false
13+
}
14+
15+
func foo(arg: String, _ flag: UnsafeMutablePointer<ObjCBool>?) -> Bool {
16+
return true
17+
}
18+
}
19+
20+
class B {
21+
var bar: Bool = false
22+
func baz() {
23+
bar = A.default.foo(arg: self.#^COMPLETE^#)
24+
}
25+
}

0 commit comments

Comments
 (0)