Skip to content

Commit 9bdd139

Browse files
committed
[wip] start banning casts of move-only types unless its the identity cast
Since structs and enums only participate in subtyping via protocols, move-only types that are structs and enums effectively are only subtypes of themselves.
1 parent b2e98a7 commit 9bdd139

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1659,6 +1659,27 @@ TypeChecker::typeCheckCheckedCast(Type fromType, Type toType,
16591659
!unwrappedIUO)) {
16601660
return CheckedCastKind::Coercion;
16611661
}
1662+
1663+
// Since move-only types currently cannot conform to protocols, nor be a class
1664+
// type, the subtyping hierarchy is a bit bizarre as of now:
1665+
//
1666+
// noncopyable
1667+
// structs and enums
1668+
// |
1669+
// +--------- Any
1670+
// | |
1671+
// AnyObject protocol
1672+
// | existentials
1673+
// | | \
1674+
// +---------+ | +-- structs/enums
1675+
// | |
1676+
// classes
1677+
// (and their subtyping)
1678+
//
1679+
//
1680+
// Thus, right now, a move-only type is only a subtype of itself.
1681+
if (fromType->isPureMoveOnly())
1682+
return CheckedCastKind::Unresolved;
16621683

16631684
// Check for a bridging conversion.
16641685
// Anything bridges to AnyObject.

test/Constraints/moveonly_constraints.swift

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
struct LocalArray<Element> {}
1515

16+
protocol P {}
17+
1618
protocol Box<T> {
1719
associatedtype T
1820
func get() -> T
@@ -152,9 +154,16 @@ func checkCasting(_ b: any Box, _ mo: MO) {
152154
let _: AnyObject = MO() // expected-error {{move-only type 'MO' cannot be used with generics yet}}
153155
let _: Any = mo // expected-error {{move-only type 'MO' cannot be used with generics yet}}
154156

155-
// FIXME: this shouldn't be allowed
156-
let _: AnyHashable = MO() as! AnyHashable
157+
_ = MO() as P // expected-error {{move-only type 'MO' cannot be used with generics yet}}
158+
_ = MO() as any P // expected-error {{move-only type 'MO' cannot be used with generics yet}}
159+
_ = MO() as Any // expected-error {{move-only type 'MO' cannot be used with generics yet}}
160+
_ = MO() as MO
161+
162+
// TODO: make sure at runtime these casts actually fail, or just make them errors?
163+
let _: AnyHashable = MO() as! AnyHashable // expected-warning {{cast from 'MO' to unrelated type 'AnyHashable' always fails}}
157164

165+
// TODO: figure out how this is getting past us! Doesn't seem to hit `typeCheckCheckedCast` at all!
166+
_ = MO() as AnyObject // expected-error {{move-only type 'MO' cannot be used with generics yet}}
158167
}
159168

160169
func checkStdlibTypes(_ mo: MO) {

0 commit comments

Comments
 (0)