Skip to content

Commit 65105f3

Browse files
committed
[Property Wrappers] Introduce a new Expr node for the property wrapper
wrapped value placeholder in an init(wrappedValue:) call that was previously injected as an OpaqueValueExpr. This commit also restores the old design of OpaqueValueExpr.
1 parent 5f00a1b commit 65105f3

File tree

13 files changed

+153
-79
lines changed

13 files changed

+153
-79
lines changed

include/swift/AST/Expr.h

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4021,14 +4021,11 @@ class DynamicTypeExpr : public Expr {
40214021
/// subexpressions of that AST node.
40224022
class OpaqueValueExpr : public Expr {
40234023
SourceRange Range;
4024-
Expr *UnderlyingValue;
40254024

40264025
public:
40274026
explicit OpaqueValueExpr(SourceRange Range, Type Ty,
4028-
bool isPlaceholder = false,
4029-
Expr *underlyingValue = nullptr)
4030-
: Expr(ExprKind::OpaqueValue, /*Implicit=*/true, Ty),
4031-
Range(Range), UnderlyingValue(underlyingValue) {
4027+
bool isPlaceholder = false)
4028+
: Expr(ExprKind::OpaqueValue, /*Implicit=*/true, Ty), Range(Range) {
40324029
Bits.OpaqueValueExpr.IsPlaceholder = isPlaceholder;
40334030
}
40344031

@@ -4041,18 +4038,64 @@ class OpaqueValueExpr : public Expr {
40414038
Bits.OpaqueValueExpr.IsPlaceholder = value;
40424039
}
40434040

4044-
Expr *getUnderlyingValue() const {
4045-
return UnderlyingValue;
4041+
SourceRange getSourceRange() const { return Range; }
4042+
4043+
static bool classof(const Expr *E) {
4044+
return E->getKind() == ExprKind::OpaqueValue;
4045+
}
4046+
};
4047+
4048+
/// A placeholder to substitute with a \c wrappedValue initialization expression
4049+
/// for a property with an attached property wrapper.
4050+
///
4051+
/// Wrapped value placeholder expressions are injected around the
4052+
/// \c wrappedValue argument in a synthesized \c init(wrappedValue:)
4053+
/// call. This injection happens for properties with attached property wrappers
4054+
/// that can be initialized out-of-line with a wrapped value expression, rather
4055+
/// than calling \c init(wrappedValue:) explicitly.
4056+
///
4057+
/// Wrapped value placeholders store the original initialization expression
4058+
/// if one exists, along with an opaque value placeholder that can be bound
4059+
/// to a different wrapped value expression.
4060+
class PropertyWrapperValuePlaceholderExpr : public Expr {
4061+
SourceRange Range;
4062+
OpaqueValueExpr *Placeholder;
4063+
Expr *WrappedValue;
4064+
4065+
PropertyWrapperValuePlaceholderExpr(SourceRange Range, Type Ty,
4066+
OpaqueValueExpr *placeholder,
4067+
Expr *wrappedValue)
4068+
: Expr(ExprKind::PropertyWrapperValuePlaceholder, /*Implicit=*/true, Ty),
4069+
Range(Range), Placeholder(placeholder), WrappedValue(wrappedValue) {}
4070+
4071+
public:
4072+
static PropertyWrapperValuePlaceholderExpr *
4073+
create(ASTContext &ctx, SourceRange range, Type ty, Expr *wrappedValue);
4074+
4075+
/// The original wrappedValue initialization expression provided via
4076+
/// \c = on a proprety with attached property wrappers.
4077+
Expr *getOriginalWrappedValue() const {
4078+
return WrappedValue;
4079+
}
4080+
4081+
void setOriginalWrappedValue(Expr *value) {
4082+
WrappedValue = value;
4083+
}
4084+
4085+
/// An opaque value placeholder that will be used to substitute in a
4086+
/// different wrapped value expression for out-of-line initialization.
4087+
OpaqueValueExpr *getOpaqueValuePlaceholder() const {
4088+
return Placeholder;
40464089
}
40474090

4048-
void setUnderlyingValue(Expr *value) {
4049-
UnderlyingValue = value;
4091+
void setOpaqueValuePlaceholder(OpaqueValueExpr *placeholder) {
4092+
Placeholder = placeholder;
40504093
}
40514094

40524095
SourceRange getSourceRange() const { return Range; }
40534096

40544097
static bool classof(const Expr *E) {
4055-
return E->getKind() == ExprKind::OpaqueValue;
4098+
return E->getKind() == ExprKind::PropertyWrapperValuePlaceholder;
40564099
}
40574100
};
40584101

include/swift/AST/ExprNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ EXPR(VarargExpansion, Expr)
126126
EXPR(DynamicType, Expr)
127127
EXPR(RebindSelfInConstructor, Expr)
128128
EXPR(OpaqueValue, Expr)
129+
EXPR(PropertyWrapperValuePlaceholder, Expr)
129130
EXPR(DefaultArgument, Expr)
130131
EXPR(BindOptional, Expr)
131132
EXPR(OptionalEvaluation, Expr)

include/swift/AST/PropertyWrappers.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,12 +190,13 @@ void simple_display(
190190
llvm::raw_ostream &out,
191191
const PropertyWrapperBackingPropertyInfo &backingInfo);
192192

193-
/// Given the initializer for the given property with an attached property
194-
/// wrapper, dig out the placeholder for the original initialization expression.
193+
/// Given the initializer for a property with an attached property wrapper,
194+
/// dig out the wrapped value placeholder for the original initialization
195+
/// expression.
195196
///
196-
/// Cannot just dig out the getOriginalInit() value because this function checks
197-
/// types, etc. Erroneous code won't return a result from here.
198-
OpaqueValueExpr *findWrappedValuePlaceholder(VarDecl *var, Expr *init);
197+
/// \note The wrapped value placeholder is injected for properties that can
198+
/// be initialized out-of-line using an expression of the wrapped property type.
199+
PropertyWrapperValuePlaceholderExpr *findWrappedValuePlaceholder(Expr *init);
199200

200201
} // end namespace swift
201202

lib/AST/ASTDumper.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2498,9 +2498,17 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
24982498

24992499
void visitOpaqueValueExpr(OpaqueValueExpr *E) {
25002500
printCommon(E, "opaque_value_expr") << " @ " << (void*)E;
2501-
if (auto *underlyingValue = E->getUnderlyingValue()) {
2501+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
2502+
}
2503+
2504+
void visitPropertyWrapperValuePlaceholderExpr(
2505+
PropertyWrapperValuePlaceholderExpr *E) {
2506+
printCommon(E, "property_wrapper_value_placeholder_expr");
2507+
OS << '\n';
2508+
printRec(E->getOpaqueValuePlaceholder());
2509+
if (auto *value = E->getOriginalWrappedValue()) {
25022510
OS << '\n';
2503-
printRec(underlyingValue);
2511+
printRec(value);
25042512
}
25052513
PrintWithColorRAII(OS, ParenthesisColor) << ')';
25062514
}

lib/AST/ASTWalker.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -506,13 +506,22 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
506506
return E;
507507
}
508508

509-
Expr *visitOpaqueValueExpr(OpaqueValueExpr *E) {
510-
if (E->getUnderlyingValue()) {
511-
if (auto *newValue = doIt(E->getUnderlyingValue()))
512-
E->setUnderlyingValue(newValue);
509+
Expr *visitOpaqueValueExpr(OpaqueValueExpr *E) { return E; }
510+
511+
Expr *visitPropertyWrapperValuePlaceholderExpr(
512+
PropertyWrapperValuePlaceholderExpr *E) {
513+
if (auto *placeholder = doIt(E->getOpaqueValuePlaceholder()))
514+
E->setOpaqueValuePlaceholder(dyn_cast<OpaqueValueExpr>(placeholder));
515+
else
516+
return nullptr;
517+
518+
if (E->getOriginalWrappedValue()) {
519+
if (auto *newValue = doIt(E->getOriginalWrappedValue()))
520+
E->setOriginalWrappedValue(newValue);
513521
else
514522
return nullptr;
515523
}
524+
516525
return E;
517526
}
518527

lib/AST/Decl.cpp

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6348,32 +6348,19 @@ void ParamDecl::setDefaultArgumentCaptureInfo(CaptureInfo captures) {
63486348
DefaultValueAndFlags.getPointer()->Captures = captures;
63496349
}
63506350

6351-
/// Return nullptr if there is no property wrapper
6352-
OpaqueValueExpr *swift::findWrappedValuePlaceholder(VarDecl *var, Expr *init) {
6353-
if (!var->hasAttachedPropertyWrapper())
6354-
return nullptr;
6355-
6356-
auto *PBD = var->getParentPatternBinding();
6357-
if (!PBD)
6358-
return nullptr;
6359-
6360-
// If there is no '=' on the pattern, there was no initial value.
6361-
if (PBD->getEqualLoc(0).isInvalid() && !PBD->isDefaultInitializable())
6362-
return nullptr;
6363-
6351+
PropertyWrapperValuePlaceholderExpr *
6352+
swift::findWrappedValuePlaceholder(Expr *init) {
63646353
class Walker : public ASTWalker {
63656354
public:
6366-
OpaqueValueExpr *placeholder = nullptr;
6355+
PropertyWrapperValuePlaceholderExpr *placeholder = nullptr;
63676356

63686357
virtual std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
63696358
if (placeholder)
63706359
return { false, E };
63716360

6372-
if (auto *opaqueValue = dyn_cast<OpaqueValueExpr>(E)) {
6373-
if (opaqueValue->getUnderlyingValue()) {
6374-
placeholder = opaqueValue;
6375-
return { false, opaqueValue };
6376-
}
6361+
if (auto *value = dyn_cast<PropertyWrapperValuePlaceholderExpr>(E)) {
6362+
placeholder = value;
6363+
return { false, value };
63776364
}
63786365

63796366
return { true, E };
@@ -6480,7 +6467,7 @@ ParamDecl::getDefaultValueStringRepresentation(
64806467
}
64816468

64826469
auto init =
6483-
findWrappedValuePlaceholder(original, parentInit)->getUnderlyingValue();
6470+
findWrappedValuePlaceholder(parentInit)->getOriginalWrappedValue();
64846471
return extractInlinableText(getASTContext().SourceMgr, init, scratch);
64856472
}
64866473
}

lib/AST/Expr.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ ConcreteDeclRef Expr::getReferencedDecl(bool stopAtParenExpr) const {
311311
PASS_THROUGH_REFERENCE(RebindSelfInConstructor, getSubExpr);
312312

313313
NO_REFERENCE(OpaqueValue);
314+
NO_REFERENCE(PropertyWrapperValuePlaceholder);
314315
NO_REFERENCE(DefaultArgument);
315316

316317
PASS_THROUGH_REFERENCE(BindOptional, getSubExpr);
@@ -624,6 +625,7 @@ bool Expr::canAppendPostfixExpression(bool appendingPostfixOperator) const {
624625

625626
case ExprKind::RebindSelfInConstructor:
626627
case ExprKind::OpaqueValue:
628+
case ExprKind::PropertyWrapperValuePlaceholder:
627629
case ExprKind::DefaultArgument:
628630
case ExprKind::BindOptional:
629631
case ExprKind::OptionalEvaluation:
@@ -1403,6 +1405,17 @@ static ValueDecl *getCalledValue(Expr *E) {
14031405
return nullptr;
14041406
}
14051407

1408+
PropertyWrapperValuePlaceholderExpr *
1409+
PropertyWrapperValuePlaceholderExpr::create(ASTContext &ctx, SourceRange range,
1410+
Type ty, Expr *wrappedValue) {
1411+
auto *placeholder =
1412+
new (ctx) OpaqueValueExpr(range, ty, /*isPlaceholder=*/true);
1413+
1414+
return new (ctx) PropertyWrapperValuePlaceholderExpr(range, ty,
1415+
placeholder,
1416+
wrappedValue);
1417+
}
1418+
14061419
const ParamDecl *DefaultArgumentExpr::getParamDecl() const {
14071420
return getParameterAt(DefaultArgsOwner.getDecl(), ParamIndex);
14081421
}

lib/SILGen/SILGenExpr.cpp

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,8 @@ namespace {
519519
MakeTemporarilyEscapableExpr *E, SGFContext C);
520520

521521
RValue visitOpaqueValueExpr(OpaqueValueExpr *E, SGFContext C);
522+
RValue visitPropertyWrapperValuePlaceholderExpr(
523+
PropertyWrapperValuePlaceholderExpr *E, SGFContext C);
522524

523525
RValue visitInOutToPointerExpr(InOutToPointerExpr *E, SGFContext C);
524526
RValue visitArrayToPointerExpr(ArrayToPointerExpr *E, SGFContext C);
@@ -2407,31 +2409,24 @@ RValue RValueEmitter::visitCaptureListExpr(CaptureListExpr *E, SGFContext C) {
24072409
return visit(E->getClosureBody(), C);
24082410
}
24092411

2410-
static OpaqueValueExpr *opaqueValueExprToSubstituteForAutoClosure(
2411-
const AbstractClosureExpr *e) {
2412-
// When we find an autoclosure that just calls an opaque closure,
2413-
// this is a case where we've created the opaque closure as a
2414-
// stand-in for the autoclosure itself. Such an opaque closure is
2415-
// created when we have a property wrapper's 'init(wrappedValue:)'
2416-
// taking an autoclosure argument.
2412+
/// Returns the wrapped value placeholder that is meant to be substituted
2413+
/// in for the given autoclosure. This autoclosure placeholder is created
2414+
/// when \c init(wrappedValue:) takes an autoclosure for the \c wrappedValue
2415+
/// parameter.
2416+
static PropertyWrapperValuePlaceholderExpr *
2417+
wrappedValueAutoclosurePlaceholder(const AbstractClosureExpr *e) {
24172418
if (auto ace = dyn_cast<AutoClosureExpr>(e)) {
24182419
if (auto ce = dyn_cast<CallExpr>(ace->getSingleExpressionBody())) {
2419-
if (auto ove = dyn_cast<OpaqueValueExpr>(ce->getFn())) {
2420-
if (!ace->isImplicit() || !ove->isImplicit() || !ove->isPlaceholder())
2421-
return nullptr;
2422-
2423-
if (ace->getType()->isEqual(ove->getType()))
2424-
return ove;
2425-
}
2420+
return dyn_cast<PropertyWrapperValuePlaceholderExpr>(ce->getFn());
24262421
}
24272422
}
24282423
return nullptr;
24292424
}
24302425

24312426
RValue RValueEmitter::visitAbstractClosureExpr(AbstractClosureExpr *e,
24322427
SGFContext C) {
2433-
if (auto ove = opaqueValueExprToSubstituteForAutoClosure(e))
2434-
return visitOpaqueValueExpr(ove, C);
2428+
if (auto *placeholder = wrappedValueAutoclosurePlaceholder(e))
2429+
return visitPropertyWrapperValuePlaceholderExpr(placeholder, C);
24352430

24362431
// Emit the closure body.
24372432
SGF.SGM.emitClosure(e);
@@ -5137,6 +5132,11 @@ RValue RValueEmitter::visitOpaqueValueExpr(OpaqueValueExpr *E, SGFContext C) {
51375132
return RValue(SGF, E, SGF.manageOpaqueValue(value, E, C));
51385133
}
51395134

5135+
RValue RValueEmitter::visitPropertyWrapperValuePlaceholderExpr(
5136+
PropertyWrapperValuePlaceholderExpr *E, SGFContext C) {
5137+
return visitOpaqueValueExpr(E->getOpaqueValuePlaceholder(), C);
5138+
}
5139+
51405140
ProtocolDecl *SILGenFunction::getPointerProtocol() {
51415141
if (SGM.PointerProtocol)
51425142
return *SGM.PointerProtocol;

lib/Sema/CSApply.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3473,6 +3473,11 @@ namespace {
34733473
return expr;
34743474
}
34753475

3476+
Expr *visitPropertyWrapperValuePlaceholderExpr(
3477+
PropertyWrapperValuePlaceholderExpr *expr) {
3478+
return expr;
3479+
}
3480+
34763481
Expr *visitDefaultArgumentExpr(DefaultArgumentExpr *expr) {
34773482
llvm_unreachable("Already type-checked");
34783483
}
@@ -5548,11 +5553,10 @@ Expr *ExprRewriter::coerceCallArguments(Expr *arg, AnyFunctionType *funcType,
55485553
target->shouldInjectWrappedValuePlaceholder(apply);
55495554

55505555
auto injectWrappedValuePlaceholder = [&](Expr *arg) -> Expr * {
5551-
auto *placeholder = new (ctx) OpaqueValueExpr(arg->getSourceRange(),
5552-
cs.getType(arg),
5553-
/*isPlaceholder=*/true,
5554-
arg);
5556+
auto *placeholder = PropertyWrapperValuePlaceholderExpr::create(ctx,
5557+
arg->getSourceRange(), cs.getType(arg), arg);
55555558
cs.cacheType(placeholder);
5559+
cs.cacheType(placeholder->getOpaqueValuePlaceholder());
55565560
shouldInjectWrappedValuePlaceholder = false;
55575561
return placeholder;
55585562
};

lib/Sema/CSGen.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2805,6 +2805,11 @@ namespace {
28052805
return expr->getType();
28062806
}
28072807

2808+
Type visitPropertyWrapperValuePlaceholderExpr(
2809+
PropertyWrapperValuePlaceholderExpr *expr) {
2810+
return expr->getType();
2811+
}
2812+
28082813
Type visitDefaultArgumentExpr(DefaultArgumentExpr *expr) {
28092814
return expr->getType();
28102815
}

lib/Sema/TypeCheckPropertyWrapper.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -669,11 +669,11 @@ Type swift::computeWrappedValueType(VarDecl *var, Type backingStorageType,
669669
}
670670

671671
static bool isOpaquePlaceholderClosure(const Expr *value) {
672-
auto ove = dyn_cast<OpaqueValueExpr>(value);
673-
if (!ove || !ove->isPlaceholder())
672+
auto *placeholder = dyn_cast<PropertyWrapperValuePlaceholderExpr>(value);
673+
if (!placeholder)
674674
return false;
675675

676-
if (auto valueFnTy = ove->getType()->getAs<FunctionType>()) {
676+
if (auto valueFnTy = placeholder->getType()->getAs<FunctionType>()) {
677677
return (valueFnTy->getNumParams() == 0);
678678
}
679679

0 commit comments

Comments
 (0)