diff options
| author | Alexander Regueiro <alexreg@me.com> | 2018-11-05 02:02:43 +0000 |
|---|---|---|
| committer | Alexander Regueiro <alexreg@me.com> | 2018-11-07 21:57:45 +0000 |
| commit | 6d3ee4170d525612161fa7f4c34315316dd422c5 (patch) | |
| tree | 3289b8f1d539ce6eb8ffae6e6c960361fd6a721e | |
| parent | 0e89f570d224ee08b6e32aa9ea8ea44a4e9244f3 (diff) | |
| download | rust-6d3ee4170d525612161fa7f4c34315316dd422c5.tar.gz rust-6d3ee4170d525612161fa7f4c34315316dd422c5.zip | |
Added error for duplicate bindings of associated type.
| -rw-r--r-- | src/librustc/traits/mod.rs | 7 | ||||
| -rw-r--r-- | src/librustc/ty/mod.rs | 46 | ||||
| -rw-r--r-- | src/librustc/ty/sty.rs | 18 | ||||
| -rw-r--r-- | src/librustc/ty/subst.rs | 14 | ||||
| -rw-r--r-- | src/librustc_typeck/astconv.rs | 130 | ||||
| -rw-r--r-- | src/test/run-pass/traits/trait-alias-object.rs (renamed from src/test/run-pass/traits/trait-alias-objects.rs) | 2 | ||||
| -rw-r--r-- | src/test/ui/error-codes/E0719-trait-alias-object.rs (renamed from src/test/ui/traits/trait-alias-associated-type-rebound.rs) | 6 | ||||
| -rw-r--r-- | src/test/ui/error-codes/E0719-trait-alias-object.stderr | 12 | ||||
| -rw-r--r-- | src/test/ui/error-codes/E0719-trait-alias.rs | 18 | ||||
| -rw-r--r-- | src/test/ui/error-codes/E0719-trait-alias.stderr | 29 | ||||
| -rw-r--r-- | src/test/ui/error-codes/E0719.rs | 8 | ||||
| -rw-r--r-- | src/test/ui/error-codes/E0719.stderr | 11 | ||||
| -rw-r--r-- | src/test/ui/traits/trait-alias-object.rs (renamed from src/test/ui/traits/trait-alias-objects.rs) | 0 | ||||
| -rw-r--r-- | src/test/ui/traits/trait-alias-object.stderr (renamed from src/test/ui/traits/trait-alias-objects.stderr) | 0 |
14 files changed, 184 insertions, 117 deletions
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index b7512790bfb..33b689c60a1 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -50,11 +50,8 @@ pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError pub use self::specialize::{OverlapError, specialization_graph, translate_substs}; pub use self::specialize::find_associated_item; pub use self::engine::{TraitEngine, TraitEngineExt}; -pub use self::util::elaborate_predicates; -pub use self::util::supertraits; -pub use self::util::Supertraits; -pub use self::util::supertrait_def_ids; -pub use self::util::SupertraitDefIds; +pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs}; +pub use self::util::{supertraits, supertrait_def_ids, Supertraits, SupertraitDefIds}; pub use self::util::transitive_bounds; #[allow(dead_code)] diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 71d59750d6c..19fe8606a4d 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -544,14 +544,14 @@ impl<'tcx> TyS<'tcx> { pub fn is_primitive_ty(&self) -> bool { match self.sty { TyKind::Bool | - TyKind::Char | - TyKind::Int(_) | - TyKind::Uint(_) | - TyKind::Float(_) | - TyKind::Infer(InferTy::IntVar(_)) | - TyKind::Infer(InferTy::FloatVar(_)) | - TyKind::Infer(InferTy::FreshIntTy(_)) | - TyKind::Infer(InferTy::FreshFloatTy(_)) => true, + TyKind::Char | + TyKind::Int(_) | + TyKind::Uint(_) | + TyKind::Float(_) | + TyKind::Infer(InferTy::IntVar(_)) | + TyKind::Infer(InferTy::FloatVar(_)) | + TyKind::Infer(InferTy::FreshIntTy(_)) | + TyKind::Infer(InferTy::FreshFloatTy(_)) => true, TyKind::Ref(_, x, _) => x.is_primitive_ty(), _ => false, } @@ -1042,15 +1042,15 @@ impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> { #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub enum Predicate<'tcx> { - /// Corresponds to `where Foo : Bar<A,B,C>`. `Foo` here would be + /// Corresponds to `where Foo: Bar<A,B,C>`. `Foo` here would be /// the `Self` type of the trait reference and `A`, `B`, and `C` /// would be the type parameters. Trait(PolyTraitPredicate<'tcx>), - /// where `'a : 'b` + /// where `'a: 'b` RegionOutlives(PolyRegionOutlivesPredicate<'tcx>), - /// where `T : 'a` + /// where `T: 'a` TypeOutlives(PolyTypeOutlivesPredicate<'tcx>), /// where `<T as TraitRef>::Name == X`, approximately. @@ -1063,7 +1063,7 @@ pub enum Predicate<'tcx> { /// trait must be object-safe ObjectSafe(DefId), - /// No direct syntax. May be thought of as `where T : FnFoo<...>` + /// No direct syntax. May be thought of as `where T: FnFoo<...>` /// for some substitutions `...` and `T` being a closure type. /// Satisfied (or refuted) once we know the closure's kind. ClosureKind(DefId, ClosureSubsts<'tcx>, ClosureKind), @@ -1112,11 +1112,11 @@ impl<'a, 'gcx, 'tcx> Predicate<'tcx> { // // Let's start with an easy case. Consider two traits: // - // trait Foo<'a> : Bar<'a,'a> { } + // trait Foo<'a>: Bar<'a,'a> { } // trait Bar<'b,'c> { } // - // Now, if we have a trait reference `for<'x> T : Foo<'x>`, then - // we can deduce that `for<'x> T : Bar<'x,'x>`. Basically, if we + // Now, if we have a trait reference `for<'x> T: Foo<'x>`, then + // we can deduce that `for<'x> T: Bar<'x,'x>`. Basically, if we // knew that `Foo<'x>` (for any 'x) then we also know that // `Bar<'x,'x>` (for any 'x). This more-or-less falls out from // normal substitution. @@ -1129,21 +1129,21 @@ impl<'a, 'gcx, 'tcx> Predicate<'tcx> { // // Another example to be careful of is this: // - // trait Foo1<'a> : for<'b> Bar1<'a,'b> { } + // trait Foo1<'a>: for<'b> Bar1<'a,'b> { } // trait Bar1<'b,'c> { } // - // Here, if we have `for<'x> T : Foo1<'x>`, then what do we know? - // The answer is that we know `for<'x,'b> T : Bar1<'x,'b>`. The + // Here, if we have `for<'x> T: Foo1<'x>`, then what do we know? + // The answer is that we know `for<'x,'b> T: Bar1<'x,'b>`. The // reason is similar to the previous example: any impl of - // `T:Foo1<'x>` must show that `for<'b> T : Bar1<'x, 'b>`. So + // `T:Foo1<'x>` must show that `for<'b> T: Bar1<'x, 'b>`. So // basically we would want to collapse the bound lifetimes from // the input (`trait_ref`) and the supertraits. // // To achieve this in practice is fairly straightforward. Let's // consider the more complicated scenario: // - // - We start out with `for<'x> T : Foo1<'x>`. In this case, `'x` - // has a De Bruijn index of 1. We want to produce `for<'x,'b> T : Bar1<'x,'b>`, + // - We start out with `for<'x> T: Foo1<'x>`. In this case, `'x` + // has a De Bruijn index of 1. We want to produce `for<'x,'b> T: Bar1<'x,'b>`, // where both `'x` and `'b` would have a DB index of 1. // The substitution from the input trait-ref is therefore going to be // `'a => 'x` (where `'x` has a DB index of 1). @@ -1219,7 +1219,7 @@ impl<'tcx> PolyTraitPredicate<'tcx> { } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] -pub struct OutlivesPredicate<A,B>(pub A, pub B); // `A : B` +pub struct OutlivesPredicate<A,B>(pub A, pub B); // `A: B` pub type PolyOutlivesPredicate<A,B> = ty::Binder<OutlivesPredicate<A,B>>; pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>; @@ -2476,7 +2476,7 @@ impl<'tcx> TyS<'tcx> { /// /// Note: prefer `ty.walk()` where possible. pub fn maybe_walk<F>(&'tcx self, mut f: F) - where F : FnMut(Ty<'tcx>) -> bool + where F: FnMut(Ty<'tcx>) -> bool { let mut walker = self.walk(); while let Some(ty) = walker.next() { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 28b58d62175..5c8549cba23 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -627,7 +627,7 @@ impl<'tcx> Binder<&'tcx List<ExistentialPredicate<'tcx>>> { /// A complete reference to a trait. These take numerous guises in syntax, /// but perhaps the most recognizable form is in a where clause: /// -/// T : Foo<U> +/// T: Foo<U> /// /// This would be represented by a trait-reference where the def-id is the /// def-id for the trait `Foo` and the substs define `T` as parameter 0, @@ -637,8 +637,8 @@ impl<'tcx> Binder<&'tcx List<ExistentialPredicate<'tcx>>> { /// that case the `Self` parameter is absent from the substitutions. /// /// Note that a `TraitRef` introduces a level of region binding, to -/// account for higher-ranked trait bounds like `T : for<'a> Foo<&'a -/// U>` or higher-ranked object types. +/// account for higher-ranked trait bounds like `T: for<'a> Foo<&'a U>` +/// or higher-ranked object types. #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct TraitRef<'tcx> { pub def_id: DefId, @@ -663,7 +663,7 @@ impl<'tcx> TraitRef<'tcx> { self.substs.type_at(0) } - pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a { + pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> + 'a { // Select only the "input types" from a trait-reference. For // now this is all the types that appear in the // trait-reference, but it should eventually exclude @@ -886,16 +886,16 @@ pub struct ProjectionTy<'tcx> { /// The parameters of the associated item. pub substs: &'tcx Substs<'tcx>, - /// The DefId of the TraitItem for the associated type N. + /// The `DefId` of the `TraitItem` for the associated type `N`. /// - /// Note that this is not the DefId of the TraitRef containing this - /// associated type, which is in tcx.associated_item(item_def_id).container. + /// Note that this is not the `DefId` of the `TraitRef` containing this + /// associated type, which is in `tcx.associated_item(item_def_id).container`. pub item_def_id: DefId, } impl<'a, 'tcx> ProjectionTy<'tcx> { - /// Construct a ProjectionTy by searching the trait from trait_ref for the - /// associated item named item_name. + /// Construct a `ProjectionTy` by searching the trait from `trait_ref` for the + /// associated item named `item_name`. pub fn from_ref_and_name( tcx: TyCtxt<'_, '_, '_>, trait_ref: ty::TraitRef<'tcx>, item_name: Ident ) -> ProjectionTy<'tcx> { diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index c1aed36c92d..b28e7c9fb19 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -27,7 +27,7 @@ use std::marker::PhantomData; use std::mem; use std::num::NonZeroUsize; -/// An entity in the Rust typesystem, which can be one of +/// An entity in the Rust type system, which can be one of /// several kinds (only types and lifetimes for now). /// To reduce memory usage, a `Kind` is a interned pointer, /// with the lowest 2 bits being reserved for a tag to @@ -171,7 +171,7 @@ impl<'tcx> Decodable for Kind<'tcx> { pub type Substs<'tcx> = List<Kind<'tcx>>; impl<'a, 'gcx, 'tcx> Substs<'tcx> { - /// Creates a Substs that maps each generic parameter to itself. + /// Creates a `Substs` that maps each generic parameter to itself. pub fn identity_for_item(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> &'tcx Substs<'tcx> { Substs::for_item(tcx, def_id, |param, _| { @@ -179,9 +179,9 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { }) } - /// Creates a Substs for generic parameter definitions, + /// Creates a `Substs` for generic parameter definitions, /// by calling closures to obtain each kind. - /// The closures get to observe the Substs as they're + /// The closures get to observe the `Substs` as they're /// being built, which can be used to correctly /// substitute defaults of generic parameters. pub fn for_item<F>(tcx: TyCtxt<'a, 'gcx, 'tcx>, @@ -242,7 +242,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { } #[inline] - pub fn types(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a { + pub fn types(&'a self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> + 'a { self.iter().filter_map(|k| { if let UnpackedKind::Type(ty) = k.unpack() { Some(ty) @@ -253,7 +253,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { } #[inline] - pub fn regions(&'a self) -> impl DoubleEndedIterator<Item=ty::Region<'tcx>> + 'a { + pub fn regions(&'a self) -> impl DoubleEndedIterator<Item = ty::Region<'tcx>> + 'a { self.iter().filter_map(|k| { if let UnpackedKind::Lifetime(lt) = k.unpack() { Some(lt) @@ -332,7 +332,7 @@ impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Substs<'tcx> {} // `foo`. Or use `foo.subst_spanned(tcx, substs, Some(span))` when // there is more information available (for better errors). -pub trait Subst<'tcx> : Sized { +pub trait Subst<'tcx>: Sized { fn subst<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &[Kind<'tcx>]) -> Self { self.subst_spanned(tcx, substs, None) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 3aaa5810eab..f3f42516938 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -37,7 +37,7 @@ use std::iter; use syntax::ast; use syntax::ptr::P; use syntax::feature_gate::{GateIssue, emit_feature_err}; -use syntax_pos::{Span, MultiSpan}; +use syntax_pos::{DUMMY_SP, Span, MultiSpan}; pub trait AstConv<'gcx, 'tcx> { fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>; @@ -719,6 +719,8 @@ 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); @@ -732,16 +734,74 @@ 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, &mut dup_bindings); + trait_ref.ref_id, poly_trait_ref, binding, speculative); // 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 @@ -824,8 +884,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { ref_id: ast::NodeId, trait_ref: ty::PolyTraitRef<'tcx>, binding: &ConvertedBinding<'tcx>, - speculative: bool, - dup_bindings: &mut FxHashMap<DefId, Span>) + speculative: bool) -> Result<ty::PolyProjectionPredicate<'tcx>, ErrorReported> { let tcx = self.tcx(); @@ -879,7 +938,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { } } - let supertraits = traits::supertraits(tcx, trait_ref); let candidate = if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) { // Simple case: X is defined in the current trait. @@ -887,11 +945,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { } else { // Otherwise, we have to walk through the supertraits to find // those that do. - let candidates = supertraits.filter(|r| { + let candidates = traits::supertraits(tcx, trait_ref).filter(|r| { self.trait_defines_associated_type_named(r.def_id(), binding.item_name) }); - let candidates = candidates.collect::<Vec<_>>(); - debug!("foo: candidates: {:?}", candidates); self.one_bound_for_assoc_type(candidates.into_iter(), &trait_ref.to_string(), binding.item_name, binding.span) }?; @@ -908,31 +964,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { } tcx.check_stability(assoc_ty.def_id, Some(ref_id), binding.span); - debug!("foo: info: {:?} {:?} {:?} {:?} {:?}", trait_ref, binding.item_name, speculative, assoc_ty.def_id, dup_bindings); - if !speculative { - dup_bindings.entry(assoc_ty.def_id) - .and_modify(|prev_span| { - let mut err = self.tcx().struct_span_lint_node( - ::rustc::lint::builtin::DUPLICATE_ASSOCIATED_TYPE_BINDINGS, - ref_id, - binding.span, - &format!("associated type binding `{}` specified more than once", - binding.item_name) - ); - err.span_label(binding.span, "used more than once"); - err.span_label(*prev_span, format!("first use of `{}`", binding.item_name)); - err.emit(); - }) - .or_insert(binding.span); - } - static mut ABC: u32 = 0; - unsafe { - ABC += 1; - if ABC == 3 { - assert!(false); - } - }; - Ok(candidate.map_bound(|trait_ref| { ty::ProjectionPredicate { projection_ty: ty::ProjectionTy::from_ref_and_name( @@ -1016,37 +1047,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { associated_types.extend(tcx.associated_items(tr.def_id()) .filter(|item| item.kind == ty::AssociatedKind::Type) .map(|item| item.def_id)); - - projection_bounds.extend(tcx.predicates_of(tr.def_id()) - .predicates.into_iter() - .filter_map(|(pred, span)| { - if let ty::Predicate::Projection(proj) = pred { - Some((proj, span)) - } else { - None - } - })); } - let mut seen_projection_bounds = FxHashMap::default(); - for (projection_bound, span) in projection_bounds.iter().rev() { - let bound_def_id = projection_bound.projection_def_id(); - seen_projection_bounds.entry(bound_def_id) - .and_modify(|prev_span| { - let assoc_item = tcx.associated_item(bound_def_id); - let trait_def_id = assoc_item.container.id(); - 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!("binding for `{}`", assoc_item.ident)) - .emit(); - }) - .or_insert(*span); - - associated_types.remove(&bound_def_id); + for (projection_bound, _) in projection_bounds.iter().rev() { + associated_types.remove(&projection_bound.projection_def_id()); } for item_def_id in associated_types { diff --git a/src/test/run-pass/traits/trait-alias-objects.rs b/src/test/run-pass/traits/trait-alias-object.rs index a5bb0cac251..adac28eeb12 100644 --- a/src/test/run-pass/traits/trait-alias-objects.rs +++ b/src/test/run-pass/traits/trait-alias-object.rs @@ -21,6 +21,6 @@ pub fn main() { let b = Box::new(456) as Box<dyn Foo>; assert!(*b == 456); - let c: &mut dyn I32Iterator<Item = u32> = &mut vec![123].into_iter(); + let c: &mut dyn I32Iterator = &mut vec![123].into_iter(); assert_eq!(c.next(), Some(123)); } diff --git a/src/test/ui/traits/trait-alias-associated-type-rebound.rs b/src/test/ui/error-codes/E0719-trait-alias-object.rs index 32f707e192d..1e842e5b508 100644 --- a/src/test/ui/traits/trait-alias-associated-type-rebound.rs +++ b/src/test/ui/error-codes/E0719-trait-alias-object.rs @@ -11,7 +11,7 @@ #![feature(trait_alias)] trait I32Iterator = Iterator<Item = i32>; -trait I32Iterator2 = I32Iterator<Item = i32>; -trait U32Iterator = I32Iterator2<Item = i32>; -pub fn main() {} +fn main() { + let _: &I32Iterator<Item = u32>; //~ ERROR E0719 +} diff --git a/src/test/ui/error-codes/E0719-trait-alias-object.stderr b/src/test/ui/error-codes/E0719-trait-alias-object.stderr new file mode 100644 index 00000000000..17ebf5901c4 --- /dev/null +++ b/src/test/ui/error-codes/E0719-trait-alias-object.stderr @@ -0,0 +1,12 @@ +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`. diff --git a/src/test/ui/error-codes/E0719-trait-alias.rs b/src/test/ui/error-codes/E0719-trait-alias.rs new file mode 100644 index 00000000000..4232cafa58b --- /dev/null +++ b/src/test/ui/error-codes/E0719-trait-alias.rs @@ -0,0 +1,18 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![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 + +fn main() {} diff --git a/src/test/ui/error-codes/E0719-trait-alias.stderr b/src/test/ui/error-codes/E0719-trait-alias.stderr new file mode 100644 index 00000000000..6bb1a541f4d --- /dev/null +++ b/src/test/ui/error-codes/E0719-trait-alias.stderr @@ -0,0 +1,29 @@ +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`. diff --git a/src/test/ui/error-codes/E0719.rs b/src/test/ui/error-codes/E0719.rs index 951041124bb..2177d29110a 100644 --- a/src/test/ui/error-codes/E0719.rs +++ b/src/test/ui/error-codes/E0719.rs @@ -8,10 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(trait_alias)] - -trait I32Iterator = Iterator<Item = i32>; - -pub fn main() { - let _: &I32Iterator<Item = f32>; //~ ERROR E0719 +fn main() { + let _: &Iterator<Item = i32, Item = i32>; //~ ERROR E0719 } diff --git a/src/test/ui/error-codes/E0719.stderr b/src/test/ui/error-codes/E0719.stderr new file mode 100644 index 00000000000..78a71b6faab --- /dev/null +++ b/src/test/ui/error-codes/E0719.stderr @@ -0,0 +1,11 @@ +error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified + --> $DIR/E0719.rs:12:22 + | +LL | let _: &Iterator<Item = i32, Item = i32>; //~ ERROR E0719 + | ^^^^^^^^^^ ---------- `Item` bound here first + | | + | re-bound here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0719`. diff --git a/src/test/ui/traits/trait-alias-objects.rs b/src/test/ui/traits/trait-alias-object.rs index 3adcd8436d8..3adcd8436d8 100644 --- a/src/test/ui/traits/trait-alias-objects.rs +++ b/src/test/ui/traits/trait-alias-object.rs diff --git a/src/test/ui/traits/trait-alias-objects.stderr b/src/test/ui/traits/trait-alias-object.stderr index 8f9681e898f..8f9681e898f 100644 --- a/src/test/ui/traits/trait-alias-objects.stderr +++ b/src/test/ui/traits/trait-alias-object.stderr |
