Skip to content

Commit 0405f61

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.
1 parent 235242e commit 0405f61

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
@@ -1216,12 +1216,14 @@ ExplicitSafety Decl::getExplicitSafety() const {
12161216
ExplicitSafety::Unspecified);
12171217
}
12181218

1219-
// Inference: Check the enclosing context.
1220-
if (auto enclosingDC = getDeclContext()) {
1221-
// Is this an extension with @safe or @unsafe on it?
1222-
if (auto ext = dyn_cast<ExtensionDecl>(enclosingDC)) {
1223-
if (auto extSafety = getExplicitSafetyFromAttrs(ext))
1224-
return *extSafety;
1219+
// Inference: Check the enclosing context, unless this is a type.
1220+
if (!isa<TypeDecl>(this)) {
1221+
if (auto enclosingDC = getDeclContext()) {
1222+
// Is this an extension with @safe or @unsafe on it?
1223+
if (auto ext = dyn_cast<ExtensionDecl>(enclosingDC)) {
1224+
if (auto extSafety = getExplicitSafetyFromAttrs(ext))
1225+
return *extSafety;
1226+
}
12251227
}
12261228
}
12271229

lib/Sema/TypeCheckUnsafe.cpp

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

375-
if (!type->isUnsafe() && !type->getCanonicalType()->isUnsafe())
375+
if (!type->getCanonicalType()->isUnsafe())
376376
return;
377377

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

388-
return false;
389-
});
389+
return false;
390+
});
391+
return specificType;
392+
};
393+
394+
Type specificType = findSpecificUnsafeType(type);
395+
if (!specificType)
396+
specificType = findSpecificUnsafeType(type->getCanonicalType());
390397

391398
diagnose(specificType ? specificType : type);
392399
}

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)