[Pitch 2] Light-weight same-type requirement syntax

I couldn’t help drafting up another example of how generic protocols could be useful. In this case, CollidesWith<T> is a generic protocol, and a generic extension implements weapon-collision logic for all entities that have hit points:

//MARK: Collision Detection

/// A generic protocol that describes how one kind of thing reacts to colliding with another kind of thing.
protocol CollidesWith<Other> {
    var position: Vec3 { get, private(set) }
    var velocity: Vec3 { get, private(set) }
    func handleCollision(with other: Other)
}

/// If T: CollidesWith<U>, then implicitly U: CollidesWith<T>.
extension<T, U> T: CollidesWith<U> where U: CollidesWith<T> {
    func handleCollision(with other: U) {
        // Nothing happens by default.
        // Can be refined by conformers.
    }
}

// Entry point for collision system.
extension CollidesWith<Other> {
    func collide(with other: Other) {
        handleCollision(with: other)
        Other.handleCollision(with: self)
    }
}

/// All the Entities that can collide with each other.
var objects: [any CollidesWith]

func physicsTick(deltaT: Int) {
    // Integrate object velocities and test for collisions.
    let collisions = gatherIntersections(among: objects, over: deltaT)
    
    for (object1, object2) in collisions {
        // This single call will handle both aspects of the collision, even if one object doesn’t react.
        object1.collide(with: object2)
    }
    
    // Apply (potentially modified) velocity.
    for object in objects {
        object.integratePosition(over: deltaT)
    }
}

//MARK: Game Specific Logic

// The world has a ground plane.
struct Ground {
    let elevation: Float
}

// Things can’t fall past the ground.
extension CollidesWith<Ground> {
    func handleCollision(with ground: Ground) {
        velocity.z = 0
    }
}

// A Weapon is anything that can cause damage.
struct Weapon {
    var damage: Int
}

// A protocol for anything that can be damaged or healed.
protocol HasHitPoints {
    var hp: Int { get, private(set) }
}

// When a weapon strikes, it causes damage.
// This is a generic extension, implemented on all types that conform to CollidesWith<Weapon>.
extension<T: HasHitPoints> T where T: CollidesWith<Weapon> {
    func handleCollision(with weapon: Weapon) {
        hp -= weapon.damage
    }
}

// A player loses when they run out of hit points.
// Notice how struct Player _only_ implements the game-over condition; weapon handling is handled by the generic extension above, but the hp setter is kept private.
struct Player: HasHitPoints, CollidesWith<Weapon>, CollidesWith<Ground> {
    private var _hp: Int
    var hp {
        get { _hp }
        private(set) {
            // No resurrecting dead players!
            if (_hp >= 0) {
                _hp = newValue
            }
        }
        didSet {
            if _hp <= 0 {
                gameOver()
            }
        }
    }
}