mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 23:12:02 +00:00
Add some basic comments about how specialization fits into the rest of the trait machinery
This commit is contained in:
parent
ed8d059d8d
commit
c1df41e776
@ -428,3 +428,43 @@ We used to try and draw finer-grained distinctions, but that led to a
|
||||
serious of annoying and weird bugs like #22019 and #18290. This simple
|
||||
rule seems to be pretty clearly safe and also still retains a very
|
||||
high hit rate (~95% when compiling rustc).
|
||||
|
||||
# Specialization
|
||||
|
||||
Defined in the `specialize` module.
|
||||
|
||||
The basic strategy is to build up a *specialization graph* during
|
||||
coherence checking. Insertion into the graph locates the right place
|
||||
to put an impl in the specialization hierarchy; if there is no right
|
||||
place (due to partial overlap but no containment), you get an overlap
|
||||
error. Specialization is consulted when selecting an impl (of course),
|
||||
and the graph is consulted when propagating defaults down the
|
||||
specialization hierarchy.
|
||||
|
||||
You might expect that the specialization graph would be used during
|
||||
selection -- i.e., when actually performing specialization. This is
|
||||
not done for two reasons:
|
||||
|
||||
- It's merely an optimization: given a set of candidates that apply,
|
||||
we can determine the most specialized one by comparing them directly
|
||||
for specialization, rather than consulting the graph. Given that we
|
||||
also cache the results of selection, the benefit of this
|
||||
optimization is questionable.
|
||||
|
||||
- To build the specialization graph in the first place, we need to use
|
||||
selection (because we need to determine whether one impl specializes
|
||||
another). Dealing with this reentrancy would require some additional
|
||||
mode switch for selection. Given that there seems to be no strong
|
||||
reason to use the graph anyway, we stick with a simpler approach in
|
||||
selection, and use the graph only for propagating default
|
||||
implementations.
|
||||
|
||||
Trait impl selection can succeed even when multiple impls can apply,
|
||||
as long as they are part of the same specialization family. In that
|
||||
case, it returns a *single* impl on success -- this is the most
|
||||
specialized impl *known* to apply. However, if there are any inference
|
||||
variables in play, the returned impl may not be the actual impl we
|
||||
will use at trans time. Thus, we take special care to avoid projecting
|
||||
associated types unless either (1) the associated type does not use
|
||||
`default` and thus cannot be overridden or (2) all input types are
|
||||
known concretely.
|
||||
|
@ -13,6 +13,9 @@
|
||||
//
|
||||
// At the moment, this implementation support only the simple "chain" rule:
|
||||
// If any two impls overlap, one must be a strict subset of the other.
|
||||
//
|
||||
// See traits/README.md for a bit more detail on how specialization
|
||||
// fits together with the rest of the trait machinery.
|
||||
|
||||
use super::util;
|
||||
use super::SelectionContext;
|
||||
|
Loading…
Reference in New Issue
Block a user