diff --git a/include/swift/AST/SubstitutionMap.h b/include/swift/AST/SubstitutionMap.h index 41a3ae3d9e6e4..b67266c50d112 100644 --- a/include/swift/AST/SubstitutionMap.h +++ b/include/swift/AST/SubstitutionMap.h @@ -306,7 +306,6 @@ class LookUpConformanceInSubstitutionMap { }; struct OverrideSubsInfo { - ASTContext &Ctx; unsigned BaseDepth; unsigned OrigDepth; SubstitutionMap BaseSubMap; diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index 249dbbad06879..c1cd0f082891d 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -7254,9 +7254,10 @@ class GenericTypeParamType : public SubstitutableType, Identifier Name; }; - unsigned Depth : 15; unsigned IsDecl : 1; - unsigned Index : 16; + unsigned Depth : 15; + unsigned Weight : 1; + unsigned Index : 15; /// The kind of generic type parameter this is. GenericTypeParamKind ParamKind; @@ -7281,15 +7282,21 @@ class GenericTypeParamType : public SubstitutableType, Type valueType, const ASTContext &ctx); /// Retrieve a canonical generic type parameter with the given kind, depth, - /// index, and optional value type. + /// index, weight, and optional value type. static GenericTypeParamType *get(GenericTypeParamKind paramKind, - unsigned depth, unsigned index, + unsigned depth, unsigned index, unsigned weight, Type valueType, const ASTContext &ctx); - /// Retrieve a canonical generic type parameter at the given depth and index. + /// Retrieve a canonical generic type parameter at the given depth and index, + /// with weight 0. static GenericTypeParamType *getType(unsigned depth, unsigned index, const ASTContext &ctx); + /// Retrieve a canonical generic type parameter at the given depth and index + /// for an opaque result type, so with weight 1. + static GenericTypeParamType *getOpaqueResultType(unsigned depth, unsigned index, + const ASTContext &ctx); + /// Retrieve a canonical generic parameter pack at the given depth and index. static GenericTypeParamType *getPack(unsigned depth, unsigned index, const ASTContext &ctx); @@ -7345,6 +7352,14 @@ class GenericTypeParamType : public SubstitutableType, return Index; } + /// The weight of this generic parameter in the type parameter order. + /// + /// Opaque result types have weight 1, while all other generic parameters + /// have weight 0. + unsigned getWeight() const { + return Weight; + } + /// Returns \c true if this type parameter is declared as a pack. /// /// \code @@ -7366,20 +7381,24 @@ class GenericTypeParamType : public SubstitutableType, Type getValueType() const; + GenericTypeParamType *withDepth(unsigned depth) const; + void Profile(llvm::FoldingSetNodeID &ID) { // Note: We explicitly don't use 'getName()' because for canonical forms // which don't store an identifier we'll go create a tau based form. We // really want to just plumb down the null Identifier because that's what's // inside the cache. - Profile(ID, getParamKind(), getDepth(), getIndex(), getValueType(), - Name); + Profile(ID, getParamKind(), getDepth(), getIndex(), getWeight(), + getValueType(), Name); } static void Profile(llvm::FoldingSetNodeID &ID, GenericTypeParamKind paramKind, unsigned depth, - unsigned index, Type valueType, Identifier name) { + unsigned index, unsigned weight, Type valueType, + Identifier name) { ID.AddInteger((uint8_t)paramKind); ID.AddInteger(depth); ID.AddInteger(index); + ID.AddInteger(weight); ID.AddPointer(valueType.getPointer()); ID.AddPointer(name.get()); } @@ -7402,7 +7421,7 @@ class GenericTypeParamType : public SubstitutableType, const ASTContext &ctx); explicit GenericTypeParamType(GenericTypeParamKind paramKind, unsigned depth, - unsigned index, Type valueType, + unsigned index, unsigned weight, Type valueType, RecursiveTypeProperties props, const ASTContext &ctx); }; @@ -7412,6 +7431,11 @@ static CanGenericTypeParamType getType(unsigned depth, unsigned index, return CanGenericTypeParamType( GenericTypeParamType::getType(depth, index, C)); } +static CanGenericTypeParamType getOpaqueResultType(unsigned depth, unsigned index, + const ASTContext &C) { + return CanGenericTypeParamType( + GenericTypeParamType::getOpaqueResultType(depth, index, C)); +} END_CAN_TYPE_WRAPPER(GenericTypeParamType, SubstitutableType) /// A type that refers to a member type of some type that is dependent on a diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index a9c3d88e332c8..74f15f4f6985c 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -5099,8 +5099,8 @@ GenericTypeParamType *GenericTypeParamType::get(Identifier name, Type valueType, const ASTContext &ctx) { llvm::FoldingSetNodeID id; - GenericTypeParamType::Profile(id, paramKind, depth, index, valueType, - name); + GenericTypeParamType::Profile(id, paramKind, depth, index, /*weight=*/0, + valueType, name); void *insertPos; if (auto gpTy = ctx.getImpl().GenericParamTypes.FindNodeOrInsertPos(id, insertPos)) @@ -5110,8 +5110,8 @@ GenericTypeParamType *GenericTypeParamType::get(Identifier name, if (paramKind == GenericTypeParamKind::Pack) props |= RecursiveTypeProperties::HasParameterPack; - auto canType = GenericTypeParamType::get(paramKind, depth, index, valueType, - ctx); + auto canType = GenericTypeParamType::get(paramKind, depth, index, /*weight=*/0, + valueType, ctx); auto result = new (ctx, AllocationArena::Permanent) GenericTypeParamType(name, canType, ctx); @@ -5130,10 +5130,10 @@ GenericTypeParamType *GenericTypeParamType::get(GenericTypeParamDecl *param) { GenericTypeParamType *GenericTypeParamType::get(GenericTypeParamKind paramKind, unsigned depth, unsigned index, - Type valueType, + unsigned weight, Type valueType, const ASTContext &ctx) { llvm::FoldingSetNodeID id; - GenericTypeParamType::Profile(id, paramKind, depth, index, valueType, + GenericTypeParamType::Profile(id, paramKind, depth, index, weight, valueType, Identifier()); void *insertPos; @@ -5145,7 +5145,7 @@ GenericTypeParamType *GenericTypeParamType::get(GenericTypeParamKind paramKind, props |= RecursiveTypeProperties::HasParameterPack; auto result = new (ctx, AllocationArena::Permanent) - GenericTypeParamType(paramKind, depth, index, valueType, props, ctx); + GenericTypeParamType(paramKind, depth, index, weight, valueType, props, ctx); ctx.getImpl().GenericParamTypes.InsertNode(result, insertPos); return result; } @@ -5154,14 +5154,21 @@ GenericTypeParamType *GenericTypeParamType::getType(unsigned depth, unsigned index, const ASTContext &ctx) { return GenericTypeParamType::get(GenericTypeParamKind::Type, depth, index, - /*valueType*/ Type(), ctx); + /*weight=*/0, /*valueType=*/Type(), ctx); +} + +GenericTypeParamType *GenericTypeParamType::getOpaqueResultType(unsigned depth, + unsigned index, + const ASTContext &ctx) { + return GenericTypeParamType::get(GenericTypeParamKind::Type, depth, index, + /*weight=*/1, /*valueType=*/Type(), ctx); } GenericTypeParamType *GenericTypeParamType::getPack(unsigned depth, unsigned index, const ASTContext &ctx) { return GenericTypeParamType::get(GenericTypeParamKind::Pack, depth, index, - /*valueType*/ Type(), ctx); + /*weight=*/0, /*valueType=*/Type(), ctx); } GenericTypeParamType *GenericTypeParamType::getValue(unsigned depth, @@ -5169,7 +5176,7 @@ GenericTypeParamType *GenericTypeParamType::getValue(unsigned depth, Type valueType, const ASTContext &ctx) { return GenericTypeParamType::get(GenericTypeParamKind::Value, depth, index, - valueType, ctx); + /*weight=*/0, valueType, ctx); } ArrayRef diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp index 3ac5bc6f80b37..d629055e23c94 100644 --- a/lib/AST/GenericSignature.cpp +++ b/lib/AST/GenericSignature.cpp @@ -831,8 +831,7 @@ int swift::compareAssociatedTypes(AssociatedTypeDecl *assocType1, return 0; } -/// Canonical ordering for type parameters. -int swift::compareDependentTypes(Type type1, Type type2) { +static int compareDependentTypesRec(Type type1, Type type2) { // Fast-path check for equality. if (type1->isEqual(type2)) return 0; @@ -853,7 +852,7 @@ int swift::compareDependentTypes(Type type1, Type type2) { // - by base, so t_0_n.`P.T` < t_1_m.`P.T` if (int compareBases = - compareDependentTypes(depMemTy1->getBase(), depMemTy2->getBase())) + compareDependentTypesRec(depMemTy1->getBase(), depMemTy2->getBase())) return compareBases; // - by name, so t_n_m.`P.T` < t_n_m.`P.U` @@ -869,6 +868,17 @@ int swift::compareDependentTypes(Type type1, Type type2) { return 0; } +/// Canonical ordering for type parameters. +int swift::compareDependentTypes(Type type1, Type type2) { + auto *root1 = type1->getRootGenericParam(); + auto *root2 = type2->getRootGenericParam(); + if (root1->getWeight() != root2->getWeight()) { + return root2->getWeight() ? -1 : +1; + } + + return compareDependentTypesRec(type1, type2); +} + #pragma mark Generic signature verification void GenericSignature::verify() const { diff --git a/lib/AST/RequirementEnvironment.cpp b/lib/AST/RequirementEnvironment.cpp index d60ea83df6f69..5c28f05e20128 100644 --- a/lib/AST/RequirementEnvironment.cpp +++ b/lib/AST/RequirementEnvironment.cpp @@ -46,10 +46,8 @@ RequirementEnvironment::RequirementEnvironment( auto conformanceToWitnessThunkGenericParamFn = [&](GenericTypeParamType *genericParam) -> GenericTypeParamType * { - return GenericTypeParamType::get(genericParam->getParamKind(), - genericParam->getDepth() + (covariantSelf ? 1 : 0), - genericParam->getIndex(), - genericParam->getValueType(), ctx); + return genericParam->withDepth( + genericParam->getDepth() + (covariantSelf ? 1 : 0)); }; // This is a substitution function from the generic parameters of the @@ -109,9 +107,7 @@ RequirementEnvironment::RequirementEnvironment( // invalid code. if (genericParam->getDepth() != 1) return Type(); - Type substGenericParam = GenericTypeParamType::get( - genericParam->getParamKind(), depth, genericParam->getIndex(), - genericParam->getValueType(), ctx); + Type substGenericParam = genericParam->withDepth(depth); if (genericParam->isParameterPack()) { substGenericParam = PackType::getSingletonPackExpansion( substGenericParam); @@ -210,10 +206,7 @@ RequirementEnvironment::RequirementEnvironment( } // Create an equivalent generic parameter at the next depth. - auto substGenericParam = GenericTypeParamType::get( - genericParam->getParamKind(), depth, genericParam->getIndex(), - genericParam->getValueType(), ctx); - + auto substGenericParam = genericParam->withDepth(depth); genericParamTypes.push_back(substGenericParam); } diff --git a/lib/AST/RequirementMachine/Term.cpp b/lib/AST/RequirementMachine/Term.cpp index 90e5b885cb6d3..5455fb348fa56 100644 --- a/lib/AST/RequirementMachine/Term.cpp +++ b/lib/AST/RequirementMachine/Term.cpp @@ -122,19 +122,42 @@ bool Term::containsNameSymbols() const { return false; } -/// Shortlex order on symbol ranges. +/// Weighted shortlex order on symbol ranges, used for implementing +/// Term::compare() and MutableTerm::compare(). /// -/// First we compare length, then perform a lexicographic comparison -/// on symbols if the two ranges have the same length. +/// We first compute a weight vector for both terms and compare the +/// vectors lexicographically: +/// - Weight of generic param symbols +/// - Number of name symbols +/// - Number of element symbols /// -/// This is used to implement Term::compare() and MutableTerm::compare() -/// below. -static std::optional shortlexCompare(const Symbol *lhsBegin, - const Symbol *lhsEnd, - const Symbol *rhsBegin, - const Symbol *rhsEnd, - RewriteContext &ctx) { - // First, compare the number of name and pack element symbols. +/// If the terms have the same weight, we compare length. +/// +/// If the terms have the same weight and length, we perform a +/// lexicographic comparison on symbols. +/// +static std::optional compareImpl(const Symbol *lhsBegin, + const Symbol *lhsEnd, + const Symbol *rhsBegin, + const Symbol *rhsEnd, + RewriteContext &ctx) { + ASSERT(lhsBegin != lhsEnd); + ASSERT(rhsBegin != rhsEnd); + + // First compare weights on generic parameters. The implicit + // assumption here is we don't form terms with generic parameter + // symbols in the middle, which is true. Otherwise, we'd need + // to add up their weights like we do below for name symbols, + // of course. + if (lhsBegin->getKind() == Symbol::Kind::GenericParam && + rhsBegin->getKind() == Symbol::Kind::GenericParam) { + unsigned lhsWeight = lhsBegin->getGenericParam()->getWeight(); + unsigned rhsWeight = rhsBegin->getGenericParam()->getWeight(); + if (lhsWeight != rhsWeight) + return lhsWeight > rhsWeight ? 1 : -1; + } + + // Compare the number of name and pack element symbols. unsigned lhsNameCount = 0; unsigned lhsPackElementCount = 0; for (auto *iter = lhsBegin; iter != lhsEnd; ++iter) { @@ -192,17 +215,17 @@ static std::optional shortlexCompare(const Symbol *lhsBegin, return 0; } -/// Shortlex order on terms. Returns None if the terms are identical except +/// Reduction order on terms. Returns None if the terms are identical except /// for an incomparable superclass or concrete type symbol at the end. std::optional Term::compare(Term other, RewriteContext &ctx) const { - return shortlexCompare(begin(), end(), other.begin(), other.end(), ctx); + return compareImpl(begin(), end(), other.begin(), other.end(), ctx); } -/// Shortlex order on mutable terms. Returns None if the terms are identical +/// Reduction order on mutable terms. Returns None if the terms are identical /// except for an incomparable superclass or concrete type symbol at the end. std::optional MutableTerm::compare(const MutableTerm &other, RewriteContext &ctx) const { - return shortlexCompare(begin(), end(), other.begin(), other.end(), ctx); + return compareImpl(begin(), end(), other.begin(), other.end(), ctx); } /// Replace the subterm in the range [from,to) of this term with \p rhs. diff --git a/lib/AST/SubstitutionMap.cpp b/lib/AST/SubstitutionMap.cpp index 2e35984f245ce..788cc66710a7e 100644 --- a/lib/AST/SubstitutionMap.cpp +++ b/lib/AST/SubstitutionMap.cpp @@ -427,8 +427,7 @@ OverrideSubsInfo::OverrideSubsInfo(const NominalTypeDecl *baseNominal, const NominalTypeDecl *derivedNominal, GenericSignature baseSig, const GenericParamList *derivedParams) - : Ctx(baseSig->getASTContext()), - BaseDepth(0), + : BaseDepth(0), OrigDepth(0), DerivedParams(derivedParams) { @@ -468,10 +467,7 @@ Type QueryOverrideSubs::operator()(SubstitutableType *type) const { ->getDeclaredInterfaceType(); } - return GenericTypeParamType::get( - gp->getParamKind(), - gp->getDepth() + info.OrigDepth - info.BaseDepth, - gp->getIndex(), gp->getValueType(), info.Ctx); + return gp->withDepth(gp->getDepth() + info.OrigDepth - info.BaseDepth); } } diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 1af4bc152f343..a2b09b3905114 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1736,7 +1736,8 @@ CanType TypeBase::computeCanonicalType() { auto &C = gpDecl->getASTContext(); Result = GenericTypeParamType::get(gp->getParamKind(), gp->getDepth(), - gp->getIndex(), gp->getValueType(), + gp->getIndex(), gp->getWeight(), + gp->getValueType(), C); break; } @@ -2081,8 +2082,9 @@ GenericTypeParamType::GenericTypeParamType(GenericTypeParamDecl *param, : SubstitutableType(TypeKind::GenericTypeParam, nullptr, props), Decl(param) { ASSERT(param->getDepth() != GenericTypeParamDecl::InvalidDepth); - Depth = param->getDepth(); IsDecl = true; + Depth = param->getDepth(); + Weight = 0; Index = param->getIndex(); ParamKind = param->getParamKind(); ValueType = param->getValueType(); @@ -2095,8 +2097,9 @@ GenericTypeParamType::GenericTypeParamType(Identifier name, canType->getRecursiveProperties()), Decl(nullptr) { Name = name; - Depth = canType->getDepth(); IsDecl = false; + Depth = canType->getDepth(); + Weight = canType->getWeight(); Index = canType->getIndex(); ParamKind = canType->getParamKind(); ValueType = canType->getValueType(); @@ -2106,13 +2109,14 @@ GenericTypeParamType::GenericTypeParamType(Identifier name, GenericTypeParamType::GenericTypeParamType(GenericTypeParamKind paramKind, unsigned depth, unsigned index, - Type valueType, + unsigned weight, Type valueType, RecursiveTypeProperties props, const ASTContext &ctx) : SubstitutableType(TypeKind::GenericTypeParam, &ctx, props), Decl(nullptr) { - Depth = depth; IsDecl = false; + Depth = depth; + Weight = weight; Index = index; ParamKind = paramKind; ValueType = valueType; @@ -2163,6 +2167,15 @@ Type GenericTypeParamType::getValueType() const { return ValueType; } +GenericTypeParamType *GenericTypeParamType::withDepth(unsigned depth) const { + return GenericTypeParamType::get(getParamKind(), + depth, + getIndex(), + getWeight(), + getValueType(), + getASTContext()); +} + const llvm::fltSemantics &BuiltinFloatType::getAPFloatSemantics() const { switch (getFPKind()) { case BuiltinFloatType::IEEE16: return APFloat::IEEEhalf(); diff --git a/lib/SIL/IR/AbstractionPattern.cpp b/lib/SIL/IR/AbstractionPattern.cpp index b27ccc849abe7..59fe0da628ed0 100644 --- a/lib/SIL/IR/AbstractionPattern.cpp +++ b/lib/SIL/IR/AbstractionPattern.cpp @@ -2423,7 +2423,8 @@ class SubstFunctionTypePatternVisitor paramKind = GenericTypeParamKind::Pack; } - auto gp = GenericTypeParamType::get(paramKind, 0, paramIndex, Type(), + auto gp = GenericTypeParamType::get(paramKind, /*depth=*/0, paramIndex, + /*weight=*/0, /*valueType=*/Type(), TC.Context); substGenericParams.push_back(gp); diff --git a/lib/SILOptimizer/Utils/Devirtualize.cpp b/lib/SILOptimizer/Utils/Devirtualize.cpp index c4aec4cb77e48..f6f67f7fb644b 100644 --- a/lib/SILOptimizer/Utils/Devirtualize.cpp +++ b/lib/SILOptimizer/Utils/Devirtualize.cpp @@ -405,8 +405,6 @@ combineSubstitutionMaps(SubstitutionMap firstSubMap, unsigned firstDepth, unsigned secondDepth, GenericSignature genericSig) { - auto &ctx = genericSig->getASTContext(); - return SubstitutionMap::get( genericSig, [&](SubstitutableType *type) { @@ -414,12 +412,8 @@ combineSubstitutionMaps(SubstitutionMap firstSubMap, if (gp->getDepth() < firstDepth) return QuerySubstitutionMap{firstSubMap}(gp); - auto *replacement = GenericTypeParamType::get( - gp->getParamKind(), - gp->getDepth() + secondDepth - firstDepth, - gp->getIndex(), - gp->getValueType(), - ctx); + auto *replacement = gp->withDepth( + gp->getDepth() + secondDepth - firstDepth); return QuerySubstitutionMap{secondSubMap}(replacement); }, // We might not have enough information in the substitution maps alone. @@ -1056,16 +1050,13 @@ getWitnessMethodSubstitutions( } if (depth < baseDepth) { - paramType = GenericTypeParamType::get(paramType->getParamKind(), - depth, paramType->getIndex(), paramType->getValueType(), ctx); - + paramType = paramType->withDepth(depth); return Type(paramType).subst(baseSubMap); } depth = depth - baseDepth + 1; - paramType = GenericTypeParamType::get(paramType->getParamKind(), - depth, paramType->getIndex(), paramType->getValueType(), ctx); + paramType = paramType->withDepth(depth); return Type(paramType).subst(origSubMap); }, [&](CanType type, Type substType, ProtocolDecl *proto) { @@ -1084,10 +1075,8 @@ getWitnessMethodSubstitutions( if (depth < baseDepth) { type = CanType(type.transformRec([&](TypeBase *t) -> std::optional { - if (t == paramType) { - return Type(GenericTypeParamType::get(paramType->getParamKind(), - depth, paramType->getIndex(), paramType->getValueType(), ctx)); - } + if (t == paramType) + return paramType->withDepth(depth); assert(!isa(t)); return std::nullopt; @@ -1099,10 +1088,8 @@ getWitnessMethodSubstitutions( depth = depth - baseDepth + 1; type = CanType(type.transformRec([&](TypeBase *t) -> std::optional { - if (t == paramType) { - return Type(GenericTypeParamType::get(paramType->getParamKind(), - depth, paramType->getIndex(), paramType->getValueType(), ctx)); - } + if (t == paramType) + return paramType->withDepth(depth); assert(!isa(t)); return std::nullopt; diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp index 779e6bdf4e6c8..bc05134590a67 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -142,7 +142,7 @@ OpaqueResultTypeRequest::evaluate(Evaluator &evaluator, for (unsigned i = 0; i < opaqueReprs.size(); ++i) { auto *currentRepr = opaqueReprs[i]; - if( auto opaqueReturn = dyn_cast(currentRepr) ) { + if (auto opaqueReturn = dyn_cast(currentRepr)) { // Usually, we resolve the opaque constraint and bail if it isn't a class // or existential type (see below). However, in this case we know we will // fail, so we can bail early and provide a better diagnostic. @@ -163,13 +163,13 @@ OpaqueResultTypeRequest::evaluate(Evaluator &evaluator, } } - auto *paramType = GenericTypeParamType::getType(opaqueSignatureDepth, i, - ctx); + auto *paramType = GenericTypeParamType::getOpaqueResultType( + opaqueSignatureDepth, i, ctx); genericParamTypes.push_back(paramType); TypeRepr *constraint = currentRepr; - if (auto opaqueReturn = dyn_cast(currentRepr)){ + if (auto opaqueReturn = dyn_cast(currentRepr)) { constraint = opaqueReturn->getConstraint(); } // Try to resolve the constraint repr in the parent decl context. It diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index bc0e9d5bd7d25..8619559ea1bda 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -1034,11 +1034,7 @@ findMissingGenericRequirementForSolutionFix( return conformance->getType(); ASSERT(gp->getDepth() > 0); - gp = GenericTypeParamType::get(gp->getParamKind(), - gp->getDepth() - 1, - gp->getIndex(), - gp->getValueType(), - ctx); + gp = gp->withDepth(gp->getDepth() - 1); } if (!sig) diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index 65fb03a81e38e..12668a90ebd01 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -7621,12 +7621,13 @@ DESERIALIZE_TYPE(GENERIC_TYPE_PARAM_TYPE)( unsigned rawParamKind; bool hasDecl; unsigned depth; + unsigned weight; unsigned index; DeclID declOrIdentifier; TypeID valueTypeID; decls_block::GenericTypeParamTypeLayout::readRecord( - scratch, rawParamKind, hasDecl, depth, index, declOrIdentifier, + scratch, rawParamKind, hasDecl, depth, weight, index, declOrIdentifier, valueTypeID); auto paramKind = getActualParamKind(rawParamKind); @@ -7655,10 +7656,11 @@ DESERIALIZE_TYPE(GENERIC_TYPE_PARAM_TYPE)( return valueType.takeError(); if (declOrIdentifier == 0) { - return GenericTypeParamType::get(*paramKind, depth, index, *valueType, + return GenericTypeParamType::get(*paramKind, depth, index, weight, *valueType, MF.getContext()); } + ASSERT(weight == 0); auto name = MF.getDeclBaseName(declOrIdentifier).getIdentifier(); return GenericTypeParamType::get(name, *paramKind, depth, index, *valueType, MF.getContext()); diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index 8af75eaf3342a..55b5c0b5ade65 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t SWIFTMODULE_VERSION_MINOR = 944; // specialized witness tables +const uint16_t SWIFTMODULE_VERSION_MINOR = 945; // generic parameter weight /// A standard hash seed used for all string hashes in a serialized module. /// @@ -1290,7 +1290,8 @@ namespace decls_block { GenericParamKindField, // param kind BCFixed<1>, // has decl? BCFixed<15>, // depth - BCFixed<16>, // index + BCFixed<1>, // weight + BCFixed<15>, // index DeclIDField, // generic type parameter decl or identifier TypeIDField // value type (if param kind == Value) ); diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index afacf625fe6b7..196e6dc6da9b9 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -5812,6 +5812,7 @@ class Serializer::TypeSerializer : public TypeVisitor { paramKind, hasDecl, genericParam->getDepth(), + genericParam->getWeight(), genericParam->getIndex(), declOrIdentifier, valueTypeID); diff --git a/test/SILGen/opaque_result_type_reduction_order.swift b/test/SILGen/opaque_result_type_reduction_order.swift new file mode 100644 index 0000000000000..0714d75c05880 --- /dev/null +++ b/test/SILGen/opaque_result_type_reduction_order.swift @@ -0,0 +1,27 @@ +// RUN: %target-swift-emit-silgen %s + +protocol N { + associatedtype A: N +} + +struct G: N { + typealias A = G> +} + +protocol P { + associatedtype A +} + +struct GG: P { + typealias A = T +} + +func f(_: T) -> some P { + return GG() +} + +func g(_: T) -> T.A { fatalError() } + +func h(_: G>>) {} + +h(g(f(G())))