Let me try to explain why we need this in more technical detail.
Consider call as applyStyle(.bordered)
from type-checker's perspective. Here is how it sees it this expression:
applyStyle<$T_param : Style>($T_base.Type[.bordered == $T_bordered])
where $T_<something>
denotes a type variable as a placeholder for type to be inferred.
Parameter type in this case is $T_param
and argument type is $T_chain_result
(which is not visible here) which are connected through an argument conversion constraint. A valid solution in such case could only be formed if all of the type variables are inferred to be concrete types, what we know about the call is:
$T_param <conforms to> Style
$T_base.Type <should have a member named .bordered> which type is $T_bordered
$T_base <equals> $T_chain_result
$T_bordered <convertible to> $T_chain_result
$T_chain_result <argument conversion> $T_param
Type-checker could make progress towards inferring solution by trying to infer any of the listed type variables ($T_param
, $T_base
, $T_bordered
, $T_chain_result
), but unfortunately there are no concrete types here to replace any of the listed type variables with. And enumeration of possible types which could conform to Style
would be efficient because - a. Such list is not available, b. it would mean checking every possible type in sequence and trying to disambiguate.
That's where the new proposal comes in. It suggests that we should try to propagate Style
requirement through equality/subtype/conversion relationships down to $T_base
. Based on that protocol conformance requirement, as a last resort, we could infer $T_base
to be Style
and try to look up any static members on protocol metatype to make forward progress. Now, once $T_base
is bound to Style
it's possible to lookup .bordered
on it. After doing so we end up with updated constraints like so:
$T_base <bound to> Style
$T_bordered <bound to> BorderedStyle
$T_base == $T_chain_result
$T_bordered <convertible> $T_chain_result
$T_chain_result <argument conversion> $T_param
Here is where type-checker encounters another problem and what's why we'd have to make a lot more changes if we wanted to support unrestricted member reference on protocol metatypes:
$T_base == $T_chain_result
and $T_bordered <convertible> $T_chain_result
mean that $T_chain_result
has to be (existential type) Style
and be a concrete type convertible to BorderedStyle
at the same time.
So to fit into an existing model proposal suggests that new references are only allowed if it's possible to replace $T_base
with a concrete type which satisfies requirement of conforming to Style
, implicitly replacing $T_base
with BorderedStyle
right after lookup, in such case would mean that all of the constraints are satisfied and type-checker could reach a solution.
I think this is a balanced step which allows to cover all of the sort-comings of the syntax without introducing anything new to the language and would allow for lifting of result type requirement in the future (by ranking such members found on conforming types lower) in expense of having additional members be attached to conforming types (which is also how protocols work in general).