protocol FooType {
    var num:Int { get set }
}
class Foo: FooType {
    var num: Int = 0 {
        didSet {
            print("Did set num")
        }
    }
}
class Bar {
    var foo: FooType = Foo() {
        didSet {
            print("Did set Foo")
        }
    }
    func changeNum(num:Int) {
        foo.num = num
    }
}
let bar = Bar()
bar.changeNum(5)
Did set num
Did set Foo
In this example, setting a property on foo causes Bar's didSet for foo to get called.
I would expect only Foo's num didSet to get called.
If I remove the protocol constraint of Bar's foo property to FooType, it behaves as I expected.
protocol FooType {
    var num:Int { get set }
}
class Foo: FooType {
    var num: Int = 0 {
        didSet {
            print("Did set num")
        }
    }
}
class Bar {
    var foo = Foo() {
        didSet {
            print("Did set Foo")
        }
    }
    func changeNum(num:Int) {
        foo.num = num
    }
}
let bar = Bar()
bar.changeNum(5)
Did set num
If I keep the conformance to FooType, but add a class constraint (FooType: class), it also behaves as expected.
protocol FooType: class {
    var num:Int { get set }
}
class Foo: FooType {
    var num: Int = 0 {
        didSet {
            print("Did set num")
        }
    }
}
class Bar {
    var foo: FooType = Foo() {
        didSet {
            print("Did set Foo")
        }
    }
    func changeNum(num:Int) {
        foo.num = num
    }
}
let bar = Bar()
bar.changeNum(5)
Did set num
If I remove the protocol completely and make Foo a struct rather than a class, we're back to both setters being called.
struct Foo {
    var num: Int = 0 {
        didSet {
            print("Did set num")
        }
    }
}
class Bar {
    var foo = Foo() {
        didSet {
            print("Did set Foo")
        }
    }
    func changeNum(num:Int) {
        foo.num = num
    }
}
let bar = Bar()
bar.changeNum(5)
Did set num
Did set Foo
In the case changing Foo to a struct, I can see why it's happening... it mentions it in the swift documentation because a struct is a value type, it makes a copy, etc. (although I didn't expect it at first).
But the other cases I don't get...