Skip to content

Commit 13e80af

Browse files
committed
support default impl for specialization
a default impl should never be considered as implementing the trait on its own -- regardless of whether it contains all items or not
1 parent f5c55ff commit 13e80af

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+66
-1525
lines changed

src/librustc/ich/impls_ty.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,7 @@ impl_stable_hash_for!(enum ty::Visibility {
218218
});
219219

220220
impl_stable_hash_for!(struct ty::TraitRef<'tcx> { def_id, substs });
221-
impl_stable_hash_for!(enum ty::DefaultImplCheck { Yes, No });
222-
impl_stable_hash_for!(struct ty::TraitPredicate<'tcx> { trait_ref, default_impl_check });
221+
impl_stable_hash_for!(struct ty::TraitPredicate<'tcx> { trait_ref });
223222
impl_stable_hash_for!(tuple_struct ty::EquatePredicate<'tcx> { t1, t2 });
224223
impl_stable_hash_for!(struct ty::SubtypePredicate<'tcx> { a_is_expected, a, b });
225224

src/librustc/traits/select.rs

+5-31
Original file line numberDiff line numberDiff line change
@@ -1083,39 +1083,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
10831083
}
10841084

10851085
// Treat negative impls as unimplemented
1086-
fn filter_negative_and_default_impls<'o>(&self,
1087-
candidate: SelectionCandidate<'tcx>,
1088-
stack: &TraitObligationStack<'o, 'tcx>)
1089-
-> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
1090-
1086+
fn filter_negative_impls(&self, candidate: SelectionCandidate<'tcx>)
1087+
-> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
10911088
if let ImplCandidate(def_id) = candidate {
10921089
if self.tcx().impl_polarity(def_id) == hir::ImplPolarity::Negative {
10931090
return Err(Unimplemented)
10941091
}
1095-
1096-
// if def_id is a default impl and it doesn't implement all the trait items,
1097-
// the impl doesn't implement the trait.
1098-
// An `Unimplemented` error is returned only if the default_impl_check is
1099-
// applicable to the trait predicate or the cause of the predicate is an
1100-
// `ObjectCastObligation`
1101-
if self.tcx().impl_is_default(def_id) &&
1102-
!self.tcx().default_impl_implement_all_methods(def_id){
1103-
match stack.obligation.cause.code {
1104-
ObligationCauseCode::ObjectCastObligation(_) => {
1105-
return Err(Unimplemented)
1106-
},
1107-
ObligationCauseCode::ItemObligation(..) |
1108-
ObligationCauseCode::MiscObligation => {
1109-
if let ty::DefaultImplCheck::Yes = stack.obligation
1110-
.predicate
1111-
.skip_binder()
1112-
.default_impl_check {
1113-
return Err(Unimplemented)
1114-
}
1115-
},
1116-
_ => {}
1117-
}
1118-
}
11191092
}
11201093
Ok(Some(candidate))
11211094
}
@@ -1205,8 +1178,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
12051178
// Instead, we select the right impl now but report `Bar does
12061179
// not implement Clone`.
12071180
if candidates.len() == 1 {
1208-
return self.filter_negative_and_default_impls(candidates.pop().unwrap(), stack);
1181+
return self.filter_negative_impls(candidates.pop().unwrap());
12091182
}
1183+
12101184
// Winnow, but record the exact outcome of evaluation, which
12111185
// is needed for specialization.
12121186
let mut candidates: Vec<_> = candidates.into_iter().filter_map(|c| {
@@ -1265,7 +1239,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
12651239
}
12661240

12671241
// Just one candidate left.
1268-
self.filter_negative_and_default_impls(candidates.pop().unwrap().candidate, stack)
1242+
self.filter_negative_impls(candidates.pop().unwrap().candidate)
12691243
}
12701244

12711245
fn is_knowable<'o>(&mut self,

src/librustc/traits/util.rs

+2-23
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,8 @@ fn anonymize_predicate<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
2222
pred: &ty::Predicate<'tcx>)
2323
-> ty::Predicate<'tcx> {
2424
match *pred {
25-
ty::Predicate::Trait(ref data) => {
26-
let anonymized_pred = ty::Predicate::Trait(tcx.anonymize_late_bound_regions(data));
27-
anonymized_pred.change_default_impl_check(ty::DefaultImplCheck::No)
28-
.unwrap_or(anonymized_pred)
29-
}
25+
ty::Predicate::Trait(ref data) =>
26+
ty::Predicate::Trait(tcx.anonymize_late_bound_regions(data)),
3027

3128
ty::Predicate::Equate(ref data) =>
3229
ty::Predicate::Equate(tcx.anonymize_late_bound_regions(data)),
@@ -557,24 +554,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
557554
pub fn impl_item_is_final(self, node_item: &NodeItem<hir::Defaultness>) -> bool {
558555
node_item.item.is_final() && !self.impl_is_default(node_item.node.def_id())
559556
}
560-
561-
pub fn default_impl_implement_all_methods(self, node_item_def_id: DefId) -> bool {
562-
if let Some(impl_trait_ref) = self.impl_trait_ref(node_item_def_id) {
563-
let trait_def = self.trait_def(impl_trait_ref.def_id);
564-
for trait_item in self.associated_items(impl_trait_ref.def_id) {
565-
let is_implemented = trait_def.ancestors(self, node_item_def_id)
566-
.defs(self, trait_item.name, trait_item.kind, impl_trait_ref.def_id)
567-
.next()
568-
.map(|node_item| !node_item.node.is_from_trait())
569-
.unwrap_or(false);
570-
571-
if !is_implemented {
572-
return false;
573-
}
574-
}
575-
}
576-
true
577-
}
578557
}
579558

580559
pub enum TupleArgumentsFlag { Yes, No }

src/librustc/ty/instance.rs

+1-118
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,14 @@
99
// except according to those terms.
1010

1111
use hir::def_id::DefId;
12-
use ty::{self, Ty, TypeFoldable, Substs, TyCtxt, AssociatedKind, AssociatedItemContainer};
12+
use ty::{self, Ty, TypeFoldable, Substs, TyCtxt};
1313
use ty::subst::{Kind, Subst};
1414
use traits;
1515
use syntax::abi::Abi;
1616
use util::ppaux;
1717

1818
use std::fmt;
1919

20-
use syntax_pos::{BytePos, Span};
21-
use syntax::ext::hygiene::SyntaxContext;
22-
use hir::map::Node::NodeTraitItem;
23-
use hir;
24-
2520
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
2621
pub struct Instance<'tcx> {
2722
pub def: InstanceDef<'tcx>,
@@ -265,13 +260,6 @@ fn resolve_associated_item<'a, 'tcx>(
265260
traits::VtableImpl(impl_data) => {
266261
let (def_id, substs) = traits::find_associated_item(
267262
tcx, trait_item, rcvr_substs, &impl_data);
268-
269-
check_unimplemented_trait_item(tcx,
270-
impl_data.impl_def_id,
271-
def_id,
272-
trait_id,
273-
trait_item);
274-
275263
let substs = tcx.erase_regions(&substs);
276264
Some(ty::Instance::new(def_id, substs))
277265
}
@@ -375,108 +363,3 @@ fn fn_once_adapter_instance<'a, 'tcx>(
375363
debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig);
376364
Instance { def, substs }
377365
}
378-
379-
fn check_unimplemented_trait_item<'a, 'tcx>(
380-
tcx: TyCtxt<'a, 'tcx, 'tcx>,
381-
impl_def_id: DefId,
382-
trait_item_def_id: DefId,
383-
trait_id: DefId,
384-
trait_item: &ty::AssociatedItem)
385-
{
386-
// if trait_item_def_id is a trait item and it doesn't have a default trait implementation
387-
// the resolution has found an unimplemented trait item inside a default impl
388-
if tcx.impl_is_default(impl_def_id) {
389-
let is_unimplemented_trait_item = match tcx.hir.as_local_node_id(trait_item_def_id) {
390-
Some(node_id) =>
391-
match tcx.hir.find(node_id) {
392-
Some(NodeTraitItem(item)) => {
393-
if let hir::TraitItemKind::Method(_,
394-
hir::TraitMethod::Provided(_))
395-
= item.node {
396-
false
397-
} else {
398-
true
399-
}
400-
},
401-
_ => false
402-
}
403-
None => {
404-
let item = tcx.global_tcx().associated_item(trait_item_def_id);
405-
match item.kind {
406-
AssociatedKind::Method => match item.container {
407-
AssociatedItemContainer::TraitContainer(_) => {
408-
!item.defaultness.has_value()
409-
}
410-
_ => false
411-
}
412-
_ => false
413-
}
414-
}
415-
};
416-
417-
if is_unimplemented_trait_item {
418-
let mut err = tcx.sess.struct_err(&format!("the trait method `{}` \
419-
is not implemented",
420-
trait_item.name));
421-
422-
let mut help_messages = Vec::new();
423-
help_messages.push(
424-
if impl_def_id.is_local() {
425-
let item = tcx.hir
426-
.expect_item(
427-
tcx.hir
428-
.as_local_node_id(impl_def_id).unwrap()
429-
);
430-
(item.span, format!("implement it inside this `default impl`"))
431-
} else {
432-
(Span::new (
433-
BytePos(0),
434-
BytePos(0),
435-
SyntaxContext::empty()
436-
),
437-
format!("implement it inside the {} `default impl`",
438-
tcx.item_path_str(impl_def_id)))
439-
}
440-
);
441-
442-
help_messages.push(
443-
if trait_id.is_local() {
444-
let trait_item = tcx.hir
445-
.expect_item(
446-
tcx.hir
447-
.as_local_node_id(trait_id).unwrap()
448-
);
449-
(trait_item.span, format!("provide a default method implementation \
450-
inside this `trait`"))
451-
} else {
452-
(Span::new (
453-
BytePos(0),
454-
BytePos(0),
455-
SyntaxContext::empty()
456-
),
457-
format!("provide a default method implementation \
458-
inside the {} `trait`",
459-
tcx.item_path_str(trait_id)))
460-
}
461-
);
462-
463-
help_messages.sort_by(|&(a,_), &(b,_)| a.partial_cmp(&b).unwrap());
464-
465-
let mut cnjs = vec!["or ", "either "];
466-
help_messages.iter().for_each(|&(span, ref msg)| {
467-
let mut help_msg = String::from(cnjs.pop().unwrap_or(""));
468-
help_msg.push_str(&msg);
469-
470-
if span.data().lo == BytePos(0) && span.data().hi == BytePos(0) {
471-
err.help(&help_msg);
472-
} else {
473-
err.span_help(span, &help_msg);
474-
}
475-
});
476-
477-
err.note(&format!("a `default impl` doesn't need to include all \
478-
items from the trait"));
479-
err.emit();
480-
}
481-
}
482-
}

src/librustc/ty/mod.rs

+2-37
Original file line numberDiff line numberDiff line change
@@ -1070,13 +1070,9 @@ impl<'a, 'gcx, 'tcx> Predicate<'tcx> {
10701070
}
10711071
}
10721072

1073-
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
1074-
pub enum DefaultImplCheck { Yes, No, }
1075-
10761073
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
10771074
pub struct TraitPredicate<'tcx> {
1078-
pub trait_ref: TraitRef<'tcx>,
1079-
pub default_impl_check: DefaultImplCheck
1075+
pub trait_ref: TraitRef<'tcx>
10801076
}
10811077
pub type PolyTraitPredicate<'tcx> = ty::Binder<TraitPredicate<'tcx>>;
10821078

@@ -1184,8 +1180,7 @@ impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
11841180
assert!(!self.has_escaping_regions());
11851181

11861182
ty::Predicate::Trait(ty::Binder(ty::TraitPredicate {
1187-
trait_ref: self.clone(),
1188-
default_impl_check: DefaultImplCheck::No
1183+
trait_ref: self.clone()
11891184
}))
11901185
}
11911186
}
@@ -1303,36 +1298,6 @@ impl<'tcx> Predicate<'tcx> {
13031298
}
13041299
}
13051300
}
1306-
1307-
pub fn change_default_impl_check(&self, default_impl_check: ty::DefaultImplCheck)
1308-
-> Option<Predicate<'tcx>> {
1309-
match *self {
1310-
Predicate::Trait(ref t) => {
1311-
if t.skip_binder().default_impl_check != default_impl_check {
1312-
Some(
1313-
Predicate::Trait(ty::Binder(ty::TraitPredicate {
1314-
trait_ref: t.skip_binder().trait_ref,
1315-
default_impl_check: default_impl_check
1316-
}))
1317-
)
1318-
} else {
1319-
None
1320-
}
1321-
}
1322-
Predicate::Trait(..) |
1323-
Predicate::Projection(..) |
1324-
Predicate::Equate(..) |
1325-
Predicate::Subtype(..) |
1326-
Predicate::RegionOutlives(..) |
1327-
Predicate::WellFormed(..) |
1328-
Predicate::ObjectSafe(..) |
1329-
Predicate::ClosureKind(..) |
1330-
Predicate::TypeOutlives(..) |
1331-
Predicate::ConstEvaluatable(..) => {
1332-
None
1333-
}
1334-
}
1335-
}
13361301
}
13371302

