use super::SelectionContext;
use super::{Obligation, ObligationCause};
+use super::project;
use super::util;
use middle::subst::{Subst};
impl1_def_id.repr(infcx.tcx),
impl2_def_id.repr(infcx.tcx));
+ let param_env = ty::empty_parameter_environment(infcx.tcx);
+ let mut selcx = SelectionContext::intercrate(infcx, ¶m_env);
+ let cause = ObligationCause::dummy();
+
// `impl1` provides an implementation of `Foo<X,Y> for Z`.
let impl1_substs =
util::fresh_substs_for_impl(infcx, DUMMY_SP, impl1_def_id);
let impl1_trait_ref =
(*ty::impl_trait_ref(infcx.tcx, impl1_def_id).unwrap()).subst(infcx.tcx, &impl1_substs);
+ let impl1_trait_ref =
+ project::normalize(&mut selcx, cause.clone(), &impl1_trait_ref);
// Determine whether `impl2` can provide an implementation for those
// same types.
- let param_env = ty::empty_parameter_environment(infcx.tcx);
- let mut selcx = SelectionContext::intercrate(infcx, ¶m_env);
- let obligation = Obligation::new(ObligationCause::dummy(),
+ let obligation = Obligation::new(cause,
ty::Binder(ty::TraitPredicate {
- trait_ref: Rc::new(impl1_trait_ref),
+ trait_ref: Rc::new(impl1_trait_ref.value),
}));
debug!("impl_can_satisfy(obligation={})", obligation.repr(infcx.tcx));
- selcx.evaluate_impl(impl2_def_id, &obligation)
+ selcx.evaluate_impl(impl2_def_id, &obligation) &&
+ impl1_trait_ref.obligations.iter().all(
+ |o| selcx.evaluate_obligation(o))
}
#[allow(missing_copy_implementations)]
use super::{DerivedObligationCause};
use super::{project};
+use super::project::Normalized;
use super::{PredicateObligation, Obligation, TraitObligation, ObligationCause};
use super::{ObligationCauseCode, BuiltinDerivedObligation};
use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch};
let impl_trait_ref =
ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap();
let impl_trait_ref =
- impl_trait_ref.subst(self.tcx(), &impl_substs);
+ impl_trait_ref.subst(self.tcx(), &impl_substs.value);
let poly_impl_trait_ref =
ty::Binder(impl_trait_ref);
let origin =
let substs =
self.rematch_impl(impl_def_id, obligation,
snapshot, &skol_map, skol_obligation_trait_ref.trait_ref);
- debug!("confirm_impl_candidate substs={:?}", substs);
+ debug!("confirm_impl_candidate substs={}", substs.repr(self.tcx()));
Ok(self.vtable_impl(impl_def_id, substs, obligation.cause.clone(),
obligation.recursion_depth + 1, skol_map, snapshot))
})
fn vtable_impl(&mut self,
impl_def_id: ast::DefId,
- substs: Substs<'tcx>,
+ substs: Normalized<'tcx, Substs<'tcx>>,
cause: ObligationCause<'tcx>,
recursion_depth: uint,
skol_map: infer::SkolemizationMap,
recursion_depth,
skol_map.repr(self.tcx()));
- let impl_predicates =
- self.impl_predicates(cause,
+ let mut impl_obligations =
+ self.impl_obligations(cause,
recursion_depth,
impl_def_id,
- &substs,
+ &substs.value,
skol_map,
snapshot);
- debug!("vtable_impl: impl_def_id={} impl_predicates={}",
+ debug!("vtable_impl: impl_def_id={} impl_obligations={}",
impl_def_id.repr(self.tcx()),
- impl_predicates.repr(self.tcx()));
+ impl_obligations.repr(self.tcx()));
+
+ impl_obligations.extend(TypeSpace, substs.obligations.into_iter());
VtableImplData { impl_def_id: impl_def_id,
- substs: substs,
- nested: impl_predicates }
+ substs: substs.value,
+ nested: impl_obligations }
}
fn confirm_object_candidate(&mut self,
snapshot: &infer::CombinedSnapshot,
skol_map: &infer::SkolemizationMap,
skol_obligation_trait_ref: Rc<ty::TraitRef<'tcx>>)
- -> Substs<'tcx>
+ -> Normalized<'tcx, Substs<'tcx>>
{
match self.match_impl(impl_def_id, obligation, snapshot,
skol_map, skol_obligation_trait_ref) {
snapshot: &infer::CombinedSnapshot,
skol_map: &infer::SkolemizationMap,
skol_obligation_trait_ref: Rc<ty::TraitRef<'tcx>>)
- -> Result<Substs<'tcx>, ()>
+ -> Result<Normalized<'tcx, Substs<'tcx>>, ()>
{
let impl_trait_ref = ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap();
let impl_trait_ref = impl_trait_ref.subst(self.tcx(),
&impl_substs);
+ let impl_trait_ref =
+ project::normalize_with_depth(self,
+ obligation.cause.clone(),
+ obligation.recursion_depth + 1,
+ &impl_trait_ref);
+
debug!("match_impl(impl_def_id={}, obligation={}, \
impl_trait_ref={}, skol_obligation_trait_ref={})",
impl_def_id.repr(self.tcx()),
let origin = infer::RelateOutputImplTypes(obligation.cause.span);
match self.infcx.sub_trait_refs(false,
origin,
- impl_trait_ref,
+ impl_trait_ref.value.clone(),
skol_obligation_trait_ref) {
Ok(()) => { }
Err(e) => {
}
debug!("match_impl: success impl_substs={}", impl_substs.repr(self.tcx()));
- Ok(impl_substs)
+ Ok(Normalized { value: impl_substs,
+ obligations: impl_trait_ref.obligations })
}
fn fast_reject_trait_refs(&mut self,
}
}
- fn impl_predicates(&mut self,
- cause: ObligationCause<'tcx>,
- recursion_depth: uint,
- impl_def_id: ast::DefId,
- impl_substs: &Substs<'tcx>,
- skol_map: infer::SkolemizationMap,
- snapshot: &infer::CombinedSnapshot)
- -> VecPerParamSpace<PredicateObligation<'tcx>>
+ fn impl_obligations(&mut self,
+ cause: ObligationCause<'tcx>,
+ recursion_depth: uint,
+ impl_def_id: ast::DefId,
+ impl_substs: &Substs<'tcx>,
+ skol_map: infer::SkolemizationMap,
+ snapshot: &infer::CombinedSnapshot)
+ -> VecPerParamSpace<PredicateObligation<'tcx>>
{
let impl_generics = ty::lookup_item_type(self.tcx(), impl_def_id).generics;
let bounds = impl_generics.to_bounds(self.tcx(), impl_substs);
cause,
recursion_depth,
&normalized_bounds.value);
- for obligation in normalized_bounds.obligations.into_iter() {
- impl_obligations.push(TypeSpace, obligation);
- }
+ impl_obligations.extend(TypeSpace, normalized_bounds.obligations.into_iter());
impl_obligations
}
--- /dev/null
+// 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 coherence detects overlap when some of the types in the
+// impls are projections of associated type. Issue #20624.
+
+use std::ops::Deref;
+
+pub struct Cow<'a, B: ?Sized>;
+
+/// Trait for moving into a `Cow`
+pub trait IntoCow<'a, B: ?Sized> {
+ /// Moves `self` into `Cow`
+ fn into_cow(self) -> Cow<'a, B>;
+}
+
+impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned {
+//~^ ERROR E0119
+ fn into_cow(self) -> Cow<'a, B> {
+ self
+ }
+}
+
+impl<'a, B: ?Sized> IntoCow<'a, B> for <B as ToOwned>::Owned where B: ToOwned {
+//~^ ERROR E0119
+ fn into_cow(self) -> Cow<'a, B> {
+ Cow
+ }
+}
+
+impl<'a, B: ?Sized> IntoCow<'a, B> for &'a B where B: ToOwned {
+ fn into_cow(self) -> Cow<'a, B> {
+ Cow
+ }
+}
+
+impl ToOwned for u8 {
+ type Owned = &'static u8;
+ fn to_owned(&self) -> &'static u8 { panic!() }
+}
+
+/// A generalization of Clone to borrowed data.
+pub trait ToOwned {
+ type Owned;
+
+ /// Create owned data from borrowed data, usually by copying.
+ fn to_owned(&self) -> Self::Owned;
+}
+
+
+fn main() {}
+