Skip to content

Commit eedbb9d

Browse files
authored
Merge pull request swiftlang#34272 from hborla/property-wrapper-parameters
2 parents b73df9d + b3d54b6 commit eedbb9d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+2089
-290
lines changed

docs/ABI/Mangling.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ Entities
325325
entity-spec ::= 'fA' INDEX // default argument N+1 generator
326326
entity-spec ::= 'fi' // non-local variable initializer
327327
entity-spec ::= 'fP' // property wrapper backing initializer
328+
entity-spec ::= 'fW' // property wrapper init from projected value
328329
entity-spec ::= 'fD' // deallocating destructor; untyped
329330
entity-spec ::= 'fd' // non-deallocating destructor; untyped
330331
entity-spec ::= 'fE' // ivar destroyer; untyped

include/swift/AST/ASTMangler.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ class ASTMangler : public Mangler {
135135
std::string mangleInitializerEntity(const VarDecl *var, SymbolKind SKind);
136136
std::string mangleBackingInitializerEntity(const VarDecl *var,
137137
SymbolKind SKind = SymbolKind::Default);
138+
std::string mangleInitFromProjectedValueEntity(const VarDecl *var,
139+
SymbolKind SKind = SymbolKind::Default);
138140

139141
std::string mangleNominalType(const NominalTypeDecl *decl);
140142

@@ -405,6 +407,7 @@ class ASTMangler : public Mangler {
405407

406408
void appendInitializerEntity(const VarDecl *var);
407409
void appendBackingInitializerEntity(const VarDecl *var);
410+
void appendInitFromProjectedValueEntity(const VarDecl *var);
408411

409412
CanType getDeclTypeForMangling(const ValueDecl *decl,
410413
GenericSignature &genericSig,

include/swift/AST/ASTWalker.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,10 @@ class ASTWalker {
215215
/// TapExpr.
216216
virtual bool shouldWalkIntoTapExpression() { return true; }
217217

218+
/// This method configures whether the the walker should visit the underlying
219+
/// value of a property wrapper placeholder.
220+
virtual bool shouldWalkIntoPropertyWrapperPlaceholderValue() { return true; }
221+
218222
/// This method configures whether the walker should visit the capture
219223
/// initializer expressions within a capture list directly, rather than
220224
/// walking the declarations.

include/swift/AST/AnyFunctionRef.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "swift/Basic/LLVM.h"
1919
#include "swift/AST/Decl.h"
2020
#include "swift/AST/Expr.h"
21+
#include "swift/AST/ParameterList.h"
2122
#include "swift/AST/Types.h"
2223
#include "llvm/ADT/DenseMap.h"
2324
#include "llvm/ADT/PointerUnion.h"
@@ -103,6 +104,18 @@ class AnyFunctionRef {
103104
return TheFunction.get<AbstractClosureExpr *>()->getSingleExpressionBody();
104105
}
105106

107+
ParameterList *getParameters() const {
108+
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>())
109+
return AFD->getParameters();
110+
return TheFunction.get<AbstractClosureExpr *>()->getParameters();
111+
}
112+
113+
bool hasPropertyWrapperParameters() const {
114+
return llvm::any_of(*getParameters(), [](const ParamDecl *param) {
115+
return param->hasAttachedPropertyWrapper();
116+
});
117+
}
118+
106119
Type getType() const {
107120
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>())
108121
return AFD->getInterfaceType();

include/swift/AST/Attr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1689,6 +1689,7 @@ class CustomAttr final : public DeclAttribute,
16891689
unsigned getNumArguments() const { return numArgLabels; }
16901690
bool hasArgumentLabelLocs() const { return hasArgLabelLocs; }
16911691

1692+
TypeExpr *getTypeExpr() const { return typeExpr; }
16921693
TypeRepr *getTypeRepr() const;
16931694
Type getType() const;
16941695

include/swift/AST/Decl.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4917,7 +4917,10 @@ class VarDecl : public AbstractStorageDecl {
49174917

49184918
/// Whether this property has any attached property wrappers.
49194919
bool hasAttachedPropertyWrapper() const;
4920-
4920+
4921+
/// Whether this var has an implicit property wrapper attribute.
4922+
bool hasImplicitPropertyWrapper() const;
4923+
49214924
/// Whether all of the attached property wrappers have an init(wrappedValue:)
49224925
/// initializer.
49234926
bool allAttachedPropertyWrappersHaveWrappedValueInit() const;
@@ -4978,6 +4981,10 @@ class VarDecl : public AbstractStorageDecl {
49784981
/// property wrapper with a \c projectedValue .
49794982
VarDecl *getPropertyWrapperProjectionVar() const;
49804983

4984+
/// Retrieve the local wrapped value var for for a parameter that has
4985+
/// an attached property wrapper.
4986+
VarDecl *getPropertyWrapperWrappedValueVar() const;
4987+
49814988
/// Visit all auxiliary declarations to this VarDecl.
49824989
///
49834990
/// An auxiliary declaration is a declaration synthesized by the compiler to support

include/swift/AST/DiagnosticsSema.def

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4109,11 +4109,11 @@ ERROR(throw_in_nonexhaustive_catch,none,
41094109

41104110
ERROR(throwing_call_in_illegal_context,none,
41114111
"call can throw, but errors cannot be thrown out of "
4112-
"%select{<<ERROR>>|a default argument|a property initializer|a global variable initializer|an enum case raw value|a catch pattern|a catch guard expression|a defer body}0",
4112+
"%select{<<ERROR>>|a default argument|a property wrapper initializer|a property initializer|a global variable initializer|an enum case raw value|a catch pattern|a catch guard expression|a defer body}0",
41134113
(unsigned))
41144114
ERROR(throw_in_illegal_context,none,
41154115
"errors cannot be thrown out of "
4116-
"%select{<<ERROR>>|a default argument|a property initializer|a global variable initializer|an enum case raw value|a catch pattern|a catch guard expression|a defer body}0",
4116+
"%select{<<ERROR>>|a default argument|a property wrapper initializer|a property initializer|a global variable initializer|an enum case raw value|a catch pattern|a catch guard expression|a defer body}0",
41174117
(unsigned))
41184118

41194119
ERROR(throwing_operator_without_try,none,
@@ -4151,11 +4151,11 @@ WARNING(no_async_in_await,none,
41514151
"no calls to 'async' functions occur within 'await' expression", ())
41524152
ERROR(async_call_in_illegal_context,none,
41534153
"'async' call cannot occur in "
4154-
"%select{<<ERROR>>|a default argument|a property initializer|a global variable initializer|an enum case raw value|a catch pattern|a catch guard expression|a defer body}0",
4154+
"%select{<<ERROR>>|a default argument|a property wrapper initializer|a property initializer|a global variable initializer|an enum case raw value|a catch pattern|a catch guard expression|a defer body}0",
41554155
(unsigned))
41564156
ERROR(await_in_illegal_context,none,
41574157
"'await' operation cannot occur in "
4158-
"%select{<<ERROR>>|a default argument|a property initializer|a global variable initializer|an enum case raw value|a catch pattern|a catch guard expression|a defer body}0",
4158+
"%select{<<ERROR>>|a default argument|a property wrapper initializer|a property initializer|a global variable initializer|an enum case raw value|a catch pattern|a catch guard expression|a defer body}0",
41594159
(unsigned))
41604160
ERROR(async_in_nonasync_function,none,
41614161
"%select{'async'|'await'|'async let'}0 in "
@@ -4197,7 +4197,7 @@ ERROR(async_let_without_await,none,
41974197
"reference to async let %0 is not marked with 'await'", (DeclName))
41984198
ERROR(async_let_in_illegal_context,none,
41994199
"async let %0 cannot be referenced in "
4200-
"%select{<<ERROR>>|a default argument|a property initializer|a global variable initializer|an enum case raw value|a catch pattern|a catch guard expression|a defer body}1",
4200+
"%select{<<ERROR>>|a default argument|a property wrapper initializer|a property initializer|a global variable initializer|an enum case raw value|a catch pattern|a catch guard expression|a defer body}1",
42014201
(DeclName, unsigned))
42024202

42034203
ERROR(asynchandler_non_func,none,
@@ -5482,8 +5482,27 @@ ERROR(property_wrapper_dynamic_self_type, none,
54825482
ERROR(property_wrapper_attribute_not_on_property, none,
54835483
"property wrapper attribute %0 can only be applied to a property",
54845484
(Identifier))
5485+
ERROR(property_wrapper_param_not_supported,none,
5486+
"property wrapper attribute on parameter not yet supported on %0",
5487+
(DescriptiveDeclKind))
54855488
NOTE(property_wrapper_declared_here,none,
54865489
"property wrapper type %0 declared here", (Identifier))
5490+
ERROR(property_wrapper_param_no_projection,none,
5491+
"cannot use property wrapper projection parameter; "
5492+
"wrapper %0 does not have a 'projectedValue'", (Type))
5493+
ERROR(property_wrapper_param_no_wrapper,none,
5494+
"cannot use property wrapper projection argument; "
5495+
"parameter does not have an attached property wrapper",
5496+
())
5497+
ERROR(property_wrapper_param_projection_invalid,none,
5498+
"cannot use property wrapper projection argument; "
5499+
"pass wrapped value type %0 instead", (Type))
5500+
ERROR(property_wrapper_param_mutating,none,
5501+
"property wrapper applied to parameter must have a nonmutating "
5502+
"'wrappedValue' getter", ())
5503+
ERROR(invalid_implicit_property_wrapper,none,
5504+
"inferred projection type %0 is not a property wrapper",
5505+
(Type))
54875506

54885507
ERROR(property_wrapper_mutating_get_composed_to_get_only,none,
54895508
"property wrapper %0 with a mutating getter cannot be composed inside "
@@ -5505,9 +5524,9 @@ ERROR(property_with_wrapper_conflict_attribute,none,
55055524
ERROR(property_wrapper_not_single_var, none,
55065525
"property wrapper can only apply to a single variable", ())
55075526
ERROR(property_with_wrapper_in_bad_context,none,
5508-
"%select{|non-static |non-static }1property %0 declared inside "
5527+
"%select{|non-static|non-static}1 %2 %0 declared inside "
55095528
"%select{a protocol|an extension|an enum}1 cannot have a wrapper",
5510-
(Identifier, int))
5529+
(Identifier, int, DescriptiveDeclKind))
55115530
ERROR(property_with_wrapper_overrides,none,
55125531
"property %0 with attached wrapper cannot override another property",
55135532
(Identifier))

include/swift/AST/Expr.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4228,6 +4228,62 @@ class PropertyWrapperValuePlaceholderExpr : public Expr {
42284228
}
42294229
};
42304230

4231+
/// An implicit applied property wrapper expression.
4232+
class AppliedPropertyWrapperExpr final : public Expr {
4233+
public:
4234+
enum class ValueKind {
4235+
WrappedValue,
4236+
ProjectedValue
4237+
};
4238+
4239+
private:
4240+
/// The concrete callee which owns the property wrapper.
4241+
ConcreteDeclRef Callee;
4242+
4243+
/// The owning declaration.
4244+
const ParamDecl *Param;
4245+
4246+
/// The source location of the argument list.
4247+
SourceLoc Loc;
4248+
4249+
/// The value to which the property wrapper is applied for initialization.
4250+
Expr *Value;
4251+
4252+
/// The kind of value that the property wrapper is applied to.
4253+
ValueKind Kind;
4254+
4255+
AppliedPropertyWrapperExpr(ConcreteDeclRef callee, const ParamDecl *param, SourceLoc loc,
4256+
Type Ty, Expr *value, ValueKind kind)
4257+
: Expr(ExprKind::AppliedPropertyWrapper, /*Implicit=*/true, Ty),
4258+
Callee(callee), Param(param), Loc(loc), Value(value), Kind(kind) {}
4259+
4260+
public:
4261+
static AppliedPropertyWrapperExpr *
4262+
create(ASTContext &ctx, ConcreteDeclRef callee, const ParamDecl *param, SourceLoc loc,
4263+
Type Ty, Expr *value, ValueKind kind);
4264+
4265+
SourceRange getSourceRange() const { return Loc; }
4266+
4267+
ConcreteDeclRef getCallee() { return Callee; }
4268+
4269+
/// Returns the parameter declaration with the attached property wrapper.
4270+
const ParamDecl *getParamDecl() const { return Param; };
4271+
4272+
/// Returns the value that the property wrapper is applied to.
4273+
Expr *getValue() { return Value; }
4274+
4275+
/// Sets the value that the property wrapper is applied to.
4276+
void setValue(Expr *value) { Value = value; }
4277+
4278+
/// Returns the kind of value, between wrapped value and projected
4279+
/// value, the property wrapper is applied to.
4280+
ValueKind getValueKind() const { return Kind; }
4281+
4282+
static bool classof(const Expr *E) {
4283+
return E->getKind() == ExprKind::AppliedPropertyWrapper;
4284+
}
4285+
};
4286+
42314287
/// An expression referring to a default argument left unspecified at the
42324288
/// call site.
42334289
///

include/swift/AST/ExprNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ EXPR(DynamicType, Expr)
131131
EXPR(RebindSelfInConstructor, Expr)
132132
EXPR(OpaqueValue, Expr)
133133
EXPR(PropertyWrapperValuePlaceholder, Expr)
134+
EXPR(AppliedPropertyWrapper, Expr)
134135
EXPR(DefaultArgument, Expr)
135136
EXPR(BindOptional, Expr)
136137
EXPR(OptionalEvaluation, Expr)

include/swift/AST/Identifier.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ class Identifier {
164164
bool isEditorPlaceholder() const {
165165
return !empty() && isEditorPlaceholder(str());
166166
}
167+
168+
bool hasDollarPrefix() const {
169+
return str().startswith("$") && !(getLength() == 1);
170+
}
167171

168172
const void *getAsOpaquePointer() const {
169173
return static_cast<const void *>(Pointer);
@@ -324,6 +328,10 @@ class DeclBaseName {
324328
return !isSpecial() && getIdentifier().isEditorPlaceholder();
325329
}
326330

331+
bool hasDollarPrefix() const {
332+
return getIdentifier().hasDollarPrefix();
333+
}
334+
327335
/// A representation of the name to be displayed to users. May be ambiguous
328336
/// between identifiers and special names.
329337
StringRef userFacingName() const {

0 commit comments

Comments
 (0)