mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
AST: Simplify SubstitutionMap representation
There was a bunch of logic to lazily populate replacement types corresponding to reducible generic parameters. This didn't seem to have a clear purpose so let's remove it.
This commit is contained in:
@@ -73,22 +73,6 @@ private:
|
|||||||
/// signature nor any replacement types/conformances.
|
/// signature nor any replacement types/conformances.
|
||||||
Storage *storage = nullptr;
|
Storage *storage = nullptr;
|
||||||
|
|
||||||
public:
|
|
||||||
/// Retrieve the array of replacement types, which line up with the
|
|
||||||
/// generic parameters.
|
|
||||||
///
|
|
||||||
/// Note that the types may be null, for cases where the generic parameter
|
|
||||||
/// is concrete but hasn't been queried yet.
|
|
||||||
///
|
|
||||||
/// Prefer \c getReplacementTypes, this is public for printing purposes.
|
|
||||||
ArrayRef<Type> getReplacementTypesBuffer() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
MutableArrayRef<Type> getReplacementTypesBuffer();
|
|
||||||
|
|
||||||
/// Retrieve a mutable reference to the buffer of conformances.
|
|
||||||
MutableArrayRef<ProtocolConformanceRef> getConformancesBuffer();
|
|
||||||
|
|
||||||
/// Form a substitution map for the given generic signature with the
|
/// Form a substitution map for the given generic signature with the
|
||||||
/// specified replacement types and conformances.
|
/// specified replacement types and conformances.
|
||||||
SubstitutionMap(GenericSignature genericSig,
|
SubstitutionMap(GenericSignature genericSig,
|
||||||
|
|||||||
@@ -5296,21 +5296,11 @@ void SubstitutionMap::Storage::Profile(
|
|||||||
id.AddPointer(genericSig.getPointer());
|
id.AddPointer(genericSig.getPointer());
|
||||||
if (!genericSig) return;
|
if (!genericSig) return;
|
||||||
|
|
||||||
// Profile those replacement types that corresponding to canonical generic
|
// Replacement types.
|
||||||
// parameters within the generic signature.
|
for (auto replacementType : replacementTypes)
|
||||||
id.AddInteger(replacementTypes.size());
|
id.AddPointer(replacementType.getPointer());
|
||||||
|
|
||||||
unsigned i = 0;
|
|
||||||
genericSig->forEachParam([&](GenericTypeParamType *gp, bool canonical) {
|
|
||||||
if (canonical)
|
|
||||||
id.AddPointer(replacementTypes[i].getPointer());
|
|
||||||
else
|
|
||||||
id.AddPointer(nullptr);
|
|
||||||
++i;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Conformances.
|
// Conformances.
|
||||||
id.AddInteger(conformances.size());
|
|
||||||
for (auto conformance : conformances)
|
for (auto conformance : conformances)
|
||||||
id.AddPointer(conformance.getOpaqueValue());
|
id.AddPointer(conformance.getOpaqueValue());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3816,16 +3816,13 @@ public:
|
|||||||
|
|
||||||
auto genericParams = genericSig.getGenericParams();
|
auto genericParams = genericSig.getGenericParams();
|
||||||
auto replacementTypes =
|
auto replacementTypes =
|
||||||
static_cast<const SubstitutionMap &>(map).getReplacementTypesBuffer();
|
static_cast<const SubstitutionMap &>(map).getReplacementTypes();
|
||||||
for (unsigned i : indices(genericParams)) {
|
for (unsigned i : indices(genericParams)) {
|
||||||
if (style == SubstitutionMap::DumpStyle::Minimal) {
|
if (style == SubstitutionMap::DumpStyle::Minimal) {
|
||||||
printFieldRaw([&](raw_ostream &out) {
|
printFieldRaw([&](raw_ostream &out) {
|
||||||
genericParams[i]->print(out);
|
genericParams[i]->print(out);
|
||||||
out << " -> ";
|
out << " -> ";
|
||||||
if (replacementTypes[i])
|
out << replacementTypes[i];
|
||||||
out << replacementTypes[i];
|
|
||||||
else
|
|
||||||
out << "<unresolved concrete type>";
|
|
||||||
}, "");
|
}, "");
|
||||||
} else {
|
} else {
|
||||||
printRecArbitrary([&](StringRef label) {
|
printRecArbitrary([&](StringRef label) {
|
||||||
@@ -3834,8 +3831,7 @@ public:
|
|||||||
genericParams[i]->print(out);
|
genericParams[i]->print(out);
|
||||||
out << " -> ";
|
out << " -> ";
|
||||||
}, "");
|
}, "");
|
||||||
if (replacementTypes[i])
|
printRec(replacementTypes[i]);
|
||||||
printRec(replacementTypes[i]);
|
|
||||||
printFoot();
|
printFoot();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ SubstitutionMap::Storage::Storage(
|
|||||||
getReplacementTypes().data());
|
getReplacementTypes().data());
|
||||||
std::copy(conformances.begin(), conformances.end(),
|
std::copy(conformances.begin(), conformances.end(),
|
||||||
getConformances().data());
|
getConformances().data());
|
||||||
populatedAllReplacements = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SubstitutionMap::SubstitutionMap(
|
SubstitutionMap::SubstitutionMap(
|
||||||
@@ -69,20 +68,6 @@ SubstitutionMap::SubstitutionMap(
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayRef<Type> SubstitutionMap::getReplacementTypesBuffer() const {
|
|
||||||
return storage ? storage->getReplacementTypes() : ArrayRef<Type>();
|
|
||||||
}
|
|
||||||
|
|
||||||
MutableArrayRef<Type> SubstitutionMap::getReplacementTypesBuffer() {
|
|
||||||
return storage ? storage->getReplacementTypes() : MutableArrayRef<Type>();
|
|
||||||
}
|
|
||||||
|
|
||||||
MutableArrayRef<ProtocolConformanceRef>
|
|
||||||
SubstitutionMap::getConformancesBuffer() {
|
|
||||||
return storage ? storage->getConformances()
|
|
||||||
: MutableArrayRef<ProtocolConformanceRef>();
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayRef<ProtocolConformanceRef> SubstitutionMap::getConformances() const {
|
ArrayRef<ProtocolConformanceRef> SubstitutionMap::getConformances() const {
|
||||||
return storage ? storage->getConformances()
|
return storage ? storage->getConformances()
|
||||||
: ArrayRef<ProtocolConformanceRef>();
|
: ArrayRef<ProtocolConformanceRef>();
|
||||||
@@ -91,16 +76,7 @@ ArrayRef<ProtocolConformanceRef> SubstitutionMap::getConformances() const {
|
|||||||
ArrayRef<Type> SubstitutionMap::getReplacementTypes() const {
|
ArrayRef<Type> SubstitutionMap::getReplacementTypes() const {
|
||||||
if (empty()) return { };
|
if (empty()) return { };
|
||||||
|
|
||||||
// Make sure we've filled in all of the replacement types.
|
return storage->getReplacementTypes();
|
||||||
if (!storage->populatedAllReplacements) {
|
|
||||||
for (auto gp : getGenericSignature().getGenericParams()) {
|
|
||||||
(void)lookupSubstitution(cast<SubstitutableType>(gp->getCanonicalType()));
|
|
||||||
}
|
|
||||||
|
|
||||||
storage->populatedAllReplacements = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return getReplacementTypesBuffer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayRef<Type> SubstitutionMap::getInnermostReplacementTypes() const {
|
ArrayRef<Type> SubstitutionMap::getInnermostReplacementTypes() const {
|
||||||
@@ -126,32 +102,32 @@ bool SubstitutionMap::hasAnySubstitutableParams() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool SubstitutionMap::hasArchetypes() const {
|
bool SubstitutionMap::hasArchetypes() const {
|
||||||
for (Type replacementTy : getReplacementTypesBuffer()) {
|
for (Type replacementTy : getReplacementTypes()) {
|
||||||
if (replacementTy && replacementTy->hasArchetype())
|
if (replacementTy->hasArchetype())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SubstitutionMap::hasLocalArchetypes() const {
|
bool SubstitutionMap::hasLocalArchetypes() const {
|
||||||
for (Type replacementTy : getReplacementTypesBuffer()) {
|
for (Type replacementTy : getReplacementTypes()) {
|
||||||
if (replacementTy && replacementTy->hasLocalArchetype())
|
if (replacementTy->hasLocalArchetype())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SubstitutionMap::hasOpaqueArchetypes() const {
|
bool SubstitutionMap::hasOpaqueArchetypes() const {
|
||||||
for (Type replacementTy : getReplacementTypesBuffer()) {
|
for (Type replacementTy : getReplacementTypes()) {
|
||||||
if (replacementTy && replacementTy->hasOpaqueArchetype())
|
if (replacementTy->hasOpaqueArchetype())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SubstitutionMap::hasDynamicSelf() const {
|
bool SubstitutionMap::hasDynamicSelf() const {
|
||||||
for (Type replacementTy : getReplacementTypesBuffer()) {
|
for (Type replacementTy : getReplacementTypes()) {
|
||||||
if (replacementTy && replacementTy->hasDynamicSelfType())
|
if (replacementTy->hasDynamicSelfType())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -162,8 +138,8 @@ bool SubstitutionMap::isCanonical() const {
|
|||||||
|
|
||||||
if (!getGenericSignature()->isCanonical()) return false;
|
if (!getGenericSignature()->isCanonical()) return false;
|
||||||
|
|
||||||
for (Type replacementTy : getReplacementTypesBuffer()) {
|
for (Type replacementTy : getReplacementTypes()) {
|
||||||
if (replacementTy && !replacementTy->isCanonical())
|
if (!replacementTy->isCanonical())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,11 +158,8 @@ SubstitutionMap SubstitutionMap::getCanonical(bool canonicalizeSignature) const
|
|||||||
if (canonicalizeSignature) sig = sig.getCanonicalSignature();
|
if (canonicalizeSignature) sig = sig.getCanonicalSignature();
|
||||||
|
|
||||||
SmallVector<Type, 4> replacementTypes;
|
SmallVector<Type, 4> replacementTypes;
|
||||||
for (Type replacementType : getReplacementTypesBuffer()) {
|
for (Type replacementType : getReplacementTypes()) {
|
||||||
if (replacementType)
|
replacementTypes.push_back(replacementType->getCanonicalType());
|
||||||
replacementTypes.push_back(replacementType->getCanonicalType());
|
|
||||||
else
|
|
||||||
replacementTypes.push_back(nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SmallVector<ProtocolConformanceRef, 4> conformances;
|
SmallVector<ProtocolConformanceRef, 4> conformances;
|
||||||
@@ -237,13 +210,7 @@ SubstitutionMap SubstitutionMap::get(GenericSignature genericSig,
|
|||||||
SmallVector<Type, 4> replacementTypes;
|
SmallVector<Type, 4> replacementTypes;
|
||||||
replacementTypes.reserve(genericSig.getGenericParams().size());
|
replacementTypes.reserve(genericSig.getGenericParams().size());
|
||||||
|
|
||||||
genericSig->forEachParam([&](GenericTypeParamType *gp, bool canonical) {
|
for (auto *gp : genericSig.getGenericParams()) {
|
||||||
// Don't eagerly form replacements for non-canonical generic parameters.
|
|
||||||
if (!canonical) {
|
|
||||||
replacementTypes.push_back(Type());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Record the replacement.
|
// Record the replacement.
|
||||||
Type replacement = Type(gp).subst(IFS);
|
Type replacement = Type(gp).subst(IFS);
|
||||||
|
|
||||||
@@ -252,7 +219,7 @@ SubstitutionMap SubstitutionMap::get(GenericSignature genericSig,
|
|||||||
"replacement for pack parameter must be a pack type");
|
"replacement for pack parameter must be a pack type");
|
||||||
|
|
||||||
replacementTypes.push_back(replacement);
|
replacementTypes.push_back(replacement);
|
||||||
});
|
}
|
||||||
|
|
||||||
// Form the stored conformances.
|
// Form the stored conformances.
|
||||||
SmallVector<ProtocolConformanceRef, 4> conformances;
|
SmallVector<ProtocolConformanceRef, 4> conformances;
|
||||||
@@ -292,11 +259,7 @@ Type SubstitutionMap::lookupSubstitution(CanSubstitutableType type) const {
|
|||||||
// Find the index of the replacement type based on the generic parameter we
|
// Find the index of the replacement type based on the generic parameter we
|
||||||
// have.
|
// have.
|
||||||
auto genericParam = cast<GenericTypeParamType>(type);
|
auto genericParam = cast<GenericTypeParamType>(type);
|
||||||
auto mutableThis = const_cast<SubstitutionMap *>(this);
|
auto genericParams = getGenericSignature().getGenericParams();
|
||||||
auto replacementTypes = mutableThis->getReplacementTypesBuffer();
|
|
||||||
auto genericSig = getGenericSignature();
|
|
||||||
assert(genericSig);
|
|
||||||
auto genericParams = genericSig.getGenericParams();
|
|
||||||
auto replacementIndex =
|
auto replacementIndex =
|
||||||
GenericParamKey(genericParam).findIndexIn(genericParams);
|
GenericParamKey(genericParam).findIndexIn(genericParams);
|
||||||
|
|
||||||
@@ -305,45 +268,7 @@ Type SubstitutionMap::lookupSubstitution(CanSubstitutableType type) const {
|
|||||||
if (replacementIndex == genericParams.size())
|
if (replacementIndex == genericParams.size())
|
||||||
return Type();
|
return Type();
|
||||||
|
|
||||||
// If we already have a replacement type, return it.
|
return getReplacementTypes()[replacementIndex];
|
||||||
Type &replacementType = replacementTypes[replacementIndex];
|
|
||||||
if (replacementType)
|
|
||||||
return replacementType;
|
|
||||||
|
|
||||||
// The generic parameter may have been made concrete by the generic signature,
|
|
||||||
// substitute into the concrete type.
|
|
||||||
if (auto concreteType = genericSig->getConcreteType(genericParam)) {
|
|
||||||
// Set the replacement type to an error, to block infinite recursion.
|
|
||||||
replacementType = ErrorType::get(concreteType);
|
|
||||||
|
|
||||||
// Substitute into the replacement type.
|
|
||||||
replacementType = concreteType.subst(*this);
|
|
||||||
|
|
||||||
// If the generic signature is canonical, canonicalize the replacement type.
|
|
||||||
if (getGenericSignature()->isCanonical())
|
|
||||||
replacementType = replacementType->getCanonicalType();
|
|
||||||
|
|
||||||
return replacementType;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The generic parameter may not be reduced. Retrieve the reduced
|
|
||||||
// type, which will be dependent.
|
|
||||||
CanType canonicalType = genericSig.getReducedType(genericParam);
|
|
||||||
|
|
||||||
// If nothing changed, we don't have a replacement.
|
|
||||||
if (canonicalType == type) return Type();
|
|
||||||
|
|
||||||
// If we're left with a substitutable type, substitute into that.
|
|
||||||
// First, set the replacement type to an error, to block infinite recursion.
|
|
||||||
replacementType = ErrorType::get(type);
|
|
||||||
|
|
||||||
replacementType = lookupSubstitution(cast<SubstitutableType>(canonicalType));
|
|
||||||
|
|
||||||
// If the generic signature is canonical, canonicalize the replacement type.
|
|
||||||
if (getGenericSignature()->isCanonical())
|
|
||||||
replacementType = replacementType->getCanonicalType();
|
|
||||||
|
|
||||||
return replacementType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ProtocolConformanceRef
|
ProtocolConformanceRef
|
||||||
@@ -500,12 +425,7 @@ SubstitutionMap SubstitutionMap::subst(InFlightSubstitution &IFS) const {
|
|||||||
if (empty()) return SubstitutionMap();
|
if (empty()) return SubstitutionMap();
|
||||||
|
|
||||||
SmallVector<Type, 4> newSubs;
|
SmallVector<Type, 4> newSubs;
|
||||||
for (Type type : getReplacementTypesBuffer()) {
|
for (Type type : getReplacementTypes()) {
|
||||||
if (!type) {
|
|
||||||
// Non-canonical parameter.
|
|
||||||
newSubs.push_back(Type());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
newSubs.push_back(type.subst(IFS));
|
newSubs.push_back(type.subst(IFS));
|
||||||
assert(type->is<PackType>() == newSubs.back()->is<PackType>() &&
|
assert(type->is<PackType>() == newSubs.back()->is<PackType>() &&
|
||||||
"substitution changed the pack-ness of a replacement type");
|
"substitution changed the pack-ness of a replacement type");
|
||||||
@@ -843,7 +763,7 @@ bool SubstitutionMap::isIdentity() const {
|
|||||||
|
|
||||||
GenericSignature sig = getGenericSignature();
|
GenericSignature sig = getGenericSignature();
|
||||||
bool hasNonIdentityReplacement = false;
|
bool hasNonIdentityReplacement = false;
|
||||||
auto replacements = getReplacementTypesBuffer();
|
auto replacements = getReplacementTypes();
|
||||||
|
|
||||||
sig->forEachParam([&](GenericTypeParamType *paramTy, bool isCanonical) {
|
sig->forEachParam([&](GenericTypeParamType *paramTy, bool isCanonical) {
|
||||||
if (isCanonical) {
|
if (isCanonical) {
|
||||||
|
|||||||
@@ -40,10 +40,7 @@ class SubstitutionMap::Storage final
|
|||||||
|
|
||||||
/// The number of conformance requirements, cached to avoid constantly
|
/// The number of conformance requirements, cached to avoid constantly
|
||||||
/// recomputing it on conformance-buffer access.
|
/// recomputing it on conformance-buffer access.
|
||||||
const unsigned numConformanceRequirements : 31;
|
const unsigned numConformanceRequirements;
|
||||||
|
|
||||||
/// Whether we've populated all replacement types already.
|
|
||||||
unsigned populatedAllReplacements : 1;
|
|
||||||
|
|
||||||
Storage() = delete;
|
Storage() = delete;
|
||||||
|
|
||||||
|
|||||||
@@ -46,4 +46,4 @@ extension P where Self == B<A> {
|
|||||||
func bar() {}
|
func bar() {}
|
||||||
// COMPLETE: Begin completions, 2 items
|
// COMPLETE: Begin completions, 2 items
|
||||||
// COMPLETE-DAG: Decl[StaticMethod]/Super/TypeRelation[Convertible]: foo()[#S#]; name=foo()
|
// COMPLETE-DAG: Decl[StaticMethod]/Super/TypeRelation[Convertible]: foo()[#S#]; name=foo()
|
||||||
// COMPLETE-DAG: Decl[StaticMethod]/Super/TypeRelation[Convertible]: qux()[#B<S>#]; name=qux()
|
// COMPLETE-DAG: Decl[StaticMethod]/Super/Flair[ExprSpecific]/TypeRelation[Convertible]: qux()[#any Q#]; name=qux()
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ func test3<MyGeneric: MyProto>() {
|
|||||||
#^GENERICEXPR^#
|
#^GENERICEXPR^#
|
||||||
// GENERICEXPR: Decl[GenericTypeParam]/Local: MyGeneric[#MyGeneric#]; name=MyGeneric
|
// GENERICEXPR: Decl[GenericTypeParam]/Local: MyGeneric[#MyGeneric#]; name=MyGeneric
|
||||||
// GENERICEXPR: Decl[Constructor]/Local: MyGeneric({#value: String#})[#MyProto#]; name=MyGeneric(value:)
|
// GENERICEXPR: Decl[Constructor]/Local: MyGeneric({#value: String#})[#MyProto#]; name=MyGeneric(value:)
|
||||||
// GENERICEXPR: Decl[Constructor]/Local: MyGeneric({#arg: String#})[#MyStruct#]; name=MyGeneric(arg:)
|
// GENERICEXPR: Decl[Constructor]/Local: MyGeneric({#arg: String#})[#MyProto#]; name=MyGeneric(arg:)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1145,6 +1145,16 @@ protocol Other1 {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
key.kind: source.lang.swift.decl.extension.struct,
|
key.kind: source.lang.swift.decl.extension.struct,
|
||||||
|
key.generic_params: [
|
||||||
|
{
|
||||||
|
key.name: "T"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
key.generic_requirements: [
|
||||||
|
{
|
||||||
|
key.description: "T == String"
|
||||||
|
}
|
||||||
|
],
|
||||||
key.offset: 396,
|
key.offset: 396,
|
||||||
key.length: 98,
|
key.length: 98,
|
||||||
key.fully_annotated_decl: "<syntaxtype.keyword>extension</syntaxtype.keyword> <ref.struct usr=\"s:16UnderscoredProto1AV\">A</ref.struct>",
|
key.fully_annotated_decl: "<syntaxtype.keyword>extension</syntaxtype.keyword> <ref.struct usr=\"s:16UnderscoredProto1AV\">A</ref.struct>",
|
||||||
|
|||||||
Reference in New Issue
Block a user