diff --git a/include/swift/Sema/Constraint.h b/include/swift/Sema/Constraint.h index 72db2f161ba3..4428ab650a31 100644 --- a/include/swift/Sema/Constraint.h +++ b/include/swift/Sema/Constraint.h @@ -49,6 +49,7 @@ namespace constraints { class ConstraintFix; class ConstraintLocator; class ConstraintSystem; +class PreparedOverload; enum class TrailingClosureMatching; /// Describes the kind of constraint placed on one or more types. @@ -437,6 +438,9 @@ class Constraint final : public llvm::ilist_node, struct { /// The first type. Type First; + + /// The prepared overload, if any. + PreparedOverload *Prepared; } Overload; struct { @@ -490,7 +494,9 @@ class Constraint final : public llvm::ilist_node, SmallPtrSetImpl &typeVars); /// Construct a new overload-binding constraint, which might have a fix. - Constraint(Type type, OverloadChoice choice, DeclContext *useDC, + Constraint(Type type, OverloadChoice choice, + PreparedOverload *preparedOverload, + DeclContext *useDC, ConstraintFix *fix, ConstraintLocator *locator, SmallPtrSetImpl &typeVars); @@ -871,6 +877,13 @@ class Constraint final : public llvm::ilist_node, return *getTrailingObjects(); } + /// Retrieve the prepared overload choice for an overload-binding + /// constraint. + PreparedOverload *getPreparedOverload() const { + ASSERT(Kind == ConstraintKind::BindOverload); + return Overload.Prepared; + } + FunctionType *getAppliedFunctionType() const { assert(Kind == ConstraintKind::ApplicableFunction); return Apply.AppliedFn; diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index 3dfb878e3f89..45524d70713e 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -64,7 +64,11 @@ namespace constraints { class ConstraintSystem; class SyntacticElementTarget; -struct PreparedOverload; + +// PreparedOverload.h +struct DeclReferenceType; +class PreparedOverload; +struct PreparedOverloadBuilder; } // end namespace constraints @@ -2143,34 +2147,6 @@ struct ClosureIsolatedByPreconcurrency { bool operator()(const ClosureExpr *expr) const; }; -/// Describes the type produced when referencing a declaration. -struct DeclReferenceType { - /// The "opened" type, which is the type of the declaration where any - /// generic parameters have been replaced with type variables. - /// - /// The mapping from generic parameters to type variables will have been - /// recorded by \c recordOpenedTypes when this type is produced. - Type openedType; - - /// The opened type, after performing contextual type adjustments such as - /// removing concurrency-related annotations for a `@preconcurrency` - /// operation. - Type adjustedOpenedType; - - /// The type of the reference, based on the original opened type. This is the - /// type that the expression used to form the declaration reference would - /// have if no adjustments had been applied. - Type referenceType; - - /// The type of the reference, which is the adjusted opened type after - /// (e.g.) applying the base of a member access. This is the type of the - /// expression used to form the declaration reference. - Type adjustedReferenceType; - - /// The type that could be thrown by accessing this declaration. - Type thrownErrorTypeOnAccess; -}; - /// Describes a system of constraints on type variables, the /// solution of which assigns concrete types to each of the type variables. /// Constraint systems are typically generated given an (untyped) expression. @@ -2954,7 +2930,7 @@ class ConstraintSystem { /// Create a new type variable. TypeVariableType *createTypeVariable(ConstraintLocator *locator, unsigned options, - PreparedOverload *preparedOverload + PreparedOverloadBuilder *preparedOverload = nullptr); /// Retrieve the set of active type variables. @@ -3414,7 +3390,8 @@ class ConstraintSystem { /// Update OpenedExistentials and record a change in the trail. void recordOpenedExistentialType(ConstraintLocator *locator, ExistentialArchetypeType *opened, - PreparedOverload *preparedOverload = nullptr); + PreparedOverloadBuilder *preparedOverload + = nullptr); /// Retrieve the generic environment for the opened element of a given pack /// expansion, or \c nullptr if no environment was recorded yet. @@ -3622,7 +3599,7 @@ class ConstraintSystem { /// Log and record the application of the fix. Return true iff any /// subsequent solution would be worse than the best known solution. bool recordFix(ConstraintFix *fix, unsigned impact = 1, - PreparedOverload *preparedOverload = nullptr); + PreparedOverloadBuilder *preparedOverload = nullptr); void recordPotentialHole(TypeVariableType *typeVar); void recordAnyTypeVarAsPotentialHole(Type type); @@ -3698,13 +3675,13 @@ class ConstraintSystem { void addConstraint(ConstraintKind kind, Type first, Type second, ConstraintLocatorBuilder locator, bool isFavored = false, - PreparedOverload *preparedOverload = nullptr); + PreparedOverloadBuilder *preparedOverload = nullptr); /// Add a requirement as a constraint to the constraint system. void addConstraint(Requirement req, ConstraintLocatorBuilder locator, bool isFavored, bool prohibitNonisolatedConformance, - PreparedOverload *preparedOverload = nullptr); + PreparedOverloadBuilder *preparedOverload = nullptr); void addApplicationConstraint( FunctionType *appliedFn, Type calleeType, @@ -3814,9 +3791,9 @@ 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); + ConstraintLocator *locator, DeclContext *useDC) { + resolveOverload(locator, boundTy, choice, useDC, + /*preparedOverload=*/nullptr); } /// Add a value member constraint to the constraint system. @@ -4319,7 +4296,7 @@ class ConstraintSystem { Type openUnboundGenericType(GenericTypeDecl *decl, Type parentTy, ConstraintLocatorBuilder locator, bool isTypeResolution, - PreparedOverload *preparedOverload = nullptr); + PreparedOverloadBuilder *preparedOverload = nullptr); /// Replace placeholder types with fresh type variables, and unbound generic /// types with bound generic types whose generic args are fresh type @@ -4330,7 +4307,7 @@ class ConstraintSystem { /// \returns The converted type. Type replaceInferableTypesWithTypeVars(Type type, ConstraintLocatorBuilder locator, - PreparedOverload *preparedOverload + PreparedOverloadBuilder *preparedOverload = nullptr); /// "Open" the given type by replacing any occurrences of generic @@ -4343,7 +4320,7 @@ class ConstraintSystem { /// \returns The opened type, or \c type if there are no archetypes in it. Type openType(Type type, ArrayRef replacements, ConstraintLocatorBuilder locator, - PreparedOverload *preparedOverload); + PreparedOverloadBuilder *preparedOverload); /// "Open" an opaque archetype type, similar to \c openType. Type openOpaqueType(OpaqueTypeArchetypeType *type, @@ -4360,12 +4337,12 @@ class ConstraintSystem { Type openPackExpansionType(PackExpansionType *expansion, ArrayRef replacements, ConstraintLocatorBuilder locator, - PreparedOverload *preparedOverload); + PreparedOverloadBuilder *preparedOverload); /// Update OpenedPackExpansionTypes and record a change in the trail. void recordOpenedPackExpansionType(PackExpansionType *expansion, TypeVariableType *expansionVar, - PreparedOverload *preparedOverload + PreparedOverloadBuilder *preparedOverload = nullptr); /// Undo the above change. @@ -4392,7 +4369,7 @@ class ConstraintSystem { ConstraintLocatorBuilder locator, SmallVectorImpl &replacements, DeclContext *outerDC, - PreparedOverload *preparedOverload); + PreparedOverloadBuilder *preparedOverload); /// Open the generic parameter list and its requirements, /// creating type variables for each of the type parameters. @@ -4400,7 +4377,7 @@ class ConstraintSystem { GenericSignature signature, ConstraintLocatorBuilder locator, SmallVectorImpl &replacements, - PreparedOverload *preparedOverload); + PreparedOverloadBuilder *preparedOverload); /// Open the generic parameter list creating type variables for each of the /// type parameters. @@ -4408,13 +4385,13 @@ class ConstraintSystem { GenericSignature signature, SmallVectorImpl &replacements, ConstraintLocatorBuilder locator, - PreparedOverload *preparedOverload); + PreparedOverloadBuilder *preparedOverload); /// Open a generic parameter into a type variable and record /// it in \c replacements. TypeVariableType *openGenericParameter(GenericTypeParamType *parameter, ConstraintLocatorBuilder locator, - PreparedOverload *preparedOverload); + PreparedOverloadBuilder *preparedOverload); /// Given generic signature open its generic requirements, /// using substitution function, and record them in the @@ -4424,7 +4401,7 @@ class ConstraintSystem { bool skipProtocolSelfConstraint, ConstraintLocatorBuilder locator, llvm::function_ref subst, - PreparedOverload *preparedOverload); + PreparedOverloadBuilder *preparedOverload); // Record the given requirement in the constraint system. void openGenericRequirement(DeclContext *outerDC, @@ -4434,18 +4411,18 @@ class ConstraintSystem { bool skipProtocolSelfConstraint, ConstraintLocatorBuilder locator, llvm::function_ref subst, - PreparedOverload *preparedOverload); + PreparedOverloadBuilder *preparedOverload); /// Update OpenedTypes and record a change in the trail. void recordOpenedType( ConstraintLocator *locator, ArrayRef openedTypes, - PreparedOverload *preparedOverload = nullptr); + PreparedOverloadBuilder *preparedOverload = nullptr); /// Record the set of opened types for the given locator. void recordOpenedTypes( ConstraintLocatorBuilder locator, const SmallVectorImpl &replacements, - PreparedOverload *preparedOverload = nullptr, + PreparedOverloadBuilder *preparedOverload = nullptr, bool fixmeAllowDuplicates = false); /// Check whether the given type conforms to the given protocol and if @@ -4458,7 +4435,7 @@ class ConstraintSystem { FunctionType *fnType, Type baseType, ValueDecl *decl, DeclContext *dc, unsigned numApplies, bool isMainDispatchQueue, ArrayRef replacements, ConstraintLocatorBuilder locator, - PreparedOverload *preparedOverload); + PreparedOverloadBuilder *preparedOverload); /// Retrieve the type of a reference to the given value declaration. /// @@ -4474,7 +4451,7 @@ class ConstraintSystem { FunctionRefInfo functionRefInfo, ConstraintLocatorBuilder locator, DeclContext *useDC, - PreparedOverload *preparedOverload); + PreparedOverloadBuilder *preparedOverload); /// Return the type-of-reference of the given value. /// @@ -4516,7 +4493,7 @@ class ConstraintSystem { Type baseTy, ValueDecl *decl, DeclContext *useDC, bool isDynamicLookup, FunctionRefInfo functionRefInfo, ConstraintLocator *locator, SmallVectorImpl *replacements = nullptr, - PreparedOverload *preparedOverload = nullptr); + PreparedOverloadBuilder *preparedOverload = nullptr); /// Retrieve a list of generic parameter types solver has "opened" (replaced /// with a type variable) at the given location. @@ -4929,9 +4906,28 @@ class ConstraintSystem { void recordResolvedOverload(ConstraintLocator *locator, SelectedOverload choice); + /// Build and allocate a prepared overload in the solver arena. + PreparedOverload *prepareOverload(ConstraintLocator *locator, + OverloadChoice choice, + DeclContext *useDC); + + /// 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, + DeclContext *useDC, + PreparedOverloadBuilder *preparedOverload); + + void replayChanges( + ConstraintLocator *locator, + PreparedOverload *preparedOverload); + /// Resolve the given overload set to the given choice. void resolveOverload(ConstraintLocator *locator, Type boundType, - OverloadChoice choice, DeclContext *useDC); + OverloadChoice choice, DeclContext *useDC, + PreparedOverload *preparedOverload); /// Simplify a type, by replacing type variables with either their /// fixed types (if available) or their representatives. @@ -5342,13 +5338,13 @@ class ConstraintSystem { ConstraintKind matchKind, ConstraintLocator *locator, ConstraintLocator *calleeLocator, - PreparedOverload *preparedOverload = nullptr); + PreparedOverloadBuilder *preparedOverload = nullptr); /// Used by applyPropertyWrapperToParameter() to update appliedPropertyWrappers /// and record a change in the trail. void applyPropertyWrapper(Expr *anchor, AppliedPropertyWrapper applied, - PreparedOverload *preparedOverload = nullptr); + PreparedOverloadBuilder *preparedOverload = nullptr); /// Undo the above change. void removePropertyWrapper(Expr *anchor); diff --git a/include/swift/Sema/OverloadChoice.h b/include/swift/Sema/OverloadChoice.h index 111703be8f50..9e0188418904 100644 --- a/include/swift/Sema/OverloadChoice.h +++ b/include/swift/Sema/OverloadChoice.h @@ -250,6 +250,23 @@ class OverloadChoice { return (OverloadChoiceKind)kind; } + bool canBePrepared() const { + switch (getKind()) { + case OverloadChoiceKind::Decl: + case OverloadChoiceKind::DeclViaBridge: + case OverloadChoiceKind::DeclViaDynamic: + case OverloadChoiceKind::DeclViaUnwrappedOptional: + case OverloadChoiceKind::DynamicMemberLookup: + case OverloadChoiceKind::KeyPathDynamicMemberLookup: + return true; + case OverloadChoiceKind::TupleIndex: + case OverloadChoiceKind::MaterializePack: + case OverloadChoiceKind::ExtractFunctionIsolation: + case OverloadChoiceKind::KeyPathApplication: + return false; + } + } + /// Determine whether this choice is for a declaration. bool isDecl() const { return DeclOrKind.is(); diff --git a/include/swift/Sema/PreparedOverload.h b/include/swift/Sema/PreparedOverload.h index 78962f892708..7cba8076eabc 100644 --- a/include/swift/Sema/PreparedOverload.h +++ b/include/swift/Sema/PreparedOverload.h @@ -13,8 +13,10 @@ #define SWIFT_SEMA_PREPAREDOVERLOAD_H #include "swift/AST/PropertyWrappers.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/TrailingObjects.h" namespace swift { @@ -27,139 +29,211 @@ namespace constraints { class ConstraintLocatorBuilder; class ConstraintSystem; +/// Describes the type produced when referencing a declaration. +struct DeclReferenceType { + /// The "opened" type, which is the type of the declaration where any + /// generic parameters have been replaced with type variables. + /// + /// The mapping from generic parameters to type variables will have been + /// recorded by \c recordOpenedTypes when this type is produced. + Type openedType; + + /// The opened type, after performing contextual type adjustments such as + /// removing concurrency-related annotations for a `@preconcurrency` + /// operation. + Type adjustedOpenedType; + + /// The type of the reference, based on the original opened type. This is the + /// type that the expression used to form the declaration reference would + /// have if no adjustments had been applied. + Type referenceType; + + /// The type of the reference, which is the adjusted opened type after + /// (e.g.) applying the base of a member access. This is the type of the + /// expression used to form the declaration reference. + Type adjustedReferenceType; + + /// The type that could be thrown by accessing this declaration. + Type thrownErrorTypeOnAccess; +}; + /// Describes a dependent type that has been opened to a particular type /// variable. using OpenedType = std::pair; +/// A change to be introduced into the constraint system when this +/// overload choice is chosen. +struct PreparedOverloadChange { + enum ChangeKind : unsigned { + /// A generic parameter was opened to a type variable. + AddedTypeVariable, + + /// A generic requirement was opened to a constraint. + AddedConstraint, + + /// A mapping of generic parameter types to type variables + /// was recorded. + OpenedTypes, + + /// An existential type was opened. + OpenedExistentialType, + + /// A pack expansion type was opened. + OpenedPackExpansionType, + + /// A property wrapper was applied to a parameter. + AppliedPropertyWrapper, + + /// A fix was recorded because a property wrapper application failed. + AddedFix + }; + + /// The kind of change. + ChangeKind Kind; + + union { + /// For ChangeKind::AddedTypeVariable. + TypeVariableType *TypeVar; + + /// For ChangeKind::AddedConstraint. + Constraint *TheConstraint; + + /// For ChangeKind::OpenedTypes. + struct { + const OpenedType *Data; + size_t Count; + } Replacements; + + /// For ChangeKind::OpenedExistentialType. + ExistentialArchetypeType *TheExistential; + + /// For ChangeKind::OpenedPackExpansionType. + struct { + PackExpansionType *TheExpansion; + TypeVariableType *TypeVar; + } PackExpansion; + + /// For ChangeKind::AppliedPropertyWrapper. + struct { + TypeBase *WrapperType; + PropertyWrapperInitKind InitKind; + } PropertyWrapper; + + /// For ChangeKind::Fix. + struct { + ConstraintFix *TheFix; + unsigned Impact; + } Fix; + }; +}; + /// A "pre-cooked" representation of all type variables and constraints /// that are generated as part of an overload choice. -struct PreparedOverload { - /// A change to be introduced into the constraint system when this - /// overload choice is chosen. - struct Change { - enum ChangeKind : unsigned { - /// A generic parameter was opened to a type variable. - AddedTypeVariable, +class PreparedOverload final : + public llvm::TrailingObjects { + +public: + using Change = PreparedOverloadChange; - /// A generic requirement was opened to a constraint. - AddedConstraint, +private: + size_t Count; + DeclReferenceType DeclType; - /// A mapping of generic parameter types to type variables - /// was recorded. - OpenedTypes, + size_t numTrailingObjects(OverloadToken) const { + return Count; + } - /// An existential type was opened. - OpenedExistentialType, +public: + PreparedOverload(const DeclReferenceType &declType, ArrayRef changes) + : Count(changes.size()), DeclType(declType) { + std::uninitialized_copy(changes.begin(), changes.end(), + getTrailingObjects()); + } - /// A pack expansion type was opened. - OpenedPackExpansionType, + Type getOpenedType() const { + return DeclType.openedType; + } - /// A property wrapper was applied to a parameter. - AppliedPropertyWrapper, + Type getAdjustedOpenedType() const { + return DeclType.adjustedOpenedType; + } - /// A fix was recorded because a property wrapper application failed. - AddedFix - }; + Type getReferenceType() const { + return DeclType.referenceType; + } - /// The kind of change. - ChangeKind Kind; + Type getAdjustedReferenceType() const { + return DeclType.adjustedReferenceType; + } - union { - /// For ChangeKind::AddedTypeVariable. - TypeVariableType *TypeVar; + Type getThrownErrorTypeOnAccess() const { + return DeclType.thrownErrorTypeOnAccess; + } - /// For ChangeKind::AddedConstraint. - Constraint *TheConstraint; - - /// For ChangeKind::OpenedTypes. - struct { - const OpenedType *Data; - size_t Count; - } Replacements; - - /// For ChangeKind::OpenedExistentialType. - ExistentialArchetypeType *TheExistential; - - /// For ChangeKind::OpenedPackExpansionType. - struct { - PackExpansionType *TheExpansion; - TypeVariableType *TypeVar; - } PackExpansion; - - /// For ChangeKind::AppliedPropertyWrapper. - struct { - TypeBase *WrapperType; - PropertyWrapperInitKind InitKind; - } PropertyWrapper; - - /// For ChangeKind::Fix. - struct { - ConstraintFix *TheFix; - unsigned Impact; - } Fix; - }; - }; + ArrayRef getChanges() const { + return ArrayRef(getTrailingObjects(), Count); + } +}; - SmallVector Changes; +struct PreparedOverloadBuilder { + SmallVector Changes; void addedTypeVariable(TypeVariableType *typeVar) { - Change change; - change.Kind = Change::AddedTypeVariable; + PreparedOverload::Change change; + change.Kind = PreparedOverload::Change::AddedTypeVariable; change.TypeVar = typeVar; Changes.push_back(change); } void addedConstraint(Constraint *constraint) { - Change change; - change.Kind = Change::AddedConstraint; + PreparedOverload::Change change; + change.Kind = PreparedOverload::Change::AddedConstraint; change.TheConstraint = constraint; Changes.push_back(change); } void openedTypes(ArrayRef replacements) { - Change change; - change.Kind = Change::OpenedTypes; + PreparedOverload::Change change; + change.Kind = PreparedOverload::Change::OpenedTypes; change.Replacements.Data = replacements.data(); change.Replacements.Count = replacements.size(); Changes.push_back(change); } void openedExistentialType(ExistentialArchetypeType *openedExistential) { - Change change; - change.Kind = Change::OpenedExistentialType; + PreparedOverload::Change change; + change.Kind = PreparedOverload::Change::OpenedExistentialType; change.TheExistential = openedExistential; Changes.push_back(change); } void openedPackExpansionType(PackExpansionType *packExpansion, TypeVariableType *typeVar) { - Change change; - change.Kind = Change::OpenedPackExpansionType; + PreparedOverload::Change change; + change.Kind = PreparedOverload::Change::OpenedPackExpansionType; change.PackExpansion.TheExpansion = packExpansion; change.PackExpansion.TypeVar = typeVar; Changes.push_back(change); } void appliedPropertyWrapper(AppliedPropertyWrapper wrapper) { - Change change; - change.Kind = Change::AppliedPropertyWrapper; + PreparedOverload::Change change; + change.Kind = PreparedOverload::Change::AppliedPropertyWrapper; change.PropertyWrapper.WrapperType = wrapper.wrapperType.getPointer(); change.PropertyWrapper.InitKind = wrapper.initKind; Changes.push_back(change); } void addedFix(ConstraintFix *fix, unsigned impact) { - Change change; - change.Kind = Change::AddedFix; + PreparedOverload::Change change; + change.Kind = PreparedOverload::Change::AddedFix; change.Fix.TheFix = fix; change.Fix.Impact = impact; Changes.push_back(change); } - - void discharge(ConstraintSystem &cs, ConstraintLocatorBuilder locator) const; }; -} -} +} // end namespace constraints +} // end namespace swift #endif diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 0b0e1af42d96..5c0bc687ae10 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -1660,7 +1660,7 @@ namespace { OverloadChoice choice = OverloadChoice(Type(), E->getDecl(), E->getFunctionRefInfo()); - CS.resolveOverload(locator, tv, choice, CurDC); + CS.addBindOverloadConstraint(tv, choice, locator, CurDC); return tv; } @@ -5124,7 +5124,7 @@ bool ConstraintSystem::generateConstraints(StmtCondition condition, void ConstraintSystem::applyPropertyWrapper( Expr *anchor, AppliedPropertyWrapper applied, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { if (preparedOverload) { ASSERT(PreparingOverload); preparedOverload->appliedPropertyWrapper(applied); @@ -5160,7 +5160,7 @@ ConstraintSystem::applyPropertyWrapperToParameter( ConstraintKind matchKind, ConstraintLocator *locator, ConstraintLocator *calleeLocator, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { Expr *anchor = getAsExpr(calleeLocator->getAnchor()); auto recordPropertyWrapperFix = [&](ConstraintFix *fix) -> TypeMatchResult { diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 80fe95cc8d61..bb07eac4d554 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -11834,8 +11834,8 @@ ConstraintSystem::simplifyValueWitnessConstraint( return fail(); auto choice = OverloadChoice(resolvedBaseType, witness.getDecl(), functionRefInfo); - resolveOverload(getConstraintLocator(locator), memberType, choice, - useDC); + addBindOverloadConstraint(memberType, choice, getConstraintLocator(locator), + useDC); return SolutionKind::Solved; } @@ -15422,7 +15422,7 @@ static bool isAugmentingFix(ConstraintFix *fix) { } bool ConstraintSystem::recordFix(ConstraintFix *fix, unsigned impact, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { if (preparedOverload) { ASSERT(PreparingOverload); preparedOverload->addedFix(fix, impact); @@ -16298,7 +16298,7 @@ void ConstraintSystem::addConstraint(Requirement req, ConstraintLocatorBuilder locator, bool isFavored, bool prohibitNonisolatedConformance, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { bool conformsToAnyObject = false; std::optional kind; switch (req.getKind()) { @@ -16362,7 +16362,7 @@ void ConstraintSystem::addConstraint(ConstraintKind kind, Type first, Type second, ConstraintLocatorBuilder locator, bool isFavored, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { if (preparedOverload) { ASSERT(PreparingOverload); auto c = Constraint::create(*this, kind, first, second, @@ -16661,7 +16661,8 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) { resolveOverload(constraint.getLocator(), constraint.getFirstType(), constraint.getOverloadChoice(), - constraint.getDeclContext()); + constraint.getDeclContext(), + constraint.getPreparedOverload()); return SolutionKind::Solved; case ConstraintKind::SubclassOf: diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp index b3f96ee3f881..2f6d0c5f0100 100644 --- a/lib/Sema/CSSolver.cpp +++ b/lib/Sema/CSSolver.cpp @@ -60,7 +60,7 @@ STATISTIC(LargestSolutionAttemptNumber, "# of the largest solution attempt"); TypeVariableType *ConstraintSystem::createTypeVariable( ConstraintLocator *locator, unsigned options, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { ++TotalNumTypeVariables; auto tv = TypeVariableType::getNew(getASTContext(), assignTypeVariableID(), locator, options); diff --git a/lib/Sema/Constraint.cpp b/lib/Sema/Constraint.cpp index 850f3fc37855..af6bbf0f17c4 100644 --- a/lib/Sema/Constraint.cpp +++ b/lib/Sema/Constraint.cpp @@ -245,14 +245,16 @@ Constraint::Constraint(ConstraintKind kind, Type first, Type second, *getTrailingObjects() = useDC; } -Constraint::Constraint(Type type, OverloadChoice choice, DeclContext *useDC, +Constraint::Constraint(Type type, OverloadChoice choice, + PreparedOverload *preparedOverload, + DeclContext *useDC, ConstraintFix *fix, ConstraintLocator *locator, SmallPtrSetImpl &typeVars) : Kind(ConstraintKind::BindOverload), NumTypeVariables(typeVars.size()), HasFix(fix != nullptr), HasDeclContext(true), HasRestriction(false), IsActive(false), IsDisabled(bool(fix)), IsDisabledForPerformance(false), RememberChoice(false), IsFavored(false), IsIsolated(false), - Overload{type}, Locator(locator) { + Overload{type, preparedOverload}, Locator(locator) { std::copy(typeVars.begin(), typeVars.end(), getTypeVariablesBuffer().begin()); if (fix) *getTrailingObjects() = fix; @@ -893,10 +895,22 @@ Constraint *Constraint::createValueWitness( } Constraint *Constraint::createBindOverload(ConstraintSystem &cs, Type type, - OverloadChoice choice, + OverloadChoice choice, DeclContext *useDC, ConstraintFix *fix, ConstraintLocator *locator) { + // FIXME: Transitional hack. + bool enablePreparedOverloads = false; + + PreparedOverload *preparedOverload = nullptr; + + // Prepare the overload. + if (enablePreparedOverloads) { + if (choice.canBePrepared()) { + preparedOverload = cs.prepareOverload(locator, choice, useDC); + } + } + // Collect type variables. SmallPtrSet typeVars; if (type->hasTypeVariable()) @@ -912,7 +926,8 @@ Constraint *Constraint::createBindOverload(ConstraintSystem &cs, Type type, typeVars.size(), fix ? 1 : 0, /*hasDeclContext=*/1, /*hasContextualTypeInfo=*/0, /*hasOverloadChoice=*/1); void *mem = cs.getAllocator().Allocate(size, alignof(Constraint)); - return new (mem) Constraint(type, choice, useDC, fix, locator, typeVars); + return new (mem) Constraint(type, choice, preparedOverload, useDC, + fix, locator, typeVars); } Constraint *Constraint::createRestricted(ConstraintSystem &cs, diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 177093469d12..3d6c091a5b66 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -904,7 +904,7 @@ ConstraintSystem::openAnyExistentialType(Type type, void ConstraintSystem::recordOpenedExistentialType( ConstraintLocator *locator, ExistentialArchetypeType *opened, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { if (preparedOverload) { preparedOverload->openedExistentialType(opened); return; diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index 679b3c282a52..c7d579352da1 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -62,6 +62,7 @@ #include "swift/Basic/StringExtras.h" #include "swift/ClangImporter/ClangModule.h" #include "swift/Sema/IDETypeChecking.h" +#include "swift/Sema/PreparedOverload.h" #include "swift/Serialization/SerializedModuleLoader.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Statistic.h" diff --git a/lib/Sema/TypeOfReference.cpp b/lib/Sema/TypeOfReference.cpp index 1a972ad80a26..96536eee7c54 100644 --- a/lib/Sema/TypeOfReference.cpp +++ b/lib/Sema/TypeOfReference.cpp @@ -46,7 +46,7 @@ Type ConstraintSystem::openUnboundGenericType(GenericTypeDecl *decl, Type parentTy, ConstraintLocatorBuilder locator, bool isTypeResolution, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { if (parentTy) { parentTy = replaceInferableTypesWithTypeVars( parentTy, locator, preparedOverload); @@ -121,7 +121,7 @@ Type ConstraintSystem::openUnboundGenericType(GenericTypeDecl *decl, static void checkNestedTypeConstraints(ConstraintSystem &cs, Type type, ConstraintLocatorBuilder locator, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { // If this is a type defined inside of constrained extension, let's add all // of the generic requirements to the constraint system to make sure that it's // something we can use. @@ -200,7 +200,7 @@ static void checkNestedTypeConstraints(ConstraintSystem &cs, Type type, Type ConstraintSystem::replaceInferableTypesWithTypeVars( Type type, ConstraintLocatorBuilder locator, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { if (!type->hasUnboundGenericType() && !type->hasPlaceholder()) return type; @@ -246,12 +246,12 @@ namespace { struct TypeOpener : public TypeTransform { ArrayRef replacements; ConstraintLocatorBuilder locator; - PreparedOverload *preparedOverload; + PreparedOverloadBuilder *preparedOverload; ConstraintSystem &cs; TypeOpener(ArrayRef replacements, ConstraintLocatorBuilder locator, - PreparedOverload *preparedOverload, + PreparedOverloadBuilder *preparedOverload, ConstraintSystem &cs) : TypeTransform(cs.getASTContext()), replacements(replacements), locator(locator), @@ -295,7 +295,7 @@ struct TypeOpener : public TypeTransform { Type ConstraintSystem::openType(Type type, ArrayRef replacements, ConstraintLocatorBuilder locator, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { assert(!type->hasUnboundGenericType()); if (!type->hasTypeParameter()) @@ -308,7 +308,7 @@ Type ConstraintSystem::openType(Type type, ArrayRef replacements, Type ConstraintSystem::openPackExpansionType(PackExpansionType *expansion, ArrayRef replacements, ConstraintLocatorBuilder locator, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { auto patternType = openType(expansion->getPatternType(), replacements, locator, preparedOverload); @@ -357,7 +357,7 @@ Type ConstraintSystem::openPackExpansionType(PackExpansionType *expansion, void ConstraintSystem::recordOpenedPackExpansionType(PackExpansionType *expansion, TypeVariableType *expansionVar, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { if (preparedOverload) { ASSERT(PreparingOverload); preparedOverload->openedPackExpansionType(expansion, expansionVar); @@ -477,7 +477,7 @@ FunctionType *ConstraintSystem::openFunctionType( ConstraintLocatorBuilder locator, SmallVectorImpl &replacements, DeclContext *outerDC, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { if (auto *genericFn = funcType->getAs()) { auto signature = genericFn->getGenericSignature(); openGenericParameters(outerDC, signature, replacements, locator, @@ -701,7 +701,7 @@ Type ConstraintSystem::getUnopenedTypeOfReference( void ConstraintSystem::recordOpenedType( ConstraintLocator *locator, ArrayRef replacements, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { if (preparedOverload) { ASSERT(PreparingOverload); preparedOverload->openedTypes(replacements); @@ -720,7 +720,7 @@ void ConstraintSystem::recordOpenedType( void ConstraintSystem::recordOpenedTypes( ConstraintLocatorBuilder locator, const SmallVectorImpl &replacements, - PreparedOverload *preparedOverload, + PreparedOverloadBuilder *preparedOverload, bool fixmeAllowDuplicates) { if (replacements.empty()) return; @@ -810,7 +810,7 @@ unwrapPropertyWrapperParameterTypes(ConstraintSystem &cs, FunctionRefInfo functionRefInfo, FunctionType *functionType, ConstraintLocatorBuilder locator, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { // Only apply property wrappers to unapplied references to functions. if (!functionRefInfo.isUnapplied()) return functionType; @@ -870,7 +870,7 @@ 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, PreparedOverload *preparedOverload) { + ConstraintLocatorBuilder locator, PreparedOverloadBuilder *preparedOverload) { auto *adjustedTy = swift::adjustFunctionTypeForConcurrency( fnType, decl, dc, numApplies, isMainDispatchQueue, GetClosureType{*this}, @@ -997,7 +997,7 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value, FunctionRefInfo functionRefInfo, ConstraintLocatorBuilder locator, DeclContext *useDC, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { ASSERT(!!preparedOverload == PreparingOverload); if (value->getDeclContext()->isTypeContext() && isa(value)) { @@ -1181,7 +1181,7 @@ static void bindArchetypesFromContext( DeclContext *outerDC, ConstraintLocator *locatorPtr, ArrayRef replacements, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { auto bindPrimaryArchetype = [&](Type paramTy, Type contextTy) { // We might not have a type variable for this generic parameter @@ -1227,7 +1227,7 @@ void ConstraintSystem::openGeneric( GenericSignature sig, ConstraintLocatorBuilder locator, SmallVectorImpl &replacements, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { if (!sig) return; @@ -1245,7 +1245,7 @@ void ConstraintSystem::openGenericParameters(DeclContext *outerDC, GenericSignature sig, SmallVectorImpl &replacements, ConstraintLocatorBuilder locator, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { ASSERT(sig); ASSERT(replacements.empty()); @@ -1263,7 +1263,7 @@ void ConstraintSystem::openGenericParameters(DeclContext *outerDC, TypeVariableType *ConstraintSystem::openGenericParameter(GenericTypeParamType *parameter, ConstraintLocatorBuilder locator, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { auto *paramLocator = getConstraintLocator( locator.withPathElement(LocatorPathElt::GenericParameter(parameter))); @@ -1282,7 +1282,7 @@ void ConstraintSystem::openGenericRequirements( DeclContext *outerDC, GenericSignature signature, bool skipProtocolSelfConstraint, ConstraintLocatorBuilder locator, llvm::function_ref substFn, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { auto requirements = signature.getRequirements(); for (unsigned pos = 0, n = requirements.size(); pos != n; ++pos) { auto openedGenericLoc = @@ -1298,7 +1298,7 @@ void ConstraintSystem::openGenericRequirement( unsigned index, const Requirement &req, bool skipProtocolSelfConstraint, ConstraintLocatorBuilder locator, llvm::function_ref substFn, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { std::optional openedReq; auto openedFirst = substFn(req.getFirstType()); @@ -1351,7 +1351,7 @@ void ConstraintSystem::openGenericRequirement( /// declared. static void addSelfConstraint(ConstraintSystem &cs, Type objectTy, Type selfTy, ConstraintLocatorBuilder locator, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { assert(!selfTy->is()); // Otherwise, use a subtype constraint for classes to cope with inheritance. @@ -1590,7 +1590,7 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference( Type baseTy, ValueDecl *value, DeclContext *useDC, bool isDynamicLookup, FunctionRefInfo functionRefInfo, ConstraintLocator *locator, SmallVectorImpl *replacementsPtr, - PreparedOverload *preparedOverload) { + PreparedOverloadBuilder *preparedOverload) { ASSERT(!!preparedOverload == PreparingOverload); // Figure out the instance type used for the base. @@ -2377,7 +2377,8 @@ isInvalidPartialApplication(ConstraintSystem &cs, /// the full opened type and the reference's type. static DeclReferenceType getTypeOfReferenceWithSpecialTypeCheckingSemantics( ConstraintSystem &CS, ConstraintLocator *locator, - DeclTypeCheckingSemantics semantics) { + DeclTypeCheckingSemantics semantics, + PreparedOverloadBuilder *preparedOverload) { switch (semantics) { case DeclTypeCheckingSemantics::Normal: llvm_unreachable("Decl does not have special type checking semantics!"); @@ -2389,17 +2390,18 @@ static DeclReferenceType getTypeOfReferenceWithSpecialTypeCheckingSemantics( // be expressed in the type system currently. auto input = CS.createTypeVariable( CS.getConstraintLocator(locator, ConstraintLocator::FunctionArgument), - TVO_CanBindToNoEscape); + TVO_CanBindToNoEscape, preparedOverload); auto output = CS.createTypeVariable( CS.getConstraintLocator(locator, ConstraintLocator::FunctionResult), - TVO_CanBindToNoEscape); + TVO_CanBindToNoEscape, preparedOverload); FunctionType::Param inputArg(input, CS.getASTContext().getIdentifier("of")); CS.addConstraint( ConstraintKind::DynamicTypeOf, output, input, - CS.getConstraintLocator(locator, ConstraintLocator::DynamicType)); + CS.getConstraintLocator(locator, ConstraintLocator::DynamicType), + /*isFavored=*/false, preparedOverload); // FIXME: Verify ExtInfo state is correct, not working by accident. FunctionType::ExtInfo info; auto refType = FunctionType::get({inputArg}, output, info); @@ -2411,18 +2413,19 @@ static DeclReferenceType getTypeOfReferenceWithSpecialTypeCheckingSemantics( // @escaping. auto noescapeClosure = CS.createTypeVariable( CS.getConstraintLocator(locator, ConstraintLocator::FunctionArgument), - TVO_CanBindToNoEscape); + TVO_CanBindToNoEscape, preparedOverload); auto escapeClosure = CS.createTypeVariable( CS.getConstraintLocator(locator, ConstraintLocator::FunctionArgument), - TVO_CanBindToNoEscape); + TVO_CanBindToNoEscape, preparedOverload); CS.addConstraint(ConstraintKind::EscapableFunctionOf, escapeClosure, - noescapeClosure, CS.getConstraintLocator(locator)); + noescapeClosure, CS.getConstraintLocator(locator), + /*isFavored=*/false, preparedOverload); auto result = CS.createTypeVariable( CS.getConstraintLocator(locator, ConstraintLocator::FunctionResult), - TVO_CanBindToNoEscape); + TVO_CanBindToNoEscape, preparedOverload); auto thrownError = CS.createTypeVariable( CS.getConstraintLocator(locator, ConstraintLocator::ThrownErrorType), - 0); + 0, preparedOverload); FunctionType::Param arg(escapeClosure); auto bodyClosure = FunctionType::get(arg, result, FunctionType::ExtInfoBuilder() @@ -2448,18 +2451,19 @@ static DeclReferenceType getTypeOfReferenceWithSpecialTypeCheckingSemantics( // existential type as its input. auto openedTy = CS.createTypeVariable( CS.getConstraintLocator(locator, ConstraintLocator::FunctionArgument), - TVO_CanBindToNoEscape); + TVO_CanBindToNoEscape, preparedOverload); auto existentialTy = CS.createTypeVariable( CS.getConstraintLocator(locator, ConstraintLocator::FunctionArgument), - TVO_CanBindToNoEscape); + TVO_CanBindToNoEscape, preparedOverload); CS.addConstraint(ConstraintKind::OpenedExistentialOf, openedTy, - existentialTy, CS.getConstraintLocator(locator)); + existentialTy, CS.getConstraintLocator(locator), + /*isFavored=*/false, preparedOverload); auto result = CS.createTypeVariable( CS.getConstraintLocator(locator, ConstraintLocator::FunctionResult), - TVO_CanBindToNoEscape); + TVO_CanBindToNoEscape, preparedOverload); auto thrownError = CS.createTypeVariable( CS.getConstraintLocator(locator, ConstraintLocator::ThrownErrorType), - 0); + 0, preparedOverload); FunctionType::Param bodyArgs[] = {FunctionType::Param(openedTy)}; auto bodyClosure = FunctionType::get(bodyArgs, result, FunctionType::ExtInfoBuilder() @@ -2493,63 +2497,112 @@ void ConstraintSystem::recordResolvedOverload(ConstraintLocator *locator, recordChange(SolverTrail::Change::ResolvedOverload(locator)); } -void PreparedOverload::discharge(ConstraintSystem &cs, - ConstraintLocatorBuilder locator) const { - for (auto change : Changes) { +void ConstraintSystem::replayChanges( + ConstraintLocator *locator, + PreparedOverload *preparedOverload) { + for (auto change : preparedOverload->getChanges()) { switch (change.Kind) { case PreparedOverload::Change::AddedTypeVariable: - cs.addTypeVariable(change.TypeVar); + addTypeVariable(change.TypeVar); break; case PreparedOverload::Change::AddedConstraint: - cs.addUnsolvedConstraint(change.TheConstraint); - cs.activateConstraint(change.TheConstraint); + simplifyDisjunctionChoice(change.TheConstraint); break; case PreparedOverload::Change::OpenedTypes: { - auto *locatorPtr = cs.getConstraintLocator(locator); ArrayRef replacements( change.Replacements.Data, change.Replacements.Count); // FIXME: Get rid of this conditional. - if (cs.getOpenedTypes(locatorPtr).empty()) - cs.recordOpenedType(locatorPtr, replacements); + if (getOpenedTypes(locator).empty()) + recordOpenedType(locator, replacements); break; } case PreparedOverload::Change::OpenedExistentialType: { - auto *locatorPtr = cs.getConstraintLocator(locator); - cs.recordOpenedExistentialType(locatorPtr, - change.TheExistential); + recordOpenedExistentialType(locator, + change.TheExistential); break; } case PreparedOverload::Change::OpenedPackExpansionType: - cs.recordOpenedPackExpansionType( + recordOpenedPackExpansionType( change.PackExpansion.TheExpansion, change.PackExpansion.TypeVar); break; case PreparedOverload::Change::AppliedPropertyWrapper: { - auto *locatorPtr = cs.getConstraintLocator(locator); - Expr *anchor = getAsExpr(locatorPtr->getAnchor()); - cs.applyPropertyWrapper(anchor, + Expr *anchor = getAsExpr(locator->getAnchor()); + applyPropertyWrapper(anchor, { Type(change.PropertyWrapper.WrapperType), change.PropertyWrapper.InitKind }); break; } case PreparedOverload::Change::AddedFix: - cs.recordFix(change.Fix.TheFix, change.Fix.Impact); + recordFix(change.Fix.TheFix, change.Fix.Impact); break; } } } +/// Populate the prepared overload with all type variables and constraints +/// that are to be introduced into the constraint system when this choice +/// is taken. +/// +/// FIXME: As a transitional mechanism, if preparedOverload is nullptr, this +/// immediately performs all operations. +DeclReferenceType +ConstraintSystem::prepareOverloadImpl(ConstraintLocator *locator, + OverloadChoice choice, + DeclContext *useDC, + PreparedOverloadBuilder *preparedOverload) { + // If we refer to a top-level decl with special type-checking semantics, + // handle it now. + auto semantics = + TypeChecker::getDeclTypeCheckingSemantics(choice.getDecl()); + if (semantics != DeclTypeCheckingSemantics::Normal) { + return getTypeOfReferenceWithSpecialTypeCheckingSemantics( + *this, locator, semantics, preparedOverload); + } else if (auto baseTy = choice.getBaseType()) { + // Retrieve the type of a reference to the specific declaration choice. + assert(!baseTy->hasTypeParameter()); + + return getTypeOfMemberReference( + baseTy, choice.getDecl(), useDC, + (choice.getKind() == OverloadChoiceKind::DeclViaDynamic), + choice.getFunctionRefInfo(), locator, nullptr, preparedOverload); + } else { + return getTypeOfReference( + choice.getDecl(), choice.getFunctionRefInfo(), locator, useDC, + preparedOverload); + } +} + +PreparedOverload *ConstraintSystem::prepareOverload(ConstraintLocator *locator, + OverloadChoice choice, + DeclContext *useDC) { + ASSERT(!PreparingOverload); + PreparingOverload = true; + + PreparedOverloadBuilder builder; + auto declRefType = prepareOverloadImpl(locator, choice, useDC, &builder); + + PreparingOverload = false; + + size_t count = builder.Changes.size(); + auto size = PreparedOverload::totalSizeToAlloc(count); + auto mem = Allocator.Allocate(size, alignof(PreparedOverload)); + + return new (mem) PreparedOverload(declRefType, builder.Changes); +} + void ConstraintSystem::resolveOverload(ConstraintLocator *locator, Type boundType, OverloadChoice choice, - DeclContext *useDC) { + DeclContext *useDC, + PreparedOverload *preparedOverload) { // Determine the type to which we'll bind the overload set's type. Type openedType; Type adjustedOpenedType; @@ -2557,41 +2610,31 @@ void ConstraintSystem::resolveOverload(ConstraintLocator *locator, Type adjustedRefType; Type thrownErrorTypeOnAccess; - switch (auto kind = choice.getKind()) { + switch (choice.getKind()) { case OverloadChoiceKind::Decl: case OverloadChoiceKind::DeclViaBridge: case OverloadChoiceKind::DeclViaDynamic: case OverloadChoiceKind::DeclViaUnwrappedOptional: case OverloadChoiceKind::DynamicMemberLookup: case OverloadChoiceKind::KeyPathDynamicMemberLookup: { - // If we refer to a top-level decl with special type-checking semantics, - // handle it now. - const auto semantics = - TypeChecker::getDeclTypeCheckingSemantics(choice.getDecl()); - DeclReferenceType declRefType; - if (semantics != DeclTypeCheckingSemantics::Normal) { - declRefType = getTypeOfReferenceWithSpecialTypeCheckingSemantics( - *this, locator, semantics); - } else if (auto baseTy = choice.getBaseType()) { - // Retrieve the type of a reference to the specific declaration choice. - assert(!baseTy->hasTypeParameter()); - - declRefType = getTypeOfMemberReference( - baseTy, choice.getDecl(), useDC, - (kind == OverloadChoiceKind::DeclViaDynamic), - choice.getFunctionRefInfo(), locator, nullptr, - /*preparedOverload=*/nullptr); + if (preparedOverload) { + replayChanges(locator, preparedOverload); + + openedType = preparedOverload->getOpenedType(); + adjustedOpenedType = preparedOverload->getAdjustedOpenedType(); + refType = preparedOverload->getReferenceType(); + adjustedRefType = preparedOverload->getAdjustedReferenceType(); + thrownErrorTypeOnAccess = preparedOverload->getThrownErrorTypeOnAccess(); } else { - declRefType = getTypeOfReference( - choice.getDecl(), choice.getFunctionRefInfo(), locator, useDC, - /*preparedOverload=*/nullptr); + auto declRefType = prepareOverloadImpl(locator, choice, useDC, nullptr); + + openedType = declRefType.openedType; + adjustedOpenedType = declRefType.adjustedOpenedType; + refType = declRefType.referenceType; + adjustedRefType = declRefType.adjustedReferenceType; + thrownErrorTypeOnAccess = declRefType.thrownErrorTypeOnAccess; } - openedType = declRefType.openedType; - adjustedOpenedType = declRefType.adjustedOpenedType; - refType = declRefType.referenceType; - adjustedRefType = declRefType.adjustedReferenceType; - thrownErrorTypeOnAccess = declRefType.thrownErrorTypeOnAccess; break; }