Skip to content

Commit c491d25

Browse files
committed
Fix printing and implement parsing of opened element archetypes in SIL
Also, fix a couple places that were checking for opened existentials to check for any local archetype.
1 parent 5dd6c4e commit c491d25

File tree

12 files changed

+215
-14
lines changed

12 files changed

+215
-14
lines changed

include/swift/AST/Attr.def.gyb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ TYPE_ATTR(callee_owned)
8484
TYPE_ATTR(callee_guaranteed)
8585
TYPE_ATTR(objc_metatype)
8686
TYPE_ATTR(opened)
87+
TYPE_ATTR(pack_element)
8788
TYPE_ATTR(pseudogeneric)
8889
TYPE_ATTR(yields)
8990
TYPE_ATTR(yield_once)

include/swift/AST/DiagnosticsParse.def

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,7 @@ ERROR(expected_generic_signature,none,
677677
"expected a generic signature", ())
678678
ERROR(sil_expected_uuid,none,
679679
"expected a UUID string literal", ())
680+
NOTE(sil_previous_instruction,none, "previous instruction", ())
680681

681682
// SIL Basic Blocks
682683
ERROR(expected_sil_block_name,none,
@@ -1656,6 +1657,14 @@ ERROR(opened_attribute_id_value,none,
16561657
ERROR(opened_attribute_expected_rparen,none,
16571658
"expected ')' after id value for 'opened' attribute", ())
16581659

1660+
// pack_element
1661+
ERROR(pack_element_attribute_expected_lparen,none,
1662+
"expected '(' after 'pack_element' attribute", ())
1663+
ERROR(pack_element_attribute_expected_rparen,none,
1664+
"expected ')' after id value for 'pack_element' attribute", ())
1665+
ERROR(multiple_open_pack_element,none,
1666+
"multiple 'open_pack_element' instructions with same UUID", ())
1667+
16591668
// unowned
16601669
ERROR(attr_unowned_invalid_specifier,none,
16611670
"expected 'safe' or 'unsafe'", ())

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5385,6 +5385,9 @@ ERROR(illegal_sil_type,none,
53855385
"type %0 is not a legal SIL value type", (Type))
53865386
ERROR(sil_box_arg_mismatch,none,
53875387
"SIL box type has wrong number of generic arguments for layout", ())
5388+
ERROR(sil_pack_element_uuid_not_found,none,
5389+
"open_pack_element instruction not found for @pack_element type UUID; "
5390+
"possible forward reference?", ())
53885391
// SIL Metatypes
53895392
ERROR(sil_metatype_without_repr,none,
53905393
"metatypes in SIL must have @thin, @thick, or @objc_metatype attribute",

include/swift/AST/GenericEnvironment.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ class ArchetypeType;
3535
class ASTContext;
3636
class GenericTypeParamType;
3737
class OpaqueTypeDecl;
38+
class ElementArchetypeType;
3839
class OpenedArchetypeType;
40+
class PackArchetypeType;
3941
class SILModule;
4042
class SILType;
4143

include/swift/Sema/SILTypeResolutionContext.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,37 @@
1313
#ifndef SWIFT_SEMA_SILTYPERESOLUTIONCONTEXT_H
1414
#define SWIFT_SEMA_SILTYPERESOLUTIONCONTEXT_H
1515

16+
#include "llvm/ADT/DenseMap.h"
17+
#include "swift/Basic/UUID.h"
18+
1619
namespace swift {
1720
class GenericParamList;
21+
class GenericEnvironment;
1822

1923
class SILTypeResolutionContext {
2024
public:
25+
struct OpenedPackElement {
26+
SourceLoc DefinitionPoint;
27+
GenericParamList *Params;
28+
GenericEnvironment *Environment;
29+
};
30+
using OpenedPackElementsMap = llvm::DenseMap<UUID, OpenedPackElement>;
31+
2132
/// Are we requesting a SIL type?
2233
bool IsSILType;
2334

2435
/// Look up types in the given parameter list.
2536
GenericParamList *GenericParams;
2637

38+
/// Look up @pack_element environments in this map.
39+
OpenedPackElementsMap *OpenedPackElements;
40+
2741
SILTypeResolutionContext(bool isSILType,
28-
GenericParamList *genericParams)
29-
: IsSILType(isSILType), GenericParams(genericParams) {}
42+
GenericParamList *genericParams,
43+
OpenedPackElementsMap *openedPackElements)
44+
: IsSILType(isSILType),
45+
GenericParams(genericParams),
46+
OpenedPackElements(openedPackElements) {}
3047
};
3148

3249
}

lib/AST/ASTPrinter.cpp

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5439,6 +5439,8 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
54395439
} else if (auto archetype = dyn_cast<ArchetypeType>(T.getPointer())) {
54405440
if (archetype->isParameterPack() && Options.PrintExplicitEach)
54415441
return false;
5442+
if (Options.PrintForSIL && isa<LocalArchetypeType>(archetype))
5443+
return false;
54425444
}
54435445
return T->hasSimpleTypeRepr();
54445446
}
@@ -6600,12 +6602,58 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
66006602
}
66016603
}
66026604

