Skip to content

Commit 4c5ba0c

Browse files
committed
[Strict memory safety] Only diagnose unsafe types in the canonical type
Typealiases involving unsafe types that resolve to safe types should not be diagnosed. (cherry picked from commit 0405f61)
1 parent 7d77c61 commit 4c5ba0c

File tree

3 files changed

+39
-17
lines changed

3 files changed

+39
-17
lines changed

lib/AST/Decl.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,12 +1212,14 @@ ExplicitSafety Decl::getExplicitSafety() const {
12121212
ExplicitSafety::Unspecified);
12131213
}
12141214

1215-
// Inference: Check the enclosing context.
1216-
if (auto enclosingDC = getDeclContext()) {
1217-
// Is this an extension with @safe or @unsafe on it?
1218-
if (auto ext = dyn_cast<ExtensionDecl>(enclosingDC)) {
1219-
if (auto extSafety = getExplicitSafetyFromAttrs(ext))
1220-
return *extSafety;
1215+
// Inference: Check the enclosing context, unless this is a type.
1216+
if (!isa<TypeDecl>(this)) {
1217+
if (auto enclosingDC = getDeclContext()) {
1218+
// Is this an extension with @safe or @unsafe on it?
1219+
if (auto ext = dyn_cast<ExtensionDecl>(enclosingDC)) {
1220+
if (auto extSafety = getExplicitSafetyFromAttrs(ext))
1221+
return *extSafety;
1222+
}
12211223
}
12221224
}
12231225

lib/Sema/TypeCheckUnsafe.cpp

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -375,21 +375,28 @@ void swift::diagnoseUnsafeType(ASTContext &ctx, SourceLoc loc, Type type,
375375
if (!ctx.LangOpts.hasFeature(Feature::StrictMemorySafety))
376376
return;
377377

378-
if (!type->isUnsafe() && !type->getCanonicalType()->isUnsafe())
378+
if (!type->getCanonicalType()->isUnsafe())
379379
return;
380380

381-
// Look for a specific @unsafe nominal type.
382-
Type specificType;
383-
type.findIf([&specificType](Type type) {
384-
if (auto typeDecl = type->getAnyNominal()) {
385-
if (typeDecl->getExplicitSafety() == ExplicitSafety::Unsafe) {
386-
specificType = type;
387-
return false;
381+
// Look for a specific @unsafe nominal type along the way.
382+
auto findSpecificUnsafeType = [](Type type) {
383+
Type specificType;
384+
(void)type.findIf([&specificType](Type type) {
385+
if (auto typeDecl = type->getAnyNominal()) {
386+
if (typeDecl->getExplicitSafety() == ExplicitSafety::Unsafe) {
387+
specificType = type;
388+
return false;
389+
}
388390
}
389-
}
390391

391-
return false;
392-
});
392+
return false;
393+
});
394+
return specificType;
395+
};
396+
397+
Type specificType = findSpecificUnsafeType(type);
398+
if (!specificType)
399+
specificType = findSpecificUnsafeType(type->getCanonicalType());
393400

394401
diagnose(specificType ? specificType : type);
395402
}

test/Unsafe/safe.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,3 +271,16 @@ struct UnsafeWrapTest {
271271

272272
@safe @unsafe
273273
struct ConfusedStruct { } // expected-error{{struct 'ConfusedStruct' cannot be both @safe and @unsafe}}
274+
275+
@unsafe
276+
struct UnsafeContainingUnspecified {
277+
typealias A = Int
278+
279+
func getA() -> A { 0 }
280+
}
281+
282+
283+
@unsafe func f(x: UnsafeContainingUnspecified) {
284+
let a = unsafe x.getA()
285+
_ = a
286+
}

0 commit comments

Comments
 (0)