mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 15:23:46 +00:00
add Self: Trait<..> inside the param_env of a default impl
This commit is contained in:
parent
2f22a929c6
commit
220bb22e1b
@ -579,15 +579,15 @@ impl<'a, I, T: 'a> FusedIterator for Cloned<I>
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
default unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned<I>
|
unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned<I>
|
||||||
where I: TrustedRandomAccess<Item=&'a T>, T: Clone
|
where I: TrustedRandomAccess<Item=&'a T>, T: Clone
|
||||||
{
|
{
|
||||||
unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item {
|
default unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item {
|
||||||
self.it.get_unchecked(i).clone()
|
self.it.get_unchecked(i).clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn may_have_side_effect() -> bool { true }
|
default fn may_have_side_effect() -> bool { true }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
@ -1710,44 +1710,22 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||||||
{
|
{
|
||||||
debug!("assemble_candidates_from_impls(obligation={:?})", obligation);
|
debug!("assemble_candidates_from_impls(obligation={:?})", obligation);
|
||||||
|
|
||||||
// Check if default impls should be emitted.
|
|
||||||
// default impls are emitted if the param_env is refered to a default impl.
|
|
||||||
// The param_env should contain a Self: Trait<..> predicate in those cases
|
|
||||||
let self_trait_is_present:Vec<&ty::Predicate<'tcx>> =
|
|
||||||
obligation.param_env
|
|
||||||
.caller_bounds
|
|
||||||
.iter()
|
|
||||||
.filter(|predicate| {
|
|
||||||
match **predicate {
|
|
||||||
ty::Predicate::Trait(ref trait_predicate) => {
|
|
||||||
trait_predicate.def_id() ==
|
|
||||||
obligation.predicate.def_id() &&
|
|
||||||
obligation.predicate.0.trait_ref.self_ty() ==
|
|
||||||
trait_predicate.skip_binder().self_ty()
|
|
||||||
}
|
|
||||||
_ => false
|
|
||||||
}
|
|
||||||
}).collect::<Vec<&ty::Predicate<'tcx>>>();
|
|
||||||
|
|
||||||
self.tcx().for_each_relevant_impl(
|
self.tcx().for_each_relevant_impl(
|
||||||
obligation.predicate.def_id(),
|
obligation.predicate.def_id(),
|
||||||
obligation.predicate.0.trait_ref.self_ty(),
|
obligation.predicate.0.trait_ref.self_ty(),
|
||||||
|impl_def_id| {
|
|impl_def_id| {
|
||||||
if self_trait_is_present.len() > 0 ||
|
self.probe(|this, snapshot| { /* [1] */
|
||||||
!self.tcx().impl_is_default(impl_def_id) {
|
match this.match_impl(impl_def_id, obligation, snapshot) {
|
||||||
self.probe(|this, snapshot| { /* [1] */
|
Ok(skol_map) => {
|
||||||
match this.match_impl(impl_def_id, obligation, snapshot) {
|
candidates.vec.push(ImplCandidate(impl_def_id));
|
||||||
Ok(skol_map) => {
|
|
||||||
candidates.vec.push(ImplCandidate(impl_def_id));
|
|
||||||
|
|
||||||
// NB: we can safely drop the skol map
|
// NB: we can safely drop the skol map
|
||||||
// since we are in a probe [1]
|
// since we are in a probe [1]
|
||||||
mem::drop(skol_map);
|
mem::drop(skol_map);
|
||||||
}
|
|
||||||
Err(_) => { }
|
|
||||||
}
|
}
|
||||||
});
|
Err(_) => { }
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2606,31 +2606,8 @@ fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
def_id: DefId)
|
def_id: DefId)
|
||||||
-> ParamEnv<'tcx> {
|
-> ParamEnv<'tcx> {
|
||||||
// Compute the bounds on Self and the type parameters.
|
// Compute the bounds on Self and the type parameters.
|
||||||
let mut predicates = tcx.predicates_of(def_id);
|
|
||||||
match tcx.hir.as_local_node_id(def_id)
|
|
||||||
.and_then(|node_id| tcx.hir.find(node_id))
|
|
||||||
.and_then(|item| {
|
|
||||||
match item {
|
|
||||||
hir::map::NodeItem(..) => {
|
|
||||||
if tcx.impl_is_default(def_id) {
|
|
||||||
tcx.impl_trait_ref(def_id)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => None
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
Some(trait_ref) =>
|
|
||||||
predicates.predicates
|
|
||||||
.push(
|
|
||||||
trait_ref.to_poly_trait_ref()
|
|
||||||
.to_predicate()
|
|
||||||
),
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
let bounds = predicates.instantiate_identity(tcx);
|
let bounds = tcx.predicates_of(def_id).instantiate_identity(tcx);
|
||||||
let predicates = bounds.predicates;
|
let predicates = bounds.predicates;
|
||||||
|
|
||||||
// Finally, we have to normalize the bounds in the environment, in
|
// Finally, we have to normalize the bounds in the environment, in
|
||||||
|
@ -1364,6 +1364,7 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
let node = tcx.hir.get(node_id);
|
let node = tcx.hir.get(node_id);
|
||||||
|
|
||||||
let mut is_trait = None;
|
let mut is_trait = None;
|
||||||
|
let mut is_default_impl_trait = None;
|
||||||
|
|
||||||
let icx = ItemCtxt::new(tcx, def_id);
|
let icx = ItemCtxt::new(tcx, def_id);
|
||||||
let no_generics = hir::Generics::empty();
|
let no_generics = hir::Generics::empty();
|
||||||
@ -1373,8 +1374,13 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
|
|
||||||
NodeItem(item) => {
|
NodeItem(item) => {
|
||||||
match item.node {
|
match item.node {
|
||||||
|
ItemImpl(_, _, defaultness, ref generics, ..) => {
|
||||||
|
if defaultness.is_default() {
|
||||||
|
is_default_impl_trait = tcx.impl_trait_ref(def_id);
|
||||||
|
}
|
||||||
|
generics
|
||||||
|
}
|
||||||
ItemFn(.., ref generics, _) |
|
ItemFn(.., ref generics, _) |
|
||||||
ItemImpl(_, _, _, ref generics, ..) |
|
|
||||||
ItemTy(_, ref generics) |
|
ItemTy(_, ref generics) |
|
||||||
ItemEnum(_, ref generics) |
|
ItemEnum(_, ref generics) |
|
||||||
ItemStruct(_, ref generics) |
|
ItemStruct(_, ref generics) |
|
||||||
@ -1446,6 +1452,18 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
predicates.push(trait_ref.to_poly_trait_ref().to_predicate());
|
predicates.push(trait_ref.to_poly_trait_ref().to_predicate());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In default impls, we can assume that the self type implements
|
||||||
|
// the trait. So in:
|
||||||
|
//
|
||||||
|
// default impl Foo for Bar { .. }
|
||||||
|
//
|
||||||
|
// we add a default where clause `Foo: Bar`. We do a similar thing for traits
|
||||||
|
// (see below). Recall that a default impl is not itself an impl, but rather a
|
||||||
|
// set of defaults that can be incorporated into another impl.
|
||||||
|
if let Some(trait_ref) = is_default_impl_trait {
|
||||||
|
predicates.push(trait_ref.to_poly_trait_ref().to_predicate());
|
||||||
|
}
|
||||||
|
|
||||||
// Collect the region predicates that were declared inline as
|
// Collect the region predicates that were declared inline as
|
||||||
// well. In the case of parameters declared on a fn or method, we
|
// well. In the case of parameters declared on a fn or method, we
|
||||||
// have to be careful to only iterate over early-bound regions.
|
// have to be careful to only iterate over early-bound regions.
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
// Tests that default impls do not have to supply all items but regular impls do.
|
||||||
|
|
||||||
#![feature(specialization)]
|
#![feature(specialization)]
|
||||||
|
|
||||||
trait Foo {
|
trait Foo {
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
// Tests that:
|
||||||
|
// - default impls do not have to supply all items and
|
||||||
|
// - a default impl does not count as an impl (in this case, an incomplete default impl).
|
||||||
|
|
||||||
#![feature(specialization)]
|
#![feature(specialization)]
|
||||||
|
|
||||||
trait Foo {
|
trait Foo {
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
// Tests that a default impl still has to have a WF trait ref.
|
||||||
|
|
||||||
#![feature(specialization)]
|
#![feature(specialization)]
|
||||||
|
|
||||||
trait Foo<'a, T: Eq + 'a> { }
|
trait Foo<'a, T: Eq + 'a> { }
|
||||||
|
@ -8,18 +8,22 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
|
// Tests that we can combine a default impl that supplies one method with a
|
||||||
|
// full impl that supplies the other, and they can invoke one another.
|
||||||
|
|
||||||
#![feature(specialization)]
|
#![feature(specialization)]
|
||||||
|
|
||||||
trait Foo {
|
trait Foo {
|
||||||
fn foo_one(&self) -> &'static str;
|
fn foo_one(&self) -> &'static str;
|
||||||
fn foo_two(&self) -> &'static str;
|
fn foo_two(&self) -> &'static str;
|
||||||
|
fn foo_three(&self) -> &'static str;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MyStruct;
|
struct MyStruct;
|
||||||
|
|
||||||
default impl<T> Foo for T {
|
default impl<T> Foo for T {
|
||||||
fn foo_one(&self) -> &'static str {
|
fn foo_one(&self) -> &'static str {
|
||||||
"generic"
|
self.foo_three()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,6 +31,10 @@ impl Foo for MyStruct {
|
|||||||
fn foo_two(&self) -> &'static str {
|
fn foo_two(&self) -> &'static str {
|
||||||
self.foo_one()
|
self.foo_one()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn foo_three(&self) -> &'static str {
|
||||||
|
"generic"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
Loading…
Reference in New Issue
Block a user