Files
swift-mirror/include/swift/AST/PropertyWrappers.h
Hamish Knight ccd32eb452 NFC: Remove ClangModuleLoader.h include from ExtInfo.h
This was unnecessarily pulling in a whole bunch
of Clang headers when all was needed was a
forward declaration.
2023-10-09 20:29:03 +01:00

294 lines
9.6 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//===--- PropertyWrappers.h - Property Wrapper ASTs -----------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines helper types for property wrappers.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_AST_PROPERTY_WRAPPERS_H
#define SWIFT_AST_PROPERTY_WRAPPERS_H
namespace llvm {
class raw_ostream;
}
namespace swift {
class ConstructorDecl;
class CustomAttr;
class Expr;
class VarDecl;
class OpaqueValueExpr;
class PropertyWrapperValuePlaceholderExpr;
class SubscriptDecl;
/// The kind of property initializer to look for
enum class PropertyWrapperInitKind {
/// An initial-value initializer (i.e. `init(initialValue:)`), which is
/// deprecated.
InitialValue,
/// An wrapped-value initializer (i.e. `init(wrappedValue:)`)
WrappedValue,
/// A projected-value initializer (i.e. `init(projectedValue:)`)
ProjectedValue,
/// An default-value initializer (i.e. `init()` or `init(defaultArgs...)`)
Default
};
/// Information about an applied property wrapper, including the backing wrapper type
/// and the initialization kind.
struct AppliedPropertyWrapper {
Type wrapperType;
PropertyWrapperInitKind initKind;
};
/// Describes a property wrapper type.
struct PropertyWrapperTypeInfo {
/// The property through which access that uses this wrapper type is
/// directed.
VarDecl *valueVar = nullptr;
/// Whether there is an init(wrappedValue:) that will be called when the
/// initializing the property wrapper type from a value of the property type.
enum {
NoWrappedValueInit = 0,
HasWrappedValueInit,
HasInitialValueInit
} wrappedValueInit = NoWrappedValueInit;
/// The initializer that will be called to default-initialize a
/// value with an attached property wrapper.
enum {
NoDefaultValueInit = 0,
HasDefaultValueInit
} defaultInit = NoDefaultValueInit;
bool hasProjectedValueInit = false;
/// The property through which the projection value ($foo) will be accessed.
///
/// This property is optional. If present, a computed property for `$foo`
/// will be created that redirects to this property.
VarDecl *projectedValueVar = nullptr;
/// The static subscript through which the access of instance properties
/// of classes can be directed (instead of wrappedValue), providing the
/// ability to reason about the enclosing "self".
SubscriptDecl *enclosingInstanceWrappedSubscript = nullptr;
/// The static subscript through which the access of instance properties
/// of classes can be directed (instead of projectedValue), providing the
/// ability to reason about the enclosing "self".
SubscriptDecl *enclosingInstanceProjectedSubscript = nullptr;
/// Forces that the property wrapper must be declared on a static, or
/// globalonce supportedproperty.
bool requireNoEnclosingInstance = false;
///
/// Whether this is a valid property wrapper.
bool isValid() const {
return valueVar != nullptr;
}
explicit operator bool() const { return isValid(); }
friend bool operator==(const PropertyWrapperTypeInfo &lhs,
const PropertyWrapperTypeInfo &rhs) {
return lhs.valueVar == rhs.valueVar &&
lhs.wrappedValueInit == rhs.wrappedValueInit;
}
};
/// Describes the mutability of the operations on a property wrapper or composition.
struct PropertyWrapperMutability {
enum Value: uint8_t {
Nonmutating = 0,
Mutating = 1,
DoesntExist = 2,
};
Value Getter, Setter;
/// Get the mutability of a composed access chained after accessing a wrapper with `this`
/// getter and setter mutability.
Value composeWith(Value x) {
switch (x) {
case DoesntExist:
return DoesntExist;
// If an operation is nonmutating, then its input relies only on the
// mutating-ness of the outer wrapper's get operation.
case Nonmutating:
return Getter;
// If it's mutating, then it relies
// on a) the outer wrapper having a setter to exist at all, and b) the
// mutating-ness of either the getter or setter, since we need both to
// perform a writeback cycle.
case Mutating:
if (Setter == DoesntExist) {
return DoesntExist;
}
return std::max(Getter, Setter);
}
llvm_unreachable("Unhandled Value in switch");
}
bool operator==(PropertyWrapperMutability other) const {
return Getter == other.Getter && Setter == other.Setter;
}
};
void simple_display(llvm::raw_ostream &os, PropertyWrapperMutability m);
/// Describes whether the reference to a property wrapper instance used for
/// accessing a wrapped property should be an l-value or not.
struct PropertyWrapperLValueness {
llvm::SmallVector<bool, 4> isLValueForGetAccess;
llvm::SmallVector<bool, 4> isLValueForSetAccess;
PropertyWrapperLValueness(unsigned numWrappers)
: isLValueForGetAccess(numWrappers), isLValueForSetAccess(numWrappers) {}
bool operator==(PropertyWrapperLValueness other) const {
return (isLValueForGetAccess == other.isLValueForGetAccess &&
isLValueForSetAccess == other.isLValueForSetAccess);
}
};
void simple_display(llvm::raw_ostream &os, PropertyWrapperLValueness l);
/// Given the initializer for a property with an attached property wrapper,
/// dig out the wrapped value placeholder for the original initialization
/// expression.
///
/// \note The wrapped value placeholder is injected for properties that can
/// be initialized out-of-line using an expression of the wrapped property type.
PropertyWrapperValuePlaceholderExpr *findWrappedValuePlaceholder(Expr *init);
/// The synthesized auxiliary declarations for a wrapped property, including the
/// backing property wrapper, the projected value variable, and if the wrapped
/// declaration is a parameter, the local wrapped value variable.
struct PropertyWrapperAuxiliaryVariables {
/// The backing property.
VarDecl *backingVar = nullptr;
/// The synthesized projection property, if any. When present, this takes the name
/// of the original wrapped property prefixed with \c $
VarDecl *projectionVar = nullptr;
/// The synthesized local wrapped value property, which shadows the original wrapped
/// declaration if it is a parameter.
VarDecl *localWrappedValueVar = nullptr;
PropertyWrapperAuxiliaryVariables() {}
PropertyWrapperAuxiliaryVariables(VarDecl *backingVar, VarDecl *projectionVar,
VarDecl *localWrappedValueVar = nullptr)
: backingVar(backingVar), projectionVar(projectionVar),
localWrappedValueVar(localWrappedValueVar) {}
/// Whether this is a valid property wrapper.
bool isValid() const {
return backingVar != nullptr;
}
explicit operator bool() const { return isValid(); }
};
/// Describes how to initialize the backing storage of a property with
/// an attached wrapper.
class PropertyWrapperInitializerInfo {
struct {
/// An expression that initializes the backing property from a value of
/// the original property's type via \c init(wrappedValue:) if supported
/// by the wrapper type.
Expr *expr = nullptr;
/// When \c expr is not null, the opaque value that is used as
/// a placeholder for a value of the original property's type.
PropertyWrapperValuePlaceholderExpr *placeholder = nullptr;
} wrappedValueInit;
struct {
/// An expression that initializes the backing property from a value of
/// the synthesized projection type via \c init(projectedValue:) if
/// supported by the wrapper type.
Expr *expr = nullptr;
/// When \c expr is not null, the opaque value that is used as
/// a placeholder for a value of the projection type.
PropertyWrapperValuePlaceholderExpr *placeholder = nullptr;
} projectedValueInit;
public:
PropertyWrapperInitializerInfo() { }
PropertyWrapperInitializerInfo(Expr *wrappedValueInitExpr,
Expr *projectedValueInitExpr) {
wrappedValueInit.expr = wrappedValueInitExpr;
if (wrappedValueInitExpr) {
wrappedValueInit.placeholder = findWrappedValuePlaceholder(wrappedValueInitExpr);
}
projectedValueInit.expr = projectedValueInitExpr;
if (projectedValueInitExpr) {
projectedValueInit.placeholder = findWrappedValuePlaceholder(projectedValueInitExpr);
}
}
bool hasInitFromWrappedValue() const {
return wrappedValueInit.expr != nullptr;
}
Expr *getInitFromWrappedValue() const {
return wrappedValueInit.expr;
}
PropertyWrapperValuePlaceholderExpr *getWrappedValuePlaceholder() {
return wrappedValueInit.placeholder;
}
bool hasInitFromProjectedValue() const {
return projectedValueInit.expr != nullptr;
}
Expr *getInitFromProjectedValue() const {
return projectedValueInit.expr;
}
PropertyWrapperValuePlaceholderExpr *getProjectedValuePlaceholder() {
return projectedValueInit.placeholder;
}
bool hasSynthesizedInitializers() const {
return hasInitFromWrappedValue() || hasInitFromProjectedValue();
}
};
void simple_display(
llvm::raw_ostream &out,
const PropertyWrapperTypeInfo &propertyWrapper);
void simple_display(
llvm::raw_ostream &out,
const PropertyWrapperInitializerInfo &initInfo);
void simple_display(
llvm::raw_ostream &out,
const PropertyWrapperAuxiliaryVariables &auxiliaryVars);
} // end namespace swift
#endif // SWIFT_AST_PROPERTY_WRAPPERS_H