Skip to content

Commit c52ccfc

Browse files
authored
Merge pull request #58717 from xedin/rdar-92347054-5.7
[5.7][CSClosure] Mark partially inferred external declarations as invalid
2 parents c537e59 + 00ac57b commit c52ccfc

File tree

3 files changed

+83
-4
lines changed

3 files changed

+83
-4
lines changed

lib/Sema/CSClosure.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,32 @@ class TypeVariableRefFinder : public ASTWalker {
5050

5151
std::pair<bool, Expr *> walkToExprPre(Expr *expr) override {
5252
if (auto *DRE = dyn_cast<DeclRefExpr>(expr)) {
53-
if (auto type = CS.getTypeIfAvailable(DRE->getDecl()))
53+
auto *decl = DRE->getDecl();
54+
55+
if (auto type = CS.getTypeIfAvailable(DRE->getDecl())) {
56+
// If this is not one of the closure parameters which
57+
// is inferrable from the body, let's replace type
58+
// variables with errors to avoid bringing external
59+
// information to the element component.
60+
if (type->hasTypeVariable() && !isa<ParamDecl>(decl)) {
61+
// If there are type variables left in the simplified version,
62+
// it means that this is an invalid external declaration
63+
// relative to this element's context.
64+
if (CS.simplifyType(type)->hasTypeVariable()) {
65+
auto transformedTy = type.transform([&](Type type) {
66+
if (auto *typeVar = type->getAs<TypeVariableType>()) {
67+
return ErrorType::get(CS.getASTContext());
68+
}
69+
return type;
70+
});
71+
72+
CS.setType(decl, transformedTy);
73+
return {true, expr};
74+
}
75+
}
76+
5477
inferVariables(type);
78+
}
5579
}
5680

5781
return {true, expr};

lib/Sema/CSStep.h

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,9 @@ class ConjunctionStep : public BindingStep<ConjunctionElementProducer> {
781781
class SolverSnapshot {
782782
ConstraintSystem &CS;
783783

784+
/// The conjunction this snapshot belongs to.
785+
Constraint *Conjunction;
786+
784787
Optional<llvm::SaveAndRestore<DeclContext *>> DC = None;
785788

786789
llvm::SetVector<TypeVariableType *> TypeVars;
@@ -794,8 +797,9 @@ class ConjunctionStep : public BindingStep<ConjunctionElementProducer> {
794797

795798
public:
796799
SolverSnapshot(ConstraintSystem &cs, Constraint *conjunction)
797-
: CS(cs), TypeVars(std::move(cs.TypeVariables)) {
798-
auto *locator = conjunction->getLocator();
800+
: CS(cs), Conjunction(conjunction),
801+
TypeVars(std::move(cs.TypeVariables)) {
802+
auto *locator = Conjunction->getLocator();
799803
// If this conjunction represents a closure, we need to
800804
// switch declaration context over to it.
801805
if (locator->directlyAt<ClosureExpr>()) {
@@ -820,7 +824,7 @@ class ConjunctionStep : public BindingStep<ConjunctionElementProducer> {
820824
IsolationScope = std::make_unique<Scope>(CS);
821825

822826
// Apply solution inferred for the conjunction.
823-
CS.applySolution(solution);
827+
applySolution(solution);
824828

825829
// Add constraints to the graph after solution
826830
// has been applied to make sure that all type
@@ -855,6 +859,36 @@ class ConjunctionStep : public BindingStep<ConjunctionElementProducer> {
855859
for (auto &constraint : CS.InactiveConstraints)
856860
CG.addConstraint(&constraint);
857861
}
862+
863+
void applySolution(const Solution &solution) {
864+
CS.applySolution(solution);
865+
866+
if (!CS.shouldAttemptFixes())
867+
return;
868+
869+
// If inference succeeded, we are done.
870+
auto score = solution.getFixedScore();
871+
if (score.Data[SK_Fix] == 0)
872+
return;
873+
874+
// If this conjunction represents a closure and inference
875+
// has failed, let's bind all of unresolved type variables
876+
// in its interface type to holes to avoid extraneous
877+
// fixes produced by outer context.
878+
879+
auto locator = Conjunction->getLocator();
880+
if (locator->directlyAt<ClosureExpr>()) {
881+
auto closureTy =
882+
CS.getClosureType(castToExpr<ClosureExpr>(locator->getAnchor()));
883+
884+
CS.simplifyType(closureTy).visit([&](Type componentTy) {
885+
if (auto *typeVar = componentTy->getAs<TypeVariableType>()) {
886+
CS.assignFixedType(
887+
typeVar, PlaceholderType::get(CS.getASTContext(), typeVar));
888+
}
889+
});
890+
}
891+
}
858892
};
859893

860894
/// Best solution solver reached so far.

test/expr/closure/multi_statement.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,3 +329,24 @@ func test_unknown_refs_in_tilde_operator() {
329329
}
330330
}
331331
}
332+
333+
// rdar://92347054 - crash during conjunction processing
334+
func test_no_crash_with_circular_ref_due_to_error() {
335+
struct S { // expected-note {{did you mean 'S'?}}
336+
var x: Int?
337+
}
338+
339+
func test(v: Int?, arr: [S]) -> Int { // expected-note {{did you mean 'v'?}}
340+
// There is missing `f` here which made body of the
341+
// `if` a multiple statement closure instead that uses
342+
// `next` inside.
343+
i let x = v, let next = arr.first?.x { // expected-error {{cannot find 'i' in scope}}
344+
// expected-error@-1 {{consecutive statements on a line must be separated by ';'}}
345+
// expected-error@-2 {{'let' cannot appear nested inside another 'var' or 'let' pattern}}
346+
// expected-error@-3 {{cannot call value of non-function type 'Int?'}}
347+
print(next)
348+
return x
349+
}
350+
return 0
351+
}
352+
}

0 commit comments

Comments
 (0)