Overridden Overload Resolution

Overload resolution per se is not hard to understand. But when override gets involved it becomes quite a puzzle.

protocol P {}

class A {}

class B: A, P {
    func m1(_: B) -> String {
        return "B.m1(:B)"
    }

    func m2(_: A) -> String {
        return "B.m2(:A)"
    }

    func m2(_: B) -> String {
        return "B.m2(:B)"
    }
}

class C: B {
    func m1(_: P) -> String {
        return "C.m1(:P)"
    }

    override func m1(_: A) -> String {
        return "C.m1(:A)"
    }

    override func m2(_: A) -> String {
        return "C.m2(:A)"
    }
}

func f(_: B, _: B) {}
func f(_: C, _: A) {}
func f(_: C, _: P) {}

let c = C()

c.m1(c)
c.m2(c)
f(c, c)
  1. Without running the code and reading further, can you tell which calls cause resolution issue?
  2. Can the resolution issue of the f call be solved by commenting out f(:C, :A)? In other words, is there any ambiguity between f(:B, :B) and f(:C, :P)?
  3. Can the resolution issue of the m1 call be solved by commenting out C.m1(:A)? In other words, is there any ambiguity between B.m1(:B) and C.m1(:P)?
  4. Why does the m2 call have no resolution issue?