Skip to content

Qualify the names of extended types in module interfaces #32780

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

Closed
Closed
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
4 changes: 4 additions & 0 deletions include/swift/AST/PrintOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ struct PrintOptions {
/// type might be ambiguous.
bool FullyQualifiedTypesIfAmbiguous = false;

/// Whether to keep extended types from being printed fully qualified, even
/// if other types would be.
bool RemoveQualificationOfExtendedTypes = true;

/// If true, printed module names will use the "exported" name, which may be
/// different from the regular name.
///
Expand Down
9 changes: 6 additions & 3 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ PrintOptions PrintOptions::printSwiftInterfaceFile(bool preferTypeRepr,
result.PrintIfConfig = false;
result.FullyQualifiedTypes = true;
result.UseExportedModuleNames = true;
result.RemoveQualificationOfExtendedTypes = false;
result.AllowNullTypes = false;
result.SkipImports = true;
result.OmitNameOfInaccessibleProperties = true;
Expand Down Expand Up @@ -2185,8 +2186,10 @@ void PrintAST::visitImportDecl(ImportDecl *decl) {

static void printExtendedTypeName(Type ExtendedType, ASTPrinter &Printer,
PrintOptions Options) {
Options.FullyQualifiedTypes = false;
Options.FullyQualifiedTypesIfAmbiguous = false;
if (Options.RemoveQualificationOfExtendedTypes) {
Options.FullyQualifiedTypes = false;
Options.FullyQualifiedTypesIfAmbiguous = false;
}

// Strip off generic arguments, if any.
auto Ty = ExtendedType->getAnyNominal()->getDeclaredType();
Expand Down Expand Up @@ -2282,7 +2285,7 @@ void PrintAST::printExtension(ExtensionDecl *decl) {
recordDeclLoc(decl, [&]{
// We cannot extend sugared types.
Type extendedType = decl->getExtendedType();
if (!extendedType) {
if (!extendedType || Options.PreferTypeRepr) {
// Fallback to TypeRepr.
printTypeLoc(decl->getExtendedTypeRepr());
return;
Expand Down
34 changes: 17 additions & 17 deletions test/ModuleInterface/access-filter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public protocol PublicProto {
func requirement()
} // CHECK-NEXT: {{^[}]$}}

// CHECK: extension PublicProto {{[{]$}}
// CHECK: extension AccessFilter.PublicProto {{[{]$}}
extension PublicProto {
// CHECK: public func publicMethod(){{$}}
public func publicMethod() {}
Expand All @@ -64,7 +64,7 @@ extension PublicProto {
@usableFromInline internal func ufiMethod() {}
} // CHECK: {{^[}]$}}

// CHECK: {{^}}extension PublicProto {{[{]$}}
// CHECK: {{^}}extension AccessFilter.PublicProto {{[{]$}}
public extension PublicProto {
// CHECK: public func publicExtPublicMethod(){{$}}
func publicExtPublicMethod() {}
Expand Down Expand Up @@ -96,7 +96,7 @@ internal protocol UFIProto {
func requirement()
} // CHECK-NEXT: {{^[}]$}}

// CHECK: extension UFIProto {{[{]$}}
// CHECK: extension AccessFilter.UFIProto {{[{]$}}
extension UFIProto {
// CHECK: public func publicMethod(){{$}}
public func publicMethod() {}
Expand All @@ -107,7 +107,7 @@ extension UFIProto {
@usableFromInline internal func ufiMethod() {}
} // CHECK: {{^[}]$}}

// CHECK: extension PublicStruct {{[{]$}}
// CHECK: extension AccessFilter.PublicStruct {{[{]$}}
extension PublicStruct {
// CHECK: @_hasInitialValue public static var secretlySettable: Swift.Int {
// CHECK-NEXT: get
Expand All @@ -120,7 +120,7 @@ extension InternalStruct_BAD: PublicProto {
internal static var dummy: Int { return 0 }
}

// CHECK: extension UFIStruct : AccessFilter.PublicProto {{[{]$}}
// CHECK: extension AccessFilter.UFIStruct : AccessFilter.PublicProto {{[{]$}}
extension UFIStruct: PublicProto {
// CHECK-NEXT: @usableFromInline
// CHECK-NEXT: internal typealias Assoc = Swift.Int
Expand Down Expand Up @@ -167,12 +167,12 @@ class InternalClass_BAD {
// CHECK: public struct GenericStruct<T>
public struct GenericStruct<T> {}

// CHECK: extension GenericStruct where T == AccessFilter.PublicStruct {{[{]$}}
// CHECK: extension AccessFilter.GenericStruct where T == AccessFilter.PublicStruct {{[{]$}}
extension GenericStruct where T == AccessFilter.PublicStruct {
// CHECK-NEXT: public func constrainedToPublicStruct(){{$}}
public func constrainedToPublicStruct() {}
} // CHECK-NEXT: {{^[}]$}}
// CHECK: extension GenericStruct where T == AccessFilter.UFIStruct {{[{]$}}
// CHECK: extension AccessFilter.GenericStruct where T == AccessFilter.UFIStruct {{[{]$}}
extension GenericStruct where T == AccessFilter.UFIStruct {
// CHECK-NEXT: @usableFromInline{{$}}
// CHECK-NEXT: internal func constrainedToUFIStruct(){{$}}
Expand All @@ -182,12 +182,12 @@ extension GenericStruct where T == InternalStruct_BAD {
@usableFromInline internal func constrainedToInternalStruct_BAD() {}
}

// CHECK: extension GenericStruct where T == AccessFilter.PublicStruct {{[{]$}}
// CHECK: extension AccessFilter.GenericStruct where T == AccessFilter.PublicStruct {{[{]$}}
extension GenericStruct where PublicStruct == T {
// CHECK-NEXT: public func constrainedToPublicStruct2(){{$}}
public func constrainedToPublicStruct2() {}
} // CHECK-NEXT: {{^[}]$}}
// CHECK: extension GenericStruct where T == AccessFilter.UFIStruct {{[{]$}}
// CHECK: extension AccessFilter.GenericStruct where T == AccessFilter.UFIStruct {{[{]$}}
extension GenericStruct where UFIStruct == T {
// CHECK-NEXT: @usableFromInline{{$}}
// CHECK-NEXT: internal func constrainedToUFIStruct2(){{$}}
Expand All @@ -197,12 +197,12 @@ extension GenericStruct where InternalStruct_BAD == T {
@usableFromInline internal func constrainedToInternalStruct2_BAD() {}
}

// CHECK: extension GenericStruct where T : AccessFilter.PublicProto {{[{]$}}
// CHECK: extension AccessFilter.GenericStruct where T : AccessFilter.PublicProto {{[{]$}}
extension GenericStruct where T: PublicProto {
// CHECK-NEXT: public func constrainedToPublicProto(){{$}}
public func constrainedToPublicProto() {}
} // CHECK-NEXT: {{^[}]$}}
// CHECK: extension GenericStruct where T : AccessFilter.UFIProto {{[{]$}}
// CHECK: extension AccessFilter.GenericStruct where T : AccessFilter.UFIProto {{[{]$}}
extension GenericStruct where T: UFIProto {
// CHECK-NEXT: @usableFromInline{{$}}
// CHECK-NEXT: internal func constrainedToUFIProto(){{$}}
Expand All @@ -212,12 +212,12 @@ extension GenericStruct where T: InternalProto_BAD {
@usableFromInline internal func constrainedToInternalProto_BAD() {}
}

// CHECK: extension GenericStruct where T : AccessFilter.PublicClass {{[{]$}}
// CHECK: extension AccessFilter.GenericStruct where T : AccessFilter.PublicClass {{[{]$}}
extension GenericStruct where T: PublicClass {
// CHECK-NEXT: public func constrainedToPublicClass(){{$}}
public func constrainedToPublicClass() {}
} // CHECK-NEXT: {{^[}]$}}
// CHECK: extension GenericStruct where T : AccessFilter.UFIClass {{[{]$}}
// CHECK: extension AccessFilter.GenericStruct where T : AccessFilter.UFIClass {{[{]$}}
extension GenericStruct where T: UFIClass {
// CHECK-NEXT: @usableFromInline{{$}}
// CHECK-NEXT: internal func constrainedToUFIClass(){{$}}
Expand All @@ -227,7 +227,7 @@ extension GenericStruct where T: InternalClass_BAD {
@usableFromInline internal func constrainedToInternalClass_BAD() {}
}

// CHECK: extension GenericStruct where T : AnyObject {{[{]$}}
// CHECK: extension AccessFilter.GenericStruct where T : AnyObject {{[{]$}}
extension GenericStruct where T: AnyObject {
// CHECK-NEXT: public func constrainedToAnyObject(){{$}}
public func constrainedToAnyObject() {}
Expand All @@ -245,12 +245,12 @@ internal typealias InternalAlias_BAD = PublicAliasBase

internal typealias ReallyInternalAlias_BAD = ReallyInternalAliasBase_BAD

// CHECK: extension GenericStruct where T == AccessFilter.PublicAlias {{[{]$}}
// CHECK: extension AccessFilter.GenericStruct where T == AccessFilter.PublicAlias {{[{]$}}
extension GenericStruct where T == PublicAlias {
// CHECK-NEXT: public func constrainedToPublicAlias(){{$}}
public func constrainedToPublicAlias() {}
} // CHECK-NEXT: {{^[}]$}}
// CHECK: extension GenericStruct where T == AccessFilter.UFIAlias {{[{]$}}
// CHECK: extension AccessFilter.GenericStruct where T == AccessFilter.UFIAlias {{[{]$}}
extension GenericStruct where T == UFIAlias {
// CHECK-NEXT: @usableFromInline{{$}}
// CHECK-NEXT: internal func constrainedToUFIAlias(){{$}}
Expand All @@ -275,7 +275,7 @@ extension GenericStruct: PublicProto where T: InternalProto_BAD {

public struct MultiGenericStruct<First, Second> {}

// CHECK: extension MultiGenericStruct where First == AccessFilter.PublicStruct, Second == AccessFilter.PublicStruct {{[{]$}}
// CHECK: extension AccessFilter.MultiGenericStruct where First == AccessFilter.PublicStruct, Second == AccessFilter.PublicStruct {{[{]$}}
extension MultiGenericStruct where First == PublicStruct, Second == PublicStruct {
// CHECK-NEXT: public func publicPublic(){{$}}
public func publicPublic() {}
Expand Down
30 changes: 15 additions & 15 deletions test/ModuleInterface/conformances.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,21 +57,21 @@ public struct B3: PublicBaseProto & PrivateSubProto {}
public struct B4: PublicBaseProto {}
extension B4: PrivateSubProto {}
// CHECK: public struct B5 {
// CHECK: extension B5 : conformances.PublicBaseProto {
// NEGATIVE-NOT: extension conformances.B5
// CHECK: extension conformances.B5 : conformances.PublicBaseProto {
// NEGATIVE-NOT: extension B5
public struct B5: PrivateSubProto {}
extension B5: PublicBaseProto {}
// CHECK: public struct B6 {
// NEGATIVE-NOT: extension B6 {
// CHECK: extension B6 : conformances.PublicBaseProto {
// NEGATIVE-NOT: extension conformances.B6
// NEGATIVE-NOT: extension conformances.B6 {
// CHECK: extension conformances.B6 : conformances.PublicBaseProto {
// NEGATIVE-NOT: extension B6
public struct B6 {}
extension B6: PrivateSubProto {}
extension B6: PublicBaseProto {}
// CHECK: public struct B7 {
// CHECK: extension B7 : conformances.PublicBaseProto {
// NEGATIVE-NOT: extension B7 {
// NEGATIVE-NOT: extension conformances.B7
// CHECK: extension conformances.B7 : conformances.PublicBaseProto {
// NEGATIVE-NOT: extension conformances.B7 {
// NEGATIVE-NOT: extension B7
public struct B7 {}
extension B7: PublicBaseProto {}
extension B7: PrivateSubProto {}
Expand Down Expand Up @@ -107,7 +107,7 @@ public struct C1: PrivateSubProto, AnotherPrivateSubProto {}
// CHECK-END: extension conformances.C2 : conformances.PublicBaseProto {}
public struct C2: PrivateSubProto & AnotherPrivateSubProto {}
// CHECK: public struct C3 {
// NEGATIVE-NOT: extension C3 {
// NEGATIVE-NOT: extension conformances.C3 {
// CHECK-END: extension conformances.C3 : conformances.PublicBaseProto {}
public struct C3: PrivateSubProto {}
extension C3: AnotherPrivateSubProto {}
Expand All @@ -130,13 +130,13 @@ public struct D3: PrivateSubProto & PublicSubProto {}
// CHECK-END: extension conformances.D4 : conformances.PublicBaseProto {}
public struct D4: APublicSubProto & PrivateSubProto {}
// CHECK: public struct D5 {
// CHECK: extension D5 : conformances.PublicSubProto {
// NEGATIVE-NOT: extension conformances.D5
// CHECK: extension conformances.D5 : conformances.PublicSubProto {
// NEGATIVE-NOT: extension D5
public struct D5: PrivateSubProto {}
extension D5: PublicSubProto {}
// CHECK: public struct D6 : conformances.PublicSubProto {
// NEGATIVE-NOT: extension D6 {
// NEGATIVE-NOT: extension conformances.D6
// NEGATIVE-NOT: extension conformances.D6 {
// NEGATIVE-NOT: extension D6
public struct D6: PublicSubProto {}
extension D6: PrivateSubProto {}

Expand Down Expand Up @@ -217,12 +217,12 @@ extension PrivateProtoConformer : PrivateProto {
public var member: Int { return 0 }
}
// CHECK: public struct PrivateProtoConformer {
// CHECK: extension PrivateProtoConformer {
// CHECK: extension conformances.PrivateProtoConformer {
// CHECK-NEXT: public var member: Swift.Int {
// CHECK-NEXT: get
// CHECK-NEXT: }
// CHECK-NEXT: {{^}$}}
// NEGATIVE-NOT: extension conformances.PrivateProtoConformer
// NEGATIVE-NOT: extension PrivateProtoConformer

// NEGATIVE-NOT: extension {{(Swift.)?}}Bool{{.+}}Hashable
// NEGATIVE-NOT: extension {{(Swift.)?}}Bool{{.+}}Equatable
Expand Down
2 changes: 1 addition & 1 deletion test/ModuleInterface/synthesized.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public enum NoRawValueWithExplicitHashable {
case a, b, c
} // CHECK: {{^}$}}

// CHECK-LABEL: extension NoRawValueWithExplicitHashable : Swift.Hashable {
// CHECK-LABEL: extension synthesized.NoRawValueWithExplicitHashable : Swift.Hashable {
extension NoRawValueWithExplicitHashable : Hashable {
// CHECK-NEXT: public func foo()
public func foo() {}
Expand Down
4 changes: 2 additions & 2 deletions test/ModuleInterface/where-clause.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ public struct Holder<Value> {
// CHECK-NEXT: }
}

// CHECK-NEXT: extension Holder.Transform where Value == Swift.Int {
// CHECK-NEXT: extension main.Holder.Transform where Value == Swift.Int {
extension Holder.Transform where Value == Int {
// CHECK-NEXT: public func negate(_ holder: main.Holder<Value>) -> Result{{$}}
public func negate(_ holder: Holder<Value>) -> Result {
return transform(Holder(value: -holder.value))
}
}
}
24 changes: 21 additions & 3 deletions test/NameLookup/stdlib_shadowing.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/HasResult.swift
// RUN: %target-swift-frontend -typecheck %s -I %t -verify
// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/HasResult.swift -enable-library-evolution -swift-version 5
// RUN: %target-swift-frontend -typecheck %s -I %t -verify -enable-library-evolution -emit-module-interface-path %t/stdlib_shadowing.swiftinterface -swift-version 5

// Since HasResult is right here, let's make sure we emit interfaces correctly.
// RUN: %FileCheck %s < %t/stdlib_shadowing.swiftinterface

import HasResult

func foo() -> Result<Int, Error> {
public func foo() -> Result<Int, Error> {
return Result<Int, Error>.success(42)
}
// CHECK: public func foo() -> HasResult.Result

extension Result {
public func library() {}
}
// CHECK: extension HasResult.Result {
// CHECK-NEXT: public func library()
// CHECK-NEXT: }

extension Swift.Result {
public func stdlib() {}
}
// CHECK: extension Swift.Result {
// CHECK-NEXT: public func stdlib()
// CHECK-NEXT: }
8 changes: 4 additions & 4 deletions test/SPI/private_swiftinterface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ public func foo() {}
}

@_spi(MySPI) public extension SPIClassLocal {
// CHECK-PRIVATE: @_spi(MySPI) extension SPIClassLocal
// CHECK-PUBLIC-NOT: extension SPIClassLocal
// CHECK-PRIVATE: @_spi(MySPI) extension {{.*}}.SPIClassLocal
// CHECK-PUBLIC-NOT: extension SPIHelper.SPIClassLocal

@_spi(MySPI) func extensionMethod() {}
// CHECK-PRIVATE: @_spi(MySPI) public func extensionMethod
Expand Down Expand Up @@ -80,7 +80,7 @@ private class PrivateClassLocal {}
// CHECK-PUBLIC-NOT: useOfSPITypeOk

@_spi(LocalSPI) extension SPIClass {
// CHECK-PRIVATE: @_spi(LocalSPI) extension SPIClass
// CHECK-PRIVATE: @_spi(LocalSPI) extension {{.*}}.SPIClass
// CHECK-PUBLIC-NOT: SPIClass

@_spi(LocalSPI) public func extensionSPIMethod() {}
Expand All @@ -100,7 +100,7 @@ private protocol PrivateConstraint {}

@_spi(LocalSPI)
extension PublicType: SPIProto2 where T: SPIProto2 {}
// CHECK-PRIVATE: extension PublicType : {{.*}}.SPIProto2 where T : {{.*}}.SPIProto2
// CHECK-PRIVATE: extension {{.*}}.PublicType : {{.*}}.SPIProto2 where T : {{.*}}.SPIProto2
// CHECK-PUBLIC-NOT: _ConstraintThatIsNotPartOfTheAPIOfThisLibrary

// The dummy conformance should be only in the private swiftinterface for
Expand Down
3 changes: 2 additions & 1 deletion test/SourceKit/CodeComplete/complete_swiftinterface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

// 1) Build .swiftinterface files for MyPoint and MyExtensions, using a non-default module cache path
// RUN: %target-swift-frontend -emit-module-interface-path %t/MyPoint.swiftinterface -module-name MyPoint -emit-module -o /dev/null %S/Inputs/parseable-interface/MyPoint.swift
// RUN: %target-swift-frontend -emit-module-interface-path %t/MyPointExtensions.swiftinterface -module-name MyPointExtensions -emit-module -o /dev/null -module-cache-path %t/modulecache -I %t %S/Inputs/parseable-interface/MyPointExtensions.swift
// FIXME: Since we're extending MyPoint.MyPoint, we need -module-interface-preserve-types-as-written
// RUN: %target-swift-frontend -emit-module-interface-path %t/MyPointExtensions.swiftinterface -module-interface-preserve-types-as-written -module-name MyPointExtensions -emit-module -o /dev/null -module-cache-path %t/modulecache -I %t %S/Inputs/parseable-interface/MyPointExtensions.swift
// RUN: %empty-directory(%t/modulecache)

// 2) Check completion using the default (cold) module cache
Expand Down