Skip to content

[ASTPrinter] Simplify archetype printing by visiting the interface type. #59233

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 1 commit into from
Jun 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
62 changes: 24 additions & 38 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6289,8 +6289,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {

void visitOpenedArchetypeType(OpenedArchetypeType *T) {
if (auto parent = T->getParent()) {
visitParentType(parent);
printArchetypeCommon(T, getAbstractTypeParamDecl(T));
printArchetypeCommon(T);
return;
}

Expand All @@ -6299,8 +6298,20 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
visit(T->getExistentialType());
}

void printArchetypeCommon(ArchetypeType *T,
const AbstractTypeParamDecl *Decl) {
void printDependentMember(DependentMemberType *T) {
if (auto *const Assoc = T->getAssocType()) {
if (Options.ProtocolQualifiedDependentMemberTypes) {
Printer << "[";
Printer.printName(Assoc->getProtocol()->getName());
Printer << "]";
}
Printer.printTypeRef(T, Assoc, T->getName());
} else {
Printer.printName(T->getName());
}
}

void printArchetypeCommon(ArchetypeType *T) {
if (Options.AlternativeTypeNames) {
auto found = Options.AlternativeTypeNames->find(T->getCanonicalType());
if (found != Options.AlternativeTypeNames->end()) {
Expand All @@ -6309,36 +6320,22 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
}
}

const auto Name = T->getName();
if (Name.empty()) {
Printer << "<anonymous>";
} else if (Decl) {
Printer.printTypeRef(T, Decl, Name);
auto interfaceType = T->getInterfaceType();
if (auto *dependentMember = interfaceType->getAs<DependentMemberType>()) {
visitParentType(T->getParent());
printDependentMember(dependentMember);
} else {
Printer.printName(Name);
visit(interfaceType);
}
}

static AbstractTypeParamDecl *getAbstractTypeParamDecl(ArchetypeType *T) {
if (auto gp = T->getInterfaceType()->getAs<GenericTypeParamType>()) {
return gp->getDecl();
}

auto depMemTy = T->getInterfaceType()->castTo<DependentMemberType>();
return depMemTy->getAssocType();
}

void visitPrimaryArchetypeType(PrimaryArchetypeType *T) {
if (auto parent = T->getParent())
visitParentType(parent);

printArchetypeCommon(T, getAbstractTypeParamDecl(T));
printArchetypeCommon(T);
}

void visitOpaqueTypeArchetypeType(OpaqueTypeArchetypeType *T) {
if (auto parent = T->getParent()) {
visitParentType(parent);
printArchetypeCommon(T, getAbstractTypeParamDecl(T));
printArchetypeCommon(T);
return;
}

Expand Down Expand Up @@ -6415,9 +6412,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
}

void visitSequenceArchetypeType(SequenceArchetypeType *T) {
if (auto parent = T->getParent())
visitParentType(parent);
printArchetypeCommon(T, getAbstractTypeParamDecl(T));
printArchetypeCommon(T);
}

void visitGenericTypeParamType(GenericTypeParamType *T) {
Expand Down Expand Up @@ -6475,16 +6470,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {

void visitDependentMemberType(DependentMemberType *T) {
visitParentType(T->getBase());
if (auto *const Assoc = T->getAssocType()) {
if (Options.ProtocolQualifiedDependentMemberTypes) {
Printer << "[";
Printer.printName(Assoc->getProtocol()->getName());
Printer << "]";
}
Printer.printTypeRef(T, Assoc, T->getName());
} else {
Printer.printName(T->getName());
}
printDependentMember(T);
}

#define REF_STORAGE(Name, name, ...) \
Expand Down
6 changes: 6 additions & 0 deletions lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6242,6 +6242,12 @@ bool TypeBase::hasSimpleTypeRepr() const {
case TypeKind::OpenedArchetype:
return false;

case TypeKind::PrimaryArchetype: {
auto archetype = cast<const PrimaryArchetypeType>(this);
auto interface = archetype->getInterfaceType();
return interface->hasSimpleTypeRepr();
}

case TypeKind::ProtocolComposition: {
// 'Any', 'AnyObject' and single protocol compositions are simple
auto composition = cast<const ProtocolCompositionType>(this);
Expand Down
4 changes: 2 additions & 2 deletions test/Generics/opaque_archetype_concrete_requirement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ struct DefinesOpaqueP1 : P {
struct ConcreteHasP<T : P1, TT : P2, TU> {}

// CHECK-LABEL: ExtensionDecl line={{.*}} base=ConcreteHasP
// CHECK-NEXT: Generic signature: <T, TT, TU where T == some P1, TT == (some P1).T, TU == (some P1).U>
// CHECK-NEXT: Generic signature: <T, TT, TU where T == some P1, TT == (some P1).[P1]T, TU == (some P1).[P1]U>
extension ConcreteHasP where T == DefinesOpaqueP1.T, TT == T.T, TU == T.U {
func checkSameType1(_ t: TT) -> DefinesOpaqueP1.T.T { return t }
func checkSameType2(_ u: TU) -> DefinesOpaqueP1.T.U { return u }
Expand All @@ -47,7 +47,7 @@ protocol HasP {
}

// CHECK-LABEL: ExtensionDecl line={{.*}} base=HasP
// CHECK-NEXT: Generic signature: <Self where Self : HasP, Self.[HasP]T == some P1, Self.[HasP]U == G<(some P1).T>>
// CHECK-NEXT: Generic signature: <Self where Self : HasP, Self.[HasP]T == some P1, Self.[HasP]U == G<(some P1).[P1]T>>
extension HasP where T == DefinesOpaqueP1.T, U == G<T.T> {
func checkSameType1(_ t: T.T) -> DefinesOpaqueP1.T.T { return t }
func checkSameType2(_ u: T.U) -> DefinesOpaqueP1.T.U { return u }
Expand Down
8 changes: 8 additions & 0 deletions test/type/opaque_parameters.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ protocol Q {
associatedtype A: P & Equatable

func f() -> A
func takesA(_: A)
}

extension Int: P { }
Expand All @@ -16,17 +17,24 @@ extension Array: Q where Element: P, Element: Equatable {
func f() -> Element {
return first!
}

func takesA(_: Element) {}
}

extension Set: Q where Element: P, Element: Equatable { // expected-warning {{redundant conformance constraint 'Element' : 'Equatable'}}
func f() -> Element {
return first!
}

func takesA(_: Element) {}
}

// expected-note@+2{{where 'some Q' = 'Int'}}
// expected-note@+1{{in call to function 'takesQ'}}
func takesQ(_ q: some Q) -> Bool {
// expected-error@+1 {{cannot convert value of type 'Int' to expected argument type '(some Q).A'}}
q.takesA(1)

return q.f() == q.f()
}

Expand Down