@@ -303,6 +303,72 @@ namespace {
303303 // solver can still make progress.
304304 auto favoredTy = (*lti.collectedTypes .begin ())->getWithoutSpecifierType ();
305305 CS.setFavoredType (expr, favoredTy.getPointer ());
306+
307+ // If we have a chain of identical binop expressions with homogeneous
308+ // argument types, we can directly simplify the associated constraint
309+ // graph.
310+ auto simplifyBinOpExprTyVars = [&]() {
311+ // Don't attempt to do linking if there are
312+ // literals intermingled with other inferred types.
313+ if (lti.hasLiteral )
314+ return ;
315+
316+ for (auto binExp1 : lti.binaryExprs ) {
317+ for (auto binExp2 : lti.binaryExprs ) {
318+ if (binExp1 == binExp2)
319+ continue ;
320+
321+ auto fnTy1 = CS.getType (binExp1)->getAs <TypeVariableType>();
322+ auto fnTy2 = CS.getType (binExp2)->getAs <TypeVariableType>();
323+
324+ if (!(fnTy1 && fnTy2))
325+ return ;
326+
327+ auto ODR1 = dyn_cast<OverloadedDeclRefExpr>(binExp1->getFn ());
328+ auto ODR2 = dyn_cast<OverloadedDeclRefExpr>(binExp2->getFn ());
329+
330+ if (!(ODR1 && ODR2))
331+ return ;
332+
333+ // TODO: We currently limit this optimization to known arithmetic
334+ // operators, but we should be able to broaden this out to
335+ // logical operators as well.
336+ if (!isArithmeticOperatorDecl (ODR1->getDecls ()[0 ]))
337+ return ;
338+
339+ if (ODR1->getDecls ()[0 ]->getBaseName () !=
340+ ODR2->getDecls ()[0 ]->getBaseName ())
341+ return ;
342+
343+ // All things equal, we can merge the tyvars for the function
344+ // types.
345+ auto rep1 = CS.getRepresentative (fnTy1);
346+ auto rep2 = CS.getRepresentative (fnTy2);
347+
348+ if (rep1 != rep2) {
349+ CS.mergeEquivalenceClasses (rep1, rep2,
350+ /* updateWorkList*/ false );
351+ }
352+
353+ auto odTy1 = CS.getType (ODR1)->getAs <TypeVariableType>();
354+ auto odTy2 = CS.getType (ODR2)->getAs <TypeVariableType>();
355+
356+ if (odTy1 && odTy2) {
357+ auto odRep1 = CS.getRepresentative (odTy1);
358+ auto odRep2 = CS.getRepresentative (odTy2);
359+
360+ // Since we'll be choosing the same overload, we can merge
361+ // the overload tyvar as well.
362+ if (odRep1 != odRep2)
363+ CS.mergeEquivalenceClasses (odRep1, odRep2,
364+ /* updateWorkList*/ false );
365+ }
366+ }
367+ }
368+ };
369+
370+ simplifyBinOpExprTyVars ();
371+
306372 return true ;
307373 }
308374
0 commit comments