Skip to content

Commit 54c38cb

Browse files
committed
Fix and generalize the printing of suppressible features,
and make `@_unsafeInheritExecutor` a suppressible feature. Some language features are required in order to parse a declaration correctly, but some can safely be ignored. For the latter, we'd like the module interface to simply contain the declaration twice, once with the feature and once without. Some basic support for that was already added for the SpecializeAttributeWithAvailability feature, but it didn't interact correctly with required features that might be checked in the same `#if` clause (it simply introduced an `#else`), and it wasn't really set up to allow multiple features to be handled this way. There were also a few other places that weren't updated to handle this, presumably because they never coincided with a `@_specialize` attribute. Introduce the concept of a suppressible feature, which is anything that the ASTPrinter can modify the current PrintOptions in order to suppress. Restructure the printing of compatibility checks so that we can print the body multiple times with different settings. Print required feature checks in an outer `#if...#endif`, then perform a separate `#if...#else...#endif` within if we have suppressible features. If there are multiple suppressible features, check for the most recent first, on the assumption that it will imply the rest; then perform subsequent checks with an `#elsif` clause. This should be a far more solid foundation on which to build compatibility checks in the future. `@_unsafeInheritExecutor` needs to be suppressible because it's been added to some rather important existing APIs. Simply suppressing the entire decl will effectively block old tools from using a new SDK to build many existing projects (if they've adopted `async`). Dropping the attribute changes the semantics of these functions, but only if the compiler features the SE-0338 scheduling change; this is a very narrow window of main-branch development builds of the tools, none of which were officially released.
1 parent aa44e12 commit 54c38cb

File tree

7 files changed

+362
-124
lines changed

7 files changed

+362
-124
lines changed

include/swift/AST/ASTPrinter.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -385,10 +385,14 @@ void getInheritedForPrinting(
385385

386386
StringRef getAccessorKindString(AccessorKind value);
387387

388-
bool printCompatibilityFeatureChecksPre(ASTPrinter &printer, Decl *decl);
389-
void printCompatibilityFeatureChecksPost(
390-
ASTPrinter &printer,
391-
llvm::function_ref<void()> printElse = []() -> void {});
388+
/// Call the given function nested appropriately within #if checks
389+
/// for the compiler features that it uses. Note that printBody
390+
/// may be called multiple times if the declaration uses suppressible
391+
/// features.
392+
bool printWithCompatibilityFeatureChecks(ASTPrinter &printer,
393+
PrintOptions &options,
394+
Decl *decl,
395+
llvm::function_ref<void()> printBody);
392396

393397
} // namespace swift
394398

include/swift/Basic/Feature.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,31 @@ enum class Feature {
2626
#include "swift/Basic/Features.def"
2727
};
2828

29+
constexpr unsigned numFeatures() {
30+
enum Features {
31+
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description, Option) \
32+
FeatureName,
33+
#include "swift/Basic/Features.def"
34+
NumFeatures
35+
};
36+
return NumFeatures;
37+
}
38+
39+
/// Determine whether the given feature is suppressible.
40+
bool isSuppressibleFeature(Feature feature);
41+
2942
/// Determine the in-source name of the given feature.
3043
llvm::StringRef getFeatureName(Feature feature);
3144

45+
/// Determine whether the first feature is more recent (and thus implies
46+
/// the existence of) the second feature. Only meaningful for suppressible
47+
/// features.
48+
inline bool featureImpliesFeature(Feature feature, Feature implied) {
49+
// Suppressible features are expected to be listed in order of
50+
// addition in Features.def.
51+
return (unsigned) feature < (unsigned) implied;
52+
}
53+
3254
}
3355

3456
#endif // SWIFT_BASIC_FEATURES_H

include/swift/Basic/Features.def

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,26 @@
2828
// Option: either a reference to a language option in the form
2929
// "langOpts.<option name>" or "true" to indicate that it's always
3030
// enabled.
31+
//
32+
// Suppressible language features can be suppressed when printing
33+
// an interface without having to suppress the entire declaration they're
34+
// contained within. The declaration will be emitted multiple times,
35+
// each with a subset of the suppressible features. To avoid combinatoric
36+
// re-emission, we assume a linear history: later features in this file
37+
// imply the existence of earlier features. (This only needs to apply to
38+
// suppressible features.)
39+
//
3140
//===----------------------------------------------------------------------===//
3241

3342
#ifndef LANGUAGE_FEATURE
3443
# error define LANGUAGE_FEATURE before including Features.def
3544
#endif
3645

46+
#ifndef SUPPRESSIBLE_LANGUAGE_FEATURE
47+
#define SUPPRESSIBLE_LANGUAGE_FEATURE(FeatureName, SENumber, Description, Option) \
48+
LANGUAGE_FEATURE(FeatureName, SENumber, Description, Option)
49+
#endif
50+
3751
LANGUAGE_FEATURE(StaticAssert, 0, "#assert", langOpts.EnableExperimentalStaticAssert)
3852
LANGUAGE_FEATURE(AsyncAwait, 296, "async/await", true)
3953
LANGUAGE_FEATURE(EffectfulProp, 310, "Effectful properties", true)
@@ -57,8 +71,9 @@ LANGUAGE_FEATURE(BuiltinCreateAsyncTaskInGroup, 0, "MainActor executor building
5771
LANGUAGE_FEATURE(BuiltinMove, 0, "Builtin.move()", true)
5872
LANGUAGE_FEATURE(BuiltinCopy, 0, "Builtin.copy()", true)
5973
LANGUAGE_FEATURE(BuiltinStackAlloc, 0, "Builtin.stackAlloc", true)
60-
LANGUAGE_FEATURE(SpecializeAttributeWithAvailability, 0, "@_specialize attribute with availability", true)
74+
SUPPRESSIBLE_LANGUAGE_FEATURE(SpecializeAttributeWithAvailability, 0, "@_specialize attribute with availability", true)
6175
LANGUAGE_FEATURE(BuiltinAssumeAlignment, 0, "Builtin.assumeAlignment", true)
62-
LANGUAGE_FEATURE(UnsafeInheritExecutor, 0, "@_unsafeInheritExecutor", true)
76+
SUPPRESSIBLE_LANGUAGE_FEATURE(UnsafeInheritExecutor, 0, "@_unsafeInheritExecutor", true)
6377

78+
#undef SUPPRESSIBLE_LANGUAGE_FEATURE
6479
#undef LANGUAGE_FEATURE

0 commit comments

Comments
 (0)