1
Fork 0

Rollup merge of #23895 - nikomatsakis:fn-trait-inheritance-add-impls, r=pnkfelix

The primary purpose of this PR is to add blanket impls for the `Fn` traits of the following (simplified) form:

    impl<F:Fn> Fn for &F
    impl<F:FnMut> FnMut for &mut F

However, this wound up requiring two changes:

1. A slight hack so that `x()` where `x: &mut F` is translated to `FnMut::call_mut(&mut *x, ())` vs `FnMut::call_mut(&mut x, ())`. This is achieved by just autoderef'ing one time when calling something whose type is `&F` or `&mut F`.
2. Making the infinite recursion test in trait matching a bit more tailored. This involves adding a notion of "matching" types that looks to see if types are potentially unifiable (it's an approximation).

The PR also includes various small refactorings to the inference code that are aimed at moving the unification and other code into a library (I've got that particular change in a branch, these changes just lead the way there by removing unnecessary dependencies between the compiler and the more general unification code). 

Note that per rust-lang/rfcs#1023, adding impls like these would be a breaking change in the future. 

cc @japaric
cc @alexcrichton 
cc @aturon 

Fixes #23015.
This commit is contained in:
Manish Goregaokar 2015-04-02 00:40:39 +05:30
commit debac97a10
35 changed files with 1635 additions and 1278 deletions

View file

@ -1145,3 +1145,52 @@ pub trait FnOnce<Args> {
/// This is called when the call operator is used.
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}
#[cfg(not(stage0))]
mod impls {
use marker::Sized;
use super::{Fn, FnMut, FnOnce};
impl<'a,A,F:?Sized> Fn<A> for &'a F
where F : Fn<A>
{
extern "rust-call" fn call(&self, args: A) -> F::Output {
(**self).call(args)
}
}
impl<'a,A,F:?Sized> FnMut<A> for &'a F
where F : Fn<A>
{
extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
(**self).call(args)
}
}
impl<'a,A,F:?Sized> FnOnce<A> for &'a F
where F : Fn<A>
{
type Output = F::Output;
extern "rust-call" fn call_once(self, args: A) -> F::Output {
(*self).call(args)
}
}
impl<'a,A,F:?Sized> FnMut<A> for &'a mut F
where F : FnMut<A>
{
extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
(*self).call_mut(args)
}
}
impl<'a,A,F:?Sized> FnOnce<A> for &'a mut F
where F : FnMut<A>
{
type Output = F::Output;
extern "rust-call" fn call_once(mut self, args: A) -> F::Output {
(*self).call_mut(args)
}
}
}