Skip to content

Commit dec124e

Browse files
authored
Merge pull request #80213 from slavapestov/protocol-order-fix
AST: Fix a problem with the protocol order
2 parents c824be3 + a7d2b24 commit dec124e

4 files changed

+66
-3
lines changed

Diff for: lib/AST/Decl.cpp

+24-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
//
1616
//===----------------------------------------------------------------------===//
1717

18+
#include "swift/Strings.h"
1819
#include "swift/AST/Decl.h"
1920
#include "swift/AST/ASTContext.h"
2021
#include "swift/AST/ASTMangler.h"
@@ -5434,9 +5435,29 @@ int TypeDecl::compare(const TypeDecl *type1, const TypeDecl *type2) {
54345435

54355436
// Prefer module names earlier in the alphabet.
54365437
if (dc1->isModuleScopeContext() && dc2->isModuleScopeContext()) {
5437-
auto module1 = dc1->getParentModule();
5438-
auto module2 = dc2->getParentModule();
5439-
if (int result = module1->getName().str().compare(module2->getName().str()))
5438+
// For protocol declarations specifically, the order here is part
5439+
// of the ABI, and so we must take care to get the correct module
5440+
// name for the comparison.
5441+
auto getModuleNameForOrder = [&](const TypeDecl *decl) -> StringRef {
5442+
// Respect @_originallyDefinedIn on the type itself, so that
5443+
// moving a protocol across modules does not change its
5444+
// position in the order.
5445+
auto alternateName = decl->getAlternateModuleName();
5446+
if (!alternateName.empty())
5447+
return alternateName;
5448+
5449+
// This used to just call getName(), which caused accidental ABI breaks
5450+
// when a module is imported under different aliases.
5451+
//
5452+
// Ideally, we would use getABIName() here. However, this would
5453+
// cause ABI breaks with the _Concurrency and CompilerSwiftSyntax
5454+
// builds, which already passed in a -module-abi-name but had
5455+
// existing symbols mangled with the wrong order.
5456+
auto *module = decl->getDeclContext()->getParentModule();
5457+
return module->getRealName().str();
5458+
};
5459+
5460+
if (int result = getModuleNameForOrder(type1).compare(getModuleNameForOrder(type2)))
54405461
return result;
54415462
}
54425463

Diff for: test/SILGen/conformance_requirement_order.swift

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module %s -module-name Horse -D LIB -emit-module-path %t/Horse.swiftmodule
3+
// RUN: %target-swift-emit-silgen %s -module-name main -I %t -module-alias SwiftHorse=Horse | %FileCheck %s
4+
5+
#if LIB
6+
public protocol Equine {}
7+
#else
8+
import SwiftHorse
9+
10+
// Make sure we use the module's real name, and not its alias name, so that
11+
// we always have Horse.Equine < Swift.Equatable. If this doesn't hold, the
12+
// two requirements in the mangling will be flipped.
13+
14+
// CHECK-LABEL: sil hidden [ossa] @$s4main21requirementOrderHorseyyx0D06EquineRzSQRzlF : $@convention(thin) <T where T : Equine, T : Equatable> (@in_guaranteed T) -> () {
15+
func requirementOrderHorse<T: Equine & Equatable>(_: T) {}
16+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %target-swift-emit-silgen %s -module-name main | %FileCheck %s
2+
3+
// See conformance_requirement_order.swift for the general case.
4+
//
5+
// Make sure that protocols from the _Concurrency module are ordered using
6+
// their real module name and not their ABI module name, which is "Swift".
7+
//
8+
// This was a mistake since they mangle like protocols from "Swift", but
9+
// at this point we cannot break existing code.
10+
11+
// CHECK-LABEL: sil hidden [ossa] @$s4main27requirementOrderConcurrencyyyxSTRzScFRzlF : $@convention(thin) <T where T : Sequence, T : Executor> (@guaranteed T) -> () {
12+
func requirementOrderConcurrency<T: Executor & Sequence>(_: T) {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %target-swift-emit-silgen %s -module-name main | %FileCheck %s
2+
3+
// REQUIRES: OS=macosx
4+
5+
@_originallyDefinedIn(module: "AnimalKit", macOS 10.10)
6+
@available(macOS 10.9, *)
7+
public protocol Ungulate {}
8+
9+
@_originallyDefinedIn(module: "HorseKit", macOS 10.10)
10+
@available(macOS 10.9, *)
11+
public protocol Horse {}
12+
13+
// CHECK-LABEL: sil [ossa] @$s4main39requirementOrderWithOriginallyDefinedInyyx9AnimalKit8UngulateRz05HorseI00K0RzlF : $@convention(thin) <T where T : Ungulate, T : Horse> (@in_guaranteed T) -> () {
14+
public func requirementOrderWithOriginallyDefinedIn<T: Ungulate & Horse>(_: T) {}

0 commit comments

Comments
 (0)