From d8ce7c32e2ebf197f54e35f0ea196e4c2203e01a Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 15 Sep 2025 15:10:59 -0400 Subject: [PATCH 01/18] Sema: Tweak VarDecl concurrency adjustment in getTypeOfReference() to look like FuncDecl case --- lib/Sema/TypeOfReference.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/Sema/TypeOfReference.cpp b/lib/Sema/TypeOfReference.cpp index 78236a8c0ae3d..38271ca1cc3d9 100644 --- a/lib/Sema/TypeOfReference.cpp +++ b/lib/Sema/TypeOfReference.cpp @@ -1257,11 +1257,9 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value, getUnopenedTypeOfReference(varDecl, Type(), useDC, getConstraintLocator(locator), wantInterfaceType); - // FIXME: Adjust the type for concurrency if requested. - valueType = adjustVarTypeForConcurrency( - valueType, varDecl, useDC, - GetClosureType{*this}, - ClosureIsolatedByPreconcurrency{*this}); + + ASSERT(!valueType->hasUnboundGenericType() && + !valueType->hasTypeParameter()); Type thrownErrorType; if (auto accessor = varDecl->getEffectfulGetAccessor()) { @@ -1269,9 +1267,17 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value, accessor->getEffectiveThrownErrorType().value_or(Type()); } - assert(!valueType->hasUnboundGenericType() && - !valueType->hasTypeParameter()); - return { valueType, valueType, valueType, valueType, thrownErrorType }; + // Adjust the type for concurrency. + auto origValueType = valueType; + + if (!isRequirementOrWitness(locator)) { + valueType = adjustVarTypeForConcurrency( + valueType, varDecl, useDC, + GetClosureType{*this}, + ClosureIsolatedByPreconcurrency{*this}); + } + + return { origValueType, valueType, origValueType, valueType, thrownErrorType }; } /// Bind type variables for archetypes that are determined from From 1efc9a6d0db3941400e8c320712bcec5099e1ea3 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 15 Sep 2025 15:49:05 -0400 Subject: [PATCH 02/18] Sema: Split off getTypeOfReferenceImpl() from getTypeOfReference() --- include/swift/Sema/ConstraintSystem.h | 11 +- lib/Sema/TypeOfReference.cpp | 189 ++++++++++++++++---------- 2 files changed, 129 insertions(+), 71 deletions(-) diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index 786fb1e33c9d4..d3e0836be850b 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -4437,8 +4437,15 @@ class ConstraintSystem { FunctionType *adjustFunctionTypeForConcurrency( FunctionType *fnType, Type baseType, ValueDecl *decl, DeclContext *dc, unsigned numApplies, bool isMainDispatchQueue, - ArrayRef replacements, ConstraintLocatorBuilder locator, - PreparedOverloadBuilder *preparedOverload); + bool openGlobalActorType, ConstraintLocatorBuilder locator); + + /// \returns The opened type and the thrown error type. + std::pair getTypeOfReferenceImpl( + ValueDecl *decl, + FunctionRefInfo functionRefInfo, + ConstraintLocatorBuilder locator, + DeclContext *useDC, + PreparedOverloadBuilder *preparedOverload); /// Retrieve the type of a reference to the given value declaration. /// diff --git a/lib/Sema/TypeOfReference.cpp b/lib/Sema/TypeOfReference.cpp index 38271ca1cc3d9..5b76275b80483 100644 --- a/lib/Sema/TypeOfReference.cpp +++ b/lib/Sema/TypeOfReference.cpp @@ -956,16 +956,22 @@ static bool isRequirementOrWitness(const ConstraintLocatorBuilder &locator) { FunctionType *ConstraintSystem::adjustFunctionTypeForConcurrency( FunctionType *fnType, Type baseType, ValueDecl *decl, DeclContext *dc, - unsigned numApplies, bool isMainDispatchQueue, ArrayRef replacements, - ConstraintLocatorBuilder locator, PreparedOverloadBuilder *preparedOverload) { + unsigned numApplies, bool isMainDispatchQueue, bool openGlobalActorType, + ConstraintLocatorBuilder locator) { auto *adjustedTy = swift::adjustFunctionTypeForConcurrency( fnType, decl, dc, numApplies, isMainDispatchQueue, GetClosureType{*this}, ClosureIsolatedByPreconcurrency{*this}, [&](Type type) { - if (replacements.empty()) + if (!type->hasTypeParameter()) return type; - return openType(type, replacements, locator, preparedOverload); + // FIXME: This should be handled elsewhere. + if (!openGlobalActorType) + return type; + + auto replacements = getOpenedTypes(getConstraintLocator(locator)); + ASSERT(!replacements.empty()); + return openType(type, replacements, locator, /*preparedOverload=*/nullptr); }); // Infer @Sendable for global actor isolated function types under the @@ -1105,13 +1111,14 @@ recordFixIfNeededForPlaceholderInDecl(ConstraintSystem &cs, ValueDecl *D, cs.recordFix(IgnoreInvalidPlaceholderInDeclRef::create(cs, loc)); } -DeclReferenceType -ConstraintSystem::getTypeOfReference(ValueDecl *value, - FunctionRefInfo functionRefInfo, - ConstraintLocatorBuilder locator, - DeclContext *useDC, - PreparedOverloadBuilder *preparedOverload) { +std::pair +ConstraintSystem::getTypeOfReferenceImpl(ValueDecl *value, + FunctionRefInfo functionRefInfo, + ConstraintLocatorBuilder locator, + DeclContext *useDC, + PreparedOverloadBuilder *preparedOverload) { ASSERT(!!preparedOverload == PreparingOverload); + recordFixIfNeededForPlaceholderInDecl(*this, value, locator); if (value->getDeclContext()->isTypeContext() && isa(value)) { @@ -1130,39 +1137,7 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value, // If we opened up any type variables, record the replacements. recordOpenedTypes(locator, replacements, preparedOverload); - auto origOpenedType = openedType; - if (!isRequirementOrWitness(locator)) { - unsigned numApplies = getNumApplications(/*hasAppliedSelf*/ false, - functionRefInfo); - openedType = adjustFunctionTypeForConcurrency( - origOpenedType, /*baseType=*/Type(), func, useDC, numApplies, false, - replacements, locator, preparedOverload); - } - - // If this is a method whose result type is dynamic Self, replace - // DynamicSelf with the actual object type. Repeat the adjustment - // for the original and adjusted types. - auto type = openedType; - if (openedType->hasDynamicSelfType()) { - auto params = openedType->getParams(); - assert(params.size() == 1); - Type selfTy = params.front().getPlainType()->getMetatypeInstanceType(); - type = openedType->replaceDynamicSelfType(selfTy) - ->castTo(); - } - - auto origType = origOpenedType; - if (origOpenedType->hasDynamicSelfType()) { - auto params = origOpenedType->getParams(); - assert(params.size() == 1); - Type selfTy = params.front().getPlainType()->getMetatypeInstanceType(); - origType = origOpenedType->replaceDynamicSelfType(selfTy) - ->castTo(); - } - - // The reference implicitly binds 'self'. - return {origOpenedType, openedType, - origType->getResult(), type->getResult(), Type()}; + return {openedType, Type()}; } // Unqualified reference to a local or global function. @@ -1191,16 +1166,7 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value, // If we opened up any type variables, record the replacements. recordOpenedTypes(locator, replacements, preparedOverload); - auto origOpenedType = openedType; - if (!isRequirementOrWitness(locator)) { - unsigned numApplies = getNumApplications(/*hasAppliedSelf*/ false, - functionRefInfo); - openedType = adjustFunctionTypeForConcurrency( - origOpenedType->castTo(), /*baseType=*/Type(), funcDecl, - useDC, numApplies, false, replacements, locator, preparedOverload); - } - - return { origOpenedType, openedType, origOpenedType, openedType, Type() }; + return {openedType, Type()}; } // Unqualified reference to a type. @@ -1222,11 +1188,11 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value, // Module types are not wrapped in metatypes. if (type->is()) - return { type, type, type, type, Type() }; + return { type, Type() }; // If it's a value reference, refer to the metatype. type = MetatypeType::get(type); - return { type, type, type, type, Type() }; + return {type, Type()}; } // Unqualified reference to a macro. @@ -1245,7 +1211,7 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value, // FIXME: Should we use replaceParamErrorTypeByPlaceholder() here? - return { openedType, openedType, openedType, openedType, Type() }; + return {openedType, Type()}; } // Only remaining case: unqualified reference to a property. @@ -1267,17 +1233,103 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value, accessor->getEffectiveThrownErrorType().value_or(Type()); } + return {valueType, thrownErrorType}; +} + +DeclReferenceType +ConstraintSystem::getTypeOfReference(ValueDecl *value, + FunctionRefInfo functionRefInfo, + ConstraintLocatorBuilder locator, + DeclContext *useDC, + PreparedOverloadBuilder *preparedOverload) { + ASSERT(!!preparedOverload == PreparingOverload); + + Type openedType, thrownErrorType; + std::tie(openedType, thrownErrorType) = getTypeOfReferenceImpl( + value, functionRefInfo, locator, useDC, preparedOverload); + + if (value->getDeclContext()->isTypeContext() && isa(value)) { + auto *openedFnType = openedType->castTo(); + + // Unqualified lookup can find operator names within nominal types. + auto func = cast(value); + assert(func->isOperator() && "Lookup should only find operators"); + + + auto origOpenedType = openedFnType; + if (!isRequirementOrWitness(locator)) { + unsigned numApplies = getNumApplications(/*hasAppliedSelf*/ false, + functionRefInfo); + openedFnType = adjustFunctionTypeForConcurrency( + origOpenedType, /*baseType=*/Type(), func, useDC, numApplies, + /*isMainDispatchQueue=*/false, /*openGlobalActorType=*/true, locator); + } + + // If this is a method whose result type is dynamic Self, replace + // DynamicSelf with the actual object type. Repeat the adjustment + // for the original and adjusted types. + auto type = openedFnType; + if (openedFnType->hasDynamicSelfType()) { + auto params = openedFnType->getParams(); + assert(params.size() == 1); + Type selfTy = params.front().getPlainType()->getMetatypeInstanceType(); + type = openedFnType->replaceDynamicSelfType(selfTy) + ->castTo(); + } + + auto origType = origOpenedType; + if (origOpenedType->hasDynamicSelfType()) { + auto params = origOpenedType->getParams(); + assert(params.size() == 1); + Type selfTy = params.front().getPlainType()->getMetatypeInstanceType(); + origType = origOpenedType->replaceDynamicSelfType(selfTy) + ->castTo(); + } + + // The reference implicitly binds 'self'. + return {origOpenedType, openedType, + origType->getResult(), type->getResult(), Type()}; + } + + // Unqualified reference to a local or global function. + if (auto funcDecl = dyn_cast(value)) { + auto origOpenedType = openedType; + if (!isRequirementOrWitness(locator)) { + unsigned numApplies = getNumApplications(/*hasAppliedSelf*/ false, + functionRefInfo); + openedType = adjustFunctionTypeForConcurrency( + origOpenedType->castTo(), /*baseType=*/Type(), funcDecl, + useDC, numApplies, /*isMainDispatchQueue=*/false, + /*openGlobalActorType=*/true, locator); + } + + return { origOpenedType, openedType, origOpenedType, openedType, Type() }; + } + + // Unqualified reference to a type. + if (isa(value)) { + return { openedType, openedType, openedType, openedType, Type() }; + } + + // Unqualified reference to a macro. + if (isa(value)) { + return { openedType, openedType, openedType, openedType, Type() }; + } + + // Only remaining case: unqualified reference to a property. + auto *varDecl = cast(value); + // Adjust the type for concurrency. - auto origValueType = valueType; + auto origOpenedType = openedType; if (!isRequirementOrWitness(locator)) { - valueType = adjustVarTypeForConcurrency( - valueType, varDecl, useDC, + openedType = adjustVarTypeForConcurrency( + openedType, varDecl, useDC, GetClosureType{*this}, ClosureIsolatedByPreconcurrency{*this}); } - return { origValueType, valueType, origValueType, valueType, thrownErrorType }; + return { origOpenedType, openedType, origOpenedType, openedType, thrownErrorType }; } /// Bind type variables for archetypes that are determined from @@ -1990,13 +2042,13 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference( unsigned numApplies = getNumApplications(hasAppliedSelf, functionRefInfo); openedType = adjustFunctionTypeForConcurrency( origOpenedType->castTo(), baseRValueTy, value, useDC, - numApplies, isMainDispatchQueueMember(locator), replacements, locator, - preparedOverload); + numApplies, isMainDispatchQueueMember(locator), + /*openGlobalActorType=*/true, locator); } else if (auto subscript = dyn_cast(value)) { openedType = adjustFunctionTypeForConcurrency( origOpenedType->castTo(), baseRValueTy, subscript, useDC, - /*numApplies=*/2, /*isMainDispatchQueue=*/false, replacements, locator, - preparedOverload); + /*numApplies=*/2, /*isMainDispatchQueue=*/false, + /*openGlobalActorType=*/true, locator); } else if (auto var = dyn_cast(value)) { // Adjust the function's result type, since that's the Var's actual type. auto origFnType = origOpenedType->castTo(); @@ -2131,9 +2183,8 @@ Type ConstraintSystem::getEffectiveOverloadType(ConstraintLocator *locator, FunctionType::ExtInfo info; type = adjustFunctionTypeForConcurrency( FunctionType::get(indices, elementTy, info), overload.getBaseType(), - subscript, useDC, - /*numApplies=*/1, /*isMainDispatchQueue=*/false, emptyReplacements, - locator, /*preparedOverload=*/nullptr); + subscript, useDC, /*numApplies=*/1, /*isMainDispatchQueue=*/false, + /*openGlobalActorType=*/false, locator); } else if (auto var = dyn_cast(decl)) { type = var->getValueInterfaceType(); if (doesStorageProduceLValue( @@ -2178,8 +2229,8 @@ Type ConstraintSystem::getEffectiveOverloadType(ConstraintLocator *locator, type = adjustFunctionTypeForConcurrency( type->castTo(), overload.getBaseType(), decl, useDC, numApplies, /*isMainDispatchQueue=*/false, - emptyReplacements, locator, /*preparedOverload=*/nullptr) - ->getResult(); + /*openGlobalActorType=*/false, locator) + ->getResult(); } } From 35a439de24c843aefa8145fb939d2ab365e84e58 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 15 Sep 2025 16:24:57 -0400 Subject: [PATCH 03/18] Sema: Remove replacements parameter from getMemberReferenceTypeFromOpenedType() --- include/swift/Sema/ConstraintSystem.h | 3 +-- lib/Sema/TypeOfReference.cpp | 28 ++++++++++++--------------- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index d3e0836be850b..3cb978bb8ecaf 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -4520,8 +4520,7 @@ class ConstraintSystem { /// determine the reference type of the member reference. Type getMemberReferenceTypeFromOpenedType( Type type, Type baseObjTy, ValueDecl *value, - ConstraintLocator *locator, bool hasAppliedSelf, bool isDynamicLookup, - ArrayRef replacements); + ConstraintLocator *locator, bool hasAppliedSelf, bool isDynamicLookup); /// Add the constraints needed to bind an overload's type variable. void bindOverloadType(const SelectedOverload &overload, Type boundType, diff --git a/lib/Sema/TypeOfReference.cpp b/lib/Sema/TypeOfReference.cpp index 5b76275b80483..f3083928f0413 100644 --- a/lib/Sema/TypeOfReference.cpp +++ b/lib/Sema/TypeOfReference.cpp @@ -814,27 +814,24 @@ void ConstraintSystem::recordOpenedTypes( // If the last path element is an archetype or associated type, ignore it. SmallVector pathElts; - auto anchor = locator.getLocatorParts(pathElts); + (void) locator.getLocatorParts(pathElts); if (!pathElts.empty() && pathElts.back().getKind() == ConstraintLocator::GenericParameter) return; - // If the locator is empty, ignore it. - if (!anchor && pathElts.empty()) - return; - ConstraintLocator *locatorPtr = getConstraintLocator(locator); assert(locatorPtr && "No locator for opened types?"); - OpenedType *openedTypes - = Allocator.Allocate(replacements.size()); - std::copy(replacements.begin(), replacements.end(), openedTypes); - // FIXME: Get rid of fixmeAllowDuplicates. - if (!fixmeAllowDuplicates || OpenedTypes.count(locatorPtr) == 0) + if (!fixmeAllowDuplicates || OpenedTypes.count(locatorPtr) == 0) { + OpenedType *openedTypes + = Allocator.Allocate(replacements.size()); + std::copy(replacements.begin(), replacements.end(), openedTypes); + recordOpenedType( locatorPtr, llvm::ArrayRef(openedTypes, replacements.size()), preparedOverload); + } } /// Determine how many levels of argument labels should be removed from the @@ -1757,8 +1754,7 @@ static bool isExistentialMemberAccessWithExplicitBaseExpression( Type ConstraintSystem::getMemberReferenceTypeFromOpenedType( Type type, Type baseObjTy, ValueDecl *value, - ConstraintLocator *locator, bool hasAppliedSelf, bool isDynamicLookup, - ArrayRef replacements) { + ConstraintLocator *locator, bool hasAppliedSelf, bool isDynamicLookup) { auto *outerDC = value->getDeclContext(); // Cope with dynamic 'Self'. @@ -1790,8 +1786,8 @@ Type ConstraintSystem::getMemberReferenceTypeFromOpenedType( baseObjTy, value, locator, isDynamicLookup) && // If there are no type variables, there were no references to 'Self'. type->hasTypeVariable()) { - auto selfGP = outerDC->getSelfInterfaceType(); - ASSERT(selfGP->isEqual(replacements[0].first)); + auto replacements = getOpenedTypes(locator); + ASSERT(replacements[0].first->isEqual(getASTContext().TheSelfType)); auto openedTypeVar = replacements[0].second; type = typeEraseOpenedExistentialReference(type, baseObjTy, openedTypeVar, @@ -2072,14 +2068,14 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference( // Handle DynamicSelfType and a couple of other things. Type type = getMemberReferenceTypeFromOpenedType( openedType, baseObjTy, value, locator, hasAppliedSelf, - isDynamicLookup, replacements); + isDynamicLookup); // Do the same thing for the original type, if there can be any difference. Type origType = type; if (openedType.getPointer() != origOpenedType.getPointer()) { origType = getMemberReferenceTypeFromOpenedType( origOpenedType, baseObjTy, value, locator, hasAppliedSelf, - isDynamicLookup, replacements); + isDynamicLookup); } return { origOpenedType, openedType, origType, type, thrownErrorType }; From 05d57692dd80f59c8aaaaa30d3faddfab0d1660e Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 15 Sep 2025 16:25:09 -0400 Subject: [PATCH 04/18] Sema: Pass baseObjTy instead of baseRValueTy to adjustFunctionTypeForConcurrency() --- lib/Sema/TypeOfReference.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Sema/TypeOfReference.cpp b/lib/Sema/TypeOfReference.cpp index f3083928f0413..29db3de7763a8 100644 --- a/lib/Sema/TypeOfReference.cpp +++ b/lib/Sema/TypeOfReference.cpp @@ -2037,12 +2037,12 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference( } else if (isa(value) || isa(value)) { unsigned numApplies = getNumApplications(hasAppliedSelf, functionRefInfo); openedType = adjustFunctionTypeForConcurrency( - origOpenedType->castTo(), baseRValueTy, value, useDC, + origOpenedType->castTo(), baseObjTy, value, useDC, numApplies, isMainDispatchQueueMember(locator), /*openGlobalActorType=*/true, locator); } else if (auto subscript = dyn_cast(value)) { openedType = adjustFunctionTypeForConcurrency( - origOpenedType->castTo(), baseRValueTy, subscript, useDC, + origOpenedType->castTo(), baseObjTy, subscript, useDC, /*numApplies=*/2, /*isMainDispatchQueue=*/false, /*openGlobalActorType=*/true, locator); } else if (auto var = dyn_cast(value)) { From 8397c0826abe33357c3ff7805e5c744aadf380fd Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 16 Sep 2025 13:10:28 -0400 Subject: [PATCH 05/18] Sema: Remove duplicate logic for throwing accessor witness matching getTypeOfMemberReference() already opens the accessor's thrown error type for us. --- lib/Sema/TypeCheckProtocol.cpp | 51 ++++++++++------------------------ 1 file changed, 14 insertions(+), 37 deletions(-) diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index e95f6e74831cd..10e85525d21d1 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -1172,14 +1172,16 @@ swift::matchWitness(WitnessChecker::RequirementEnvironmentCache &reqEnvCache, reqLocator = cs->getConstraintLocator(req, ConstraintLocator::ProtocolRequirement); - reqType = + auto reqTypeInfo = cs->getTypeOfMemberReference(selfTy, req, dc, /*isDynamicResult=*/false, FunctionRefInfo::doubleBaseNameApply(), - reqLocator, &reqReplacements) - .adjustedReferenceType; + reqLocator, &reqReplacements); + reqType = reqTypeInfo.adjustedReferenceType; reqType = reqType->getRValueType(); + Type reqThrownError = reqTypeInfo.thrownErrorTypeOnAccess; + // For any type parameters we replaced in the witness, map them // to the corresponding archetypes in the witness's context. for (const auto &replacement : reqReplacements) { @@ -1205,50 +1207,25 @@ swift::matchWitness(WitnessChecker::RequirementEnvironmentCache &reqEnvCache, witnessType = witness->getInterfaceType(); witnessLocator = cs->getConstraintLocator(req, LocatorPathElt::Witness(witness)); + DeclReferenceType openWitnessTypeInfo; + if (witness->getDeclContext()->isTypeContext()) { - openWitnessType = + openWitnessTypeInfo = cs->getTypeOfMemberReference(selfTy, witness, dc, /*isDynamicResult=*/false, FunctionRefInfo::doubleBaseNameApply(), - witnessLocator, &witnessReplacements) - .adjustedReferenceType; + witnessLocator, &witnessReplacements); } else { - openWitnessType = + openWitnessTypeInfo = cs->getTypeOfReference( witness, FunctionRefInfo::doubleBaseNameApply(), witnessLocator, - /*useDC=*/nullptr, /*preparedOverload=*/nullptr) - .adjustedReferenceType; + /*useDC=*/nullptr, /*preparedOverload=*/nullptr); } - openWitnessType = openWitnessType->getRValueType(); - Type reqThrownError; - Type witnessThrownError; - - if (auto *witnessASD = dyn_cast(witness)) { - auto *reqASD = cast(req); - - // Dig out the thrown error types from the getter so we can compare them - // later. - auto getThrownErrorType = [](AbstractStorageDecl *asd) -> Type { - if (auto getter = asd->getEffectfulGetAccessor()) { - if (Type thrownErrorType = getter->getThrownInterfaceType()) { - return thrownErrorType; - } else if (getter->hasThrows()) { - return asd->getASTContext().getErrorExistentialType(); - } - } - - return asd->getASTContext().getNeverType(); - }; - - reqThrownError = getThrownErrorType(reqASD); - reqThrownError = cs->openType(reqThrownError, reqReplacements, - reqLocator, /*preparedOverload=*/nullptr); + openWitnessType = openWitnessTypeInfo.adjustedReferenceType; + openWitnessType = openWitnessType->getRValueType(); - witnessThrownError = getThrownErrorType(witnessASD); - witnessThrownError = cs->openType(witnessThrownError, witnessReplacements, - witnessLocator, /*preparedOverload=*/nullptr); - } + Type witnessThrownError = openWitnessTypeInfo.thrownErrorTypeOnAccess; return std::make_tuple(std::nullopt, reqType, openWitnessType, reqThrownError, witnessThrownError); From 2fde4a50e7884738557c73dcf633625bc7b82452 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 16 Sep 2025 13:11:38 -0400 Subject: [PATCH 06/18] Sema: Split off getTypeOfMemberReferenceImpl() from getTypeOfMemberReference() --- include/swift/Sema/ConstraintSystem.h | 7 ++++ lib/Sema/TypeOfReference.cpp | 51 ++++++++++++++++++++------- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index 3cb978bb8ecaf..cab3df708856f 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -4463,6 +4463,13 @@ class ConstraintSystem { DeclContext *useDC, PreparedOverloadBuilder *preparedOverload); + /// \returns the opened type, the thrown error type, and the base object type. + std::tuple getTypeOfMemberReferenceImpl( + Type baseTy, ValueDecl *decl, DeclContext *useDC, bool isDynamicLookup, + FunctionRefInfo functionRefInfo, ConstraintLocator *locator, + SmallVectorImpl *replacements = nullptr, + PreparedOverloadBuilder *preparedOverload = nullptr); + /// Retrieve the type of a reference to the given value declaration, /// as a member with a base of the given type. /// diff --git a/lib/Sema/TypeOfReference.cpp b/lib/Sema/TypeOfReference.cpp index 29db3de7763a8..15499923f61e7 100644 --- a/lib/Sema/TypeOfReference.cpp +++ b/lib/Sema/TypeOfReference.cpp @@ -1851,11 +1851,13 @@ static FunctionType *applyOptionality(ValueDecl *value, FunctionType *fnTy) { fnTy->getExtInfo()); } -DeclReferenceType ConstraintSystem::getTypeOfMemberReference( +std::tuple +ConstraintSystem::getTypeOfMemberReferenceImpl( Type baseTy, ValueDecl *value, DeclContext *useDC, bool isDynamicLookup, FunctionRefInfo functionRefInfo, ConstraintLocator *locator, SmallVectorImpl *replacementsPtr, PreparedOverloadBuilder *preparedOverload) { + ASSERT(!isa(value)); ASSERT(!!preparedOverload == PreparingOverload); recordFixIfNeededForPlaceholderInDecl(*this, value, locator); @@ -1863,17 +1865,6 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference( Type baseRValueTy = baseTy->getRValueType(); auto baseObjTy = baseRValueTy->getMetatypeInstanceType(); - // If the base is a module type, just use the type of the decl. - if (baseObjTy->is()) { - return getTypeOfReference(value, functionRefInfo, locator, useDC, - preparedOverload); - } - - if (auto *typeDecl = dyn_cast(value)) { - return getTypeOfMemberTypeReference(baseObjTy, typeDecl, - locator, preparedOverload); - } - // Figure out the declaration context to use when opening this type. DeclContext *innerDC = value->getInnermostDeclContext(); DeclContext *outerDC = value->getDeclContext(); @@ -1914,7 +1905,7 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference( isa(value)) { auto interfaceType = value->getInterfaceType(); if (interfaceType->is() || isa(value)) - return { interfaceType, interfaceType, interfaceType, interfaceType, Type() }; + return { interfaceType, Type(), baseObjTy }; if (outerDC->getSelfClassDecl()) { if (isa(value)) { @@ -2030,6 +2021,40 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference( } } + return { openedType, thrownErrorType, baseObjTy }; +} + +DeclReferenceType ConstraintSystem::getTypeOfMemberReference( + Type baseTy, ValueDecl *value, DeclContext *useDC, bool isDynamicLookup, + FunctionRefInfo functionRefInfo, ConstraintLocator *locator, + SmallVectorImpl *replacementsPtr, + PreparedOverloadBuilder *preparedOverload) { + ASSERT(!!preparedOverload == PreparingOverload); + + // Figure out the instance type used for the base. + Type baseRValueTy = baseTy; + Type baseObjTy = baseRValueTy->getMetatypeInstanceType(); + + // If the base is a module type, just use the type of the decl. + if (baseObjTy->getMetatypeInstanceType()->is()) { + return getTypeOfReference(value, functionRefInfo, locator, useDC, + preparedOverload); + } + + if (auto *typeDecl = dyn_cast(value)) { + return getTypeOfMemberTypeReference(baseObjTy, typeDecl, + locator, preparedOverload); + } + + Type openedType, thrownErrorType; + std::tie(openedType, thrownErrorType, baseObjTy) + = getTypeOfMemberReferenceImpl(baseTy, value, useDC, + isDynamicLookup, functionRefInfo, + locator, replacementsPtr, + preparedOverload); + + auto hasAppliedSelf = doesMemberRefApplyCurriedSelf(baseRValueTy, value); + // Adjust the opened type for concurrency. Type origOpenedType = openedType; if (isRequirementOrWitness(locator)) { From d8ead6c5cc5d30d9760c2380bc4878f88da13cde Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 16 Sep 2025 13:51:47 -0400 Subject: [PATCH 07/18] Sema: Refactor getTypeOf{Member,}Reference() to take the OverloadChoice --- include/swift/Sema/ConstraintSystem.h | 19 ++---- lib/Sema/TypeCheckProtocol.cpp | 20 +++--- lib/Sema/TypeOfReference.cpp | 94 ++++++++++++++++----------- 3 files changed, 69 insertions(+), 64 deletions(-) diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index cab3df708856f..b97fb09465020 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -4441,8 +4441,7 @@ class ConstraintSystem { /// \returns The opened type and the thrown error type. std::pair getTypeOfReferenceImpl( - ValueDecl *decl, - FunctionRefInfo functionRefInfo, + OverloadChoice choice, ConstraintLocatorBuilder locator, DeclContext *useDC, PreparedOverloadBuilder *preparedOverload); @@ -4453,20 +4452,16 @@ class ConstraintSystem { /// the type by replacing each instance of an archetype with a fresh type /// variable. /// - /// \param decl The declarations whose type is being computed. - /// /// \returns a description of the type of this declaration reference. DeclReferenceType getTypeOfReference( - ValueDecl *decl, - FunctionRefInfo functionRefInfo, + OverloadChoice choice, ConstraintLocatorBuilder locator, DeclContext *useDC, PreparedOverloadBuilder *preparedOverload); /// \returns the opened type, the thrown error type, and the base object type. std::tuple getTypeOfMemberReferenceImpl( - Type baseTy, ValueDecl *decl, DeclContext *useDC, bool isDynamicLookup, - FunctionRefInfo functionRefInfo, ConstraintLocator *locator, + OverloadChoice choice, DeclContext *useDC, ConstraintLocator *locator, SmallVectorImpl *replacements = nullptr, PreparedOverloadBuilder *preparedOverload = nullptr); @@ -4477,13 +4472,9 @@ class ConstraintSystem { /// this routine "opens up" the type by replacing each instance of a generic /// parameter with a fresh type variable. /// - /// \param isDynamicLookup Indicates that this declaration was found via - /// dynamic lookup. - /// /// \returns a description of the type of this declaration reference. DeclReferenceType getTypeOfMemberReference( - Type baseTy, ValueDecl *decl, DeclContext *useDC, bool isDynamicLookup, - FunctionRefInfo functionRefInfo, ConstraintLocator *locator, + OverloadChoice choice, DeclContext *useDC, ConstraintLocator *locator, SmallVectorImpl *replacements = nullptr, PreparedOverloadBuilder *preparedOverload = nullptr); @@ -4497,7 +4488,7 @@ class ConstraintSystem { } private: - DeclReferenceType getTypeOfMemberTypeReference( + Type getTypeOfMemberTypeReference( Type baseObjTy, TypeDecl *typeDecl, ConstraintLocator *locator, PreparedOverloadBuilder *preparedOverload); diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index 10e85525d21d1..b9d053a8b93f0 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -1172,11 +1172,9 @@ swift::matchWitness(WitnessChecker::RequirementEnvironmentCache &reqEnvCache, reqLocator = cs->getConstraintLocator(req, ConstraintLocator::ProtocolRequirement); + OverloadChoice reqChoice(selfTy, req, FunctionRefInfo::doubleBaseNameApply()); auto reqTypeInfo = - cs->getTypeOfMemberReference(selfTy, req, dc, - /*isDynamicResult=*/false, - FunctionRefInfo::doubleBaseNameApply(), - reqLocator, &reqReplacements); + cs->getTypeOfMemberReference(reqChoice, dc, reqLocator, &reqReplacements); reqType = reqTypeInfo.adjustedReferenceType; reqType = reqType->getRValueType(); @@ -1202,23 +1200,23 @@ swift::matchWitness(WitnessChecker::RequirementEnvironmentCache &reqEnvCache, } // Open up the witness type. - SmallVector witnessReplacements; - witnessType = witness->getInterfaceType(); witnessLocator = cs->getConstraintLocator(req, LocatorPathElt::Witness(witness)); DeclReferenceType openWitnessTypeInfo; if (witness->getDeclContext()->isTypeContext()) { + OverloadChoice witnessChoice(selfTy, witness, FunctionRefInfo::doubleBaseNameApply()); openWitnessTypeInfo = - cs->getTypeOfMemberReference(selfTy, witness, dc, - /*isDynamicResult=*/false, - FunctionRefInfo::doubleBaseNameApply(), - witnessLocator, &witnessReplacements); + cs->getTypeOfMemberReference(witnessChoice, dc, + witnessLocator, + /*replacements=*/nullptr, + /*preparedOverload=*/nullptr); } else { + OverloadChoice witnessChoice(Type(), witness, FunctionRefInfo::doubleBaseNameApply()); openWitnessTypeInfo = cs->getTypeOfReference( - witness, FunctionRefInfo::doubleBaseNameApply(), witnessLocator, + witnessChoice, witnessLocator, /*useDC=*/nullptr, /*preparedOverload=*/nullptr); } diff --git a/lib/Sema/TypeOfReference.cpp b/lib/Sema/TypeOfReference.cpp index 15499923f61e7..8bfa9f6eb1ee9 100644 --- a/lib/Sema/TypeOfReference.cpp +++ b/lib/Sema/TypeOfReference.cpp @@ -1109,11 +1109,12 @@ recordFixIfNeededForPlaceholderInDecl(ConstraintSystem &cs, ValueDecl *D, } std::pair -ConstraintSystem::getTypeOfReferenceImpl(ValueDecl *value, - FunctionRefInfo functionRefInfo, +ConstraintSystem::getTypeOfReferenceImpl(OverloadChoice choice, ConstraintLocatorBuilder locator, DeclContext *useDC, PreparedOverloadBuilder *preparedOverload) { + auto *value = choice.getDecl(); + ASSERT(!!preparedOverload == PreparingOverload); recordFixIfNeededForPlaceholderInDecl(*this, value, locator); @@ -1139,6 +1140,8 @@ ConstraintSystem::getTypeOfReferenceImpl(ValueDecl *value, // Unqualified reference to a local or global function. if (auto funcDecl = dyn_cast(value)) { + auto functionRefInfo = choice.getFunctionRefInfo(); + SmallVector replacements; auto funcType = funcDecl->getInterfaceType()->castTo(); @@ -1234,8 +1237,7 @@ ConstraintSystem::getTypeOfReferenceImpl(ValueDecl *value, } DeclReferenceType -ConstraintSystem::getTypeOfReference(ValueDecl *value, - FunctionRefInfo functionRefInfo, +ConstraintSystem::getTypeOfReference(OverloadChoice choice, ConstraintLocatorBuilder locator, DeclContext *useDC, PreparedOverloadBuilder *preparedOverload) { @@ -1243,7 +1245,9 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value, Type openedType, thrownErrorType; std::tie(openedType, thrownErrorType) = getTypeOfReferenceImpl( - value, functionRefInfo, locator, useDC, preparedOverload); + choice, locator, useDC, preparedOverload); + + auto *value = choice.getDecl(); if (value->getDeclContext()->isTypeContext() && isa(value)) { auto *openedFnType = openedType->castTo(); @@ -1252,6 +1256,7 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value, auto func = cast(value); assert(func->isOperator() && "Lookup should only find operators"); + auto functionRefInfo = choice.getFunctionRefInfo(); auto origOpenedType = openedFnType; if (!isRequirementOrWitness(locator)) { @@ -1293,7 +1298,7 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value, auto origOpenedType = openedType; if (!isRequirementOrWitness(locator)) { unsigned numApplies = getNumApplications(/*hasAppliedSelf*/ false, - functionRefInfo); + choice.getFunctionRefInfo()); openedType = adjustFunctionTypeForConcurrency( origOpenedType->castTo(), /*baseType=*/Type(), funcDecl, useDC, numApplies, /*isMainDispatchQueue=*/false, @@ -1523,10 +1528,10 @@ void ConstraintSystem::openGenericRequirement( preparedOverload); } -DeclReferenceType ConstraintSystem::getTypeOfMemberTypeReference( +Type ConstraintSystem::getTypeOfMemberTypeReference( Type baseObjTy, TypeDecl *typeDecl, ConstraintLocator *locator, PreparedOverloadBuilder *preparedOverload) { - assert(!isa(typeDecl) && "Nested module?"); + ASSERT(!isa(typeDecl) && "Nested module?"); auto memberTy = TypeChecker::substMemberTypeWithBase(typeDecl, baseObjTy); @@ -1552,8 +1557,7 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberTypeReference( } FunctionType::Param baseObjParam(baseObjTy); - auto openedType = FunctionType::get({baseObjParam}, memberTy); - return { openedType, openedType, memberTy, memberTy, Type() }; + return FunctionType::get({baseObjParam}, memberTy); } std::pair ConstraintSystem::getOpenedStorageType( @@ -1853,18 +1857,30 @@ static FunctionType *applyOptionality(ValueDecl *value, FunctionType *fnTy) { std::tuple ConstraintSystem::getTypeOfMemberReferenceImpl( - Type baseTy, ValueDecl *value, DeclContext *useDC, bool isDynamicLookup, - FunctionRefInfo functionRefInfo, ConstraintLocator *locator, - SmallVectorImpl *replacementsPtr, + OverloadChoice choice, DeclContext *useDC, + ConstraintLocator *locator, SmallVectorImpl *replacementsPtr, PreparedOverloadBuilder *preparedOverload) { - ASSERT(!isa(value)); ASSERT(!!preparedOverload == PreparingOverload); + + auto *value = choice.getDecl(); + auto functionRefInfo = choice.getFunctionRefInfo(); + recordFixIfNeededForPlaceholderInDecl(*this, value, locator); // Figure out the instance type used for the base. + auto baseTy = choice.getBaseType(); Type baseRValueTy = baseTy->getRValueType(); auto baseObjTy = baseRValueTy->getMetatypeInstanceType(); + Type openedType; + Type thrownErrorType; + + if (auto *typeDecl = dyn_cast(value)) { + openedType = getTypeOfMemberTypeReference(baseObjTy, typeDecl, + locator, preparedOverload); + return {openedType, thrownErrorType, baseObjTy}; + } + // Figure out the declaration context to use when opening this type. DeclContext *innerDC = value->getInnermostDeclContext(); DeclContext *outerDC = value->getDeclContext(); @@ -1898,8 +1914,6 @@ ConstraintSystem::getTypeOfMemberReferenceImpl( // strip it off later. auto hasAppliedSelf = doesMemberRefApplyCurriedSelf(baseRValueTy, value); - Type openedType; - Type thrownErrorType; if (isa(value) || isa(value) || isa(value)) { @@ -1987,7 +2001,7 @@ ConstraintSystem::getTypeOfMemberReferenceImpl( addConstraint(ConstraintKind::Bind, baseOpenedTy, selfObjTy, getConstraintLocator(locator), /*isFavored=*/false, preparedOverload); - } else if (!isDynamicLookup) { + } else if (choice.getKind() != OverloadChoiceKind::DeclViaDynamic) { addSelfConstraint(*this, baseOpenedTy, selfObjTy, locator, preparedOverload); } @@ -2025,34 +2039,31 @@ ConstraintSystem::getTypeOfMemberReferenceImpl( } DeclReferenceType ConstraintSystem::getTypeOfMemberReference( - Type baseTy, ValueDecl *value, DeclContext *useDC, bool isDynamicLookup, - FunctionRefInfo functionRefInfo, ConstraintLocator *locator, + OverloadChoice choice, DeclContext *useDC, ConstraintLocator *locator, SmallVectorImpl *replacementsPtr, PreparedOverloadBuilder *preparedOverload) { ASSERT(!!preparedOverload == PreparingOverload); + auto *value = choice.getDecl(); + // Figure out the instance type used for the base. - Type baseRValueTy = baseTy; + Type baseRValueTy = choice.getBaseType(); Type baseObjTy = baseRValueTy->getMetatypeInstanceType(); - // If the base is a module type, just use the type of the decl. - if (baseObjTy->getMetatypeInstanceType()->is()) { - return getTypeOfReference(value, functionRefInfo, locator, useDC, - preparedOverload); - } - - if (auto *typeDecl = dyn_cast(value)) { - return getTypeOfMemberTypeReference(baseObjTy, typeDecl, - locator, preparedOverload); - } + // A reference to a module member is really unqualified, and should + // be handled by the caller via getTypeOfReference(). + ASSERT(!baseObjTy->is()); Type openedType, thrownErrorType; std::tie(openedType, thrownErrorType, baseObjTy) - = getTypeOfMemberReferenceImpl(baseTy, value, useDC, - isDynamicLookup, functionRefInfo, - locator, replacementsPtr, + = getTypeOfMemberReferenceImpl(choice, useDC, locator, replacementsPtr, preparedOverload); + if (isa(value)) { + auto type = openedType->castTo()->getResult(); + return { openedType, openedType, type, type, Type() }; + } + auto hasAppliedSelf = doesMemberRefApplyCurriedSelf(baseRValueTy, value); // Adjust the opened type for concurrency. @@ -2060,7 +2071,8 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference( if (isRequirementOrWitness(locator)) { // Don't adjust when doing witness matching, because that can cause cycles. } else if (isa(value) || isa(value)) { - unsigned numApplies = getNumApplications(hasAppliedSelf, functionRefInfo); + unsigned numApplies = getNumApplications( + hasAppliedSelf, choice.getFunctionRefInfo()); openedType = adjustFunctionTypeForConcurrency( origOpenedType->castTo(), baseObjTy, value, useDC, numApplies, isMainDispatchQueueMember(locator), @@ -2082,6 +2094,8 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference( origFnType->getParams(), resultTy, origFnType->getExtInfo()); } + bool isDynamicLookup = (choice.getKind() == OverloadChoiceKind::DeclViaDynamic); + // Check if we need to apply a layer of optionality to the type. if (!isRequirementOrWitness(locator)) { if (isDynamicLookup || value->getAttrs().hasAttribute()) { @@ -2833,14 +2847,16 @@ ConstraintSystem::prepareOverloadImpl(ConstraintLocator *locator, // Retrieve the type of a reference to the specific declaration choice. assert(!baseTy->hasTypeParameter()); + // If the base is a module type, it's an unqualified reference. + if (baseTy->getMetatypeInstanceType()->is()) { + return getTypeOfReference(choice, locator, useDC, preparedOverload); + } + return getTypeOfMemberReference( - baseTy, choice.getDecl(), useDC, - (choice.getKind() == OverloadChoiceKind::DeclViaDynamic), - choice.getFunctionRefInfo(), locator, nullptr, preparedOverload); + choice, useDC, locator, /*replacements=*/nullptr, preparedOverload); } else { return getTypeOfReference( - choice.getDecl(), choice.getFunctionRefInfo(), locator, useDC, - preparedOverload); + choice, locator, useDC, preparedOverload); } } From a028eb36b722c4f746bec78c5c339550643e5e42 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 16 Sep 2025 13:58:04 -0400 Subject: [PATCH 08/18] Sema: Don't need to return new baseObjTy from getTypeOfMemberReferenceImpl() --- include/swift/Sema/ConstraintSystem.h | 4 ++-- lib/Sema/TypeOfReference.cpp | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index b97fb09465020..3c43a3f25404f 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -4459,8 +4459,8 @@ class ConstraintSystem { DeclContext *useDC, PreparedOverloadBuilder *preparedOverload); - /// \returns the opened type, the thrown error type, and the base object type. - std::tuple getTypeOfMemberReferenceImpl( + /// \returns the opened type and the thrown error type. + std::pair getTypeOfMemberReferenceImpl( OverloadChoice choice, DeclContext *useDC, ConstraintLocator *locator, SmallVectorImpl *replacements = nullptr, PreparedOverloadBuilder *preparedOverload = nullptr); diff --git a/lib/Sema/TypeOfReference.cpp b/lib/Sema/TypeOfReference.cpp index 8bfa9f6eb1ee9..b6c58f9d00f01 100644 --- a/lib/Sema/TypeOfReference.cpp +++ b/lib/Sema/TypeOfReference.cpp @@ -1628,8 +1628,8 @@ std::pair ConstraintSystem::getOpenedStorageType( FunctionType::Param selfParam(selfTy, Identifier(), selfFlags); FunctionType::ExtInfo info; - return std::make_pair(thrownErrorType, - FunctionType::get({selfParam}, refType, info)); + return std::make_pair(FunctionType::get({selfParam}, refType, info), + thrownErrorType); } /// Add the constraint on the type used for the 'Self' type for a member @@ -1855,7 +1855,7 @@ static FunctionType *applyOptionality(ValueDecl *value, FunctionType *fnTy) { fnTy->getExtInfo()); } -std::tuple +std::pair ConstraintSystem::getTypeOfMemberReferenceImpl( OverloadChoice choice, DeclContext *useDC, ConstraintLocator *locator, SmallVectorImpl *replacementsPtr, @@ -1878,7 +1878,7 @@ ConstraintSystem::getTypeOfMemberReferenceImpl( if (auto *typeDecl = dyn_cast(value)) { openedType = getTypeOfMemberTypeReference(baseObjTy, typeDecl, locator, preparedOverload); - return {openedType, thrownErrorType, baseObjTy}; + return {openedType, thrownErrorType}; } // Figure out the declaration context to use when opening this type. @@ -1919,7 +1919,7 @@ ConstraintSystem::getTypeOfMemberReferenceImpl( isa(value)) { auto interfaceType = value->getInterfaceType(); if (interfaceType->is() || isa(value)) - return { interfaceType, Type(), baseObjTy }; + return { interfaceType, Type() }; if (outerDC->getSelfClassDecl()) { if (isa(value)) { @@ -1939,7 +1939,7 @@ ConstraintSystem::getTypeOfMemberReferenceImpl( } else { auto *storage = cast(value); - std::tie(thrownErrorType, openedType) = getOpenedStorageType( + std::tie(openedType, thrownErrorType) = getOpenedStorageType( baseTy, storage, useDC, hasAppliedSelf, replacements, locator, preparedOverload); } @@ -1976,7 +1976,6 @@ ConstraintSystem::getTypeOfMemberReferenceImpl( // to make sure that it's opened before use. baseOpenedTy = openType(concreteSelf, replacements, locator, preparedOverload); - baseObjTy = baseOpenedTy; } } } else { @@ -2035,7 +2034,7 @@ ConstraintSystem::getTypeOfMemberReferenceImpl( } } - return { openedType, thrownErrorType, baseObjTy }; + return { openedType, thrownErrorType }; } DeclReferenceType ConstraintSystem::getTypeOfMemberReference( @@ -2047,7 +2046,8 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference( auto *value = choice.getDecl(); // Figure out the instance type used for the base. - Type baseRValueTy = choice.getBaseType(); + Type baseTy = choice.getBaseType(); + Type baseRValueTy = baseTy->getRValueType(); Type baseObjTy = baseRValueTy->getMetatypeInstanceType(); // A reference to a module member is really unqualified, and should @@ -2055,7 +2055,7 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference( ASSERT(!baseObjTy->is()); Type openedType, thrownErrorType; - std::tie(openedType, thrownErrorType, baseObjTy) + std::tie(openedType, thrownErrorType) = getTypeOfMemberReferenceImpl(choice, useDC, locator, replacementsPtr, preparedOverload); From 4ea2f1706b4d6ecf081da605e63a00ed40f9cd3f Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Wed, 17 Sep 2025 10:21:59 -0400 Subject: [PATCH 09/18] Sema: Simplify getConcreteReplacementForProtocolSelfType() --- lib/Sema/ConstraintSystem.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 6d6452dd48af9..d0e9af4696d26 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -4325,15 +4325,9 @@ Type constraints::getConcreteReplacementForProtocolSelfType(ValueDecl *member) { if (!DC->getSelfProtocolDecl()) return Type(); - GenericSignature signature; - if (auto *genericContext = member->getAsGenericContext()) { - signature = genericContext->getGenericSignature(); - } else { - signature = DC->getGenericSignatureOfContext(); - } - + auto sig = member->getInnermostDeclContext()->getGenericSignatureOfContext(); auto selfTy = DC->getSelfInterfaceType(); - return signature->getConcreteType(selfTy); + return sig->getConcreteType(selfTy); } static bool isOperator(Expr *expr, StringRef expectedName) { From 182c38470bed5119d7b2ffe5c77fb59c237c5990 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 16 Sep 2025 14:12:49 -0400 Subject: [PATCH 10/18] Sema: Remove replacementsPtr parameter from getTypeOfMemberReference() --- include/swift/Sema/ConstraintSystem.h | 6 ++-- lib/Sema/TypeCheckProtocol.cpp | 9 +++--- lib/Sema/TypeOfReference.cpp | 45 +++++++++++---------------- 3 files changed, 24 insertions(+), 36 deletions(-) diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index 3c43a3f25404f..25c989b7684f5 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -4462,8 +4462,7 @@ class ConstraintSystem { /// \returns the opened type and the thrown error type. std::pair getTypeOfMemberReferenceImpl( OverloadChoice choice, DeclContext *useDC, ConstraintLocator *locator, - SmallVectorImpl *replacements = nullptr, - PreparedOverloadBuilder *preparedOverload = nullptr); + PreparedOverloadBuilder *preparedOverload); /// Retrieve the type of a reference to the given value declaration, /// as a member with a base of the given type. @@ -4475,8 +4474,7 @@ class ConstraintSystem { /// \returns a description of the type of this declaration reference. DeclReferenceType getTypeOfMemberReference( OverloadChoice choice, DeclContext *useDC, ConstraintLocator *locator, - SmallVectorImpl *replacements = nullptr, - PreparedOverloadBuilder *preparedOverload = nullptr); + PreparedOverloadBuilder *preparedOverload); /// Retrieve a list of generic parameter types solver has "opened" (replaced /// with a type variable) at the given location. diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index b9d053a8b93f0..d425cf7be4eb8 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -1168,13 +1168,13 @@ swift::matchWitness(WitnessChecker::RequirementEnvironmentCache &reqEnvCache, Type selfTy = proto->getSelfInterfaceType().subst(reqSubMap); // Open up the type of the requirement. - SmallVector reqReplacements; - reqLocator = cs->getConstraintLocator(req, ConstraintLocator::ProtocolRequirement); OverloadChoice reqChoice(selfTy, req, FunctionRefInfo::doubleBaseNameApply()); auto reqTypeInfo = - cs->getTypeOfMemberReference(reqChoice, dc, reqLocator, &reqReplacements); + cs->getTypeOfMemberReference(reqChoice, dc, reqLocator, + /*preparedOverload=*/nullptr); + reqType = reqTypeInfo.adjustedReferenceType; reqType = reqType->getRValueType(); @@ -1182,7 +1182,7 @@ swift::matchWitness(WitnessChecker::RequirementEnvironmentCache &reqEnvCache, // For any type parameters we replaced in the witness, map them // to the corresponding archetypes in the witness's context. - for (const auto &replacement : reqReplacements) { + for (const auto &replacement : cs->getOpenedTypes(reqLocator)) { auto replacedInReq = Type(replacement.first).subst(reqSubMap); // If substitution failed, skip the requirement. This only occurs in @@ -1210,7 +1210,6 @@ swift::matchWitness(WitnessChecker::RequirementEnvironmentCache &reqEnvCache, openWitnessTypeInfo = cs->getTypeOfMemberReference(witnessChoice, dc, witnessLocator, - /*replacements=*/nullptr, /*preparedOverload=*/nullptr); } else { OverloadChoice witnessChoice(Type(), witness, FunctionRefInfo::doubleBaseNameApply()); diff --git a/lib/Sema/TypeOfReference.cpp b/lib/Sema/TypeOfReference.cpp index b6c58f9d00f01..73bec1508eb34 100644 --- a/lib/Sema/TypeOfReference.cpp +++ b/lib/Sema/TypeOfReference.cpp @@ -1858,7 +1858,7 @@ static FunctionType *applyOptionality(ValueDecl *value, FunctionType *fnTy) { std::pair ConstraintSystem::getTypeOfMemberReferenceImpl( OverloadChoice choice, DeclContext *useDC, - ConstraintLocator *locator, SmallVectorImpl *replacementsPtr, + ConstraintLocator *locator, PreparedOverloadBuilder *preparedOverload) { ASSERT(!!preparedOverload == PreparingOverload); @@ -1888,28 +1888,23 @@ ConstraintSystem::getTypeOfMemberReferenceImpl( auto genericSig = innerDC->getGenericSignatureOfContext(); // Open the type of the generic function or member of a generic type. - ArrayRef replacements; - SmallVector localReplacements; - { - auto &_replacements = replacementsPtr ? *replacementsPtr : localReplacements; - - // If we have a generic signature, open the parameters. We delay opening - // requirements to allow contextual types to affect the situation. - if (genericSig) { - openGenericParameters(outerDC, genericSig, _replacements, locator, - preparedOverload); - } + SmallVector replacements; - // If we opened up any type variables, record the replacements. We do this - // up-front to allow requirement fix coalescing logic to work correctly with - // requirements imposed on base type (since that relies on being able to - // find the recorded opened type). We then make the array immutable for the - // following logic to ensure they don't attempt to add any additional opened - // types. - recordOpenedTypes(locator, _replacements, preparedOverload); - replacements = _replacements; + // If we have a generic signature, open the parameters. We delay opening + // requirements to allow contextual types to affect the situation. + if (genericSig) { + openGenericParameters(outerDC, genericSig, replacements, locator, + preparedOverload); } + // If we opened up any type variables, record the replacements. We do this + // up-front to allow requirement fix coalescing logic to work correctly with + // requirements imposed on base type (since that relies on being able to + // find the recorded opened type). We then make the array immutable for the + // following logic to ensure they don't attempt to add any additional opened + // types. + recordOpenedTypes(locator, replacements, preparedOverload); + // Check to see if the self parameter is applied, in which case we'll want to // strip it off later. auto hasAppliedSelf = doesMemberRefApplyCurriedSelf(baseRValueTy, value); @@ -2039,7 +2034,6 @@ ConstraintSystem::getTypeOfMemberReferenceImpl( DeclReferenceType ConstraintSystem::getTypeOfMemberReference( OverloadChoice choice, DeclContext *useDC, ConstraintLocator *locator, - SmallVectorImpl *replacementsPtr, PreparedOverloadBuilder *preparedOverload) { ASSERT(!!preparedOverload == PreparingOverload); @@ -2056,8 +2050,7 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference( Type openedType, thrownErrorType; std::tie(openedType, thrownErrorType) - = getTypeOfMemberReferenceImpl(choice, useDC, locator, replacementsPtr, - preparedOverload); + = getTypeOfMemberReferenceImpl(choice, useDC, locator, preparedOverload); if (isa(value)) { auto type = openedType->castTo()->getResult(); @@ -2852,11 +2845,9 @@ ConstraintSystem::prepareOverloadImpl(ConstraintLocator *locator, return getTypeOfReference(choice, locator, useDC, preparedOverload); } - return getTypeOfMemberReference( - choice, useDC, locator, /*replacements=*/nullptr, preparedOverload); + return getTypeOfMemberReference(choice, useDC, locator, preparedOverload); } else { - return getTypeOfReference( - choice, locator, useDC, preparedOverload); + return getTypeOfReference(choice, locator, useDC, preparedOverload); } } From c344d6b0eb77dc2f6118eb18313a453c2a385367 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 16 Sep 2025 18:14:34 -0400 Subject: [PATCH 11/18] Sema: Rename getTypeOf{Member,}ReferenceImpl() to Pre() and factor out Post() versions --- include/swift/Sema/ConstraintSystem.h | 50 +++++++------- lib/Sema/CSSimplify.cpp | 11 +-- lib/Sema/TypeCheckProtocol.cpp | 7 +- lib/Sema/TypeOfReference.cpp | 99 ++++++++++++++++----------- 4 files changed, 94 insertions(+), 73 deletions(-) diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index 25c989b7684f5..3fa280772705c 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -3795,7 +3795,7 @@ class ConstraintSystem { /// Add a constraint that binds an overload set to a specific choice. void addBindOverloadConstraint(Type boundTy, OverloadChoice choice, ConstraintLocator *locator, DeclContext *useDC) { - resolveOverload(locator, boundTy, choice, useDC, + resolveOverload(choice, useDC, locator, boundTy, /*preparedOverload=*/nullptr); } @@ -4439,13 +4439,6 @@ class ConstraintSystem { unsigned numApplies, bool isMainDispatchQueue, bool openGlobalActorType, ConstraintLocatorBuilder locator); - /// \returns The opened type and the thrown error type. - std::pair getTypeOfReferenceImpl( - OverloadChoice choice, - ConstraintLocatorBuilder locator, - DeclContext *useDC, - PreparedOverloadBuilder *preparedOverload); - /// Retrieve the type of a reference to the given value declaration. /// /// For references to polymorphic function types, this routine "opens up" @@ -4454,14 +4447,7 @@ class ConstraintSystem { /// /// \returns a description of the type of this declaration reference. DeclReferenceType getTypeOfReference( - OverloadChoice choice, - ConstraintLocatorBuilder locator, - DeclContext *useDC, - PreparedOverloadBuilder *preparedOverload); - - /// \returns the opened type and the thrown error type. - std::pair getTypeOfMemberReferenceImpl( - OverloadChoice choice, DeclContext *useDC, ConstraintLocator *locator, + OverloadChoice choice, DeclContext *useDC, ConstraintLocatorBuilder locator, PreparedOverloadBuilder *preparedOverload); /// Retrieve the type of a reference to the given value declaration, @@ -4486,6 +4472,24 @@ class ConstraintSystem { } private: + /// \returns The opened type and the thrown error type. + std::pair getTypeOfReferencePre( + OverloadChoice choice, DeclContext *useDC, ConstraintLocatorBuilder locator, + PreparedOverloadBuilder *preparedOverload); + + DeclReferenceType getTypeOfReferencePost( + OverloadChoice choice, DeclContext *useDC, ConstraintLocatorBuilder locator, + Type openedType, Type thrownErrorType); + + /// \returns the opened type and the thrown error type. + std::pair getTypeOfMemberReferencePre( + OverloadChoice choice, DeclContext *useDC, ConstraintLocator *locator, + PreparedOverloadBuilder *preparedOverload); + + DeclReferenceType getTypeOfMemberReferencePost( + OverloadChoice choice, DeclContext *useDC, ConstraintLocator *locator, + Type openedType, Type thrownErrorType); + Type getTypeOfMemberTypeReference( Type baseObjTy, TypeDecl *typeDecl, ConstraintLocator *locator, PreparedOverloadBuilder *preparedOverload); @@ -4920,17 +4924,17 @@ class ConstraintSystem { SelectedOverload choice); /// Build and allocate a prepared overload in the solver arena. - PreparedOverload *prepareOverload(ConstraintLocator *locator, - OverloadChoice choice, - DeclContext *useDC); + PreparedOverload *prepareOverload(OverloadChoice choice, + DeclContext *useDC, + ConstraintLocator *locator); /// Populate the prepared overload with all type variables and constraints /// that are to be introduced into the constraint system when this choice /// is taken. DeclReferenceType - prepareOverloadImpl(ConstraintLocator *locator, - OverloadChoice choice, + prepareOverloadImpl(OverloadChoice choice, DeclContext *useDC, + ConstraintLocator *locator, PreparedOverloadBuilder *preparedOverload); void replayChanges( @@ -4938,8 +4942,8 @@ class ConstraintSystem { PreparedOverload *preparedOverload); /// Resolve the given overload set to the given choice. - void resolveOverload(ConstraintLocator *locator, Type boundType, - OverloadChoice choice, DeclContext *useDC, + void resolveOverload(OverloadChoice choice, DeclContext *useDC, + ConstraintLocator *locator, Type boundType, PreparedOverload *preparedOverload); /// Simplify a type, by replacing type variables with either their diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index fa4ca09341de8..6fac54731c3d9 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -16742,16 +16742,17 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) { if (!preparedOverload) { if (enablePreparedOverloads && constraint.getOverloadChoice().canBePrepared()) { - preparedOverload = prepareOverload(constraint.getLocator(), - constraint.getOverloadChoice(), - constraint.getDeclContext()); + preparedOverload = prepareOverload(constraint.getOverloadChoice(), + constraint.getDeclContext(), + constraint.getLocator()); const_cast(constraint).setPreparedOverload(preparedOverload); } } - resolveOverload(constraint.getLocator(), constraint.getFirstType(), - constraint.getOverloadChoice(), + resolveOverload(constraint.getOverloadChoice(), constraint.getDeclContext(), + constraint.getLocator(), + constraint.getFirstType(), preparedOverload); return SolutionKind::Solved; } diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index d425cf7be4eb8..ba859e927e7f4 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -1208,15 +1208,14 @@ swift::matchWitness(WitnessChecker::RequirementEnvironmentCache &reqEnvCache, if (witness->getDeclContext()->isTypeContext()) { OverloadChoice witnessChoice(selfTy, witness, FunctionRefInfo::doubleBaseNameApply()); openWitnessTypeInfo = - cs->getTypeOfMemberReference(witnessChoice, dc, - witnessLocator, + cs->getTypeOfMemberReference(witnessChoice, dc, witnessLocator, /*preparedOverload=*/nullptr); } else { OverloadChoice witnessChoice(Type(), witness, FunctionRefInfo::doubleBaseNameApply()); openWitnessTypeInfo = cs->getTypeOfReference( - witnessChoice, witnessLocator, - /*useDC=*/nullptr, /*preparedOverload=*/nullptr); + witnessChoice, /*useDC=*/nullptr, witnessLocator, + /*preparedOverload=*/nullptr); } openWitnessType = openWitnessTypeInfo.adjustedReferenceType; diff --git a/lib/Sema/TypeOfReference.cpp b/lib/Sema/TypeOfReference.cpp index 73bec1508eb34..4188eaa3811e8 100644 --- a/lib/Sema/TypeOfReference.cpp +++ b/lib/Sema/TypeOfReference.cpp @@ -1109,10 +1109,10 @@ recordFixIfNeededForPlaceholderInDecl(ConstraintSystem &cs, ValueDecl *D, } std::pair -ConstraintSystem::getTypeOfReferenceImpl(OverloadChoice choice, - ConstraintLocatorBuilder locator, - DeclContext *useDC, - PreparedOverloadBuilder *preparedOverload) { +ConstraintSystem::getTypeOfReferencePre(OverloadChoice choice, + DeclContext *useDC, + ConstraintLocatorBuilder locator, + PreparedOverloadBuilder *preparedOverload) { auto *value = choice.getDecl(); ASSERT(!!preparedOverload == PreparingOverload); @@ -1237,16 +1237,10 @@ ConstraintSystem::getTypeOfReferenceImpl(OverloadChoice choice, } DeclReferenceType -ConstraintSystem::getTypeOfReference(OverloadChoice choice, - ConstraintLocatorBuilder locator, - DeclContext *useDC, - PreparedOverloadBuilder *preparedOverload) { - ASSERT(!!preparedOverload == PreparingOverload); - - Type openedType, thrownErrorType; - std::tie(openedType, thrownErrorType) = getTypeOfReferenceImpl( - choice, locator, useDC, preparedOverload); - +ConstraintSystem::getTypeOfReferencePost(OverloadChoice choice, + DeclContext *useDC, + ConstraintLocatorBuilder locator, + Type openedType, Type thrownErrorType) { auto *value = choice.getDecl(); if (value->getDeclContext()->isTypeContext() && isa(value)) { @@ -1331,7 +1325,24 @@ ConstraintSystem::getTypeOfReference(OverloadChoice choice, ClosureIsolatedByPreconcurrency{*this}); } - return { origOpenedType, openedType, origOpenedType, openedType, thrownErrorType }; + return { origOpenedType, openedType, + origOpenedType, openedType, + thrownErrorType }; +} + +DeclReferenceType +ConstraintSystem::getTypeOfReference(OverloadChoice choice, + DeclContext *useDC, + ConstraintLocatorBuilder locator, + PreparedOverloadBuilder *preparedOverload) { + ASSERT(!!preparedOverload == PreparingOverload); + + Type openedType, thrownErrorType; + std::tie(openedType, thrownErrorType) = getTypeOfReferencePre( + choice, useDC, locator, preparedOverload); + + return getTypeOfReferencePost(choice, useDC, locator, + openedType, thrownErrorType); } /// Bind type variables for archetypes that are determined from @@ -1856,7 +1867,7 @@ static FunctionType *applyOptionality(ValueDecl *value, FunctionType *fnTy) { } std::pair -ConstraintSystem::getTypeOfMemberReferenceImpl( +ConstraintSystem::getTypeOfMemberReferencePre( OverloadChoice choice, DeclContext *useDC, ConstraintLocator *locator, PreparedOverloadBuilder *preparedOverload) { @@ -2032,13 +2043,16 @@ ConstraintSystem::getTypeOfMemberReferenceImpl( return { openedType, thrownErrorType }; } -DeclReferenceType ConstraintSystem::getTypeOfMemberReference( +DeclReferenceType ConstraintSystem::getTypeOfMemberReferencePost( OverloadChoice choice, DeclContext *useDC, ConstraintLocator *locator, - PreparedOverloadBuilder *preparedOverload) { - ASSERT(!!preparedOverload == PreparingOverload); - + Type openedType, Type thrownErrorType) { auto *value = choice.getDecl(); + if (isa(value)) { + auto type = openedType->castTo()->getResult(); + return { openedType, openedType, type, type, Type() }; + } + // Figure out the instance type used for the base. Type baseTy = choice.getBaseType(); Type baseRValueTy = baseTy->getRValueType(); @@ -2048,15 +2062,6 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference( // be handled by the caller via getTypeOfReference(). ASSERT(!baseObjTy->is()); - Type openedType, thrownErrorType; - std::tie(openedType, thrownErrorType) - = getTypeOfMemberReferenceImpl(choice, useDC, locator, preparedOverload); - - if (isa(value)) { - auto type = openedType->castTo()->getResult(); - return { openedType, openedType, type, type, Type() }; - } - auto hasAppliedSelf = doesMemberRefApplyCurriedSelf(baseRValueTy, value); // Adjust the opened type for concurrency. @@ -2113,6 +2118,19 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference( return { origOpenedType, openedType, origType, type, thrownErrorType }; } +DeclReferenceType ConstraintSystem::getTypeOfMemberReference( + OverloadChoice choice, DeclContext *useDC, ConstraintLocator *locator, + PreparedOverloadBuilder *preparedOverload) { + ASSERT(!!preparedOverload == PreparingOverload); + + Type openedType, thrownErrorType; + std::tie(openedType, thrownErrorType) + = getTypeOfMemberReferencePre(choice, useDC, locator, preparedOverload); + + return getTypeOfMemberReferencePost( + choice, useDC, locator, openedType, thrownErrorType); +} + Type ConstraintSystem::getEffectiveOverloadType(ConstraintLocator *locator, const OverloadChoice &overload, bool allowMembers, @@ -2825,9 +2843,9 @@ void ConstraintSystem::replayChanges( /// FIXME: As a transitional mechanism, if preparedOverload is nullptr, this /// immediately performs all operations. DeclReferenceType -ConstraintSystem::prepareOverloadImpl(ConstraintLocator *locator, - OverloadChoice choice, +ConstraintSystem::prepareOverloadImpl(OverloadChoice choice, DeclContext *useDC, + ConstraintLocator *locator, PreparedOverloadBuilder *preparedOverload) { // If we refer to a top-level decl with special type-checking semantics, // handle it now. @@ -2842,23 +2860,23 @@ ConstraintSystem::prepareOverloadImpl(ConstraintLocator *locator, // If the base is a module type, it's an unqualified reference. if (baseTy->getMetatypeInstanceType()->is()) { - return getTypeOfReference(choice, locator, useDC, preparedOverload); + return getTypeOfReference(choice, useDC, locator, preparedOverload); } return getTypeOfMemberReference(choice, useDC, locator, preparedOverload); } else { - return getTypeOfReference(choice, locator, useDC, preparedOverload); + return getTypeOfReference(choice, useDC, locator, preparedOverload); } } -PreparedOverload *ConstraintSystem::prepareOverload(ConstraintLocator *locator, - OverloadChoice choice, - DeclContext *useDC) { +PreparedOverload *ConstraintSystem::prepareOverload(OverloadChoice choice, + DeclContext *useDC, + ConstraintLocator *locator) { ASSERT(!PreparingOverload); PreparingOverload = true; PreparedOverloadBuilder builder; - auto declRefType = prepareOverloadImpl(locator, choice, useDC, &builder); + auto declRefType = prepareOverloadImpl(choice, useDC, locator, &builder); PreparingOverload = false; @@ -2869,9 +2887,8 @@ PreparedOverload *ConstraintSystem::prepareOverload(ConstraintLocator *locator, return new (mem) PreparedOverload(declRefType, builder.Changes); } -void ConstraintSystem::resolveOverload(ConstraintLocator *locator, - Type boundType, OverloadChoice choice, - DeclContext *useDC, +void ConstraintSystem::resolveOverload(OverloadChoice choice, DeclContext *useDC, + ConstraintLocator *locator, Type boundType, PreparedOverload *preparedOverload) { // Determine the type to which we'll bind the overload set's type. Type openedType; @@ -2896,7 +2913,7 @@ void ConstraintSystem::resolveOverload(ConstraintLocator *locator, adjustedRefType = preparedOverload->getAdjustedReferenceType(); thrownErrorTypeOnAccess = preparedOverload->getThrownErrorTypeOnAccess(); } else { - auto declRefType = prepareOverloadImpl(locator, choice, useDC, nullptr); + auto declRefType = prepareOverloadImpl(choice, useDC, locator, nullptr); openedType = declRefType.openedType; adjustedOpenedType = declRefType.adjustedOpenedType; From b181fcf0fd840cfcb05c38bcb187b87794744298 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Wed, 17 Sep 2025 11:26:38 -0400 Subject: [PATCH 12/18] Sema: Get prepared overloads working again with the Pre()/Post() split --- include/swift/Sema/ConstraintSystem.h | 7 +- include/swift/Sema/PreparedOverload.h | 27 +++----- lib/Sema/TypeOfReference.cpp | 95 +++++++++++++++++---------- 3 files changed, 75 insertions(+), 54 deletions(-) diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index 3fa280772705c..e62e789d05b65 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -4931,7 +4931,12 @@ class ConstraintSystem { /// Populate the prepared overload with all type variables and constraints /// that are to be introduced into the constraint system when this choice /// is taken. - DeclReferenceType + /// + /// Returns a pair consisting of the opened type, and the thrown error type. + /// + /// FIXME: As a transitional mechanism, if preparedOverload is nullptr, this + /// immediately performs all operations. + std::pair prepareOverloadImpl(OverloadChoice choice, DeclContext *useDC, ConstraintLocator *locator, diff --git a/include/swift/Sema/PreparedOverload.h b/include/swift/Sema/PreparedOverload.h index a3253fbc351c9..19a213dc5bca6 100644 --- a/include/swift/Sema/PreparedOverload.h +++ b/include/swift/Sema/PreparedOverload.h @@ -144,38 +144,29 @@ class PreparedOverload final : using Change = PreparedOverloadChange; private: + Type OpenedType; + Type ThrownErrorType; size_t Count; - DeclReferenceType DeclType; size_t numTrailingObjects(OverloadToken) const { return Count; } public: - PreparedOverload(const DeclReferenceType &declType, ArrayRef changes) - : Count(changes.size()), DeclType(declType) { + PreparedOverload(Type openedType, Type thrownErrorType, + ArrayRef changes) + : OpenedType(openedType), ThrownErrorType(thrownErrorType), + Count(changes.size()) { std::uninitialized_copy(changes.begin(), changes.end(), getTrailingObjects()); } Type getOpenedType() const { - return DeclType.openedType; + return OpenedType; } - Type getAdjustedOpenedType() const { - return DeclType.adjustedOpenedType; - } - - Type getReferenceType() const { - return DeclType.referenceType; - } - - Type getAdjustedReferenceType() const { - return DeclType.adjustedReferenceType; - } - - Type getThrownErrorTypeOnAccess() const { - return DeclType.thrownErrorTypeOnAccess; + Type getThrownErrorType() const { + return ThrownErrorType; } ArrayRef getChanges() const { diff --git a/lib/Sema/TypeOfReference.cpp b/lib/Sema/TypeOfReference.cpp index 4188eaa3811e8..62cd83dd480b4 100644 --- a/lib/Sema/TypeOfReference.cpp +++ b/lib/Sema/TypeOfReference.cpp @@ -2625,7 +2625,7 @@ isInvalidPartialApplication(ConstraintSystem &cs, /// checking semantics, compute the type of the reference. For now, follow /// the lead of \c getTypeOfMemberReference and return a pair of /// the full opened type and the reference's type. -static DeclReferenceType getTypeOfReferenceWithSpecialTypeCheckingSemantics( +static Type getTypeOfReferenceWithSpecialTypeCheckingSemantics( ConstraintSystem &CS, ConstraintLocator *locator, DeclTypeCheckingSemantics semantics, PreparedOverloadBuilder *preparedOverload) { @@ -2654,8 +2654,7 @@ static DeclReferenceType getTypeOfReferenceWithSpecialTypeCheckingSemantics( /*isFavored=*/false, preparedOverload); // FIXME: Verify ExtInfo state is correct, not working by accident. FunctionType::ExtInfo info; - auto refType = FunctionType::get({inputArg}, output, info); - return {refType, refType, refType, refType, Type()}; + return FunctionType::get({inputArg}, output, info); } case DeclTypeCheckingSemantics::WithoutActuallyEscaping: { // Proceed with a "WithoutActuallyEscaping" operation. The body closure @@ -2702,14 +2701,13 @@ static DeclReferenceType getTypeOfReferenceWithSpecialTypeCheckingSemantics( withoutEscapingIsolation = FunctionTypeIsolation::forNonIsolatedCaller(); } - auto refType = FunctionType::get(args, result, - FunctionType::ExtInfoBuilder() - .withNoEscape(false) - .withIsolation(withoutEscapingIsolation) - .withAsync(true) - .withThrows(true, thrownError) - .build()); - return {refType, refType, refType, refType, Type()}; + return FunctionType::get(args, result, + FunctionType::ExtInfoBuilder() + .withNoEscape(false) + .withIsolation(withoutEscapingIsolation) + .withAsync(true) + .withThrows(true, thrownError) + .build()); } case DeclTypeCheckingSemantics::OpenExistential: { // The body closure receives a freshly-opened archetype constrained by the @@ -2755,14 +2753,13 @@ static DeclReferenceType getTypeOfReferenceWithSpecialTypeCheckingSemantics( openExistentialIsolation = FunctionTypeIsolation::forNonIsolatedCaller(); } - auto refType = FunctionType::get(args, result, - FunctionType::ExtInfoBuilder() - .withNoEscape(false) - .withThrows(true, thrownError) - .withIsolation(openExistentialIsolation) - .withAsync(true) - .build()); - return {refType, refType, refType, refType, Type()}; + return FunctionType::get(args, result, + FunctionType::ExtInfoBuilder() + .withNoEscape(false) + .withThrows(true, thrownError) + .withIsolation(openExistentialIsolation) + .withAsync(true) + .build()); } } @@ -2840,9 +2837,11 @@ void ConstraintSystem::replayChanges( /// that are to be introduced into the constraint system when this choice /// is taken. /// +/// Returns a pair consisting of the opened type, and the thrown error type. +/// /// FIXME: As a transitional mechanism, if preparedOverload is nullptr, this /// immediately performs all operations. -DeclReferenceType +std::pair ConstraintSystem::prepareOverloadImpl(OverloadChoice choice, DeclContext *useDC, ConstraintLocator *locator, @@ -2852,20 +2851,21 @@ ConstraintSystem::prepareOverloadImpl(OverloadChoice choice, auto semantics = TypeChecker::getDeclTypeCheckingSemantics(choice.getDecl()); if (semantics != DeclTypeCheckingSemantics::Normal) { - return getTypeOfReferenceWithSpecialTypeCheckingSemantics( + auto openedType = getTypeOfReferenceWithSpecialTypeCheckingSemantics( *this, locator, semantics, preparedOverload); + return {openedType, Type()}; } else if (auto baseTy = choice.getBaseType()) { // Retrieve the type of a reference to the specific declaration choice. assert(!baseTy->hasTypeParameter()); // If the base is a module type, it's an unqualified reference. if (baseTy->getMetatypeInstanceType()->is()) { - return getTypeOfReference(choice, useDC, locator, preparedOverload); + return getTypeOfReferencePre(choice, useDC, locator, preparedOverload); } - return getTypeOfMemberReference(choice, useDC, locator, preparedOverload); + return getTypeOfMemberReferencePre(choice, useDC, locator, preparedOverload); } else { - return getTypeOfReference(choice, useDC, locator, preparedOverload); + return getTypeOfReferencePre(choice, useDC, locator, preparedOverload); } } @@ -2876,7 +2876,10 @@ PreparedOverload *ConstraintSystem::prepareOverload(OverloadChoice choice, PreparingOverload = true; PreparedOverloadBuilder builder; - auto declRefType = prepareOverloadImpl(choice, useDC, locator, &builder); + Type openedType; + Type thrownErrorType; + std::tie(openedType, thrownErrorType) = prepareOverloadImpl( + choice, useDC, locator, &builder); PreparingOverload = false; @@ -2884,7 +2887,7 @@ PreparedOverload *ConstraintSystem::prepareOverload(OverloadChoice choice, auto size = PreparedOverload::totalSizeToAlloc(count); auto mem = Allocator.Allocate(size, alignof(PreparedOverload)); - return new (mem) PreparedOverload(declRefType, builder.Changes); + return new (mem) PreparedOverload(openedType, thrownErrorType, builder.Changes); } void ConstraintSystem::resolveOverload(OverloadChoice choice, DeclContext *useDC, @@ -2895,7 +2898,7 @@ void ConstraintSystem::resolveOverload(OverloadChoice choice, DeclContext *useDC Type adjustedOpenedType; Type refType; Type adjustedRefType; - Type thrownErrorTypeOnAccess; + Type thrownErrorType; switch (choice.getKind()) { case OverloadChoiceKind::Decl: @@ -2908,18 +2911,40 @@ void ConstraintSystem::resolveOverload(OverloadChoice choice, DeclContext *useDC replayChanges(locator, preparedOverload); openedType = preparedOverload->getOpenedType(); - adjustedOpenedType = preparedOverload->getAdjustedOpenedType(); - refType = preparedOverload->getReferenceType(); - adjustedRefType = preparedOverload->getAdjustedReferenceType(); - thrownErrorTypeOnAccess = preparedOverload->getThrownErrorTypeOnAccess(); + thrownErrorType = preparedOverload->getThrownErrorType(); } else { - auto declRefType = prepareOverloadImpl(choice, useDC, locator, nullptr); + std::tie(openedType, thrownErrorType) = prepareOverloadImpl( + choice, useDC, locator, nullptr); + } + + auto semantics = + TypeChecker::getDeclTypeCheckingSemantics(choice.getDecl()); + if (semantics != DeclTypeCheckingSemantics::Normal) { + adjustedOpenedType = openedType; + refType = openedType; + adjustedRefType = openedType; + } else { + DeclReferenceType declRefType; + + if (auto baseTy = choice.getBaseType()) { + // If the base is a module type, it's an unqualified reference. + if (baseTy->getMetatypeInstanceType()->is()) { + declRefType = getTypeOfReferencePost( + choice, useDC, locator, openedType, thrownErrorType); + } else { + declRefType = getTypeOfMemberReferencePost( + choice, useDC, locator, openedType, thrownErrorType); + } + } else { + declRefType = getTypeOfReferencePost( + choice, useDC, locator, openedType, thrownErrorType); + } openedType = declRefType.openedType; adjustedOpenedType = declRefType.adjustedOpenedType; refType = declRefType.referenceType; adjustedRefType = declRefType.adjustedReferenceType; - thrownErrorTypeOnAccess = declRefType.thrownErrorTypeOnAccess; + thrownErrorType = declRefType.thrownErrorTypeOnAccess; } break; @@ -3110,9 +3135,9 @@ void ConstraintSystem::resolveOverload(OverloadChoice choice, DeclContext *useDC // If accessing this declaration could throw an error, record this as a // potential throw site. - if (thrownErrorTypeOnAccess) { + if (thrownErrorType) { recordPotentialThrowSite( - PotentialThrowSite::PropertyAccess, thrownErrorTypeOnAccess, locator); + PotentialThrowSite::PropertyAccess, thrownErrorType, locator); } // Note that we have resolved this overload. From a12c160d0b61218426d9468585af303caae076ce Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Wed, 17 Sep 2025 12:02:46 -0400 Subject: [PATCH 13/18] Sema: Replace calls to OverloadChoice constructor with two overloads of getDecl() --- include/swift/Sema/OverloadChoice.h | 23 +++++++++++++++++++---- lib/Sema/CSDiagnostics.cpp | 15 ++++++++------- lib/Sema/CSGen.cpp | 18 +++++++++--------- lib/Sema/CSSimplify.cpp | 13 +++++++------ lib/Sema/TypeCheckProtocol.cpp | 9 ++++++--- 5 files changed, 49 insertions(+), 29 deletions(-) diff --git a/include/swift/Sema/OverloadChoice.h b/include/swift/Sema/OverloadChoice.h index b86d736368c5d..e1b4f0643b2f4 100644 --- a/include/swift/Sema/OverloadChoice.h +++ b/include/swift/Sema/OverloadChoice.h @@ -126,20 +126,19 @@ class OverloadChoice { /// FIXME: This needs three bits. Can we pack them somewhere? FunctionRefInfo TheFunctionRefInfo = FunctionRefInfo::unappliedBaseName(); -public: - OverloadChoice() : BaseAndDeclKind(nullptr, 0), DeclOrKind() {} - OverloadChoice(Type base, ValueDecl *value, FunctionRefInfo functionRefInfo) : BaseAndDeclKind(base, 0), TheFunctionRefInfo(functionRefInfo) { - assert(!base || !base->hasTypeParameter()); assert((reinterpret_cast(value) & (uintptr_t)0x03) == 0 && "Badly aligned decl"); DeclOrKind = value; } +public: + OverloadChoice() : BaseAndDeclKind(nullptr, 0), DeclOrKind() {} + OverloadChoice(Type base, OverloadChoiceKind kind) : BaseAndDeclKind(base, 0), DeclOrKind(uint32_t(kind)) { assert(base && "Must have a base type for overload choice"); @@ -162,6 +161,22 @@ class OverloadChoice { BaseAndDeclKind.getInt() == 0 && DeclOrKind.isNull(); } + /// Retrieve an overload choice for a declaration that was found via + /// unqualified lookup. + static OverloadChoice getDecl(ValueDecl *value, + FunctionRefInfo functionRefInfo) { + return OverloadChoice(Type(), value, functionRefInfo); + } + + + /// Retrieve an overload choice for a declaration that was found via + /// qualified lookup. + static OverloadChoice getDecl(Type base, ValueDecl *value, + FunctionRefInfo functionRefInfo) { + ASSERT(!base->hasTypeParameter()); + return OverloadChoice(base, value, functionRefInfo); + } + /// Retrieve an overload choice for a declaration that was found via /// dynamic lookup. static OverloadChoice getDeclViaDynamic(Type base, ValueDecl *value, diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 2a8b50dc1a9fc..c4e76f309168b 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -2465,9 +2465,10 @@ AssignmentFailure::resolveImmutableBase(Expr *expr) const { const auto &declRef = SE->getDecl(); if (auto *subscript = dyn_cast_or_null(declRef.getDecl())) { - if (isImmutable(subscript)) - return {expr, OverloadChoice(getType(SE->getBase()), subscript, - FunctionRefInfo::doubleBaseNameApply())}; + if (isImmutable(subscript)) { + return {expr, OverloadChoice::getDecl(getType(SE->getBase()), subscript, + FunctionRefInfo::doubleBaseNameApply())}; + } } } @@ -2522,8 +2523,8 @@ AssignmentFailure::resolveImmutableBase(Expr *expr) const { // If the member isn't settable, then it is the problem: return it. if (auto member = dyn_cast(MRE->getMember().getDecl())) if (isImmutable(member)) - return {expr, OverloadChoice(getType(MRE->getBase()), member, - FunctionRefInfo::singleBaseNameApply())}; + return {expr, OverloadChoice::getDecl(getType(MRE->getBase()), member, + FunctionRefInfo::singleBaseNameApply())}; // If we weren't able to resolve a member or if it is mutable, then the // problem must be with the base, recurse. @@ -2543,8 +2544,8 @@ AssignmentFailure::resolveImmutableBase(Expr *expr) const { } if (auto *DRE = dyn_cast(expr)) - return {expr, OverloadChoice(Type(), DRE->getDecl(), - FunctionRefInfo::unappliedBaseName())}; + return {expr, OverloadChoice::getDecl(DRE->getDecl(), + FunctionRefInfo::unappliedBaseName())}; // Look through x! if (auto *FVE = dyn_cast(expr)) diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 7bf1eb08330d1..4b88be5bbf36f 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -1020,7 +1020,7 @@ namespace { options); SmallVector outerChoices; for (auto decl : outerAlternatives) { - outerChoices.push_back(OverloadChoice(Type(), decl, functionRefInfo)); + outerChoices.push_back(OverloadChoice::getDecl(decl, functionRefInfo)); } CS.addValueMemberConstraint( baseTy, name, tv, CurDC, functionRefInfo, outerChoices, @@ -1044,8 +1044,8 @@ namespace { auto tv = CS.createTypeVariable(memberLocator, TVO_CanBindToLValue | TVO_CanBindToNoEscape); - OverloadChoice choice = - OverloadChoice(CS.getType(base), decl, functionRefInfo); + auto choice = + OverloadChoice::getDecl(CS.getType(base), decl, functionRefInfo); auto locator = CS.getConstraintLocator(expr, ConstraintLocator::Member); CS.addBindOverloadConstraint(tv, choice, locator, CurDC); @@ -1162,7 +1162,7 @@ namespace { // a known subscript here. This might be cleaner if we split off a new // UnresolvedSubscriptExpr from SubscriptExpr. if (auto decl = declOrNull) { - OverloadChoice choice = OverloadChoice( + auto choice = OverloadChoice::getDecl( baseTy, decl, FunctionRefInfo::doubleBaseNameApply()); CS.addBindOverloadConstraint(memberTy, choice, memberLocator, CurDC); @@ -1657,8 +1657,8 @@ namespace { // resolve it. This records the overload for use later. auto tv = CS.createTypeVariable(locator, options); - OverloadChoice choice = - OverloadChoice(Type(), E->getDecl(), E->getFunctionRefInfo()); + auto choice = + OverloadChoice::getDecl(E->getDecl(), E->getFunctionRefInfo()); CS.addBindOverloadConstraint(tv, choice, locator, CurDC); return tv; } @@ -1775,8 +1775,8 @@ namespace { if (decls[i]->isInvalid()) continue; - OverloadChoice choice = - OverloadChoice(Type(), decls[i], expr->getFunctionRefInfo()); + auto choice = + OverloadChoice::getDecl(decls[i], expr->getFunctionRefInfo()); choices.push_back(choice); } @@ -4120,7 +4120,7 @@ namespace { // logic. if (result->isInvalid()) continue; - OverloadChoice choice = OverloadChoice(Type(), result, functionRefInfo); + auto choice = OverloadChoice::getDecl(result, functionRefInfo); choices.push_back(choice); } diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 6fac54731c3d9..976138a71b4f3 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -10491,8 +10491,8 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, auto choice = instanceTy->isAnyObject() ? candidate - : OverloadChoice(instanceTy, decl, - FunctionRefInfo::singleBaseNameApply()); + : OverloadChoice::getDecl(instanceTy, decl, + FunctionRefInfo::singleBaseNameApply()); const bool invalidMethodRef = isa(decl) && !hasInstanceMethods; const bool invalidMemberRef = !isa(decl) && !hasInstanceMembers; @@ -10727,7 +10727,7 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, } } - return OverloadChoice(baseTy, cand, functionRefInfo); + return OverloadChoice::getDecl(baseTy, cand, functionRefInfo); }; // Add all results from this lookup. @@ -11866,7 +11866,8 @@ ConstraintSystem::simplifyValueWitnessConstraint( if (!witness) return fail(); - auto choice = OverloadChoice(resolvedBaseType, witness.getDecl(), functionRefInfo); + auto choice = OverloadChoice::getDecl( + resolvedBaseType, witness.getDecl(), functionRefInfo); addBindOverloadConstraint(memberType, choice, getConstraintLocator(locator), useDC); return SolutionKind::Solved; @@ -14110,8 +14111,8 @@ ConstraintSystem::simplifyDynamicCallableApplicableFnConstraint( SmallVector choices; for (auto candidate : candidates) { if (candidate->isInvalid()) continue; - choices.push_back(OverloadChoice(type2, candidate, - FunctionRefInfo::singleBaseNameApply())); + choices.push_back(OverloadChoice::getDecl(type2, candidate, + FunctionRefInfo::singleBaseNameApply())); } if (choices.empty()) { diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index ba859e927e7f4..3f5b32c24845b 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -1170,7 +1170,8 @@ swift::matchWitness(WitnessChecker::RequirementEnvironmentCache &reqEnvCache, // Open up the type of the requirement. reqLocator = cs->getConstraintLocator(req, ConstraintLocator::ProtocolRequirement); - OverloadChoice reqChoice(selfTy, req, FunctionRefInfo::doubleBaseNameApply()); + auto reqChoice = OverloadChoice::getDecl( + selfTy, req, FunctionRefInfo::doubleBaseNameApply()); auto reqTypeInfo = cs->getTypeOfMemberReference(reqChoice, dc, reqLocator, /*preparedOverload=*/nullptr); @@ -1206,12 +1207,14 @@ swift::matchWitness(WitnessChecker::RequirementEnvironmentCache &reqEnvCache, DeclReferenceType openWitnessTypeInfo; if (witness->getDeclContext()->isTypeContext()) { - OverloadChoice witnessChoice(selfTy, witness, FunctionRefInfo::doubleBaseNameApply()); + auto witnessChoice = OverloadChoice::getDecl( + selfTy, witness, FunctionRefInfo::doubleBaseNameApply()); openWitnessTypeInfo = cs->getTypeOfMemberReference(witnessChoice, dc, witnessLocator, /*preparedOverload=*/nullptr); } else { - OverloadChoice witnessChoice(Type(), witness, FunctionRefInfo::doubleBaseNameApply()); + auto witnessChoice = OverloadChoice::getDecl( + witness, FunctionRefInfo::doubleBaseNameApply()); openWitnessTypeInfo = cs->getTypeOfReference( witnessChoice, /*useDC=*/nullptr, witnessLocator, From 8744e8a3a09890566b6301f183db6f1284ee6bc6 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Wed, 17 Sep 2025 12:18:00 -0400 Subject: [PATCH 14/18] Sema: Sink ModuleDecl handling back down into getTypeOfMemberReferencePre/Post() --- lib/Sema/TypeOfReference.cpp | 43 ++++++++++++++---------------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/lib/Sema/TypeOfReference.cpp b/lib/Sema/TypeOfReference.cpp index 62cd83dd480b4..f6fa9e6875296 100644 --- a/lib/Sema/TypeOfReference.cpp +++ b/lib/Sema/TypeOfReference.cpp @@ -1883,6 +1883,10 @@ ConstraintSystem::getTypeOfMemberReferencePre( Type baseRValueTy = baseTy->getRValueType(); auto baseObjTy = baseRValueTy->getMetatypeInstanceType(); + if (baseObjTy->is()) { + return getTypeOfReferencePre(choice, useDC, locator, preparedOverload); + } + Type openedType; Type thrownErrorType; @@ -2048,19 +2052,20 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReferencePost( Type openedType, Type thrownErrorType) { auto *value = choice.getDecl(); - if (isa(value)) { - auto type = openedType->castTo()->getResult(); - return { openedType, openedType, type, type, Type() }; - } - // Figure out the instance type used for the base. Type baseTy = choice.getBaseType(); Type baseRValueTy = baseTy->getRValueType(); Type baseObjTy = baseRValueTy->getMetatypeInstanceType(); - // A reference to a module member is really unqualified, and should - // be handled by the caller via getTypeOfReference(). - ASSERT(!baseObjTy->is()); + if (baseObjTy->is()) { + return getTypeOfReferencePost(choice, useDC, locator, + openedType, thrownErrorType); + } + + if (isa(value)) { + auto type = openedType->castTo()->getResult(); + return { openedType, openedType, type, type, Type() }; + } auto hasAppliedSelf = doesMemberRefApplyCurriedSelf(baseRValueTy, value); @@ -2854,15 +2859,7 @@ ConstraintSystem::prepareOverloadImpl(OverloadChoice choice, auto openedType = getTypeOfReferenceWithSpecialTypeCheckingSemantics( *this, locator, semantics, preparedOverload); return {openedType, Type()}; - } else if (auto baseTy = choice.getBaseType()) { - // Retrieve the type of a reference to the specific declaration choice. - assert(!baseTy->hasTypeParameter()); - - // If the base is a module type, it's an unqualified reference. - if (baseTy->getMetatypeInstanceType()->is()) { - return getTypeOfReferencePre(choice, useDC, locator, preparedOverload); - } - + } else if (choice.getBaseType()) { return getTypeOfMemberReferencePre(choice, useDC, locator, preparedOverload); } else { return getTypeOfReferencePre(choice, useDC, locator, preparedOverload); @@ -2926,15 +2923,9 @@ void ConstraintSystem::resolveOverload(OverloadChoice choice, DeclContext *useDC } else { DeclReferenceType declRefType; - if (auto baseTy = choice.getBaseType()) { - // If the base is a module type, it's an unqualified reference. - if (baseTy->getMetatypeInstanceType()->is()) { - declRefType = getTypeOfReferencePost( - choice, useDC, locator, openedType, thrownErrorType); - } else { - declRefType = getTypeOfMemberReferencePost( - choice, useDC, locator, openedType, thrownErrorType); - } + if (choice.getBaseType()) { + declRefType = getTypeOfMemberReferencePost( + choice, useDC, locator, openedType, thrownErrorType); } else { declRefType = getTypeOfReferencePost( choice, useDC, locator, openedType, thrownErrorType); From ad324b7c43e054f0b83f2e0e69951ab96fc1d0c0 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Wed, 17 Sep 2025 12:25:33 -0400 Subject: [PATCH 15/18] Sema: Clean up ConstraintSystem::resolveOverload() a bit --- lib/Sema/TypeOfReference.cpp | 78 ++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/lib/Sema/TypeOfReference.cpp b/lib/Sema/TypeOfReference.cpp index f6fa9e6875296..37363a602209e 100644 --- a/lib/Sema/TypeOfReference.cpp +++ b/lib/Sema/TypeOfReference.cpp @@ -2891,11 +2891,7 @@ void ConstraintSystem::resolveOverload(OverloadChoice choice, DeclContext *useDC ConstraintLocator *locator, Type boundType, PreparedOverload *preparedOverload) { // Determine the type to which we'll bind the overload set's type. - Type openedType; - Type adjustedOpenedType; - Type refType; - Type adjustedRefType; - Type thrownErrorType; + DeclReferenceType declRefType; switch (choice.getKind()) { case OverloadChoiceKind::Decl: @@ -2904,6 +2900,8 @@ void ConstraintSystem::resolveOverload(OverloadChoice choice, DeclContext *useDC case OverloadChoiceKind::DeclViaUnwrappedOptional: case OverloadChoiceKind::DynamicMemberLookup: case OverloadChoiceKind::KeyPathDynamicMemberLookup: { + Type openedType, thrownErrorType; + if (preparedOverload) { replayChanges(locator, preparedOverload); @@ -2917,12 +2915,12 @@ void ConstraintSystem::resolveOverload(OverloadChoice choice, DeclContext *useDC auto semantics = TypeChecker::getDeclTypeCheckingSemantics(choice.getDecl()); if (semantics != DeclTypeCheckingSemantics::Normal) { - adjustedOpenedType = openedType; - refType = openedType; - adjustedRefType = openedType; + declRefType.openedType = openedType; + declRefType.adjustedOpenedType = openedType; + declRefType.referenceType = openedType; + declRefType.adjustedReferenceType = openedType; + declRefType.thrownErrorTypeOnAccess = thrownErrorType; } else { - DeclReferenceType declRefType; - if (choice.getBaseType()) { declRefType = getTypeOfMemberReferencePost( choice, useDC, locator, openedType, thrownErrorType); @@ -2930,12 +2928,6 @@ void ConstraintSystem::resolveOverload(OverloadChoice choice, DeclContext *useDC declRefType = getTypeOfReferencePost( choice, useDC, locator, openedType, thrownErrorType); } - - openedType = declRefType.openedType; - adjustedOpenedType = declRefType.adjustedOpenedType; - refType = declRefType.referenceType; - adjustedRefType = declRefType.adjustedReferenceType; - thrownErrorType = declRefType.thrownErrorTypeOnAccess; } break; @@ -2945,14 +2937,16 @@ void ConstraintSystem::resolveOverload(OverloadChoice choice, DeclContext *useDC if (auto lvalueTy = choice.getBaseType()->getAs()) { // When the base of a tuple lvalue, the member is always an lvalue. auto tuple = lvalueTy->getObjectType()->castTo(); - adjustedRefType = tuple->getElementType(choice.getTupleIndex())->getRValueType(); - adjustedRefType = LValueType::get(adjustedRefType); + declRefType.adjustedReferenceType = + LValueType::get( + tuple->getElementType(choice.getTupleIndex())->getRValueType()); } else { // When the base is a tuple rvalue, the member is always an rvalue. auto tuple = choice.getBaseType()->castTo(); - adjustedRefType = tuple->getElementType(choice.getTupleIndex())->getRValueType(); + declRefType.adjustedReferenceType = + tuple->getElementType(choice.getTupleIndex())->getRValueType(); } - refType = adjustedRefType; + declRefType.referenceType = declRefType.adjustedReferenceType; break; case OverloadChoiceKind::MaterializePack: { @@ -2962,18 +2956,18 @@ void ConstraintSystem::resolveOverload(OverloadChoice choice, DeclContext *useDC // In the future, _if_ the syntax allows for multiple expansions // this code would have to be adjusted to project l-value from the // base type just like TupleIndex does. - adjustedRefType = + declRefType.adjustedReferenceType = getPatternTypeOfSingleUnlabeledPackExpansionTuple(choice.getBaseType()); - refType = adjustedRefType; + declRefType.referenceType = declRefType.adjustedReferenceType; break; } case OverloadChoiceKind::ExtractFunctionIsolation: { // The type of `.isolation` is `(any Actor)?` auto actor = getASTContext().getProtocol(KnownProtocolKind::Actor); - adjustedRefType = + declRefType.adjustedReferenceType = OptionalType::get(actor->getDeclaredExistentialType()); - refType = adjustedRefType; + declRefType.referenceType = declRefType.adjustedReferenceType; break; } @@ -3004,11 +2998,11 @@ void ConstraintSystem::resolveOverload(OverloadChoice choice, DeclContext *useDC // FIXME: Verify ExtInfo state is correct, not working by accident. FunctionType::ExtInfo fullInfo; auto fullTy = FunctionType::get({baseParam}, subscriptTy, fullInfo); - openedType = fullTy; - adjustedOpenedType = fullTy; + declRefType.openedType = fullTy; + declRefType.adjustedOpenedType = fullTy; // FIXME: @preconcurrency - refType = subscriptTy; - adjustedRefType = subscriptTy; + declRefType.referenceType = subscriptTy; + declRefType.adjustedReferenceType = subscriptTy; // Increase the score so that actual subscripts get preference. // ...except if we're solving for code completion and the index expression @@ -3021,8 +3015,9 @@ void ConstraintSystem::resolveOverload(OverloadChoice choice, DeclContext *useDC break; } } - assert(!refType->hasTypeParameter() && "Cannot have a dependent type here"); - assert(!adjustedRefType->hasTypeParameter() && + assert(!declRefType.referenceType->hasTypeParameter() && + "Cannot have a dependent type here"); + assert(!declRefType.adjustedReferenceType->hasTypeParameter() && "Cannot have a dependent type here"); if (auto *decl = choice.getDeclOrNull()) { @@ -3042,7 +3037,7 @@ void ConstraintSystem::resolveOverload(OverloadChoice choice, DeclContext *useDC if (locator->isResultOfKeyPathDynamicMemberLookup() || locator->isKeyPathSubscriptComponent()) { // Subscript type has a format of (Self[.Type) -> (Arg...) -> Result - auto declTy = adjustedOpenedType->castTo(); + auto declTy = declRefType.adjustedOpenedType->castTo(); auto subscriptTy = declTy->getResult()->castTo(); // If we have subscript, each of the arguments has to conform to // Hashable, because it would be used as a component inside key path. @@ -3114,7 +3109,7 @@ void ConstraintSystem::resolveOverload(OverloadChoice choice, DeclContext *useDC // The default type of the #isolation builtin macro is `(any Actor)?` if (macro->getBuiltinKind() == BuiltinMacroKind::IsolationMacro) { - auto *fnType = openedType->getAs(); + auto *fnType = declRefType.openedType->getAs(); auto actor = getASTContext().getProtocol(KnownProtocolKind::Actor); addConstraint( ConstraintKind::Defaultable, fnType->getResult(), @@ -3126,14 +3121,20 @@ void ConstraintSystem::resolveOverload(OverloadChoice choice, DeclContext *useDC // If accessing this declaration could throw an error, record this as a // potential throw site. - if (thrownErrorType) { + if (declRefType.thrownErrorTypeOnAccess) { recordPotentialThrowSite( - PotentialThrowSite::PropertyAccess, thrownErrorType, locator); + PotentialThrowSite::PropertyAccess, + declRefType.thrownErrorTypeOnAccess, + locator); } // Note that we have resolved this overload. auto overload = SelectedOverload{ - choice, openedType, adjustedOpenedType, refType, adjustedRefType, + choice, + declRefType.openedType, + declRefType.adjustedOpenedType, + declRefType.referenceType, + declRefType.adjustedReferenceType, boundType}; recordResolvedOverload(locator, overload); @@ -3149,7 +3150,7 @@ void ConstraintSystem::resolveOverload(OverloadChoice choice, DeclContext *useDC log << "(overload set choice binding "; boundType->print(log, PO); log << " := "; - adjustedRefType->print(log, PO); + declRefType.adjustedReferenceType->print(log, PO); auto openedAtLoc = getOpenedTypes(locator); if (!openedAtLoc.empty()) { @@ -3181,8 +3182,9 @@ void ConstraintSystem::resolveOverload(OverloadChoice choice, DeclContext *useDC OverloadChoiceKind::DeclViaDynamic)) { // Strip curried 'self' parameters. - auto fromTy = openedType->castTo()->getResult(); - auto toTy = refType; + auto fromTy = declRefType.openedType + ->castTo()->getResult(); + auto toTy = declRefType.referenceType; if (!doesMemberRefApplyCurriedSelf(baseTy, decl)) { toTy = toTy->castTo()->getResult(); } From 9dea72579adb33ffd44e09b4c15f8d4487fd1f5a Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Wed, 17 Sep 2025 23:19:12 -0400 Subject: [PATCH 16/18] Sema: Record ASTNode type changes in PreparedOverload Also, move some methods from ConstraintSystem.h to ConstraintSystem.cpp. --- include/swift/Sema/ConstraintSystem.h | 88 ++++++--------------------- include/swift/Sema/PreparedOverload.h | 23 ++++++- lib/Sema/CSGen.cpp | 6 +- lib/Sema/ConstraintSystem.cpp | 67 ++++++++++++++++++++ lib/Sema/TypeOfReference.cpp | 4 ++ 5 files changed, 115 insertions(+), 73 deletions(-) diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index e62e789d05b65..0ea70a2421b27 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -3068,7 +3068,7 @@ class ConstraintSystem { return nullptr; } - TypeBase* getFavoredType(Expr *E) { + TypeBase *getFavoredType(Expr *E) { assert(E != nullptr); return this->FavoredTypes[E]; } @@ -3082,39 +3082,15 @@ class ConstraintSystem { /// /// The side tables are used through the expression type checker to avoid /// mutating nodes until we know we have successfully type-checked them. - void setType(ASTNode node, Type type) { - ASSERT(!node.isNull() && "Cannot set type information on null node"); - ASSERT(type && "Expected non-null type"); - - // Record the type. - Type &entry = NodeTypes[node]; - Type oldType = entry; - entry = type; - - if (oldType.getPointer() != type.getPointer()) { - // Record the fact that we assigned a type to this node. - if (solverState) - recordChange(SolverTrail::Change::RecordedNodeType(node, oldType)); - } - } + void setType(ASTNode node, Type type, + PreparedOverloadBuilder *preparedOverload=nullptr); /// Undo the above change. - void restoreType(ASTNode node, Type oldType) { - ASSERT(!node.isNull() && "Cannot set type information on null node"); - - if (oldType) { - auto found = NodeTypes.find(node); - ASSERT(found != NodeTypes.end()); - found->second = oldType; - } else { - bool erased = NodeTypes.erase(node); - ASSERT(erased); - } - } + void restoreType(ASTNode node, Type oldType); /// Check to see if we have a type for a node. bool hasType(ASTNode node) const { - assert(!node.isNull() && "Expected non-null node"); + ASSERT(!node.isNull() && "Expected non-null node"); return NodeTypes.count(node) > 0; } @@ -3122,55 +3098,30 @@ class ConstraintSystem { /// map is used throughout the expression type checker in order to /// avoid mutating expressions until we know we have successfully /// type-checked them. - void setType(const KeyPathExpr *KP, unsigned I, Type T) { - ASSERT(KP && "Expected non-null key path parameter!"); - ASSERT(T && "Expected non-null type!"); + void setType(const KeyPathExpr *KP, unsigned I, Type T); - Type &entry = KeyPathComponentTypes[{KP, I}]; - Type oldType = entry; - entry = T; - - if (oldType.getPointer() != T.getPointer()) { - if (solverState) { - recordChange( - SolverTrail::Change::RecordedKeyPathComponentType( - KP, I, oldType)); - } - } - } - - void restoreType(const KeyPathExpr *KP, unsigned I, Type T) { - ASSERT(KP && "Expected non-null key path parameter!"); - - if (T) { - auto found = KeyPathComponentTypes.find({KP, I}); - ASSERT(found != KeyPathComponentTypes.end()); - found->second = T; - } else { - bool erased = KeyPathComponentTypes.erase({KP, I}); - ASSERT(erased); - } - } + void restoreType(const KeyPathExpr *KP, unsigned I, Type T); bool hasType(const KeyPathExpr *KP, unsigned I) const { - assert(KP && "Expected non-null key path parameter!"); + ASSERT(KP && "Expected non-null key path parameter!"); return KeyPathComponentTypes.find(std::make_pair(KP, I)) != KeyPathComponentTypes.end(); } /// Get the type for an node. Type getType(ASTNode node) const { - assert(hasType(node) && "Expected type to have been set!"); - // FIXME: lvalue differences - // assert((!E->getType() || - // E->getType()->isEqual(ExprTypes.find(E)->second)) && - // "Mismatched types!"); - return NodeTypes.find(node)->second; + ASSERT(!node.isNull() && "Expected non-null node"); + auto found = NodeTypes.find(node); + ASSERT(found != NodeTypes.end() && "Expected type to have been set!"); + return found->second; } Type getType(const KeyPathExpr *KP, unsigned I) const { - assert(hasType(KP, I) && "Expected type to have been set!"); - return KeyPathComponentTypes.find(std::make_pair(KP, I))->second; + ASSERT(KP && "Expected non-null key path parameter!"); + auto found = KeyPathComponentTypes.find(std::make_pair(KP, I)); + ASSERT(found != KeyPathComponentTypes.end() && + "Expected type to have been set!"); + return found->second; } /// Retrieve the type of the node, if known. @@ -3182,11 +3133,6 @@ class ConstraintSystem { return known->second; } - /// Retrieve type of the given declaration to be used in - /// constraint system, this is better than calling `getType()` - /// directly because it accounts of constraint system flags. - Type getVarType(const VarDecl *var); - /// Cache the type of the expression argument and return that same /// argument. template diff --git a/include/swift/Sema/PreparedOverload.h b/include/swift/Sema/PreparedOverload.h index 19a213dc5bca6..0d678214a6126 100644 --- a/include/swift/Sema/PreparedOverload.h +++ b/include/swift/Sema/PreparedOverload.h @@ -88,7 +88,10 @@ struct PreparedOverloadChange { AppliedPropertyWrapper, /// A fix was recorded because a property wrapper application failed. - AddedFix + AddedFix, + + /// The type of an AST node was changed. + RecordedNodeType }; /// The kind of change. @@ -132,7 +135,17 @@ struct PreparedOverloadChange { ConstraintFix *TheFix; unsigned Impact; } Fix; + + /// For ChangeKind::RecordedNodeType. + struct { + ASTNode Node; + Type TheType; + } Node; }; + + PreparedOverloadChange() + : Kind(ChangeKind::AddedTypeVariable), + TypeVar(nullptr) { } }; /// A "pre-cooked" representation of all type variables and constraints @@ -238,6 +251,14 @@ struct PreparedOverloadBuilder { change.Fix.Impact = impact; Changes.push_back(change); } + + void recordedNodeType(ASTNode node, Type type) { + PreparedOverload::Change change; + change.Kind = PreparedOverload::Change::RecordedNodeType; + change.Node.Node = node; + change.Node.TheType = type; + Changes.push_back(change); + } }; } // end namespace constraints diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 4b88be5bbf36f..56ce4b28d47e9 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -2811,6 +2811,9 @@ namespace { // interface type request via `var->getType()` that would // attempt to validate `weak` attribute, and produce a // diagnostic in the middle of the solver path. + // + // FIXME: getVarType() is now gone. Is the above still + // relevant? CS.addConstraint(ConstraintKind::OneWayEqual, oneWayVarType, varType, locator); @@ -5241,7 +5244,8 @@ ConstraintSystem::applyPropertyWrapperToParameter( locator, /*isFavored=*/false, preparedOverload); - setType(param->getPropertyWrapperWrappedValueVar(), wrappedValueType); + setType(param->getPropertyWrapperWrappedValueVar(), wrappedValueType, + preparedOverload); applyPropertyWrapper(anchor, { wrapperType, PropertyWrapperInitKind::WrappedValue }, diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index d0e9af4696d26..be0e39b0ba047 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -905,6 +905,73 @@ ConstraintLocator *ConstraintSystem::getOpenOpaqueLocator( { LocatorPathElt::OpenedOpaqueArchetype(opaqueDecl) }, 0); } +void ConstraintSystem::setType(ASTNode node, Type type, + PreparedOverloadBuilder *preparedOverload) { + ASSERT(PreparingOverload == !!preparedOverload); + + ASSERT(!node.isNull() && "Cannot set type information on null node"); + ASSERT(type && "Expected non-null type"); + + if (preparedOverload) { + preparedOverload->recordedNodeType(node, type); + return; + } + + // Record the type. + Type &entry = NodeTypes[node]; + Type oldType = entry; + entry = type; + + if (oldType.getPointer() != type.getPointer()) { + // Record the fact that we assigned a type to this node. + if (solverState) + recordChange(SolverTrail::Change::RecordedNodeType(node, oldType)); + } +} + +void ConstraintSystem::restoreType(ASTNode node, Type oldType) { + ASSERT(!node.isNull() && "Cannot set type information on null node"); + + if (oldType) { + auto found = NodeTypes.find(node); + ASSERT(found != NodeTypes.end()); + found->second = oldType; + } else { + bool erased = NodeTypes.erase(node); + ASSERT(erased); + } +} + +void ConstraintSystem::setType(const KeyPathExpr *KP, unsigned I, Type T) { + ASSERT(KP && "Expected non-null key path parameter!"); + ASSERT(T && "Expected non-null type!"); + + Type &entry = KeyPathComponentTypes[{KP, I}]; + Type oldType = entry; + entry = T; + + if (oldType.getPointer() != T.getPointer()) { + if (solverState) { + recordChange( + SolverTrail::Change::RecordedKeyPathComponentType( + KP, I, oldType)); + } + } +} + +void ConstraintSystem::restoreType(const KeyPathExpr *KP, unsigned I, Type T) { + ASSERT(KP && "Expected non-null key path parameter!"); + + if (T) { + auto found = KeyPathComponentTypes.find({KP, I}); + ASSERT(found != KeyPathComponentTypes.end()); + found->second = T; + } else { + bool erased = KeyPathComponentTypes.erase({KP, I}); + ASSERT(erased); + } +} + std::pair ConstraintSystem::openAnyExistentialType(Type type, ConstraintLocator *locator) { diff --git a/lib/Sema/TypeOfReference.cpp b/lib/Sema/TypeOfReference.cpp index 37363a602209e..5bb457d0457c6 100644 --- a/lib/Sema/TypeOfReference.cpp +++ b/lib/Sema/TypeOfReference.cpp @@ -2834,6 +2834,10 @@ void ConstraintSystem::replayChanges( case PreparedOverload::Change::AddedFix: recordFix(change.Fix.TheFix, change.Fix.Impact); break; + + case PreparedOverload::Change::RecordedNodeType: + setType(change.Node.Node, change.Node.TheType); + break; } } } From 7f8c4e08a8641ca9bdec0de52a9b2195a89286fa Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 18 Sep 2025 10:40:35 -0400 Subject: [PATCH 17/18] Sema: Correctly thread PreparedOverloadBuilder through InferableTypeOpener --- lib/Sema/ConstraintSystem.cpp | 6 ++++-- lib/Sema/TypeOfReference.cpp | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index be0e39b0ba047..e6d462f004f1a 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -3508,8 +3508,10 @@ void OpenGenericTypeRequirements::operator()(GenericTypeDecl *decl, cs.recordOpenedTypes(locator, replacements, preparedOverload, /*fixmeAllowDuplicates*/ true); - for (auto [gp, typeVar] : replacements) - cs.addConstraint(ConstraintKind::Bind, typeVar, subst(gp), locator); + for (auto [gp, typeVar] : replacements) { + cs.addConstraint(ConstraintKind::Bind, typeVar, subst(gp), locator, + /*isFavored=*/false, preparedOverload); + } auto openType = [&](Type ty) -> Type { return cs.openType(ty, replacements, locator, preparedOverload); diff --git a/lib/Sema/TypeOfReference.cpp b/lib/Sema/TypeOfReference.cpp index 5bb457d0457c6..fbcc700b1973f 100644 --- a/lib/Sema/TypeOfReference.cpp +++ b/lib/Sema/TypeOfReference.cpp @@ -303,7 +303,8 @@ class InferableTypeOpener final { // an invalid AST node. if (type->hasError()) { cs.recordFix( - IgnoreInvalidASTNode::create(cs, cs.getConstraintLocator(locator))); + IgnoreInvalidASTNode::create(cs, cs.getConstraintLocator(locator)), + /*impact=*/1, preparedOverload); } return type.transformRec([&](Type type) -> std::optional { if (!type->hasUnboundGenericType() && !type->hasPlaceholder() && From e9070cf229a1c76cf8141f2984c59ec280b25eff Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Sat, 13 Sep 2025 16:24:32 -0400 Subject: [PATCH 18/18] Sema: Remove unused variable --- lib/Sema/MiscDiagnostics.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index 0418ad790ca95..bb0e1b2d377d9 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -4005,8 +4005,7 @@ VarDeclUsageChecker::~VarDeclUsageChecker() { if (!(access & RK_Defined)) continue; - if (auto *caseStmt = - dyn_cast_or_null(var->getRecursiveParentPatternStmt())) { + if (isa_and_nonnull(var->getRecursiveParentPatternStmt())) { // Only diagnose for the parent-most VarDecl. if (var->getParentVarDecl()) continue;