Skip to content

Commit d80189d

Browse files
committed
Test fixes, added README for tests
1 parent 3262016 commit d80189d

19 files changed

+230
-27
lines changed

src/librustc/middle/traits/specialize/mod.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use middle::def_id::DefId;
2525
use middle::infer::{self, InferCtxt, TypeOrigin};
2626
use middle::region;
2727
use middle::subst::{Subst, Substs};
28-
use middle::traits::ProjectionMode;
28+
use middle::traits::{self, ProjectionMode, ObligationCause, Normalized};
2929
use middle::ty::{self, TyCtxt};
3030
use syntax::codemap::DUMMY_SP;
3131

@@ -149,14 +149,21 @@ pub fn specializes(tcx: &TyCtxt, impl1_def_id: DefId, impl2_def_id: DefId) -> bo
149149
// create a parameter environment corresponding to a (skolemized) instantiation of impl1
150150
let scheme = tcx.lookup_item_type(impl1_def_id);
151151
let predicates = tcx.lookup_predicates(impl1_def_id);
152-
let penv = tcx.construct_parameter_environment(DUMMY_SP,
153-
&scheme.generics,
154-
&predicates,
155-
region::DUMMY_CODE_EXTENT);
152+
let mut penv = tcx.construct_parameter_environment(DUMMY_SP,
153+
&scheme.generics,
154+
&predicates,
155+
region::DUMMY_CODE_EXTENT);
156156
let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id)
157157
.unwrap()
158158
.subst(tcx, &penv.free_substs);
159159

160+
// Normalize the trait reference, adding any obligations that arise into the impl1 assumptions
161+
let Normalized { value: impl1_trait_ref, obligations: normalization_obligations } = {
162+
let selcx = &mut SelectionContext::new(&infcx);
163+
traits::normalize(selcx, ObligationCause::dummy(), &impl1_trait_ref)
164+
};
165+
penv.caller_bounds.extend(normalization_obligations.into_iter().map(|o| o.predicate));
166+
160167
// Install the parameter environment, which means we take the predicates of impl1 as assumptions:
161168
infcx.parameter_environment = penv;
162169

src/test/auxiliary/xcrate_associated_type_defaults.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@
1010

1111
#![feature(associated_type_defaults)]
1212

