Skip to content

Commit 1f14005

Browse files
authored
Merge pull request #34584 from xedin/rdar-70880670
[CSGen] Turn invalid decls into holes
2 parents 5b74552 + 8e95096 commit 1f14005

File tree

14 files changed

+110
-21
lines changed

14 files changed

+110
-21
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3726,6 +3726,9 @@ ERROR(capture_across_type_decl,none,
37263726
"%0 declaration cannot close over value %1 defined in outer scope",
37273727
(DescriptiveDeclKind, Identifier))
37283728

3729+
ERROR(reference_to_invalid_decl,none,
3730+
"cannot reference invalid declaration %0", (DeclName))
3731+
37293732
//------------------------------------------------------------------------------
37303733
// MARK: Type Check Statements
37313734
//------------------------------------------------------------------------------

include/swift/Sema/CSFix.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,10 @@ enum class FixKind : uint8_t {
281281

282282
/// Resolve type of `nil` by providing a contextual type.
283283
SpecifyContextualTypeForNil,
284+
285+
/// Allow expressions to reference invalid declarations by turning
286+
/// them into holes.
287+
AllowRefToInvalidDecl,
284288
};
285289

286290
class ConstraintFix {
@@ -2055,6 +2059,25 @@ class SpecifyContextualTypeForNil final : public ConstraintFix {
20552059
ConstraintLocator * locator);
20562060
};
20572061

2062+
class AllowRefToInvalidDecl final : public ConstraintFix {
2063+
AllowRefToInvalidDecl(ConstraintSystem &cs, ConstraintLocator *locator)
2064+
: ConstraintFix(cs, FixKind::AllowRefToInvalidDecl, locator) {}
2065+
2066+
public:
2067+
std::string getName() const override {
2068+
return "ignore invalid declaration reference";
2069+
}
2070+
2071+
bool diagnose(const Solution &solution, bool asNote = false) const override;
2072+
2073+
bool diagnoseForAmbiguity(CommonFixesArray commonFixes) const override {
2074+
return diagnose(*commonFixes.front().first);
2075+
}
2076+
2077+
static AllowRefToInvalidDecl *create(ConstraintSystem &cs,
2078+
ConstraintLocator *locator);
2079+
};
2080+
20582081
} // end namespace constraints
20592082
} // end namespace swift
20602083

lib/Sema/CSDiagnostics.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7002,3 +7002,21 @@ bool MissingContextualTypeForNil::diagnoseAsError() {
70027002
emitDiagnostic(diag::unresolved_nil_literal);
70037003
return true;
70047004
}
7005+
7006+
bool ReferenceToInvalidDeclaration::diagnoseAsError() {
7007+
auto *decl = castToExpr<DeclRefExpr>(getAnchor())->getDecl();
7008+
assert(decl);
7009+
7010+
auto &DE = getASTContext().Diags;
7011+
// This problem should have been already diagnosed during
7012+
// validation of the declaration.
7013+
if (DE.hadAnyError())
7014+
return true;
7015+
7016+
// If no errors have been emitted yet, let's emit one
7017+
// about reference to an invalid declaration.
7018+
7019+
emitDiagnostic(diag::reference_to_invalid_decl, decl->getName());
7020+
emitDiagnosticAt(decl, diag::decl_declared_here, decl->getName());
7021+
return true;
7022+
}

lib/Sema/CSDiagnostics.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2281,6 +2281,21 @@ class MissingContextualTypeForNil final : public FailureDiagnostic {
22812281
bool diagnoseAsError() override;
22822282
};
22832283

2284+
/// Diagnostic situations where AST node references an invalid declaration.
2285+
///
2286+
/// \code
2287+
/// let foo = doesntExist // or something invalid
2288+
/// foo(42)
2289+
/// \endcode
2290+
class ReferenceToInvalidDeclaration final : public FailureDiagnostic {
2291+
public:
2292+
ReferenceToInvalidDeclaration(const Solution &solution,
2293+
ConstraintLocator *locator)
2294+
: FailureDiagnostic(solution, locator) {}
2295+
2296+
bool diagnoseAsError() override;
2297+
};
2298+
22842299
} // end namespace constraints
22852300
} // end namespace swift
22862301

lib/Sema/CSFix.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1615,3 +1615,15 @@ SpecifyContextualTypeForNil::create(ConstraintSystem &cs,
16151615
ConstraintLocator *locator) {
16161616
return new (cs.getAllocator()) SpecifyContextualTypeForNil(cs, locator);
16171617
}
1618+
1619+
bool AllowRefToInvalidDecl::diagnose(const Solution &solution,
1620+
bool asNote) const {
1621+
ReferenceToInvalidDeclaration failure(solution, getLocator());
1622+
return failure.diagnose(asNote);
1623+
}
1624+
1625+
AllowRefToInvalidDecl *
1626+
AllowRefToInvalidDecl::create(ConstraintSystem &cs,
1627+
ConstraintLocator *locator) {
1628+
return new (cs.getAllocator()) AllowRefToInvalidDecl(cs, locator);
1629+
}

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

lib/Sema/CSSimplify.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10153,7 +10153,8 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
1015310153
case FixKind::SpecifyLabelToAssociateTrailingClosure:
1015410154
case FixKind::AllowKeyPathWithoutComponents:
1015510155
case FixKind::IgnoreInvalidResultBuilderBody:
10156-
case FixKind::SpecifyContextualTypeForNil: {
10156+
case FixKind::SpecifyContextualTypeForNil:
10157+
case FixKind::AllowRefToInvalidDecl: {
1015710158
return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved;
1015810159
}
1015910160

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() }
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %target-typecheck-verify-swift -target x86_64-apple-macosx10.15 -swift-version 5
2+
// REQUIRES: objc_interop
3+
// REQUIRES: OS=macosx
4+
5+
import SwiftUI
6+
7+
var foo = doesntExist // expected-error {{cannot find 'doesntExist' in scope}}
8+
9+
struct ContentView: View {
10+
var body: some View {
11+
VStack {
12+
Text(verbatim: foo)
13+
}
14+
}
15+
}

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)