@@ -220,34 +220,27 @@ struct LiteralRequirement {
220
220
};
221
221
222
222
struct PotentialBindings {
223
- using BindingScore =
224
- std::tuple<bool , bool , bool , bool , bool , unsigned char , int >;
225
-
226
223
// / The constraint system this type variable and its bindings belong to.
227
224
ConstraintSystem &CS;
228
225
229
226
TypeVariableType *TypeVar;
230
227
231
228
// / The set of potential bindings.
232
- llvm::SmallSetVector <PotentialBinding, 4 > Bindings;
229
+ llvm::SmallVector <PotentialBinding, 4 > Bindings;
233
230
234
231
// / The set of protocol requirements placed on this type variable.
235
232
llvm::SmallVector<Constraint *, 4 > Protocols;
236
233
237
- // / The set of transitive protocol requirements inferred through
238
- // / subtype/conversion/equivalence relations with other type variables.
239
- llvm::Optional<llvm::SmallPtrSet<Constraint *, 4 >> TransitiveProtocols;
240
-
241
234
// / The set of unique literal protocol requirements placed on this
242
235
// / type variable or inferred transitively through subtype chains.
243
236
// /
244
237
// / Note that ordering is important when it comes to bindings, we'd
245
238
// / like to add any "direct" default types first to attempt them
246
239
// / before transitive ones.
247
- llvm::SmallMapVector<ProtocolDecl *, LiteralRequirement , 2 > Literals;
240
+ llvm::SmallPtrSet<Constraint * , 2 > Literals;
248
241
249
242
// / The set of constraints which would be used to infer default types.
250
- llvm::SmallDenseMap<CanType, Constraint *, 2 > Defaults;
243
+ llvm::SmallPtrSet< Constraint *, 2 > Defaults;
251
244
252
245
// / The set of constraints which delay attempting this type variable.
253
246
llvm::TinyPtrVector<Constraint *> DelayedBy;
@@ -274,49 +267,81 @@ struct PotentialBindings {
274
267
PotentialBindings (ConstraintSystem &cs, TypeVariableType *typeVar)
275
268
: CS(cs), TypeVar(typeVar) {}
276
269
277
- // / Determine whether the set of bindings is non-empty.
278
- explicit operator bool () const {
279
- return hasViableBindings ()|| isDirectHole ();
280
- }
270
+ void addDefault (Constraint *constraint);
281
271
282
- // / Determine whether this set has any "viable" (or non-hole) bindings.
283
- // /
284
- // / A viable binding could be - a direct or transitive binding
285
- // / inferred from a constraint, literal binding, or defaltable
286
- // / binding.
287
- // /
288
- // / A hole is not considered a viable binding since it doesn't
289
- // / add any new type information to constraint system.
290
- bool hasViableBindings () const {
291
- return !Bindings.empty () || getNumViableLiteralBindings () > 0 ||
292
- !Defaults.empty ();
272
+ void addLiteral (Constraint *constraint);
273
+
274
+ // / Add a potential binding to the list of bindings,
275
+ // / coalescing supertype bounds when we are able to compute the meet.
276
+ void addPotentialBinding (PotentialBinding binding);
277
+
278
+ // / Check if this binding is viable for inclusion in the set.
279
+ bool isViable (PotentialBinding &binding) const ;
280
+
281
+ bool isGenericParameter () const ;
282
+
283
+ bool isSubtypeOf (TypeVariableType *typeVar) const {
284
+ auto result = SubtypeOf.find (typeVar);
285
+ if (result == SubtypeOf.end ())
286
+ return false ;
287
+
288
+ auto *constraint = result->second ;
289
+ return constraint->getKind () == ConstraintKind::Subtype;
293
290
}
294
291
295
- // / Determines whether this type variable could be `nil`,
296
- // / which means that all of its bindings should be optional.
297
- bool canBeNil () const ;
292
+ private:
293
+ // / Attempt to infer a new binding and other useful information
294
+ // / (i.e. whether bindings should be delayed) from the given
295
+ // / relational constraint.
296
+ Optional<PotentialBinding> inferFromRelational (Constraint *constraint);
298
297
299
- // / Determine whether attempting this type variable should be
300
- // / delayed until the rest of the constraint system is considered
301
- // / "fully bound" meaning constraints, which affect completeness
302
- // / of the binding set, for this type variable such as - member
303
- // / constraint, disjunction, function application etc. - are simplified .
298
+ public:
299
+ void infer (Constraint * constraint);
300
+
301
+ // / Retract all bindings and other information related to a given
302
+ // / constraint from this binding set .
304
303
// /
305
- // / Note that in some situations i.e. when there are no more
306
- // / disjunctions or type variables left to attempt, it's still
307
- // / okay to attempt "delayed" type variable to make forward progress.
308
- bool isDelayed () const ;
304
+ // / This would happen when constraint is simplified or solver backtracks
305
+ // / (either from overload choice or (some) type variable binding).
306
+ void retract (Constraint *constraint);
307
+ } ;
309
308
310
- // / Whether the bindings of this type involve other type variables,
311
- // / or the type variable itself is adjacent to other type variables
312
- // / that could become valid bindings in the future.
313
- bool involvesTypeVariables () const ;
309
+ class BindingSet {
310
+ using BindingScore =
311
+ std::tuple<bool , bool , bool , bool , bool , unsigned char , int >;
314
312
315
- // / Whether the bindings represent (potentially) incomplete set,
316
- // / there is no way to say with absolute certainty if that's the
317
- // / case, but that could happen when certain constraints like
318
- // / `bind param` are present in the system.
319
- bool isPotentiallyIncomplete () const ;
313
+ ConstraintSystem &CS;
314
+
315
+ TypeVariableType *TypeVar;
316
+
317
+ PotentialBindings Info;
318
+
319
+ public:
320
+ llvm::SmallSetVector<PotentialBinding, 4 > Bindings;
321
+ llvm::SmallMapVector<ProtocolDecl *, LiteralRequirement, 2 > Literals;
322
+ llvm::SmallDenseMap<CanType, Constraint *, 2 > Defaults;
323
+
324
+ // / The set of transitive protocol requirements inferred through
325
+ // / subtype/conversion/equivalence relations with other type variables.
326
+ llvm::Optional<llvm::SmallPtrSet<Constraint *, 4 >> TransitiveProtocols;
327
+
328
+ BindingSet (const PotentialBindings info)
329
+ : CS(info.CS), TypeVar(info.TypeVar), Info(info) {
330
+ for (auto *literal : info.Literals )
331
+ addLiteralRequirement (literal);
332
+
333
+ for (const auto &binding : info.Bindings )
334
+ addBinding (binding);
335
+
336
+ for (auto *constraint : info.Defaults )
337
+ addDefault (constraint);
338
+ }
339
+
340
+ ConstraintSystem &getConstraintSystem () const { return CS; }
341
+
342
+ TypeVariableType *getTypeVariable () const { return Info.TypeVar ; }
343
+
344
+ bool canBeNil () const ;
320
345
321
346
// / If this type variable doesn't have any viable bindings, or
322
347
// / if there is only one binding and it's a placeholder type, consider
@@ -340,6 +365,28 @@ struct PotentialBindings {
340
365
// / bound to a placeholder type.
341
366
bool isDirectHole () const ;
342
367
368
+ // / Determine whether attempting this type variable should be
369
+ // / delayed until the rest of the constraint system is considered
370
+ // / "fully bound" meaning constraints, which affect completeness
371
+ // / of the binding set, for this type variable such as - member
372
+ // / constraint, disjunction, function application etc. - are simplified.
373
+ // /
374
+ // / Note that in some situations i.e. when there are no more
375
+ // / disjunctions or type variables left to attempt, it's still
376
+ // / okay to attempt "delayed" type variable to make forward progress.
377
+ bool isDelayed () const ;
378
+
379
+ // / Whether the bindings of this type involve other type variables,
380
+ // / or the type variable itself is adjacent to other type variables
381
+ // / that could become valid bindings in the future.
382
+ bool involvesTypeVariables () const ;
383
+
384
+ // / Whether the bindings represent (potentially) incomplete set,
385
+ // / there is no way to say with absolute certainty if that's the
386
+ // / case, but that could happen when certain constraints like
387
+ // / `bind param` are present in the system.
388
+ bool isPotentiallyIncomplete () const ;
389
+
343
390
// / Determine if the bindings only constrain the type variable from above
344
391
// / with an existential type; such a binding is not very helpful because
345
392
// / it's impossible to enumerate the existential type's subtypes.
@@ -353,6 +400,29 @@ struct PotentialBindings {
353
400
});
354
401
}
355
402
403
+ explicit operator bool () const {
404
+ return hasViableBindings () || isDirectHole ();
405
+ }
406
+
407
+ // / Determine whether this set has any "viable" (or non-hole) bindings.
408
+ // /
409
+ // / A viable binding could be - a direct or transitive binding
410
+ // / inferred from a constraint, literal binding, or defaltable
411
+ // / binding.
412
+ // /
413
+ // / A hole is not considered a viable binding since it doesn't
414
+ // / add any new type information to constraint system.
415
+ bool hasViableBindings () const {
416
+ return !Bindings.empty () || getNumViableLiteralBindings () > 0 ||
417
+ !Defaults.empty ();
418
+ }
419
+
420
+ LiteralBindingKind getLiteralKind () const ;
421
+
422
+ ArrayRef<Constraint *> getConformanceRequirements () const {
423
+ return Info.Protocols ;
424
+ }
425
+
356
426
unsigned getNumViableLiteralBindings () const ;
357
427
358
428
unsigned getNumViableDefaultableBindings () const {
@@ -383,46 +453,8 @@ struct PotentialBindings {
383
453
return numDefaultable - unviable;
384
454
}
385
455
386
- static BindingScore formBindingScore (const PotentialBindings &b);
387
-
388
- // / Compare two sets of bindings, where \c x < y indicates that
389
- // / \c x is a better set of bindings that \c y.
390
- friend bool operator <(const PotentialBindings &x,
391
- const PotentialBindings &y) {
392
- auto xScore = formBindingScore (x);
393
- auto yScore = formBindingScore (y);
394
-
395
- if (xScore < yScore)
396
- return true ;
397
-
398
- if (yScore < xScore)
399
- return false ;
400
-
401
- auto xDefaults = x.getNumViableDefaultableBindings ();
402
- auto yDefaults = y.getNumViableDefaultableBindings ();
403
-
404
- // If there is a difference in number of default types,
405
- // prioritize bindings with fewer of them.
406
- if (xDefaults != yDefaults)
407
- return xDefaults < yDefaults;
408
-
409
- // If neither type variable is a "hole" let's check whether
410
- // there is a subtype relationship between them and prefer
411
- // type variable which represents superclass first in order
412
- // for "subtype" type variable to attempt more bindings later.
413
- // This is required because algorithm can't currently infer
414
- // bindings for subtype transitively through superclass ones.
415
- if (!(std::get<0 >(xScore) && std::get<0 >(yScore))) {
416
- if (x.isSubtypeOf (y.TypeVar ))
417
- return false ;
418
-
419
- if (y.isSubtypeOf (x.TypeVar ))
420
- return true ;
421
- }
422
-
423
- // As a last resort, let's check if the bindings are
424
- // potentially incomplete, and if so, let's de-prioritize them.
425
- return x.isPotentiallyIncomplete () < y.isPotentiallyIncomplete ();
456
+ ASTNode getAssociatedCodeCompletionToken () const {
457
+ return Info.AssociatedCodeCompletionToken ;
426
458
}
427
459
428
460
LiteralBindingKind getLiteralKind () const ;
@@ -464,41 +496,78 @@ struct PotentialBindings {
464
496
// / \param inferredBindings The set of all bindings inferred for type
465
497
// / variables in the workset.
466
498
void inferTransitiveBindings (
467
- const llvm::SmallDenseMap<TypeVariableType *, PotentialBindings >
499
+ const llvm::SmallDenseMap<TypeVariableType *, BindingSet >
468
500
&inferredBindings);
469
501
470
502
// / Detect subtype, conversion or equivalence relationship
471
503
// / between two type variables and attempt to propagate protocol
472
504
// / requirements down the subtype or equivalence chain.
473
505
void inferTransitiveProtocolRequirements (
474
- llvm::SmallDenseMap<TypeVariableType *, PotentialBindings>
475
- &inferredBindings);
506
+ llvm::SmallDenseMap<TypeVariableType *, BindingSet> &inferredBindings);
476
507
477
- // / Attempt to infer a new binding and other useful information
478
- // / (i.e. whether bindings should be delayed) from the given
479
- // / relational constraint.
480
- Optional<PotentialBinding> inferFromRelational (Constraint *constraint );
508
+ // / Finalize binding computation for this type variable by
509
+ // / inferring bindings from context e.g. transitive bindings.
510
+ void finalize (
511
+ llvm::SmallDenseMap<TypeVariableType *, BindingSet> &inferredBindings );
481
512
482
- public:
483
- void infer (Constraint *constraint);
513
+ // / Check if this binding is favored over a disjunction e.g.
514
+ // / if it has only concrete types or would resolve a closure.
515
+ bool favoredOverDisjunction (Constraint *disjunction) const ;
484
516
485
- // / Retract all bindings and other information related to a given
486
- // / constraint from this binding set.
487
- // /
488
- // / This would happen when constraint is simplified or solver backtracks
489
- // / (either from overload choice or (some) type variable binding).
490
- void retract (Constraint *constraint);
517
+ static BindingScore formBindingScore (const BindingSet &b);
491
518
492
- // / Finalize binding computation for this type variable by
493
- // / inferring bindings from context e.g. transitive bindings.
494
- void finalize (llvm::SmallDenseMap<TypeVariableType *, PotentialBindings>
495
- &inferredBindings);
519
+ // / Compare two sets of bindings, where \c x < y indicates that
520
+ // / \c x is a better set of bindings that \c y.
521
+ friend bool operator <(const BindingSet &x, const BindingSet &y) {
522
+ auto xScore = formBindingScore (x);
523
+ auto yScore = formBindingScore (y);
524
+
525
+ if (xScore < yScore)
526
+ return true ;
527
+
528
+ if (yScore < xScore)
529
+ return false ;
496
530
497
- void dump (llvm::raw_ostream &out,
498
- unsigned indent = 0 ) const LLVM_ATTRIBUTE_USED;
531
+ auto xDefaults = x.getNumViableDefaultableBindings ();
532
+ auto yDefaults = y.getNumViableDefaultableBindings ();
533
+
534
+ // If there is a difference in number of default types,
535
+ // prioritize bindings with fewer of them.
536
+ if (xDefaults != yDefaults)
537
+ return xDefaults < yDefaults;
499
538
539
+ // If neither type variable is a "hole" let's check whether
540
+ // there is a subtype relationship between them and prefer
541
+ // type variable which represents superclass first in order
542
+ // for "subtype" type variable to attempt more bindings later.
543
+ // This is required because algorithm can't currently infer
544
+ // bindings for subtype transitively through superclass ones.
545
+ if (!(std::get<0 >(xScore) && std::get<0 >(yScore))) {
546
+ if (x.Info .isSubtypeOf (y.getTypeVariable ()))
547
+ return false ;
548
+
549
+ if (y.Info .isSubtypeOf (x.getTypeVariable ()))
550
+ return true ;
551
+ }
552
+
553
+ // As a last resort, let's check if the bindings are
554
+ // potentially incomplete, and if so, let's de-prioritize them.
555
+ return x.isPotentiallyIncomplete () < y.isPotentiallyIncomplete ();
556
+ }
557
+
558
+ void dump (llvm::raw_ostream &out, unsigned indent) const ;
500
559
void dump (TypeVariableType *typeVar, llvm::raw_ostream &out,
501
- unsigned indent = 0 ) const LLVM_ATTRIBUTE_USED;
560
+ unsigned indent) const ;
561
+
562
+ private:
563
+ void addBinding (PotentialBinding binding);
564
+
565
+ void addLiteralRequirement (Constraint *literal);
566
+
567
+ void addDefault (Constraint *constraint) {
568
+ auto defaultTy = constraint->getSecondType ();
569
+ Defaults.insert ({defaultTy->getCanonicalType (), constraint});
570
+ }
502
571
};
503
572
504
573
} // end namespace inference
0 commit comments