diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index b66a4234d3d..e9d50decd61 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -4244,19 +4244,25 @@ SILGenModule::emitKeyPathComponentForDecl(SILLocation loc, CanType componentTy; if (!var->getDeclContext()->isTypeContext()) { componentTy = var->getInterfaceType()->getCanonicalType(); + } else if (var->getDeclContext()->getSelfProtocolDecl() && + baseTy->isExistentialType()) { + componentTy = var->getValueInterfaceType()->getCanonicalType(); + ASSERT(!componentTy->hasTypeParameter()); } else { - componentTy = + // The mapTypeIntoContext() / mapTypeOutOfContext() dance is there + // to handle the case where baseTy being a type parameter subject + // to a superclass requirement. + componentTy = var->getValueInterfaceType().subst( GenericEnvironment::mapTypeIntoContext(genericEnv, baseTy) - ->getTypeOfMember(var) - ->getReferenceStorageReferent() + ->getContextSubstitutionMap(var->getDeclContext())) ->mapTypeOutOfContext() ->getCanonicalType(); + } - // The component type for an @objc optional requirement needs to be - // wrapped in an optional. - if (var->getAttrs().hasAttribute()) { - componentTy = OptionalType::get(componentTy)->getCanonicalType(); - } + // The component type for an @objc optional requirement needs to be + // wrapped in an optional. + if (var->getAttrs().hasAttribute()) { + componentTy = OptionalType::get(componentTy)->getCanonicalType(); } if (canStorageUseStoredKeyPathComponent(var, expansion)) { diff --git a/test/SILGen/keypaths.swift b/test/SILGen/keypaths.swift index 5c28014c962..6abc6b13c60 100644 --- a/test/SILGen/keypaths.swift +++ b/test/SILGen/keypaths.swift @@ -677,3 +677,12 @@ func test_optional_chaining_with_function_conversion() { _ = data.compactMap(\.elements!.db) } } + +protocol HasAlias { + var id: Self.ID { get } + typealias ID = Int +} + +func testHasAlias() { + _ = \HasAlias.id +} \ No newline at end of file