support default impl for specialization
not skipping any wfchecks on default impls
This commit is contained in:
parent
13e80af159
commit
b20bfb1fc2
6 changed files with 63 additions and 30 deletions
|
|
@ -181,6 +181,9 @@ 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
|
||||
|
|
@ -452,6 +455,7 @@ 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,6 +1296,12 @@ 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
|
||||
}
|
||||
|
|
@ -1714,18 +1720,21 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
obligation.predicate.def_id(),
|
||||
obligation.predicate.0.trait_ref.self_ty(),
|
||||
|impl_def_id| {
|
||||
self.probe(|this, snapshot| { /* [1] */
|
||||
match this.match_impl(impl_def_id, obligation, snapshot) {
|
||||
Ok(skol_map) => {
|
||||
candidates.vec.push(ImplCandidate(impl_def_id));
|
||||
if self.infcx().emit_defaul_impl_candidates.get() ||
|
||||
!self.tcx().impl_is_default(impl_def_id) {
|
||||
self.probe(|this, snapshot| { /* [1] */
|
||||
match this.match_impl(impl_def_id, obligation, snapshot) {
|
||||
Ok(skol_map) => {
|
||||
candidates.vec.push(ImplCandidate(impl_def_id));
|
||||
|
||||
// NB: we can safely drop the skol map
|
||||
// since we are in a probe [1]
|
||||
mem::drop(skol_map);
|
||||
// NB: we can safely drop the skol map
|
||||
// since we are in a probe [1]
|
||||
mem::drop(skol_map);
|
||||
}
|
||||
Err(_) => { }
|
||||
}
|
||||
Err(_) => { }
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -92,16 +92,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
self_ty: Ty<'tcx>,
|
||||
mut f: F)
|
||||
{
|
||||
let mut emit_impl = |impl_def_id: DefId| {
|
||||
if !self.impl_is_default(impl_def_id) {
|
||||
f(impl_def_id);
|
||||
}
|
||||
};
|
||||
|
||||
let impls = self.trait_impls_of(def_id);
|
||||
|
||||
for &impl_def_id in impls.blanket_impls.iter() {
|
||||
emit_impl(impl_def_id);
|
||||
f(impl_def_id);
|
||||
}
|
||||
|
||||
// simplify_type(.., false) basically replaces type parameters and
|
||||
|
|
@ -132,13 +126,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
if let Some(simp) = fast_reject::simplify_type(self, self_ty, true) {
|
||||
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
|
||||
for &impl_def_id in impls {
|
||||
emit_impl(impl_def_id);
|
||||
f(impl_def_id);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for v in impls.non_blanket_impls.values() {
|
||||
for &impl_def_id in v {
|
||||
emit_impl(impl_def_id);
|
||||
f(impl_def_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1745,6 +1745,8 @@ 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,
|
||||
|
|
@ -1763,6 +1765,22 @@ 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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -343,18 +343,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
|
|||
fcx.body_id,
|
||||
&trait_ref,
|
||||
ast_trait_ref.path.span);
|
||||
|
||||
// not registering predicates associcated with a `default impl`
|
||||
let impl_is_default = fcx.tcx.impl_is_default(item_def_id);
|
||||
for obligation in obligations {
|
||||
let register = match obligation.predicate {
|
||||
ty::Predicate::Trait(..) => !impl_is_default,
|
||||
_ => true
|
||||
};
|
||||
|
||||
if register {
|
||||
fcx.register_predicate(obligation);
|
||||
}
|
||||
fcx.register_predicate(obligation);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright 2015 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.
|
||||
|
||||
#![feature(specialization)]
|
||||
|
||||
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(){}
|
||||
Loading…
Add table
Add a link
Reference in a new issue