6605+
static Type findPackForElementArchetype(ElementArchetypeType *T) {
6606+
// The type in @pack_element is looked up in the generic params
6607+
// of the identified open_pack_element instruction. The param list
6608+
// is long gone, but the sugar survives in the type parameters of
6609+
// the generic signature of the contextual substitution map in the
6610+
// opened element environment.
6611+
auto env = T->getGenericEnvironment();
6612+
auto subs = env->getPackElementContextSubstitutions();
6613+
auto sig = subs.getGenericSignature();
6614+
auto params = sig.getGenericParams();
6615+
6616+
auto elementShapeClass =
6617+
env->getOpenedElementShapeClass()->mapTypeOutOfContext();
6618+
6619+
// The element archetypes are at a depth one past the max depth
6620+
// of the base signature.
6621+
unsigned elementDepth = params.back()->getDepth() + 1;
6622+
6623+
// Transform the archetype's interface type to be based on the
6624+
// corresponding non-canonical type parameter.
6625+
auto interfaceType = T->getInterfaceType();
6626+
return interfaceType.subst([&](SubstitutableType *type) -> Type {
6627+
// Don't transform types that aren't element type parameters.
6628+
auto *elementParam = type->getAs<GenericTypeParamType>();
6629+
if (!elementParam || elementParam->getDepth() != elementDepth)
6630+
return Type();
6631+
6632+
// Loop through the type parameters looking for the type parameter
6633+
// pack at the appropriate index. We only expect to actually do
6634+
// this once for each type, so it's fine to do it in the callback.
6635+
unsigned nextIndex = 0;
6636+
for (auto *genericParam : params) {
6637+
if (!genericParam->isParameterPack())
6638+
continue;
6639+
6640+
if (!sig->haveSameShape(genericParam, elementShapeClass))
6641+
continue;
6642+
6643+
if (nextIndex == elementParam->getIndex())
6644+
return genericParam;
6645+
nextIndex++;
6646+
}
6647+
llvm_unreachable("ran out of type parameters");
6648+
return Type();
6649+
}, LookUpConformanceInSignature(sig.getPointer()));
6650+
}
6651+
66036652
void visitElementArchetypeType(ElementArchetypeType *T) {
66046653
if (Options.PrintForSIL) {
6605-
Printer << "@element(\"" << T->getOpenedElementID() << ") ";
6606-
6607-
auto interfaceTy = T->getInterfaceType();
6608-
visit(interfaceTy);
6654+
Printer << "@pack_element(\"" << T->getOpenedElementID() << "\") ";
6655+
auto packTy = findPackForElementArchetype(T);
6656+
visit(packTy);
66096657
} else {
66106658
visit(T->getInterfaceType());
66116659
}

lib/AST/GenericEnvironment.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ Type QueryInterfaceTypeSubstitutions::operator()(SubstitutableType *type) const{
547547
Type GenericEnvironment::mapTypeIntoContext(
548548
Type type,
549549
LookupConformanceFn lookupConformance) const {
550-
assert((!type->hasArchetype() || type->hasOpenedExistential()) &&
550+
assert((!type->hasArchetype() || type->hasLocalArchetype()) &&
551551
"already have a contextual type");
552552

553553
type = maybeApplyOuterContextSubstitutions(type);

lib/AST/Type.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4710,7 +4710,7 @@ static Type substType(Type derivedType,
47104710
if (origArchetype->isRoot()) {
47114711
// Root opened archetypes are not required to be substituted. Other root
47124712
// archetypes must already have been substituted above.
4713-
if (isa<OpenedArchetypeType>(origArchetype)) {
4713+
if (isa<LocalArchetypeType>(origArchetype)) {
47144714
return Type(type);
47154715
} else {
47164716
return ErrorType::get(type);

lib/Parse/ParseDecl.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4164,6 +4164,33 @@ ParserStatus Parser::parseTypeAttribute(TypeAttributes &Attributes,
41644164
break;
41654165
}
41664166

4167+
case TAK_pack_element: {
4168+
if (!isInSILMode()) {
4169+
diagnose(AtLoc, diag::only_allowed_in_sil, "pack_element");
4170+
return makeParserSuccess();
4171+
}
4172+
4173+
// Parse the opened ID string in parens
4174+
SourceLoc beginLoc = Tok.getLoc(), idLoc, endLoc;
4175+
if (consumeIfNotAtStartOfLine(tok::l_paren)) {
4176+
idLoc = Tok.getLoc();
4177+
UUID id;
4178+
if (!parseUUIDString(id, diag::opened_attribute_id_value))
4179+
Attributes.OpenedID = id;
4180+
4181+
// TODO: allow more information so that these can be parsed
4182+
// prior to the open instruction.
4183+
4184+
parseMatchingToken(tok::r_paren, endLoc,
4185+
diag::opened_attribute_expected_rparen,
4186+
beginLoc);
4187+
} else {
4188+
diagnose(Tok, diag::pack_element_attribute_expected_lparen);
4189+
}
4190+
4191+
break;
4192+
}
4193+
41674194
case TAK_differentiable: {
41684195
Attributes.differentiabilityKind = DifferentiabilityKind::Normal;
41694196
if (parseDifferentiableTypeAttributeArgument(

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -157,13 +157,20 @@ namespace swift {
157157
llvm::DenseMap<SILBasicBlock*,
158158
Located<Identifier>> UndefinedBlocks;
159159

160+
/// The set of opened packs in the function, indexed by UUID.
161+
/// Note that we don't currently support parsing references to
162+
/// opened packs prior to their instruction, although this is
163+
/// theoretically possible if basic blocks are not sorted in
164+
/// dominance order.
165+
SILTypeResolutionContext::OpenedPackElementsMap OpenedPackElements;
166+
160167
/// Data structures used to perform name lookup for local values.
161168
llvm::StringMap<ValueBase*> LocalValues;
162169
llvm::StringMap<SourceLoc> ForwardRefLocalValues;
163170

164171
Type performTypeResolution(TypeRepr *TyR, bool IsSILType,
165172
GenericSignature GenericSig,
166-
GenericParamList *GenericParams) const;
173+
GenericParamList *GenericParams);
167174

168175
void convertRequirements(ArrayRef<RequirementRepr> From,
169176
SmallVectorImpl<Requirement> &To,
@@ -1253,11 +1260,12 @@ static bool parseDeclSILOptional(bool *isTransparent,
12531260

12541261
Type SILParser::performTypeResolution(TypeRepr *TyR, bool IsSILType,
12551262
GenericSignature GenericSig,
1256-
GenericParamList *GenericParams) const {
1263+
GenericParamList *GenericParams) {
12571264
if (!GenericSig)
12581265
GenericSig = ContextGenericSig;
12591266

1260-
SILTypeResolutionContext SILContext(IsSILType, GenericParams);
1267+
SILTypeResolutionContext SILContext(IsSILType, GenericParams,
1268+
&OpenedPackElements);
12611269

12621270
return swift::performTypeResolution(TyR, P.Context, GenericSig,
12631271
&SILContext, &P.SF);
@@ -3408,7 +3416,18 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
34083416
auto openedEnv = GenericEnvironment::forOpenedElement(openedElementSig,
34093417
uuid, shapeClass, openedSubMap);
34103418

3411-
ResultVal = B.createOpenPackElement(InstLoc, Val, openedEnv);
3419+
auto openInst = B.createOpenPackElement(InstLoc, Val, openedEnv);
3420+
ResultVal = openInst;
3421+
3422+
auto &entry = OpenedPackElements[uuid];
3423+
if (entry.DefinitionPoint.isValid()) {
3424+
P.diagnose(OpcodeLoc, diag::multiple_open_pack_element);
3425+
P.diagnose(entry.DefinitionPoint, diag::sil_previous_instruction);
3426+
} else {
3427+
entry.DefinitionPoint = OpcodeLoc;
3428+
entry.Params = openedGenerics;
3429+
entry.Environment = openedEnv;
3430+
}
34123431
break;
34133432
}
34143433

@@ -7593,7 +7612,8 @@ static bool parseSILWitnessTableEntry(
75937612
return true;
75947613

75957614
SILTypeResolutionContext silContext(/*isSILType=*/false,
7596-
witnessParams);
7615+
witnessParams,
7616+
/*openedPacks=*/nullptr);
75977617
auto Ty =
75987618
swift::performTypeResolution(TyR.get(), P.Context,
75997619
witnessSig, &silContext,
@@ -7657,7 +7677,8 @@ static bool parseSILWitnessTableEntry(
76577677
return true;
76587678

76597679
SILTypeResolutionContext silContext(/*isSILType=*/false,
7660-
witnessParams);
7680+
witnessParams,
7681+
/*openedPacks=*/nullptr);
76617682
auto Ty =
76627683
swift::performTypeResolution(TyR.get(), P.Context,
76637684
witnessSig, &silContext,

lib/Sema/TypeCheckType.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1975,6 +1975,10 @@ namespace {
19751975
TypeAttributes &attrs, TypeRepr *repr,
19761976
TypeResolutionOptions options);
19771977

1978+
NeverNullType resolvePackElementArchetype(
1979+
TypeAttributes &attrs, TypeRepr *repr,
1980+
TypeResolutionOptions options);
1981+
19781982
NeverNullType resolveAttributedType(AttributedTypeRepr *repr,
19791983
TypeResolutionOptions options);
19801984
NeverNullType resolveAttributedType(TypeAttributes &attrs, TypeRepr *repr,
@@ -2507,6 +2511,71 @@ TypeResolver::resolveOpenedExistentialArchetype(
25072511
return archetypeType;
25082512
}
25092513

2514+
/// In SIL, handle '@pack_element(UUID) interfaceType',
2515+
/// which creates an opened archetype.
2516+
NeverNullType
2517+
TypeResolver::resolvePackElementArchetype(
2518+
TypeAttributes &attrs, TypeRepr *repr,
2519+
TypeResolutionOptions options) {
2520+
assert(silContext);
2521+
assert(attrs.has(TAK_pack_element));
2522+
assert(attrs.OpenedID.hasValue());
2523+
2524+
attrs.clearAttribute(TAK_pack_element);
2525+
2526+
auto dc = getDeclContext();
2527+
auto &ctx = dc->getASTContext();
2528+
2529+
const SILTypeResolutionContext::OpenedPackElement *entry = nullptr;
2530+
if (const auto *openedPacksMap = silContext->OpenedPackElements) {
2531+
auto it = openedPacksMap->find(*attrs.OpenedID);
2532+
if (it != openedPacksMap->end()) {
2533+
entry = &it->second;
2534+
}
2535+
}
2536+
if (!entry) {
2537+
diagnoseInvalid(repr, attrs.getLoc(TAK_pack_element),
2538+
diag::sil_pack_element_uuid_not_found);
2539+
return ErrorType::get(ctx);
2540+
}
2541+
2542+
options.setContext(None);
2543+
2544+
// The interface type is the type wrapped by the attribute. Resolve it
2545+
// within the generic parameter list for the opened generic environment.
2546+
// Use structural resolution to avoid querying the DeclContext's
2547+
// generic signature, which is not the right signature for this.
2548+
auto structuralResolution = TypeResolution::forStructural(
2549+
dc, options,
2550+
/*unboundTyOpener*/ nullptr,
2551+
/*placeholderHandler*/ nullptr,
2552+
/*packElementOpener*/ nullptr);
2553+
auto interfaceType = [&] {
2554+
SILInnerGenericContextRAII scope(silContext, entry->Params);
2555+
2556+
TypeResolver interfaceTypeResolver(structuralResolution, silContext);
2557+
return interfaceTypeResolver.resolveType(repr, options);
2558+
}();
2559+
2560+
if (!interfaceType->isTypeParameter()) {
2561+
diagnoseInvalid(repr, attrs.getLoc(TAK_pack_element),
2562+
diag::opened_bad_interface_type,
2563+
interfaceType);
2564+
2565+
return ErrorType::get(ctx);
2566+
}
2567+
2568+
// Map the interface type into the element context.
2569+
auto archetypeType =
2570+
entry->Environment->mapPackTypeIntoElementContext(interfaceType);
2571+
if (archetypeType->hasError()) {
2572+
diagnoseInvalid(repr, attrs.getLoc(TAK_pack_element),
2573+
diag::opened_bad_interface_type,
2574+
interfaceType);
2575+
}
2576+
return archetypeType;
2577+
}
2578+
25102579
/// \returns true iff the # of isolated params is > \c lowerBound
25112580
static bool hasMoreIsolatedParamsThan(FunctionTypeRepr* fnTy, unsigned lowerBound) {
25122581
unsigned count = 0;
@@ -2953,6 +3022,8 @@ TypeResolver::resolveAttributedType(TypeAttributes &attrs, TypeRepr *repr,
29533022

29543023
if (attrs.has(TAK_opened)) {
29553024
ty = resolveOpenedExistentialArchetype(attrs, repr, options);
3025+
} else if (attrs.has(TAK_pack_element)) {
3026+
ty = resolvePackElementArchetype(attrs, repr, options);
29563027
}
29573028

29583029
auto instanceOptions = options;

test/SIL/Parser/variadic_generics.sil

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,14 @@ bb0:
3030
// CHECK: [[INNER_INDEX:%.*]] = dynamic_pack_index {{%.*}} of $Pack{repeat each T}
3131
// CHECK: [[INDEX:%.*]] = pack_pack_index 1, [[INNER_INDEX]] of $Pack{Int, repeat each T}
3232
// CHECK: {{%.*}} = open_pack_element [[INDEX]] of <U...> at <Pack{Int, repeat each T}>, shape $U, uuid "01234567-89AB-CDEF-0123-000000000002"
33+
// CHECK: metatype $@thick (@pack_element("01234567-89AB-CDEF-0123-000000000002") U).Type
3334
sil @test3 : $<T...> () -> () {
3435
bb0:
3536
%intIndex = integer_literal $Builtin.Word, 0
3637
%innerIndex = dynamic_pack_index %intIndex of $Pack{repeat each T}
3738
%index = pack_pack_index 1, %innerIndex of $Pack{Int, repeat each T}
3839
%0 = open_pack_element %index of <U...> at <Pack{Int, repeat each T}>, shape $U, uuid "01234567-89AB-CDEF-0123-000000000002"
40+
%metatype = metatype $@thick (@pack_element("01234567-89AB-CDEF-0123-000000000002") U).Type
3941
%ret = tuple ()
4042
return %ret : $()
4143
}

0 commit comments

Comments
 (0)