Skip to content
This repository has been archived by the owner on Mar 30, 2022. It is now read-only.

Order of Code Input/Execution: ProtocolConformance & TFDifferentiation #88

Closed
bartchr808 opened this issue Nov 29, 2018 · 5 comments
Closed

Comments

@bartchr808
Copy link
Contributor

bartchr808 commented Nov 29, 2018

There are two separate but sorted related issues I'm experiencing in both Swift REPL and swift-jupyter and I'll describe both issues here.

System info:

  • OS X 10.14 (18A391)
  • Xcode Version 10.1 (10B61)
  • November 21, 2018 Swift version 4.2-dev (LLVM c4a0883115, Clang 0a99881462, Swift 2538fca)
  • Target: x86_64-apple-darwin18.0.0

Error 1: ProtocolConformance.cpp Tensor Protocol Assertion Failed.

How to Reproduce

  1. Start up a fresh Swift REPL session in the console.
  2. Paste the following code into the console:
import TensorFlow
func quadratic(_ x: Float) -> Float {
    return x * x
}
let dq = #gradient(quadratic)
  1. Hit Enter/Return to execute the code. You should see something that looks like the following in blue in the console:
dq: (Float) -> Float = 0x0000000109e8a2a0 $__lldb_expr2`AD__$s13__lldb_expr_19quadraticyS2fF__grad_src_0_wrt_0 at repl.swift:2
  1. Past the following code into the console:
var x = Tensor<Float>([[1, 2], [3, 4]])
  1. When you hit Enter/Return, it should Error with the following stack trace:
Assertion failed: ((!isComplete() || isInvalid() || requirement->getAttrs().hasAttribute<OptionalAttr>() || requirement->getAttrs().isUnavailable( requirement->getASTContext())) && "Conformance already complete?"), function setWitness, file /usr/local/src/swift-build/swift/lib/AST/ProtocolConformance.cpp, line 886.
0  lldb                     0x000000010f2afa18 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 40
1  lldb                     0x000000010f2aec67 llvm::sys::RunSignalHandlers() + 39
2  lldb                     0x000000010f2b0092 SignalHandler(int) + 258
3  libsystem_platform.dylib 0x00007fff61a7eb3d _sigtramp + 29
4  libsystem_platform.dylib 0x00007feb6b900000 _sigtramp + 166204640
5  libsystem_c.dylib        0x00007fff6193d1c9 abort + 127
6  libsystem_c.dylib        0x00007fff61905868 basename_r + 0
7  LLDB                     0x000000011e6e3951 swift::NormalProtocolConformance::setWitness(swift::ValueDecl*, swift::Witness) const + 817
8  LLDB                     0x000000011e3d2ed5 swift::ConformanceChecker::recordWitness(swift::ValueDecl*, swift::RequirementMatch const&) + 293
9  LLDB                     0x000000011e3d6185 swift::ConformanceChecker::resolveWitnessViaLookup(swift::ValueDecl*) + 2549
10 LLDB                     0x000000011e3f5cd8 swift::ConformanceChecker::resolveSingleWitness(swift::ValueDecl*) + 472
11 LLDB                     0x000000011e3dce4b swift::TypeChecker::resolveWitness(swift::NormalProtocolConformance const*, swift::ValueDecl*) + 443
12 LLDB                     0x000000011e6e11fa swift::NormalProtocolConformance::getWitness(swift::ValueDecl*, swift::LazyResolver*) const + 330
13 LLDB                     0x000000011e6e0f78 swift::ProtocolConformance::getWitnessDeclRef(swift::ValueDecl*, swift::LazyResolver*) const + 40
14 LLDB                     0x000000011e24d0ab findNamedWitnessImpl(swift::TypeChecker&, swift::DeclContext*, swift::Type, swift::ProtocolDecl*, swift::DeclName, swift::Diag<>, llvm::Optional<swift::ProtocolConformanceRef>) + 475
15 LLDB                     0x000000011e251a1b swift::TypeChecker::callWitness(swift::Expr*, swift::DeclContext*, swift::ProtocolDecl*, swift::ProtocolConformanceRef, swift::DeclName, llvm::MutableArrayRef<swift::Expr*>, swift::Diag<>) + 315
16 LLDB                     0x000000011e26622d (anonymous namespace)::ExprRewriter::convertLiteral(swift::Expr*, swift::Type, swift::Type, swift::ProtocolDecl*, llvm::PointerUnion<swift::Identifier, swift::Type>, swift::DeclName, swift::ProtocolDecl*, llvm::PointerUnion<swift::Identifier, swift::Type>, swift::DeclName, bool (*)(swift::Type), swift::Diag<>, swift::Diag<>) + 845
17 LLDB                     0x000000011e2663da (anonymous namespace)::ExprRewriter::convertLiteral(swift::Expr*, swift::Type, swift::Type, swift::ProtocolDecl*, llvm::PointerUnion<swift::Identifier, swift::Type>, swift::DeclName, swift::ProtocolDecl*, llvm::PointerUnion<swift::Identifier, swift::Type>, swift::DeclName, bool (*)(swift::Type), swift::Diag<>, swift::Diag<>) + 1274
18 LLDB                     0x000000011e2668eb (anonymous namespace)::ExprRewriter::handleIntegerLiteralExpr(swift::LiteralExpr*) + 555
19 LLDB                     0x000000011e251406 (anonymous namespace)::ExprRewriter::walkToExprPost(swift::Expr*) + 22
20 LLDB                     0x000000011e2574e6 (anonymous namespace)::ExprWalker::walkToExprPost(swift::Expr*) + 22
21 LLDB                     0x000000011e61899f (anonymous namespace)::Traversal::visitCollectionExpr(swift::CollectionExpr*) + 287
22 LLDB                     0x000000011e61897e (anonymous namespace)::Traversal::visitCollectionExpr(swift::CollectionExpr*) + 254
23 LLDB                     0x000000011e6163e0 swift::ASTVisitor<(anonymous namespace)::Traversal, swift::Expr*, swift::Stmt*, bool, swift::Pattern*, bool, void>::visit(swift::Expr*) + 256
24 LLDB                     0x000000011e618c6f (anonymous namespace)::Traversal::visitApplyExpr(swift::ApplyExpr*) + 207
25 LLDB                     0x000000011e615cb4 swift::Expr::walk(swift::ASTWalker&) + 84
26 LLDB                     0x000000011e24e4ed swift::constraints::ConstraintSystem::applySolution(swift::constraints::Solution&, swift::Expr*, swift::Type, bool, bool) + 573
27 LLDB                     0x000000011e37a71c swift::TypeChecker::typeCheckExpression(swift::Expr*&, swift::DeclContext*, swift::TypeLoc, swift::ContextualTypePurpose, swift::OptionSet<swift::TypeCheckExprFlags, unsigned int>, swift::ExprTypeCheckListener*, swift::constraints::ConstraintSystem*) + 1132
28 LLDB                     0x000000011e37f515 swift::TypeChecker::typeCheckBinding(swift::Pattern*&, swift::Expr*&, swift::DeclContext*, bool) + 357
29 LLDB                     0x000000011e37f81b swift::TypeChecker::typeCheckPatternBinding(swift::PatternBindingDecl*, unsigned int, bool) + 315
30 LLDB                     0x000000011e394d2e validatePatternBindingEntries(swift::TypeChecker&, swift::PatternBindingDecl*) + 814
31 LLDB                     0x000000011e38d1a4 (anonymous namespace)::DeclChecker::visit(swift::Decl*) + 884
32 LLDB                     0x000000011e38ce26 swift::TypeChecker::typeCheckDecl(swift::Decl*) + 38
33 LLDB                     0x000000011e406b73 swift::ASTVisitor<(anonymous namespace)::StmtChecker, void, swift::Stmt*, void, void, void, void>::visit(swift::Stmt*) + 451
34 LLDB                     0x000000011e405ea8 bool (anonymous namespace)::StmtChecker::typeCheckStmt<swift::BraceStmt>(swift::BraceStmt*&) + 136
35 LLDB                     0x000000011e405dde swift::TypeChecker::typeCheckTopLevelCodeDecl(swift::TopLevelCodeDecl*) + 174
36 LLDB                     0x000000011e426945 swift::performTypeChecking(swift::SourceFile&, swift::TopLevelContext&, swift::OptionSet<swift::TypeCheckingFlags, unsigned int>, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int) + 853
37 LLDB                     0x000000011f0ab988 lldb_private::SwiftExpressionParser::Parse(lldb_private::DiagnosticManager&, unsigned int, unsigned int, unsigned int) + 442
38 LLDB                     0x000000011f0fce76 lldb_private::SwiftUserExpression::Parse(lldb_private::DiagnosticManager&, lldb_private::ExecutionContext&, lldb_private::ExecutionPolicy, bool, bool, unsigned int) + 904
39 LLDB                     0x000000011ee86dc2 lldb_private::UserExpression::Evaluate(lldb_private::ExecutionContext&, lldb_private::EvaluateExpressionOptions const&, llvm::StringRef, llvm::StringRef, lldb_private::SharingPtr<lldb_private::ValueObject>&, lldb_private::Status&, unsigned int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*, std::__1::shared_ptr<lldb_private::Module>*) + 1294
40 LLDB                     0x000000011ed2d155 lldb_private::REPL::IOHandlerInputComplete(lldb_private::IOHandler&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) + 1881
41 LLDB                     0x000000011edce147 lldb_private::IOHandlerEditline::Run() + 319
42 LLDB                     0x000000011ec7839a lldb_private::Debugger::ExecuteIOHandlers() + 68
43 LLDB                     0x000000011ec7b124 lldb_private::Debugger::IOHandlerThread(void*) + 14
44 LLDB                     0x000000011eee5012 lldb_private::HostNativeThreadBase::ThreadCreateTrampoline(void*) + 110
45 libsystem_pthread.dylib  0x00007fff61a8733d _pthread_body + 126
46 libsystem_pthread.dylib  0x00007fff61a8a2a7 _pthread_start + 70
47 libsystem_pthread.dylib  0x00007fff61a86425 thread_start + 13
[1]    6104 abort      swift

This should also happen if you were to type this manually and not copy and paste the code into the console. The should comes with a caveat:

  • NOTE: Actually, it's expected to error the same way, but the second error described below prevents you from typing the above code out manually. Funnily enough, I only discovered the error below when I was verifying that the code also errors if you type the code out manually.

Expected Behavior

What should occur is the code should not error out and get the following in blue in the console:

x: TensorFlow.Tensor<Float> = [[1.0, 2.0], [3.0, 4.0]]

Interestingly, this is possible! However, this is only possible if you paste in all of the code above as one chunk:

import TensorFlow
func quadratic(_ x: Float) -> Float {
    return x * x
}
let dq = #gradient(quadratic)
var x = Tensor<Float>([[1, 2], [3, 4]])

And in the console you get the following as expected:

dq: (Float) -> Float = 0x0000000109e8a360 $__lldb_expr2`AD__$s13__lldb_expr_19quadraticyS2fF__grad_src_0_wrt_0 at repl.swift:2
x: TensorFlow.Tensor<Float> = [[1.0, 2.0], [3.0, 4.0]]

