Skip to content

Commit 7d9ee03

Browse files
author
Alexander Regueiro
committed
Only do check for trait objects, not trait or trait alias definitions.
1 parent 6d3ee41 commit 7d9ee03

13 files changed

+112
-163
lines changed

src/librustc/ty/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,6 +1195,7 @@ impl<'a, 'gcx, 'tcx> Predicate<'tcx> {
11951195
pub struct TraitPredicate<'tcx> {
11961196
pub trait_ref: TraitRef<'tcx>
11971197
}
1198+
11981199
pub type PolyTraitPredicate<'tcx> = ty::Binder<TraitPredicate<'tcx>>;
11991200

12001201
impl<'tcx> TraitPredicate<'tcx> {
@@ -1516,14 +1517,14 @@ impl UniverseIndex {
15161517
UniverseIndex::from_u32(self.private.checked_add(1).unwrap())
15171518
}
15181519

1519-
/// `true` if `self` can name a name from `other` -- in other words,
1520+
/// Returns `true` if `self` can name a name from `other` -- in other words,
15201521
/// if the set of names in `self` is a superset of those in
15211522
/// `other` (`self >= other`).
15221523
pub fn can_name(self, other: UniverseIndex) -> bool {
15231524
self.private >= other.private
15241525
}
15251526

1526-
/// `true` if `self` cannot name some names from `other` -- in other
1527+
/// Returns `true` if `self` cannot name some names from `other` -- in other
15271528
/// words, if the set of names in `self` is a strict subset of
15281529
/// those in `other` (`self < other`).
15291530
pub fn cannot_name(self, other: UniverseIndex) -> bool {

src/librustc_typeck/astconv.rs

Lines changed: 44 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -719,8 +719,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
719719
speculative: bool)
720720
-> ty::PolyTraitRef<'tcx>
721721
{
722-
let tcx = self.tcx();
723-
724722
let trait_def_id = self.trait_def_id(trait_ref);
725723

726724
debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
@@ -734,74 +732,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
734732
trait_ref.path.segments.last().unwrap());
735733
let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs));
736734

735+
let mut dup_bindings = FxHashMap::default();
737736
poly_projections.extend(assoc_bindings.iter().filter_map(|binding| {
738737
// specify type to assert that error was already reported in Err case:
739738
let predicate: Result<_, ErrorReported> =
740739
self.ast_type_binding_to_poly_projection_predicate(
741-
trait_ref.ref_id, poly_trait_ref, binding, speculative);
740+
trait_ref.ref_id, poly_trait_ref, binding, speculative, &mut dup_bindings);
742741
// okay to ignore Err because of ErrorReported (see above)
743742
Some((predicate.ok()?, binding.span))
744743
}));
745744

746-
// make flat_map:
747-
// for tr in traits::supertraits(tcx, poly_trait_ref) {
748-
// let sup_trait_ref = tr.skip_binder();
749-
// poly_projections.extend(sup_trait_ref.substs.types().filter_map(|t| {
750-
// if let TyKind::Projection(proj) = t.sty {
751-
// Some((proj, span))
752-
// } else {
753-
// None
754-
// }
755-
// });
756-
// }
757-
758-
// Include all projections from associated type bindings of supertraits.
759-
poly_projections.extend(traits::elaborate_trait_ref(tcx, poly_trait_ref)
760-
.into_iter()
761-
.filter_map(|pred| {
762-
if let ty::Predicate::Projection(proj) = pred {
763-
Some(proj)
764-
} else {
765-
None
766-
}
767-
})
768-
.map(|proj| (proj, DUMMY_SP))
769-
);
770-
771-
// // Include associated type bindings from supertraits.
772-
// let mut foo = poly_projections.clone();
773-
// foo.extend(tcx.predicates_of(trait_def_id)
774-
// .predicates.into_iter()
775-
// .filter_map(|(pred, span)| {
776-
// debug!("pred: {:?}", pred);
777-
// if let ty::Predicate::Projection(proj) = pred {
778-
// Some((proj, span))
779-
// } else {
780-
// None
781-
// }
782-
// }));
783-
784-
// Check for multiple bindings of associated types.
785-
let mut seen_projection_bounds = FxHashMap::default();
786-
for (projection_bound, span) in poly_projections.iter().rev() {
787-
let bound_def_id = projection_bound.projection_def_id();
788-
let assoc_item = tcx.associated_item(bound_def_id);
789-
let trait_def_id = assoc_item.container.id();
790-
// let trait_ref = tcx.associated_item(proj.projection_type.item_def_id).container;
791-
seen_projection_bounds.entry((assoc_item.def_id, bound_def_id))
792-
.and_modify(|prev_span| {
793-
struct_span_err!(tcx.sess, *span, E0719,
794-
"the value of the associated type `{}` (from the trait `{}`) \
795-
is already specified",
796-
assoc_item.ident,
797-
tcx.item_path_str(trait_def_id))
798-
.span_label(*span, "re-bound here")
799-
.span_label(*prev_span, format!("`{}` bound here first", assoc_item.ident))
800-
.emit();
801-
})
802-
.or_insert(*span);
803-
}
804-
805745
debug!("instantiate_poly_trait_ref({:?}, projections={:?}) -> {:?}",
806746
trait_ref, poly_projections, poly_trait_ref);
807747
poly_trait_ref
@@ -884,7 +824,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
884824
ref_id: ast::NodeId,
885825
trait_ref: ty::PolyTraitRef<'tcx>,
886826
binding: &ConvertedBinding<'tcx>,
887-
speculative: bool)
827+
speculative: bool,
828+
dup_bindings: &mut FxHashMap<DefId, Span>)
888829
-> Result<ty::PolyProjectionPredicate<'tcx>, ErrorReported>
889830
{
890831
let tcx = self.tcx();
@@ -948,7 +889,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
948889
let candidates = traits::supertraits(tcx, trait_ref).filter(|r| {
949890
self.trait_defines_associated_type_named(r.def_id(), binding.item_name)
950891
});
951-
self.one_bound_for_assoc_type(candidates.into_iter(), &trait_ref.to_string(),
892+
self.one_bound_for_assoc_type(candidates, &trait_ref.to_string(),
952893
binding.item_name, binding.span)
953894
}?;
954895

@@ -964,6 +905,21 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
964905
}
965906
tcx.check_stability(assoc_ty.def_id, Some(ref_id), binding.span);
966907

