mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Strict memory safety] Only diagnose unsafe types in the canonical type
Typealiases involving unsafe types that resolve to safe types should not be diagnosed.
This commit is contained in:
@@ -1216,12 +1216,14 @@ ExplicitSafety Decl::getExplicitSafety() const {
|
||||
ExplicitSafety::Unspecified);
|
||||
}
|
||||
|
||||
// Inference: Check the enclosing context.
|
||||
if (auto enclosingDC = getDeclContext()) {
|
||||
// Is this an extension with @safe or @unsafe on it?
|
||||
if (auto ext = dyn_cast<ExtensionDecl>(enclosingDC)) {
|
||||
if (auto extSafety = getExplicitSafetyFromAttrs(ext))
|
||||
return *extSafety;
|
||||
// Inference: Check the enclosing context, unless this is a type.
|
||||
if (!isa<TypeDecl>(this)) {
|
||||
if (auto enclosingDC = getDeclContext()) {
|
||||
// Is this an extension with @safe or @unsafe on it?
|
||||
if (auto ext = dyn_cast<ExtensionDecl>(enclosingDC)) {
|
||||
if (auto extSafety = getExplicitSafetyFromAttrs(ext))
|
||||
return *extSafety;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -372,21 +372,28 @@ void swift::diagnoseUnsafeType(ASTContext &ctx, SourceLoc loc, Type type,
|
||||
if (!ctx.LangOpts.hasFeature(Feature::StrictMemorySafety))
|
||||
return;
|
||||
|
||||
if (!type->isUnsafe() && !type->getCanonicalType()->isUnsafe())
|
||||
if (!type->getCanonicalType()->isUnsafe())
|
||||
return;
|
||||
|
||||
// Look for a specific @unsafe nominal type.
|
||||
Type specificType;
|
||||
type.findIf([&specificType](Type type) {
|
||||
if (auto typeDecl = type->getAnyNominal()) {
|
||||
if (typeDecl->getExplicitSafety() == ExplicitSafety::Unsafe) {
|
||||
specificType = type;
|
||||
return false;
|
||||
// Look for a specific @unsafe nominal type along the way.
|
||||
auto findSpecificUnsafeType = [](Type type) {
|
||||
Type specificType;
|
||||
(void)type.findIf([&specificType](Type type) {
|
||||
if (auto typeDecl = type->getAnyNominal()) {
|
||||
if (typeDecl->getExplicitSafety() == ExplicitSafety::Unsafe) {
|
||||
specificType = type;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
return false;
|
||||
});
|
||||
return specificType;
|
||||
};
|
||||
|
||||
Type specificType = findSpecificUnsafeType(type);
|
||||
if (!specificType)
|
||||
specificType = findSpecificUnsafeType(type->getCanonicalType());
|
||||
|
||||
diagnose(specificType ? specificType : type);
|
||||
}
|
||||
|
||||
@@ -271,3 +271,16 @@ struct UnsafeWrapTest {
|
||||
|
||||
@safe @unsafe
|
||||
struct ConfusedStruct { } // expected-error{{struct 'ConfusedStruct' cannot be both @safe and @unsafe}}
|
||||
|
||||
@unsafe
|
||||
struct UnsafeContainingUnspecified {
|
||||
typealias A = Int
|
||||
|
||||
func getA() -> A { 0 }
|
||||
}
|
||||
|
||||
|
||||
@unsafe func f(x: UnsafeContainingUnspecified) {
|
||||
let a = unsafe x.getA()
|
||||
_ = a
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user