mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
AST: Fix TypeBase::hasSimpleTypeRepr() for ProtocolCompositionType
Prior to the introduction of noncopyable generics, a ProtocolCompositionType was 'simple' if it was exactly 'Any' or 'AnyObject'. Now, there is a new simple case, where we have a single inverse requirement '~Copyable' or '~Escapable', and the old logic was never updated to account for this possibility. Instead, it would ignore inverses, so it would claim that a composition like `P & ~Copyable` was simple when it shouldn't be. Fixes rdar://139465298.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
Reference in New Issue
Block a user