Skip to content

Commit b821c8d

Browse files
committed
[Sema] Add an implicit applied property wrapper expression and a new
dedicated initializer context for this expressions.
1 parent 648c575 commit b821c8d

File tree

14 files changed

+197
-7
lines changed

14 files changed

+197
-7
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 5 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,

include/swift/AST/Expr.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4228,6 +4228,57 @@ 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 owning declaration.
4241+
const ParamDecl *Param;
4242+
4243+
/// The source location of the argument list.
4244+
SourceLoc Loc;
4245+
4246+
/// The value to which the property wrapper is applied for initialization.
4247+
Expr *Value;
4248+
4249+
/// The kind of value that the property wrapper is applied to.
4250+
ValueKind Kind;
4251+
4252+
AppliedPropertyWrapperExpr(const ParamDecl *param, SourceLoc loc,
4253+
Type Ty, Expr *value, ValueKind kind)
4254+
: Expr(ExprKind::AppliedPropertyWrapper, /*Implicit=*/true, Ty),
4255+
Param(param), Loc(loc), Value(value), Kind(kind) {}
4256+
4257+
public:
4258+
static AppliedPropertyWrapperExpr *
4259+
create(ASTContext &ctx, const ParamDecl *param, SourceLoc loc,
4260+
Type Ty, Expr *value, ValueKind kind);
4261+
4262+
SourceRange getSourceRange() const { return Loc; }
4263+
4264+
/// Returns the parameter declaration with the attached property wrapper.
4265+
const ParamDecl *getParamDecl() const { return Param; };
4266+
4267+
/// Returns the value that the property wrapper is applied to.
4268+
Expr *getValue() { return Value; }
4269+
4270+
/// Sets the value that the property wrapper is applied to.
4271+
void setValue(Expr *value) { Value = value; }
4272+
4273+
/// Returns the kind of value, between wrapped value and projected
4274+
/// value, the property wrapper is applied to.
4275+
ValueKind getValueKind() const { return Kind; }
4276+
4277+
static bool classof(const Expr *E) {
4278+
return E->getKind() == ExprKind::AppliedPropertyWrapper;
4279+
}
4280+
};
4281+
42314282
/// An expression referring to a default argument left unspecified at the
42324283
/// call site.
42334284
///

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/Initializer.h

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ enum class InitializerKind : uint8_t {
3333

3434
/// A function's default argument expression.
3535
DefaultArgument,
36+
37+
/// A property wrapper initialization expression.
38+
PropertyWrapper,
3639
};
3740

3841
/// An Initializer is a kind of DeclContext used for expressions that
@@ -41,9 +44,9 @@ enum class InitializerKind : uint8_t {
4144
/// Generally, Initializers are created lazily, as most initializers
4245
/// don't really require DeclContexts.
4346
class Initializer : public DeclContext {
44-
unsigned Kind : 1;
47+
unsigned Kind : 2;
4548
protected:
46-
unsigned SpareBits : 31;
49+
unsigned SpareBits : 30;
4750

4851
Initializer(InitializerKind kind, DeclContext *parent)
4952
: DeclContext(DeclContextKind::Initializer, parent),
@@ -195,6 +198,39 @@ class SerializedDefaultArgumentInitializer : public SerializedLocalDeclContext {
195198
return false;
196199
}
197200
};
201+
202+
/// A property wrapper initialization expression. The parent context is the
203+
/// function or closure which owns the property wrapper.
204+
class PropertyWrapperInitializer : public Initializer {
205+
public:
206+
enum class Kind {
207+
WrappedValue,
208+
ProjectedValue
209+
};
210+
211+
private:
212+
ParamDecl *param;
213+
Kind kind;
214+
215+
public:
216+
explicit PropertyWrapperInitializer(DeclContext *parent, ParamDecl *param, Kind kind)
217+
: Initializer(InitializerKind::PropertyWrapper, parent),
218+
param(param), kind(kind) {}
219+
220+
ParamDecl *getParam() const { return param; }
221+
222+
Kind getKind() const { return kind; }
223+
224+
static bool classof(const DeclContext *DC) {
225+
if (auto init = dyn_cast<Initializer>(DC))
226+
return classof(init);
227+
return false;
228+
}
229+
230+
static bool classof(const Initializer *I) {
231+
return I->getInitializerKind() == InitializerKind::PropertyWrapper;
232+
}
233+
};
198234

199235
} // end namespace swift
200236

lib/AST/ASTDumper.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,6 +1385,9 @@ void swift::printContext(raw_ostream &os, DeclContext *dc) {
13851385
case InitializerKind::DefaultArgument:
13861386
os << "default argument initializer";
13871387
break;
1388+
case InitializerKind::PropertyWrapper:
1389+
os << "property wrapper initializer";
1390+
break;
13881391
}
13891392
break;
13901393

@@ -2585,6 +2588,12 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
25852588
PrintWithColorRAII(OS, ParenthesisColor) << ')';
25862589
}
25872590

