Skip to content

Commit 82f4a10

Browse files
authored
Merge pull request #85527 from hamishknight/the-whole-hole
[CS] Eagerly produce holes in a couple of places
2 parents 40cee72 + 61a5ae8 commit 82f4a10

15 files changed

+46
-42
lines changed

lib/Sema/CSFix.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -939,7 +939,11 @@ DefineMemberBasedOnUse::diagnoseForAmbiguity(CommonFixesArray commonFixes) const
939939
const auto *solution = solutionAndFix.first;
940940
const auto *fix = solutionAndFix.second->getAs<DefineMemberBasedOnUse>();
941941

942-
auto baseType = solution->simplifyType(fix->BaseType);
942+
// Ignore differences in optionality since we can look through an optional
943+
// to resolve an implicit member `.foo`.
944+
auto baseType = solution->simplifyType(fix->BaseType)
945+
->getMetatypeInstanceType()
946+
->lookThroughAllOptionalTypes();
943947
if (!concreteBaseType)
944948
concreteBaseType = baseType;
945949

lib/Sema/CSGen.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,14 +1308,17 @@ namespace {
13081308
CS.setType(expr, expansionType);
13091309
}
13101310

1311-
/// Records a fix for an invalid AST node, and returns a potential hole
1312-
/// type variable for it.
1311+
/// Records a fix for an invalid AST node, and returns a hole for it.
13131312
Type recordInvalidNode(ASTNode node) {
13141313
CS.recordFix(
13151314
IgnoreInvalidASTNode::create(CS, CS.getConstraintLocator(node)));
13161315

1317-
return CS.createTypeVariable(CS.getConstraintLocator(node),
1318-
TVO_CanBindToHole);
1316+
// Ideally we wouldn't need a type variable here, but we don't have a
1317+
// suitable placeholder originator for all the cases here.
1318+
auto ty = CS.createTypeVariable(CS.getConstraintLocator(node),
1319+
TVO_CanBindToHole);
1320+
CS.recordTypeVariablesAsHoles(ty);
1321+
return ty;
13191322
}
13201323

13211324
virtual Type visitErrorExpr(ErrorExpr *E) {

lib/Sema/CSSimplify.cpp

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6694,6 +6694,10 @@ bool ConstraintSystem::repairFailures(
66946694
}
66956695

66966696
case ConstraintLocator::Condition: {
6697+
// If the condition is already a hole, we're done.
6698+
if (lhs->isPlaceholder())
6699+
return true;
6700+
66976701
if (repairViaOptionalUnwrap(*this, lhs, rhs, matchKind, conversionsOrFixes,
66986702
locator))
66996703
return true;
@@ -11604,22 +11608,11 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
1160411608
// `key path` constraint can't be retired until all components
1160511609
// are simplified.
1160611610
addTypeVariableConstraintsToWorkList(memberTypeVar);
11607-
} else if (isa<Expr *>(locator->getAnchor()) &&
11608-
!getSemanticsProvidingParentExpr(
11609-
getAsExpr(locator->getAnchor()))) {
11610-
// If there are no contextual expressions that could provide
11611-
// a type for the member type variable, let's default it to
11612-
// a placeholder eagerly so it could be propagated to the
11613-
// pattern if necessary.
11614-
recordTypeVariablesAsHoles(memberTypeVar);
11615-
} else if (locator->isLastElement<LocatorPathElt::PatternMatch>()) {
11616-
// Let's handle member patterns specifically because they use
11617-
// equality instead of argument application constraint, so allowing
11618-
// them to bind member could mean missing valid hole positions in
11619-
// the pattern.
11620-
recordTypeVariablesAsHoles(memberTypeVar);
1162111611
} else {
11622-
recordPotentialHole(memberTypeVar);
11612+
// Eagerly turn the member type variable into a hole since we know
11613+
// this is where the issue is and we've recorded a fix for it. This
11614+
// avoids producing unnecessary holes for e.g generic parameters.
11615+
recordTypeVariablesAsHoles(memberTypeVar);
1162311616
}
1162411617
}
1162511618

lib/Sema/ConstraintSystem.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3581,12 +3581,13 @@ void constraints::simplifyLocator(ASTNode &anchor,
35813581
}
35823582
case ConstraintLocator::AutoclosureResult:
35833583
case ConstraintLocator::LValueConversion:
3584+
case ConstraintLocator::OptionalInjection:
35843585
case ConstraintLocator::DynamicType:
35853586
case ConstraintLocator::UnresolvedMember:
35863587
case ConstraintLocator::ImplicitCallAsFunction:
35873588
// Arguments in autoclosure positions, lvalue and rvalue adjustments,
3588-
// unresolved members, and implicit callAsFunction references are
3589-
// implicit.
3589+
// optional injections, unresolved members, and implicit callAsFunction
3590+
// references are implicit.
35903591
path = path.slice(1);
35913592
continue;
35923593

@@ -3913,7 +3914,6 @@ void constraints::simplifyLocator(ASTNode &anchor,
39133914

39143915
case ConstraintLocator::Witness:
39153916
case ConstraintLocator::WrappedValue:
3916-
case ConstraintLocator::OptionalInjection:
39173917
case ConstraintLocator::ImplicitlyUnwrappedDisjunctionChoice:
39183918
case ConstraintLocator::FallbackType:
39193919
case ConstraintLocator::KeyPathSubscriptIndex:

test/Constraints/closures.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1362,7 +1362,7 @@ do {
13621362
}
13631363
}
13641364

1365-
test { // expected-error {{invalid conversion from throwing function of type '(Int) throws -> Void' to non-throwing function type '(Int) -> Void'}}
1365+
test { // expected-error {{invalid conversion from throwing function of type '(Int) throws -> _' to non-throwing function type '(Int) -> Void'}}
13661366
try $0.missing // expected-error {{value of type 'Int' has no member 'missing'}}
13671367
}
13681368
}

