Skip to content

Fixes for printing variadic generic types #62180

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 10 commits into from
Dec 2, 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
13 changes: 7 additions & 6 deletions include/swift/AST/PackExpansionMatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,18 @@ namespace swift {

class ASTContext;

/// The result of a match. If one of lhs or rhs is a pack expansion type,
/// the other one is a pack type.
/// The result of a match. An important invariant is that either both types
/// are PackExpansionTypes, or both types are scalars. In particular, any
/// PackTypes are always wrapped in a PackExpansionType.
struct MatchedPair {
Type lhs;
Type rhs;

// An index into the original left-hand side.
unsigned idx;
unsigned lhsIdx;
unsigned rhsIdx;

MatchedPair(Type lhs, Type rhs, unsigned idx)
: lhs(lhs), rhs(rhs), idx(idx) {}
MatchedPair(Type lhs, Type rhs, unsigned lhsIdx, unsigned rhsIdx)
: lhs(lhs), rhs(rhs), lhsIdx(lhsIdx), rhsIdx(rhsIdx) {}
};

/// Performs a structural match of two lists of tuple elements. The invariant
Expand Down
1 change: 0 additions & 1 deletion include/swift/AST/TypeRepr.h
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,6 @@ class GenericIdentTypeRepr final : public ComponentIdentTypeRepr,
: ComponentIdentTypeRepr(TypeReprKind::GenericIdent, Loc, Id),
AngleBrackets(AngleBrackets) {
Bits.GenericIdentTypeRepr.NumGenericArgs = GenericArgs.size();
assert(!GenericArgs.empty());
#ifndef NDEBUG
for (auto arg : GenericArgs)
assert(arg != nullptr);
Expand Down
9 changes: 9 additions & 0 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class Identifier;
class InOutType;
class OpaqueTypeDecl;
class OpenedArchetypeType;
class PackType;
class PlaceholderTypeRepr;
enum class ReferenceCounting : uint8_t;
enum class ResilienceExpansion : unsigned;
Expand Down Expand Up @@ -2002,6 +2003,8 @@ class TypeAliasType final
/// this type references.
ArrayRef<Type> getDirectGenericArgs() const;

PackType *getExpandedGenericArgsPack();

// Support for FoldingSet.
void Profile(llvm::FoldingSetNodeID &id) const;

Expand Down Expand Up @@ -2420,6 +2423,8 @@ class BoundGenericType : public NominalOrBoundGenericNominalType,
return {getTrailingObjectsPointer(), Bits.BoundGenericType.GenericArgCount};
}

PackType *getExpandedGenericArgsPack();

void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getDecl(), getParent(), getGenericArgs());
}
Expand Down Expand Up @@ -6478,6 +6483,10 @@ class PackType final : public TypeBase, public llvm::FoldingSetNode,
/// Creates a pack from the types in \p elements.
static PackType *get(const ASTContext &C, ArrayRef<Type> elements);

static PackType *get(const ASTContext &C,
TypeArrayView<GenericTypeParamType> params,
ArrayRef<Type> args);

