mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
LifetimeDependence: implement strict type checking
Rework the type checker to support completely checking lifetime dependence
requirements. Don't let anything through without the feature being enabled and
complete annotation or inference.
First, prevent lifetime dependencies from sneaking into source that does not
enable LifetimeDependence. This is essential for controlling the scope of the
feature.
Fixing this is disruptive because, ever since `~Escapable` was introduced we
have been declaring empty non-Escapable types without enabling
LifetimeDependence. Such as:
struct Implicit_Init_Nonescapable : ~Escapable {}
Fixes: rdar://145979187 ([nonescapable] diagnose implicit non-Escapable
initializers as an error unless LifetimeDependence is enabled)
Various forms of unsupported 'inout' dependencies are now also caught by the
type checker.
Second, disable lifetime dependency inferrence except in unambiguous cases and
some implicitly generated cases.
Fixes: rdar://131176898 ([nonescapable] missing diagnostic for incorrectly inferred inherited dependence)
This is important to avoid source compatibility problems as inference rules
change. They will change as the proposal goes through review.
This fixes various latent missing dependency bugs.
Disable experimental lifetime dependence inference. Unambiguous lifetime
dependency candidates will still be inferred by default, without any frontend
options. Ambiguous candidates will, however, no longer be inferred unless
-Xfrontend -enable_experimental_lifetime_dependence_inference is enabled.
This all has to be done without breaking existing .swiftinterface files. So
backward compatibility logic is maintained.
Examples of inference rules that are no longer enabled by default:
1. do not infer a dependency on non-Escapable 'self' for methods with more than
zero parameters:
extension NE: ~Escapable {
/*@lifetime(self)*/ // ERROR: 'self' not inferred
func method<Arg>(arg: Arg) -> NE { ... }
}
2. Never infer a 'copy' dependency kind for explicit functions
extension NE: ~Escapable {
@lifetime(self) // ERROR: 'copy' not inferred
func method() -> NE { ... }
@lifetime(self) // ERROR: 'copy' not inferred
var property : NE { /*@lifetime(self: newValue)*/ set { ... } }
}
This commit is contained in:
@@ -227,32 +227,6 @@ class LifetimeDependenceInfo {
|
||||
|
||||
unsigned targetIndex;
|
||||
|
||||
static LifetimeDependenceInfo getForIndex(AbstractFunctionDecl *afd,
|
||||
unsigned targetIndex,
|
||||
unsigned sourceIndex,
|
||||
LifetimeDependenceKind kind);
|
||||
|
||||
/// Builds LifetimeDependenceInfo from @lifetime attribute
|
||||
static std::optional<ArrayRef<LifetimeDependenceInfo>>
|
||||
fromLifetimeAttribute(AbstractFunctionDecl *afd);
|
||||
|
||||
/// Infer LifetimeDependenceInfo on result
|
||||
static std::optional<LifetimeDependenceInfo> infer(AbstractFunctionDecl *afd);
|
||||
|
||||
/// Infer LifetimeDependenceInfo on setter
|
||||
static std::optional<LifetimeDependenceInfo>
|
||||
inferSetter(AbstractFunctionDecl *afd);
|
||||
|
||||
/// Infer LifetimeDependenceInfo on mutating self
|
||||
static std::optional<LifetimeDependenceInfo>
|
||||
inferMutatingSelf(AbstractFunctionDecl *afd);
|
||||
|
||||
/// Builds LifetimeDependenceInfo from SIL function type
|
||||
static std::optional<LifetimeDependenceInfo>
|
||||
fromDependsOn(LifetimeDependentTypeRepr *lifetimeDependentRepr,
|
||||
unsigned targetIndex, ArrayRef<SILParameterInfo> params,
|
||||
DeclContext *dc);
|
||||
|
||||
public:
|
||||
LifetimeDependenceInfo(IndexSubset *inheritLifetimeParamIndices,
|
||||
IndexSubset *scopeLifetimeParamIndices,
|
||||
@@ -350,8 +324,8 @@ public:
|
||||
|
||||
/// Builds LifetimeDependenceInfo from SIL
|
||||
static std::optional<llvm::ArrayRef<LifetimeDependenceInfo>>
|
||||
get(FunctionTypeRepr *funcRepr, ArrayRef<SILParameterInfo> params,
|
||||
ArrayRef<SILResultInfo> results, DeclContext *dc);
|
||||
getFromSIL(FunctionTypeRepr *funcRepr, ArrayRef<SILParameterInfo> params,
|
||||
ArrayRef<SILResultInfo> results, DeclContext *dc);
|
||||
|
||||
bool operator==(const LifetimeDependenceInfo &other) const {
|
||||
return this->isImmortal() == other.isImmortal() &&
|
||||
|
||||
@@ -598,7 +598,7 @@ namespace swift {
|
||||
bool EnableRequirementMachineOpaqueArchetypes = false;
|
||||
|
||||
/// Enable implicit lifetime dependence for ~Escapable return types.
|
||||
bool EnableExperimentalLifetimeDependenceInference = true;
|
||||
bool EnableExperimentalLifetimeDependenceInference = false;
|
||||
|
||||
/// Skips decls that cannot be referenced externally.
|
||||
bool SkipNonExportableDecls = false;
|
||||
|
||||
Reference in New Issue
Block a user