//===--- Substitution.cpp - Type substitutions ----------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file implements the Substitution class and operations on it. // //===----------------------------------------------------------------------===// #include "swift/AST/Substitution.h" #include "swift/AST/ASTContext.h" #include "swift/AST/GenericEnvironment.h" #include "swift/AST/Module.h" #include "swift/AST/ProtocolConformance.h" #include "swift/AST/SubstitutionMap.h" #include "swift/AST/Types.h" #include "llvm/ADT/DenseMap.h" using namespace swift; bool Substitution::operator==(const Substitution &other) const { // The archetypes may be missing, but we can compare them directly // because archetypes are always canonical. return Replacement->isEqual(other.Replacement) && Conformance.equals(other.Conformance); } Substitution::Substitution(Type Replacement, ArrayRef Conformance) : Replacement(Replacement), Conformance(Conformance) { // The replacement type must be materializable. assert(Replacement->isMaterializable() && "cannot substitute with a non-materializable type"); } Substitution Substitution::subst(const SubstitutionMap &subMap) const { return subst(QuerySubstitutionMap{subMap}, LookUpConformanceInSubstitutionMap(subMap)); } Substitution Substitution::subst(TypeSubstitutionFn subs, LookupConformanceFn conformances) const { // Substitute the replacement. Type substReplacement = Replacement.subst(subs, conformances, SubstFlags::UseErrorType); assert(!substReplacement->hasError() && "substitution replacement failed"); if (substReplacement->isEqual(Replacement)) return *this; if (Conformance.empty()) { return {substReplacement, Conformance}; } bool conformancesChanged = false; SmallVector substConformances; substConformances.reserve(Conformance.size()); for (auto c : Conformance) { auto newC = c.subst(Replacement, subs, conformances); if (c != newC) conformancesChanged = true; substConformances.push_back(newC); } assert(substConformances.size() == Conformance.size()); ArrayRef substConfs; if (conformancesChanged) substConfs = Replacement->getASTContext().AllocateCopy(substConformances); else substConfs = Conformance; return Substitution{substReplacement, substConfs}; }