Skip to content

AST: Fix TypeBase::hasSimpleTypeRepr() for ProtocolCompositionType #79647

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
Feb 27, 2025
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
21 changes: 19 additions & 2 deletions lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4561,11 +4561,28 @@ bool TypeBase::hasSimpleTypeRepr() const {
}

case TypeKind::ProtocolComposition: {
// 'Any', 'AnyObject' and single protocol compositions are simple
auto composition = cast<const ProtocolCompositionType>(this);

// A protocol composition is simple if its syntactic representation does not
// involve `&`. This is true if we have 'Any', 'AnyObject', or a single
// inverse requirement like `~Copyable`.

// All other protocol compositions contain at least two `&`-separated terms.

// Add each logical member Foo.
auto memberCount = composition->getMembers().size();

// And each inverse requirement ~Foo.
for (auto ip : composition->getInverses()) {
(void) ip;
++memberCount;
}

// And finally, AnyObject.
if (composition->hasExplicitAnyObject())
return memberCount == 0;
++memberCount;

// Almost always, this will be > 1.
return memberCount <= 1;
}

Expand Down
19 changes: 19 additions & 0 deletions test/ModuleInterface/existential-any.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,22 @@ public protocol ProtocolTypealias {

// CHECK: public func dependentExistential<T>(value: (T) -> any main.P) where T : main.ProtocolTypealias
public func dependentExistential<T: ProtocolTypealias>(value: (T) -> T.A) {}

public protocol Yescopyable {}
public protocol Noncopyable: ~Copyable {}

// CHECK: public func existentialMetatype1(_: any (main.Noncopyable & ~Copyable).Type)
// CHECK: public func existentialMetatype2(_: any (main.Noncopyable & main.Yescopyable).Type)
// CHECK: public func existentialMetatype3(_: any ~Copyable.Type)

public func existentialMetatype1(_: any (Noncopyable & ~Copyable).Type) {}
public func existentialMetatype2(_: any (Yescopyable & Noncopyable).Type) {}
public func existentialMetatype3(_: any ~Copyable.Type) {}

// CHECK: public func metatypeExistential1(_: (any main.Noncopyable & ~Copyable).Type)
// CHECK: public func metatypeExistential2(_: (any main.Noncopyable & main.Yescopyable).Type)
// CHECK: public func metatypeExistential3(_: (any ~Copyable).Type)

public func metatypeExistential1(_: (any Noncopyable & ~Copyable).Type) {}
public func metatypeExistential2(_: (any Yescopyable & Noncopyable).Type) {}
public func metatypeExistential3(_: (any ~Copyable).Type) {}