Only do check for trait objects, not trait or trait alias definitions.
This commit is contained in:
parent
6d3ee4170d
commit
7d9ee0314a
13 changed files with 114 additions and 165 deletions
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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`.
|
|
@ -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>;
|
||||
}
|
|
@ -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`.
|
|
@ -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`.
|
|
@ -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`.
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue