Skip to content

Commit e88f063

Browse files
hamishknightslavapestov
authored andcommitted
[Sema] Treat a lazy property's synthesised getter as being a property initialiser for error handling diagnostics
The only code we should be diagnosing on in such a context is within the property's initialiser expression that has been transplanted from the var's pattern binding decl. We don't perform the analysis on the init expr while it's still a part of the original PBD, as it doesn't get a solution applied there.
1 parent 1bcef4a commit e88f063

File tree

2 files changed

+34
-13
lines changed

2 files changed

+34
-13
lines changed

lib/Sema/TypeCheckError.cpp

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -873,6 +873,14 @@ class Context {
873873
llvm_unreachable("invalid classify result");
874874
}
875875

876+
static Context getContextForPatternBinding(PatternBindingDecl *pbd) {
877+
if (!pbd->isStatic() && pbd->getDeclContext()->isTypeContext()) {
878+
return Context(Kind::IVarInitializer);
879+
} else {
880+
return Context(Kind::GlobalVarInitializer);
881+
}
882+
}
883+
876884
Kind TheKind;
877885
bool DiagnoseErrorOnTry = false;
878886
DeclContext *RethrowsDC = nullptr;
@@ -895,6 +903,23 @@ class Context {
895903
result.RethrowsDC = D;
896904
return result;
897905
}
906+
907+
// HACK: If the decl is the synthesized getter for a 'lazy' property, then
908+
// treat the context as a property initializer in order to produce a better
909+
// diagnostic; the only code we should be diagnosing on is within the
910+
// initializer expression that has been transplanted from the var's pattern
911+
// binding decl. We don't perform the analysis on the initializer while it's
912+
// still a part of that PBD, as it doesn't get a solution applied there.
913+
if (auto *accessor = dyn_cast<AccessorDecl>(D)) {
914+
if (auto *var = dyn_cast<VarDecl>(accessor->getStorage())) {
915+
if (accessor->isGetter() && var->getAttrs().hasAttribute<LazyAttr>()) {
916+
auto *pbd = var->getParentPatternBinding();
917+
assert(pbd && "lazy var didn't have a pattern binding decl");
918+
return getContextForPatternBinding(pbd);
919+
}
920+
}
921+
}
922+
898923
return Context(getKindForFunctionBody(
899924
D->getInterfaceType(), D->getNumParameterLists()));
900925
}
@@ -904,14 +929,10 @@ class Context {
904929
return Context(Kind::DefaultArgument);
905930
}
906931

907-
auto binding = cast<PatternBindingInitializer>(init)->getBinding();
932+
auto *binding = cast<PatternBindingInitializer>(init)->getBinding();
908933
assert(!binding->getDeclContext()->isLocalContext() &&
909934
"setting up error context for local pattern binding?");
910-
if (!binding->isStatic() && binding->getDeclContext()->isTypeContext()) {
911-
return Context(Kind::IVarInitializer);
912-
} else {
913-
return Context(Kind::GlobalVarInitializer);
914-
}
935+
return getContextForPatternBinding(binding);
915936
}
916937

917938
static Context forEnumElementInitializer(EnumElementDecl *elt) {

test/decl/func/throwing_functions.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -205,19 +205,19 @@ struct IllegalContext {
205205
}
206206
}()
207207

208-
lazy var y1: Int = genError() // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}}
208+
lazy var y1: Int = genError() // expected-error {{call can throw, but errors cannot be thrown out of a property initializer}}
209209

210-
lazy var y2 = genError() // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}}
210+
lazy var y2 = genError() // expected-error {{call can throw, but errors cannot be thrown out of a property initializer}}
211211

212-
lazy var y3 = try genError() // expected-error {{errors thrown from here are not handled}}
212+
lazy var y3 = try genError() // expected-error {{call can throw, but errors cannot be thrown out of a property initializer}}
213213

214-
lazy var y4: Int = try genError() // expected-error {{errors thrown from here are not handled}}
214+
lazy var y4: Int = try genError() // expected-error {{call can throw, but errors cannot be thrown out of a property initializer}}
215215

216-
lazy var y5 = B() // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}}
216+
lazy var y5 = B() // expected-error {{call can throw, but errors cannot be thrown out of a property initializer}}
217217

218-
lazy var y6 = try B() // expected-error {{errors thrown from here are not handled}}
218+
lazy var y6 = try B() // expected-error {{call can throw, but errors cannot be thrown out of a property initializer}}
219219

220-
lazy var y7 = { // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}}
220+
lazy var y7 = { // expected-error {{call can throw, but errors cannot be thrown out of a property initializer}}
221221
return try genError()
222222
}()
223223

0 commit comments

Comments
 (0)