test/Constraints/diagnostics.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,10 +1126,12 @@ func rdar17170728() {
11261126
// expected-error@-1 4 {{optional type 'Int?' cannot be used as a boolean; test for '!= nil' instead}}
11271127
}
11281128

1129+
// FIXME: Bad diagnostic, `Bool.Stride` is bogus, we shouldn't be suggesting
1130+
// `reduce(into:)`, and the actual problem is that Int cannot be used as a boolean
1131+
// condition.
11291132
let _ = [i, j, k].reduce(0 as Int?) { // expected-error {{missing argument label 'into:' in call}}
1130-
// expected-error@-1 {{cannot convert value of type 'Int?' to expected argument type '(inout (Bool, Bool) -> Bool?, Int?) throws -> ()'}}
11311133
$0 && $1 ? $0 + $1 : ($0 ? $0 : ($1 ? $1 : nil))
1132-
// expected-error@-1 {{binary operator '+' cannot be applied to two 'Bool' operands}}
1134+
// expected-error@-1 {{binary operator '+' cannot be applied to operands of type 'Bool.Stride' and 'Bool'}}
11331135
}
11341136
}
11351137

test/Constraints/ternary_expr.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ _ = true ? x : 1.2 // expected-error {{result values in '? :' expression have mi
5959
_ = (x: true) ? true : false // expected-error {{cannot convert value of type '(x: Bool)' to expected condition type 'Bool'}}
6060
_ = (x: 1) ? true : false // expected-error {{cannot convert value of type '(x: Int)' to expected condition type 'Bool'}}
6161

62+
_ = undefined ? 0 : 1 // expected-error {{cannot find 'undefined' in scope}}
63+
_ = [undefined] ? 0 : 1 // expected-error {{cannot find 'undefined' in scope}}
64+
// expected-error@-1 {{cannot convert value of type '[Element]' to expected condition type 'Bool'}}
65+
6266
func resultBool() -> Bool { true }
6367
_ = resultBool ? true : false // expected-error {{function 'resultBool' was used as a property; add () to call it}} {{15-15=()}}
6468

test/Parse/subscripting.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,6 @@ struct A6 {
179179
// expected-note@-2 {{did you mean}}
180180
get {
181181
return i + j // expected-error {{cannot find 'j' in scope}}
182-
// expected-error@-1 {{cannot convert return expression of type 'Int' to return type '(Int) -> Int'}}
183182
}
184183
}
185184
}

test/stmt/statements.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,9 @@ func bad_if() {
560560
if (x: false) {} // expected-error {{cannot convert value of type '(x: Bool)' to expected condition type 'Bool'}}
561561
if (x: 1) {} // expected-error {{cannot convert value of type '(x: Int)' to expected condition type 'Bool'}}
562562
if nil {} // expected-error {{'nil' is not compatible with expected condition type 'Bool'}}
563+
if undefined {} // expected-error {{cannot find 'undefined' in scope}}
564+
if [undefined] {} // expected-error {{cannot find 'undefined' in scope}}
565+
// expected-error@-1 {{cannot convert value of type '[Element]' to expected condition type 'Bool'}}
563566
}
564567

565568
// Typo correction for loop labels

test/type/protocol_composition.swift

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -191,16 +191,12 @@ takesP1AndP2([AnyObject & P1 & P2]())
191191
takesP1AndP2([Swift.AnyObject & P1 & P2]())
192192
takesP1AndP2([AnyObject & protocol_composition.P1 & P2]())
193193
takesP1AndP2([AnyObject & P1 & protocol_composition.P2]())
194-
takesP1AndP2([DoesNotExist & P1 & P2]()) // expected-error {{cannot find 'DoesNotExist' in scope}}
195-
// expected-error@-1 {{binary operator '&' cannot be applied to operands of type 'UInt8' and '(any P2).Type'}}
196-
// expected-error@-2 {{binary operator '&' cannot be applied to operands of type 'UInt8' and '(any P1).Type'}}
197-
// expected-note@-3 2 {{overloads for '&' exist with these partially matching parameter lists}}
198-
// expected-error@-4 {{cannot call value of non-function type '[UInt8]'}}
199-
takesP1AndP2([Swift.DoesNotExist & P1 & P2]()) // expected-error {{module 'Swift' has no member named 'DoesNotExist'}}
200-
// expected-error@-1 {{binary operator '&' cannot be applied to operands of type 'UInt8' and '(any P2).Type'}}
201-
// expected-error@-2 {{binary operator '&' cannot be applied to operands of type 'UInt8' and '(any P1).Type'}}
202-
// expected-note@-3 2 {{overloads for '&' exist with these partially matching parameter lists}}
203-
// expected-error@-4 {{cannot call value of non-function type '[UInt8]'}}
194+
takesP1AndP2([DoesNotExist & P1 & P2]())
195+
// expected-error@-1 {{cannot find 'DoesNotExist' in scope}}
196+
// expected-error@-2 {{cannot call value of non-function type '[Element]'}}
197+
takesP1AndP2([Swift.DoesNotExist & P1 & P2]())
198+
// expected-error@-1 {{module 'Swift' has no member named 'DoesNotExist'}}
199+
// expected-error@-2 {{cannot call value of non-function type '[Element]'}}
204200

205201
typealias T08 = P1 & inout P2 // expected-error {{'inout' may only be used on parameters}}
206202
typealias T09 = P1 & __shared P2 // expected-error {{'__shared' may only be used on parameters}}

0 commit comments

Comments
 (0)