about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAaron Turon <aturon@mozilla.com>2015-12-30 15:57:49 -0800
committerAaron Turon <aturon@mozilla.com>2016-03-14 15:04:39 -0700
commitc1df41e776c5a65ce8345d34a7e22296a99abd5e (patch)
tree66a6d269c8129db180ba3593a19adfce27b64abe
parented8d059d8d49491b736ea88edd8f2b57a866c44a (diff)
downloadrust-c1df41e776c5a65ce8345d34a7e22296a99abd5e.tar.gz
rust-c1df41e776c5a65ce8345d34a7e22296a99abd5e.zip
Add some basic comments about how specialization fits into the rest of the trait machinery
-rw-r--r--src/librustc/middle/traits/README.md40
-rw-r--r--src/librustc/middle/traits/specialize.rs3
2 files changed, 43 insertions, 0 deletions
diff --git a/src/librustc/middle/traits/README.md b/src/librustc/middle/traits/README.md
index 92982af92dc..ff72f9dd07e 100644
--- a/src/librustc/middle/traits/README.md
+++ b/src/librustc/middle/traits/README.md
@@ -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.
diff --git a/src/librustc/middle/traits/specialize.rs b/src/librustc/middle/traits/specialize.rs
index 0f47e19eaf3..30897e9289d 100644
--- a/src/librustc/middle/traits/specialize.rs
+++ b/src/librustc/middle/traits/specialize.rs
@@ -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;