Skip to content

Instantly share code, notes, and snippets.

@landonf
Last active April 30, 2019 14:28
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save landonf/0716c0e9655217d549e6 to your computer and use it in GitHub Desktop.
Save landonf/0716c0e9655217d549e6 to your computer and use it in GitHub Desktop.
My Swift Bugs
// FILED: rdar://17240493
// Type constraint ignored on function type parameter
//
protocol BoolT {}
class TrueT : BoolT {}
class FalseT : BoolT {}
protocol Nat {
typealias IsZero
}
class Zero : Nat {
typealias IsZero = TrueT
}
class Succ : Nat {
typealias IsZero = FalseT
}
// A type parameter with a constraint
func isZero<N : Nat where N.IsZero == TrueT> (n: N) {
println("true!")
}
// Shouldn't this fail to compile since Succ.IsZero is *not* TrueT?
// Instead, it compiles and runs, printing `true'
isZero(Succ())
// FILED: rdar//17240590
// Dueling function type constraints, plus conflicting struct types, triggers backend assertion:
//
// Basic Block in function '_TF9TypeLevel6isZeroUS_3Nat__FPS0__T_' does not have terminator!
// label %entry2
// LLVM ERROR: Broken function found, compilation aborted!
//
protocol BoolT {}
protocol TrueT : BoolT {}
protocol FalseT : BoolT {}
protocol Nat {
typealias IsZero = BoolT
}
struct Zero : Nat {
typealias IsZero = TrueT
}
struct Succ : Nat {
typealias IsZero = FalseT
}
func isZero<N : Nat where N.IsZero == TrueT> (n: N) {
println("true!")
}
// Comment this out and compliation succeeds
func isZero<N1 : Nat where N1.IsZero == FalseT> (n: N1) {
println("false!")
}
// FILED: rdar://17240737
// Crashes in swift::irgen::IRGenFunction::emitTypeMetadataRef()
//
protocol BoolT {}
protocol TrueT : BoolT {}
protocol FalseT : BoolT {}
protocol Nat {
typealias IsZero = BoolT
}
struct Zero : Nat {
typealias IsZero = TrueT
}
struct Succ : Nat {
typealias IsZero = FalseT
}
func isZero<B : TrueT, N : Nat where N.IsZero == B> (n: N) {
println("true!")
}
func isZero<N1 : Nat where N1.IsZero == FalseT> (n: N1) {
println("false!")
}
// Replace with isZero(Succ()) and the crash disappears
isZero(Zero())
// FILED: rdar://17240924
// Crashes with:
// malloc: *** error for object 0x7fff5a350c58: pointer being freed was not allocated
// in:
// 5 libsystem_malloc.dylib 0x00007fff9782607f malloc_get_zone_name + 0
// 6 swift 0x0000000106417e82 llvm::Value::setName(llvm::Twine const&) + 594
// 7 swift 0x0000000105919765 swift::irgen::IRGenFunction::bindArchetype(swift::ArchetypeType*, llvm::Value*, llvm::ArrayRef<llvm::Value*>) + 101
// 8 swift 0x000000010591f9e8 (anonymous namespace)::EmitPolymorphicParameters::emitWithSourceBound(swift::irgen::Explosion&) + 1192
//
protocol BoolT {}
class FalseT : BoolT {}
class TrueT : BoolT {}
// If you reverse the check, this doesn't crash
struct NatEqualsT<N1 : Nat, N2: Nat where N2.IsZero == N1.IsZero> {}
// struct NatEqualsT<N1 : Nat, N2: Nat where N1.IsZero == N2.IsZero> {}
protocol Nat {
typealias IsZero
}
// FILED: rdar://17242441
// Segfaults the typechecker (after triggering a type error) in:
// swift::TypeBase::getCanonicalType() + 1429
//
protocol BoolT {}
class FalseT : BoolT {}
class TrueT : BoolT {}
class EqualsVisitor <N1 : Nat, N2 : Nat where N1.Prev == N2> : NatVisitor {
}
protocol Nat {
typealias Prev
typealias Equals
}
struct SuccessorT<P : Nat> : Nat {
// from TypeNatural
typealias Prev = P
typealias Equals = EqualsVisitor<SuccessorT<P>, Prev>
}
// rdar://17242486
// EqualsVisitor types segfault the type checker in:
// 4 swift 0x0000000109f7a225 std::__1::__function::__func<swift::Type::subst(swift::Module*, llvm::DenseMap<swift::TypeBase*, swift::Type, llvm::DenseMapInfo<swift::TypeBase*> >&, bool, swift::LazyResolver*) const::$_4, std::__1::allocator<swift::Type::subst(swift::Module*, llvm::DenseMap<swift::TypeBase*, swift::Type, llvm::DenseMapInfo<swift::TypeBase*> >&, bool, swift::LazyResolver*) const::$_4>, swift::Type (swift::Type)>::operator()(swift::Type&&) + 949
// 5 swift 0x0000000109f78120 swift::Type::transform(std::__1::function<swift::Type (swift::Type)> const&) const + 48
//
protocol BoolT {}
class FalseT : BoolT {}
class TrueT : BoolT {}
protocol NatVisitor {
typealias VisitType
typealias VisitZero = VisitType
typealias VisitSucc = VisitType
}
class EqualsVisitor <N1 : Nat, N2 : Nat where N1.Prev == N2> : NatVisitor { }
class EqualsVisitor <N1, N2> {}
/** A natural number encoded in the type system */
protocol Nat {
typealias Prev
}
// FILED: rdar://17242683
// Type inference engine appears to infer a nonsense type for the entire expression.
//
import Foundation
func try<T> (expr: (NSErrorPointer) -> T?) -> Result<NSError, T> {
var error : NSError?
if let result = expr(&error) {
return .Ok({result})
} else {
return .Err({error!}) // Will trigger a runtime error if `error` was not populated.
}
}
enum Result<X, T> {
case Err(() -> X)
case Ok(() -> T)
}
let fm = NSFileManager.defaultManager()
// error: cannot convert the expression's type 'Result<NSError, $T1>' to type '$T1!'
try { return fm.contentsOfDirectoryAtPath("/", error: $0) }
// This also fails, with the same error
// try { return fm.contentsOfDirectoryAtPath("/", error: $0) as AnyObject[]! }
// But this works:
// try { fm.contentsOfDirectoryAtPath("/", error: $0 ) }
// FILED: rdar://17242908
// Compiler can't disambiguate constraints for the second function, parsing fails.
//
import Foundation
protocol Ex {
typealias T
typealias U
}
// Works
func foo<E : Ex, B : Ex where B.T == E.T, B.U == E.U> () {
}
// Ambiguious
// error: expected '>' to complete generic parameter list
func foo<E : Ex, B : Ex where B.T == E.T, B.U == E.U, A : Ex where A.T = B.T> () {
}
// FILED: rdar://17242985
// The runtime permits out-of-bounds Range subscript access
//
let f = 0 .. 10
// Prints '20' instead of raising an error.
println(f[20])
//
// Crashes in swift::Lowering::TypeConverter::getTypeLowering(swift::Lowering::AbstractionPattern, swift::Type, unsigned int) + 67
//
enum Typed<T : AnyObject> {
case IllTyped(object: AnyObject)
case Missing()
case WellTyped(value: T)
}
protocol Lens {
typealias Node
typealias Key
typealias Result : AnyObject
func get (node: Node, _ key: Key) -> Typed<Result>
}
func get<N, K, R, L : Lens where L.Node == N, L.Key == K, L.Result == R> (lens: L, node: N, key: K) -> Typed<R> {
return lens.get(node, key)
}
// Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
// 0 swift 0x000000010d2f9923 swift::Lowering::TypeConverter::getTypeLowering(swift::Lowering::AbstractionPattern, swift::Type, unsigned int) + 67
// 1 swift 0x000000010d34a802 emitDecisionTree(swift::Lowering::SILGenFunction&, swift::SwitchStmt*, (anonymous namespace)::ClauseMatrix&&, llvm::MapVector<swift::CaseStmt*, (anonymous namespace)::CaseBlock, llvm::DenseMap<swift::CaseStmt*, unsigned int, llvm::DenseMapInfo<swift::CaseStmt*> >, std::__1::vector<std::__1::pair<swift::CaseStmt*, (anonymous namespace)::CaseBlock>, std::__1::allocator<std::__1::pair<swift::CaseStmt*, (anonymous namespace)::CaseBlock> > > >&, swift::SILBasicBlock*, unsigned int) + 7426
// 2 swift 0x000000010d347d2d swift::Lowering::SILGenFunction::emitSwitchStmt(swift::SwitchStmt*) + 1197
class NSDictLens<T : AnyObject> : Lens {
typealias Node = NSDictionary
typealias Key = String
typealias Result = T
func get (node: Node, _ key: Key) -> Typed<Result> {
let obj: AnyObject? = node[key]
switch obj {
case let value as T: return Typed.WellTyped(value: value);
case .Some(let other): return Typed.IllTyped(object: other)
}
}
}
//
// Crashes in swift::NominalTypeDecl::getExtensions() + 18
//
class Observable<T> : Stream<T> {
let create: (T -> T -> ())
var observers: Array<Event<T> -> ()> = []
struct TypeParam<O : Observer where O.EventType == T> {
let v: O
}
let tp:TypeParam<Observer>
init<O : Observer where O.EventType == T> (_ create: O -> Event<T> -> ()) {
self.create = create
}
func observe<O : Observer where O.EventType == T> (observer: O) -> Disposable {
self.observers.append(create(observer))
return Disposable()
}
class func empty() -> Stream<T> {
return Observable { observer in
observer.send(.Completed)
}
}
}
class Stream<T> {
}
protocol Observer {
typealias EventType
func send(Event<EventType>)
}
class Disposable {}
enum Event<T> {
//case Next(Box<T>)
//case Error(NSError)
case Completed
}
func main() {
}
//
// Subclasses are not permitted to specify a concrete type for a superclass' type parameter.
// error: classes derived from generic classes must also be generic
//
class Boxed<T> {
let v: T
init (v: T) { self.v = v }
}
// error: classes derived from generic classes must also be generic
class ExprR : Boxed<Expr> {}
enum Expr {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment