I installed Xcode 12 beta 5 and 6 and tried to build our existing (test) code:
it("should throw an error") {
expect {
try JSONDecoder().decode(SomeModel.self, from: data)
}.to(throwError())
}
I expected the code to compile.
The code failed to compile with a ambiguous use of 'expect' error. With these two candidates:
public func expect<T>(_ expression: @autoclosure @escaping () throws -> T?, file: FileString = #file, line: UInt = #line) -> Expectation<T>public func expect<T>(_ file: FileString = #file, line: UInt = #line, expression: @escaping () throws -> T?) -> Expectation<T>List the software versions you're using:
Please also mention which package manager you used and its version. Delete the
other package managers in this list:
https://github.com/rastersize/Xcode12Beta5Nimble
After cloning do the following:
carthage.sh bootstraparm64 slice for both the simulator and device, and a universal binary can’t contain two slices for the same architecture.Change the call-site of expect to specify using the non-autoclosure function. That is:
it("should throw an error") {
expect(expression: {
try JSONDecoder().decode(SomeModel.self, from: data)
}).to(throwError())
}
Not as pretty but it works for now.
This is probably a regression in the Swift compiler to be honest, and should be resolved there I guess. Especially as it just crashed Swiftc while compiling some more code. Filed with Apple as FB8464226 and in the Swift Bug tracker as SR-13421.
Added a sample project that demonstrates the issue with Nimble 9.0.0-rc.1.
I'm on the same configuration and I'm getting a similar error, Illegal instruction: 4, but always when evaluating expect{}.toEventually()
CompileSwift normal x86_64 (in target 'LoungeFoundationTests' from project 'LoungeFoundation')
[...]
fromType->getCanonicalType() = (bound_generic_struct_type decl=Nimble.(file).Predicate@/Users/ngiancecchi/Projects/ios-app/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Predicate.swift:20:15
(protocol_composition_type))
toType->getCanonicalType() = (bound_generic_struct_type decl=Nimble.(file).Predicate@/Users/ngiancecchi/Projects/ios-app/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Predicate.swift:20:15
(function_type escaping
(input=function_params num_params=0)
(output=tuple_type num_elements=0)))
Stack dump:
0. Program arguments: [...]
1. Apple Swift version 5.3 (swiftlang-1200.0.28.1 clang-1200.0.30.1)
2. While evaluating request TypeCheckSourceFileRequest(source_file "/Users/ngiancecchi/Projects/ios-app/Subprojects/LoungeFoundation/LoungeFoundationTests/ConfigTests.swift")
3. While evaluating request TypeCheckFunctionBodyUntilRequest(LoungeFoundationTests.(file).ConfigTests.testPostsNotification()@/Users/ngiancecchi/Projects/ios-app/Subprojects/LoungeFoundation/LoungeFoundationTests/ConfigTests.swift:46:10, )
4. While type-checking statement at [/Users/ngiancecchi/Projects/ios-app/Subprojects/LoungeFoundation/LoungeFoundationTests/ConfigTests.swift:46:34 - line:53:5] RangeText="{
let newConfig: Config = .mockedWith(appDomainID: 5555)
let expectedNotification = Notification(name: .newConfigAvailable, object: newConfig)
expect {
Config.current = newConfig
}.toEventually(postNotifications(contain(expectedNotification, from: newConfig)))
"
5. While type-checking expression at [/Users/ngiancecchi/Projects/ios-app/Subprojects/LoungeFoundation/LoungeFoundationTests/ConfigTests.swift:50:9 - line:52:89] RangeText="expect {
Config.current = newConfig
}.toEventually(postNotifications(contain(expectedNotification, from: newConfig))"
0 swift 0x00000001087a5a85 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 37
1 swift 0x00000001087a4a85 llvm::sys::RunSignalHandlers() + 85
2 swift 0x00000001087a603f SignalHandler(int) + 111
3 libsystem_platform.dylib 0x00007fff6ed735fd _sigtramp + 29
4 libsystem_kernel.dylib 0x00007fff6ecbf35e __ioctl + 10
5 swift 0x0000000104ff1413 (anonymous namespace)::ExprRewriter::coerceCallArguments(swift::Expr*, swift::AnyFunctionType*, swift::ConcreteDeclRef, swift::ApplyExpr*, llvm::ArrayRef<swift::Identifier>, swift::constraints::ConstraintLocatorBuilder) + 8899
6 swift 0x0000000104fee352 (anonymous namespace)::ExprRewriter::finishApply(swift::ApplyExpr*, swift::Type, swift::constraints::ConstraintLocatorBuilder, swift::constraints::ConstraintLocatorBuilder) + 11970
7 swift 0x0000000104ff9b5d (anonymous namespace)::ExprRewriter::visitApplyExpr(swift::ApplyExpr*) + 477
8 swift 0x0000000104fd0b02 (anonymous namespace)::ExprWalker::walkToExprPost(swift::Expr*) + 18
9 swift 0x0000000104fc71e3 (anonymous namespace)::ExprWalker::rewriteTarget(swift::constraints::SolutionApplicationTarget) + 371
10 swift 0x0000000104fc6ed0 swift::constraints::ConstraintSystem::applySolution(swift::constraints::Solution&, swift::constraints::SolutionApplicationTarget) + 6400
11 swift 0x00000001051aff1a swift::TypeChecker::typeCheckExpression(swift::constraints::SolutionApplicationTarget&, bool&, swift::OptionSet<swift::TypeCheckExprFlags, unsigned int>) + 1242
12 swift 0x00000001051af988 swift::TypeChecker::typeCheckExpression(swift::Expr*&, swift::DeclContext*, swift::TypeLoc, swift::ContextualTypePurpose, swift::OptionSet<swift::TypeCheckExprFlags, unsigned int>) + 360
13 swift 0x0000000105294e4b swift::ASTVisitor<(anonymous namespace)::StmtChecker, void, swift::Stmt*, void, void, void, void>::visit(swift::Stmt*) + 9115
14 swift 0x000000010529069a bool (anonymous namespace)::StmtChecker::typeCheckStmt<swift::BraceStmt>(swift::BraceStmt*&) + 314
15 swift 0x000000010528f0a7 swift::TypeCheckFunctionBodyUntilRequest::evaluate(swift::Evaluator&, swift::AbstractFunctionDecl*, swift::SourceLoc) const + 2231
16 swift 0x0000000105297e7d llvm::Expected<swift::TypeCheckFunctionBodyUntilRequest::OutputType> swift::Evaluator::getResultCached<swift::TypeCheckFunctionBodyUntilRequest, (void*)0>(swift::TypeCheckFunctionBodyUntilRequest const&) + 925
17 swift 0x0000000105290148 swift::TypeCheckFunctionBodyUntilRequest::OutputType swift::evaluateOrDefault<swift::TypeCheckFunctionBodyUntilRequest>(swift::Evaluator&, swift::TypeCheckFunctionBodyUntilRequest, swift::TypeCheckFunctionBodyUntilRequest::OutputType) + 440
18 swift 0x00000001052cda84 swift::TypeCheckSourceFileRequest::evaluate(swift::Evaluator&, swift::SourceFile*) const + 1380
19 swift 0x00000001052d0699 llvm::Expected<swift::TypeCheckSourceFileRequest::OutputType> swift::Evaluator::getResultUncached<swift::TypeCheckSourceFileRequest>(swift::TypeCheckSourceFileRequest const&) + 953
20 swift 0x00000001052cd394 swift::TypeCheckSourceFileRequest::OutputType swift::evaluateOrDefault<swift::TypeCheckSourceFileRequest>(swift::Evaluator&, swift::TypeCheckSourceFileRequest, swift::TypeCheckSourceFileRequest::OutputType) + 164
21 swift 0x0000000104448e78 swift::CompilerInstance::performSemaUpTo(swift::SourceFile::ASTStage_t) + 7576
22 swift 0x000000010430996d swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 6845
23 swift 0x000000010428e277 main + 1255
24 libdyld.dylib 0x00007fff6eb7acc9 start + 1
25 libdyld.dylib 0x00000000000000d4 start + 18446603338658632716
error: Illegal instruction: 4 (in target 'LoungeFoundationTests' from project 'LoungeFoundation')
I talked to a colleague about this and they suggested that it could be due to the new “forward scan” behavior for trailing closures. Noting that Nimble was apparently called out as one of the libraries that would break.
It appears this is still an issue with Xcode 12 Beta 6 and the version of Swift it bundles with.
It seems like Xcode Beta 6 is near identical to Beta 5. Same version of swiftc and almost no difference in build version for Xcode itself. Hopefully coming version will fix it 🤞
Here's to hoping for a fix whilst Xcode 12 remains in Beta.
@rastersize - is it worthwhile tagging each beta individually or updating the defect title with the lastest beta version as they progress without a fix? I'm sure there are many others who'll be searching for a very similar thing 😃
@sraiteri Good suggestion, I've updated the title and issue description. As well as the SR.
Hey folks, could you try my possible fix of #820?
@ikesyo I tried out your possible fix branch with the codebase I work on that had ~185 errors before. With the branch/PR I no longer get these errors, or at least the compiler didn’t get to it. Instead I got two different errors:
to(_:description:)' is deprecated: Use Predicate insteadexpect(status).to(equal(.pending(inviteId: "foo"))) where status is an enum that conforms to Equatable and pending is a case of that enum.Cannot convert value of type 'Double' to expected argument type 'DispatchTimeInterval'toEventually(..., timeout: 3.0).Note that I was using Nimble 8.1.2 before using the branch, so maybe it’s related to the 8->9 version change?
so maybe it’s related to the 8->9 version change?
@rastersize Exactly, those are not related to #820.
@ikesyo I also tried out your branch, and I also am unsure of what is expected behavior in 9.0 (I'm coming from 8.0.7). But I've observed these breakages:
expect no longer works: expect(try Blah.throwBlah()).to(equal("")) // Call can throw, but it is executed in a non-throwing autoclosure
expect(something.that.returns.a.bool(), file: file, line: line).toEventually(beTrue()) fail because the expression is now expected after file and line params, not before.extra trailing closure passed in call:expect(file, line: line) { () -> T in
return try something()
}.toNot(throwError())
I understand the iOS 14 release was announced just today, and am of course not expecting miracles! But are you able to provide any guidance on when we should expect to see a compatible Nimble release? That would greatly help me, and hopefully others, plan their iOS 14 updates. Thank you!
As a workaround, adding this function got my tests to run on Nimble 8.x using Xcode 12 GM.
public func expect<T>(_ expression: @escaping () throws -> T?) -> Expectation<T> {
Nimble.expect(expression: expression)
}
calling a throwing function inside expect no longer works:
That is due to #821 and I now understand that the change was not correct. I'll revert it.
calls like: expect(something.that.returns.a.bool(), file: file, line: line).toEventually(beTrue()) fail because the expression is now expected after file and line params, not before.
Could you please reorder arguments.
calls like this result in compilation error: extra trailing closure passed in call:
Adding file argument label should fix that: expect(file: file, ...).
Just wanted to note that we seem to be running into the same issue (both the "expect" ambiguity and the Illegal Instruction crash). Happy to help test this, thanks @ikesyo for your quick work here!
Thanks for your work @ikesyo !
I tested out https://github.com/Quick/Nimble/pull/821 and it resolved a lot of the issues I was facing. On a minor note I noticed that this no longer works
expect({
if 1 == 1 {
return .failed(reason: "this failed")
}
return .succeeded
}).to(succeed())
This can be fixed by returning a closure instead i.e. return { .succeeded } but I am curious if this regression can be reverted?
Thanks for your work @ikesyo !
I tested out #821 and it resolved a lot of the issues I was facing. On a minor note I noticed that this no longer works
expect({ if 1 == 1 { return .failed(reason: "this failed") } return .succeeded }).to(succeed())This can be fixed by returning a closure instead i.e.
return { .succeeded }but I am curious if this regression can be reverted?
@ketenshi Another workaround I found is by adding () -> ToSucceedResult in like so:
expect({ () -> ToSucceedResult in
if 1 == 1 {
return .failed(reason: "this failed")
}
return .succeeded
}).to(succeed())
Not sure if this behaviour is expected in Nimble 9.
Confirming the issue is still present on GM, so a high chance it will be still in the final release, and the changes in #820 still fix it.
Just released v9.0.0-rc.3 including the fix for this. Please try it!
@ikesyo - I tried the fix and it's working for me! Thanks a bunch
We tried the rc.3 build and we were able to resolve our issues as well. This is awesome, thanks for your work @ikesyo!
Most helpful comment
@ketenshi Another workaround I found is by adding
() -> ToSucceedResult inlike so:Not sure if this behaviour is expected in Nimble 9.