@@ -2406,6 +2406,53 @@ LazyStoragePropertyRequest::evaluate(Evaluator &evaluator,
24062406 return Storage;
24072407}
24082408
2409+ // / Synthesize a computed property representing the wrapped value for a
2410+ // / parameter with an attached property wrapper.
2411+ static VarDecl *synthesizeLocalWrappedValueVar (VarDecl *var) {
2412+ if (!var->hasAttachedPropertyWrapper () || !isa<ParamDecl>(var))
2413+ return nullptr ;
2414+
2415+ auto dc = var->getDeclContext ();
2416+ auto &ctx = var->getASTContext ();
2417+
2418+ SmallString<64 > nameBuf;
2419+ if (var->getName ().hasDollarPrefix ()) {
2420+ nameBuf = var->getName ().str ().drop_front ();
2421+ } else {
2422+ nameBuf = var->getName ().str ();
2423+ }
2424+ Identifier name = ctx.getIdentifier (nameBuf);
2425+
2426+ VarDecl *localVar = new (ctx) VarDecl (/* IsStatic=*/ false ,
2427+ VarDecl::Introducer::Var,
2428+ var->getLoc (), name, dc);
2429+ if (!var->hasImplicitPropertyWrapper ())
2430+ localVar->setInterfaceType (var->getInterfaceType ());
2431+ localVar->setImplicit ();
2432+ localVar->getAttrs () = var->getAttrs ();
2433+ localVar->overwriteAccess (var->getFormalAccess ());
2434+
2435+ if (var->hasImplicitPropertyWrapper ()) {
2436+ // FIXME: This can have a setter, but we need a resolved wrapper type
2437+ // to figure it out.
2438+ localVar->setImplInfo (StorageImplInfo::getImmutableComputed ());
2439+ } else {
2440+ auto mutability = *var->getPropertyWrapperMutability ();
2441+ if (mutability.Getter == PropertyWrapperMutability::Mutating) {
2442+ ctx.Diags .diagnose (var->getLoc (), diag::property_wrapper_param_mutating);
2443+ return nullptr ;
2444+ }
2445+
2446+ if (mutability.Setter == PropertyWrapperMutability::Nonmutating) {
2447+ localVar->setImplInfo (StorageImplInfo::getMutableComputed ());
2448+ } else {
2449+ localVar->setImplInfo (StorageImplInfo::getImmutableComputed ());
2450+ }
2451+ }
2452+
2453+ return localVar;
2454+ }
2455+
24092456// / Synthesize a computed property `$foo` for a property with an attached
24102457// / wrapper that has a `projectedValue` property.
24112458static VarDecl *synthesizePropertyWrapperProjectionVar (
@@ -2710,6 +2757,7 @@ PropertyWrapperAuxiliaryVariablesRequest::evaluate(Evaluator &evaluator,
27102757 auto dc = var->getDeclContext ();
27112758 VarDecl *backingVar = nullptr ;
27122759 VarDecl *projectionVar = nullptr ;
2760+ VarDecl *wrappedValueVar = nullptr ;
27132761
27142762 if (auto *param = dyn_cast<ParamDecl>(var)) {
27152763 backingVar = ParamDecl::cloneWithoutType (ctx, param);
@@ -2768,7 +2816,14 @@ PropertyWrapperAuxiliaryVariablesRequest::evaluate(Evaluator &evaluator,
27682816 ctx, var, wrapperType, wrapperInfo.projectedValueVar );
27692817 }
27702818
2771- return PropertyWrapperAuxiliaryVariables (backingVar, projectionVar);
2819+ if ((wrappedValueVar = synthesizeLocalWrappedValueVar (var))) {
2820+ // Record the backing storage for the local wrapped value var, which
2821+ // is needed for synthesizing its accessors.
2822+ evaluator.cacheOutput (PropertyWrapperAuxiliaryVariablesRequest{wrappedValueVar},
2823+ PropertyWrapperAuxiliaryVariables (backingVar, projectionVar));
2824+ }
2825+
2826+ return PropertyWrapperAuxiliaryVariables (backingVar, projectionVar, wrappedValueVar);
27722827}
27732828
27742829PropertyWrapperInitializerInfo
@@ -2888,56 +2943,6 @@ PropertyWrapperInitializerInfoRequest::evaluate(Evaluator &evaluator,
28882943 return PropertyWrapperInitializerInfo (wrappedValueInit, projectedValueInit);
28892944}
28902945
2891- VarDecl *
2892- PropertyWrapperWrappedValueVarRequest::evaluate (Evaluator &evaluator,
2893- VarDecl *var) const {
2894- auto wrapperInfo = var->getPropertyWrapperAuxiliaryVariables ();
2895- if (!wrapperInfo || !isa<ParamDecl>(var))
2896- return nullptr ;
2897-
2898- auto dc = var->getDeclContext ();
2899- auto &ctx = var->getASTContext ();
2900-
2901- SmallString<64 > nameBuf;
2902- if (var->getName ().hasDollarPrefix ()) {
2903- nameBuf = var->getName ().str ().drop_front ();
2904- } else {
2905- nameBuf = var->getName ().str ();
2906- }
2907- Identifier name = ctx.getIdentifier (nameBuf);
2908-
2909- VarDecl *localVar = new (ctx) VarDecl (/* IsStatic=*/ false ,
2910- VarDecl::Introducer::Var,
2911- var->getLoc (), name, dc);
2912- if (!var->hasImplicitPropertyWrapper ())
2913- localVar->setInterfaceType (var->getInterfaceType ());
2914- localVar->setImplicit ();
2915- localVar->getAttrs () = var->getAttrs ();
2916- localVar->overwriteAccess (var->getFormalAccess ());
2917-
2918- if (var->hasImplicitPropertyWrapper ()) {
2919- // FIXME: This can have a setter, but we need a resolved wrapper type
2920- // to figure it out.
2921- localVar->setImplInfo (StorageImplInfo::getImmutableComputed ());
2922- } else {
2923- auto mutability = *var->getPropertyWrapperMutability ();
2924- if (mutability.Getter == PropertyWrapperMutability::Mutating) {
2925- ctx.Diags .diagnose (var->getLoc (), diag::property_wrapper_param_mutating);
2926- return nullptr ;
2927- }
2928-
2929- if (mutability.Setter == PropertyWrapperMutability::Nonmutating) {
2930- localVar->setImplInfo (StorageImplInfo::getMutableComputed ());
2931- } else {
2932- localVar->setImplInfo (StorageImplInfo::getImmutableComputed ());
2933- }
2934- }
2935-
2936- evaluator.cacheOutput (PropertyWrapperAuxiliaryVariablesRequest{localVar},
2937- std::move (wrapperInfo));
2938- return localVar;
2939- }
2940-
29412946// / Given a storage declaration in a protocol, set it up with the right
29422947// / StorageImpl and add the right set of opaque accessors.
29432948static void finishProtocolStorageImplInfo (AbstractStorageDecl *storage,
0 commit comments