Skip to content

Commit f3819f0

Browse files
committed
Auto merge of #25796 - arielb1:default-assoc, r=eddyb
r? @eddyb Fixes #19476.
2 parents 47f9e52 + 699fc80 commit f3819f0

File tree

13 files changed

+222
-120
lines changed

13 files changed

+222
-120
lines changed

src/librustc/metadata/decoder.rs

+22-13
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,13 @@ fn doc_type<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd) -> Ty<'tcx>
252252
|_, did| translate_def_id(cdata, did))
253253
}
254254

255+
fn maybe_doc_type<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd) -> Option<Ty<'tcx>> {
256+
reader::maybe_get_doc(doc, tag_items_data_item_type).map(|tp| {
257+
parse_ty_data(tp.data, cdata.cnum, tp.start, tcx,
258+
|_, did| translate_def_id(cdata, did))
259+
})
260+
}
261+
255262
fn doc_method_fty<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>,
256263
cdata: Cmd) -> ty::BareFnTy<'tcx> {
257264
let tp = reader::get_doc(doc, tag_item_method_fty);
@@ -875,24 +882,24 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
875882
id: ast::NodeId,
876883
tcx: &ty::ctxt<'tcx>)
877884
-> ty::ImplOrTraitItem<'tcx> {
878-
let method_doc = lookup_item(id, cdata.data());
885+
let item_doc = lookup_item(id, cdata.data());
879886

880-
let def_id = item_def_id(method_doc, cdata);
887+
let def_id = item_def_id(item_doc, cdata);
881888

882-
let container_id = item_require_parent_item(cdata, method_doc);
889+
let container_id = item_require_parent_item(cdata, item_doc);
883890
let container_doc = lookup_item(container_id.node, cdata.data());
884891
let container = match item_family(container_doc) {
885892
Trait => TraitContainer(container_id),
886893
_ => ImplContainer(container_id),
887894
};
888895

889-
let name = item_name(&*intr, method_doc);
890-
let vis = item_visibility(method_doc);
896+
let name = item_name(&*intr, item_doc);
897+
let vis = item_visibility(item_doc);
891898

