Skip to content

Commit bcf77c4

Browse files
committed
Diagnose references to unowned(unsafe) variables as unsafe uses
1 parent 683dcfc commit bcf77c4

File tree

5 files changed

+42
-19
lines changed

5 files changed

+42
-19
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8084,6 +8084,8 @@ NOTE(note_reference_to_unsafe_typed_decl,none,
80848084
NOTE(note_reference_to_nonisolated_unsafe,none,
80858085
"reference to nonisolated(unsafe) %kind0 is unsafe in concurrently-executing code",
80868086
(const ValueDecl *))
8087+
NOTE(note_reference_unowned_unsafe,none,
8088+
"reference to unowned(unsafe) %kind0 is unsafe", (const ValueDecl *))
80878089

80888090
GROUPED_WARNING(override_safe_withunsafe,Unsafe,none,
80898091
"override of safe %0 with unsafe %0", (DescriptiveDeclKind))
@@ -8095,8 +8097,8 @@ GROUPED_WARNING(type_witness_unsafe,Unsafe,none,
80958097
(Type, DeclName))
80968098
GROUPED_WARNING(unchecked_conformance_is_unsafe,Unsafe,none,
80978099
"@unchecked conformance involves unsafe code", ())
8098-
GROUPED_WARNING(unowned_unsafe_is_unsafe,Unsafe,none,
8099-
"unowned(unsafe) involves unsafe code", ())
8100+
GROUPED_WARNING(reference_unowned_unsafe,Unsafe,none,
8101+
"reference to unowned(unsafe) %kind0 is unsafe", (const ValueDecl *))
81008102
GROUPED_WARNING(reference_to_nonisolated_unsafe,Unsafe,none,
81018103
"reference to nonisolated(unsafe) %kind0 is unsafe in concurrently-executing code",
81028104
(const ValueDecl *))

lib/Sema/TypeCheckAttr.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
#include "swift/AST/SwiftNameTranslation.h"
4343
#include "swift/AST/TypeCheckRequests.h"
4444
#include "swift/AST/Types.h"
45-
#include "swift/AST/UnsafeUse.h"
4645
#include "swift/Basic/Assertions.h"
4746
#include "swift/Parse/Lexer.h"
4847
#include "swift/Parse/ParseDeclName.h"
@@ -4976,15 +4975,6 @@ Type TypeChecker::checkReferenceOwnershipAttr(VarDecl *var, Type type,
49764975
}
49774976
}
49784977

4979-
// unowned(unsafe) is unsafe (duh).
4980-
if (ownershipKind == ReferenceOwnership::Unmanaged &&
4981-
ctx.LangOpts.hasFeature(Feature::WarnUnsafe) &&
4982-
!var->allowsUnsafe()) {
4983-
diagnoseUnsafeUse(
4984-
UnsafeUse::forUnownedUnsafe(var, attr->getLocation(),
4985-
var->getDeclContext()));
4986-
}
4987-
49884978
if (attr->isInvalid())
49894979
return type;
49904980

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4229,6 +4229,19 @@ diagnoseDeclUnsafe(const ValueDecl *D, SourceRange R,
42294229
valueDecl, R.Start, Where.getDeclContext()));
42304230
return;
42314231
}
4232+
4233+
if (auto var = dyn_cast<VarDecl>(valueDecl)) {
4234+
// unowned(unsafe) is unsafe (duh).
4235+
if (auto ownershipAttr =
4236+
var->getAttrs().getAttribute<ReferenceOwnershipAttr>()) {
4237+
if (ownershipAttr->get() == ReferenceOwnership::Unmanaged) {
4238+
diagnoseUnsafeUse(
4239+
UnsafeUse::forUnownedUnsafe(var, R.Start,
4240+
Where.getDeclContext()));
4241+
return;
4242+
}
4243+
}
4244+
}
42324245
}
42334246
}
42344247

lib/Sema/TypeCheckUnsafe.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,13 @@ static bool isUnsafeUseInDefinition(const UnsafeUse &use) {
3939
case UnsafeUse::Witness:
4040
case UnsafeUse::TypeWitness:
4141
case UnsafeUse::UnsafeConformance:
42-
case UnsafeUse::UnownedUnsafe:
4342
// Never part of the definition. These are always part of the interface.
4443
return false;
4544

4645
case UnsafeUse::ReferenceToUnsafe:
4746
case UnsafeUse::CallToUnsafe:
4847
case UnsafeUse::NonisolatedUnsafe:
48+
case UnsafeUse::UnownedUnsafe:
4949
return enclosingContextForUnsafe(use).second;
5050
}
5151
}
@@ -100,7 +100,8 @@ void swift::diagnoseUnsafeUse(const UnsafeUse &use, bool asNote) {
100100
// same declaration.
101101
if (use.getKind() == UnsafeUse::ReferenceToUnsafe ||
102102
use.getKind() == UnsafeUse::CallToUnsafe ||
103-
use.getKind() == UnsafeUse::NonisolatedUnsafe) {
103+
use.getKind() == UnsafeUse::NonisolatedUnsafe ||
104+
use.getKind() == UnsafeUse::UnownedUnsafe) {
104105
auto [enclosingDecl, _] = enclosingContextForUnsafe(
105106
use.getLocation(), use.getDeclContext());
106107
if (enclosingDecl) {
@@ -164,9 +165,16 @@ void swift::diagnoseUnsafeUse(const UnsafeUse &use, bool asNote) {
164165

165166
case UnsafeUse::UnownedUnsafe: {
166167
auto var = cast<VarDecl>(use.getDecl());
167-
var->diagnose(diag::unowned_unsafe_is_unsafe);
168-
var->diagnose(diag::make_enclosing_context_unsafe, var)
169-
.fixItInsert(var->getAttributeInsertionLoc(false), "@unsafe ");
168+
ASTContext &ctx = var->getASTContext();
169+
ctx.Diags.diagnose(
170+
use.getLocation(),
171+
asNote ? diag::note_reference_unowned_unsafe
172+
: diag::reference_unowned_unsafe,
173+
var);
174+
if (!asNote) {
175+
var->diagnose(diag::make_enclosing_context_unsafe, var)
176+
.fixItInsert(var->getAttributeInsertionLoc(false), "@unsafe ");
177+
}
170178
return;
171179
}
172180

test/Unsafe/unsafe.swift

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,18 @@ class Sub: Super { // expected-note{{make class 'Sub' @unsafe to allow unsafe ov
5454
// -----------------------------------------------------------------------
5555
struct SuperHolder {
5656
unowned var s1: Super
57-
unowned(unsafe) var s2: Super // expected-warning{{unowned(unsafe) involves unsafe code}}
58-
// expected-note@-1{{make property 's2' @unsafe to indicate that its use is not memory-safe}}{{3-3=@unsafe }}
57+
unowned(unsafe) var s2: Super
58+
59+
// expected-warning@+1{{instance method 'getSuper2' involves unsafe code; use '@safe(unchecked)' to assert that the code is memory-safe}}
60+
func getSuper2() -> Super {
61+
return s2 // expected-note{{reference to unowned(unsafe) property 's2' is unsafe}}
62+
}
63+
64+
// FIXME: We should be able to identify this as being inside the function
65+
// expected-warning@+1{{instance method 'getSuper2b' involves unsafe code; use '@unsafe' to indicate that its use is not memory-safe}}
66+
func getSuper2b() -> Super {
67+
s2 // expected-note{{reference to unowned(unsafe) property 's2' is unsafe}}
68+
}
5969
}
6070

6171
// -----------------------------------------------------------------------

0 commit comments

Comments
 (0)