]> git.lizzy.rs Git - rust.git/commit
Auto merge of #30652 - aturon:specialization, r=nikomatsakis
authorbors <bors@rust-lang.org>
Tue, 15 Mar 2016 00:55:41 +0000 (17:55 -0700)
committerbors <bors@rust-lang.org>
Tue, 15 Mar 2016 00:55:41 +0000 (17:55 -0700)
commit9ca75619dc80f71f356cab0cdd11cc959e4c24db
tree2b3d421cd75d435b7ddb4ea2f1a1e089195a12e3
parent6d215fe04ce3f638d717d7fcea95c40d0a655ff9
parent6562eeb05396be4ee4d4f413ac3e0f9f1afcc536
Auto merge of #30652 - aturon:specialization, r=nikomatsakis

Implement RFC 1210: impl specialization

This PR implements [impl specialization](https://github.com/rust-lang/rfcs/pull/1210),
carefully following the proposal laid out in the RFC.

The implementation covers the bulk of the RFC. The remaining gaps I know of are:

- no checking for lifetime-dependent specialization (a soundness hole);
- no `default impl` yet;
- no support for `default` with associated consts;

I plan to cover these gaps in follow-up PRs, as per @nikomatsakis's preference.

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.

r? @nikomatsakis
src/librustc_driver/test.rs