@@ -428,3 +428,43 @@ We used to try and draw finer-grained distinctions, but that led to a
428
428
serious of annoying and weird bugs like #22019 and #18290 . This simple
429
429
rule seems to be pretty clearly safe and also still retains a very
430
430
high hit rate (~ 95% when compiling rustc).
431
+
432
+ # Specialization
433
+
434
+ Defined in the ` specialize ` module.
435
+
436
+ The basic strategy is to build up a * specialization graph* during
437
+ coherence checking. Insertion into the graph locates the right place
438
+ to put an impl in the specialization hierarchy; if there is no right
439
+ place (due to partial overlap but no containment), you get an overlap
440
+ error. Specialization is consulted when selecting an impl (of course),
441
+ and the graph is consulted when propagating defaults down the
442
+ specialization hierarchy.
443
+
444
+ You might expect that the specialization graph would be used during
445
+ selection -- i.e., when actually performing specialization. This is
446
+ not done for two reasons:
447
+
448
+ - It's merely an optimization: given a set of candidates that apply,
449
+ we can determine the most specialized one by comparing them directly
450
+ for specialization, rather than consulting the graph. Given that we
451
+ also cache the results of selection, the benefit of this
452
+ optimization is questionable.
453
+
454
+ - To build the specialization graph in the first place, we need to use
455
+ selection (because we need to determine whether one impl specializes
456
+ another). Dealing with this reentrancy would require some additional
457
+ mode switch for selection. Given that there seems to be no strong
458
+ reason to use the graph anyway, we stick with a simpler approach in
459
+ selection, and use the graph only for propagating default
460
+ implementations.
461
+
462
+ Trait impl selection can succeed even when multiple impls can apply,
463
+ as long as they are part of the same specialization family. In that
464
+ case, it returns a * single* impl on success -- this is the most
465
+ specialized impl * known* to apply. However, if there are any inference
466
+ variables in play, the returned impl may not be the actual impl we
467
+ will use at trans time. Thus, we take special care to avoid projecting
468
+ associated types unless either (1) the associated type does not use
469
+ ` default ` and thus cannot be overridden or (2) all input types are
470
+ known concretely.
0 commit comments