Also, note that you can reproduce the same error in swift-jupyter but you need to treat each code block as separate code cells. If you stick all the code into one code cell, it will work as expected. The only different with swift-jupyter is that you get a generic error in the web-view and only the first/top line of the stack trace in the console where Jupyter is running.

Error 2: TFDifferentiation.cpp Function Body Assertion Failed.

How to Reproduce

  1. Start up a fresh Swift REPL session in the console.
  2. Paste the following code into the console:
import TensorFlow
func quadratic(_ x: Float) -> Float {
    return x * x
}
  1. Hit Enter/Return to execute the code.
  2. Past the following code into the console:
let dq = #gradient(quadratic) // NOTE: if you type `var x = Tensor<Float>([[1, 2], [3, 4]])` here instead, it works!
  1. When you hit Enter/Return, it should Error with the following stack trace:
Assertion failed: (original->isSerialized() && "Differentiation task cannot be on a function without a body"), function registerDifferentiationTask, file /usr/local/src/swift-build/swift/lib/SILOptimizer/Mandatory/TFDifferentiation.cpp, line 1056.
0  lldb                     0x0000000100c29a18 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 40
1  lldb                     0x0000000100c28c67 llvm::sys::RunSignalHandlers() + 39
2  lldb                     0x0000000100c2a092 SignalHandler(int) + 258
3  libsystem_platform.dylib 0x00007fff61a7eb3d _sigtramp + 29
4  libsystem_platform.dylib 0x00007fb682d4f200 _sigtramp + 556599008
5  libsystem_c.dylib        0x00007fff6193d1c9 abort + 127
6  libsystem_c.dylib        0x00007fff61905868 basename_r + 0
7  LLDB                     0x0000000114151aeb (anonymous namespace)::ADContext::registerDifferentiationTask(swift::SILFunction*, swift::SILAutoDiffIndices const&, (anonymous namespace)::DifferentiationInvoker) + 1899
8  LLDB                     0x000000011414e024 (anonymous namespace)::Differentiation::run() + 4148
9  LLDB                     0x000000011423652b swift::SILPassManager::runModulePass(unsigned int) + 1083
10 LLDB                     0x0000000114236ff4 swift::SILPassManager::execute() + 692
11 LLDB                     0x000000011371981b swift::SILPassManager::executePassPipelinePlan(swift::SILPassPipelinePlan const&) + 187
12 LLDB                     0x000000011423c1c4 swift::runSILDiagnosticPasses(swift::SILModule&) + 132
13 LLDB                     0x0000000114904428 lldb_private::SwiftExpressionParser::Parse(lldb_private::DiagnosticManager&, unsigned int, unsigned int, unsigned int) + 7258
14 LLDB                     0x0000000114953e76 lldb_private::SwiftUserExpression::Parse(lldb_private::DiagnosticManager&, lldb_private::ExecutionContext&, lldb_private::ExecutionPolicy, bool, bool, unsigned int) + 904
15 LLDB                     0x00000001146dddc2 lldb_private::UserExpression::Evaluate(lldb_private::ExecutionContext&, lldb_private::EvaluateExpressionOptions const&, llvm::StringRef, llvm::StringRef, lldb_private::SharingPtr<lldb_private::ValueObject>&, lldb_private::Status&, unsigned int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*, std::__1::shared_ptr<lldb_private::Module>*) + 1294
16 LLDB                     0x0000000114584155 lldb_private::REPL::IOHandlerInputComplete(lldb_private::IOHandler&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) + 1881
17 LLDB                     0x0000000114625147 lldb_private::IOHandlerEditline::Run() + 319
18 LLDB                     0x00000001144cf39a lldb_private::Debugger::ExecuteIOHandlers() + 68
19 LLDB                     0x00000001144d2124 lldb_private::Debugger::IOHandlerThread(void*) + 14
20 LLDB                     0x000000011473c012 lldb_private::HostNativeThreadBase::ThreadCreateTrampoline(void*) + 110
21 libsystem_pthread.dylib  0x00007fff61a8733d _pthread_body + 126
22 libsystem_pthread.dylib  0x00007fff61a8a2a7 _pthread_start + 70
23 libsystem_pthread.dylib  0x00007fff61a86425 thread_start + 13
[1]    11700 abort      swift

