Skip to content

Commit 12a87b4

Browse files
committed
Work with assoc types in a super trait.
And fix a bug with type param visibility though the Self rib.
1 parent dc8a8e9 commit 12a87b4

9 files changed

+101
-63
lines changed

src/librustc_resolve/lib.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -1815,12 +1815,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
18151815
ItemTrait(_, ref generics, ref bounds, ref trait_items) => {
18161816
self.check_if_primitive_type_name(name, item.span);
18171817

1818-
self.with_self_rib(DefSelfTy(Some(local_def(item.id)), None), |this| {
1819-
// Create a new rib for the trait-wide type parameters.
1820-
this.with_type_parameter_rib(HasTypeParameters(generics,
1821-
TypeSpace,
1822-
NormalRibKind),
1823-
|this| {
1818+
// Create a new rib for the trait-wide type parameters.
1819+
self.with_type_parameter_rib(HasTypeParameters(generics,
1820+
TypeSpace,
1821+
ItemRibKind),
1822+
|this| {
1823+
this.with_self_rib(DefSelfTy(Some(local_def(item.id)), None), |this| {
18241824
this.visit_generics(generics);
18251825
visit::walk_ty_param_bounds_helper(this, bounds);
18261826

src/librustc_typeck/astconv.rs

+65-48
Original file line numberDiff line numberDiff line change
@@ -871,24 +871,11 @@ fn ast_type_binding_to_poly_projection_predicate<'tcx>(
871871
}
872872
}
873873

874-
if candidates.len() > 1 {
875-
span_err!(tcx.sess, binding.span, E0217,
876-
"ambiguous associated type: `{}` defined in multiple supertraits `{}`",
877-
token::get_name(binding.item_name),
878-
candidates.user_string(tcx));
879-
return Err(ErrorReported);
880-
}
881-
882-
let candidate = match candidates.pop() {
883-
Some(c) => c,
884-
None => {
885-
span_err!(tcx.sess, binding.span, E0218,
886-
"no associated type `{}` defined in `{}`",
887-
token::get_name(binding.item_name),
888-
trait_ref.user_string(tcx));
889-
return Err(ErrorReported);
890-
}
891-
};
874+
let candidate = try!(one_bound_for_assoc_type(tcx,
875+
candidates,
876+
&trait_ref.user_string(tcx),
877+
&token::get_name(binding.item_name),
878+
binding.span));
892879

893880
Ok(ty::Binder(ty::ProjectionPredicate { // <-------------------------+
894881
projection_ty: ty::ProjectionTy { // |
@@ -1042,19 +1029,18 @@ fn report_ambiguous_associated_type(tcx: &ty::ctxt,
10421029
}
10431030

10441031
// Search for a bound on a type parameter which includes the associated item
1045-
// given by assoc_name. We assume that ty_path_def is the def for such a type
1046-
// parameter (which might be `Self`). This function will fail if there are no
1047-
// suitable bounds or there is any ambiguity.
1032+
// given by assoc_name. ty_param_node_id is the node id for the type parameter
1033+
// (which might be `Self`, but only if it is the `Self` of a trait, not an
1034+
// impl). This function will fail if there are no suitable bounds or there is
1035+
// any ambiguity.
10481036
fn find_bound_for_assoc_item<'tcx>(this: &AstConv<'tcx>,
1049-
ty_path_def: def::Def,
1037+
ty_param_node_id: ast::NodeId,
10501038
assoc_name: ast::Name,
10511039
span: Span)
10521040
-> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
10531041
{
10541042
let tcx = this.tcx();
10551043

1056-
let ty_param_node_id = ty_path_def.local_node_id();
1057-
10581044
let bounds = match this.get_type_parameter_bounds(span, ty_param_node_id) {
10591045
Ok(v) => v,
10601046
Err(ErrorReported) => {
@@ -1069,35 +1055,52 @@ fn find_bound_for_assoc_item<'tcx>(this: &AstConv<'tcx>,
10691055

10701056
// Check that there is exactly one way to find an associated type with the
10711057
// correct name.
1072-
let mut suitable_bounds: Vec<_> =
1058+
let suitable_bounds: Vec<_> =
10731059
traits::transitive_bounds(tcx, &bounds)
10741060
.filter(|b| this.trait_defines_associated_type_named(b.def_id(), assoc_name))
10751061
.collect();
10761062

1077-
let ty_param_name = tcx.ty_param_defs.borrow().get(&ty_param_node_id).unwrap().name;
1078-
if suitable_bounds.len() == 0 {
1063+
let ty_param_name = tcx.type_parameter_def(ty_param_node_id).name;
1064+
one_bound_for_assoc_type(tcx,
1065+
suitable_bounds,
1066+
&token::get_name(ty_param_name),
1067+
&token::get_name(assoc_name),
1068+
span)
1069+
}
1070+
1071+
1072+
// Checks that bounds contains exactly one element and reports appropriate
1073+
// errors otherwise.
1074+
fn one_bound_for_assoc_type<'tcx>(tcx: &ty::ctxt<'tcx>,
1075+
bounds: Vec<ty::PolyTraitRef<'tcx>>,
1076+
ty_param_name: &str,
1077+
assoc_name: &str,
1078+
span: Span)
1079+
-> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
1080+
{
1081+
if bounds.len() == 0 {
10791082
span_err!(tcx.sess, span, E0220,
1080-
"associated type `{}` not found for type parameter `{}`",
1081-
token::get_name(assoc_name),
1082-
token::get_name(ty_param_name));
1083+
"associated type `{}` not found for `{}`",
1084+
assoc_name,
1085+
ty_param_name);
10831086
return Err(ErrorReported);
10841087
}
10851088

1086-
if suitable_bounds.len() > 1 {
1089+
if bounds.len() > 1 {
10871090
span_err!(tcx.sess, span, E0221,
1088-
"ambiguous associated type `{}` in bounds of `{}`",
1089-
token::get_name(assoc_name),
1090-
token::get_name(ty_param_name));
1091+
"ambiguous associated type `{}` in bounds of `{}`",
1092+
assoc_name,
1093+
ty_param_name);
10911094

1092-
for suitable_bound in &suitable_bounds {
1095+
for bound in &bounds {
10931096
span_note!(tcx.sess, span,
10941097
"associated type `{}` could derive from `{}`",
1095-
token::get_name(ty_param_name),
1096-
suitable_bound.user_string(tcx));
1098+
ty_param_name,
1099+
bound.user_string(tcx));
10971100
}
10981101
}
10991102

1100-
Ok(suitable_bounds.pop().unwrap().clone())
1103+
Ok(bounds[0].clone())
11011104
}
11021105

11031106
// Create a type from a a path to an associated type.
@@ -1122,12 +1125,16 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
11221125

11231126
// Find the type of the associated item, and the trait where the associated
11241127
// item is declared.
1125-
let (ty, trait_did) = match (&ty.sty, ty_path_def) {
1128+
let bound = match (&ty.sty, ty_path_def) {
11261129
(_, def::DefSelfTy(Some(trait_did), Some((impl_id, _)))) => {
11271130
// `Self` in an impl of a trait - we have a concrete self type and a
11281131
// trait reference.
11291132
match tcx.map.expect_item(impl_id).node {
11301133
ast::ItemImpl(_, _, _, Some(ref trait_ref), _, _) => {
1134+
if this.ensure_super_predicates(span, trait_did).is_err() {
1135+
return (tcx.types.err, ty_path_def);
1136+
}
1137+
11311138
let trait_segment = &trait_ref.path.segments.last().unwrap();
11321139
let trait_ref = ast_path_to_mono_trait_ref(this,
11331140
&ExplicitRscope,
@@ -1137,8 +1144,19 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
11371144
Some(ty),
11381145
trait_segment);
11391146

1140-
let ty = this.projected_ty(span, trait_ref, assoc_name);
1141-
(ty, trait_did)
1147+
let candidates: Vec<ty::PolyTraitRef> =
1148+
traits::supertraits(tcx, ty::Binder(trait_ref.clone()))
1149+
.filter(|r| this.trait_defines_associated_type_named(r.def_id(), assoc_name))
1150+
.collect();
1151+
1152+
match one_bound_for_assoc_type(tcx,
1153+
candidates,
1154+
"Self",
1155+
&token::get_name(assoc_name),
1156+
span) {
1157+
Ok(bound) => bound,
1158+
Err(ErrorReported) => return (tcx.types.err, ty_path_def),
1159+
}
11421160
}
11431161
_ => unreachable!()
11441162
}
@@ -1147,17 +1165,13 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
11471165
(&ty::ty_param(_), def::DefSelfTy(Some(_), None)) => {
11481166
// A type parameter or Self, we need to find the associated item from
11491167
// a bound.
1150-
let bound = match find_bound_for_assoc_item(this, ty_path_def, assoc_name, span) {
1168+
let ty_param_node_id = ty_path_def.local_node_id();
1169+
match find_bound_for_assoc_item(this, ty_param_node_id, assoc_name, span) {
11511170
Ok(bound) => bound,
11521171
Err(ErrorReported) => return (tcx.types.err, ty_path_def),
1153-
};
1154-
let trait_did = bound.0.def_id;
1155-
let ty = this.projected_ty_from_poly_trait_ref(span, bound, assoc_name);
1156-
1157-
(ty, trait_did)
1172+
}
11581173
}
11591174
_ => {
1160-
println!("{:?} {:?}", ty.sty, ty_path_def);
11611175
report_ambiguous_associated_type(tcx,
11621176
span,
11631177
&ty.user_string(tcx),
@@ -1167,6 +1181,9 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
11671181
}
11681182
};
11691183

1184+
let trait_did = bound.0.def_id;
1185+
let ty = this.projected_ty_from_poly_trait_ref(span, bound, assoc_name);
1186+
11701187
let item_did = if trait_did.krate == ast::LOCAL_CRATE {
11711188
// `ty::trait_items` used below requires information generated
11721189
// by type collection, which may be in progress at this point.

src/librustc_typeck/collect.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1815,7 +1815,7 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
18151815
ty::ty_param(p) => if p.idx > cur_idx {
18161816
span_err!(tcx.sess, path.span, E0128,
18171817
"type parameters with a default cannot use \
1818-
forward declared identifiers");
1818+
forward declared identifiers");
18191819
},
18201820
_ => {}
18211821
}

src/test/compile-fail/self-impl.rs

+8
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,18 @@ trait Foo {
1616
type Baz;
1717
}
1818

19+
trait SuperFoo {
20+
type SuperBaz;
21+
}
22+
1923
impl Foo for Bar {
2024
type Baz = bool;
2125
}
2226

27+
impl SuperFoo for Bar {
28+
type SuperBaz = bool;
29+
}
30+
2331
impl Bar {
2432
fn f() {
2533
let _: <Self>::Baz = true;

src/test/compile-fail/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
trait One<A> { fn foo(&self) -> A; }
1414

15-
fn foo(_: &One()) //~ ERROR no associated type `Output` defined in `One<()>`
15+
fn foo(_: &One()) //~ ERROR associated type `Output` not found for `One<()>`
1616
{}
1717

1818
fn main() { }

src/test/compile-fail/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ trait Three<A,B,C> { fn dummy(&self) -> (A,B,C); }
1414

1515
fn foo(_: &Three())
1616
//~^ ERROR wrong number of type arguments
17-
//~| ERROR no associated type `Output`
17+
//~| ERROR associated type `Output` not found
1818
{}
1919

2020
fn main() { }

src/test/compile-fail/unboxed-closure-sugar-wrong-number-number-type-parameters.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ trait Zero { fn dummy(&self); }
1414

1515
fn foo(_: Zero())
1616
//~^ ERROR wrong number of type arguments
17-
//~| ERROR no associated type `Output` defined in `Zero`
17+
//~| ERROR associated type `Output` not found for `Zero`
1818
{}
1919

2020
fn main() { }

src/test/compile-fail/unboxed-closure-sugar-wrong-trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ trait Trait {}
1414

1515
fn f<F:Trait(isize) -> isize>(x: F) {}
1616
//~^ ERROR wrong number of type arguments: expected 0, found 1
17-
//~| ERROR no associated type `Output`
17+
//~| ERROR associated type `Output` not found
1818

1919
fn main() {}

src/test/run-pass/self-impl.rs

+17-4
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,31 @@ pub struct Baz<X> {
4040
pub f: X,
4141
}
4242

43-
trait Bar<X> {
43+
trait SuperBar {
44+
type SuperQux;
45+
}
46+
47+
trait Bar<X>: SuperBar {
4448
type Qux;
4549

46-
fn bar(x: Self, y: &Self, z: Box<Self>) -> Self;
50+
fn bar(x: Self, y: &Self, z: Box<Self>, _: Self::SuperQux) -> Self;
4751
fn dummy(&self, x: X) { }
4852
}
4953

54+
impl SuperBar for Box<Baz<isize>> {
55+
type SuperQux = bool;
56+
}
57+
5058
impl Bar<isize> for Box<Baz<isize>> {
5159
type Qux = i32;
5260

53-
fn bar(_x: Self, _y: &Self, _z: Box<Self>) -> Self {
61+
fn bar(_x: Self, _y: &Self, _z: Box<Self>, _: Self::SuperQux) -> Self {
5462
let _: Self::Qux = 42;
5563
let _: <Self as Bar<isize>>::Qux = 42;
64+
65+
let _: Self::SuperQux = true;
66+
let _: <Self as SuperBar>::SuperQux = true;
67+
5668
box Baz { f: 42 }
5769
}
5870
}
@@ -61,5 +73,6 @@ fn main() {
6173
let _: Foo = Foo::foo(Foo, &Foo, box Foo);
6274
let _: Box<Baz<isize>> = Bar::bar(box Baz { f: 42 },
6375
&box Baz { f: 42 },
64-
box box Baz { f: 42 });
76+
box box Baz { f: 42 },
77+
true);
6578
}

0 commit comments

Comments
 (0)