Remove Module parameter from GenericEnvironment::mapTypeOutOfContext.

The substitution only replaces archetypes with abstract generic parameters, so no conformance lookup is necessary, and we can provide a "lookup" callback now that just vends abstract conformances.

(Ideally, we'd be able to do this for mapTypeIntoContext too, but we run into problems with generic signatures with same-type constraints on associated types with protocol requirements. Mapping `t_0_0.AssocType` into such a context will require conformance lookup for the concrete type replacement, since same-type Requirements don't preserve the conformances that satisfy the protocol requirements for the same-type relationship.)
This commit is contained in:
Joe Groff
2016-12-15 10:55:33 -08:00
parent b482c7ff33
commit 57d9ad0a03
13 changed files with 48 additions and 47 deletions

View File

@@ -315,8 +315,7 @@ public:
static Type mapTypeOutOfContext(const DeclContext *dc, Type type); static Type mapTypeOutOfContext(const DeclContext *dc, Type type);
/// Map a contextual type to an interface type. /// Map a contextual type to an interface type.
static Type mapTypeOutOfContext(ModuleDecl *M, static Type mapTypeOutOfContext(GenericEnvironment *genericEnv,
GenericEnvironment *genericEnv,
Type type); Type type);
/// \brief Dump all of the requirements, both specified and inferred. /// \brief Dump all of the requirements, both specified and inferred.

View File

@@ -197,7 +197,7 @@ public:
} }
/// Map a contextual type to an interface type. /// Map a contextual type to an interface type.
Type mapTypeOutOfContext(ModuleDecl *M, Type type) const; Type mapTypeOutOfContext(Type type) const;
/// Map an interface type to a contextual type. /// Map an interface type to a contextual type.
Type mapTypeIntoContext(ModuleDecl *M, Type type) const; Type mapTypeIntoContext(ModuleDecl *M, Type type) const;

View File