public:
/// Retrieves the number of elements in this pack.
unsigned getNumElements() const { return Bits.PackType.Count; }
Expand Down
5 changes: 0 additions & 5 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3258,11 +3258,6 @@ PackType *PackType::get(const ASTContext &C, ArrayRef<Type> elements) {
RecursiveTypeProperties properties;
bool isCanonical = true;
for (Type eltTy : elements) {
assert(!eltTy->isTypeParameter() ||
!eltTy->getRootGenericParam()->isParameterPack() &&
"Pack type parameter outside of a pack expansion");
assert(!eltTy->is<PackArchetypeType>() &&
"Pack type archetype outside of a pack expansion");
assert(!eltTy->is<PackType>() &&
"Cannot have pack directly inside another pack");

Expand Down
52 changes: 33 additions & 19 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5282,15 +5282,20 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
Optional<llvm::DenseMap<const clang::Module *, ModuleDecl *>>
VisibleClangModules;

void printGenericArgs(ArrayRef<Type> Args) {
if (Args.empty())
return;

void printGenericArgs(PackType *flatArgs) {
Printer << "<";
interleave(Args, [&](Type Arg) { visit(Arg); }, [&] { Printer << ", "; });
interleave(flatArgs->getElementTypes(),
[&](Type arg) { visit(arg); },
[&] { Printer << ", "; });
Printer << ">";
}

void printGenericArgs(ASTContext &ctx,
TypeArrayView<GenericTypeParamType> params,
ArrayRef<Type> args) {
printGenericArgs(PackType::get(ctx, params, args));
}

/// Helper function for printing a type that is embedded within a larger type.
///
/// This is necessary whenever the inner type may not normally be represented
Expand Down Expand Up @@ -5626,7 +5631,11 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
}

printQualifiedType(T);
printGenericArgs(T->getDirectGenericArgs());

auto *typeAliasDecl = T->getDecl();
if (typeAliasDecl->isGeneric()) {
printGenericArgs(T->getExpandedGenericArgsPack());
}
}

void visitParenType(ParenType *T) {
Expand Down Expand Up @@ -5711,7 +5720,8 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
}
}
printQualifiedType(T);
printGenericArgs(T->getGenericArgs());

printGenericArgs(T->getExpandedGenericArgsPack());
}

void visitParentType(Type T) {
Expand Down Expand Up @@ -6525,6 +6535,11 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
return false;
};

OpaqueTypeDecl *decl = T->getDecl();
auto *namingDecl = decl->getNamingDecl();
auto genericSig = namingDecl->getInnermostDeclContext()
->getGenericSignatureOfContext();

switch (Options.OpaqueReturnTypePrinting) {
case PrintOptions::OpaqueReturnTypePrintingMode::WithOpaqueKeyword:
if (printNamedOpaque())
Expand All @@ -6542,8 +6557,6 @@ class TypePrinter : public TypeVisitor<TypePrinter> {

// Opaque archetype substitutions are always canonical, so re-sugar the
// constraint type using the owning declaration's generic parameter names.
auto genericSig = T->getDecl()->getNamingDecl()->getInnermostDeclContext()
->getGenericSignatureOfContext();
if (genericSig)
constraint = genericSig->getSugaredType(constraint);

Expand All @@ -6556,7 +6569,6 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
// turn this back into a reference to the naming decl for the opaque
// type.
Printer << "@_opaqueReturnTypeOf(";
OpaqueTypeDecl *decl = T->getDecl();

Printer.printEscapedStringLiteral(
decl->getOpaqueReturnTypeIdentifier().str());
Expand All @@ -6570,22 +6582,24 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
// attribute to apply to, but the attribute alone references the opaque
// type.
Printer << ") __";
printGenericArgs(T->getSubstitutions().getReplacementTypes());

if (genericSig) {
printGenericArgs(decl->getASTContext(),
genericSig.getGenericParams(),
T->getSubstitutions().getReplacementTypes());
}
return;
}
case PrintOptions::OpaqueReturnTypePrintingMode::Description: {
// TODO(opaque): present opaque types with user-facing syntax. we should
// probably print this as `some P` and record the fact that we printed that
// so that diagnostics can add followup notes.
Printer << "(return type of " << T->getDecl()->getNamingDecl()->printRef();
Printer << "(return type of " << namingDecl->printRef();
Printer << ')';
if (!T->getSubstitutions().empty()) {
Printer << '<';
auto replacements = T->getSubstitutions().getReplacementTypes();
llvm::interleave(
replacements.begin(), replacements.end(), [&](Type t) { visit(t); },
[&] { Printer << ", "; });
Printer << '>';
if (genericSig) {
printGenericArgs(decl->getASTContext(),
genericSig.getGenericParams(),
T->getSubstitutions().getReplacementTypes());
}
return;
}
Expand Down
Loading