13381303
/// Represents the bounds declared on a particular set of type

src/librustc/ty/structural_impls.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::TraitPredicate<'a> {
278278
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
279279
-> Option<ty::TraitPredicate<'tcx>> {
280280
tcx.lift(&self.trait_ref).map(|trait_ref| ty::TraitPredicate {
281-
trait_ref: trait_ref,
282-
default_impl_check: self.default_impl_check
281+
trait_ref,
283282
})
284283
}
285284
}
@@ -1128,8 +1127,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::SubtypePredicate<'tcx> {
11281127
impl<'tcx> TypeFoldable<'tcx> for ty::TraitPredicate<'tcx> {
11291128
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
11301129
ty::TraitPredicate {
1131-
trait_ref: self.trait_ref.fold_with(folder),
1132-
default_impl_check: self.default_impl_check
1130+
trait_ref: self.trait_ref.fold_with(folder)
11331131
}
11341132
}
11351133

src/librustc/ty/sty.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -582,10 +582,7 @@ impl<'tcx> PolyTraitRef<'tcx> {
582582

583583
pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> {
584584
// Note that we preserve binding levels
585-
Binder(ty::TraitPredicate {
586-
trait_ref: self.0.clone(),
587-
default_impl_check: ty::DefaultImplCheck::No
588-
})
585+
Binder(ty::TraitPredicate { trait_ref: self.0.clone() })
589586
}
590587
}
591588

src/librustc/ty/trait_def.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,16 @@ 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+
95101
let impls = self.trait_impls_of(def_id);
96102

97103
for &impl_def_id in impls.blanket_impls.iter() {
98-
f(impl_def_id);
104+
emit_impl(impl_def_id);
99105
}
100106

101107
// simplify_type(.., false) basically replaces type parameters and
@@ -126,13 +132,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
126132
if let Some(simp) = fast_reject::simplify_type(self, self_ty, true) {
127133
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
128134
for &impl_def_id in impls {
129-
f(impl_def_id);
135+
emit_impl(impl_def_id);
130136
}
131137
}
132138
} else {
133139
for v in impls.non_blanket_impls.values() {
134140
for &impl_def_id in v {
135-
f(impl_def_id);
141+
emit_impl(impl_def_id);
136142
}
137143
}
138144
}

src/librustc/util/ppaux.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -1230,12 +1230,8 @@ define_print! {
12301230
define_print! {
12311231
('tcx) ty::TraitPredicate<'tcx>, (self, f, cx) {
12321232
debug {
1233-
let default_impl_check_value = match self.default_impl_check {
1234-
ty::DefaultImplCheck::Yes => "default_impl_check: yes",
1235-
ty::DefaultImplCheck::No => "default_impl_check: no",
1236-
};
1237-
write!(f, "TraitPredicate({:?}, {})",
1238-
self.trait_ref, default_impl_check_value)
1233+
write!(f, "TraitPredicate({:?})",
1234+
self.trait_ref)
12391235
}
12401236
display {
12411237
print!(f, cx, print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref))

0 commit comments

Comments
 (0)