Implicit promotion of Optional

Is there a blessed guide or documentation on "Optional Promotion"?

This "feature" seems to be a Swift only? I haven't used another language where I can pass T where T? is being required. I'd like to know more specifics about when this promotion can happen? How deep the chain can this happen? T??
This is the only thing I could find

This is so magical I think it is almost like everytime I say I can take an optional I am also saying I take a non optional as in func myFunc(_ thing: String? | String). In TS this would be something like function myFunc( thing: string | null)

Is there some form of a magical subtyping happening here? As in, is String a subtype of String? /? Is String?? a subtype of String??? /?

This may seem like I am trolling but I really want to have some sort of reference.

Yes, T is a subtype of Optional<T>. Therefore String?? is a subtype of String??? I'm not sure where the exact reference on this is, give me a few minutes to look it up.

EDIT: This was the best I could find, the built in subtyping support of Optional<T> should probably get an appendix in the Swift language guide or something.

1 Like

Nice find but I guess those were "only vague notions." ;) I guess this is called "implicit promotion". Maybe @Ben_Cohen can update his 2014 article now that we is part of the core team. :)

I guess the teams was planning some work in this area.

As far as I know, there are two conversion rules in the type checker that are relevant to this question:

Rule 1:
A type T1 is implicitly convertible to T2? if T1 is implicitly convertible to T2.

Examples:

let x = 2
let y: Int? = x // Int is implicitly convertible to Int?,
			    // because Int is implicitly convertible to itself.

let x = 2
let y: Int?? = x  // Int is implicitly convertible to Int??,
		          // because Int is implicitly convertible to Int?,
		          // because Int is implicitly convertible to itself.

class B {}
class C: B {}

let c = C()
let b: B? = c	// C is implicitly convertible to B?,
     			// because C is implicitly convertible to B,
	    		// because a subclass is implicitly convertible to its base class.

Rule 2:
A type T1? is implicitly convertible to T2? if T1 is implicitly convertible to T2.

Examples:

let x: Int? = 42
let y: Any? = x	// Int? is implicitly convertible to Any?,
     			// because Int is implicitly convertible to Any,
	    		// because any type is implicitly convertible to Any.

class B {}
class C: B {}

let c: C? = C()
let b: B? = c	// C? is implicitly convertible to B?,
     			// because C is implicitly convertible to B,
	    		// because a subclass is implicitly convertible to its base class.

I hope this helps. I don't know if there's an official reference of these implicit conversions somewhere, but I did list many of them in my master thesis (see chapter 6.6.14 Conversions on pages 118-120).

3 Likes