Auto merge of #26870 - jroesch:default-typaram-fallback, r=nikomatsakis

This PR completes [RFC 213](https://github.com/rust-lang/rfcs/blob/master/text/0213-defaulted-type-params.md) by allowing default type parameters to influence inference. This is almost certainly a breaking change due to interactions between default type parameters and the old fallback algorithm used for integral and floating point literals.

The error messages still require polish but I wanted to get early review and feedback from others on the the changes, error messages, and test cases. I also imagine we will want to run anywhere from 1-3 versions of this on crater and evaluate the impact, and it would be best to get that ball rolling. 

The only outstanding issue I'm aware of is that type alias defaults don't work. It seems this may require significant restructuring, since during inference type aliases have already been expanded. @nikomatsakis might be able to provide some clarity here.

r? @nikomatsakis 

cc @eddyb @Gankro @aturon @brson
This commit is contained in:
bors 2015-07-26 10:39:18 +00:00
commit a5c12f4e39
31 changed files with 952 additions and 120 deletions

View file

@ -0,0 +1,19 @@
// Copyright 2015 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.
#![crate_type = "lib"]
#![crate_name = "default_param_test"]
use std::marker::PhantomData;
pub struct Foo<A, B>(PhantomData<(A, B)>);
pub fn bleh<A=i32, X=char>() -> Foo<A, X> { Foo(PhantomData) }

View file

@ -0,0 +1,32 @@
// Copyright 2015 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.
#![feature(default_type_parameter_fallback)]
use std::fmt::Debug;
// Example from the RFC
fn foo<F:Default=usize>() -> F { F::default() }
//~^ NOTE: a default was defined here...
fn bar<B:Debug=isize>(b: B) { println!("{:?}", b); }
//~^ NOTE: a second default was defined here...
fn main() {
// Here, F is instantiated with $0=uint
let x = foo();
//~^ ERROR: mismatched types
//~| NOTE: conflicting type parameter defaults `usize` and `isize`
//~| NOTE: ...that was applied to an unconstrained type variable here
// Here, B is instantiated with $1=uint, and constraint $0 <: $1 is added.
bar(x);
//~^ NOTE: ...that also applies to the same type variable here
}

View file

@ -0,0 +1,29 @@
// Copyright 2015 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.
//
//aux-build:default_ty_param_cross_crate_crate.rs
#![feature(default_type_parameter_fallback)]
extern crate default_param_test;
use default_param_test::{Foo, bleh};
fn meh<X, B=bool>(x: Foo<X, B>) {}
//~^ NOTE: a default was defined here...
fn main() {
let foo = bleh();
//~^ NOTE: ...that also applies to the same type variable here
meh(foo);
//~^ ERROR: mismatched types:
//~| NOTE: conflicting type parameter defaults `bool` and `char`
}

View file

@ -0,0 +1,36 @@
// Copyright 2015 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.
//
#![feature(default_type_parameter_fallback)]
use std::marker::PhantomData;
trait Id {
type This;
}
impl<A> Id for A {
type This = A;
}
struct Foo<X: Default = usize, Y = <X as Id>::This> {
data: PhantomData<(X, Y)>
}
impl<X: Default, Y> Foo<X, Y> {
fn new() -> Foo<X, Y> {
Foo { data: PhantomData }
}
}
fn main() {
let foo = Foo::new();
}

View file

@ -0,0 +1,19 @@
// Copyright 2015 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.
//
#![feature(default_type_parameter_fallback)]
use std::marker::PhantomData;
struct Foo<T,U=T> { t: T, data: PhantomData<U> }
fn main() {
let foo = Foo { t: 'a', data: PhantomData };
}

View file

@ -0,0 +1,24 @@
// Copyright 2015 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.
#![feature(default_type_parameter_fallback)]
struct Foo;
impl Foo {
fn method<A:Default=String>(&self) -> A {
A::default()
}
}
fn main() {
let f = Foo.method();
println!("{}", f);
}

View file

@ -0,0 +1,23 @@
// Copyright 2015 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.
#![feature(default_type_parameter_fallback)]
struct Foo<A>(A);
impl<A:Default=i32> Foo<A> {
fn new() -> Foo<A> {
Foo(A::default())
}
}
fn main() {
let foo = Foo::new();
}

View file

@ -0,0 +1,40 @@
// Copyright 2015 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.
//
#![feature(default_type_parameter_fallback)]
use std::marker::PhantomData;
struct DeterministicHasher;
struct RandomHasher;
struct MyHashMap<K, V, H=DeterministicHasher> {
data: PhantomData<(K, V, H)>
}
impl<K, V, H> MyHashMap<K, V, H> {
fn new() -> MyHashMap<K, V, H> {
MyHashMap { data: PhantomData }
}
}
mod mystd {
use super::{MyHashMap, RandomHasher};
pub type HashMap<K, V, H=RandomHasher> = MyHashMap<K, V, H>;
}
fn try_me<H>(hash_map: mystd::HashMap<i32, i32, H>) {}
fn main() {
let hash_map = mystd::HashMap::new();
try_me(hash_map);
}

View file

@ -0,0 +1,25 @@
// Copyright 2015 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.
#![feature(default_type_parameter_fallback)]
// Another example from the RFC
trait Foo { }
trait Bar { }
impl<T:Bar=usize> Foo for Vec<T> {}
impl Bar for usize {}
fn takes_foo<F:Foo>(f: F) {}
fn main() {
let x = Vec::new(); // x: Vec<$0>
takes_foo(x); // adds oblig Vec<$0> : Foo
}

View file

@ -0,0 +1,26 @@
// Copyright 2015 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.
#![feature(default_type_parameter_fallback)]
// An example from the RFC
trait Foo { fn takes_foo(&self); }
trait Bar { }
impl<T:Bar=usize> Foo for Vec<T> {
fn takes_foo(&self) {}
}
impl Bar for usize {}
fn main() {
let x = Vec::new(); // x: Vec<$0>
x.takes_foo(); // adds oblig Vec<$0> : Foo
}

View file

@ -0,0 +1,19 @@
// Copyright 2015 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.
#![feature(default_type_parameter_fallback)]
use std::collections::HashMap;
type IntMap<K=usize> = HashMap<K, usize>;
fn main() {
let x = IntMap::new();
}