mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[AST/Sema] Remove TypeWrapper feature functionality
This commit is contained in:
@@ -189,35 +189,6 @@ static void maybeAddMemberwiseDefaultArg(ParamDecl *arg, VarDecl *var,
|
||||
arg->setDefaultArgumentKind(DefaultArgumentKind::StoredProperty);
|
||||
}
|
||||
|
||||
static void maybeAddTypeWrapperDefaultArg(ParamDecl *arg, VarDecl *var,
|
||||
ASTContext &ctx) {
|
||||
assert(var->isAccessedViaTypeWrapper() || var->hasAttachedPropertyWrapper());
|
||||
|
||||
if (!(var->getParentPattern() && var->getParentPattern()->getSingleVar()))
|
||||
return;
|
||||
|
||||
auto *PBD = var->getParentPatternBinding();
|
||||
|
||||
Expr *initExpr = nullptr;
|
||||
|
||||
if (var->hasAttachedPropertyWrapper()) {
|
||||
auto initInfo = var->getPropertyWrapperInitializerInfo();
|
||||
|
||||
if (initInfo.hasInitFromWrappedValue()) {
|
||||
initExpr =
|
||||
initInfo.getWrappedValuePlaceholder()->getOriginalWrappedValue();
|
||||
}
|
||||
} else {
|
||||
initExpr = PBD->getInit(/*index=*/0);
|
||||
}
|
||||
|
||||
if (!initExpr)
|
||||
return;
|
||||
|
||||
arg->setDefaultExpr(initExpr, PBD->isInitializerChecked(/*index=*/0));
|
||||
arg->setDefaultArgumentKind(DefaultArgumentKind::Normal);
|
||||
}
|
||||
|
||||
/// Describes the kind of implicit constructor that will be
|
||||
/// generated.
|
||||
enum class ImplicitConstructorKind {
|
||||
@@ -232,12 +203,6 @@ enum class ImplicitConstructorKind {
|
||||
/// the instance variables from a parameter of the same type and
|
||||
/// name.
|
||||
Memberwise,
|
||||
/// The constructor of a type wrapped type that accepts an instance of
|
||||
/// type wrapper i.e. `init(storageWrapper: Wrapper<Self, $Storage>)`.
|
||||
TypeWrapperStorage,
|
||||
/// The memberwise constructor of a type wrapped type which is going to
|
||||
/// initialize underlying storage for all applicable properties.
|
||||
TypeWrapperMemberwise,
|
||||
};
|
||||
|
||||
static ParamDecl *createMemberwiseInitParameter(DeclContext *DC,
|
||||
@@ -359,122 +324,6 @@ static ConstructorDecl *createImplicitConstructor(NominalTypeDecl *decl,
|
||||
arg->setInterfaceType(systemTy);
|
||||
arg->setImplicit();
|
||||
|
||||
params.push_back(arg);
|
||||
}
|
||||
} else if (ICK == ImplicitConstructorKind::TypeWrapperStorage) {
|
||||
accessLevel = decl->getTypeWrapperStorageDecl()->getFormalAccess();
|
||||
|
||||
auto typeWrapperInfo = decl->getTypeWrapper();
|
||||
assert(typeWrapperInfo);
|
||||
|
||||
auto *typeWrapper = typeWrapperInfo->Wrapper;
|
||||
|
||||
auto *arg = new (ctx) ParamDecl(SourceLoc(), Loc, ctx.Id_storageWrapper,
|
||||
Loc, ctx.Id_storageWrapper, decl);
|
||||
|
||||
auto typeWrapperType = typeWrapper->getDeclaredInterfaceType();
|
||||
|
||||
TypeSubstitutionMap subs;
|
||||
{
|
||||
auto genericParams =
|
||||
typeWrapper->getGenericSignature().getInnermostGenericParams();
|
||||
// Wrapped -> wrapped type
|
||||
subs[genericParams[0]->getCanonicalType()->castTo<SubstitutableType>()] =
|
||||
decl->getDeclaredInterfaceType();
|
||||
// Storage -> $Storage
|
||||
subs[genericParams[1]->getCanonicalType()->castTo<SubstitutableType>()] =
|
||||
decl->getTypeWrapperStorageDecl()->getDeclaredInterfaceType();
|
||||
}
|
||||
|
||||
auto paramType = typeWrapperType.subst(SubstitutionMap::get(
|
||||
typeWrapper->getGenericSignature(), QueryTypeSubstitutionMap{subs},
|
||||
LookUpConformanceInModule(decl->getParentModule())));
|
||||
|
||||
arg->setSpecifier(ParamSpecifier::Default);
|
||||
arg->setInterfaceType(paramType);
|
||||
arg->setImplicit();
|
||||
|
||||
params.push_back(arg);
|
||||
} else if (ICK == ImplicitConstructorKind::TypeWrapperMemberwise) {
|
||||
// Access to the initializer should match that of its parent type.
|
||||
accessLevel = decl->getEffectiveAccess();
|
||||
|
||||
for (auto *member : decl->getMembers()) {
|
||||
auto *var = dyn_cast<VarDecl>(member);
|
||||
if (!var)
|
||||
continue;
|
||||
|
||||
if (!var->isAccessedViaTypeWrapper()) {
|
||||
// Compiler synthesized properties are not included.
|
||||
if (var->isImplicit())
|
||||
continue;
|
||||
|
||||
// Computed properties are not included, except in cases
|
||||
// where property has a property wrapper and `@typeWrapperIgnored`
|
||||
// attribute.
|
||||
if (!var->hasStorage() &&
|
||||
!(var->hasAttachedPropertyWrapper() &&
|
||||
var->getAttrs().hasAttribute<TypeWrapperIgnoredAttr>()))
|
||||
continue;
|
||||
|
||||
// If this is a memberwise initializeable property include
|
||||
// it into the type wrapper initializer otherwise the instance
|
||||
// of type wrapped type wouldn't be completely initialized.
|
||||
if (var->isMemberwiseInitialized(/*preferDeclaredProperties=*/true))
|
||||
params.push_back(createMemberwiseInitParameter(decl, Loc, var));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
Identifier argName = var->getName();
|
||||
Identifier paramName = argName;
|
||||
|
||||
auto paramInterfaceType = var->getValueInterfaceType();
|
||||
DeclAttributes attrs;
|
||||
|
||||
// If this is a backing storage of a property wrapped property
|
||||
// let's use wrapped property as a parameter and synthesize
|
||||
// appropriate property wrapper initialization upon assignment.
|
||||
if (auto *wrappedVar = var->getOriginalWrappedProperty(
|
||||
PropertyWrapperSynthesizedPropertyKind::Backing)) {
|
||||
// If there is `init(wrappedValue:)` or default value for a wrapped
|
||||
// property we should use wrapped type, otherwise let's proceed with
|
||||
// wrapper type.
|
||||
if (wrappedVar->isPropertyMemberwiseInitializedWithWrappedType()) {
|
||||
var = wrappedVar;
|
||||
// If parameter have to get wrapped type, let's re-map both argument
|
||||
// and parameter name to match wrapped property and let property
|
||||
// wrapper attributes generate wrapped value and projection variables.
|
||||
argName = wrappedVar->getName();
|
||||
paramName = argName;
|
||||
|
||||
paramInterfaceType = var->getPropertyWrapperInitValueInterfaceType();
|
||||
// The parameter needs to have all of the property wrapper
|
||||
// attributes to generate projection and wrapper variables.
|
||||
for (auto *attr : wrappedVar->getAttachedPropertyWrappers())
|
||||
attrs.add(attr);
|
||||
} else {
|
||||
// If parameter has to have wrapper type then argument type should
|
||||
// match that of a wrapped property but parameter name stays the same
|
||||
// since it represents the type of backing storage and could be passed
|
||||
// to `$Storage` constructor directly.
|
||||
argName = wrappedVar->getName();
|
||||
}
|
||||
}
|
||||
|
||||
if (!paramInterfaceType || paramInterfaceType->hasError())
|
||||
continue;
|
||||
|
||||
auto *arg =
|
||||
new (ctx) ParamDecl(SourceLoc(), Loc, argName, Loc, paramName, decl);
|
||||
|
||||
arg->getAttrs().add(attrs);
|
||||
arg->setSpecifier(ParamSpecifier::Default);
|
||||
arg->setInterfaceType(paramInterfaceType);
|
||||
arg->setImplicit();
|
||||
|
||||
maybeAddTypeWrapperDefaultArg(arg, var, ctx);
|
||||
|
||||
params.push_back(arg);
|
||||
}
|
||||
}
|
||||
@@ -1270,10 +1119,6 @@ static bool shouldAttemptInitializerSynthesis(const NominalTypeDecl *decl) {
|
||||
if (decl->isInvalid())
|
||||
return false;
|
||||
|
||||
// Don't attempt if the decl has a type wrapper.
|
||||
if (decl->hasTypeWrapper())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1283,20 +1128,6 @@ void TypeChecker::addImplicitConstructors(NominalTypeDecl *decl) {
|
||||
return;
|
||||
|
||||
if (!shouldAttemptInitializerSynthesis(decl)) {
|
||||
if (decl->hasTypeWrapper()) {
|
||||
auto &ctx = decl->getASTContext();
|
||||
|
||||
// Synthesize a special `init(storageWrapper: <Wrapper>)`
|
||||
// initializer if possible.
|
||||
(void)decl->getTypeWrappedTypeStorageInitializer();
|
||||
|
||||
// If declaration is type wrapped and there are no
|
||||
// designated initializers, synthesize a special
|
||||
// memberwise initializer that would instantiate `$storage`.
|
||||
if (!hasUserDefinedDesignatedInit(ctx.evaluator, decl))
|
||||
(void)decl->getTypeWrappedTypeMemberwiseInitializer();
|
||||
}
|
||||
|
||||
decl->setAddedImplicitInitializers();
|
||||
return;
|
||||
}
|
||||
@@ -1617,202 +1448,3 @@ bool swift::addNonIsolatedToSynthesized(NominalTypeDecl *nominal,
|
||||
value->getAttrs().add(new (ctx) NonisolatedAttr(/*isImplicit=*/true));
|
||||
return true;
|
||||
}
|
||||
|
||||
static std::pair<BraceStmt *, /*isTypeChecked=*/bool>
|
||||
synthesizeTypeWrappedTypeStorageWrapperInitializerBody(
|
||||
AbstractFunctionDecl *decl, void *) {
|
||||
auto &ctx = decl->getASTContext();
|
||||
auto *ctor = cast<ConstructorDecl>(decl);
|
||||
auto *wrappedType = ctor->getDeclContext()->getSelfNominalTypeDecl();
|
||||
auto *storageProperty = wrappedType->getTypeWrapperProperty();
|
||||
|
||||
// self.$storage = storageWrapper
|
||||
SmallVector<ASTNode, 2> body;
|
||||
{
|
||||
auto *storageVarRef = UnresolvedDotExpr::createImplicit(
|
||||
ctx,
|
||||
new (ctx) DeclRefExpr({ctor->getImplicitSelfDecl()},
|
||||
/*Loc=*/DeclNameLoc(), /*Implicit=*/true),
|
||||
storageProperty->getName());
|
||||
|
||||
auto *paramRef = new (ctx)
|
||||
DeclRefExpr(ctor->getParameters()->get(0), /*Loc=*/DeclNameLoc(),
|
||||
/*Implicit=*/true);
|
||||
|
||||
body.push_back(new (ctx) AssignExpr(storageVarRef, /*EqualLoc=*/SourceLoc(),
|
||||
paramRef,
|
||||
/*Implicit=*/true));
|
||||
}
|
||||
|
||||
return {BraceStmt::create(ctx, /*lbloc=*/ctor->getLoc(), body,
|
||||
/*rbloc=*/ctor->getLoc(), /*implicit=*/true),
|
||||
/*isTypeChecked=*/false};
|
||||
}
|
||||
|
||||
ConstructorDecl *SynthesizeTypeWrappedTypeStorageWrapperInitializer::evaluate(
|
||||
Evaluator &evaluator, NominalTypeDecl *wrappedType) const {
|
||||
if (isa<ProtocolDecl>(wrappedType))
|
||||
return nullptr;
|
||||
|
||||
if (!wrappedType->hasTypeWrapper())
|
||||
return nullptr;
|
||||
|
||||
auto &ctx = wrappedType->getASTContext();
|
||||
|
||||
// .swiftinterfaces have both attribute and a synthesized member
|
||||
// (if it's public), so in this case we need use existing declaration
|
||||
// if available.
|
||||
{
|
||||
auto parentSF = wrappedType->getDeclContext()->getParentSourceFile();
|
||||
if (parentSF && parentSF->Kind == SourceFileKind::Interface) {
|
||||
DeclName initName(ctx, DeclBaseName::createConstructor(),
|
||||
/*labels=*/{ctx.Id_storageWrapper});
|
||||
auto results = wrappedType->lookupDirect(initName);
|
||||
if (results.size() == 1)
|
||||
return cast<ConstructorDecl>(results.front());
|
||||
}
|
||||
}
|
||||
|
||||
// `@typeWrapperIgnored` properties suppress this initializer.
|
||||
if (llvm::any_of(wrappedType->getMembers(), [&](Decl *member) {
|
||||
return member->getAttrs().hasAttribute<TypeWrapperIgnoredAttr>();
|
||||
}))
|
||||
return nullptr;
|
||||
|
||||
// Create the implicit type wrapper storage constructor.
|
||||
auto ctor = createImplicitConstructor(
|
||||
wrappedType, ImplicitConstructorKind::TypeWrapperStorage, ctx);
|
||||
wrappedType->addMember(ctor);
|
||||
|
||||
ctor->setBodySynthesizer(
|
||||
synthesizeTypeWrappedTypeStorageWrapperInitializerBody);
|
||||
return ctor;
|
||||
}
|
||||
|
||||
static std::pair<BraceStmt *, /*isTypeChecked=*/bool>
|
||||
synthesizeTypeWrappedTypeMemberwiseInitializerBody(AbstractFunctionDecl *decl,
|
||||
void *) {
|
||||
auto *ctor = cast<ConstructorDecl>(decl);
|
||||
auto &ctx = ctor->getASTContext();
|
||||
auto *parent = ctor->getDeclContext()->getSelfNominalTypeDecl();
|
||||
|
||||
assert(!isa<ProtocolDecl>(parent));
|
||||
|
||||
// self.$storage = .init(storage: $Storage(...))
|
||||
auto *storageType =
|
||||
cast<NominalTypeDecl>(parent->getTypeWrapperStorageDecl());
|
||||
assert(storageType);
|
||||
|
||||
auto *typeWrapperVar = parent->getTypeWrapperProperty();
|
||||
assert(typeWrapperVar);
|
||||
|
||||
auto *storageVarRef = UnresolvedDotExpr::createImplicit(
|
||||
ctx,
|
||||
new (ctx) DeclRefExpr({ctor->getImplicitSelfDecl()},
|
||||
/*Loc=*/DeclNameLoc(), /*Implicit=*/true),
|
||||
typeWrapperVar->getName());
|
||||
|
||||
// Check whether given parameter requires a direct assignment to
|
||||
// intialize the property.
|
||||
//
|
||||
// If `$Storage` doesn't have a member that corresponds
|
||||
// to the current parameter it means that this is a property
|
||||
// that not managed by the type wrapper which has to be
|
||||
// initialized by direct assignment: `self.<name> = <arg>`
|
||||
auto useDirectAssignment = [&](ParamDecl *param) {
|
||||
// Properties with property wrappers are always managed by the type wrapper
|
||||
if (param->hasAttachedPropertyWrapper())
|
||||
return false;
|
||||
return storageType->lookupDirect(param->getName()).empty();
|
||||
};
|
||||
|
||||
SmallVector<ASTNode, 2> body;
|
||||
|
||||
SmallVector<Argument, 4> initArgs;
|
||||
{
|
||||
for (auto *param : *ctor->getParameters()) {
|
||||
VarDecl *arg = param;
|
||||
|
||||
if (useDirectAssignment(param)) {
|
||||
auto *propRef = UnresolvedDotExpr::createImplicit(
|
||||
ctx,
|
||||
new (ctx) DeclRefExpr({ctor->getImplicitSelfDecl()},
|
||||
/*Loc=*/DeclNameLoc(), /*Implicit=*/true),
|
||||
arg->getName());
|
||||
|
||||
body.push_back(new (ctx) AssignExpr(
|
||||
propRef, /*EqualLoc=*/SourceLoc(),
|
||||
new (ctx) DeclRefExpr({arg}, /*DeclNameLoc=*/DeclNameLoc(),
|
||||
/*Implicit=*/true),
|
||||
/*Implicit=*/true));
|
||||
continue;
|
||||
}
|
||||
|
||||
// type wrappers wrap only backing storage of a wrapped
|
||||
// property, so in this case we need to pass `_<name>` to
|
||||
// `$Storage` constructor.
|
||||
if (param->hasAttachedPropertyWrapper()) {
|
||||
arg = param->getPropertyWrapperBackingProperty();
|
||||
(void)param->getPropertyWrapperBackingPropertyType();
|
||||
}
|
||||
|
||||
initArgs.push_back({/*labelLoc=*/SourceLoc(), arg->getName(),
|
||||
new (ctx) DeclRefExpr(arg, /*Loc=*/DeclNameLoc(),
|
||||
/*Implicit=*/true)});
|
||||
}
|
||||
}
|
||||
|
||||
auto *storageInit = CallExpr::createImplicit(
|
||||
ctx,
|
||||
TypeExpr::createImplicitForDecl(
|
||||
/*Loc=*/DeclNameLoc(), storageType, ctor,
|
||||
ctor->mapTypeIntoContext(storageType->getInterfaceType())),
|
||||
ArgumentList::createImplicit(ctx, initArgs));
|
||||
|
||||
auto *initRef = new (ctx) UnresolvedMemberExpr(
|
||||
/*dotLoc=*/SourceLoc(), /*declNameLoc=*/DeclNameLoc(),
|
||||
DeclNameRef::createConstructor(), /*implicit=*/true);
|
||||
{ initRef->setFunctionRefKind(FunctionRefKind::DoubleApply); }
|
||||
|
||||
auto *selfTypeRef = TypeExpr::createImplicitForDecl(
|
||||
DeclNameLoc(), parent, parent->getDeclContext(),
|
||||
ctor->mapTypeIntoContext(parent->getInterfaceType()));
|
||||
|
||||
auto *selfRef = new (ctx)
|
||||
DotSelfExpr(selfTypeRef, /*dot=*/SourceLoc(), /*self=*/SourceLoc());
|
||||
selfRef->setImplicit();
|
||||
|
||||
// .init($Storage(for:storage:))
|
||||
Expr *typeWrapperInit = CallExpr::createImplicit(
|
||||
ctx, initRef,
|
||||
ArgumentList::createImplicit(
|
||||
ctx,
|
||||
{Argument(/*labelLoc=*/SourceLoc(), ctx.Id_for, selfRef),
|
||||
Argument(/*labelLoc=*/SourceLoc(), ctx.Id_storage, storageInit)}));
|
||||
|
||||
body.push_back(new (ctx) AssignExpr(storageVarRef, /*EqualLoc=*/SourceLoc(),
|
||||
typeWrapperInit,
|
||||
/*Implicit=*/true));
|
||||
|
||||
return {BraceStmt::create(ctx, /*lbloc=*/ctor->getLoc(), body,
|
||||
/*rbloc=*/ctor->getLoc(), /*implicit=*/true),
|
||||
/*isTypeChecked=*/false};
|
||||
}
|
||||
|
||||
ConstructorDecl *SynthesizeTypeWrappedTypeMemberwiseInitializer::evaluate(
|
||||
Evaluator &evaluator, NominalTypeDecl *wrappedType) const {
|
||||
if (isa<ProtocolDecl>(wrappedType))
|
||||
return nullptr;
|
||||
|
||||
if (!wrappedType->hasTypeWrapper())
|
||||
return nullptr;
|
||||
|
||||
// Create the implicit memberwise constructor.
|
||||
auto &ctx = wrappedType->getASTContext();
|
||||
auto ctor = createImplicitConstructor(
|
||||
wrappedType, ImplicitConstructorKind::TypeWrapperMemberwise, ctx);
|
||||
wrappedType->addMember(ctor);
|
||||
|
||||
ctor->setBodySynthesizer(synthesizeTypeWrappedTypeMemberwiseInitializerBody);
|
||||
return ctor;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user