Skip to content

Commit 483fca9

Browse files
committed
rollup merge of rust-lang#20757: nikomatsakis/issue-20624-assoc-types-coherence
2 parents 4281bd1 + d548f3e commit 483fca9

11 files changed

+276
-33
lines changed

src/librustc/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
#![feature(box_syntax)]
3030
#![allow(unknown_features)] #![feature(int_uint)]
3131
#![feature(rustc_diagnostic_macros)]
32-
#![feature(old_impl_check)]
3332

3433
extern crate arena;
3534
extern crate flate;

src/librustc/middle/subst.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,17 @@ impl<T> VecPerParamSpace<T> {
313313
self.content.insert(limit, value);
314314
}
315315

316+
/// Appends `values` to the vector associated with `space`.
317+
///
318+
/// Unlike the `extend` method in `Vec`, this should not be assumed
319+
/// to be a cheap operation (even when amortized over many calls).
320+
pub fn extend<I:Iterator<Item=T>>(&mut self, space: ParamSpace, mut values: I) {
321+
// This could be made more efficient, obviously.
322+
for item in values {
323+
self.push(space, item);
324+
}
325+
}
326+
316327
pub fn pop(&mut self, space: ParamSpace) -> Option<T> {
317328
let (start, limit) = self.limits(space);
318329
if start == limit {

src/librustc/middle/traits/coherence.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
1313
use super::SelectionContext;
1414
use super::{Obligation, ObligationCause};
15+
use super::project;
1516
use super::util;
1617

1718
use middle::subst::{Subst};
@@ -34,22 +35,28 @@ pub fn impl_can_satisfy(infcx: &InferCtxt,
3435
impl1_def_id.repr(infcx.tcx),
3536
impl2_def_id.repr(infcx.tcx));
3637

38+
let param_env = ty::empty_parameter_environment(infcx.tcx);
39+
let mut selcx = SelectionContext::intercrate(infcx, &param_env);
40+
let cause = ObligationCause::dummy();
41+
3742
// `impl1` provides an implementation of `Foo<X,Y> for Z`.
3843
let impl1_substs =
3944
util::fresh_substs_for_impl(infcx, DUMMY_SP, impl1_def_id);
4045
let impl1_trait_ref =
4146
(*ty::impl_trait_ref(infcx.tcx, impl1_def_id).unwrap()).subst(infcx.tcx, &impl1_substs);
47+
let impl1_trait_ref =
48+
project::normalize(&mut selcx, cause.clone(), &impl1_trait_ref);
4249

4350
// Determine whether `impl2` can provide an implementation for those
4451
// same types.
45-
let param_env = ty::empty_parameter_environment(infcx.tcx);
46-
let mut selcx = SelectionContext::intercrate(infcx, &param_env);
47-
let obligation = Obligation::new(ObligationCause::dummy(),
52+
let obligation = Obligation::new(cause,
4853
ty::Binder(ty::TraitPredicate {
49-
trait_ref: Rc::new(impl1_trait_ref),
54+
trait_ref: Rc::new(impl1_trait_ref.value),
5055
}));
5156
debug!("impl_can_satisfy(obligation={})", obligation.repr(infcx.tcx));
52-
selcx.evaluate_impl(impl2_def_id, &obligation)
57+
selcx.evaluate_impl(impl2_def_id, &obligation) &&
58+
impl1_trait_ref.obligations.iter().all(
59+
|o| selcx.evaluate_obligation(o))
5360
}
5461

5562
#[allow(missing_copy_implementations)]

src/librustc/middle/traits/project.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ impl<'a,'b,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'b,'tcx> {
206206
// normalize it when we instantiate those bound regions (which
207207
// should occur eventually).
208208

209+
let ty = ty_fold::super_fold_ty(self, ty);
209210
match ty.sty {
210211
ty::ty_projection(ref data) if !data.has_escaping_regions() => { // (*)
211212

@@ -229,8 +230,9 @@ impl<'a,'b,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'b,'tcx> {
229230
self.obligations.extend(obligations.into_iter());
230231
ty
231232
}
233+
232234
_ => {
233-
ty_fold::super_fold_ty(self, ty)
235+
ty
234236
}
235237
}
236238
}
@@ -243,6 +245,12 @@ pub struct Normalized<'tcx,T> {
243245

244246
pub type NormalizedTy<'tcx> = Normalized<'tcx, Ty<'tcx>>;
245247

248+
impl<'tcx,T> Normalized<'tcx,T> {
249+
pub fn with<U>(self, value: U) -> Normalized<'tcx,U> {
250+
Normalized { value: value, obligations: self.obligations }
251+
}
252+
}
253+
246254
pub fn normalize_projection_type<'a,'b,'tcx>(
247255
selcx: &'a mut SelectionContext<'b,'tcx>,
248256
projection_ty: ty::ProjectionTy<'tcx>,

src/librustc/middle/traits/select.rs

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use self::EvaluationResult::*;
1919

2020
use super::{DerivedObligationCause};
2121
use super::{project};
22+
use super::project::Normalized;
2223
use super::{PredicateObligation, Obligation, TraitObligation, ObligationCause};
2324
use super::{ObligationCauseCode, BuiltinDerivedObligation};
2425
use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch};
@@ -1155,7 +1156,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11551156
let impl_trait_ref =
11561157
ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap();
11571158
let impl_trait_ref =
1158-
impl_trait_ref.subst(self.tcx(), &impl_substs);
1159+
impl_trait_ref.subst(self.tcx(), &impl_substs.value);
11591160
let poly_impl_trait_ref =
11601161
ty::Binder(impl_trait_ref);
11611162
let origin =
@@ -1712,15 +1713,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
17121713
let substs =
17131714
self.rematch_impl(impl_def_id, obligation,
17141715
snapshot, &skol_map, skol_obligation_trait_ref.trait_ref);
1715-
debug!("confirm_impl_candidate substs={:?}", substs);
1716+
debug!("confirm_impl_candidate substs={}", substs.repr(self.tcx()));
17161717
Ok(self.vtable_impl(impl_def_id, substs, obligation.cause.clone(),
17171718
obligation.recursion_depth + 1, skol_map, snapshot))
17181719
})
17191720
}
17201721

