Skip to content

[AST/Sema] TypeWrappers: Extend implementation to support wrapped type #61501

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Oct 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3926,9 +3926,13 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
NominalTypeDecl *getTypeWrapperStorageDecl() const;

/// If this declaration is a type wrapper, retrieve
/// its required initializer - `init(storage:)`.
/// its required initializer - `init(storageWrapper:)`.
ConstructorDecl *getTypeWrapperInitializer() const;

/// Get an initializer that accepts a type wrapper instance to
/// initialize the wrapped type.
ConstructorDecl *getTypeWrappedTypeStorageInitializer() const;

/// Get a memberwise initializer that could be used to instantiate a
/// type wrapped type.
ConstructorDecl *getTypeWrappedTypeMemberwiseInitializer() const;
Expand Down
29 changes: 21 additions & 8 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -6591,21 +6591,30 @@ ERROR(type_wrapper_attribute_not_allowed_here,none,
"type wrapper attribute %0 can only be applied to a class, struct",
(Identifier))

ERROR(type_wrapper_requires_a_single_generic_param,none,
"type wrapper has to declare a single generic parameter "
"for underlying storage type", ())
ERROR(type_wrapper_requires_two_generic_params,none,
"type wrapper has to declare two generic parameters: "
"wrapped and storage types", ())

ERROR(cannot_use_multiple_type_wrappers,none,
"type %0 cannot use more than one type wrapper", ())

ERROR(type_wrapper_requires_memberwise_init,none,
"type wrapper type %0 does not contain a required initializer"
" - init(memberwise:)",
" - init(for:storage:)",
(DeclName))

ERROR(cannot_overload_type_wrapper_initializer,none,
"cannot overload type wrapper initializer 'init(for:storage:)'", ())

ERROR(cannot_declare_type_wrapper_init_with_invalid_first_param,none,
"first parameter of type wrapper initializer should be wrapped type - %0", (Type))

ERROR(cannot_declare_type_wrapper_init_with_invalid_second_param,none,
"second parameter of type wrapper initializer should be storage type - %0", (Type))

ERROR(type_wrapper_requires_subscript,none,
"type wrapper type %0 does not contain a required subscript"
" - subscript(storedKeyPath:)",
" - subscript(propertyKeyPath:storageKeyPath:)",
(DeclName))

