Skip to content

Commit 1c65a55

Browse files
committed
[CSGen] Turn invalid decls into holes
Instead of failing constraint generation upon encountering an invalid declaration, let's turn that declaration into a potential hole and keep going. Doing so enables the solver to reach a solution and diagnose any other issue with expression.
1 parent 7e854ef commit 1c65a55

File tree

7 files changed

+22
-20
lines changed

7 files changed

+22
-20
lines changed

lib/Sema/CSGen.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,9 +1227,11 @@ namespace {
12271227
if (knownType) {
12281228
// If the known type has an error, bail out.
12291229
if (knownType->hasError()) {
1230+
auto *hole = CS.createTypeVariable(locator, TVO_CanBindToHole);
1231+
(void)CS.recordFix(AllowRefToInvalidDecl::create(CS, locator));
12301232
if (!CS.hasType(E))
1231-
CS.setType(E, knownType);
1232-
return nullptr;
1233+
CS.setType(E, hole);
1234+
return hole;
12331235
}
12341236

12351237
if (!knownType->hasHole()) {
@@ -1258,14 +1260,13 @@ namespace {
12581260
}
12591261
}
12601262

1261-
// If we're referring to an invalid declaration, don't type-check.
1262-
//
1263-
// FIXME: If the decl is in error, we get no information from this.
1264-
// We may, alternatively, want to use a type variable in that case,
1265-
// and possibly infer the type of the variable that way.
1263+
// If declaration is invalid, let's turn it into a potential hole
1264+
// and keep generating constraints.
12661265
if (!knownType && E->getDecl()->isInvalid()) {
1267-
CS.setType(E, E->getDecl()->getInterfaceType());
1268-
return nullptr;
1266+
auto *hole = CS.createTypeVariable(locator, TVO_CanBindToHole);
1267+
(void)CS.recordFix(AllowRefToInvalidDecl::create(CS, locator));
1268+
CS.setType(E, hole);
1269+
return hole;
12691270
}
12701271

12711272
// Create an overload choice referencing this declaration and immediately

test/ClangImporter/MixedSource/can_import_objc_idempotent.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
// expected-error@-1 {{cannot find 'CGRect' in scope}}
3131

3232
let (r, s) = square.divided(atDistance: 50, from: .minXEdge)
33+
// expected-error@-1 {{type of expression is ambiguous without more context}}
3334
#endif
3435

3536
#if canImport(MixedWithHeader)

test/ClangImporter/cf.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import CoreCooling
66
import CFAndObjC
77

8-
func assertUnmanaged<T>(_ t: Unmanaged<T>) {}
8+
func assertUnmanaged<T>(_ t: Unmanaged<T>) {} // expected-note {{in call to function 'assertUnmanaged'}}
99
func assertManaged<T: AnyObject>(_ t: T) {}
1010

1111
func test0(_ fridge: CCRefrigerator) {
@@ -15,7 +15,7 @@ func test0(_ fridge: CCRefrigerator) {
1515
func test1(_ power: Unmanaged<CCPowerSupply>) {
1616
assertUnmanaged(power)
1717
let fridge = CCRefrigeratorCreate(power) // expected-error {{cannot convert value of type 'Unmanaged<CCPowerSupply>' to expected argument type 'CCPowerSupply?'}}
18-
assertUnmanaged(fridge)
18+
assertUnmanaged(fridge) // expected-error {{generic parameter 'T' could not be inferred}}
1919
}
2020

2121
func test2() {

test/NameLookup/name_lookup.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,6 @@ struct PatternBindingWithTwoVars3 { var x = y, y = x }
650650

651651
// https://bugs.swift.org/browse/SR-9015
652652
func sr9015() {
653-
let closure1 = { closure2() } // expected-error {{circular reference}} expected-note {{through reference here}} expected-note {{through reference here}} expected-error {{unable to infer closure}}
654-
let closure2 = { closure1() } // expected-note {{through reference here}} expected-note {{through reference here}} expected-note {{through reference here}} expected-error {{unable to infer closure}}
653+
let closure1 = { closure2() } // expected-error {{circular reference}} expected-note {{through reference here}} expected-note {{through reference here}}
654+
let closure2 = { closure1() } // expected-note {{through reference here}} expected-note {{through reference here}} expected-note {{through reference here}}
655655
}

test/attr/attr_noescape.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,8 @@ class SomeClass {
184184
// Implicit conversions (in this case to @convention(block)) are ok.
185185
@_silgen_name("whatever")
186186
func takeNoEscapeAsObjCBlock(_: @noescape @convention(block) () -> Void) // expected-error{{unknown attribute 'noescape'}}
187-
func takeNoEscapeTest2(_ fn : @noescape () -> ()) { // expected-error{{unknown attribute 'noescape'}}
188-
takeNoEscapeAsObjCBlock(fn)
187+
func takeNoEscapeTest2(_ fn : @noescape () -> ()) { // expected-error{{unknown attribute 'noescape'}} expected-note {{parameter 'fn' is implicitly non-escaping}}
188+
takeNoEscapeAsObjCBlock(fn) // expected-error {{passing non-escaping parameter 'fn' to function expecting an @escaping closure}}
189189
}
190190

191191
// Autoclosure implies noescape..
@@ -290,14 +290,14 @@ typealias CompletionHandler = (_ success: Bool) -> ()
290290

291291
var escape : CompletionHandlerNE
292292
var escapeOther : CompletionHandler
293-
func doThing1(_ completion: (_ success: Bool) -> ()) {
294-
escape = completion
293+
func doThing1(_ completion: (_ success: Bool) -> ()) { // expected-note {{parameter 'completion' is implicitly non-escaping}}
294+
escape = completion // expected-error {{assigning non-escaping parameter 'completion' to an @escaping closure}}
295295
}
296296
func doThing2(_ completion: CompletionHandlerNE) {
297297
escape = completion
298298
}
299-
func doThing3(_ completion: CompletionHandler) {
300-
escape = completion
299+
func doThing3(_ completion: CompletionHandler) { // expected-note {{parameter 'completion' is implicitly non-escaping}}
300+
escape = completion // expected-error {{assigning non-escaping parameter 'completion' to an @escaping closure}}
301301
}
302302
func doThing4(_ completion: @escaping CompletionHandler) {
303303
escapeOther = completion

test/expr/closure/closures.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ assert(f0(1) == 1)
119119
var selfRef = { selfRef() }
120120
// expected-note@-1 2{{through reference here}}
121121
// expected-error@-2 {{circular reference}}
122-
// expected-error@-3 {{unable to infer closure type in the current context}}
123122

124123
var nestedSelfRef = {
125124
var recursive = { nestedSelfRef() }

validation-test/Sema/type_checker_perf/slow/fast-operator-typechecking.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ func checksum(value: UInt16) -> UInt16 {
55
var checksum = (((value >> 2) ^ (value >> 8) ^ (value >> 12) ^ (value >> 14)) & 0x01) << 1
66
// expected-error@-1 {{the compiler is unable to type-check this expression in reasonable time}}
77
checksum |= (((value) ^ (value >> UInt16(4)) ^ (value >> UInt16(6)) ^ (value >> UInt16(10))) & 0x01)
8+
// expected-error@-1 {{the compiler is unable to type-check this expression in reasonable time}}
89
checksum ^= 0x02
910
return checksum
1011
}

0 commit comments

Comments
 (0)