17211722
fn vtable_impl(&mut self,
17221723
impl_def_id: ast::DefId,
1723-
substs: Substs<'tcx>,
1724+
substs: Normalized<'tcx, Substs<'tcx>>,
17241725
cause: ObligationCause<'tcx>,
17251726
recursion_depth: uint,
17261727
skol_map: infer::SkolemizationMap,
@@ -1733,21 +1734,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
17331734
recursion_depth,
17341735
skol_map.repr(self.tcx()));
17351736

1736-
let impl_predicates =
1737-
self.impl_predicates(cause,
1737+
let mut impl_obligations =
1738+
self.impl_obligations(cause,
17381739
recursion_depth,
17391740
impl_def_id,
1740-
&substs,
1741+
&substs.value,
17411742
skol_map,
17421743
snapshot);
17431744

1744-
debug!("vtable_impl: impl_def_id={} impl_predicates={}",
1745+
debug!("vtable_impl: impl_def_id={} impl_obligations={}",
17451746
impl_def_id.repr(self.tcx()),
1746-
impl_predicates.repr(self.tcx()));
1747+
impl_obligations.repr(self.tcx()));
1748+
1749+
impl_obligations.extend(TypeSpace, substs.obligations.into_iter());
17471750

17481751
VtableImplData { impl_def_id: impl_def_id,
1749-
substs: substs,
1750-
nested: impl_predicates }
1752+
substs: substs.value,
1753+
nested: impl_obligations }
17511754
}
17521755

17531756
fn confirm_object_candidate(&mut self,
@@ -1931,7 +1934,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
19311934
snapshot: &infer::CombinedSnapshot,
19321935
skol_map: &infer::SkolemizationMap,
19331936
skol_obligation_trait_ref: Rc<ty::TraitRef<'tcx>>)
1934-
-> Substs<'tcx>
1937+
-> Normalized<'tcx, Substs<'tcx>>
19351938
{
19361939
match self.match_impl(impl_def_id, obligation, snapshot,
19371940
skol_map, skol_obligation_trait_ref) {
@@ -1953,7 +1956,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
19531956
snapshot: &infer::CombinedSnapshot,
19541957
skol_map: &infer::SkolemizationMap,
19551958
skol_obligation_trait_ref: Rc<ty::TraitRef<'tcx>>)
1956-
-> Result<Substs<'tcx>, ()>
1959+
-> Result<Normalized<'tcx, Substs<'tcx>>, ()>
19571960
{
19581961
let impl_trait_ref = ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap();
19591962

@@ -1971,6 +1974,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
19711974
let impl_trait_ref = impl_trait_ref.subst(self.tcx(),
19721975
&impl_substs);
19731976

1977+
let impl_trait_ref =
1978+
project::normalize_with_depth(self,
1979+
obligation.cause.clone(),
1980+
obligation.recursion_depth + 1,
1981+
&impl_trait_ref);
1982+
19741983
debug!("match_impl(impl_def_id={}, obligation={}, \
19751984
impl_trait_ref={}, skol_obligation_trait_ref={})",
19761985
impl_def_id.repr(self.tcx()),
@@ -1981,7 +1990,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
19811990
let origin = infer::RelateOutputImplTypes(obligation.cause.span);
19821991
match self.infcx.sub_trait_refs(false,
19831992
origin,
1984-
impl_trait_ref,
1993+
impl_trait_ref.value.clone(),
19851994
skol_obligation_trait_ref) {
19861995
Ok(()) => { }
19871996
Err(e) => {
@@ -2001,7 +2010,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
20012010
}
20022011

20032012
debug!("match_impl: success impl_substs={}", impl_substs.repr(self.tcx()));
2004-
Ok(impl_substs)
2013+
Ok(Normalized { value: impl_substs,
2014+
obligations: impl_trait_ref.obligations })
20052015
}
20062016

20072017
fn fast_reject_trait_refs(&mut self,
@@ -2142,14 +2152,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
21422152
}
21432153
}
21442154

2145-
fn impl_predicates(&mut self,
2146-
cause: ObligationCause<'tcx>,
2147-
recursion_depth: uint,
2148-
impl_def_id: ast::DefId,
2149-
impl_substs: &Substs<'tcx>,
2150-
skol_map: infer::SkolemizationMap,
2151-
snapshot: &infer::CombinedSnapshot)
2152-
-> VecPerParamSpace<PredicateObligation<'tcx>>
2155+
fn impl_obligations(&mut self,
2156+
cause: ObligationCause<'tcx>,
2157+
recursion_depth: uint,
2158+
impl_def_id: ast::DefId,
2159+
impl_substs: &Substs<'tcx>,
2160+
skol_map: infer::SkolemizationMap,
2161+
snapshot: &infer::CombinedSnapshot)
2162+
-> VecPerParamSpace<PredicateObligation<'tcx>>
21532163
{
21542164
let impl_generics = ty::lookup_item_type(self.tcx(), impl_def_id).generics;
21552165
let bounds = impl_generics.to_bounds(self.tcx(), impl_substs);
@@ -2162,9 +2172,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
21622172
cause,
21632173
recursion_depth,
21642174
&normalized_bounds.value);
2165-
for obligation in normalized_bounds.obligations.into_iter() {
2166-
impl_obligations.push(TypeSpace, obligation);
2167-
}
2175+
impl_obligations.extend(TypeSpace, normalized_bounds.obligations.into_iter());
21682176
impl_obligations
21692177
}
21702178

src/librustc_typeck/check/wf.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,9 +235,16 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
235235
// Find the supertrait bounds. This will add `int:Bar`.
236236
let poly_trait_ref = ty::Binder(trait_ref);
237237
let predicates = ty::predicates_for_trait_ref(fcx.tcx(), &poly_trait_ref);
238-
for predicate in predicates.into_iter() {
238+
let predicates = {
239+
let selcx = &mut traits::SelectionContext::new(fcx.infcx(), fcx);
240+
traits::normalize(selcx, cause.clone(), &predicates)
241+
};
242+
for predicate in predicates.value.into_iter() {
239243
fcx.register_predicate(traits::Obligation::new(cause.clone(), predicate));
240244
}
245+
for obligation in predicates.obligations.into_iter() {
246+
fcx.register_predicate(obligation);
247+
}
241248
});
242249
}
243250
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that coherence detects overlap when some of the types in the
12+
// impls are projections of associated type. Issue #20624.
13+
14+
use std::ops::Deref;
15+
16+
pub struct Cow<'a, B: ?Sized>;
17+
18+
/// Trait for moving into a `Cow`
19+
pub trait IntoCow<'a, B: ?Sized> {
20+
/// Moves `self` into `Cow`
21+
fn into_cow(self) -> Cow<'a, B>;
22+
}
23+
24+
impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned {
25+
//~^ ERROR E0119
26+
fn into_cow(self) -> Cow<'a, B> {
27+
self
28+
}
29+
}
30+
31+
impl<'a, B: ?Sized> IntoCow<'a, B> for <B as ToOwned>::Owned where B: ToOwned {
32+
//~^ ERROR E0119
33+
fn into_cow(self) -> Cow<'a, B> {
34+
Cow
35+
}
36+
}
37+
38+
impl<'a, B: ?Sized> IntoCow<'a, B> for &'a B where B: ToOwned {
39+
fn into_cow(self) -> Cow<'a, B> {
40+
Cow
41+
}
42+
}
43+
44+
impl ToOwned for u8 {
45+
type Owned = &'static u8;
46+
fn to_owned(&self) -> &'static u8 { panic!() }
47+
}
48+
49+
/// A generalization of Clone to borrowed data.
50+
pub trait ToOwned {
51+
type Owned;
52+
53+
/// Create owned data from borrowed data, usually by copying.
54+
fn to_owned(&self) -> Self::Owned;
55+
}
56+
57+
58+
fn main() {}
59+
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that we can resolve nested projection types. Issue #20666.
12+
13+
use std::slice;
14+
15+
trait Bound {}
16+
17+
impl<'a> Bound for &'a int {}
18+
19+
trait IntoIterator {
20+
type Iter: Iterator;
21+
22+
fn into_iter(self) -> Self::Iter;
23+
}
24+
25+
impl<'a, T> IntoIterator for &'a [T; 3] {
26+
type Iter = slice::Iter<'a, T>;
27+
28+
fn into_iter(self) -> slice::Iter<'a, T> {
29+
self.iter()
30+
}
31+
}
32+
33+
fn foo<X>(x: X) where
34+
X: IntoIterator,
35+
<<X as IntoIterator>::Iter as Iterator>::Item: Bound,
36+
{
37+
}
38+
39+
fn bar<T, I, X>(x: X) where
40+
T: Bound,
41+
I: Iterator<Item=T>,
42+
X: IntoIterator<Iter=I>,
43+
{
44+
45+
}
46+
47+
fn main() {
48+
foo(&[0i, 1, 2]);
49+
bar(&[0i, 1, 2]);
50+
}

0 commit comments

Comments
 (0)