8000 Fix SPM integration. by sunshinejr · Pull Request #746 · Quick/Quick · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Fix SPM integration. #746

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 3 commits into from
Sep 27, 2017
Merged

Fix SPM integration. #746

merged 3 commits into from
Sep 27, 2017

Conversation

sunshinejr
Copy link
Contributor
@sunshinejr sunshinejr commented Sep 26, 2017

Hey guys! First of all thank you so much for your constant work on Quick/Nimble, really appreciate that. Recently I was working extensively with SPM and wanted to try both Quick/Nimble with SPM. I encountered a runtime crash (bad access) on this line.

My environment:

  • SPM/Swift 4.0
  • PackageDescriptionV4
  • Quick version 1.1.0

Seems like the forcecast on the superclass type was creating a crash whenever there was no superclass. I've changed it to be safer so whenever there is no superclass, it will just skip it. If the code style is different from what you have right now, feel free to correct me/change it.

Cheers!

block(subclass as! T.Type) // swiftlint:disable:this force_cast
}

guard let superclass = class_getSuperclass(subclass),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trailing Whitespace Violation: Lines should not have trailing whitespace. (trailing_whitespace)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Damn it :D

@QuickBot
Copy link
QuickBot commented Sep 26, 2017
1 Warning
⚠️ Need to add an unit test if you’re modifying swift source

Generated by 🚫 danger

Copy link
Member
@modocache modocache left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks so much, @sunshinejr! I think I'm not following some of your changes, though. Are you sure this is fixing the cause of the error? Or is it preventing the error case from being reached? See my questions below for details, and apologies in advance if I'm misunderstanding.

}

guard let superclass = class_getSuperclass(subclass),
superclass === klass else { return }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return here would halt enumeration of the classes defined in this bundle, no? Should this be a continue instead? Let me know if I'm misreading this 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, you are right, sorry about that. I've just made it a simple if like it was before.

guard let superclass = class_getSuperclass(subclass),
superclass === klass else { return }

block(subclass as! T.Type) // swiftlint:disable:this force_cast
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand how this fixes the problem.

So, here's the code before:

// 1. Get the superclass.
superclass = class_getSuperclass(subclass)
// 2. If the superclass is the same as the class passed into this function...
if superclass === klass {
    // 3. ...then force-cast the subclass.
    block(subclass as! T.Type)
}

And here's the new version:

// 1. Get the superclass and check if it's the same as the class passed into
//    this function. If it isn't, exit early.
guard let superclass = class_getSuperclass(subclass),
    superclass === klass else { return }
// 2. Otherwise, the superclass is the same as the class passed into this function...
// 3. ...then force-cast the subclass.
block(subclass as! T.Type)

Reading the two, it seems like they basically do the same thing...?

However, I think maybe the difference is that you return instead of continue. So I think the actual assertion failure happens later in the iteration. In other words, maybe your change prevents the error because it prevents this loop from going through all of the classes, and therefore it never reaches the class that causes the error.

Or am I misreading this? Let me know, thanks!

@sunshinejr
Copy link
Contributor Author

@modocache the most important line didn't get the commit it seems, not sure why SourceTree didn't catch it, but yeah, now it is up. Sorry about that!

So the line:

var subclass, superclass: AnyClass!

was the issue as it force-casted the superclass, even though it could be nil in some cases. I created a local check which in case of a nil will just skip it, instead of assigning to force-casted type and then crashing. So basically:

var superclass: AnyClass!
superclass = class_getSuperclass(subclass) // which causes assigning nil to force-casted type when there is no superclass 
if superclass === klass { // now we are accessing nil object in AnyClass! which results in bad access
    block(subclass as! T.Type) // swiftlint:disable:this force_cast
}

vs

// in case of a nil, we just skip it
if let superclass = class_getSuperclass(subclass), superclass === klass {
    block(subclass as! T.Type) // swiftlint:disable:this force_cast
}

Let me know if it's clear now 😅

@modocache modocache merged commit c498edf into Quick:master Sep 27, 2017
@modocache
Copy link
Member

Excellent, thank you @sunshinejr! ❤️

@sunshinejr sunshinejr deleted the fix/spm_integration branch September 27, 2017 06:31
@sunshinejr sunshinejr mentioned this pull request Sep 27, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants
0