Skip to content

Commit b20bfb1

Browse files
committed
support default impl for specialization
not skipping any wfchecks on default impls
1 parent 13e80af commit b20bfb1

File tree

6 files changed

+64
-31
lines changed

6 files changed

+64
-31
lines changed

src/librustc/infer/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
181181
// obligations within. This is expected to be done 'late enough'
182182
// that all type inference variables have been bound and so forth.
183183
region_obligations: RefCell<Vec<(ast::NodeId, RegionObligation<'tcx>)>>,
184+
185+
// true if trait selection in this context should emit `default impl` candiates
186+
pub emit_defaul_impl_candidates: Cell<bool>,
184187
}
185188

186189
/// A map returned by `skolemize_late_bound_regions()` indicating the skolemized
@@ -452,6 +455,7 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
452455
err_count_on_creation: tcx.sess.err_count(),
453456
in_snapshot: Cell::new(false),
454457
region_obligations: RefCell::new(vec![]),
458+
emit_defaul_impl_candidates: Cell::new(false)
455459
}))
456460
}
457461
}

src/librustc/traits/select.rs

+20-11
Original file line numberDiff line numberDiff line change
@@ -1296,6 +1296,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
12961296
return false;
12971297
}
12981298

1299+
// Using local cache if the infcx can emit `default impls`
1300+
if self.infcx.emit_defaul_impl_candidates.get() {
1301+
return false;
1302+
}
1303+
1304+
12991305
// Otherwise, we can use the global cache.
13001306
true
13011307
}
@@ -1714,18 +1720,21 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
17141720
obligation.predicate.def_id(),
17151721
obligation.predicate.0.trait_ref.self_ty(),
17161722
|impl_def_id| {
1717-
self.probe(|this, snapshot| { /* [1] */
1718-
match this.match_impl(impl_def_id, obligation, snapshot) {
1719-
Ok(skol_map) => {
1720-
candidates.vec.push(ImplCandidate(impl_def_id));
1721-
1722-
// NB: we can safely drop the skol map
1723-
// since we are in a probe [1]
1724-
mem::drop(skol_map);
1723+
if self.infcx().emit_defaul_impl_candidates.get() ||
1724+
!self.tcx().impl_is_default(impl_def_id) {
1725+
self.probe(|this, snapshot| { /* [1] */
1726+
match this.match_impl(impl_def_id, obligation, snapshot) {
1727+
Ok(skol_map) => {
1728+
candidates.vec.push(ImplCandidate(impl_def_id));
1729+
1730+
// NB: we can safely drop the skol map
1731+
// since we are in a probe [1]
1732+
mem::drop(skol_map);
1733+
}
1734+
Err(_) => { }
17251735
}
1726-
Err(_) => { }
1727-
}
1728-
});
1736+
});
1737+
}
17291738
}
17301739
);
17311740

src/librustc/ty/trait_def.rs

+3-9
Original file line numberDiff line numberDiff line change
@@ -92,16 +92,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
9292
self_ty: Ty<'tcx>,
9393
mut f: F)
9494
{
95-
let mut emit_impl = |impl_def_id: DefId| {
96-
if !self.impl_is_default(impl_def_id) {
97-
f(impl_def_id);
98-
}
99-
};
100-
10195
let impls = self.trait_impls_of(def_id);
10296

10397
for &impl_def_id in impls.blanket_impls.iter() {
104-
emit_impl(impl_def_id);
98+
f(impl_def_id);
10599
}
106100

107101
// simplify_type(.., false) basically replaces type parameters and
@@ -132,13 +126,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
132126
if let Some(simp) = fast_reject::simplify_type(self, self_ty, true) {
133127
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
134128
for &impl_def_id in impls {
135-
emit_impl(impl_def_id);
129+
f(impl_def_id);
136130
}
137131
}
138132
} else {
139133
for v in impls.non_blanket_impls.values() {
140134
for &impl_def_id in v {
141-
emit_impl(impl_def_id);
135+
f(impl_def_id);
142136
}
143137
}
144138
}

src/librustc_typeck/check/mod.rs

+18
Original file line numberDiff line numberDiff line change
@@ -1745,6 +1745,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
17451745
param_env: ty::ParamEnv<'tcx>,
17461746
body_id: ast::NodeId)
17471747
-> FnCtxt<'a, 'gcx, 'tcx> {
1748+
FnCtxt::set_emit_default_impl_candidates(inh, body_id);
1749+
17481750
FnCtxt {
17491751
body_id,
17501752
param_env,
@@ -1763,6 +1765,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
17631765
}
17641766
}
17651767

1768+
fn set_emit_default_impl_candidates(inh: &'a Inherited<'a, 'gcx, 'tcx>,
1769+
body_id: ast::NodeId) {
1770+
inh.infcx.emit_defaul_impl_candidates.set(
1771+
match inh.tcx.hir.find(body_id) {
1772+
Some(Node::NodeItem(..)) => {
1773+
if inh.tcx.impl_is_default(inh.tcx.hir.local_def_id(body_id)) {
1774+
true
1775+
} else {
1776+
false
1777+
}
1778+
},
1779+
_ => false
1780+
}
1781+
);
1782+
}
1783+
17661784
pub fn sess(&self) -> &Session {
17671785
&self.tcx.sess
17681786
}

src/librustc_typeck/check/wfcheck.rs

+1-11
Original file line numberDiff line numberDiff line change
@@ -343,18 +343,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
343343
fcx.body_id,
344344
&trait_ref,
345345
ast_trait_ref.path.span);
346-
347-
// not registering predicates associcated with a `default impl`
348-
let impl_is_default = fcx.tcx.impl_is_default(item_def_id);
349346
for obligation in obligations {
350-
let register = match obligation.predicate {
351-
ty::Predicate::Trait(..) => !impl_is_default,
352-
_ => true
353-
};
354-
355-
if register {
356-
fcx.register_predicate(obligation);
357-
}
347+
fcx.register_predicate(obligation);
358348
}
359349
}
360350
None => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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+
#![feature(specialization)]
12+
13+
trait Foo<'a, T: Eq + 'a> { }
14+
15+
default impl<U> Foo<'static, U> for () {}
16+
//~^ ERROR the trait bound `U: std::cmp::Eq` is not satisfied
17+
18+
fn main(){}

0 commit comments

Comments
 (0)