ERROR(type_wrapper_requires_readonly_subscript,none,
Expand All @@ -6622,9 +6631,13 @@ NOTE(add_type_wrapper_subscript_stub_note,none,
ERROR(type_wrapper_failable_init,none,
"type wrapper initializer %0 cannot be failable", (DeclName))

ERROR(type_wrapper_invalid_subscript_param_type, none,
"type wrapper subscript expects a key path parameter type (got: %0)",
(Type))
ERROR(type_wrapper_subscript_invalid_parameter_type,none,
"type wrapper subscript parameter %0 expects type %1 (got: %2)",
(Identifier, Type, Type))

ERROR(type_wrapper_subscript_invalid_keypath_parameter,none,
"type wrapper subscript parameter %0 expects a key path (got: %1)",
(Identifier, Type))

ERROR(type_wrapper_type_requirement_not_accessible,none,
"%select{private|fileprivate|internal|public|open}0 %1 %2 cannot have "
Expand Down
6 changes: 4 additions & 2 deletions include/swift/AST/KnownIdentifiers.def
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,11 @@ IDENTIFIER_WITH_NAME(builderSelf, "$builderSelf")

// Type wrappers
IDENTIFIER_WITH_NAME(TypeWrapperStorage, "$Storage")
IDENTIFIER_WITH_NAME(TypeWrapperProperty, "$_storage")
IDENTIFIER_WITH_NAME(TypeWrapperProperty, "$storage")
IDENTIFIER(storageKeyPath)
IDENTIFIER(memberwise)
IDENTIFIER(propertyKeyPath)
IDENTIFIER(wrappedSelf)
IDENTIFIER(storageWrapper)
IDENTIFIER_WITH_NAME(localStorageVar, "_storage")

// Attribute options
Expand Down
10 changes: 5 additions & 5 deletions include/swift/AST/TypeCheckRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -3588,7 +3588,7 @@ class GetTypeWrapperStorage
bool isCached() const { return true; }
};

/// Inject or get `$_storage` property which is used to route accesses through
/// Inject or get `$storage` property which is used to route accesses through
/// to all stored properties of a type that has a type wrapper.
class GetTypeWrapperProperty
: public SimpleRequest<GetTypeWrapperProperty, VarDecl *(NominalTypeDecl *),
Expand Down Expand Up @@ -3689,17 +3689,17 @@ class SynthesizeTypeWrappedTypeMemberwiseInitializer
bool isCached() const { return true; }
};

class SynthesizeTypeWrappedTypeMemberwiseInitializerBody
: public SimpleRequest<SynthesizeTypeWrappedTypeMemberwiseInitializerBody,
BraceStmt *(ConstructorDecl *),
class SynthesizeTypeWrappedTypeStorageWrapperInitializer
: public SimpleRequest<SynthesizeTypeWrappedTypeStorageWrapperInitializer,
ConstructorDecl *(NominalTypeDecl *),
RequestFlags::Cached> {
public:
using SimpleRequest::SimpleRequest;

private:
friend SimpleRequest;

BraceStmt *evaluate(Evaluator &evaluator, ConstructorDecl *) const;
ConstructorDecl *evaluate(Evaluator &evaluator, NominalTypeDecl *) const;

public:
bool isCached() const { return true; }
Expand Down
4 changes: 2 additions & 2 deletions include/swift/AST/TypeCheckerTypeIDZone.def
Original file line number Diff line number Diff line change
Expand Up @@ -431,8 +431,8 @@ SWIFT_REQUEST(TypeChecker, IsPropertyAccessedViaTypeWrapper,
SWIFT_REQUEST(TypeChecker, SynthesizeTypeWrappedTypeMemberwiseInitializer,
ConstructorDecl *(NominalTypeDecl *),
Cached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, SynthesizeTypeWrappedTypeMemberwiseInitializerBody,
BraceStmt *(ConstructorDecl *),
SWIFT_REQUEST(TypeChecker, SynthesizeTypeWrappedTypeStorageWrapperInitializer,
ConstructorDecl *(NominalTypeDecl *),
Cached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, SynthesizeLocalVariableForTypeWrapperStorage,
VarDecl *(ConstructorDecl *),
Expand Down
18 changes: 13 additions & 5 deletions lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ namespace {
/// corresponds to `self`.
void injectActorHops();

/// Injects `self.$storage = .init(memberwise: $Storage(...))`
/// Injects `self.$storage = .init(storage: $Storage(...))`
/// assignment instructions into the function after each point
/// where `_storage` becomes fully initialized via `assign_by_wrapper`.
/// This is only necessary only for user-defined initializers of a
Expand Down Expand Up @@ -1117,7 +1117,7 @@ void LifetimeChecker::injectTypeWrapperStorageInitalization() {
auto storageType = F.getLoweredType(
ctor->mapTypeIntoContext(storageDecl->getDeclaredInterfaceType()));

// Argument value to use in call to <TypeWrapper>.init(memberwise:)
// Argument value to use in call to <TypeWrapper>.init(storage:)
SILValue storageObj = allocStack(storageType);

// let storageObj = $Storage(<destructured _storage tuple>)
Expand Down Expand Up @@ -1253,7 +1253,7 @@ void LifetimeChecker::injectTypeWrapperStorageInitalization() {
StoreOwnershipQualifier::Init);
}

// self.$storage = <TypeWrapper>(memberwise: storageObj))
// self.$storage = <TypeWrapper>(storage: storageObj))
{
bool isClass = isa<ClassDecl>(parentType);

Expand Down Expand Up @@ -1291,6 +1291,11 @@ void LifetimeChecker::injectTypeWrapperStorageInitalization() {
loc, selfRef, parentType->getTypeWrapperProperty());
}

auto wrappedType = MetatypeType::get(self->getType().getASTType(),
MetatypeRepresentation::Thick);
auto wrappedMetatype =
b.createMetatype(loc, F.getLoweredType(wrappedType));

auto typeWrapperType =
b.createMetatype(loc, F.getLoweredType(MetatypeType::get(
storagePropRef->getType().getASTType())));
Expand All @@ -1305,14 +1310,17 @@ void LifetimeChecker::injectTypeWrapperStorageInitalization() {
wrapperInitArgs.push_back(*localWrapperObj);
}

wrapperInitArgs.push_back(wrappedMetatype);
wrapperInitArgs.push_back(storageObj);
wrapperInitArgs.push_back(typeWrapperType);

// <wrapper-var> = <TypeWrapper>.init(memberwise: tmpStorage)
// <wrapper-var> = <TypeWrapper>.init(storage: tmpStorage)
auto wrapperInitResult = b.createApply(
loc, typeWrapperInitRef,
SubstitutionMap::get(typeWrapperInit->getGenericSignature(),
/*substitutions=*/{storageType.getASTType()},
/*substitutions=*/
{wrappedType->getMetatypeInstanceType(),
storageType.getASTType()},
/*conformances=*/{}),
wrapperInitArgs);

Expand Down
Loading