Skip to content

Commit

Permalink
Sema: Fix convenience init delegation to a convenience init in a gene…
Browse files Browse the repository at this point in the history
…ric base class

While in the constraint system, the delegation is modeled as
returning an instance of the derived class, in the AST we type
the reference as returning an instance of the base class, and
insert a downcast, because in SILGen we're calling the base
class initializer which is typed as returning the base class.

This bit of fixup logic wasn't happening if the base class was
generic, and so we were not inserting the cast, which would
crash in SILGen with an assert.

Fixes <rdar://problem/31000248>.
  • Loading branch information
slavapestov committed Mar 26, 2017
1 parent fedf6b1 commit 19b12aa
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 9 deletions.
23 changes: 15 additions & 8 deletions lib/Sema/CSApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1389,21 +1389,28 @@ namespace {

ref = ConcreteDeclRef(ctx, ctor, substitutions);
} else {
Type containerTy = ctor->getDeclContext()->getDeclaredTypeOfContext();
resultTy = openedFullType->replaceCovariantResultType(
containerTy, ctor->getNumParameterLists());
// No substitutions.
resultTy = openedFullType;
ref = ConcreteDeclRef(ctor);
}

// The constructor was opened with the allocating type, not the
// initializer type. Map the former into the latter.
auto resultFnTy = resultTy->castTo<FunctionType>();
auto selfTy = resultFnTy->getInput()->getRValueInstanceType();
auto selfTy = resultTy->castTo<FunctionType>()->getInput()
->getRValueInstanceType();

// Also replace the result type with the base type, so that calls
// to constructors defined in a superclass will know to cast the
// result to the derived type.
resultTy = resultTy->replaceCovariantResultType(
selfTy, ctor->getNumParameterLists());

if (!selfTy->hasReferenceSemantics())
selfTy = InOutType::get(selfTy);

resultTy = FunctionType::get(selfTy, resultFnTy->getResult(),
resultFnTy->getExtInfo());

resultTy = FunctionType::get(selfTy,
resultTy->castTo<FunctionType>()->getResult(),
resultTy->castTo<FunctionType>()->getExtInfo());

// Build the constructor reference.
Expr *ctorRef = cs.cacheType(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: not --crash %target-swift-frontend -emit-silgen -primary-file %s -o /dev/null
// RUN: %target-swift-frontend -emit-silgen -primary-file %s -o /dev/null

class Base<T> {
convenience init(count: Int) {
Expand Down

0 comments on commit 19b12aa

Please sign in to comment.