diff --git a/lib/IRGen/GenArchetype.h b/lib/IRGen/GenArchetype.h index b2abfcfc3f9fb..b80a7b2c207c4 100644 --- a/lib/IRGen/GenArchetype.h +++ b/lib/IRGen/GenArchetype.h @@ -18,6 +18,7 @@ #define SWIFT_IRGEN_GENARCHETYPE_H #include "swift/AST/Types.h" +#include "llvm/ADT/STLExtras.h" namespace llvm { class Value; @@ -31,6 +32,13 @@ namespace irgen { class Address; class IRGenFunction; + using GetTypeParameterInContextFn = + llvm::function_ref; + + void bindArchetypeAccessPaths(IRGenFunction &IGF, + GenericSignature *generics, + GetTypeParameterInContextFn getInContext); + /// Emit a type metadata reference for an archetype. llvm::Value *emitArchetypeTypeMetadataRef(IRGenFunction &IGF, CanArchetypeType archetype); diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp index 3a31881eaec41..3333be2d0b576 100644 --- a/lib/IRGen/GenMeta.cpp +++ b/lib/IRGen/GenMeta.cpp @@ -2762,6 +2762,18 @@ irgen::emitFieldTypeAccessor(IRGenModule &IGM, // use it to provide metadata for generic parameters in field types. IGF.bindLocalTypeDataFromTypeMetadata(formalType, IsExact, metadata); + // Bind archetype access paths if the type is generic. + if (type->isGenericContext()) { + auto declCtxt = type; + if (auto generics = declCtxt->getGenericSignatureOfContext()) { + auto getInContext = [&](CanType type) -> CanType { + return ArchetypeBuilder::mapTypeIntoContext(declCtxt, type, nullptr) + ->getCanonicalType(); + }; + bindArchetypeAccessPaths(IGF, generics, getInContext); + } + } + // Allocate storage for the field vector. unsigned allocSize = fieldTypes.size() * IGM.getPointerSize().getValue(); auto allocSizeVal = llvm::ConstantInt::get(IGM.IntPtrTy, allocSize); diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp index e59bf7295f699..5da8cb190e828 100644 --- a/lib/IRGen/GenProto.cpp +++ b/lib/IRGen/GenProto.cpp @@ -995,10 +995,6 @@ getWitnessTableLazyAccessFunction(IRGenModule &IGM, return accessor; } -static void bindArchetypeAccessPaths(IRGenFunction &IGF, - GenericSignature *Generics, - GetTypeParameterInContextFn getInContext); - namespace { /// Conformance info for a witness table that can be directly generated. @@ -1853,9 +1849,8 @@ void addPotentialArchetypeAccessPath(IRGenFunction &IGF, {srcBaseArchetype, association}); } -static void bindArchetypeAccessPaths(IRGenFunction &IGF, - GenericSignature *Generics, - GetTypeParameterInContextFn getInContext) { +void irgen::bindArchetypeAccessPaths(IRGenFunction &IGF, GenericSignature *Generics, + GetTypeParameterInContextFn getInContext) { // Remember all the extra ways we have of reaching the parameter // archetypes due to type equality constraints. for (auto reqt : Generics->getRequirements()) { diff --git a/test/IRGen/same_type_constraints.swift b/test/IRGen/same_type_constraints.swift index 9887d110ef488..61bb861b07956 100644 --- a/test/IRGen/same_type_constraints.swift +++ b/test/IRGen/same_type_constraints.swift @@ -23,13 +23,22 @@ public class C2: C1 {} // CHECK: define{{( protected)?}} void @_TFC21same_type_constraints2C1D -public protocol DataType {} +public protocol MyHashable {} +public protocol DataType : MyHashable {} public protocol E { associatedtype Data: DataType } +struct Dict {} +struct Val {} + public class GenericKlazz : E where R.Data == T { public typealias Data = T + + var d: Dict + init() { + d = Dict() + } }