2591+
void visitAppliedPropertyWrapperExpr(AppliedPropertyWrapperExpr *E) {
2592+
printCommon(E, "applied_property_wrapper_expr");
2593+
printRec(E->getValue());
2594+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
2595+
}
2596+
25882597
void visitDefaultArgumentExpr(DefaultArgumentExpr *E) {
25892598
printCommon(E, "default_argument_expr");
25902599
OS << " default_args_owner=";

lib/AST/ASTMangler.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2116,6 +2116,19 @@ void ASTMangler::appendContext(const DeclContext *ctx, StringRef useModuleName)
21162116
}
21172117
return;
21182118
}
2119+
2120+
case InitializerKind::PropertyWrapper: {
2121+
auto wrapperInit = cast<PropertyWrapperInitializer>(ctx);
2122+
switch (wrapperInit->getKind()) {
2123+
case PropertyWrapperInitializer::Kind::WrappedValue:
2124+
appendBackingInitializerEntity(wrapperInit->getParam());
2125+
break;
2126+
case PropertyWrapperInitializer::Kind::ProjectedValue:
2127+
appendInitFromProjectedValueEntity(wrapperInit->getParam());
2128+
break;
2129+
}
2130+
return;
2131+
}
21192132
}
21202133
llvm_unreachable("bad initializer kind");
21212134

lib/AST/ASTWalker.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,16 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
514514
return E;
515515
}
516516

517+
Expr *visitAppliedPropertyWrapperExpr(AppliedPropertyWrapperExpr *E) {
518+
if (auto *newValue = doIt(E->getValue())) {
519+
E->setValue(newValue);
520+
} else {
521+
return nullptr;
522+
}
523+
524+
return E;
525+
}
526+
517527
Expr *visitDefaultArgumentExpr(DefaultArgumentExpr *E) { return E; }
518528

519529
Expr *visitInterpolatedStringLiteralExpr(InterpolatedStringLiteralExpr *E) {

lib/AST/DeclContext.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,19 @@ unsigned DeclContext::printContext(raw_ostream &OS, const unsigned indent,
677677
OS << " DefaultArgument index=" << init->getIndex();
678678
break;
679679
}
680+
case InitializerKind::PropertyWrapper: {
681+
auto init = cast<PropertyWrapperInitializer>(this);
682+
OS << "PropertyWrapper 0x" << (void*)init->getParam() << ", kind=";
683+
switch (init->getKind()) {
684+
case PropertyWrapperInitializer::Kind::WrappedValue:
685+
OS << "wrappedValue";
686+
break;
687+
case PropertyWrapperInitializer::Kind::ProjectedValue:
688+
OS << "projectedValue";
689+
break;
690+
}
691+
break;
692+
}
680693
}
681694
break;
682695

lib/AST/Expr.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ ConcreteDeclRef Expr::getReferencedDecl(bool stopAtParenExpr) const {
320320

321321
NO_REFERENCE(OpaqueValue);
322322
NO_REFERENCE(PropertyWrapperValuePlaceholder);
323+
NO_REFERENCE(AppliedPropertyWrapper);
323324
NO_REFERENCE(DefaultArgument);
324325

325326
PASS_THROUGH_REFERENCE(BindOptional, getSubExpr);
@@ -633,6 +634,7 @@ bool Expr::canAppendPostfixExpression(bool appendingPostfixOperator) const {
633634
case ExprKind::RebindSelfInConstructor:
634635
case ExprKind::OpaqueValue:
635636
case ExprKind::PropertyWrapperValuePlaceholder:
637+
case ExprKind::AppliedPropertyWrapper:
636638
case ExprKind::DefaultArgument:
637639
case ExprKind::BindOptional:
638640
case ExprKind::OptionalEvaluation:
@@ -1507,6 +1509,13 @@ PropertyWrapperValuePlaceholderExpr::create(ASTContext &ctx, SourceRange range,
15071509
range, ty, placeholder, wrappedValue, isAutoClosure);
15081510
}
15091511

1512+
AppliedPropertyWrapperExpr *
1513+
AppliedPropertyWrapperExpr::create(ASTContext &ctx, const ParamDecl *param,
1514+
SourceLoc loc, Type Ty, Expr *value,
1515+
AppliedPropertyWrapperExpr::ValueKind kind) {
1516+
return new (ctx) AppliedPropertyWrapperExpr(param, loc, Ty, value, kind);
1517+
}
1518+
15101519
const ParamDecl *DefaultArgumentExpr::getParamDecl() const {
15111520
return getParameterAt(DefaultArgsOwner.getDecl(), ParamIndex);
15121521
}

lib/IDE/ExprContextAnalysis.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,6 +1097,15 @@ class ExprContextAnalyzer {
10971097
recordPossibleType(AFD->mapTypeIntoContext(param->getInterfaceType()));
10981098
break;
10991099
}
1100+
case InitializerKind::PropertyWrapper: {
1101+
auto initDC = cast<PropertyWrapperInitializer>(DC);
1102+
auto AFD = dyn_cast<AbstractFunctionDecl>(initDC->getParent());
1103+
if (!AFD)
1104+
return;
1105+
auto *param = initDC->getParam();
1106+
recordPossibleType(AFD->mapTypeIntoContext(param->getInterfaceType()));
1107+
break;
1108+
}
11001109
}
11011110
}
11021111

0 commit comments

Comments
 (0)