This happens also if you were to type this manually and not copy and paste the code into the console.

Expected Behavior

What should occur is the code should not error out and you should see something that looks like the following in blue in the console:

dq: (Float) -> Float = 0x0000000109e8a2a0 $__lldb_expr2`AD__$s13__lldb_expr_19quadraticyS2fF__grad_src_0_wrt_0 at repl.swift:2

Just like the first error, this won't error if you past the code into the console as one chunk like this:

import TensorFlow
func quadratic(_ x: Float) -> Float {
    return x * x
}
let dq = #gradient(quadratic)

And in the console you get the following as expected:

dq: (Float) -> Float = 0x0000000109e8a2a0 $__lldb_expr2`AD__$s13__lldb_expr_19quadraticyS2fF__grad_src_0_wrt_0 at repl.swift:2

Also, same thing regarding swift-jupyter experiencing a crash just like in the first error above applies here too.

Summary

Both errors seem related in that the error occurs due to the order of execution (maybe not order, but what Swift REPL sees in a specific instance when it reads and evaluates). However, as seen in the stack trace, they have to do with two different parts of Swift: already existing file ProtocolConformance.cpp and the new file TFDifferentiation.cpp that's a part of the Swift for TensorFlow project.

@rxwei
Copy link
Contributor

rxwei commented Dec 1, 2018

