mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 15:01:51 +00:00
Test fixes, added README for tests
This commit is contained in:
parent
326201657a
commit
d80189d305
@ -25,7 +25,7 @@ use middle::def_id::DefId;
|
|||||||
use middle::infer::{self, InferCtxt, TypeOrigin};
|
use middle::infer::{self, InferCtxt, TypeOrigin};
|
||||||
use middle::region;
|
use middle::region;
|
||||||
use middle::subst::{Subst, Substs};
|
use middle::subst::{Subst, Substs};
|
||||||
use middle::traits::ProjectionMode;
|
use middle::traits::{self, ProjectionMode, ObligationCause, Normalized};
|
||||||
use middle::ty::{self, TyCtxt};
|
use middle::ty::{self, TyCtxt};
|
||||||
use syntax::codemap::DUMMY_SP;
|
use syntax::codemap::DUMMY_SP;
|
||||||
|
|
||||||
@ -149,14 +149,21 @@ pub fn specializes(tcx: &TyCtxt, impl1_def_id: DefId, impl2_def_id: DefId) -> bo
|
|||||||
// create a parameter environment corresponding to a (skolemized) instantiation of impl1
|
// create a parameter environment corresponding to a (skolemized) instantiation of impl1
|
||||||
let scheme = tcx.lookup_item_type(impl1_def_id);
|
let scheme = tcx.lookup_item_type(impl1_def_id);
|
||||||
let predicates = tcx.lookup_predicates(impl1_def_id);
|
let predicates = tcx.lookup_predicates(impl1_def_id);
|
||||||
let penv = tcx.construct_parameter_environment(DUMMY_SP,
|
let mut penv = tcx.construct_parameter_environment(DUMMY_SP,
|
||||||
&scheme.generics,
|
&scheme.generics,
|
||||||
&predicates,
|
&predicates,
|
||||||
region::DUMMY_CODE_EXTENT);
|
region::DUMMY_CODE_EXTENT);
|
||||||
let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id)
|
let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.subst(tcx, &penv.free_substs);
|
.subst(tcx, &penv.free_substs);
|
||||||
|
|
||||||
|
// Normalize the trait reference, adding any obligations that arise into the impl1 assumptions
|
||||||
|
let Normalized { value: impl1_trait_ref, obligations: normalization_obligations } = {
|
||||||
|
let selcx = &mut SelectionContext::new(&infcx);
|
||||||
|
traits::normalize(selcx, ObligationCause::dummy(), &impl1_trait_ref)
|
||||||
|
};
|
||||||
|
penv.caller_bounds.extend(normalization_obligations.into_iter().map(|o| o.predicate));
|
||||||
|
|
||||||
// Install the parameter environment, which means we take the predicates of impl1 as assumptions:
|
// Install the parameter environment, which means we take the predicates of impl1 as assumptions:
|
||||||
infcx.parameter_environment = penv;
|
infcx.parameter_environment = penv;
|
||||||
|
|
||||||
|
@ -10,9 +10,13 @@
|
|||||||
|
|
||||||
#![feature(associated_type_defaults)]
|
#![feature(associated_type_defaults)]
|
||||||
|
|
||||||
pub trait Foo {
|
pub trait Foo<T: Default + ToString> {
|
||||||
type Input = usize;
|
type Out: Default + ToString = T;
|
||||||
fn bar(&self, _: Self::Input) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Foo for () {}
|
impl Foo<u32> for () {
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Foo<u64> for () {
|
||||||
|
type Out = bool;
|
||||||
|
}
|
||||||
|
21
src/test/compile-fail/specialization/README.md
Normal file
21
src/test/compile-fail/specialization/README.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
This directory contains the test for incorrect usage of specialization that
|
||||||
|
should lead to compile failure. Those tests break down into a few categories:
|
||||||
|
|
||||||
|
- Feature gating
|
||||||
|
- [On use of the `default` keyword](specialization-feature-gate-default.rs)
|
||||||
|
- [On overlapping impls](specialization-feature-gate-overlap.rs)
|
||||||
|
|
||||||
|
- Overlap checking with specialization enabled
|
||||||
|
- [Basic overlap scenarios](specialization-overlap.rs)
|
||||||
|
- Includes purely structural overlap
|
||||||
|
- Includes purely trait-based overlap
|
||||||
|
- Includes mix
|
||||||
|
- [Overlap with differing polarity](specialization-overlap-negative.rs)
|
||||||
|
|
||||||
|
- [Attempt to specialize without using `default`](specialization-no-default.rs)
|
||||||
|
|
||||||
|
- [Attempt to change impl polarity in a specialization](specialization-polarity.rs)
|
||||||
|
|
||||||
|
- Attempt to rely on projection of a `default` type
|
||||||
|
- [Rely on it externally in both generic and monomorphic contexts](specialization-default-projection.rs)
|
||||||
|
- [Rely on it both within an impl and outside it](specialization-default-types.rs)
|
@ -28,14 +28,14 @@ fn generic<T>() -> <T as Foo>::Assoc {
|
|||||||
// `T` could be some downstream crate type that specializes (or,
|
// `T` could be some downstream crate type that specializes (or,
|
||||||
// for that matter, `u8`).
|
// for that matter, `u8`).
|
||||||
|
|
||||||
() //~ ERROR E0308
|
() //~ ERROR mismatched types
|
||||||
}
|
}
|
||||||
|
|
||||||
fn monomorphic() -> () {
|
fn monomorphic() -> () {
|
||||||
// Even though we know that `()` is not specialized in a
|
// Even though we know that `()` is not specialized in a
|
||||||
// downstream crate, typeck refuses to project here.
|
// downstream crate, typeck refuses to project here.
|
||||||
|
|
||||||
generic::<()>() //~ ERROR E0308
|
generic::<()>() //~ ERROR mismatched types
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -22,7 +22,7 @@ trait Example {
|
|||||||
impl<T> Example for T {
|
impl<T> Example for T {
|
||||||
default type Output = Box<T>;
|
default type Output = Box<T>;
|
||||||
default fn generate(self) -> Self::Output {
|
default fn generate(self) -> Self::Output {
|
||||||
Box::new(self) //~ ERROR E0308
|
Box::new(self) //~ ERROR mismatched types
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ impl Example for bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn trouble<T>(t: T) -> Box<T> {
|
fn trouble<T>(t: T) -> Box<T> {
|
||||||
Example::generate(t) //~ ERROR E0308
|
Example::generate(t) //~ ERROR mismatched types
|
||||||
}
|
}
|
||||||
|
|
||||||
fn weaponize() -> bool {
|
fn weaponize() -> bool {
|
||||||
|
@ -22,4 +22,8 @@ trait Baz<U> {}
|
|||||||
impl<T> Baz<T> for u8 {}
|
impl<T> Baz<T> for u8 {}
|
||||||
impl<T> Baz<u8> for T {} //~ ERROR E0119
|
impl<T> Baz<u8> for T {} //~ ERROR E0119
|
||||||
|
|
||||||
|
trait Qux {}
|
||||||
|
impl<T: Clone> Qux for T {}
|
||||||
|
impl<T: Eq> Qux for T {} //~ ERROR E0119
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -10,23 +10,22 @@
|
|||||||
|
|
||||||
#![feature(associated_type_defaults)]
|
#![feature(associated_type_defaults)]
|
||||||
|
|
||||||
trait Foo<T> {
|
trait Foo<T: Default + ToString> {
|
||||||
type Out = T;
|
type Out: Default + ToString = T;
|
||||||
fn foo(&self) -> Self::Out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Foo<u32> for () {
|
impl Foo<u32> for () {
|
||||||
fn foo(&self) -> u32 {
|
|
||||||
4u32
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Foo<u64> for bool {
|
impl Foo<u64> for () {
|
||||||
type Out = ();
|
type Out = bool;
|
||||||
fn foo(&self) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
assert_eq!(<() as Foo<u32>>::foo(&()), 4u32);
|
assert_eq!(
|
||||||
assert_eq!(<bool as Foo<u64>>::foo(&true), ());
|
<() as Foo<u32>>::Out::default().to_string(),
|
||||||
|
"0");
|
||||||
|
assert_eq!(
|
||||||
|
<() as Foo<u64>>::Out::default().to_string(),
|
||||||
|
"false");
|
||||||
}
|
}
|
||||||
|
37
src/test/run-pass/specialization/README.md
Normal file
37
src/test/run-pass/specialization/README.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
Tests that specialization is working correctly:
|
||||||
|
|
||||||
|
- Dispatch
|
||||||
|
- [On methods](specialization-basics.rs), includes:
|
||||||
|
- Specialization via adding a trait bound
|
||||||
|
- Including both remote and local traits
|
||||||
|
- Specialization via pure structure (e.g. `(T, U)` vs `(T, T)`)
|
||||||
|
- Specialization via concrete types vs unknown types
|
||||||
|
- In top level of the trait reference
|
||||||
|
- Embedded within another type (`Vec<T>` vs `Vec<i32>`)
|
||||||
|
- [Specialization based on super trait relationships](specialization-super-traits.rs)
|
||||||
|
- [On assoc fns](specialization-assoc-fns.rs)
|
||||||
|
- [Ensure that impl order doesn't matter](specialization-out-of-order.rs)
|
||||||
|
|
||||||
|
- Item inheritance
|
||||||
|
- [Correct default cascading for methods](specialization-default-methods.rs)
|
||||||
|
- Inheritance works across impls with varying generics
|
||||||
|
- [With projections](specialization-translate-projections.rs)
|
||||||
|
- [With projections that involve input types](specialization-translate-projections-with-params.rs)
|
||||||
|
|
||||||
|
- Normalization issues
|
||||||
|
- [Non-default assoc types can be projected](specialization-projection.rs)
|
||||||
|
- Including non-specialized cases
|
||||||
|
- Including specialized cases
|
||||||
|
- [Specialized Impls can happen on projections](specialization-on-projection.rs)
|
||||||
|
- [Projections and aliases play well together](specialization-projection-alias.rs)
|
||||||
|
- [Projections involving specialization allowed in the trait ref for impls, and overlap can still be determined](specialization-overlap-projection.rs)
|
||||||
|
- Only works for the simple case where the most specialized impl directly
|
||||||
|
provides a non-`default` associated type
|
||||||
|
|
||||||
|
- Across crates
|
||||||
|
- [For traits defined in upstream crate](specialization-allowed-cross-crate.rs)
|
||||||
|
- [Full method dispatch tests, drawing from upstream crate](specialization-cross-crate.rs)
|
||||||
|
- Including *additional* local specializations
|
||||||
|
- [Full method dispatch tests, *without* turning on specialization in local crate](specialization-cross-crate-no-gate.rs)
|
||||||
|
- [Test that defaults cascade correctly from upstream crates](specialization-cross-crate-defaults.rs)
|
||||||
|
- Including *additional* local use of defaults
|
@ -8,6 +8,8 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
// Test that non-method associated functions can be specialized
|
||||||
|
|
||||||
#![feature(specialization)]
|
#![feature(specialization)]
|
||||||
|
|
||||||
trait Foo {
|
trait Foo {
|
||||||
|
@ -16,10 +16,22 @@ extern crate specialization_cross_crate_defaults;
|
|||||||
|
|
||||||
use specialization_cross_crate_defaults::*;
|
use specialization_cross_crate_defaults::*;
|
||||||
|
|
||||||
|
struct LocalDefault;
|
||||||
|
struct LocalOverride;
|
||||||
|
|
||||||
|
impl Foo for LocalDefault {}
|
||||||
|
|
||||||
|
impl Foo for LocalOverride {
|
||||||
|
fn foo(&self) -> bool { true }
|
||||||
|
}
|
||||||
|
|
||||||
fn test_foo() {
|
fn test_foo() {
|
||||||
assert!(0i8.foo() == false);
|
assert!(0i8.foo() == false);
|
||||||
assert!(0i32.foo() == false);
|
assert!(0i32.foo() == false);
|
||||||
assert!(0i64.foo() == true);
|
assert!(0i64.foo() == true);
|
||||||
|
|
||||||
|
assert!(LocalDefault.foo() == false);
|
||||||
|
assert!(LocalOverride.foo() == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_bar() {
|
fn test_bar() {
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
// Test that specialization works even if only the upstream crate enables it
|
||||||
|
|
||||||
|
// aux-build:specialization_cross_crate.rs
|
||||||
|
|
||||||
|
extern crate specialization_cross_crate;
|
||||||
|
|
||||||
|
use specialization_cross_crate::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert!(0u8.foo() == "generic Clone");
|
||||||
|
assert!(vec![0u8].foo() == "generic Vec");
|
||||||
|
assert!(vec![0i32].foo() == "Vec<i32>");
|
||||||
|
assert!(0i32.foo() == "i32");
|
||||||
|
assert!(String::new().foo() == "String");
|
||||||
|
assert!(((), 0).foo() == "generic pair");
|
||||||
|
assert!(((), ()).foo() == "generic uniform pair");
|
||||||
|
assert!((0u8, 0u32).foo() == "(u8, u32)");
|
||||||
|
assert!((0u8, 0u8).foo() == "(u8, u8)");
|
||||||
|
}
|
@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
#![feature(specialization)]
|
#![feature(specialization)]
|
||||||
|
|
||||||
|
// Test that default methods are cascaded correctly
|
||||||
|
|
||||||
// First, test only use of explicit `default` items:
|
// First, test only use of explicit `default` items:
|
||||||
|
|
||||||
trait Foo {
|
trait Foo {
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
#![feature(specialization)]
|
#![feature(specialization)]
|
||||||
|
|
||||||
|
// Ensure that specialization works for impls defined directly on a projection
|
||||||
|
|
||||||
trait Foo<T> {}
|
trait Foo<T> {}
|
||||||
|
|
||||||
trait Assoc {
|
trait Assoc {
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
// Copyright 2016 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 impls on projected self types can resolve overlap, even when the
|
||||||
|
// projections involve specialization, so long as the associated type is
|
||||||
|
// provided by the most specialized impl.
|
||||||
|
|
||||||
|
#![feature(specialization)]
|
||||||
|
|
||||||
|
trait Assoc {
|
||||||
|
type Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Assoc for T {
|
||||||
|
default type Output = bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Assoc for u8 { type Output = u8; }
|
||||||
|
impl Assoc for u16 { type Output = u16; }
|
||||||
|
|
||||||
|
trait Foo {}
|
||||||
|
impl Foo for u32 {}
|
||||||
|
impl Foo for <u8 as Assoc>::Output {}
|
||||||
|
impl Foo for <u16 as Assoc>::Output {}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -23,6 +23,10 @@ impl<T> Id_ for T {
|
|||||||
default type Out = T;
|
default type Out = T;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn test_proection() {
|
||||||
let x: Id<bool> = panic!();
|
let x: Id<bool> = panic!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
// Make sure we *can* project non-defaulted associated types
|
// Make sure we *can* project non-defaulted associated types
|
||||||
// cf compile-fail/specialization-default-projection.rs
|
// cf compile-fail/specialization-default-projection.rs
|
||||||
|
|
||||||
|
// First, do so without any use of specialization
|
||||||
|
|
||||||
trait Foo {
|
trait Foo {
|
||||||
type Assoc;
|
type Assoc;
|
||||||
}
|
}
|
||||||
@ -21,9 +23,27 @@ impl<T> Foo for T {
|
|||||||
type Assoc = ();
|
type Assoc = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generic<T>() -> <T as Foo>::Assoc {
|
fn generic_foo<T>() -> <T as Foo>::Assoc {
|
||||||
()
|
()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Next, allow for one layer of specialization
|
||||||
|
|
||||||
|
trait Bar {
|
||||||
|
type Assoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Bar for T {
|
||||||
|
default type Assoc = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone> Bar for T {
|
||||||
|
type Assoc = u8;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generic_bar_clone<T: Clone>() -> <T as Bar>::Assoc {
|
||||||
|
0u8
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,10 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
// Ensure that provided items are inherited properly even when impls vary in
|
||||||
|
// type parameters *and* rely on projections, and the type parameters are input
|
||||||
|
// types on the trait.
|
||||||
|
|
||||||
#![feature(specialization)]
|
#![feature(specialization)]
|
||||||
|
|
||||||
trait Trait<T> {
|
trait Trait<T> {
|
||||||
|
@ -8,6 +8,9 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
// Ensure that provided items are inherited properly even when impls vary in
|
||||||
|
// type parameters *and* rely on projections.
|
||||||
|
|
||||||
#![feature(specialization)]
|
#![feature(specialization)]
|
||||||
|
|
||||||
use std::convert::Into;
|
use std::convert::Into;
|
||||||
|
@ -13,6 +13,26 @@
|
|||||||
extern crate xcrate_associated_type_defaults;
|
extern crate xcrate_associated_type_defaults;
|
||||||
use xcrate_associated_type_defaults::Foo;
|
use xcrate_associated_type_defaults::Foo;
|
||||||
|
|
||||||
fn main() {
|
struct LocalDefault;
|
||||||
().bar(5);
|
impl Foo<u32> for LocalDefault {}
|
||||||
|
|
||||||
|
struct LocalOverride;
|
||||||
|
impl Foo<u64> for LocalOverride {
|
||||||
|
type Out = bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert_eq!(
|
||||||
|
<() as Foo<u32>>::Out::default().to_string(),
|
||||||
|
"0");
|
||||||
|
assert_eq!(
|
||||||
|
<() as Foo<u64>>::Out::default().to_string(),
|
||||||
|
"false");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
<LocalDefault as Foo<u32>>::Out::default().to_string(),
|
||||||
|
"0");
|
||||||
|
assert_eq!(
|
||||||
|
<LocalOverride as Foo<u64>>::Out::default().to_string(),
|
||||||
|
"false");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user