@@ -944,7 +944,6 @@ namespace {
944944 class ConstraintGenerator : public ExprVisitor <ConstraintGenerator, Type> {
945945 ConstraintSystem &CS;
946946 DeclContext *CurDC;
947- ConstraintSystemPhase CurrPhase;
948947
949948 // / A map from each UnresolvedMemberExpr to the respective (implicit) base
950949 // / found during our walk.
@@ -1158,6 +1157,33 @@ namespace {
11581157 if (addedTypeVars)
11591158 addedTypeVars->push_back (memberTy);
11601159
1160+ SmallVector<AnyFunctionType::Param, 8 > params;
1161+ getMatchingParams (argList, params);
1162+
1163+ // Add the constraint that the index expression's type be convertible
1164+ // to the input type of the subscript operator.
1165+ auto addApplicableFn = [&]() {
1166+ CS.addApplicationConstraint (
1167+ FunctionType::get (params, outputTy), memberTy,
1168+ /* trailingClosureMatching=*/ std::nullopt , CurDC, fnLocator);
1169+ };
1170+
1171+ // If we have a dynamic member base we need to add the applicable function
1172+ // first since solving the member constraint requires the constraint to be
1173+ // available since it may retire it. We can't yet do this in the general
1174+ // case since the simplifying of the applicable fn in CSGen is currently
1175+ // load-bearing for existential opening.
1176+ // FIXME: Once existential opening is no longer sensitive to solving
1177+ // order, we ought to be able to just always record the applicable fn as
1178+ // an unsolved constraint before the member.
1179+ auto hasDynamicMemberLookup = CS.simplifyType (baseTy)
1180+ ->getRValueType ()
1181+ ->getMetatypeInstanceType ()
1182+ ->eraseDynamicSelfType ()
1183+ ->hasDynamicMemberLookupAttribute ();
1184+ if (hasDynamicMemberLookup)
1185+ addApplicableFn ();
1186+
11611187 // FIXME: synthesizeMaterializeForSet() wants to statically dispatch to
11621188 // a known subscript here. This might be cleaner if we split off a new
11631189 // UnresolvedSubscriptExpr from SubscriptExpr.
@@ -1173,14 +1199,10 @@ namespace {
11731199 /* outerAlternatives=*/ {}, memberLocator);
11741200 }
11751201
1176- SmallVector<AnyFunctionType::Param, 8 > params;
1177- getMatchingParams (argList, params);
1178-
1179- // Add the constraint that the index expression's type be convertible
1180- // to the input type of the subscript operator.
1181- CS.addApplicationConstraint (FunctionType::get (params, outputTy), memberTy,
1182- /* trailingClosureMatching=*/ std::nullopt ,
1183- CurDC, fnLocator);
1202+ // If we don't have a dynamic member, we add the application after the
1203+ // member, see the above comment.
1204+ if (!hasDynamicMemberLookup)
1205+ addApplicableFn ();
11841206
11851207 if (CS.performanceHacksEnabled ()) {
11861208 Type fixedOutputType =
@@ -1250,23 +1272,15 @@ namespace {
12501272
12511273 public:
12521274 ConstraintGenerator (ConstraintSystem &CS, DeclContext *DC)
1253- : CS(CS), CurDC(DC ? DC : CS.DC), CurrPhase(CS.getPhase()) {
1254- // Although constraint system is initialized in `constraint
1255- // generation` phase, we have to set it here manually because e.g.
1256- // result builders could generate constraints for its body
1257- // in the middle of the solving.
1258- CS.setPhase (ConstraintSystemPhase::ConstraintGeneration);
1259-
1275+ : CS(CS), CurDC(DC ? DC : CS.DC) {
12601276 // Pick up the saved stack of pack expansions so we can continue
12611277 // to handle pack element references inside the closure body.
12621278 if (auto *ACE = dyn_cast<AbstractClosureExpr>(CurDC)) {
12631279 OuterExpansions = CS.getCapturedExpansions (ACE);
12641280 }
12651281 }
12661282
1267- virtual ~ConstraintGenerator () {
1268- CS.setPhase (CurrPhase);
1269- }
1283+ virtual ~ConstraintGenerator () = default ;
12701284
12711285 ConstraintSystem &getConstraintSystem () const { return CS; }
12721286
0 commit comments