908+
if !speculative {
909+
dup_bindings.entry(assoc_ty.def_id)
910+
.and_modify(|prev_span| {
911+
struct_span_err!(self.tcx().sess, binding.span, E0719,
912+
"the value of the associated type `{}` (from the trait `{}`) \
913+
is already specified",
914+
binding.item_name,
915+
tcx.item_path_str(assoc_ty.container.id()))
916+
.span_label(binding.span, "re-bound here")
917+
.span_label(*prev_span, format!("`{}` bound here first", binding.item_name))
918+
.emit();
919+
})
920+
.or_insert(binding.span);
921+
}
922+
967923
Ok(candidate.map_bound(|trait_ref| {
968924
ty::ProjectionPredicate {
969925
projection_ty: ty::ProjectionTy::from_ref_and_name(
@@ -989,6 +945,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
989945
)
990946
}
991947

948+
/// Transform a `PolyTraitRef` into a `PolyExistentialTraitRef` by
949+
/// removing the dummy `Self` type (`TRAIT_OBJECT_DUMMY_SELF`).
950+
fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>)
951+
-> ty::ExistentialTraitRef<'tcx> {
952+
assert_eq!(trait_ref.self_ty().sty, TRAIT_OBJECT_DUMMY_SELF);
953+
ty::ExistentialTraitRef::erase_self_ty(self.tcx(), trait_ref)
954+
}
955+
992956
fn conv_object_ty_poly_trait_ref(&self,
993957
span: Span,
994958
trait_bounds: &[hir::PolyTraitRef],
@@ -1043,13 +1007,22 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
10431007
// Use a `BTreeSet` to keep output in a more consistent order.
10441008
let mut associated_types = BTreeSet::default();
10451009

1046-
for tr in traits::supertraits(tcx, principal) {
1047-
associated_types.extend(tcx.associated_items(tr.def_id())
1048-
.filter(|item| item.kind == ty::AssociatedKind::Type)
1049-
.map(|item| item.def_id));
1010+
for tr in traits::elaborate_trait_ref(tcx, principal) {
1011+
match tr {
1012+
ty::Predicate::Trait(pred) => {
1013+
associated_types.extend(tcx.associated_items(pred.def_id())
1014+
.filter(|item| item.kind == ty::AssociatedKind::Type)
1015+
.map(|item| item.def_id));
1016+
}
1017+
ty::Predicate::Projection(pred) => {
1018+
// Include projections defined on supertraits.
1019+
projection_bounds.push((pred, DUMMY_SP))
1020+
}
1021+
_ => ()
1022+
}
10501023
}
10511024

1052-
for (projection_bound, _) in projection_bounds.iter().rev() {
1025+
for (projection_bound, _) in &projection_bounds {
10531026
associated_types.remove(&projection_bound.projection_def_id());
10541027
}
10551028

@@ -1067,13 +1040,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
10671040

10681041
// Erase the `dummy_self` (`TRAIT_OBJECT_DUMMY_SELF`) used above.
10691042
let existential_principal = principal.map_bound(|trait_ref| {
1070-
assert_eq!(trait_ref.self_ty().sty, TRAIT_OBJECT_DUMMY_SELF);
1071-
ty::ExistentialTraitRef::erase_self_ty(self.tcx(), trait_ref)
1043+
self.trait_ref_to_existential(trait_ref)
10721044
});
10731045
let existential_projections = projection_bounds.iter().map(|(bound, _)| {
10741046
bound.map_bound(|b| {
1075-
let trait_ref = ty::ExistentialTraitRef::erase_self_ty(self.tcx(),
1076-
b.projection_ty.trait_ref(tcx));
1047+
let trait_ref = self.trait_ref_to_existential(b.projection_ty.trait_ref(tcx));
10771048
ty::ExistentialProjection {
10781049
ty: b.ty,
10791050
item_def_id: b.projection_ty.item_def_id,

src/test/ui/lint/issue-50589-multiple-associated-types.rs renamed to src/test/run-pass/associated-types/associated-types-from-supertrait.rs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// compile-pass
12-
13-
use std::iter::Iterator;
14-
15-
type Unit = ();
16-
17-
fn test() -> Box<Iterator<Item = (), Item = Unit>> {
18-
Box::new(None.into_iter())
19-
}
11+
trait Foo: Iterator<Item = i32> {}
12+
trait Bar: Foo {}
2013

2114
fn main() {
22-
test();
15+
let _: &dyn Bar;
2316
}

src/test/ui/error-codes/E0719-trait-alias-object.rs renamed to src/test/ui/associated-types/associated-types-overridden-binding-2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@
1313
trait I32Iterator = Iterator<Item = i32>;
1414

1515
fn main() {
16-
let _: &I32Iterator<Item = u32>; //~ ERROR E0719
16+
let _: &I32Iterator<Item = u32> = &vec![42].into_iter();
1717
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0271]: type mismatch resolving `<std::vec::IntoIter<u32> as std::iter::Iterator>::Item == i32`
2+
--> $DIR/associated-types-overridden-binding-2.rs:16:39
3+
|
4+
LL | let _: &I32Iterator<Item = u32> = &vec![42].into_iter();
5+
| ^^^^^^^^^^^^^^^^^^^^^ expected u32, found i32
6+
|
7+
= note: expected type `u32`
8+
found type `i32`
9+
= note: required for the cast to the object type `dyn I32Iterator<Item=u32, Item=i32>`
10+
11+
error: aborting due to previous error
12+
13+
For more information about this error, try `rustc --explain E0271`.

src/test/ui/error-codes/E0719-trait-alias.rs renamed to src/test/ui/associated-types/associated-types-overridden-binding.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@
1010

1111
#![feature(trait_alias)]
1212

13+
trait Foo: Iterator<Item = i32> {}
14+
trait Bar: Foo<Item = u32> {}
15+
1316
trait I32Iterator = Iterator<Item = i32>;
14-
trait I32Iterator2 = I32Iterator<Item = i32>; //~ ERROR E0719
15-
trait U32Iterator = I32Iterator2<Item = i32>; //~ ERROR E0719
16-
trait U32Iterator2 = U32Iterator<Item = u32>; //~ ERROR E0719
17+
trait U32Iterator = I32Iterator<Item = u32>;
1718

18-
fn main() {}
19+
fn main() {
20+
let _: &I32Iterator<Item = u32>;
21+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0284]: type annotations required: cannot resolve `<Self as std::iter::Iterator>::Item == i32`
2+
--> $DIR/associated-types-overridden-binding.rs:14:1
3+
|
4+
LL | trait Bar: Foo<Item = u32> {}
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
note: required by `Foo`
8+
--> $DIR/associated-types-overridden-binding.rs:13:1
9+
|
10+
LL | trait Foo: Iterator<Item = i32> {}
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0284`.

src/test/ui/error-codes/E0719-trait-alias-object.stderr

Lines changed: 0 additions & 12 deletions
This file was deleted.

src/test/ui/error-codes/E0719-trait-alias.stderr

Lines changed: 0 additions & 29 deletions
This file was deleted.

src/test/ui/error-codes/E0719.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
trait Foo: Iterator<Item = i32, Item = i32> {}
12+
13+
type Unit = ();
14+
15+
fn test() -> Box<Iterator<Item = (), Item = Unit>> {
16+
Box::new(None.into_iter())
17+
}
18+
1119
fn main() {
12-
let _: &Iterator<Item = i32, Item = i32>; //~ ERROR E0719
20+
let _: &Iterator<Item = i32, Item = i32>;
21+
test();
1322
}

src/test/ui/error-codes/E0719.stderr

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
2-
--> $DIR/E0719.rs:12:22
2+
--> $DIR/E0719.rs:11:33
33
|
4-
LL | let _: &Iterator<Item = i32, Item = i32>; //~ ERROR E0719
5-
| ^^^^^^^^^^ ---------- `Item` bound here first
6-
| |
7-
| re-bound here
4+
LL | trait Foo: Iterator<Item = i32, Item = i32> {}
5+
| ---------- ^^^^^^^^^^ re-bound here
6+
| |
7+
| `Item` bound here first
88

9-
error: aborting due to previous error
9+
error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
10+
--> $DIR/E0719.rs:15:38
11+
|
12+
LL | fn test() -> Box<Iterator<Item = (), Item = Unit>> {
13+
| --------- ^^^^^^^^^^^ re-bound here
14+
| |
15+
| `Item` bound here first
16+
17+
error: aborting due to 2 previous errors
1018

1119
For more information about this error, try `rustc --explain E0719`.

src/test/ui/lint/issue-50589-multiple-associated-types.stderr

Lines changed: 0 additions & 23 deletions
This file was deleted.

0 commit comments

Comments
 (0)