Skip to content

Commit 3938d56

Browse files
joewillsherDougGregor
authored andcommitted
[SE-0095] [Runtime], [Demangler], & AST printer updated to new composition syntax
- All parts of the compiler now use ‘P1 & P2’ syntax - The demangler and AST printer wrap the composition in parens if it is in a metatype lookup - IRGen mangles compositions differently - “protocol<>” is now “swift.Any” - “protocol<_TP1P,_TP1Q>” is now “_TP1P&_TP1Q” - Tests cases are updated and added to test the new syntax and mangling
1 parent 622c86b commit 3938d56

File tree

68 files changed

+321
-309
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+321
-309
lines changed

include/swift/AST/Types.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3476,7 +3476,7 @@ END_CAN_TYPE_WRAPPER(ProtocolType, NominalType)
34763476
/// \code
34773477
/// protocol P { /* ... */ }
34783478
/// protocol Q { /* ... */ }
3479-
/// var x : protocol<P, Q>
3479+
/// var x : P & Q
34803480
/// \endcode
34813481
///
34823482
/// Here, the type of x is a composition of the protocols 'P' and 'Q'.

lib/AST/ASTPrinter.cpp

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3294,6 +3294,12 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
32943294
return !arch->isOpenedExistential();
32953295
}
32963296

3297+
case TypeKind::ProtocolComposition: {
3298+
// 'Any' and single protocol compositions are simple
3299+
auto composition = type->getAs<ProtocolCompositionType>();
3300+
return composition->getProtocols().size() <= 1;
3301+
}
3302+
32973303
default:
32983304
return true;
32993305
}
@@ -4043,16 +4049,18 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
40434049
}
40444050

