mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
add Self: Trait<..> inside the param_env of a default impl
This commit is contained in:
parent
b20bfb1fc2
commit
2f22a929c6
@ -181,9 +181,6 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
// obligations within. This is expected to be done 'late enough'
|
||||
// that all type inference variables have been bound and so forth.
|
||||
region_obligations: RefCell<Vec<(ast::NodeId, RegionObligation<'tcx>)>>,
|
||||
|
||||
// true if trait selection in this context should emit `default impl` candiates
|
||||
pub emit_defaul_impl_candidates: Cell<bool>,
|
||||
}
|
||||
|
||||
/// A map returned by `skolemize_late_bound_regions()` indicating the skolemized
|
||||
@ -455,7 +452,6 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
|
||||
err_count_on_creation: tcx.sess.err_count(),
|
||||
in_snapshot: Cell::new(false),
|
||||
region_obligations: RefCell::new(vec![]),
|
||||
emit_defaul_impl_candidates: Cell::new(false)
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
@ -1296,12 +1296,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Using local cache if the infcx can emit `default impls`
|
||||
if self.infcx.emit_defaul_impl_candidates.get() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Otherwise, we can use the global cache.
|
||||
true
|
||||
}
|
||||
@ -1716,11 +1710,30 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
{
|
||||
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(
|
||||
obligation.predicate.def_id(),
|
||||
obligation.predicate.0.trait_ref.self_ty(),
|
||||
|impl_def_id| {
|
||||
if self.infcx().emit_defaul_impl_candidates.get() ||
|
||||
if self_trait_is_present.len() > 0 ||
|
||||
!self.tcx().impl_is_default(impl_def_id) {
|
||||
self.probe(|this, snapshot| { /* [1] */
|
||||
match this.match_impl(impl_def_id, obligation, snapshot) {
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
use hir::def_id::DefId;
|
||||
use ty::{self, Ty, TypeFoldable, Substs, TyCtxt};
|
||||
use ty::subst::{Kind, Subst};
|
||||
use ty::subst::Kind;
|
||||
use traits;
|
||||
use syntax::abi::Abi;
|
||||
use util::ppaux;
|
||||
|
@ -2606,8 +2606,31 @@ fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId)
|
||||
-> ParamEnv<'tcx> {
|
||||
// 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 = tcx.predicates_of(def_id).instantiate_identity(tcx);
|
||||
let bounds = predicates.instantiate_identity(tcx);
|
||||
let predicates = bounds.predicates;
|
||||
|
||||
// Finally, we have to normalize the bounds in the environment, in
|
||||
|
@ -1745,8 +1745,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
body_id: ast::NodeId)
|
||||
-> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
FnCtxt::set_emit_default_impl_candidates(inh, body_id);
|
||||
|
||||
FnCtxt {
|
||||
body_id,
|
||||
param_env,
|
||||
@ -1765,22 +1763,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn set_emit_default_impl_candidates(inh: &'a Inherited<'a, 'gcx, 'tcx>,
|
||||
body_id: ast::NodeId) {
|
||||
inh.infcx.emit_defaul_impl_candidates.set(
|
||||
match inh.tcx.hir.find(body_id) {
|
||||
Some(Node::NodeItem(..)) => {
|
||||
if inh.tcx.impl_is_default(inh.tcx.hir.local_def_id(body_id)) {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
},
|
||||
_ => false
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
pub fn sess(&self) -> &Session {
|
||||
&self.tcx.sess
|
||||
}
|
||||
|
@ -28,4 +28,4 @@ impl Foo for MyStruct {}
|
||||
|
||||
fn main() {
|
||||
println!("{}", MyStruct.foo_one());
|
||||
}
|
||||
}
|
||||
|
@ -27,4 +27,4 @@ default impl<T> Foo for T {
|
||||
fn main() {
|
||||
println!("{}", MyStruct.foo_one());
|
||||
//~^ ERROR no method named `foo_one` found for type `MyStruct` in the current scope
|
||||
}
|
||||
}
|
||||
|
@ -15,4 +15,4 @@ trait Foo<'a, T: Eq + 'a> { }
|
||||
default impl<U> Foo<'static, U> for () {}
|
||||
//~^ ERROR the trait bound `U: std::cmp::Eq` is not satisfied
|
||||
|
||||
fn main(){}
|
||||
fn main(){}
|
||||
|
@ -31,4 +31,4 @@ impl Foo for MyStruct {
|
||||
|
||||
fn main() {
|
||||
assert!(MyStruct.foo_two() == "generic");
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user