13-
pub trait Foo {
14-
type Input = usize;
15-
fn bar(&self, _: Self::Input) {}
13+
pub trait Foo<T: Default + ToString> {
14+
type Out: Default + ToString = T;
1615
}
1716

18-
impl Foo for () {}
17+
impl Foo<u32> for () {
18+
}
19+
20+
impl Foo<u64> for () {
21+
type Out = bool;
22+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
This directory contains the test for incorrect usage of specialization that
2+
should lead to compile failure. Those tests break down into a few categories:
3+
4+
- Feature gating
5+
- [On use of the `default` keyword](specialization-feature-gate-default.rs)
6+
- [On overlapping impls](specialization-feature-gate-overlap.rs)
7+
8+
- Overlap checking with specialization enabled
9+
- [Basic overlap scenarios](specialization-overlap.rs)
10+
- Includes purely structural overlap
11+
- Includes purely trait-based overlap
12+
- Includes mix
13+
- [Overlap with differing polarity](specialization-overlap-negative.rs)
14+
15+
- [Attempt to specialize without using `default`](specialization-no-default.rs)
16+
17+
- [Attempt to change impl polarity in a specialization](specialization-polarity.rs)
18+
19+
- Attempt to rely on projection of a `default` type
20+
- [Rely on it externally in both generic and monomorphic contexts](specialization-default-projection.rs)
21+
- [Rely on it both within an impl and outside it](specialization-default-types.rs)

src/test/compile-fail/specialization/specialization-default-projection.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@ fn generic<T>() -> <T as Foo>::Assoc {
2828
// `T` could be some downstream crate type that specializes (or,
2929
// for that matter, `u8`).
3030

31-
() //~ ERROR E0308
31+
() //~ ERROR mismatched types
3232
}
3333

3434
fn monomorphic() -> () {
3535
// Even though we know that `()` is not specialized in a
3636
// downstream crate, typeck refuses to project here.
3737

38-
generic::<()>() //~ ERROR E0308
38+
generic::<()>() //~ ERROR mismatched types
3939
}
4040

4141
fn main() {

src/test/compile-fail/specialization/specialization-default-types.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ trait Example {
2222
impl<T> Example for T {
2323
default type Output = Box<T>;
2424
default fn generate(self) -> Self::Output {
25-
Box::new(self) //~ ERROR E0308
25+
Box::new(self) //~ ERROR mismatched types
2626
}
2727
}
2828

@@ -32,7 +32,7 @@ impl Example for bool {
3232
}
3333

3434
fn trouble<T>(t: T) -> Box<T> {
35-
Example::generate(t) //~ ERROR E0308
35+
Example::generate(t) //~ ERROR mismatched types
3636
}
3737

3838
fn weaponize() -> bool {

src/test/compile-fail/specialization/specialization-overlap.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,8 @@ trait Baz<U> {}
2222
impl<T> Baz<T> for u8 {}
2323
impl<T> Baz<u8> for T {} //~ ERROR E0119
2424

25+
trait Qux {}
26+
impl<T: Clone> Qux for T {}
27+
impl<T: Eq> Qux for T {} //~ ERROR E0119
28+
2529
fn main() {}

src/test/run-pass/default-associated-types.rs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,22 @@
1010

1111
#![feature(associated_type_defaults)]
1212

13-
trait Foo<T> {
14-
type Out = T;
15-
fn foo(&self) -> Self::Out;
13+
trait Foo<T: Default + ToString> {
14+
type Out: Default + ToString = T;
1615
}
1716

1817
impl Foo<u32> for () {
19-
fn foo(&self) -> u32 {
20-
4u32
21-
}
2218
}
2319

24-
impl Foo<u64> for bool {
25-
type Out = ();
26-
fn foo(&self) {}
20+
impl Foo<u64> for () {
21+
type Out = bool;
2722
}
2823

2924
fn main() {
30-
assert_eq!(<() as Foo<u32>>::foo(&()), 4u32);
31-
assert_eq!(<bool as Foo<u64>>::foo(&true), ());
25+
assert_eq!(
26+
<() as Foo<u32>>::Out::default().to_string(),
27+
"0");
28+
assert_eq!(
29+
<() as Foo<u64>>::Out::default().to_string(),
30+
"false");
3231
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
Tests that specialization is working correctly:
2+
3+
- Dispatch
4+
- [On methods](specialization-basics.rs), includes:
5+
- Specialization via adding a trait bound
6+
- Including both remote and local traits
7+
- Specialization via pure structure (e.g. `(T, U)` vs `(T, T)`)
8+
- Specialization via concrete types vs unknown types
9+
- In top level of the trait reference
10+
- Embedded within another type (`Vec<T>` vs `Vec<i32>`)
11+
- [Specialization based on super trait relationships](specialization-super-traits.rs)
12+
- [On assoc fns](specialization-assoc-fns.rs)
13+
- [Ensure that impl order doesn't matter](specialization-out-of-order.rs)
14+
15+
- Item inheritance
16+
- [Correct default cascading for methods](specialization-default-methods.rs)
17+
- Inheritance works across impls with varying generics
18+
- [With projections](specialization-translate-projections.rs)
19+
- [With projections that involve input types](specialization-translate-projections-with-params.rs)
20+
21+
- Normalization issues
22+
- [Non-default assoc types can be projected](specialization-projection.rs)
23+
- Including non-specialized cases
24+
- Including specialized cases
25+
- [Specialized Impls can happen on projections](specialization-on-projection.rs)
26+
- [Projections and aliases play well together](specialization-projection-alias.rs)
27+
- [Projections involving specialization allowed in the trait ref for impls, and overlap can still be determined](specialization-overlap-projection.rs)
28+
- Only works for the simple case where the most specialized impl directly
29+
provides a non-`default` associated type
30+
31+
- Across crates
32+
- [For traits defined in upstream crate](specialization-allowed-cross-crate.rs)
33+
- [Full method dispatch tests, drawing from upstream crate](specialization-cross-crate.rs)
34+
- Including *additional* local specializations
35+
- [Full method dispatch tests, *without* turning on specialization in local crate](specialization-cross-crate-no-gate.rs)
36+
- [Test that defaults cascade correctly from upstream crates](specialization-cross-crate-defaults.rs)
37+
- Including *additional* local use of defaults

src/test/run-pass/specialization/specialization-assoc-fns.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// Test that non-method associated functions can be specialized
12+
1113
#![feature(specialization)]
1214

1315
trait Foo {

src/test/run-pass/specialization/specialization-cross-crate-defaults.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,22 @@ extern crate specialization_cross_crate_defaults;
1616

1717
use specialization_cross_crate_defaults::*;
1818

19+
struct LocalDefault;
20+
struct LocalOverride;
21+
22+
impl Foo for LocalDefault {}
23+
24+
impl Foo for LocalOverride {
25+
fn foo(&self) -> bool { true }
26+
}
27+
1928
fn test_foo() {
2029
assert!(0i8.foo() == false);
2130
assert!(0i32.foo() == false);
2231
assert!(0i64.foo() == true);
32+
33+
assert!(LocalDefault.foo() == false);
34+
assert!(LocalOverride.foo() == true);
2335
}
2436

2537
fn test_bar() {

0 commit comments

Comments
 (0)