Feasibility of "T1 & ¬T2"

Hi SE,

I’m pondering some esoteric type stuff as I’m sketching out an improved date/time library (https://github.com/davedelong/Chronology), and I’m wondering two things:

1️⃣ Is there a way to express a type that does *not* conform to a protocol?

For example, let’s say I have three protocols:

protocol YearHaving { var year: Int }
protocol MonthHaving { var month: Int }
protocol DayHaving { var day: Int }
typealias DateHaving = YearHaving & MonthHaving & DayHaving

Now, I want to allow for some adjustments to values that have these types:

extension DayHaving {
    func removingDay() → Self & ¬DayHaving // whatever type “self” is, except it does not conform to “DayHaving”, because you just removed the day value
}

Is this possible?

2️⃣ If this is not possible, would it be hard to add something like this in?

Dave

Hi SE,

I’m pondering some esoteric type stuff as I’m sketching out an improved date/time library (https://github.com/davedelong/Chronology), and I’m wondering two things:

1️⃣ Is there a way to express a type that does *not* conform to a protocol?

For example, let’s say I have three protocols:

protocol YearHaving { var year: Int }
protocol MonthHaving { var month: Int }
protocol DayHaving { var day: Int }
typealias DateHaving = YearHaving & MonthHaving & DayHaving

Now, I want to allow for some adjustments to values that have these types:

extension DayHaving {
    func removingDay() → Self & ¬DayHaving // whatever type “self” is, except it does not conform to “DayHaving”, because you just removed the day value
}

Is this possible?

There is no way to express this.

2️⃣ If this is not possible, would it be hard to add something like this in?

It would not be hard, although do note that it can only check “there is no conformance of the type to the protocol visible from this module”; a conformance might be present in some other module, or might be loaded dynamically later on. It can also be “hidden” from the static type system:

func f<T>(_: T) where ¬DayHaving { }
struct X { }
f(X()) // okay
struct Y : DayHaving { }
f(Y()) // error: Y conforms to DayHaving but shouldn’t

func g<T>(_ t: T) { f(t) } // succeeds, because T is not known to conform to DayHaving
g(X()) // okay, as expected
g(Y()) // okay, but surprising

  - Doug

···

On Nov 29, 2017, at 7:27 PM, Dave DeLong via swift-evolution <swift-evolution@swift.org> wrote: