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

@ -23,10 +23,6 @@ pub fn main() {
let f2: &Fat<[isize; 3]> = &f1;
let f3: &Fat<[usize]> = f2;
//~^ ERROR mismatched types
//~| expected `&Fat<[usize]>`
//~| found `&Fat<[isize; 3]>`
//~| expected usize
//~| found isize
// With a trait.
let f1 = Fat { ptr: Foo };

View file

@ -81,8 +81,8 @@ fn load3<'a,'b>(ss: &'a SomeTrait) -> &'b SomeTrait {
// which fails to type check.
ss
//~^ ERROR cannot infer
//~| ERROR mismatched types
//~^ ERROR lifetime of the source pointer does not outlive lifetime bound
//~| ERROR cannot infer
}
fn main() {

View file

@ -25,7 +25,7 @@ fn load(ss: &mut SomeStruct) -> Box<SomeTrait> {
// `Box<SomeTrait>` defaults to a `'static` bound, so this return
// is illegal.
ss.r //~ ERROR mismatched types
ss.r //~ ERROR lifetime of the source pointer does not outlive lifetime bound
}
fn store(ss: &mut SomeStruct, b: Box<SomeTrait>) {
@ -38,7 +38,7 @@ fn store(ss: &mut SomeStruct, b: Box<SomeTrait>) {
fn store1<'b>(ss: &mut SomeStruct, b: Box<SomeTrait+'b>) {
// Here we override the lifetimes explicitly, and so naturally we get an error.
ss.r = b; //~ ERROR mismatched types
ss.r = b; //~ ERROR lifetime of the source pointer does not outlive lifetime bound
}
fn main() {

View file

@ -27,7 +27,7 @@ fn make_object_good2<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'b> {
fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'c> {
// A outlives 'a AND 'b...but not 'c.
box v as Box<SomeTrait+'a> //~ ERROR mismatched types
box v as Box<SomeTrait+'a> //~ ERROR lifetime of the source pointer does not outlive
}
fn main() {

View file

@ -22,7 +22,7 @@ fn foo2<'a:'b,'b>(x: &'b mut (Dummy+'a)) -> &'b mut (Dummy+'b) {
fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy {
// Without knowing 'a:'b, we can't coerce
x //~ ERROR mismatched types
x //~ ERROR lifetime of the source pointer does not outlive
//~^ ERROR cannot infer
}

View file

@ -0,0 +1,37 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test that you can supply `&F` where `F: FnMut()`.
// pretty-expanded FIXME #23616
#![feature(lang_items, unboxed_closures)]
fn a<F:FnMut() -> i32>(mut f: F) -> i32 {
f()
}
fn b(f: &mut FnMut() -> i32) -> i32 {
a(f)
}
fn c<F:FnMut() -> i32>(f: &mut F) -> i32 {
a(f)
}
fn main() {
let z: isize = 7;
let x = b(&mut || 22);
assert_eq!(x, 22);
let x = c(&mut || 22);
assert_eq!(x, 22);
}

View file

@ -0,0 +1,37 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test that you can supply `&F` where `F: Fn()`.
// pretty-expanded FIXME #23616
#![feature(lang_items, unboxed_closures)]
fn a<F:Fn() -> i32>(f: F) -> i32 {
f()
}
fn b(f: &Fn() -> i32) -> i32 {
a(f)
}
fn c<F:Fn() -> i32>(f: &F) -> i32 {
a(f)
}
fn main() {
let z: isize = 7;
let x = b(&|| 22);
assert_eq!(x, 22);
let x = c(&|| 22);
assert_eq!(x, 22);
}