Skip to content
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

[SR-11565] AnyObject allows invalid as? conversion of combined protocols #53970

Open
rnapier opened this issue Oct 3, 2019 · 7 comments
Open
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself runtime The Swift Runtime

Comments

@rnapier
Copy link

rnapier commented Oct 3, 2019

Previous ID SR-11565
Radar rdar://problem/55987397
Original Reporter @rnapier
Type Bug
Environment

Xcode 11.1 GM

Additional Detail from JIRA
Votes 1
Component/s Compiler
Labels Bug, Miscompile, Runtime
Assignee None
Priority Medium

md5: 8b2c435e4403ed71b97f0b42fcc6b4d5

Issue Description:

protocol P {}


class C { let v = 1 }
class SubCP: C, P {}   // Just to show that some C's are P, but not all of them
class D: P {}


typealias AnyP = AnyObject & P  // Removing AnyObject resolves this issue
typealias CP = C & P            // Not all C are P, but CP is


let d = (D() as AnyP) as? CP    // This should fail; D is not C
d?.v    // Returns garbage value

See StackOverflow for another form of this issue.

This problem persists when P requires AnyObject directly.

protocol P: AnyObject {}


class C { let v = 1 }
class SubCP: C, P {}
class D: P {}


let d = (D() as P) as? C & P    // This should fail
d?.v    // Returns garbage value
@belkadan
Copy link
Contributor

belkadan commented Oct 3, 2019

Yikes! Haven't seen this one before. Thanks, Rob.

@swift-ci create

@swift-ci
Copy link
Collaborator

swift-ci commented Oct 6, 2019

Comment by Oleg Shanyuk (JIRA)

Hey! Just got pretty similar results using is operator:

runtime Xcode 10.3 + Playgrounds

class BasicObject {
    var a:Int = 0
}

protocol SuperNatural { }

class ChildObject0: BasicObject, SuperNatural {
    var b:Int = 0
}

class ChildObject1: BasicObject, SuperNatural {
    var c:Int = 0
}
// empty array vs non-empty array
let falselyDetectedArrayType = [ChildObject0]() // here's empty array of the required type
let correctlyDetectedArrayType = [ChildObject0()]  // pay attention → heres same type array with 1 element inside

let falselyCastArray = falselyDetectedArrayType as [SuperNatural]
let correctCastArray = correctlyDetectedArrayType as [SuperNatural]

// this line produces error
let arrayItemTypeFails = falselyCastArray is [ChildObject1] ? ChildObject1.self : ChildObject0.self
// this line works as expected
let arrayItemTypeSuccess = correctCastArray is [ChildObject1] ? ChildObject1.self : ChildObject0.self

print("type is \(arrayItemTypeFails)")
print("type is \(arrayItemTypeSuccess)")
print("type of falselyDetectedArrayType is \(type(of: falselyDetectedArrayType))")
print("type of falselyCastArray is \(type(of: falselyCastArray))")
print("type of correctCastArray is \(type(of: correctCastArray))")
print("test of direct type compare : \( [ChildObject0].self == [ChildObject1].self )")
// next line produces incorrect debugger warning also:
// WARNING text: Cast from '[ChildObject0]' to unrelated type '[ChildObject1]' always fails
print("test of type validation using <is> : \( [ChildObject0]() is [ChildObject1] )")

OUTPUT:

type is ChildObject1
type is ChildObject0
type of falselyDetectedArrayType is Array<ChildObject0>
type of falselyCastArray is Array<SuperNatural>
type of correctCastArray is Array<SuperNatural>
test of direct type compare : false
test of type validation using <is> : true

@belkadan
Copy link
Contributor

belkadan commented Oct 7, 2019

Yep, is and as? are implemented the same way, so it's probably the same bug.

@swift-ci
Copy link
Collaborator

swift-ci commented Oct 7, 2019

Comment by Oleg Shanyuk (JIRA)

@belkadan Thanks. Shall I create a new ticket, or this will go now in single train?

@belkadan
Copy link
Contributor

belkadan commented Oct 7, 2019

I think it's fine to leave here. You've found another test case for the same issue.

@mikeash
Copy link
Contributor

mikeash commented Oct 9, 2019

I see the bug using this test case with optimizations off, but it goes away when optimizations are on. Presumably that means the optimizer has the correct notion of subtyping here (yay!) but the runtime doesn't.

@mikeash
Copy link
Contributor

mikeash commented Oct 9, 2019

Changed my mind: it looks like the compiler is only emitting code to check for `P`, not `C`. I've forwarded this along to the appropriate folks.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself runtime The Swift Runtime
Projects
None yet
Development

No branches or pull requests

4 participants