892-
match item_sort(method_doc) {
899+
match item_sort(item_doc) {
893900
Some('C') => {
894-
let ty = doc_type(method_doc, tcx, cdata);
895-
let default = get_provided_source(method_doc, cdata);
901+
let ty = doc_type(item_doc, tcx, cdata);
902+
let default = get_provided_source(item_doc, cdata);
896903
ty::ConstTraitItem(Rc::new(ty::AssociatedConst {
897904
name: name,
898905
ty: ty,
@@ -903,11 +910,11 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
903910
}))
904911
}
905912
Some('r') | Some('p') => {
906-
let generics = doc_generics(method_doc, tcx, cdata, tag_method_ty_generics);
907-
let predicates = doc_predicates(method_doc, tcx, cdata, tag_method_ty_generics);
908-
let fty = doc_method_fty(method_doc, tcx, cdata);
909-
let explicit_self = get_explicit_self(method_doc);
910-
let provided_source = get_provided_source(method_doc, cdata);
913+
let generics = doc_generics(item_doc, tcx, cdata, tag_method_ty_generics);
914+
let predicates = doc_predicates(item_doc, tcx, cdata, tag_method_ty_generics);
915+
let fty = doc_method_fty(item_doc, tcx, cdata);
916+
let explicit_self = get_explicit_self(item_doc);
917+
let provided_source = get_provided_source(item_doc, cdata);
911918

912919
ty::MethodTraitItem(Rc::new(ty::Method::new(name,
913920
generics,
@@ -920,8 +927,10 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
920927
provided_source)))
921928
}
922929
Some('t') => {
930+
let ty = maybe_doc_type(item_doc, tcx, cdata);
923931
ty::TypeTraitItem(Rc::new(ty::AssociatedType {
924932
name: name,
933+
ty: ty,
925934
vis: vis,
926935
def_id: def_id,
927936
container: container,

src/librustc/metadata/encoder.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -894,12 +894,12 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
894894
rbml_w.end_tag();
895895
}
896896

897-
fn encode_info_for_associated_type(ecx: &EncodeContext,
898-
rbml_w: &mut Encoder,
899-
associated_type: &ty::AssociatedType,
900-
impl_path: PathElems,
901-
parent_id: NodeId,
902-
impl_item_opt: Option<&ast::ImplItem>) {
897+
fn encode_info_for_associated_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
898+
rbml_w: &mut Encoder,
899+
associated_type: &ty::AssociatedType<'tcx>,
900+
impl_path: PathElems,
901+
parent_id: NodeId,
902+
impl_item_opt: Option<&ast::ImplItem>) {
903903
debug!("encode_info_for_associated_type({:?},{:?})",
904904
associated_type.def_id,
905905
token::get_name(associated_type.name));
@@ -913,8 +913,6 @@ fn encode_info_for_associated_type(ecx: &EncodeContext,
913913
encode_parent_item(rbml_w, local_def(parent_id));
914914
encode_item_sort(rbml_w, 't');
915915

916-
encode_bounds_and_type_for_item(rbml_w, ecx, associated_type.def_id.local_id());
917-
918916
let stab = stability::lookup(ecx.tcx, associated_type.def_id);
919917
encode_stability(rbml_w, stab);
920918

@@ -923,7 +921,14 @@ fn encode_info_for_associated_type(ecx: &EncodeContext,
923921

924922
if let Some(ii) = impl_item_opt {
925923
encode_attributes(rbml_w, &ii.attrs);
926-
encode_type(ecx, rbml_w, ty::node_id_to_type(ecx.tcx, ii.id));
924+
} else {
925+
encode_predicates(rbml_w, ecx,
926+
&ty::lookup_predicates(ecx.tcx, associated_type.def_id),
927+
tag_item_generics);
928+
}
929+
930+
if let Some(ty) = associated_type.ty {
931+
encode_type(ecx, rbml_w, ty);
927932
}
928933

929934
rbml_w.end_tag();

src/librustc/middle/traits/project.rs

+28-24
Original file line numberDiff line numberDiff line change
@@ -857,37 +857,41 @@ fn confirm_impl_candidate<'cx,'tcx>(
857857
-> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
858858
{
859859
// there don't seem to be nicer accessors to these:
860-
let impl_items_map = selcx.tcx().impl_items.borrow();
861860
let impl_or_trait_items_map = selcx.tcx().impl_or_trait_items.borrow();
862861

863-
let impl_items = impl_items_map.get(&impl_vtable.impl_def_id).unwrap();
864-
let mut impl_ty = None;
865-
for impl_item in impl_items {
866-
let assoc_type = match *impl_or_trait_items_map.get(&impl_item.def_id()).unwrap() {
867-
ty::TypeTraitItem(ref assoc_type) => assoc_type.clone(),
868-
ty::ConstTraitItem(..) | ty::MethodTraitItem(..) => { continue; }
869-
};
870-
871-
if assoc_type.name != obligation.predicate.item_name {
872-
continue;
862+
// Look for the associated type in the impl
863+
for impl_item in &selcx.tcx().impl_items.borrow()[&impl_vtable.impl_def_id] {
864+
if let ty::TypeTraitItem(ref assoc_ty) = impl_or_trait_items_map[&impl_item.def_id()] {
865+
if assoc_ty.name == obligation.predicate.item_name {
866+
return (assoc_ty.ty.unwrap().subst(selcx.tcx(), &impl_vtable.substs),
867+
impl_vtable.nested.into_vec());
868+
}
873869
}
874-
875-
let impl_poly_ty = ty::lookup_item_type(selcx.tcx(), assoc_type.def_id);
876-
impl_ty = Some(impl_poly_ty.ty.subst(selcx.tcx(), &impl_vtable.substs));
877-
break;
878870
}
879871

880-
match impl_ty {
881-
Some(ty) => (ty, impl_vtable.nested.into_vec()),
882-
None => {
883-
// This means that the impl is missing a
884-
// definition for the associated type. This error
885-
// ought to be reported by the type checker method
886-
// `check_impl_items_against_trait`, so here we
887-
// just return ty_err.
888-
(selcx.tcx().types.err, vec!())
872+
// It is not in the impl - get the default from the trait.
873+
let trait_ref = obligation.predicate.trait_ref;
874+
for trait_item in ty::trait_items(selcx.tcx(), trait_ref.def_id).iter() {
875+
if let &ty::TypeTraitItem(ref assoc_ty) = trait_item {
876+
if assoc_ty.name == obligation.predicate.item_name {
877+
if let Some(ty) = assoc_ty.ty {
878+
return (ty.subst(selcx.tcx(), trait_ref.substs),
879+
impl_vtable.nested.into_vec());
880+
} else {
881+
// This means that the impl is missing a
882+
// definition for the associated type. This error
883+
// ought to be reported by the type checker method
884+
// `check_impl_items_against_trait`, so here we
885+
// just return ty_err.
886+
return (selcx.tcx().types.err, vec!());
887+
}
888+
}
889889
}
890890
}
891+
892+
selcx.tcx().sess.span_bug(obligation.cause.span,
893+
&format!("No associated type for {}",
894+
trait_ref.repr(selcx.tcx())));
891895
}
892896

893897
impl<'tcx> Repr<'tcx> for ProjectionTyError<'tcx> {

src/librustc/middle/ty.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ impl ImplOrTraitItemContainer {
136136
pub enum ImplOrTraitItem<'tcx> {
137137
ConstTraitItem(Rc<AssociatedConst<'tcx>>),
138138
MethodTraitItem(Rc<Method<'tcx>>),
139-
TypeTraitItem(Rc<AssociatedType>),
139+
TypeTraitItem(Rc<AssociatedType<'tcx>>),
140140
}
141141

142142
impl<'tcx> ImplOrTraitItem<'tcx> {
@@ -267,8 +267,9 @@ pub struct AssociatedConst<'tcx> {
267267
}
268268

269269
#[derive(Clone, Copy, Debug)]
270-
pub struct AssociatedType {
270+
pub struct AssociatedType<'tcx> {
271271
pub name: ast::Name,
272+
pub ty: Option<Ty<'tcx>>,
272273
pub vis: ast::Visibility,
273274
pub def_id: ast::DefId,
274275
pub container: ImplOrTraitItemContainer,

src/librustc/util/ppaux.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1077,7 +1077,7 @@ impl<'tcx> Repr<'tcx> for ty::AssociatedConst<'tcx> {
10771077
}
10781078
}
10791079

1080-
impl<'tcx> Repr<'tcx> for ty::AssociatedType {
1080+
impl<'tcx> Repr<'tcx> for ty::AssociatedType<'tcx> {
10811081
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
10821082
format!("AssociatedType(name: {}, vis: {}, def_id: {})",
10831083
self.name.repr(tcx),

src/librustc_typeck/check/mod.rs

+9-8
Original file line numberDiff line numberDiff line change
@@ -1070,7 +1070,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
10701070
// Check for missing items from trait
10711071
let provided_methods = ty::provided_trait_methods(tcx, impl_trait_ref.def_id);
10721072
let associated_consts = ty::associated_consts(tcx, impl_trait_ref.def_id);
1073-
let mut missing_methods = Vec::new();
1073+
let mut missing_items = Vec::new();
10741074
for trait_item in &*trait_items {
10751075
match *trait_item {
10761076
ty::ConstTraitItem(ref associated_const) => {
@@ -1086,8 +1086,8 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
10861086
associated_consts.iter().any(|ac| ac.default.is_some() &&
10871087
ac.name == associated_const.name);
10881088
if !is_implemented && !is_provided {
1089-
missing_methods.push(format!("`{}`",
1090-
token::get_name(associated_const.name)));
1089+
missing_items.push(format!("`{}`",
1090+
token::get_name(associated_const.name)));
10911091
}
10921092
}
10931093
ty::MethodTraitItem(ref trait_method) => {
@@ -1103,7 +1103,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
11031103
let is_provided =
11041104
provided_methods.iter().any(|m| m.name == trait_method.name);
11051105
if !is_implemented && !is_provided {
1106-
missing_methods.push(format!("`{}`", token::get_name(trait_method.name)));
1106+
missing_items.push(format!("`{}`", token::get_name(trait_method.name)));
11071107
}
11081108
}
11091109
ty::TypeTraitItem(ref associated_type) => {
@@ -1115,17 +1115,18 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
11151115
_ => false,
11161116
}
11171117
});
1118-
if !is_implemented {
1119-
missing_methods.push(format!("`{}`", token::get_name(associated_type.name)));
1118+
let is_provided = associated_type.ty.is_some();
1119+
if !is_implemented && !is_provided {
1120+
missing_items.push(format!("`{}`", token::get_name(associated_type.name)));
11201121
}
11211122
}
11221123
}
11231124
}
11241125

1125-
if !missing_methods.is_empty() {
1126+
if !missing_items.is_empty() {
11261127
span_err!(tcx.sess, impl_span, E0046,
11271128
"not all trait items implemented, missing: {}",
1128-
missing_methods.connect(", "));
1129+
missing_items.connect(", "));
11291130
}
11301131
}
11311132

src/librustc_typeck/collect.rs

+23-23
Original file line numberDiff line numberDiff line change
@@ -717,15 +717,17 @@ fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
717717
.insert(local_def(id), ty::ConstTraitItem(associated_const));
718718
}
719719

720-
fn as_refsociated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
721-
container: ImplOrTraitItemContainer,
722-
ident: ast::Ident,
723-
id: ast::NodeId,
724-
vis: ast::Visibility)
720+
fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
721+
container: ImplOrTraitItemContainer,
722+
ident: ast::Ident,
723+
id: ast::NodeId,
724+
vis: ast::Visibility,
725+
ty: Option<Ty<'tcx>>)
725726
{
726727
let associated_type = Rc::new(ty::AssociatedType {
727728
name: ident.name,
728729
vis: vis,
730+
ty: ty,
729731
def_id: local_def(id),
730732
container: container
731733
});
@@ -878,18 +880,11 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
878880
"associated types are not allowed in inherent impls");
879881
}
880882

881-
as_refsociated_type(ccx, ImplContainer(local_def(it.id)),
882-
impl_item.ident, impl_item.id, impl_item.vis);
883-
884883
let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, ty);
885-
tcx.tcache.borrow_mut().insert(local_def(impl_item.id),
886-
TypeScheme {
887-
generics: ty::Generics::empty(),
888-
ty: typ,
889-
});
890-
tcx.predicates.borrow_mut().insert(local_def(impl_item.id),
891-
ty::GenericPredicates::empty());
892-
write_ty_to_tcx(tcx, impl_item.id, typ);
884+
885+
convert_associated_type(ccx, ImplContainer(local_def(it.id)),
886+
impl_item.ident, impl_item.id, impl_item.vis,
887+
Some(typ));
893888
}
894889
}
895890

@@ -972,9 +967,14 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
972967
// Convert all the associated types.
973968
for trait_item in trait_items {
974969
match trait_item.node {
975-
ast::TypeTraitItem(..) => {
976-
as_refsociated_type(ccx, TraitContainer(local_def(it.id)),
977-
trait_item.ident, trait_item.id, ast::Public);
970+
ast::TypeTraitItem(_, ref opt_ty) => {
971+
let typ = opt_ty.as_ref().map({
972+
|ty| ccx.icx(&trait_predicates).to_ty(&ExplicitRscope, &ty)
973+
});
974+
975+
convert_associated_type(ccx, TraitContainer(local_def(it.id)),
976+
trait_item.ident, trait_item.id, ast::Public,
977+
typ);
978978
}
979979
_ => {}
980980
}
@@ -2291,10 +2291,10 @@ fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
22912291

22922292
let lifetimes_in_associated_types: HashSet<_> =
22932293
impl_items.iter()
2294-
.filter_map(|item| match item.node {
2295-
ast::TypeImplItem(..) => Some(ty::node_id_to_type(tcx, item.id)),
2296-
ast::ConstImplItem(..) | ast::MethodImplItem(..) |
2297-
ast::MacImplItem(..) => None,
2294+
.map(|item| ty::impl_or_trait_item(tcx, local_def(item.id)))
2295+
.filter_map(|item| match item {
2296+
ty::TypeTraitItem(ref assoc_ty) => assoc_ty.ty,
2297+
ty::ConstTraitItem(..) | ty::MethodTraitItem(..) => None
22982298
})
22992299
.flat_map(|ty| ctp::parameters_for_type(ty).into_iter())
23002300
.filter_map(|p| match p {

src/librustdoc/clean/inline.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -362,11 +362,13 @@ pub fn build_impl(cx: &DocContext,
362362
}
363363
ty::TypeTraitItem(ref assoc_ty) => {
364364
let did = assoc_ty.def_id;
365-
let type_scheme = ty::lookup_item_type(tcx, did);
366-
let predicates = ty::lookup_predicates(tcx, did);
365+
let type_scheme = ty::TypeScheme {
366+
ty: assoc_ty.ty.unwrap(),
367+
generics: ty::Generics::empty()
368+
};
367369
// Not sure the choice of ParamSpace actually matters here,
368370
// because an associated type won't have generics on the LHS
369-
let typedef = (type_scheme, predicates,
371+
let typedef = (type_scheme, ty::GenericPredicates::empty(),
370372
subst::ParamSpace::TypeSpace).clean(cx);
371373
Some(clean::Item {
372374
name: Some(assoc_ty.name.clean(cx)),

0 commit comments

Comments
 (0)