Skip to content

Commit 3bbf815

Browse files
committed
Sema: New syntax for @opened archetypes in textual SIL
The old syntax was @opened("UUID") constraintType Where constraintType was the right hand side of a conformance requirement. This would always create an archetype where the interface type was `Self`, so it couldn't cope with member types of opened existential types. Member types of opened existential types is now a thing with SE-0309, so this lack of support prevented writing SIL test cases using this feature. The new syntax is @opened("UUID", constraintType) interfaceType The interfaceType is a type parameter rooted in an implicit `Self` generic parameter, which is understood to be the underlying type of the existential. Fixes rdar://problem/93771238.
1 parent 30c99b5 commit 3bbf815

File tree

121 files changed

+1661
-1548
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

121 files changed

+1661
-1548
lines changed

include/swift/AST/ASTContext.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,10 @@ class ASTContext final {
13251325
bool isRecursivelyConstructingRequirementMachine(
13261326
const ProtocolDecl *proto);
13271327

1328+
/// Retrieve a generic parameter list with a single parameter named `Self`.
1329+
/// This is for parsing @opened archetypes in textual SIL.
1330+
GenericParamList *getSelfGenericParamList(DeclContext *dc) const;
1331+
13281332
/// Retrieve a generic signature with a single unconstrained type parameter,
13291333
/// like `<T>`.
13301334
CanGenericSignature getSingleGenericParameterSignature() const;

include/swift/AST/Attr.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2493,6 +2493,9 @@ class TypeAttributes {
24932493
// For an opened existential type, the known ID.
24942494
Optional<UUID> OpenedID;
24952495

2496+
// For an opened existential type, the constraint type.
2497+
Optional<TypeRepr *> ConstraintType;
2498+
24962499
// For a reference to an opaque return type, the mangled name and argument
24972500
// index into the generic signature.
24982501
struct OpaqueReturnTypeRef {
@@ -2581,6 +2584,9 @@ class TypeAttributes {
25812584
bool hasOpenedID() const { return OpenedID.hasValue(); }
25822585
UUID getOpenedID() const { return *OpenedID; }
25832586

2587+
bool hasConstraintType() const { return ConstraintType.hasValue(); }
2588+
TypeRepr *getConstraintType() const { return *ConstraintType; }
2589+
25842590
/// Given a name like "autoclosure", return the type attribute ID that
25852591
/// corresponds to it. This returns TAK_Count on failure.
25862592
///

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5089,8 +5089,10 @@ ERROR(differentiable_function_type_no_differentiability_parameters,
50895089
(/*isLinear*/ bool))
50905090

50915091
// SIL
5092-
ERROR(opened_non_protocol,none,
5093-
"@opened cannot be applied to non-protocol type %0", (Type))
5092+
ERROR(opened_bad_constraint_type,none,
5093+
"@opened constraint type %0 is not a protocol or protocol composition", (Type))
5094+
ERROR(opened_bad_interface_type,none,
5095+
"@opened interface type %0 is not a type parameter", (Type))
50945096
ERROR(sil_function_ellipsis,PointsToFirstBadToken,
50955097
"SIL function types cannot be variadic", ())
50965098
ERROR(sil_function_input_label,PointsToFirstBadToken,

lib/AST/ASTContext.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,10 @@ struct ASTContext::Implementation {
331331
/// Stores information about lazy deserialization of various declarations.
332332
llvm::DenseMap<const DeclContext *, LazyContextData *> LazyContexts;
333333

334+
/// A fake generic parameter list <Self> for parsing @opened archetypes
335+
/// in textual SIL.
336+
GenericParamList *SelfGenericParamList = nullptr;
337+
334338
/// The single-parameter generic signature with no constraints, <T>.
335339
CanGenericSignature SingleGenericParameterSignature;
336340

@@ -5152,6 +5156,26 @@ ASTContext::getClangTypeForIRGen(Type ty) {
51525156
return getClangTypeConverter().convert(ty).getTypePtrOrNull();
51535157
}
51545158

5159+
GenericParamList *ASTContext::getSelfGenericParamList(DeclContext *dc) const {
5160+
auto *theParamList = getImpl().SelfGenericParamList;
5161+
if (theParamList)
5162+
return theParamList;
5163+
5164+
// Note: we always return a GenericParamList rooted at the first
5165+
// DeclContext this was called with. Since this is just a giant
5166+
// hack for SIL mode, that should be OK.
5167+
auto *selfParam = GenericTypeParamDecl::create(
5168+
dc, Id_Self, SourceLoc(),
5169+
/*isTypeSequence=*/false, /*depth=*/0, /*index=*/0,
5170+
/*isOpaqueType=*/false, /*opaqueTypeRepr=*/nullptr);
5171+
5172+
theParamList = GenericParamList::create(
5173+
const_cast<ASTContext &>(*this), SourceLoc(), {selfParam}, SourceLoc());
5174+
getImpl().SelfGenericParamList = theParamList;
5175+
5176+
return theParamList;
5177+
}
5178+
51555179
CanGenericSignature ASTContext::getSingleGenericParameterSignature() const {
51565180
if (auto theSig = getImpl().SingleGenericParameterSignature)
51575181
return theSig;

lib/AST/ASTPrinter.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "swift/AST/ExistentialLayout.h"
2727
#include "swift/AST/Expr.h"
2828
#include "swift/AST/FileUnit.h"
29+
#include "swift/AST/GenericEnvironment.h"
2930
#include "swift/AST/GenericParamList.h"
3031
#include "swift/AST/GenericSignature.h"
3132
#include "swift/AST/Module.h"
@@ -6307,14 +6308,25 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
63076308
}
63086309

63096310
void visitOpenedArchetypeType(OpenedArchetypeType *T) {
6310-
if (auto parent = T->getParent()) {
6311-
printArchetypeCommon(T);
6312-
return;
6313-
}
6311+
if (Options.PrintForSIL) {
6312+
Printer << "@opened(\"" << T->getOpenedExistentialID() << "\", ";
6313+
visit(T->getGenericEnvironment()->getOpenedExistentialType());
6314+
Printer << ") ";
6315+
6316+
llvm::DenseMap<CanType, Identifier> newAlternativeTypeNames;
63146317

6315-
if (Options.PrintForSIL)
6316-
Printer << "@opened(\"" << T->getOpenedExistentialID() << "\") ";
6317-
visit(T->getExistentialType());
6318+
auto interfaceTy = T->getInterfaceType();
6319+
auto selfTy = interfaceTy->getRootGenericParam();
6320+
auto &ctx = selfTy->getASTContext();
6321+
newAlternativeTypeNames[selfTy->getCanonicalType()] = ctx.Id_Self;
6322+
6323+
PrintOptions subOptions = Options;
6324+
subOptions.AlternativeTypeNames = &newAlternativeTypeNames;
6325+
TypePrinter sub(Printer, subOptions);
6326+
sub.visit(interfaceTy);
6327+
} else {
6328+
visit(T->getExistentialType());
6329+
}
63186330
}
63196331

63206332
void printDependentMember(DependentMemberType *T) {

lib/Parse/ParseDecl.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3715,6 +3715,17 @@ ParserStatus Parser::parseTypeAttribute(TypeAttributes &Attributes,
37153715
} else {
37163716
diagnose(Tok, diag::opened_attribute_id_value);
37173717
}
3718+
3719+
if (Tok.is(tok::comma)) {
3720+
consumeToken(tok::comma);
3721+
3722+
auto constraintType = parseType(diag::expected_type);
3723+
if (constraintType.isNonNull())
3724+
Attributes.ConstraintType = constraintType.getPtrOrNull();
3725+
} else {
3726+
diagnose(Tok, diag::attr_expected_comma, "@opened", false);
3727+
}
3728+
37183729
parseMatchingToken(tok::r_paren, endLoc,
37193730
diag::opened_attribute_expected_rparen,
37203731
beginLoc);

lib/Sema/TypeCheckType.cpp

Lines changed: 69 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1924,6 +1924,10 @@ namespace {
19241924
return diags.diagnose(std::forward<ArgTypes>(Args)...);
19251925
}
19261926

1927+
NeverNullType resolveOpenedExistentialArchetype(
1928+
TypeAttributes &attrs, TypeRepr *repr,
1929+
TypeResolutionOptions options);
1930+
19271931
NeverNullType resolveAttributedType(AttributedTypeRepr *repr,
19281932
TypeResolutionOptions options);
19291933
NeverNullType resolveAttributedType(TypeAttributes &attrs, TypeRepr *repr,
@@ -2307,6 +2311,67 @@ TypeResolver::resolveAttributedType(AttributedTypeRepr *repr,
23072311
return resolveAttributedType(attrs, repr->getTypeRepr(), options);
23082312
}
23092313

2314+
/// In SIL, handle '@opened(UUID, constraintType) interfaceType',
2315+
/// which creates an opened archetype.
2316+
NeverNullType
2317+
TypeResolver::resolveOpenedExistentialArchetype(
2318+
TypeAttributes &attrs, TypeRepr *repr,
2319+
TypeResolutionOptions options) {
2320+
options.setContext(None);
2321+
2322+
auto *dc = getDeclContext();
2323+
auto &ctx = dc->getASTContext();
2324+
2325+
// The interface type is the type wrapped by the attribute. Resolve it
2326+
// with the fake <Self> generic parameter list uniquely stored in the
2327+
// ASTContext, and use structural resolution to avoid querying the
2328+
// DeclContext's generic signature, which is not the right signature
2329+
// for this.
2330+
auto structuralResolution = TypeResolution::forStructural(
2331+
dc, options,
2332+
/*unboundTyOpener*/ nullptr,
2333+
/*placeholderHandler*/ nullptr);
2334+
TypeResolver interfaceTypeResolver(structuralResolution,
2335+
ctx.getSelfGenericParamList(dc));
2336+
auto interfaceType = interfaceTypeResolver.resolveType(repr, options);
2337+
2338+
// The constraint type is stored inside the attribute. It is resolved
2339+
// normally, as if it were written in the current context.
2340+
auto constraintType = resolveType(attrs.getConstraintType(), options);
2341+
2342+
Type archetypeType;
2343+
if (!constraintType->isExistentialType()) {
2344+
diagnoseInvalid(repr, attrs.getLoc(TAK_opened),
2345+
diag::opened_bad_constraint_type,
2346+
constraintType);
2347+
2348+
archetypeType = ErrorType::get(constraintType->getASTContext());
2349+
} else if (!interfaceType->isTypeParameter()) {
2350+
diagnoseInvalid(repr, attrs.getLoc(TAK_opened),
2351+
diag::opened_bad_interface_type,
2352+
interfaceType);
2353+
2354+
archetypeType = ErrorType::get(interfaceType->getASTContext());
2355+
} {
2356+
// The constraint type is written with respect to the surrounding
2357+
// generic environment.
2358+
constraintType = GenericEnvironment::mapTypeIntoContext(
2359+
resolution.getGenericSignature().getGenericEnvironment(),
2360+
constraintType);
2361+
2362+
// The opened existential type is formed by mapping the interface type
2363+
// into a new opened generic environment.
2364+
archetypeType = OpenedArchetypeType::get(constraintType->getCanonicalType(),
2365+
interfaceType,
2366+
GenericSignature(),
2367+
attrs.getOpenedID());
2368+
}
2369+
2370+
attrs.clearAttribute(TAK_opened);
2371+
2372+
return archetypeType;
2373+
}
2374+
23102375
NeverNullType
23112376
TypeResolver::resolveAttributedType(TypeAttributes &attrs, TypeRepr *repr,
23122377
TypeResolutionOptions options) {
@@ -2715,6 +2780,10 @@ TypeResolver::resolveAttributedType(TypeAttributes &attrs, TypeRepr *repr,
27152780
attrs.clearAttribute(TAK_unchecked);
27162781
}
27172782

2783+
if (attrs.has(TAK_opened)) {
2784+
ty = resolveOpenedExistentialArchetype(attrs, repr, options);
2785+
}
2786+
27182787
auto instanceOptions = options;
27192788
instanceOptions.setContext(None);
27202789

@@ -2834,21 +2903,6 @@ TypeResolver::resolveAttributedType(TypeAttributes &attrs, TypeRepr *repr,
28342903
attrs.clearAttribute(TAK_noDerivative);
28352904
}
28362905

2837-
// In SIL, handle @opened (n), which creates an existential archetype.
2838-
if (attrs.has(TAK_opened)) {
2839-
if (!ty->isExistentialType()) {
2840-
diagnoseInvalid(repr, attrs.getLoc(TAK_opened), diag::opened_non_protocol,
2841-
ty);
2842-
} else {
2843-
ty = GenericEnvironment::mapTypeIntoContext(
2844-
resolution.getGenericSignature().getGenericEnvironment(), ty);
2845-
ty = OpenedArchetypeType::get(ty->getCanonicalType(),
2846-
resolution.getGenericSignature(),
2847-
attrs.OpenedID);
2848-
}
2849-
attrs.clearAttribute(TAK_opened);
2850-
}
2851-
28522906
// In SIL files *only*, permit @weak and @unowned to apply directly to types.
28532907
if (attrs.hasOwnership()) {
28542908
if (auto SF = getDeclContext()->getParentSourceFile()) {

test/SIL/OwnershipVerifier/interior_pointer.sil

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,16 +139,16 @@ bb0(%0 : @owned $Builtin.NativeObject):
139139
// CHECK-NEXT: Found outside of lifetime use?!
140140
// CHECK-NEXT: Value: %1 = begin_borrow %0 : $Error // users: %3, %2
141141
// CHECK-NEXT: Consuming User: end_borrow %1 : $Error // id: %3
142-
// CHECK-NEXT: Non Consuming User: %6 = apply %5<@opened("01234567-89AB-CDEF-0123-000000000000") Error>(%2) : $@convention(witness_method: Error) <τ_0_0 where τ_0_0 : Error> (@in_guaranteed τ_0_0) -> Int // type-defs: %2; user: %7
142+
// CHECK-NEXT: Non Consuming User: %6 = apply %5<@opened("01234567-89AB-CDEF-0123-000000000000", Error) Self>(%2) : $@convention(witness_method: Error) <τ_0_0 where τ_0_0 : Error> (@in_guaranteed τ_0_0) -> Int // type-defs: %2; user: %7
143143
// CHECK-NEXT: Block: bb0
144144
// CHECK: Error#: 0. End Error in Function: 'open_existential_box_interior_pointer_error'
145145
sil [ossa] @open_existential_box_interior_pointer_error : $@convention(thin) (@owned Error) -> Int {
146146
bb0(%0 : @owned $Error):
147147
%1 = begin_borrow %0 : $Error
148-
%2 = open_existential_box %1 : $Error to $*@opened("01234567-89AB-CDEF-0123-000000000000") Error
148+
%2 = open_existential_box %1 : $Error to $*@opened("01234567-89AB-CDEF-0123-000000000000", Error) Self
149149
end_borrow %1 : $Error
150150
destroy_value %0 : $Error
151-
%m = witness_method $@opened("01234567-89AB-CDEF-0123-000000000000") Error, #Error._code!getter, %2 : $*@opened("01234567-89AB-CDEF-0123-000000000000") Error : $@convention(witness_method: Error) <Self: Error> (@in_guaranteed Self) -> Int
152-
%result = apply %m<@opened("01234567-89AB-CDEF-0123-000000000000") Error>(%2) : $@convention(witness_method: Error) <Self: Error> (@in_guaranteed Self) -> Int
151+
%m = witness_method $@opened("01234567-89AB-CDEF-0123-000000000000", Error) Self, #Error._code!getter, %2 : $*@opened("01234567-89AB-CDEF-0123-000000000000", Error) Self : $@convention(witness_method: Error) <Self: Error> (@in_guaranteed Self) -> Int
152+
%result = apply %m<@opened("01234567-89AB-CDEF-0123-000000000000", Error) Self>(%2) : $@convention(witness_method: Error) <Self: Error> (@in_guaranteed Self) -> Int
153153
return %result : $Int
154154
}

test/SIL/OwnershipVerifier/use_verifier.sil

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,8 @@ bb0(%0 : @owned $SomeError):
230230
%2 = project_existential_box $SomeError in %1 : $Error
231231
store %0 to [init] %2 : $*SomeError
232232
%1a = begin_borrow %1 : $Error
233-
%4 = open_existential_box %1a : $Error to $*@opened("01234567-89AB-CDEF-0123-333333333333") Error
234-
destroy_addr %4 : $*@opened("01234567-89AB-CDEF-0123-333333333333") Error
233+
%4 = open_existential_box %1a : $Error to $*@opened("01234567-89AB-CDEF-0123-333333333333", Error) Self
234+
destroy_addr %4 : $*@opened("01234567-89AB-CDEF-0123-333333333333", Error) Self
235235
end_borrow %1a : $Error
236236
dealloc_existential_box %1 : $Error, $SomeError
237237
%9999 = tuple()
@@ -789,21 +789,21 @@ bb9:
789789

790790
sil [ossa] @dynamic_method_br_test : $@convention(thin) (@owned AnyObject, @thick AnyObject.Type) -> () {
791791
bb0(%0 : @owned $AnyObject, %1 : $@thick AnyObject.Type):
792-
%2 = open_existential_ref %0 : $AnyObject to $@opened("01234567-89ab-cdef-0123-000000000000") AnyObject
793-
dynamic_method_br %2 : $@opened("01234567-89ab-cdef-0123-000000000000") AnyObject, #X.f!foreign, bb1, bb2
792+
%2 = open_existential_ref %0 : $AnyObject to $@opened("01234567-89ab-cdef-0123-000000000000", AnyObject) Self
793+
dynamic_method_br %2 : $@opened("01234567-89ab-cdef-0123-000000000000", AnyObject) Self, #X.f!foreign, bb1, bb2
794794

795-
bb1(%4 : $@convention(objc_method) (@opened("01234567-89ab-cdef-0123-000000000000") AnyObject) -> ()):
795+
bb1(%4 : $@convention(objc_method) (@opened("01234567-89ab-cdef-0123-000000000000", AnyObject) Self) -> ()):
796796
br bb3
797797

798798
bb2:
799799
br bb3
800800

801801
bb3:
802-
destroy_value %2 : $@opened("01234567-89ab-cdef-0123-000000000000") AnyObject
803-
%5 = open_existential_metatype %1 : $@thick AnyObject.Type to $@thick (@opened("01234567-89ab-cdef-0123-000000000001") AnyObject).Type
804-
dynamic_method_br %5 : $@thick (@opened("01234567-89ab-cdef-0123-000000000001") AnyObject).Type, #X.g!foreign, bb4, bb5
802+
destroy_value %2 : $@opened("01234567-89ab-cdef-0123-000000000000", AnyObject) Self
803+
%5 = open_existential_metatype %1 : $@thick AnyObject.Type to $@thick (@opened("01234567-89ab-cdef-0123-000000000001", AnyObject) Self).Type
804+
dynamic_method_br %5 : $@thick (@opened("01234567-89ab-cdef-0123-000000000001", AnyObject) Self).Type, #X.g!foreign, bb4, bb5
805805

806-
bb4(%6 : $@convention(objc_method) (@thick (@opened("01234567-89ab-cdef-0123-000000000001") AnyObject).Type) -> ()):
806+
bb4(%6 : $@convention(objc_method) (@thick (@opened("01234567-89ab-cdef-0123-000000000001", AnyObject) Self).Type) -> ()):
807807
br bb6
808808

809809
bb5:
@@ -1029,10 +1029,10 @@ bb0:
10291029
sil [ossa] @dependent_type : $@convention(thin) (@owned SwiftKlassP) -> () {
10301030
bb0(%0 : @owned $SwiftKlassP):
10311031
%1 = begin_borrow %0 : $SwiftKlassP
1032-
%2 = open_existential_ref %1 : $SwiftKlassP to $@opened("3B64717A-E2B3-11E6-9646-985AEB89C610") SwiftKlassP
1033-
%cast = unchecked_ref_cast %2 : $@opened("3B64717A-E2B3-11E6-9646-985AEB89C610") SwiftKlassP to $Builtin.NativeObject
1034-
%3 = witness_method $@opened("3B64717A-E2B3-11E6-9646-985AEB89C610") SwiftKlassP, #SwiftKlassP.foo, %2 : $@opened("3B64717A-E2B3-11E6-9646-985AEB89C610") SwiftKlassP : $@convention(witness_method: SwiftKlassP) <τ_0_0 where τ_0_0 : SwiftKlassP> (@guaranteed τ_0_0) -> ()
1035-
apply %3<@opened("3B64717A-E2B3-11E6-9646-985AEB89C610") SwiftKlassP>(%2) : $@convention(witness_method: SwiftKlassP) <τ_0_0 where τ_0_0 : SwiftKlassP> (@guaranteed τ_0_0) -> ()
1032+
%2 = open_existential_ref %1 : $SwiftKlassP to $@opened("3B64717A-E2B3-11E6-9646-985AEB89C610", SwiftKlassP) Self
1033+
%cast = unchecked_ref_cast %2 : $@opened("3B64717A-E2B3-11E6-9646-985AEB89C610", SwiftKlassP) Self to $Builtin.NativeObject
1034+
%3 = witness_method $@opened("3B64717A-E2B3-11E6-9646-985AEB89C610", SwiftKlassP) Self, #SwiftKlassP.foo, %2 : $@opened("3B64717A-E2B3-11E6-9646-985AEB89C610", SwiftKlassP) Self : $@convention(witness_method: SwiftKlassP) <τ_0_0 where τ_0_0 : SwiftKlassP> (@guaranteed τ_0_0) -> ()
1035+
apply %3<@opened("3B64717A-E2B3-11E6-9646-985AEB89C610", SwiftKlassP) Self>(%2) : $@convention(witness_method: SwiftKlassP) <τ_0_0 where τ_0_0 : SwiftKlassP> (@guaranteed τ_0_0) -> ()
10361036
end_borrow %1 : $SwiftKlassP
10371037
destroy_value %0 : $SwiftKlassP
10381038
%9999 = tuple()

0 commit comments

Comments
 (0)