40454051
void visitProtocolCompositionType(ProtocolCompositionType *T) {
4046-
Printer << tok::kw_protocol << "<";
4047-
bool First = true;
4048-
for (auto Proto : T->getProtocols()) {
4049-
if (First)
4050-
First = false;
4051-
else
4052-
Printer << ", ";
4053-
visit(Proto);
4052+
if (T->getProtocols().empty()) {
4053+
Printer << "Any";
4054+
} else {
4055+
bool First = true;
4056+
for (auto Proto : T->getProtocols()) {
4057+
if (First)
4058+
First = false;
4059+
else
4060+
Printer << " & ";
4061+
visit(Proto);
4062+
}
40544063
}
4055-
Printer << ">";
40564064
}
40574065

40584066
void visitLValueType(LValueType *T) {

lib/AST/ArchetypeBuilder.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -826,23 +826,17 @@ void ArchetypeBuilder::PotentialArchetype::dump(llvm::raw_ostream &Out,
826826
if (!ConformsTo.empty()) {
827827
Out << " : ";
828828

829-
if (ConformsTo.size() != 1)
830-
Out << "protocol<";
831-
832829
bool First = true;
833830
for (const auto &ProtoAndSource : ConformsTo) {
834831
if (First)
835832
First = false;
836833
else
837-
Out << ", ";
834+
Out << " & ";
838835

839836
Out << ProtoAndSource.first->getName().str() << " [";
840837
ProtoAndSource.second.dump(Out, SrcMgr);
841838
Out << "]";
842839
}
843-
844-
if (ConformsTo.size() != 1)
845-
Out << ">";
846840
}
847841

848842
if (Representative != this) {

lib/AST/TypeRepr.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -434,16 +434,18 @@ ProtocolCompositionTypeRepr::create(ASTContext &C,
434434

435435
void ProtocolCompositionTypeRepr::printImpl(ASTPrinter &Printer,
436436
const PrintOptions &Opts) const {
437-
Printer << "protocol<";
438-
bool First = true;
439-
for (auto Proto : Protocols) {
440-
if (First)
441-
First = false;
442-
else
443-
Printer << ", ";
444-
printTypeRepr(Proto, Printer, Opts);
437+
if (Protocols.empty()) {
438+
Printer << "Any";
439+
} else {
440+
bool First = true;
441+
for (auto Proto : Protocols) {
442+
if (First)
443+
First = false;
444+
else
445+
Printer << " & ";
446+
printTypeRepr(Proto, Printer, Opts);
447+
}
445448
}
446-
Printer << ">";
447449
}
448450

449451
void MetatypeTypeRepr::printImpl(ASTPrinter &Printer,

lib/Basic/Demangle.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3465,12 +3465,10 @@ void NodePrinter::print(NodePointer pointer, bool asContext, bool suppressType)
34653465
NodePointer type_list = pointer->getChild(0);
34663466
if (!type_list)
34673467
return;
3468-
bool needs_proto_marker = (type_list->getNumChildren() != 1);
3469-
if (needs_proto_marker)
3470-
Printer << "protocol<";
3471-
printChildren(type_list, ", ");
3472-
if (needs_proto_marker)
3473-
Printer << ">";
3468+
if (type_list->getNumChildren() == 0)
3469+
Printer << "Any";
3470+
else
3471+
printChildren(type_list, " & ");
34743472
return;
34753473
}
34763474
case Node::Kind::Archetype: {

lib/IDE/TypeReconstruction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1890,7 +1890,7 @@ static void VisitNodeProtocolList(
18901890
nodes.push_back(cur_node->getFirstChild());
18911891
VisitNode(ast, nodes, protocol_types_result, generic_context);
18921892
if (protocol_types_result._error
1893-
.empty() /* cannot check for empty type list as protocol<> is allowed */) {
1893+
.empty() /* cannot check for empty type list as Any is allowed */) {
18941894
if (ast) {
18951895
result._types.push_back(
18961896
ProtocolCompositionType::get(*ast, protocol_types_result._types));

lib/IRGen/GenExistential.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,8 @@ class ExistentialTypeInfoBase : public Base,
258258

259259
/// A TypeInfo implementation for existential types, i.e., types like:
260260
/// Printable
261-
/// protocol<Printable, Serializable>
261+
/// Printable & Serializable
262+
/// Any
262263
/// with the semantic translation:
263264
/// \exists t : Printable . t
264265
/// t here is an ArchetypeType.

lib/IRGen/GenType.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1657,16 +1657,18 @@ llvm::StructType *IRGenModule::createNominalType(CanType type) {
16571657
llvm::StructType *
16581658
IRGenModule::createNominalType(ProtocolCompositionType *type) {
16591659
llvm::SmallString<32> typeName;
1660-
1660+
16611661
SmallVector<ProtocolDecl *, 4> protocols;
16621662
type->getAnyExistentialTypeProtocols(protocols);
1663-
1664-
typeName.append("protocol<");
1665-
for (unsigned i = 0, e = protocols.size(); i != e; ++i) {
1666-
if (i) typeName.push_back(',');
1667-
LinkEntity::forNonFunction(protocols[i]).mangle(typeName);
1663+
1664+
if (protocols.empty()) {
1665+
typeName.append("swift.Any");
1666+
} else {
1667+
for (unsigned i = 0, e = protocols.size(); i != e; ++i) {
1668+
if (i) typeName.push_back('&');
1669+
LinkEntity::forNonFunction(protocols[i]).mangle(typeName);
1670+
}
16681671
}
1669-
typeName.push_back('>');
16701672
return llvm::StructType::create(getLLVMContext(), typeName.str());
16711673
}
16721674

stdlib/public/runtime/Casting.cpp

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -123,34 +123,33 @@ static const char *_getProtocolName(const ProtocolDescriptor *protocol) {
123123
}
124124

125125
static void _buildExistentialTypeName(const ProtocolDescriptorList *protocols,
126+
TypeSyntaxLevel level,
126127
bool qualified,
127128
std::string &result) {
128129
auto options = Demangle::DemangleOptions();
129130
options.QualifyEntities = qualified;
130131
options.DisplayDebuggerGeneratedModule = false;
131-
132+
132133
// If there's only one protocol, the existential type name is the protocol
133-
// name.
134+
// name. If there are 0 protocols it is 'Any'
134135
auto descriptors = protocols->getProtocols();
136+
auto numProtocols = protocols->NumProtocols;
135137

136-
if (protocols->NumProtocols == 1) {
137-
auto name = _getProtocolName(descriptors[0]);
138-
result += Demangle::demangleTypeAsString(name,
139-
strlen(name),
140-
options);
141-
return;
142-
}
143-
144-
result += "protocol<";
145-
for (unsigned i = 0, e = protocols->NumProtocols; i < e; ++i) {
146-
if (i > 0)
147-
result += ", ";
148-
auto name = _getProtocolName(descriptors[i]);
149-
result += Demangle::demangleTypeAsString(name,
150-
strlen(name),
151-
options);
138+
if (numProtocols == 0) {
139+
result += "Any";
140+
} else {
141+
// compositions of more than 1 protocol need parens in .Type contexts
142+
bool needsParens = level >= TypeSyntaxLevel::TypeSimple && numProtocols != 1;
143+
if (needsParens) result += "(";
144+
for (unsigned i = 0, e = numProtocols; i < e; ++i) {
145+
if (i) result += " & ";
146+
auto name = _getProtocolName(descriptors[i]);
147+
result += Demangle::demangleTypeAsString(name,
148+
strlen(name),
149+
options);
150+
}
151+
if (needsParens) result += ")";
152152
}
153-
result += ">";
154153
}
155154

156155
static void _buildFunctionTypeName(const FunctionTypeMetadata *func,
@@ -233,7 +232,7 @@ static void _buildNameForMetadata(const Metadata *type,
233232
}
234233
case MetadataKind::Existential: {
235234
auto exis = static_cast<const ExistentialTypeMetadata *>(type);
236-
_buildExistentialTypeName(&exis->Protocols, qualified, result);
235+
_buildExistentialTypeName(&exis->Protocols, level, qualified, result);
237236
return;
238237
}
239238
case MetadataKind::ExistentialMetatype: {

stdlib/public/runtime/Reflection.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ - (id)debugQuickLookObject;
4747

4848
namespace {
4949

50-
/// The layout of protocol<>.
50+
/// The layout of Any.
5151
using Any = OpaqueExistentialContainer;
5252

5353
// Swift assumes Any is returned in memory.

test/1_stdlib/PrintDiagnostics.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
var stream = ""
44

5-
print(3, &stream) // expected-error{{'&' used with non-inout argument of type 'protocol<>'}}
6-
debugPrint(3, &stream) // expected-error{{'&' used with non-inout argument of type 'protocol<>'}}
5+
print(3, &stream) // expected-error{{'&' used with non-inout argument of type 'Any'}}
6+
debugPrint(3, &stream) // expected-error{{'&' used with non-inout argument of type 'Any'}}
77
print(3, &stream, appendNewline: false) // expected-error {{cannot pass immutable value as inout argument: implicit conversion from 'String' to 'OutputStream' requires a temporary}}
88
debugPrint(3, &stream, appendNewline: false) // expected-error {{cannot pass immutable value as inout argument: implicit conversion from 'String' to 'OutputStream' requires a temporary}}
99
print(4, quack: 5) // expected-error {{argument labels '(_:, quack:)' do not match any available overloads}}
10-
// expected-note@-1{{overloads for 'print' exist with these partially matching parameter lists: (protocol<>..., separator: String, terminator: String), (T, appendNewline: Bool), (T, inout OutputStream), (T, inout OutputStream, appendNewline: Bool)}}
10+
// expected-note@-1{{overloads for 'print' exist with these partially matching parameter lists: (Any..., separator: String, terminator: String), (T, appendNewline: Bool), (T, inout OutputStream), (T, inout OutputStream, appendNewline: Bool)}}

test/1_stdlib/Runtime.swift.gyb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ Runtime.test("typeName") {
311311
expectEqual("a.SomeClass", _typeName(SomeClass.self))
312312
expectEqual("a.SomeStruct", _typeName(SomeStruct.self))
313313
expectEqual("a.SomeEnum", _typeName(SomeEnum.self))
314-
expectEqual("protocol<>.Protocol", _typeName(Any.Protocol.self))
314+
expectEqual("Any.Protocol", _typeName(Any.Protocol.self))
315315
expectEqual("Swift.AnyObject.Protocol", _typeName(AnyObject.Protocol.self))
316316
expectEqual("Swift.AnyObject.Type.Protocol", _typeName(AnyClass.Protocol.self))
317317
expectEqual("Swift.Optional<Swift.AnyObject>.Type", _typeName((AnyObject?).Type.self))
@@ -336,7 +336,7 @@ Runtime.test("typeName") {
336336
_typeName(a.dynamicType))
337337

338338
a = Any.self
339-
expectEqual("protocol<>.Protocol", _typeName(a.dynamicType))
339+
expectEqual("Any.Protocol", _typeName(a.dynamicType))
340340
}
341341

342342
class SomeSubclass : SomeClass {}
@@ -562,7 +562,7 @@ Reflection.test("Struct/Generic/DefaultMirror") {
562562
dump(value, to: &output)
563563

564564
let expected =
565-
"▿ a.GenericStructWithDefaultMirror<Swift.Int, Swift.Array<Swift.Optional<protocol<>>>>\n" +
565+
"▿ a.GenericStructWithDefaultMirror<Swift.Int, Swift.Array<Swift.Optional<Any>>>\n" +
566566
" - first: 123\n" +
567567
" ▿ second: 3 elements\n" +
568568
" ▿ Optional(\"abc\")\n" +

test/1_stdlib/RuntimeObjC.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -767,9 +767,8 @@ Reflection.test("MetatypeMirror") {
767767
dump(objcProtocolConcreteMetatype, to: &output)
768768
expectEqual(expectedObjCProtocolConcrete, output)
769769

770-
typealias Composition = SomeNativeProto & SomeObjCProto
771-
let compositionConcreteMetatype = Composition.self
772-
let expectedComposition = "- protocol<a.SomeNativeProto, a.SomeObjCProto> #0\n"
770+
let compositionConcreteMetatype = (SomeNativeProto & SomeObjCProto).self
771+
let expectedComposition = "- a.SomeNativeProto & a.SomeObjCProto> #0\n"
773772
output = ""
774773
dump(compositionConcreteMetatype, to: &output)
775774
expectEqual(expectedComposition, output)

test/1_stdlib/TypeName.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,10 @@ TypeNameTests.test("Prints") {
5050

5151
expectEqual("main.P", _typeName(P.self))
5252
typealias PP2 = P & P2
53-
expectEqual("protocol<main.P, main.P2>",
53+
expectEqual("main.P & main.P2",
5454
_typeName(PP2.self))
55-
expectEqual("protocol<>", _typeName(Any.self))
56-
expectEqual("protocol<main.P, main.P2>", _typeName((P & P2).self))
55+
expectEqual("Any", _typeName(Any.self))
56+
expectEqual("main.P & main.P2", _typeName((P & P2).self))
5757

5858
typealias F = () -> ()
5959
typealias F2 = () -> () -> ()
@@ -78,8 +78,8 @@ TypeNameTests.test("Prints") {
7878
expectEqual("((()) -> ()).Type", _typeName(F.Type.self))
7979
expectEqual("main.C.Type", _typeName(C.Type.self))
8080
expectEqual("main.C.Type.Type", _typeName(C.Type.Type.self))
81-
expectEqual("protocol<>.Type", _typeName(Any.Type.self))
82-
expectEqual("protocol<>.Protocol", _typeName(Any.Protocol.self))
81+
expectEqual("Any.Type", _typeName(Any.Type.self))
82+
expectEqual("Any.Protocol", _typeName(Any.Protocol.self))
8383
expectEqual("Swift.AnyObject", _typeName(AnyObject.self))
8484
expectEqual("Swift.AnyObject.Type", _typeName(AnyClass.self))
8585
expectEqual("Swift.Optional<Swift.AnyObject>",
@@ -88,7 +88,7 @@ TypeNameTests.test("Prints") {
8888

8989

9090
typealias Tup = (Any, F, C)
91-
expectEqual("(protocol<>, (()) -> (), main.C)",
91+
expectEqual("(Any, (()) -> (), main.C)",
9292
_typeName(Tup.self))
9393
}
9494

@@ -115,7 +115,7 @@ TypeNameTests.test("Inout") {
115115
_typeName(IF3c.self))
116116
expectEqual("(inout ((()) -> ())) -> ()",
117117
_typeName(IF4.self))
118-
expectEqual("(inout Swift.Int, protocol<>) -> ()",
118+
expectEqual("(inout Swift.Int, Any) -> ()",
119119
_typeName(IF5.self))
120120
}
121121

test/ClangModules/objc_parse.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ func testProtocols(_ b: B, bp: BProto) {
192192
var c1 : Cat1Proto = b
193193
var bcat1 = b.getAsProtoWithCat()!
194194
c1 = bcat1
195-
bcat1 = c1 // expected-error{{value of type 'Cat1Proto' does not conform to 'protocol<BProto, Cat1Proto>' in assignment}}
195+
bcat1 = c1 // expected-error{{value of type 'Cat1Proto' does not conform to 'BProto & Cat1Proto' in assignment}}
196196
}
197197

198198
// Methods only defined in a protocol
@@ -505,17 +505,17 @@ func testCStyle() {
505505

506506
func testProtocolQualified(_ obj: CopyableNSObject, cell: CopyableSomeCell,
507507
plainObj: NSObject, plainCell: SomeCell) {
508-
_ = obj as NSObject // expected-error {{'CopyableNSObject' (aka 'protocol<NSCopying, NSObjectProtocol>') is not convertible to 'NSObject'; did you mean to use 'as!' to force downcast?}} {{11-13=as!}}
508+
_ = obj as NSObject // expected-error {{'CopyableNSObject' (aka 'NSCopying & NSObjectProtocol') is not convertible to 'NSObject'; did you mean to use 'as!' to force downcast?}} {{11-13=as!}}
509509
_ = obj as NSObjectProtocol
510510
_ = obj as NSCopying
511-
_ = obj as SomeCell // expected-error {{'CopyableNSObject' (aka 'protocol<NSCopying, NSObjectProtocol>') is not convertible to 'SomeCell'; did you mean to use 'as!' to force downcast?}} {{11-13=as!}}
511+
_ = obj as SomeCell // expected-error {{'CopyableNSObject' (aka 'NSCopying & NSObjectProtocol') is not convertible to 'SomeCell'; did you mean to use 'as!' to force downcast?}} {{11-13=as!}}
512512

513513
_ = cell as NSObject
514514
_ = cell as NSObjectProtocol
515515
_ = cell as NSCopying // expected-error {{'CopyableSomeCell' (aka 'SomeCell') is not convertible to 'NSCopying'; did you mean to use 'as!' to force downcast?}} {{12-14=as!}}
516516
_ = cell as SomeCell
517517

518-
_ = plainObj as CopyableNSObject // expected-error {{'NSObject' is not convertible to 'CopyableNSObject' (aka 'protocol<NSCopying, NSObjectProtocol>'); did you mean to use 'as!' to force downcast?}} {{16-18=as!}}
518+
_ = plainObj as CopyableNSObject // expected-error {{'NSObject' is not convertible to 'CopyableNSObject' (aka 'NSCopying & NSObjectProtocol'); did you mean to use 'as!' to force downcast?}} {{16-18=as!}}
519519
_ = plainCell as CopyableSomeCell // FIXME: This is not really typesafe.
520520
}
521521

test/ClangModules/protocol_metatype_object_conversion.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ func takesProtocol(_ x: Protocol) {}
1414
takesProtocol(ObjCProto.self)
1515
takesProtocol(ObjCProto2.self)
1616
takesProtocol(NonObjCProto.self) // expected-error{{cannot convert value of type 'NonObjCProto.Protocol' to expected argument type 'Protocol'}}
17-
takesProtocol(TwoObjCProtos.self) // expected-error{{cannot convert value of type 'TwoObjCProtos.Protocol' (aka 'protocol<ObjCProto, ObjCProto2>.Protocol') to expected argument type 'Protocol'}}
17+
takesProtocol(TwoObjCProtos.self) // expected-error{{cannot convert value of type 'TwoObjCProtos.Protocol' (aka '(ObjCProto & ObjCProto2).Protocol') to expected argument type 'Protocol'}}

test/Constraints/ErrorProtocol_bridging.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ var ns4 = compo as NSError
3434

3535
// NSError conversion must be explicit.
3636
// TODO: fixit to insert 'as NSError'
37-
ns4 = compo // expected-error{{cannot assign value of type 'protocol<HairyErrorProtocol, Runcible>' to type 'NSError'}}
37+
ns4 = compo // expected-error{{cannot assign value of type 'HairyErrorProtocol & Runcible' to type 'NSError'}}
3838

3939
let e1 = ns1 as? FooError
4040
let e1fix = ns1 as FooError // expected-error{{did you mean to use 'as!'}} {{17-19=as!}}

0 commit comments

Comments
 (0)