Only do check for trait objects, not trait or trait alias definitions.

This commit is contained in:
Alexander Regueiro 2018-11-06 23:17:11 +00:00
parent 6d3ee4170d
commit 7d9ee0314a
13 changed files with 114 additions and 165 deletions

View file

@ -1195,6 +1195,7 @@ impl<'a, 'gcx, 'tcx> Predicate<'tcx> {
pub struct TraitPredicate<'tcx> {
pub trait_ref: TraitRef<'tcx>
}
pub type PolyTraitPredicate<'tcx> = ty::Binder<TraitPredicate<'tcx>>;
impl<'tcx> TraitPredicate<'tcx> {
@ -1516,14 +1517,14 @@ impl UniverseIndex {
UniverseIndex::from_u32(self.private.checked_add(1).unwrap())
}
/// `true` if `self` can name a name from `other` -- in other words,
/// Returns `true` if `self` can name a name from `other` -- in other words,
/// if the set of names in `self` is a superset of those in
/// `other` (`self >= other`).
pub fn can_name(self, other: UniverseIndex) -> bool {
self.private >= other.private
}
/// `true` if `self` cannot name some names from `other` -- in other
/// Returns `true` if `self` cannot name some names from `other` -- in other
/// words, if the set of names in `self` is a strict subset of
/// those in `other` (`self < other`).
pub fn cannot_name(self, other: UniverseIndex) -> bool {

View file

@ -719,8 +719,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
speculative: bool)
-> ty::PolyTraitRef<'tcx>
{
let tcx = self.tcx();
let trait_def_id = self.trait_def_id(trait_ref);
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 {
trait_ref.path.segments.last().unwrap());
let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs));
let mut dup_bindings = FxHashMap::default();
poly_projections.extend(assoc_bindings.iter().filter_map(|binding| {
// specify type to assert that error was already reported in Err case:
let predicate: Result<_, ErrorReported> =
self.ast_type_binding_to_poly_projection_predicate(
trait_ref.ref_id, poly_trait_ref, binding, speculative);
trait_ref.ref_id, poly_trait_ref, binding, speculative, &mut dup_bindings);
// okay to ignore Err because of ErrorReported (see above)
Some((predicate.ok()?, binding.span))
}));
// make flat_map:
// for tr in traits::supertraits(tcx, poly_trait_ref) {
// let sup_trait_ref = tr.skip_binder();
// poly_projections.extend(sup_trait_ref.substs.types().filter_map(|t| {
// if let TyKind::Projection(proj) = t.sty {
// Some((proj, span))
// } else {
// None
// }
// });
// }
// Include all projections from associated type bindings of supertraits.
poly_projections.extend(traits::elaborate_trait_ref(tcx, poly_trait_ref)
.into_iter()
.filter_map(|pred| {
if let ty::Predicate::Projection(proj) = pred {
Some(proj)
} else {
None
}
})
.map(|proj| (proj, DUMMY_SP))
);
// // Include associated type bindings from supertraits.
// let mut foo = poly_projections.clone();
// foo.extend(tcx.predicates_of(trait_def_id)
// .predicates.into_iter()
// .filter_map(|(pred, span)| {
// debug!("pred: {:?}", pred);
// if let ty::Predicate::Projection(proj) = pred {
// Some((proj, span))
// } else {
// None
// }
// }));
// Check for multiple bindings of associated types.
let mut seen_projection_bounds = FxHashMap::default();
for (projection_bound, span) in poly_projections.iter().rev() {
let bound_def_id = projection_bound.projection_def_id();
let assoc_item = tcx.associated_item(bound_def_id);
let trait_def_id = assoc_item.container.id();
// let trait_ref = tcx.associated_item(proj.projection_type.item_def_id).container;
seen_projection_bounds.entry((assoc_item.def_id, bound_def_id))
.and_modify(|prev_span| {
struct_span_err!(tcx.sess, *span, E0719,
"the value of the associated type `{}` (from the trait `{}`) \
is already specified",
assoc_item.ident,
tcx.item_path_str(trait_def_id))
.span_label(*span, "re-bound here")
.span_label(*prev_span, format!("`{}` bound here first", assoc_item.ident))
.emit();
})
.or_insert(*span);
}
debug!("instantiate_poly_trait_ref({:?}, projections={:?}) -> {:?}",
trait_ref, poly_projections, poly_trait_ref);
poly_trait_ref
@ -884,7 +824,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
ref_id: ast::NodeId,
trait_ref: ty::PolyTraitRef<'tcx>,
binding: &ConvertedBinding<'tcx>,
speculative: bool)
speculative: bool,
dup_bindings: &mut FxHashMap<DefId, Span>)
-> Result<ty::PolyProjectionPredicate<'tcx>, ErrorReported>
{
let tcx = self.tcx();
@ -948,7 +889,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
let candidates = traits::supertraits(tcx, trait_ref).filter(|r| {
self.trait_defines_associated_type_named(r.def_id(), binding.item_name)
});
self.one_bound_for_assoc_type(candidates.into_iter(), &trait_ref.to_string(),
self.one_bound_for_assoc_type(candidates, &trait_ref.to_string(),
binding.item_name, binding.span)
}?;
@ -964,6 +905,21 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
}
tcx.check_stability(assoc_ty.def_id, Some(ref_id), binding.span);
if !speculative {
dup_bindings.entry(assoc_ty.def_id)
.and_modify(|prev_span| {
struct_span_err!(self.tcx().sess, binding.span, E0719,
"the value of the associated type `{}` (from the trait `{}`) \
is already specified",
binding.item_name,
tcx.item_path_str(assoc_ty.container.id()))
.span_label(binding.span, "re-bound here")
.span_label(*prev_span, format!("`{}` bound here first", binding.item_name))
.emit();
})
.or_insert(binding.span);
}
Ok(candidate.map_bound(|trait_ref| {
ty::ProjectionPredicate {
projection_ty: ty::ProjectionTy::from_ref_and_name(
@ -989,6 +945,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
)
}
/// Transform a `PolyTraitRef` into a `PolyExistentialTraitRef` by
/// removing the dummy `Self` type (`TRAIT_OBJECT_DUMMY_SELF`).
fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>)
-> ty::ExistentialTraitRef<'tcx> {
assert_eq!(trait_ref.self_ty().sty, TRAIT_OBJECT_DUMMY_SELF);
ty::ExistentialTraitRef::erase_self_ty(self.tcx(), trait_ref)
}
fn conv_object_ty_poly_trait_ref(&self,
span: Span,
trait_bounds: &[hir::PolyTraitRef],
@ -1043,13 +1007,22 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
// Use a `BTreeSet` to keep output in a more consistent order.
let mut associated_types = BTreeSet::default();
for tr in traits::supertraits(tcx, principal) {
associated_types.extend(tcx.associated_items(tr.def_id())
.filter(|item| item.kind == ty::AssociatedKind::Type)
.map(|item| item.def_id));
for tr in traits::elaborate_trait_ref(tcx, principal) {
match tr {
ty::Predicate::Trait(pred) => {
associated_types.extend(tcx.associated_items(pred.def_id())
.filter(|item| item.kind == ty::AssociatedKind::Type)
.map(|item| item.def_id));
}
ty::Predicate::Projection(pred) => {
// Include projections defined on supertraits.
projection_bounds.push((pred, DUMMY_SP))
}
_ => ()
}
}
for (projection_bound, _) in projection_bounds.iter().rev() {
for (projection_bound, _) in &projection_bounds {
associated_types.remove(&projection_bound.projection_def_id());
}
@ -1067,13 +1040,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
// Erase the `dummy_self` (`TRAIT_OBJECT_DUMMY_SELF`) used above.
let existential_principal = principal.map_bound(|trait_ref| {
assert_eq!(trait_ref.self_ty().sty, TRAIT_OBJECT_DUMMY_SELF);
ty::ExistentialTraitRef::erase_self_ty(self.tcx(), trait_ref)
self.trait_ref_to_existential(trait_ref)
});
let existential_projections = projection_bounds.iter().map(|(bound, _)| {
bound.map_bound(|b| {
let trait_ref = ty::ExistentialTraitRef::erase_self_ty(self.tcx(),
b.projection_ty.trait_ref(tcx));
let trait_ref = self.trait_ref_to_existential(b.projection_ty.trait_ref(tcx));
ty::ExistentialProjection {
ty: b.ty,
item_def_id: b.projection_ty.item_def_id,

View file

@ -8,16 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-pass
use std::iter::Iterator;
type Unit = ();
fn test() -> Box<Iterator<Item = (), Item = Unit>> {
Box::new(None.into_iter())
}
trait Foo: Iterator<Item = i32> {}
trait Bar: Foo {}
fn main() {
test();
let _: &dyn Bar;
}

View file

@ -13,5 +13,5 @@
trait I32Iterator = Iterator<Item = i32>;
fn main() {
let _: &I32Iterator<Item = u32>; //~ ERROR E0719
let _: &I32Iterator<Item = u32> = &vec![42].into_iter();
}

View file

@ -0,0 +1,13 @@
error[E0271]: type mismatch resolving `<std::vec::IntoIter<u32> as std::iter::Iterator>::Item == i32`
--> $DIR/associated-types-overridden-binding-2.rs:16:39
|
LL | let _: &I32Iterator<Item = u32> = &vec![42].into_iter();
| ^^^^^^^^^^^^^^^^^^^^^ expected u32, found i32
|
= note: expected type `u32`
found type `i32`
= note: required for the cast to the object type `dyn I32Iterator<Item=u32, Item=i32>`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0271`.

View file

@ -10,9 +10,12 @@
#![feature(trait_alias)]
trait I32Iterator = Iterator<Item = i32>;
trait I32Iterator2 = I32Iterator<Item = i32>; //~ ERROR E0719
trait U32Iterator = I32Iterator2<Item = i32>; //~ ERROR E0719
trait U32Iterator2 = U32Iterator<Item = u32>; //~ ERROR E0719
trait Foo: Iterator<Item = i32> {}
trait Bar: Foo<Item = u32> {}
fn main() {}
trait I32Iterator = Iterator<Item = i32>;
trait U32Iterator = I32Iterator<Item = u32>;
fn main() {
let _: &I32Iterator<Item = u32>;
}

View file

@ -0,0 +1,15 @@
error[E0284]: type annotations required: cannot resolve `<Self as std::iter::Iterator>::Item == i32`
--> $DIR/associated-types-overridden-binding.rs:14:1
|
LL | trait Bar: Foo<Item = u32> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: required by `Foo`
--> $DIR/associated-types-overridden-binding.rs:13:1
|
LL | trait Foo: Iterator<Item = i32> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0284`.

View file

@ -1,12 +0,0 @@
error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
--> $DIR/E0719-trait-alias-object.rs:16:25
|
LL | trait I32Iterator = Iterator<Item = i32>;
| ---------- `Item` bound here first
...
LL | let _: &I32Iterator<Item = u32>; //~ ERROR E0719
| ^^^^^^^^^^ re-bound here
error: aborting due to previous error
For more information about this error, try `rustc --explain E0719`.

View file

@ -1,29 +0,0 @@
error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
--> $DIR/E0719-trait-alias.rs:14:34
|
LL | trait I32Iterator = Iterator<Item = i32>;
| ---------- `Item` bound here first
LL | trait I32Iterator2 = I32Iterator<Item = i32>; //~ ERROR E0719
| ^^^^^^^^^^ re-bound here
error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
--> $DIR/E0719-trait-alias.rs:15:34
|
LL | trait I32Iterator = Iterator<Item = i32>;
| ---------- `Item` bound here first
LL | trait I32Iterator2 = I32Iterator<Item = i32>; //~ ERROR E0719
LL | trait U32Iterator = I32Iterator2<Item = i32>; //~ ERROR E0719
| ^^^^^^^^^^ re-bound here
error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
--> $DIR/E0719-trait-alias.rs:16:34
|
LL | trait I32Iterator = Iterator<Item = i32>;
| ---------- `Item` bound here first
...
LL | trait U32Iterator2 = U32Iterator<Item = u32>; //~ ERROR E0719
| ^^^^^^^^^^ re-bound here
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0719`.

View file

@ -8,6 +8,15 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() {
let _: &Iterator<Item = i32, Item = i32>; //~ ERROR E0719
trait Foo: Iterator<Item = i32, Item = i32> {}
type Unit = ();
fn test() -> Box<Iterator<Item = (), Item = Unit>> {
Box::new(None.into_iter())
}
fn main() {
let _: &Iterator<Item = i32, Item = i32>;
test();
}

View file

@ -1,11 +1,19 @@
error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
--> $DIR/E0719.rs:12:22
--> $DIR/E0719.rs:11:33
|
LL | let _: &Iterator<Item = i32, Item = i32>; //~ ERROR E0719
| ^^^^^^^^^^ ---------- `Item` bound here first
| |
| re-bound here
LL | trait Foo: Iterator<Item = i32, Item = i32> {}
| ---------- ^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
error: aborting due to previous error
error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
--> $DIR/E0719.rs:15:38
|
LL | fn test() -> Box<Iterator<Item = (), Item = Unit>> {
| --------- ^^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0719`.

View file

@ -1,23 +0,0 @@
warning: associated type binding `Item` specified more than once
--> $DIR/issue-50589-multiple-associated-types.rs:17:39
|
LL | fn test() -> Box<Iterator<Item = (), Item = Unit>> {
| --------- ^^^^^^^^^^^ used more than once
| |
| first use of `Item`
|
= note: #[warn(duplicate_associated_type_bindings)] on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #50589 <https://github.com/rust-lang/rust/issues/50589>
warning: associated type binding `Item` specified more than once
--> $DIR/issue-50589-multiple-associated-types.rs:17:39
|
LL | fn test() -> Box<Iterator<Item = (), Item = Unit>> {
| --------- ^^^^^^^^^^^ used more than once
| |
| first use of `Item`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #50589 <https://github.com/rust-lang/rust/issues/50589>

View file

@ -1,5 +1,5 @@
error[E0038]: the trait `EqAlias` cannot be made into an object
--> $DIR/trait-alias-objects.rs:17:13
--> $DIR/trait-alias-object.rs:17:13
|
LL | let _: &dyn EqAlias = &123;
| ^^^^^^^^^^^ the trait `EqAlias` cannot be made into an object
@ -7,7 +7,7 @@ LL | let _: &dyn EqAlias = &123;
= note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
error[E0191]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified
--> $DIR/trait-alias-objects.rs:18:13
--> $DIR/trait-alias-object.rs:18:13
|
LL | let _: &dyn IteratorAlias = &vec![123].into_iter();
| ^^^^^^^^^^^^^^^^^ missing associated type `Item` value