Skip to content

Commit c9220e6

Browse files
committed
Add additional lifetime dependence diagnostics
1 parent 7476970 commit c9220e6

File tree

4 files changed

+59
-38
lines changed

4 files changed

+59
-38
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7786,6 +7786,11 @@ ERROR(pack_iteration_where_clause_not_supported, none,
77867786
"lifetime dependence specifiers may only be used on result of "
77877787
"functions, methods, initializers",
77887788
())
7789-
7789+
ERROR(lifetime_dependence_invalid_return_type, none,
7790+
"lifetime dependence specifiers can only be specifier on ~Escapable "
7791+
"results", ())
7792+
ERROR(lifetime_dependence_missing_ownership_modifier, none,
7793+
"lifetime dependence can only be specified on parameters with ownership "
7794+
"modifiers (borrowing, consuming, inout)", ())
77907795
#define UNDEFINE_DIAGNOSTIC_MACROS
77917796
#include "DefineDiagnosticMacros.h"

lib/Sema/TypeCheckDecl.cpp

Lines changed: 41 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2577,8 +2577,8 @@ static Type validateParameterType(ParamDecl *decl) {
25772577
}
25782578

25792579
llvm::Optional<LifetimeDependenceInfo> validateLifetimeDependenceInfo(
2580-
LifetimeDependentReturnTypeRepr *lifetimeDependentRepr, Decl *decl,
2581-
bool allowIndex) {
2580+
LifetimeDependentReturnTypeRepr *lifetimeDependentRepr, Type resultTy,
2581+
Decl *decl, bool allowIndex) {
25822582
auto *afd = cast<AbstractFunctionDecl>(decl);
25832583
auto *dc = decl->getDeclContext();
25842584
auto &ctx = dc->getASTContext();
@@ -2592,26 +2592,35 @@ llvm::Optional<LifetimeDependenceInfo> validateLifetimeDependenceInfo(
25922592
auto loc = specifier.getLoc();
25932593
auto kind = specifier.getLifetimeDependenceKind();
25942594

2595-
// Sema cannot diagnose illegal lifetime dependence kinds when no
2596-
// ownership parameter modifiers are specified. They can be diagnosed
2597-
// later in SIL.
2598-
if (ownership != ValueOwnership::Default) {
2599-
if (kind == LifetimeDependenceKind::Borrow &&
2600-
ownership != ValueOwnership::Shared) {
2601-
diags.diagnose(loc, diag::lifetime_dependence_cannot_use_kind, "borrow",
2602-
getOwnershipSpelling(ownership));
2603-
return true;
2604-
} else if (kind == LifetimeDependenceKind::Mutate &&
2605-
ownership != ValueOwnership::InOut) {
2606-
diags.diagnose(loc, diag::lifetime_dependence_cannot_use_kind, "mutate",
2607-
getOwnershipSpelling(ownership));
2608-
return true;
2609-
} else if (kind == LifetimeDependenceKind::Consume &&
2610-
ownership != ValueOwnership::Owned) {
2611-
diags.diagnose(loc, diag::lifetime_dependence_cannot_use_kind,
2612-
"consume", getOwnershipSpelling(ownership));
2613-
return true;
2614-
}
2595+
/* TODO: Enable this
2596+
if (TypeChecker::conformsToKnownProtocol(resultTy,
2597+
InvertibleProtocolKind::Escapable,
2598+
dc->getParentModule())) {
2599+
diags.diagnose(loc, diag::lifetime_dependence_invalid_return_type);
2600+
return true;
2601+
}
2602+
*/
2603+
if (ownership == ValueOwnership::Default) {
2604+
diags.diagnose(loc, diag::lifetime_dependence_missing_ownership_modifier);
2605+
return true;
2606+
}
2607+
if (kind == LifetimeDependenceKind::Borrow &&
2608+
ownership != ValueOwnership::Shared) {
2609+
diags.diagnose(loc, diag::lifetime_dependence_cannot_use_kind, "borrow",
2610+
getOwnershipSpelling(ownership));
2611+
return true;
2612+
}
2613+
if (kind == LifetimeDependenceKind::Mutate &&
2614+
ownership != ValueOwnership::InOut) {
2615+
diags.diagnose(loc, diag::lifetime_dependence_cannot_use_kind, "mutate",
2616+
getOwnershipSpelling(ownership));
2617+
return true;
2618+
}
2619+
if (kind == LifetimeDependenceKind::Consume &&
2620+
ownership != ValueOwnership::Owned) {
2621+
diags.diagnose(loc, diag::lifetime_dependence_cannot_use_kind, "consume",
2622+
getOwnershipSpelling(ownership));
2623+
return true;
26152624
}
26162625
if (copyLifetimeParamIndices.test(paramIndexToSet) ||
26172626
borrowLifetimeParamIndices.test(paramIndexToSet)) {
@@ -2846,16 +2855,6 @@ InterfaceTypeRequest::evaluate(Evaluator &eval, ValueDecl *D) const {
28462855
}
28472856
}
28482857

2849-
auto *returnTypeRepr = AFD->getResultTypeRepr();
2850-
llvm::Optional<LifetimeDependenceInfo> lifetimeDependenceInfo;
2851-
if (returnTypeRepr) {
2852-
if (auto *lifetimeDependentRepr =
2853-
dyn_cast<LifetimeDependentReturnTypeRepr>(returnTypeRepr)) {
2854-
lifetimeDependenceInfo = validateLifetimeDependenceInfo(
2855-
lifetimeDependentRepr, D, /*allowIndex*/ false);
2856-
}
2857-
}
2858-
28592858
// Result
28602859
Type resultTy;
28612860
if (auto fn = dyn_cast<FuncDecl>(D)) {
@@ -2867,6 +2866,16 @@ InterfaceTypeRequest::evaluate(Evaluator &eval, ValueDecl *D) const {
28672866
resultTy = TupleType::getEmpty(AFD->getASTContext());
28682867
}
28692868

2869+
auto *returnTypeRepr = AFD->getResultTypeRepr();
2870+
llvm::Optional<LifetimeDependenceInfo> lifetimeDependenceInfo;
2871+
if (returnTypeRepr) {
2872+
if (auto *lifetimeDependentRepr =
2873+
dyn_cast<LifetimeDependentReturnTypeRepr>(returnTypeRepr)) {
2874+
lifetimeDependenceInfo = validateLifetimeDependenceInfo(
2875+
lifetimeDependentRepr, resultTy, D, /*allowIndex*/ false);
2876+
}
2877+
}
2878+
28702879
// (Args...) -> Result
28712880
Type funcTy;
28722881

lib/Sema/TypeCheckType.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4608,7 +4608,6 @@ TypeResolver::resolveResultDependsOnTypeRepr(ResultDependsOnTypeRepr *repr,
46084608

46094609
NeverNullType TypeResolver::resolveLifetimeDependentReturnTypeRepr(
46104610
LifetimeDependentReturnTypeRepr *repr, TypeResolutionOptions options) {
4611-
46124611
if (!options.is(TypeResolverContext::FunctionResult)) {
46134612
diagnoseInvalid(
46144613
repr, repr->getSpecifierLoc(),

test/Sema/explicit_lifetime_dependence_specifiers.swift

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ struct MutableBufferView : ~Escapable, ~Copyable {
1616
}
1717
}
1818

19+
class Klass {}
20+
21+
struct WrapperStruct {
22+
let k: Klass
23+
}
24+
25+
func invalidLifetimeDependenceOnEscapable(_ w: borrowing WrapperStruct) -> Klass {
26+
return w.k
27+
}
28+
1929
func incorrectSelfInvalidLifetimeDependence(_ x: borrowing BufferView) -> _borrow(self) BufferView { // expected-error{{invalid lifetime dependence specifier, self is valid in non-static methods only}}
2030
return BufferView(x.ptr)
2131
}
@@ -52,13 +62,11 @@ func borrowingParamInvalidLifetimeDependence2(_ x: borrowing BufferView) -> _mut
5262
return BufferView(x.ptr)
5363
}
5464

55-
// Sema cannot diagnose this
56-
func implicitBorrowingParamInvalidLifetimeDependence1(_ x: BufferView) -> _consume(x) BufferView {
65+
func implicitBorrowingParamInvalidLifetimeDependence1(_ x: BufferView) -> _consume(x) BufferView { // expected-error{{lifetime dependence can only be specified on parameters with ownership modifiers (borrowing, consuming, inout)}}
5766
return BufferView(x.ptr)
5867
}
5968

60-
// Sema cannot diagnose this
61-
func implicitBorrowingParamInvalidLifetimeDependence2(_ x: BufferView) -> _mutate(x) BufferView {
69+
func implicitBorrowingParamInvalidLifetimeDependence2(_ x: BufferView) -> _mutate(x) BufferView {// expected-error{{lifetime dependence can only be specified on parameters with ownership modifiers (borrowing, consuming, inout)}}
6270
return BufferView(x.ptr)
6371
}
6472

0 commit comments

Comments
 (0)