about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-05-23 05:09:13 +0000
committerbors <bors@rust-lang.org>2018-05-23 05:09:13 +0000
commit9a4e5df12685e58ad42ce0152cdbe266373c6bf3 (patch)
tree9a444841d99befe893ba2801037b11d949f0497e /src
parent5ec4ab9b6820c5f0937bf29c09637648fcb547a3 (diff)
parent88f810f52e628795875260a31d479af4f28a5edb (diff)
downloadrust-9a4e5df12685e58ad42ce0152cdbe266373c6bf3.tar.gz
rust-9a4e5df12685e58ad42ce0152cdbe266373c6bf3.zip
Auto merge of #50682 - F001:issue-50589, r=petrochenkov
Add lint for multiple associated types

Fix https://github.com/rust-lang/rust/issues/50589. cc @abonander
Diffstat (limited to 'src')
-rw-r--r--src/librustc/lint/builtin.rs7
-rw-r--r--src/librustc_lint/lib.rs5
-rw-r--r--src/librustc_typeck/astconv.rs27
-rw-r--r--src/test/ui/lint/issue-50589-multiple-associated-types.rs23
-rw-r--r--src/test/ui/lint/issue-50589-multiple-associated-types.stderr23
5 files changed, 81 insertions, 4 deletions
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index ac2fa8515bc..5d7d2f0f9e6 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -279,6 +279,12 @@ declare_lint! {
     "detects labels that are never used"
 }
 
+declare_lint! {
+    pub DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
+    Warn,
+    "warns about duplicate associated type bindings in generics"
+}
+
 /// Does nothing as a lint pass, but registers some `Lint`s
 /// which are used by other parts of the compiler.
 #[derive(Copy, Clone)]
@@ -330,6 +336,7 @@ impl LintPass for HardwiredLints {
             BARE_TRAIT_OBJECT,
             ABSOLUTE_PATH_NOT_STARTING_WITH_CRATE,
             UNSTABLE_NAME_COLLISION,
+            DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
         )
     }
 }
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index cfd5cf5a0f9..e35537459b7 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -283,6 +283,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
             reference: "issue TBD",
             edition: Some(Edition::Edition2018),
         },
+        FutureIncompatibleInfo {
+            id: LintId::of(DUPLICATE_ASSOCIATED_TYPE_BINDINGS),
+            reference: "issue #50589 <https://github.com/rust-lang/rust/issues/50589>",
+            edition: None,
+        },
         ]);
 
     // Register renamed and removed lints
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index f2fe8b1d891..68587fb8b3c 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -27,7 +27,7 @@ use rustc_target::spec::abi;
 use std::slice;
 use require_c_abi_if_variadic;
 use util::common::ErrorReported;
-use util::nodemap::FxHashSet;
+use util::nodemap::{FxHashSet, FxHashMap};
 use errors::FatalError;
 
 use std::iter;
@@ -398,11 +398,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> 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);
+                self.ast_type_binding_to_poly_projection_predicate(
+                    trait_ref.ref_id, poly_trait_ref, binding, speculative, &mut dup_bindings);
             predicate.ok() // ok to ignore Err() because ErrorReported (see above)
         }));
 
@@ -487,7 +488,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> 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();
@@ -566,6 +568,23 @@ impl<'o, 'gcx: 'tcx, 'tcx> 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| {
+                    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);
+        }
+
         Ok(candidate.map_bound(|trait_ref| {
             ty::ProjectionPredicate {
                 projection_ty: ty::ProjectionTy::from_ref_and_name(
diff --git a/src/test/ui/lint/issue-50589-multiple-associated-types.rs b/src/test/ui/lint/issue-50589-multiple-associated-types.rs
new file mode 100644
index 00000000000..2c789a139cd
--- /dev/null
+++ b/src/test/ui/lint/issue-50589-multiple-associated-types.rs
@@ -0,0 +1,23 @@
+// 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.
+
+// compile-pass
+
+use std::iter::Iterator;
+
+type Unit = ();
+
+fn test() ->  Box<Iterator<Item = (), Item = Unit>> {
+    Box::new(None.into_iter())
+}
+
+fn main() {
+    test();
+}
diff --git a/src/test/ui/lint/issue-50589-multiple-associated-types.stderr b/src/test/ui/lint/issue-50589-multiple-associated-types.stderr
new file mode 100644
index 00000000000..7f0a1ee1f33
--- /dev/null
+++ b/src/test/ui/lint/issue-50589-multiple-associated-types.stderr
@@ -0,0 +1,23 @@
+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>
+