Skip to content

Commit 4e21196

Browse files
committed
---
yaml --- r: 273143 b: refs/heads/beta c: 5dedbda h: refs/heads/master i: 273141: 01374c3 273139: c602c27 273135: d67c8f6
1 parent 2059f1a commit 4e21196

File tree

8 files changed

+139
-14
lines changed

8 files changed

+139
-14
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ refs/tags/0.9: 36870b185fc5f5486636d4515f0e22677493f225
2323
refs/tags/0.10: ac33f2b15782272ae348dbd7b14b8257b2148b5a
2424
refs/tags/0.11.0: e1247cb1d0d681be034adb4b558b5a0c0d5720f9
2525
refs/tags/0.12.0: f0c419429ef30723ceaf6b42f9b5a2aeb5d2e2d1
26-
refs/heads/beta: 1077ff2deca4c80f27596905119a84564fe9813f
26+
refs/heads/beta: 5dedbdaea4254a78c58c322f636ecd9175cb53fa
2727
refs/tags/1.0.0-alpha: e42bd6d93a1d3433c486200587f8f9e12590a4d7
2828
refs/heads/tmp: e06d2ad9fcd5027bcaac5b08fc9aa39a49d0ecd3
2929
refs/tags/1.0.0-alpha.2: 4c705f6bc559886632d3871b04f58aab093bfa2f

branches/beta/src/librustc/middle/traits/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ pub use self::select::SelectionContext;
5050
pub use self::select::SelectionCache;
5151
pub use self::select::{MethodMatchResult, MethodMatched, MethodAmbiguous, MethodDidNotMatch};
5252
pub use self::select::{MethodMatchedData}; // intentionally don't export variants
53-
pub use self::specialize::{Overlap, SpecializationGraph, get_impl_item_or_default, ItemSource, specializes};
53+
pub use self::specialize::{Overlap, SpecializationGraph, specializes};
54+
pub use self::specialize::{ItemSource, get_impl_item_or_default, get_parent_impl_item};
5455
pub use self::util::elaborate_predicates;
5556
pub use self::util::get_vtable_index_of_object_method;
5657
pub use self::util::trait_ref_for_builtin_bound;

branches/beta/src/librustc/middle/traits/specialize.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,26 @@ pub fn get_impl_item_or_default<'tcx, I, F>(tcx: &ty::ctxt<'tcx>,
299299
None
300300
}
301301

302+
/// Convenience function for locating an item defined in a specialization parent, if any.
303+
pub fn get_parent_impl_item<'tcx, I, F>(tcx: &ty::ctxt<'tcx>,
304+
child_impl: DefId,
305+
f: F)
306+
-> Option<(I, DefId)>
307+
where F: for<'a> FnMut(&ImplOrTraitItem<'tcx>) -> Option<I>
308+
{
309+
let trait_def_id = tcx.trait_id_of_impl(child_impl).unwrap();
310+
let trait_def = tcx.lookup_trait_def(trait_def_id);
311+
312+
trait_def.parent_of_impl(child_impl)
313+
.and_then(|parent_impl| get_impl_item_or_default(tcx, parent_impl, f))
314+
.and_then(|(item, source)| {
315+
match source {
316+
ItemSource::Trait { .. } => None,
317+
ItemSource::Impl { actual_impl, .. } => Some((item, actual_impl)),
318+
}
319+
})
320+
}
321+
302322
fn skolemizing_subst_for_impl<'a>(tcx: &ty::ctxt<'a>, impl_def_id: DefId) -> Substs<'a> {
303323
let impl_generics = tcx.lookup_item_type(impl_def_id).generics;
304324

branches/beta/src/librustc/middle/ty/mod.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2670,14 +2670,23 @@ impl<'tcx> TyCtxt<'tcx> {
26702670
Some(self.tables.borrow().upvar_capture_map.get(&upvar_id).unwrap().clone())
26712671
}
26722672

2673-
26742673
pub fn visit_all_items_in_krate<V,F>(&self,
26752674
dep_node_fn: F,
26762675
visitor: &mut V)
26772676
where F: FnMut(DefId) -> DepNode, V: Visitor<'tcx>
26782677
{
26792678
dep_graph::visit_all_items_in_krate(self, dep_node_fn, visitor);
26802679
}
2680+
/// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err`
2681+
/// with the name of the crate containing the impl.
2682+
pub fn span_of_impl(&self, impl_did: DefId) -> Result<Span, String> {
2683+
if impl_did.is_local() {
2684+
let node_id = self.map.as_local_node_id(impl_did).unwrap();
2685+
Ok(self.map.span(node_id))
2686+
} else {
2687+
Err(self.sess.cstore.crate_name(impl_did.krate))
2688+
}
2689+
}
26812690
}
26822691

26832692
/// The category of explicit self.

branches/beta/src/librustc_typeck/check/mod.rs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ use syntax::util::lev_distance::find_best_match_for_name;
127127

128128
use rustc_front::intravisit::{self, Visitor};
129129
use rustc_front::hir;
130-
use rustc_front::hir::{Visibility, PatKind};
130+
use rustc_front::hir::{Visibility, PatKind, Defaultness};
131131
use rustc_front::print::pprust;
132132
use rustc_back::slice;
133133

@@ -864,6 +864,33 @@ fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
864864
check_bare_fn(ccx, &sig.decl, body, id, span, fty, param_env);
865865
}
866866

867+
fn check_specialization_validity<'tcx, F>(tcx: &ty::ctxt<'tcx>,
868+
impl_id: DefId,
869+
impl_item: &hir::ImplItem,
870+
f: F)
871+
where F: FnMut(&ty::ImplOrTraitItem<'tcx>) -> Option<hir::Defaultness>
872+
{
873+
let parent_item_opt = traits::get_parent_impl_item(tcx, impl_id, f);
874+
if let Some((Defaultness::Final, parent_impl)) = parent_item_opt {
875+
span_err!(tcx.sess, impl_item.span, E0520,
876+
"item `{}` is provided by an implementation that \
877+
specializes another, but the item in the parent \
878+
implementations is not marked `default` and so it \
879+
cannot be specialized.",
880+
impl_item.name);
881+
882+
match tcx.span_of_impl(parent_impl) {
883+
Ok(span) => {
884+
span_note!(tcx.sess, span, "parent implementation is here:");
885+
}
886+
Err(cname) => {
887+
tcx.sess.note(&format!("parent implementation is in crate `{}`",
888+
cname));
889+
}
890+
}
891+
}
892+
}
893+
867894
fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
868895
impl_span: Span,
869896
impl_id: DefId,
@@ -903,6 +930,15 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
903930
impl_const.name,
904931
impl_trait_ref)
905932
}
933+
934+
check_specialization_validity(ccx.tcx, impl_id, impl_item, |cand| {
935+
if let &ty::ConstTraitItem(ref trait_const) = cand {
936+
if trait_const.name == impl_item.name {
937+
return Some(trait_const.defaultness);
938+
}
939+
}
940+
None
941+
});
906942
}
907943
hir::ImplItemKind::Method(ref sig, ref body) => {
908944
check_trait_fn_not_const(ccx, impl_item.span, sig.constness);
@@ -926,6 +962,15 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
926962
impl_method.name,
927963
impl_trait_ref)
928964
}
965+
966+
check_specialization_validity(ccx.tcx, impl_id, impl_item, |cand| {
967+
if let &ty::MethodTraitItem(ref meth) = cand {
968+
if meth.name == impl_method.name {
969+
return Some(meth.defaultness);
970+
}
971+
}
972+
None
973+
});
929974
}
930975
hir::ImplItemKind::Type(_) => {
931976
let impl_type = match ty_impl_item {
@@ -944,6 +989,15 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
944989
impl_type.name,
945990
impl_trait_ref)
946991
}
992+
993+
check_specialization_validity(ccx.tcx, impl_id, impl_item, |cand| {
994+
if let &ty::TypeTraitItem(ref at) = cand {
995+
if at.name == impl_item.name {
996+
return Some(at.defaultness);
997+
}
998+
}
999+
None
1000+
});
9471001
}
9481002
}
9491003
}

branches/beta/src/librustc_typeck/coherence/overlap.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,10 @@
1313
//! constructor provide a method with the same name.
1414
1515
use middle::cstore::CrateStore;
16-
use middle::def_id::DefId;
1716
use middle::traits;
1817
use middle::ty::{self, TyCtxt};
1918
use middle::infer;
2019
use syntax::ast;
21-
use syntax::codemap::Span;
2220
use rustc::dep_graph::DepNode;
2321
use rustc_front::hir;
2422
use rustc_front::intravisit;
@@ -169,13 +167,14 @@ impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> {
169167
overlap.on_trait_ref,
170168
self_type);
171169

172-
if overlap.with_impl.is_local() {
173-
span_note!(self.tcx.sess, self.span_of_def_id(overlap.with_impl),
174-
"conflicting implementation is here:");
175-
} else {
176-
let cname = self.tcx.sess.cstore.crate_name(overlap.with_impl.krate);
177-
self.tcx.sess.note(&format!("conflicting implementation in crate `{}`",
178-
cname));
170+
match self.tcx.span_of_impl(overlap.with_impl) {
171+
Ok(span) => {
172+
span_note!(self.tcx.sess, span, "conflicting implementation is here:");
173+
}
174+
Err(cname) => {
175+
self.tcx.sess.note(&format!("conflicting implementation in crate `{}`",
176+
cname));
177+
}
179178
}
180179
}
181180

branches/beta/src/librustc_typeck/diagnostics.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3696,5 +3696,6 @@ register_diagnostics! {
36963696
// type `{}` was overridden
36973697
E0436, // functional record update requires a struct
36983698
E0513, // no type for local variable ..
3699-
E0519 // redundant default implementations of trait
3699+
E0519, // redundant default implementations of trait
3700+
E0520 // cannot specialize non-default item
37003701
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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+
trait Foo {
12+
fn foo(&self);
13+
fn bar(&self);
14+
}
15+
16+
impl<T> Foo for T {
17+
fn foo(&self) {}
18+
fn bar(&self) {}
19+
}
20+
21+
impl Foo for u8 {}
22+
impl Foo for u16 {
23+
fn foo(&self) {} //~ ERROR E0520
24+
}
25+
impl Foo for u32 {
26+
fn bar(&self) {} //~ ERROR E0520
27+
}
28+
29+
trait Bar {
30+
type T;
31+
}
32+
33+
impl<T> Bar for T {
34+
type T = u8;
35+
}
36+
37+
impl Bar for u8 {
38+
type T = (); //~ ERROR E0520
39+
}
40+
41+
fn main() {}

0 commit comments

Comments
 (0)