Start allowing extensions of protocol types.

Remove the semantic restrictions that prohibited extensions of
protocol types, and start making some systematic changes so that
protocol extensions start to make sense:
  - Replace a lot of occurrences of isa<ProtocolDecl> and
    dyn_cast<ProtocolDecl> on DeclContexts to use the new
    DeclContext::isProtocolOrProtocolExtensionContext(), where we want
    that behavior to apply equally to protocols and protocol extensions.
  - Eliminate ProtocolDecl::getSelf() in favor of
    DeclContext::getProtocolSelf(), which produces the appropriate
    generic type parameter for the 'Self' of a protocol or protocol
    extension. Update all of the callers of ProtocolDecl::getSelf()
    appropriately.
  - Update extension validation to appropriately form generic
    parameter lists for protocol extensions.
  - Methods in protocol extensions always use the witnesscc calling
  convention.

At this point, we can type check and SILGen very basic definitions of
protocol extensions with methods that can call protocol requirements,
generic free functions, and other methods within the same protocol
extension.

Regresses four compiler crashers but improves three compiler
crashers... we'll call that "progress"; the four regressions all hit
the same assertion in the constraint system that will likely be
addressed as protocol extensions starts working.

Swift SVN r26579
This commit is contained in:
Doug Gregor
2015-03-26 04:50:51 +00:00
parent 2350895b08
commit 3d77855b31
38 changed files with 322 additions and 168 deletions

View File

@@ -943,7 +943,8 @@ void ConstraintSystem::openGeneric(
auto subjectTy = req.getFirstType().transform(replaceDependentTypes);
if (auto proto = req.getSecondType()->getAs<ProtocolType>()) {
if (!skipProtocolSelfConstraint ||
!(isa<ProtocolDecl>(dc) || isa<ProtocolDecl>(dc->getParent())) ||
!(dc->isProtocolOrProtocolExtensionContext() ||
dc->getParent()->isProtocolOrProtocolExtensionContext()) ||
!isProtocolSelfType(req.getFirstType())) {
addConstraint(ConstraintKind::ConformsTo, subjectTy, proto,
locatorPtr);
@@ -1122,9 +1123,9 @@ ConstraintSystem::getTypeOfMemberReference(Type baseTy, ValueDecl *value,
// Determine the object type of 'self'.
auto nominal = value->getDeclContext()->getDeclaredTypeOfContext()
->getAnyNominal();
if (auto protocol = dyn_cast<ProtocolDecl>(nominal)) {
if (dc->isProtocolOrProtocolExtensionContext()) {
// Retrieve the type variable for 'Self'.
selfTy = replacements[protocol->getSelf()->getDeclaredType()
selfTy = replacements[dc->getProtocolSelf()->getDeclaredType()
->getCanonicalType()];
} else {
// Open the nominal type.
@@ -1182,7 +1183,7 @@ ConstraintSystem::getTypeOfMemberReference(Type baseTy, ValueDecl *value,
// Constrain the 'self' object type.
auto openedFnType = openedType->castTo<FunctionType>();
Type selfObjTy = openedFnType->getInput()->getRValueInstanceType();
if (isa<ProtocolDecl>(value->getDeclContext())) {
if (value->getDeclContext()->isProtocolOrProtocolExtensionContext()) {
// For a protocol, substitute the base object directly. We don't need a
// conformance constraint because we wouldn't have found the declaration
// if it didn't conform.