@@ -92,366 +92,6 @@ static bool mergeRepresentativeEquivalenceClasses(ConstraintSystem &CS,
92
92
}
93
93
94
94
namespace {
95
-
96
- // / Internal struct for tracking information about types within a series
97
- // / of "linked" expressions. (Such as a chain of binary operator invocations.)
98
- struct LinkedTypeInfo {
99
- unsigned haveIntLiteral : 1 ;
100
- unsigned haveFloatLiteral : 1 ;
101
- unsigned haveStringLiteral : 1 ;
102
-
103
- llvm::SmallSet<TypeBase*, 16 > collectedTypes;
104
-
105
- llvm::SmallVector<TypeVariableType *, 16 > intLiteralTyvars;
106
- llvm::SmallVector<TypeVariableType *, 16 > floatLiteralTyvars;
107
- llvm::SmallVector<TypeVariableType *, 16 > stringLiteralTyvars;
108
-
109
- llvm::SmallVector<BinaryExpr *, 4 > binaryExprs;
110
-
111
- // TODO: manage as a set of lists, to speed up addition of binding
112
- // constraints.
113
- llvm::SmallVector<DeclRefExpr *, 16 > anonClosureParams;
114
-
115
- LinkedTypeInfo () {
116
- haveIntLiteral = false ;
117
- haveFloatLiteral = false ;
118
- haveStringLiteral = false ;
119
- }
120
-
121
- bool hasLiteral () {
122
- return haveIntLiteral || haveFloatLiteral || haveStringLiteral;
123
- }
124
- };
125
-
126
- // / Walks an expression sub-tree, and collects information about expressions
127
- // / whose types are mutually dependent upon one another.
128
- class LinkedExprCollector : public ASTWalker {
129
-
130
- llvm::SmallVectorImpl<Expr*> &LinkedExprs;
131
- ConstraintSystem &CS;
132
-
133
- public:
134
- LinkedExprCollector (llvm::SmallVectorImpl<Expr *> &linkedExprs,
135
- ConstraintSystem &cs)
136
- : LinkedExprs(linkedExprs), CS(cs) {}
137
-
138
- std::pair<bool , Expr *> walkToExprPre (Expr *expr) override {
139
-
140
- if (CS.shouldReusePrecheckedType () &&
141
- !CS.getType (expr)->hasTypeVariable ()) {
142
- return { false , expr };
143
- }
144
-
145
- // Store top-level binary exprs for further analysis.
146
- if (isa<BinaryExpr>(expr) ||
147
-
148
- // Literal exprs are contextually typed, so store them off as well.
149
- isa<LiteralExpr>(expr) ||
150
-
151
- // We'd like to take a look at implicit closure params, so store
152
- // them.
153
- isa<ClosureExpr>(expr) ||
154
-
155
- // We'd like to look at the elements of arrays and dictionaries.
156
- isa<ArrayExpr>(expr) ||
157
- isa<DictionaryExpr>(expr) ||
158
-
159
- // assignment expression can involve anonymous closure parameters
160
- // as source and destination, so it's beneficial for diagnostics if
161
- // we look at the assignment.
162
- isa<AssignExpr>(expr)) {
163
- LinkedExprs.push_back (expr);
164
- return {false , expr};
165
- }
166
-
167
- return { true , expr };
168
- }
169
-
170
- Expr *walkToExprPost (Expr *expr) override {
171
- return expr;
172
- }
173
-
174
- // / Ignore statements.
175
- std::pair<bool , Stmt *> walkToStmtPre (Stmt *stmt) override {
176
- return { false , stmt };
177
- }
178
-
179
- // / Ignore declarations.
180
- bool walkToDeclPre (Decl *decl) override { return false ; }
181
-
182
- // / Ignore patterns.
183
- std::pair<bool , Pattern*> walkToPatternPre (Pattern *pat) override {
184
- return { false , pat };
185
- }
186
-
187
- // / Ignore types.
188
- bool walkToTypeLocPre (TypeLoc &TL) override { return false ; }
189
- };
190
-
191
- // / Given a collection of "linked" expressions, analyzes them for
192
- // / commonalities regarding their types. This will help us compute a
193
- // / "best common type" from the expression types.
194
- class LinkedExprAnalyzer : public ASTWalker {
195
-
196
- LinkedTypeInfo <I;
197
- ConstraintSystem &CS;
198
-
199
- public:
200
-
201
- LinkedExprAnalyzer (LinkedTypeInfo <i, ConstraintSystem &cs) :
202
- LTI (lti), CS(cs) {}
203
-
204
- std::pair<bool , Expr *> walkToExprPre (Expr *expr) override {
205
-
206
- if (CS.shouldReusePrecheckedType () &&
207
- !CS.getType (expr)->hasTypeVariable ()) {
208
- return { false , expr };
209
- }
210
-
211
- if (isa<IntegerLiteralExpr>(expr)) {
212
- LTI.haveIntLiteral = true ;
213
- auto tyvar = CS.getType (expr)->getAs <TypeVariableType>();
214
-
215
- if (tyvar) {
216
- LTI.intLiteralTyvars .push_back (tyvar);
217
- }
218
-
219
- return { false , expr };
220
- }
221
-
222
- if (isa<FloatLiteralExpr>(expr)) {
223
- LTI.haveFloatLiteral = true ;
224
- auto tyvar = CS.getType (expr)->getAs <TypeVariableType>();
225
-
226
- if (tyvar) {
227
- LTI.floatLiteralTyvars .push_back (tyvar);
228
- }
229
-
230
- return { false , expr };
231
- }
232
-
233
- if (isa<StringLiteralExpr>(expr)) {
234
- LTI.haveStringLiteral = true ;
235
-
236
- auto tyvar = CS.getType (expr)->getAs <TypeVariableType>();
237
-
238
- if (tyvar) {
239
- LTI.stringLiteralTyvars .push_back (tyvar);
240
- }
241
-
242
- return { false , expr };
243
- }
244
-
245
- if (isa<CollectionExpr>(expr)) {
246
- return { true , expr };
247
- }
248
-
249
- if (auto UDE = dyn_cast<UnresolvedDotExpr>(expr)) {
250
-
251
- if (CS.hasType (UDE))
252
- LTI.collectedTypes .insert (CS.getType (UDE).getPointer ());
253
-
254
- // Don't recurse into the base expression.
255
- return { false , expr };
256
- }
257
-
258
-
259
- if (isa<ClosureExpr>(expr)) {
260
- return { true , expr };
261
- }
262
-
263
- if (auto FVE = dyn_cast<ForceValueExpr>(expr)) {
264
- LTI.collectedTypes .insert (CS.getType (FVE).getPointer ());
265
- return { false , expr };
266
- }
267
-
268
- if (auto DRE = dyn_cast<DeclRefExpr>(expr)) {
269
- if (auto varDecl = dyn_cast<VarDecl>(DRE->getDecl ())) {
270
- if (isa<ParamDecl>(varDecl) &&
271
- cast<ParamDecl>(varDecl)->isAnonClosureParam ()) {
272
- LTI.anonClosureParams .push_back (DRE);
273
- } else if (CS.hasType (DRE)) {
274
- LTI.collectedTypes .insert (CS.getType (DRE).getPointer ());
275
- }
276
- return { false , expr };
277
- }
278
- }
279
-
280
- // In the case of a function application, we would have already captured
281
- // the return type during constraint generation, so there's no use in
282
- // looking any further.
283
- if (isa<ApplyExpr>(expr) &&
284
- !(isa<BinaryExpr>(expr) || isa<PrefixUnaryExpr>(expr) ||
285
- isa<PostfixUnaryExpr>(expr))) {
286
- return { false , expr };
287
- }
288
-
289
- if (isa<BinaryExpr>(expr)) {
290
- LTI.binaryExprs .push_back (dyn_cast<BinaryExpr>(expr));
291
- }
292
-
293
- if (auto favoredType = CS.getFavoredType (expr)) {
294
- LTI.collectedTypes .insert (favoredType);
295
-
296
- return { false , expr };
297
- }
298
-
299
- // Optimize branches of a conditional expression separately.
300
- if (auto IE = dyn_cast<IfExpr>(expr)) {
301
- CS.optimizeConstraints (IE->getCondExpr ());
302
- CS.optimizeConstraints (IE->getThenExpr ());
303
- CS.optimizeConstraints (IE->getElseExpr ());
304
- return { false , expr };
305
- }
306
-
307
- // For exprs of a structural type that are not modeling argument lists,
308
- // avoid merging the type variables. (We need to allow for cases like
309
- // (Int, Int32).)
310
- if (isa<TupleExpr>(expr) && !isa<ApplyExpr>(Parent.getAsExpr ())) {
311
- return { false , expr };
312
- }
313
-
314
- // Coercion exprs have a rigid type, so there's no use in gathering info
315
- // about them.
316
- if (auto *coercion = dyn_cast<CoerceExpr>(expr)) {
317
- // Let's not collect information about types initialized by
318
- // coercions just like we don't for regular initializer calls,
319
- // because that might lead to overly eager type variable merging.
320
- if (!coercion->isLiteralInit ())
321
- LTI.collectedTypes .insert (CS.getType (expr).getPointer ());
322
- return { false , expr };
323
- }
324
-
325
- // Don't walk into subscript expressions - to do so would risk factoring
326
- // the index expression into edge contraction. (We don't want to do this
327
- // if the index expression is a literal type that differs from the return
328
- // type of the subscript operation.)
329
- if (isa<SubscriptExpr>(expr) || isa<DynamicLookupExpr>(expr)) {
330
- return { false , expr };
331
- }
332
-
333
- // Don't walk into unresolved member expressions - we avoid merging type
334
- // variables inside UnresolvedMemberExpr and those outside, since they
335
- // should be allowed to behave independently in CS.
336
- if (isa<UnresolvedMemberExpr>(expr)) {
337
- return {false , expr };
338
- }
339
-
340
- return { true , expr };
341
- }
342
-
343
- // / Ignore statements.
344
- std::pair<bool , Stmt *> walkToStmtPre (Stmt *stmt) override {
345
- return { false , stmt };
346
- }
347
-
348
- // / Ignore declarations.
349
- bool walkToDeclPre (Decl *decl) override { return false ; }
350
-
351
- // / Ignore patterns.
352
- std::pair<bool , Pattern*> walkToPatternPre (Pattern *pat) override {
353
- return { false , pat };
354
- }
355
-
356
- // / Ignore types.
357
- bool walkToTypeLocPre (TypeLoc &TL) override { return false ; }
358
- };
359
-
360
- // / For a given expression, given information that is global to the
361
- // / expression, attempt to derive a favored type for it.
362
- bool computeFavoredTypeForExpr (Expr *expr, ConstraintSystem &CS) {
363
- LinkedTypeInfo lti;
364
-
365
- expr->walk (LinkedExprAnalyzer (lti, CS));
366
-
367
- // Link anonymous closure params of the same index.
368
- // TODO: As stated above, we should bucket these whilst collecting the
369
- // exprs to avoid quadratic behavior.
370
- for (auto acp1 : lti.anonClosureParams ) {
371
- for (auto acp2 : lti.anonClosureParams ) {
372
- if (acp1 == acp2)
373
- continue ;
374
-
375
- if (acp1->getDecl ()->getBaseName () == acp2->getDecl ()->getBaseName ()) {
376
-
377
- auto tyvar1 = CS.getType (acp1)->getAs <TypeVariableType>();
378
- auto tyvar2 = CS.getType (acp2)->getAs <TypeVariableType>();
379
-
380
- mergeRepresentativeEquivalenceClasses (CS, tyvar1, tyvar2);
381
- }
382
- }
383
- }
384
-
385
- auto mergeTypeVariables = [&](ArrayRef<TypeVariableType *> typeVars) {
386
- if (typeVars.size () < 2 )
387
- return ;
388
-
389
- auto rep1 = CS.getRepresentative (typeVars.front ());
390
- for (unsigned i = 1 , n = typeVars.size (); i != n; ++i) {
391
- auto rep2 = CS.getRepresentative (typeVars[i]);
392
- if (rep1 != rep2)
393
- CS.mergeEquivalenceClasses (rep1, rep2, /* updateWorkList*/ false );
394
- }
395
- };
396
-
397
- mergeTypeVariables (lti.intLiteralTyvars );
398
- mergeTypeVariables (lti.floatLiteralTyvars );
399
- mergeTypeVariables (lti.stringLiteralTyvars );
400
-
401
- if (lti.collectedTypes .size () == 1 ) {
402
- // TODO: Compute the BCT.
403
-
404
- // It's only useful to favor the type instead of
405
- // binding it directly to arguments/result types,
406
- // which means in case it has been miscalculated
407
- // solver can still make progress.
408
- auto favoredTy = (*lti.collectedTypes .begin ())->getWithoutSpecifierType ();
409
- CS.setFavoredType (expr, favoredTy.getPointer ());
410
- return true ;
411
- }
412
-
413
- if (lti.haveFloatLiteral ) {
414
- if (auto floatProto =
415
- CS.TC .Context .getProtocol (
416
- KnownProtocolKind::ExpressibleByFloatLiteral)) {
417
- if (auto defaultType = CS.TC .getDefaultType (floatProto, CS.DC )) {
418
- if (!CS.getFavoredType (expr)) {
419
- CS.setFavoredType (expr, defaultType.getPointer ());
420
- }
421
- return true ;
422
- }
423
- }
424
- }
425
-
426
- if (lti.haveIntLiteral ) {
427
- if (auto intProto =
428
- CS.TC .Context .getProtocol (
429
- KnownProtocolKind::ExpressibleByIntegerLiteral)) {
430
- if (auto defaultType = CS.TC .getDefaultType (intProto, CS.DC )) {
431
- if (!CS.getFavoredType (expr)) {
432
- CS.setFavoredType (expr, defaultType.getPointer ());
433
- }
434
- return true ;
435
- }
436
- }
437
- }
438
-
439
- if (lti.haveStringLiteral ) {
440
- if (auto stringProto =
441
- CS.TC .Context .getProtocol (
442
- KnownProtocolKind::ExpressibleByStringLiteral)) {
443
- if (auto defaultType = CS.TC .getDefaultType (stringProto, CS.DC )) {
444
- if (!CS.getFavoredType (expr)) {
445
- CS.setFavoredType (expr, defaultType.getPointer ());
446
- }
447
- return true ;
448
- }
449
- }
450
- }
451
-
452
- return false ;
453
- }
454
-
455
95
// / Determine whether the given parameter type and argument should be
456
96
// / "favored" because they match exactly.
457
97
bool isFavoredParamAndArg (ConstraintSystem &CS,
@@ -3658,17 +3298,6 @@ void ConstraintSystem::optimizeConstraints(Expr *e) {
3658
3298
if (TC.getLangOpts ().DisableConstraintSolverPerformanceHacks )
3659
3299
return ;
3660
3300
3661
- SmallVector<Expr *, 16 > linkedExprs;
3662
-
3663
- // Collect any linked expressions.
3664
- LinkedExprCollector collector (linkedExprs, *this );
3665
- e->walk (collector);
3666
-
3667
- // Favor types, as appropriate.
3668
- for (auto linkedExpr : linkedExprs) {
3669
- computeFavoredTypeForExpr (linkedExpr, *this );
3670
- }
3671
-
3672
3301
// Optimize the constraints.
3673
3302
ConstraintOptimizer optimizer (*this );
3674
3303
e->walk (optimizer);
0 commit comments