Skip to content

More SubstitutionList => SubstitutionMap cleanups #7969

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Mar 8, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions include/swift/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -683,19 +683,38 @@ class ASTContext {
takeDelayedConformanceDiags(NormalProtocolConformance *conformance);

/// \brief Produce a specialized conformance, which takes a generic
/// conformance and substitutes
/// conformance and substitutions written in terms of the generic
/// conformance's signature.
///
/// \param type The type for which we are retrieving the conformance.
///
/// \param generic The generic conformance.
///
/// \param substitutions The set of substitutions required to produce the
/// specialized conformance from the generic conformance.
/// specialized conformance from the generic conformance. This list is
/// copied so passing a temporary is permitted.
SpecializedProtocolConformance *
getSpecializedConformance(Type type,
ProtocolConformance *generic,
SubstitutionList substitutions);

/// \brief Produce a specialized conformance, which takes a generic
/// conformance and substitutions written in terms of the generic
/// conformance's signature.
///
/// \param type The type for which we are retrieving the conformance.
///
/// \param generic The generic conformance.
///
/// \param substitutions The set of substitutions required to produce the
/// specialized conformance from the generic conformance. The keys must
/// be generic parameters, not archetypes, so for example passing in
/// TypeBase::getContextSubstitutionMap() is OK.
SpecializedProtocolConformance *
getSpecializedConformance(Type type,
ProtocolConformance *generic,
const SubstitutionMap &substitutions);

/// \brief Produce an inherited conformance, for subclasses of a type
/// that already conforms to a protocol.
///
Expand Down
11 changes: 4 additions & 7 deletions include/swift/AST/ProtocolConformance.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,18 +279,15 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance {

/// Get the property declaration for a behavior conformance, if this is one.
AbstractStorageDecl *getBehaviorDecl() const;

void dump() const;
void dump(llvm::raw_ostream &out, unsigned indent = 0) const;

private:
friend class Substitution;
/// Substitute the conforming type and produce a ProtocolConformance that
/// applies to the substituted type.
ProtocolConformance *subst(ModuleDecl *module,
Type substType,
ProtocolConformance *subst(Type substType,
TypeSubstitutionFn subs,
LookupConformanceFn conformances) const;

void dump() const;
void dump(llvm::raw_ostream &out, unsigned indent = 0) const;
};

/// Normal protocol conformance, which involves mapping each of the protocol
Expand Down
5 changes: 5 additions & 0 deletions include/swift/AST/ProtocolConformanceRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ class ProtocolConformanceRef {
/// conformance represents.
ProtocolConformanceRef getInherited(ProtocolDecl *parent) const;

/// Apply a substitution to the conforming type.
ProtocolConformanceRef subst(Type origType,
TypeSubstitutionFn subs,
LookupConformanceFn conformances) const;

void dump() const;
void dump(llvm::raw_ostream &out, unsigned indent = 0) const;

Expand Down
11 changes: 0 additions & 11 deletions include/swift/AST/Substitution.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,6 @@ class Substitution {
const PrintOptions &PO = PrintOptions()) const;
void dump() const;
void dump(llvm::raw_ostream &os, unsigned indent = 0) const;

/// Apply a substitution to this substitution's replacement type and
/// conformances.
Substitution subst(ModuleDecl *module,
const SubstitutionMap &subMap) const;
Substitution subst(ModuleDecl *module,
TypeSubstitutionFn subs,
LookupConformanceFn conformances) const;

private:
friend class ProtocolConformance;
};

} // end namespace swift
Expand Down
16 changes: 13 additions & 3 deletions include/swift/AST/SubstitutionMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,19 +80,29 @@ class SubstitutionMap {
CanType type, ProtocolDecl *proto,
llvm::SmallPtrSetImpl<CanType> *visitedParents = nullptr) const;

/// Retrieve the conformances for the given type.
ArrayRef<ProtocolConformanceRef> getConformances(CanType type) const;

bool empty() const {
return subMap.empty();
}

/// Query whether any replacement types in the map contain archetypes.
bool hasArchetypes() const;

/// Query whether any replacement types in the map contain an opened
/// existential.
bool hasOpenedExistential() const;

/// Query whether any replacement type sin the map contain dynamic Self.
bool hasDynamicSelf() const;

/// Apply a substitution to all replacement types in the map. Does not
/// change keys.
SubstitutionMap subst(const SubstitutionMap &subMap) const;

/// Apply a substitution to all replacement types in the map. Does not
/// change keys.
SubstitutionMap subst(TypeSubstitutionFn subs,
LookupConformanceFn conformances) const;

/// Create a substitution map for a protocol conformance.
static SubstitutionMap
getProtocolSubstitutions(ProtocolDecl *protocol,
Expand Down
144 changes: 78 additions & 66 deletions include/swift/SIL/SILCloner.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#ifndef SWIFT_SIL_SILCLONER_H
#define SWIFT_SIL_SILCLONER_H

#include "swift/AST/ProtocolConformance.h"
#include "swift/SIL/SILOpenedArchetypesTracker.h"
#include "swift/SIL/SILBuilder.h"
#include "swift/SIL/SILDebugScope.h"
Expand Down Expand Up @@ -94,7 +95,7 @@ class SILCloner : protected SILVisitor<ImplClass> {
const SILDebugScope *remapScope(const SILDebugScope *DS) { return DS; }
SILType remapType(SILType Ty) { return Ty; }
CanType remapASTType(CanType Ty) { return Ty; }
ProtocolConformanceRef remapConformance(CanType Ty, ProtocolConformanceRef C){
ProtocolConformanceRef remapConformance(Type Ty, ProtocolConformanceRef C){
return C;
}
SILValue remapValue(SILValue Value);
Expand All @@ -108,37 +109,12 @@ class SILCloner : protected SILVisitor<ImplClass> {
const SILDebugScope *getOpScope(const SILDebugScope *DS) {
return asImpl().remapScope(DS);
}
Substitution getOpSubstitution(Substitution sub) {
return asImpl().remapSubstitution(sub);
}
Substitution remapSubstitution(Substitution sub) {
CanType newReplacement =
asImpl().getOpASTType(sub.getReplacement()->getCanonicalType());

return Substitution(newReplacement, sub.getConformances());
}
SubstitutionList getOpSubstitutions(SubstitutionList Subs) {
MutableArrayRef<Substitution> newSubsBuf;

auto copySubs = [&]{
if (!newSubsBuf.empty())
return;
newSubsBuf = getBuilder().getASTContext()
.template Allocate<Substitution>(Subs.size());
memcpy(newSubsBuf.data(), Subs.data(),
sizeof(Substitution) * Subs.size());
Subs = newSubsBuf;
};

for (unsigned i = 0, e = Subs.size(); i < e; ++i) {
Substitution newSub = asImpl().getOpSubstitution(Subs[i]);
if (newSub != Subs[i]) {
copySubs();
newSubsBuf[i] = newSub;
}
SmallVector<Substitution, 4> getOpSubstitutions(SubstitutionList Subs) {
SmallVector<Substitution, 4> NewSubs;
for (auto Sub : Subs) {
NewSubs.push_back(getOpSubstitution(Sub));
}

return Subs;
return NewSubs;
}

SILType getTypeInClonedContext(SILType Ty) {
Expand All @@ -152,15 +128,15 @@ class SILCloner : protected SILVisitor<ImplClass> {
return asImpl().remapType(Ty);
}

CanType getASTTypeInClonedContext(CanType ty) {
CanType getASTTypeInClonedContext(Type ty) {
// Do not substitute opened existential types, if we do not have any.
if (!ty->hasOpenedExistential())
return ty;
return ty->getCanonicalType();
// Do not substitute opened existential types, if it is not required.
// This is often the case when cloning basic blocks inside the same
// function.
if (OpenedExistentialSubs.empty())
return ty;
return ty->getCanonicalType();

return ty.transform(
[&](Type t) -> Type {
Expand All @@ -181,32 +157,46 @@ class SILCloner : protected SILVisitor<ImplClass> {
return t;
})->getCanonicalType();
}

CanType getOpASTType(CanType ty) {
ty = getASTTypeInClonedContext(ty);
return asImpl().remapASTType(ty);
}

/// Remap an entire set of conformances.
///
/// Returns the passed-in conformances array if none of the elements
/// changed.
ArrayRef<ProtocolConformanceRef> getOpConformances(CanType type,
ArrayRef<ProtocolConformanceRef> oldConformances) {
Substitution sub(type, oldConformances);
Substitution mappedSub = asImpl().remapSubstitution(sub);
ArrayRef<ProtocolConformanceRef> newConformances =
mappedSub.getConformances();

// Use the existing conformances array if possible.
if (oldConformances == newConformances)
return oldConformances;

return type->getASTContext().AllocateCopy(newConformances);
ProtocolConformanceRef getOpConformance(Type ty,
ProtocolConformanceRef conformance) {
auto newConformance =
conformance.subst(ty,
[&](SubstitutableType *t) -> Type {
if (t->isOpenedExistential()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use llvm's early return style here. if (!t-> isOpenedExistential()) return t; This will reduce the indentation.

auto found = OpenedExistentialSubs.find(
t->castTo<ArchetypeType>());
if (found != OpenedExistentialSubs.end())
return found->second;
return t;
}
return t;
},
MakeAbstractConformanceForGenericType());
return asImpl().remapConformance(getASTTypeInClonedContext(ty),
newConformance);
}

ProtocolConformanceRef getOpConformance(CanType ty,
ProtocolConformanceRef conformance) {
return asImpl().remapConformance(ty, conformance);
ArrayRef<ProtocolConformanceRef>
getOpConformances(Type ty,
ArrayRef<ProtocolConformanceRef> conformances) {
SmallVector<ProtocolConformanceRef, 4> newConformances;
for (auto conformance : conformances)
newConformances.push_back(getOpConformance(ty, conformance));
return ty->getASTContext().AllocateCopy(newConformances);
}

Substitution getOpSubstitution(Substitution sub) {
CanType newReplacement =
getOpASTType(sub.getReplacement()->getCanonicalType());
auto conformances = getOpConformances(sub.getReplacement(),
sub.getConformances());
return Substitution(newReplacement, conformances);
}

SILValue getOpValue(SILValue Value) {
Expand Down Expand Up @@ -538,9 +528,10 @@ SILCloner<ImplClass>::visitAllocExistentialBoxInst(
AllocExistentialBoxInst *Inst) {
auto origExistentialType = Inst->getExistentialType();
auto origFormalType = Inst->getFormalConcreteType();

auto conformances =getOpConformances(origFormalType, Inst->getConformances());


auto conformances = getOpConformances(origFormalType,
Inst->getConformances());

getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
doPostProcess(Inst,
getBuilder().createAllocExistentialBox(getOpLocation(Inst->getLoc()),
Expand Down Expand Up @@ -1447,7 +1438,7 @@ SILCloner<ImplClass>::visitClassMethodInst(ClassMethodInst *Inst) {
getBuilder().createClassMethod(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
Inst->getMember(),
getOpType(Inst->getType()),
Inst->getType(),
Inst->isVolatile()));
}

Expand All @@ -1459,25 +1450,37 @@ SILCloner<ImplClass>::visitSuperMethodInst(SuperMethodInst *Inst) {
getBuilder().createSuperMethod(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
Inst->getMember(),
getOpType(Inst->getType()),
Inst->getType(),
Inst->isVolatile()));
}

template<typename ImplClass>
void
SILCloner<ImplClass>::visitWitnessMethodInst(WitnessMethodInst *Inst) {
auto conformance =
getOpConformance(Inst->getLookupType(), Inst->getConformance());
auto lookupType = Inst->getLookupType();
auto conformance = getOpConformance(lookupType, Inst->getConformance());
auto newLookupType = getOpASTType(lookupType);

if (conformance.isConcrete()) {
CanType Ty = conformance.getConcrete()->getType()->getCanonicalType();

if (Ty != newLookupType) {
assert(Ty->isExactSuperclassOf(newLookupType, nullptr) &&
"Should only create upcasts for sub class.");

// We use the super class as the new look up type.
newLookupType = Ty;
}
}

getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
doPostProcess(
Inst,
getBuilder()
.createWitnessMethod(
getOpLocation(Inst->getLoc()),
newLookupType, conformance,
Inst->getMember(), getOpType(Inst->getType()),
Inst->getMember(), Inst->getType(),
Inst->isVolatile()));
}

Expand Down Expand Up @@ -1601,7 +1604,10 @@ template<typename ImplClass>
void
SILCloner<ImplClass>::visitInitExistentialAddrInst(InitExistentialAddrInst *Inst) {
CanType origFormalType = Inst->getFormalConcreteType();
auto conformances =getOpConformances(origFormalType, Inst->getConformances());

auto conformances = getOpConformances(origFormalType,
Inst->getConformances());

getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
doPostProcess(Inst,
getBuilder().createInitExistentialAddr(getOpLocation(Inst->getLoc()),
Expand All @@ -1615,8 +1621,10 @@ template <typename ImplClass>
void SILCloner<ImplClass>::visitInitExistentialOpaqueInst(
InitExistentialOpaqueInst *Inst) {
CanType origFormalType = Inst->getFormalConcreteType();
auto conformances =
getOpConformances(origFormalType, Inst->getConformances());

auto conformances = getOpConformances(origFormalType,
Inst->getConformances());

getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
doPostProcess(Inst,
getBuilder().createInitExistentialOpaque(
Expand All @@ -1629,8 +1637,10 @@ template<typename ImplClass>
void
SILCloner<ImplClass>::
visitInitExistentialMetatypeInst(InitExistentialMetatypeInst *Inst) {
auto conformances = getOpConformances(Inst->getFormalErasedObjectType(),
auto origFormalType = Inst->getFormalErasedObjectType();
auto conformances = getOpConformances(origFormalType,
Inst->getConformances());

getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
doPostProcess(Inst,
getBuilder().createInitExistentialMetatype(getOpLocation(Inst->getLoc()),
Expand All @@ -1644,7 +1654,9 @@ void
SILCloner<ImplClass>::
visitInitExistentialRefInst(InitExistentialRefInst *Inst) {
CanType origFormalType = Inst->getFormalConcreteType();
auto conformances =getOpConformances(origFormalType, Inst->getConformances());
auto conformances = getOpConformances(origFormalType,
Inst->getConformances());

getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
doPostProcess(Inst,
getBuilder().createInitExistentialRef(getOpLocation(Inst->getLoc()),
Expand Down
Loading