Skip to content

Commit b7b5a2a

Browse files
committed
[SE-0458] Enable unsafe expressions / attributes / for..in effects by default
With the acceptance of SE-0458, allow the use of unsafe expressions, the @safe and @unsafe attributes, and the `unsafe` effect on the for..in loop in all Swift code. Introduce the `-strict-memory-safety` flag detailed in the proposal to enable strict memory safety checking. This enables a new class of feature, an optional feature (that is *not* upcoming or experimental), and which can be detected via `hasFeature(StrictMemorySafety)`.
1 parent 71e23ac commit b7b5a2a

37 files changed

+112
-119
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8165,9 +8165,6 @@ NOTE(sending_function_result_with_sending_param_note, none,
81658165
//------------------------------------------------------------------------------
81668166
// MARK: Strict Safety Diagnostics
81678167
//------------------------------------------------------------------------------
8168-
ERROR(unsafe_attr_disabled,none,
8169-
"attribute requires '-enable-experimental-feature AllowUnsafeAttribute'", ())
8170-
81718168
NOTE(note_reference_to_unsafe_decl,none,
81728169
"%select{reference|call}0 to unsafe %kind1",
81738170
(bool, const ValueDecl *))

include/swift/Basic/Features.def

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@
4848
// for features that can be assumed to be available in any Swift compiler that
4949
// will be used to process the textual interface files produced by this
5050
// Swift compiler.
51+
//
52+
// OPTIONAL_LANGUAGE_FEATURE is the same as LANGUAGE_FEATURE, but describes
53+
// accepted features that can be enabled independently of language version and
54+
// are not scheduled to be enabled in some specific language version. Examples
55+
// of optional language features include strict memory safety checking (SE-0458)
56+
// and Embedded Swift.
5157
//===----------------------------------------------------------------------===//
5258

5359
#ifndef LANGUAGE_FEATURE
@@ -89,6 +95,11 @@
8995
LANGUAGE_FEATURE(FeatureName, SENumber, Description)
9096
#endif
9197

98+
#ifndef OPTIONAL_LANGUAGE_FEATURE
99+
# define OPTIONAL_LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
100+
LANGUAGE_FEATURE(FeatureName, SENumber, Description)
101+
#endif
102+
92103
// A feature that's both conditionally-suppressible and experimental.
93104
// Delegates to whichever the includer defines.
94105
#ifndef CONDITIONALLY_SUPPRESSIBLE_EXPERIMENTAL_FEATURE
@@ -203,6 +214,7 @@ LANGUAGE_FEATURE(IsolatedAny2, 431, "@isolated(any) function types")
203214
LANGUAGE_FEATURE(ObjCImplementation, 436, "@objc @implementation extensions")
204215
LANGUAGE_FEATURE(NonescapableTypes, 446, "Nonescapable types")
205216
LANGUAGE_FEATURE(BuiltinEmplaceTypedThrows, 0, "Builtin.emplace typed throws")
217+
SUPPRESSIBLE_LANGUAGE_FEATURE(MemorySafetyAttributes, 458, "@unsafe attribute")
206218

207219
// Swift 6
208220
UPCOMING_FEATURE(ConciseMagicFile, 274, 6)
@@ -226,6 +238,14 @@ UPCOMING_FEATURE(ExistentialAny, 335, 7)
226238
UPCOMING_FEATURE(InternalImportsByDefault, 409, 7)
227239
UPCOMING_FEATURE(MemberImportVisibility, 444, 7)
228240

241+
// Optional language features / modes
242+
243+
/// Diagnose uses of language constructs and APIs that can violate memory
244+
/// safety.
245+
OPTIONAL_LANGUAGE_FEATURE(StrictMemorySafety, 458, "Strict memory safety")
246+
247+
// Experimental features
248+
229249
EXPERIMENTAL_FEATURE(StaticAssert, false)
230250
EXPERIMENTAL_FEATURE(NamedOpaqueTypes, false)
231251
EXPERIMENTAL_FEATURE(FlowSensitiveConcurrencyCaptures, false)
@@ -396,12 +416,6 @@ EXPERIMENTAL_FEATURE(Extern, true)
396416
// Enable trailing comma for comma-separated lists.
397417
EXPERIMENTAL_FEATURE(TrailingComma, false)
398418

399-
/// Allow the @unsafe attribute.
400-
SUPPRESSIBLE_EXPERIMENTAL_FEATURE(AllowUnsafeAttribute, true)
401-
402-
/// Warn on use of unsafe constructs.
403-
EXPERIMENTAL_FEATURE(WarnUnsafe, true)
404-
405419
// Import bounds safety and lifetime attributes from interop headers to
406420
// generate Swift wrappers with safe pointer types.
407421
EXPERIMENTAL_FEATURE(SafeInteropWrappers, false)
@@ -463,6 +477,7 @@ EXPERIMENTAL_FEATURE(IsolatedConformances, true)
463477
#undef EXPERIMENTAL_FEATURE
464478
#undef UPCOMING_FEATURE
465479
#undef BASELINE_LANGUAGE_FEATURE
480+
#undef OPTIONAL_LANGUAGE_FEATURE
466481
#undef CONDITIONALLY_SUPPRESSIBLE_EXPERIMENTAL_FEATURE
467482
#undef CONDITIONALLY_SUPPRESSIBLE_LANGUAGE_FEATURE
468483
#undef SUPPRESSIBLE_EXPERIMENTAL_FEATURE

include/swift/Option/Options.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,11 @@ def disable_upcoming_feature : Separate<["-"], "disable-upcoming-feature">,
10051005
HelpText<"Disable a feature that will be introduced in an upcoming language "
10061006
"version">;
10071007

1008+
def strict_memory_safety : Flag<["-"], "strict-memory-safety">,
1009+
Flags<[FrontendOption, ModuleInterfaceOptionIgnorable,
1010+
SwiftAPIDigesterOption, SwiftSynthesizeInterfaceOption]>,
1011+
HelpText<"Enable strict memory safety checking">;
1012+
10081013
def Rpass_EQ : Joined<["-"], "Rpass=">,
10091014
Flags<[FrontendOption]>,
10101015
HelpText<"Report performed transformations by optimization passes whose "

lib/AST/ASTPrinter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3214,9 +3214,10 @@ struct ExcludeAttrRAII {
32143214
}
32153215

32163216
static void
3217-
suppressingFeatureAllowUnsafeAttribute(PrintOptions &options,
3217+
suppressingFeatureMemorySafetyAttributes(PrintOptions &options,
32183218
llvm::function_ref<void()> action) {
32193219
ExcludeAttrRAII scope(options.ExcludeAttrList, DeclAttrKind::Unsafe);
3220+
ExcludeAttrRAII scope2(options.ExcludeAttrList, DeclAttrKind::Safe);
32203221
action();
32213222
}
32223223

lib/AST/FeatureSet.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -330,10 +330,6 @@ UNINTERESTING_FEATURE(ReinitializeConsumeInMultiBlockDefer)
330330
UNINTERESTING_FEATURE(SE427NoInferenceOnExtension)
331331
UNINTERESTING_FEATURE(TrailingComma)
332332

333-
static bool usesFeatureAllowUnsafeAttribute(Decl *decl) {
334-
return decl->getAttrs().hasAttribute<UnsafeAttr>();
335-
}
336-
337333
static ABIAttr *getABIAttr(Decl *decl) {
338334
if (auto pbd = dyn_cast<PatternBindingDecl>(decl))
339335
for (auto i : range(pbd->getNumPatternEntries()))
@@ -353,7 +349,12 @@ static bool usesFeatureIsolatedConformances(Decl *decl) {
353349
return false;
354350
}
355351

356-
UNINTERESTING_FEATURE(WarnUnsafe)
352+
static bool usesFeatureMemorySafetyAttributes(Decl *decl) {
353+
return decl->getAttrs().hasAttribute<SafeAttr>() ||
354+
decl->getAttrs().hasAttribute<UnsafeAttr>();
355+
}
356+
357+
UNINTERESTING_FEATURE(StrictMemorySafety)
357358
UNINTERESTING_FEATURE(SafeInteropWrappers)
358359
UNINTERESTING_FEATURE(AssumeResilientCxxTypes)
359360
UNINTERESTING_FEATURE(CoroutineAccessorsUnwindOnCallerError)

lib/ASTGen/Sources/ASTGen/SourceFile.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ extension Parser.ExperimentalFeatures {
7777
mapFeature(.CoroutineAccessors, to: .coroutineAccessors)
7878
mapFeature(.ValueGenerics, to: .valueGenerics)
7979
mapFeature(.ABIAttribute, to: .abiAttribute)
80-
mapFeature(.WarnUnsafe, to: .unsafeExpression)
8180
}
8281
}
8382

lib/Basic/LangOptions.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ LangOptions::LangOptions() {
3838
Features.insert(Feature::FeatureName);
3939
#define UPCOMING_FEATURE(FeatureName, SENumber, Version)
4040
#define EXPERIMENTAL_FEATURE(FeatureName, AvailableInProd)
41+
#define OPTIONAL_LANGUAGE_FEATURE(FeatureName, SENumber, Description)
4142
#include "swift/Basic/Features.def"
4243

4344
// Special case: remove macro support if the compiler wasn't built with a
@@ -636,6 +637,8 @@ bool swift::isFeatureAvailableInProduction(Feature feature) {
636637
return true;
637638
#define EXPERIMENTAL_FEATURE(FeatureName, AvailableInProd) \
638639
case Feature::FeatureName: return AvailableInProd;
640+
#define OPTIONAL_LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
641+
LANGUAGE_FEATURE(FeatureName, SENumber, Description)
639642
#include "swift/Basic/Features.def"
640643
}
641644
llvm_unreachable("covered switch");
@@ -655,6 +658,7 @@ std::optional<Feature> swift::getExperimentalFeature(llvm::StringRef name) {
655658
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description)
656659
#define EXPERIMENTAL_FEATURE(FeatureName, AvailableInProd) \
657660
.Case(#FeatureName, Feature::FeatureName)
661+
#define OPTIONAL_LANGUAGE_FEATURE(FeatureName, SENumber, Description)
658662
#include "swift/Basic/Features.def"
659663
.Default(std::nullopt);
660664
}
@@ -664,6 +668,7 @@ std::optional<unsigned> swift::getFeatureLanguageVersion(Feature feature) {
664668
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description)
665669
#define UPCOMING_FEATURE(FeatureName, SENumber, Version) \
666670
case Feature::FeatureName: return Version;
671+
#define OPTIONAL_LANGUAGE_FEATURE(FeatureName, SENumber, Description)
667672
#include "swift/Basic/Features.def"
668673
default:
669674
return std::nullopt;
@@ -677,6 +682,8 @@ bool swift::includeInModuleInterface(Feature feature) {
677682
return true;
678683
#define EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE(FeatureName, AvailableInProd) \
679684
case Feature::FeatureName: return false;
685+
#define OPTIONAL_LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
686+
LANGUAGE_FEATURE(FeatureName, SENumber, Description)
680687
#include "swift/Basic/Features.def"
681688
}
682689
llvm_unreachable("covered switch");

lib/ClangImporter/ImportDecl.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2039,7 +2039,7 @@ namespace {
20392039
fd->getAttrs().add(new (Impl.SwiftContext)
20402040
UnsafeNonEscapableResultAttr(/*Implicit=*/true));
20412041
if (Impl.SwiftContext.LangOpts.hasFeature(
2042-
Feature::AllowUnsafeAttribute))
2042+
Feature::StrictMemorySafety))
20432043
fd->getAttrs().add(new (Impl.SwiftContext)
20442044
UnsafeAttr(/*Implicit=*/true));
20452045
}
@@ -2201,7 +2201,7 @@ namespace {
22012201
// We have to do this after populating ImportedDecls to avoid importing
22022202
// the same multiple times.
22032203
if (Impl.SwiftContext.LangOpts.hasFeature(
2204-
Feature::AllowUnsafeAttribute)) {
2204+
Feature::StrictMemorySafety)) {
22052205
if (const auto *ctsd =
22062206
dyn_cast<clang::ClassTemplateSpecializationDecl>(decl)) {
22072207
for (auto arg : ctsd->getTemplateArgs().asArray()) {
@@ -4178,13 +4178,13 @@ namespace {
41784178
LifetimeDependenceInfoRequest{result},
41794179
Impl.SwiftContext.AllocateCopy(lifetimeDependencies));
41804180
}
4181-
if (ASTContext.LangOpts.hasFeature(Feature::AllowUnsafeAttribute)) {
4181+
if (ASTContext.LangOpts.hasFeature(Feature::StrictMemorySafety)) {
41824182
for (auto [idx, param] : llvm::enumerate(decl->parameters())) {
41834183
if (swiftParams->get(idx)->getInterfaceType()->isEscapable())
41844184
continue;
41854185
if (param->hasAttr<clang::NoEscapeAttr>() || paramHasAnnotation[idx])
41864186
continue;
4187-
// We have a nonescapabe parameter that does not have its lifetime
4187+
// We have a nonescapable parameter that does not have its lifetime
41884188
// annotated nor is it marked noescape.
41894189
auto attr = new (ASTContext) UnsafeAttr(/*implicit=*/true);
41904190
result->getAttrs().add(attr);
@@ -8722,8 +8722,6 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
87228722
}
87238723

87248724
if (swiftAttr->getAttribute() == "unsafe") {
8725-
if (!SwiftContext.LangOpts.hasFeature(Feature::AllowUnsafeAttribute))
8726-
continue;
87278725
seenUnsafe = true;
87288726
continue;
87298727
}

lib/Driver/ToolChains.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI,
282282
options::OPT_disable_experimental_feature,
283283
options::OPT_enable_upcoming_feature,
284284
options::OPT_disable_upcoming_feature});
285+
inputArgs.AddLastArg(arguments, options::OPT_strict_memory_safety);
285286
inputArgs.AddLastArg(arguments, options::OPT_warn_implicit_overrides);
286287
inputArgs.AddLastArg(arguments, options::OPT_typo_correction_limit);
287288
inputArgs.AddLastArg(arguments, options::OPT_enable_app_extension);

lib/Frontend/CompilerInvocation.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,9 @@ static bool ParseEnabledFeatureArgs(LangOptions &Opts, ArgList &Args,
878878

879879
Opts.enableFeature(Feature::LayoutPrespecialization);
880880

881+
if (Args.hasArg(OPT_strict_memory_safety))
882+
Opts.enableFeature(Feature::StrictMemorySafety);
883+
881884
return HadError;
882885
}
883886

@@ -3909,7 +3912,7 @@ bool CompilerInvocation::parseArgs(
39093912
}
39103913
}
39113914

3912-
if (LangOpts.hasFeature(Feature::WarnUnsafe)) {
3915+
if (LangOpts.hasFeature(Feature::StrictMemorySafety)) {
39133916
if (SILOpts.RemoveRuntimeAsserts ||
39143917
SILOpts.AssertConfig == SILOptions::Unchecked) {
39153918
Diags.diagnose(SourceLoc(),

0 commit comments

Comments
 (0)