Thanks a lot for the detailed report!
Error 1 is likely an LLDB bug.
Error 2 is a known issue: This is because each Jupyter cell or REPL cell gets lowered to LLVM without having the SIL function serialized. When AD can't find the function body, it cannot differentiate the function. To work around this bug, you can force quadratic(_:) to be differentiated in the first place by adding a @differentiable attribute. Currently the attribute is @differentiable(reverse), but it'll be simplified to @differentiable.

import TensorFlow
@differentiable(reverse)
func quadratic(_ x: Float) -> Float {
    return x * x
}

@bartchr808
Copy link
Contributor Author

No problem @rxwei !

For error 1, should I file a bug here regarding it so we can investigate it further at a later date since it isn't a major bug, or file it somewhere else? Unsure as it's related to the LLDB Debugger, but also this seems TensorFlow specific.

Regarding error 2, thanks for the explanation that makes sense to me now! Especially after going through the Swift TensorFlow tutorial, it has made things clearer; specifically this limitation even seems sort of similar to the Swift Dataset API as described in the tutorial in that you need to make the dataset initialization function inlinable, copy the function to every Jupyter cell you use it, etc.

@rxwei
Copy link
Contributor

rxwei commented Dec 3, 2018

If you can file a JIRA bug for error 1, that would be helpful!

For error 2 we have a related bug: SR-8613, and have a planned fix next year.

@bartchr808
Copy link
Contributor Author

Filed the JIRA bug! Feel free to close this issue once you see this message.

@rxwei
Copy link
Contributor

rxwei commented Dec 4, 2018

Thanks!

@rxwei rxwei closed this as completed Dec 4, 2018
brettkoonce pushed a commit to brettkoonce/swift that referenced this issue Mar 14, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants