Skip to content

Commit 6b27005

Browse files
author
Ariel Ben-Yehuda
committed
require reimplementations of all items when a defaulted associated type is overriden
This is a [breaking-change] but it follows the RFC (not sure whether it will be accepted).
1 parent ace8670 commit 6b27005

File tree

3 files changed

+68
-12
lines changed

3 files changed

+68
-12
lines changed

src/librustc_typeck/check/mod.rs

+40-11
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
846846
// Locate trait methods
847847
let tcx = ccx.tcx;
848848
let trait_items = tcx.trait_items(impl_trait_ref.def_id);
849+
let mut overridden_associated_type = None;
849850

850851
// Check existing impl methods to see if they are both present in trait
851852
// and compatible with trait signature
@@ -911,8 +912,10 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
911912
_ => tcx.sess.span_bug(impl_item.span, "non-type impl-item for type")
912913
};
913914

914-
if let &ty::TypeTraitItem(..) = ty_trait_item {
915-
// ...
915+
if let &ty::TypeTraitItem(ref at) = ty_trait_item {
916+
if let Some(_) = at.ty {
917+
overridden_associated_type = Some(impl_item);
918+
}
916919
} else {
917920
span_err!(tcx.sess, impl_item.span, E0325,
918921
"item `{}` is an associated type, \
@@ -930,6 +933,8 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
930933
let provided_methods = tcx.provided_trait_methods(impl_trait_ref.def_id);
931934
let associated_consts = tcx.associated_consts(impl_trait_ref.def_id);
932935
let mut missing_items = Vec::new();
936+
let mut invalidated_items = Vec::new();
937+
let associated_type_overridden = overridden_associated_type.is_some();
933938
for trait_item in trait_items.iter() {
934939
match *trait_item {
935940
ty::ConstTraitItem(ref associated_const) => {
@@ -944,9 +949,12 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
944949
let is_provided =
945950
associated_consts.iter().any(|ac| ac.default.is_some() &&
946951
ac.name == associated_const.name);
947-
if !is_implemented && !is_provided {
948-
missing_items.push(format!("`{}`",
949-
token::get_name(associated_const.name)));
952+
if !is_implemented {
953+
if !is_provided {
954+
missing_items.push(associated_const.name);
955+
} else if associated_type_overridden {
956+
invalidated_items.push(associated_const.name);
957+
}
950958
}
951959
}
952960
ty::MethodTraitItem(ref trait_method) => {
@@ -961,8 +969,12 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
961969
});
962970
let is_provided =
963971
provided_methods.iter().any(|m| m.name == trait_method.name);
964-
if !is_implemented && !is_provided {
965-
missing_items.push(format!("`{}`", token::get_name(trait_method.name)));
972+
if !is_implemented {
973+
if !is_provided {
974+
missing_items.push(trait_method.name);
975+
} else if associated_type_overridden {
976+
invalidated_items.push(trait_method.name);
977+
}
966978
}
967979
}
968980
ty::TypeTraitItem(ref associated_type) => {
@@ -975,17 +987,34 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
975987
}
976988
});
977989
let is_provided = associated_type.ty.is_some();
978-
if !is_implemented && !is_provided {
979-
missing_items.push(format!("`{}`", token::get_name(associated_type.name)));
990+
if !is_implemented {
991+
if !is_provided {
992+
missing_items.push(associated_type.name);
993+
} else if associated_type_overridden {
994+
invalidated_items.push(associated_type.name);
995+
}
980996
}
981997
}
982998
}
983999
}
9841000

9851001
if !missing_items.is_empty() {
9861002
span_err!(tcx.sess, impl_span, E0046,
987-
"not all trait items implemented, missing: {}",
988-
missing_items.connect(", "));
1003+
"not all trait items implemented, missing: `{}`",
1004+
missing_items.iter()
1005+
.map(<ast::Name>::as_str)
1006+
.collect::<Vec<_>>().connect("`, `"))
1007+
}
1008+
1009+
if !invalidated_items.is_empty() {
1010+
let invalidator = overridden_associated_type.unwrap();
1011+
span_err!(tcx.sess, invalidator.span, E0399,
1012+
"the following trait items need to be reimplemented \
1013+
as `{}` was overridden: `{}`",
1014+
invalidator.ident.as_str(),
1015+
invalidated_items.iter()
1016+
.map(<ast::Name>::as_str)
1017+
.collect::<Vec<_>>().connect("`, `"))
9891018
}
9901019
}
9911020

src/librustc_typeck/diagnostics.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -2066,6 +2066,8 @@ register_diagnostics! {
20662066
// `#[lang = \"{}\"]` is allowed for the `{}` primitive
20672067
E0391, // unsupported cyclic reference between types/traits detected
20682068
E0392, // parameter `{}` is never used
2069-
E0393 // the type parameter `{}` must be explicitly specified in an object
2069+
E0393, // the type parameter `{}` must be explicitly specified in an object
20702070
// type because its default value `{}` references the type `Self`"
2071+
E0399 // trait items need to be implemented because the associated
2072+
// type `{}` was overridden
20712073
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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(associated_consts)]
12+
13+
pub trait Tr {
14+
type Assoc = u8;
15+
type Assoc2 = Self::Assoc;
16+
const C: u8 = 11;
17+
fn foo(&self) {}
18+
}
19+
20+
impl Tr for () {
21+
type Assoc = ();
22+
//~^ ERROR need to be reimplemented as `Assoc` was overridden: `Assoc2`, `C`, `foo`
23+
}
24+
25+
fn main() {}

0 commit comments

Comments
 (0)