@@ -105,6 +105,17 @@ public:
ProtocolType *conformedProtocol) const; ProtocolType *conformedProtocol) const;
}; };
/// Functor class suitable for use as a \c LookupConformanceFn that provides
/// only abstract conformances for generic types. Asserts that the replacement
/// type is an opaque generic type.
class MakeAbstractConformanceForGenericType {
public:
Optional<ProtocolConformanceRef>
operator()(CanType dependentType,
Type conformingReplacementType,
ProtocolType *conformedProtocol) const;
};
/// Flags that can be passed when substituting into a type. /// Flags that can be passed when substituting into a type.
enum class SubstFlags { enum class SubstFlags {
/// If a type cannot be produced because some member type is /// If a type cannot be produced because some member type is

View File

@@ -423,8 +423,7 @@ auto ArchetypeBuilder::PotentialArchetype::getNestedType(
// Map the type out of its context. // Map the type out of its context.
if (auto genericEnv = alias->getGenericEnvironmentOfContext()) { if (auto genericEnv = alias->getGenericEnvironmentOfContext()) {
type = genericEnv->mapTypeOutOfContext(alias->getModuleContext(), type = genericEnv->mapTypeOutOfContext(type);
type);
} }
if (auto existingPA = builder.resolveArchetype(type)) { if (auto existingPA = builder.resolveArchetype(type)) {
@@ -688,8 +687,7 @@ void ArchetypeType::resolveNestedType(
auto &builder = *genericEnv->getArchetypeBuilder(); auto &builder = *genericEnv->getArchetypeBuilder();
Type interfaceType = Type interfaceType =
genericEnv->mapTypeOutOfContext(&builder.getModule(), genericEnv->mapTypeOutOfContext(const_cast<ArchetypeType *>(this));
const_cast<ArchetypeType *>(this));
auto parentPA = builder.resolveArchetype(interfaceType); auto parentPA = builder.resolveArchetype(interfaceType);
auto memberPA = parentPA->getNestedType(nested.first, builder); auto memberPA = parentPA->getNestedType(nested.first, builder);
auto result = memberPA->getTypeInContext(builder, genericEnv); auto result = memberPA->getTypeInContext(builder, genericEnv);
@@ -1975,14 +1973,12 @@ Type ArchetypeBuilder::mapTypeIntoContext(ModuleDecl *M,
Type Type
ArchetypeBuilder::mapTypeOutOfContext(const DeclContext *dc, Type type) { ArchetypeBuilder::mapTypeOutOfContext(const DeclContext *dc, Type type) {
return mapTypeOutOfContext(dc->getParentModule(), return mapTypeOutOfContext(dc->getGenericEnvironmentOfContext(),
dc->getGenericEnvironmentOfContext(),
type); type);
} }
Type Type
ArchetypeBuilder::mapTypeOutOfContext(ModuleDecl *M, ArchetypeBuilder::mapTypeOutOfContext(GenericEnvironment *env,
GenericEnvironment *env,
Type type) { Type type) {
auto canType = type->getCanonicalType(); auto canType = type->getCanonicalType();
assert(!canType->hasTypeParameter() && "already have an interface type"); assert(!canType->hasTypeParameter() && "already have an interface type");
@@ -1991,7 +1987,7 @@ ArchetypeBuilder::mapTypeOutOfContext(ModuleDecl *M,
assert(env && "dependent type in non-generic context"); assert(env && "dependent type in non-generic context");
return env->mapTypeOutOfContext(M, type); return env->mapTypeOutOfContext(type);
} }
void ArchetypeBuilder::addGenericSignature(GenericSignature *sig) { void ArchetypeBuilder::addGenericSignature(GenericSignature *sig) {

View File

@@ -303,7 +303,7 @@ Type DeclContext::mapTypeIntoContext(Type type) const {
Type DeclContext::mapTypeOutOfContext(Type type) const { Type DeclContext::mapTypeOutOfContext(Type type) const {
if (auto genericEnv = getGenericEnvironmentOfContext()) if (auto genericEnv = getGenericEnvironmentOfContext())
return genericEnv->mapTypeOutOfContext(getParentModule(), type); return genericEnv->mapTypeOutOfContext(type);
return type; return type;
} }

View File

@@ -142,9 +142,9 @@ bool GenericEnvironment::containsPrimaryArchetype(
QueryArchetypeToInterfaceSubstitutions(this)(archetype)); QueryArchetypeToInterfaceSubstitutions(this)(archetype));
} }
Type GenericEnvironment::mapTypeOutOfContext(ModuleDecl *M, Type type) const { Type GenericEnvironment::mapTypeOutOfContext(Type type) const {
type = type.subst(QueryArchetypeToInterfaceSubstitutions(this), type = type.subst(QueryArchetypeToInterfaceSubstitutions(this),
LookUpConformanceInModule(M), MakeAbstractConformanceForGenericType(),
SubstFlags::AllowLoweredTypes); SubstFlags::AllowLoweredTypes);
assert(!type->hasArchetype() && "not fully substituted"); assert(!type->hasArchetype() && "not fully substituted");
return type; return type;

View File

@@ -2892,6 +2892,16 @@ LookUpConformanceInSubstitutionMap::operator()(CanType dependentType,
return Subs.lookupConformance(dependentType, conformedProtocol->getDecl()); return Subs.lookupConformance(dependentType, conformedProtocol->getDecl());
} }
Optional<ProtocolConformanceRef>
MakeAbstractConformanceForGenericType::operator()(CanType dependentType,
Type conformingReplacementType,
ProtocolType *conformedProtocol) const {
assert((conformingReplacementType->is<SubstitutableType>()
|| conformingReplacementType->is<DependentMemberType>())
&& "replacement requires looking up a concrete conformance");
return ProtocolConformanceRef(conformedProtocol->getDecl());
}
Type DependentMemberType::substBaseType(ModuleDecl *module, Type DependentMemberType::substBaseType(ModuleDecl *module,
Type substBase, Type substBase,
LazyResolver *resolver) { LazyResolver *resolver) {

View File

@@ -277,8 +277,7 @@ SILType GenericEnvironment::mapTypeIntoContext(SILModule &M,
} }
Type SILFunction::mapTypeOutOfContext(Type type) const { Type SILFunction::mapTypeOutOfContext(Type type) const {
return ArchetypeBuilder::mapTypeOutOfContext(getModule().getSwiftModule(), return ArchetypeBuilder::mapTypeOutOfContext(getGenericEnvironment(),
getGenericEnvironment(),
type); type);
} }

View File

@@ -1591,7 +1591,6 @@ static CanAnyFunctionType getDefaultArgGeneratorInterfaceType(
if (auto genTy = funcInfo.FormalInterfaceType->getAs<GenericFunctionType>()) { if (auto genTy = funcInfo.FormalInterfaceType->getAs<GenericFunctionType>()) {
sig = genTy->getGenericSignature()->getCanonicalSignature(); sig = genTy->getGenericSignature()->getCanonicalSignature();
resultTy = ArchetypeBuilder::mapTypeOutOfContext( resultTy = ArchetypeBuilder::mapTypeOutOfContext(
TC.M.getSwiftModule(),
funcInfo.GenericEnv, funcInfo.GenericEnv,
resultTy)->getCanonicalType(); resultTy)->getCanonicalType();
} }

View File

@@ -1986,12 +1986,10 @@ getOrCreateReabstractionThunk(GenericEnvironment *genericEnv,
// Substitute context parameters out of the "from" and "to" types. // Substitute context parameters out of the "from" and "to" types.
auto fromInterfaceType auto fromInterfaceType
= ArchetypeBuilder::mapTypeOutOfContext( = ArchetypeBuilder::mapTypeOutOfContext(genericEnv, fromType)
M.getSwiftModule(), genericEnv, fromType)
->getCanonicalType(); ->getCanonicalType();
auto toInterfaceType auto toInterfaceType
= ArchetypeBuilder::mapTypeOutOfContext( = ArchetypeBuilder::mapTypeOutOfContext(genericEnv, toType)
M.getSwiftModule(), genericEnv, toType)
->getCanonicalType(); ->getCanonicalType();
mangler.mangleType(fromInterfaceType, /*uncurry*/ 0); mangler.mangleType(fromInterfaceType, /*uncurry*/ 0);

View File

@@ -138,9 +138,7 @@ void GenericTypeToArchetypeResolver::recordParamType(ParamDecl *decl, Type type)
// When type checking functions, the CompleteGenericTypeResolver sets // When type checking functions, the CompleteGenericTypeResolver sets
// the interface type. // the interface type.
if (!decl->hasInterfaceType()) if (!decl->hasInterfaceType())
decl->setInterfaceType(ArchetypeBuilder::mapTypeOutOfContext( decl->setInterfaceType(ArchetypeBuilder::mapTypeOutOfContext(GenericEnv,
decl->getDeclContext()->getParentModule(),
GenericEnv,
type)); type));
} }

View File

@@ -2106,9 +2106,6 @@ Type TypeResolver::resolveASTFunctionType(FunctionTypeRepr *repr,
extInfo = extInfo.withThrows(repr->throws()); extInfo = extInfo.withThrows(repr->throws());
ModuleDecl *M = DC->getParentModule();
// If this is a function type without parens around the parameter list, // If this is a function type without parens around the parameter list,
// diagnose this and produce a fixit to add them. // diagnose this and produce a fixit to add them.
if (!isa<TupleTypeRepr>(repr->getArgsTypeRepr()) && if (!isa<TupleTypeRepr>(repr->getArgsTypeRepr()) &&
@@ -2127,8 +2124,8 @@ Type TypeResolver::resolveASTFunctionType(FunctionTypeRepr *repr,
if (auto genericEnv = repr->getGenericEnvironment()) { if (auto genericEnv = repr->getGenericEnvironment()) {
auto *genericSig = repr->getGenericSignature(); auto *genericSig = repr->getGenericSignature();
assert(genericSig != nullptr && "Did not call handleSILGenericParams()?"); assert(genericSig != nullptr && "Did not call handleSILGenericParams()?");
inputTy = ArchetypeBuilder::mapTypeOutOfContext(M, genericEnv, inputTy); inputTy = ArchetypeBuilder::mapTypeOutOfContext(genericEnv, inputTy);
outputTy = ArchetypeBuilder::mapTypeOutOfContext(M, genericEnv, outputTy); outputTy = ArchetypeBuilder::mapTypeOutOfContext(genericEnv, outputTy);
return GenericFunctionType::get(genericSig, inputTy, outputTy, extInfo); return GenericFunctionType::get(genericSig, inputTy, outputTy, extInfo);
} }
@@ -2186,8 +2183,7 @@ Type TypeResolver::resolveSILBoxType(SILBoxTypeRepr *repr,
genericSig = repr->getGenericSignature()->getCanonicalSignature(); genericSig = repr->getGenericSignature()->getCanonicalSignature();
for (auto &field : fields) { for (auto &field : fields) {
auto transTy = genericEnv->mapTypeOutOfContext(DC->getParentModule(), auto transTy = genericEnv->mapTypeOutOfContext(field.getLoweredType());
field.getLoweredType());
field = {transTy->getCanonicalType(), field.isMutable()}; field = {transTy->getCanonicalType(), field.isMutable()};
} }
} }
@@ -2311,8 +2307,6 @@ Type TypeResolver::resolveSILFunctionType(FunctionTypeRepr *repr,
return ErrorType::get(Context); return ErrorType::get(Context);
} }
ModuleDecl *M = DC->getParentModule();
// FIXME: Remap the parsed context types to interface types. // FIXME: Remap the parsed context types to interface types.
CanGenericSignature genericSig; CanGenericSignature genericSig;
SmallVector<SILParameterInfo, 4> interfaceParams; SmallVector<SILParameterInfo, 4> interfaceParams;
@@ -2323,19 +2317,19 @@ Type TypeResolver::resolveSILFunctionType(FunctionTypeRepr *repr,
for (auto &param : params) { for (auto &param : params) {
auto transParamType = ArchetypeBuilder::mapTypeOutOfContext( auto transParamType = ArchetypeBuilder::mapTypeOutOfContext(
M, genericEnv, param.getType())->getCanonicalType(); genericEnv, param.getType())->getCanonicalType();
interfaceParams.push_back(param.getWithType(transParamType)); interfaceParams.push_back(param.getWithType(transParamType));
} }
for (auto &result : results) { for (auto &result : results) {
auto transResultType = auto transResultType =
ArchetypeBuilder::mapTypeOutOfContext( ArchetypeBuilder::mapTypeOutOfContext(
M, genericEnv, result.getType())->getCanonicalType(); genericEnv, result.getType())->getCanonicalType();
interfaceResults.push_back(result.getWithType(transResultType)); interfaceResults.push_back(result.getWithType(transResultType));
} }
if (errorResult) { if (errorResult) {
auto transErrorResultType = ArchetypeBuilder::mapTypeOutOfContext( auto transErrorResultType = ArchetypeBuilder::mapTypeOutOfContext(
M, genericEnv, errorResult->getType())->getCanonicalType(); genericEnv, errorResult->getType())->getCanonicalType();
interfaceErrorResult = interfaceErrorResult =
errorResult->getWithType(transErrorResultType); errorResult->getWithType(transErrorResultType);
} }

View File

@@ -863,8 +863,8 @@ void Serializer::writePattern(const Pattern *pattern, DeclContext *owningDC) {
// If we have an owning context and a contextual type, map out to an // If we have an owning context and a contextual type, map out to an
// interface type. // interface type.
if (owningDC && type->hasArchetype()) { if (owningDC && type->hasArchetype()) {
type = owningDC->getGenericEnvironmentOfContext()->mapTypeOutOfContext( type = owningDC->getGenericEnvironmentOfContext()
owningDC->getParentModule(), type); ->mapTypeOutOfContext(type);
} }
return type; return type;
@@ -1260,7 +1260,7 @@ Serializer::writeConformance(ProtocolConformanceRef conformanceRef,
unsigned abbrCode = abbrCodes[SpecializedProtocolConformanceLayout::Code]; unsigned abbrCode = abbrCodes[SpecializedProtocolConformanceLayout::Code];
auto type = conf->getType(); auto type = conf->getType();
if (genericEnv) if (genericEnv)
type = genericEnv->mapTypeOutOfContext(const_cast<ModuleDecl *>(M), type); type = genericEnv->mapTypeOutOfContext(type);
SpecializedProtocolConformanceLayout::emitRecord(Out, ScratchRecord, SpecializedProtocolConformanceLayout::emitRecord(Out, ScratchRecord,
abbrCode, abbrCode,
addTypeRef(type), addTypeRef(type),
@@ -1278,7 +1278,7 @@ Serializer::writeConformance(ProtocolConformanceRef conformanceRef,
auto type = conf->getType(); auto type = conf->getType();
if (genericEnv) if (genericEnv)
type = genericEnv->mapTypeOutOfContext(const_cast<ModuleDecl *>(M), type); type = genericEnv->mapTypeOutOfContext(type);
InheritedProtocolConformanceLayout::emitRecord( InheritedProtocolConformanceLayout::emitRecord(
Out, ScratchRecord, abbrCode, addTypeRef(type)); Out, ScratchRecord, abbrCode, addTypeRef(type));
@@ -1318,8 +1318,7 @@ Serializer::writeSubstitutions(ArrayRef<Substitution> substitutions,
auto replacementType = sub.getReplacement(); auto replacementType = sub.getReplacement();
if (genericEnv) { if (genericEnv) {
replacementType = replacementType =
genericEnv->mapTypeOutOfContext(const_cast<ModuleDecl *>(M), genericEnv->mapTypeOutOfContext(replacementType);
replacementType);
} }
BoundGenericSubstitutionLayout::emitRecord( BoundGenericSubstitutionLayout::emitRecord(
@@ -2359,9 +2358,7 @@ void Serializer::writeDecl(const Decl *D) {
underlying = typeAlias->getUnderlyingType(); underlying = typeAlias->getUnderlyingType();
if (underlying->hasArchetype()) { if (underlying->hasArchetype()) {
auto genericEnv = typeAlias->getGenericEnvironmentOfContext(); auto genericEnv = typeAlias->getGenericEnvironmentOfContext();
underlying = genericEnv->mapTypeOutOfContext( underlying = genericEnv->mapTypeOutOfContext(underlying);
typeAlias->getModuleContext(),
underlying);
} }
} }