about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAlexander Regueiro <alexreg@me.com>2018-11-04 04:47:10 +0000
committerAlexander Regueiro <alexreg@me.com>2018-11-07 21:57:40 +0000
commit0e89f570d224ee08b6e32aa9ea8ea44a4e9244f3 (patch)
treeb4608c47fb643d3b8955e272b3c322274f788ecc /src
parentd08a42bf2c2115fc1869b3a72ee40fa4dd445795 (diff)
downloadrust-0e89f570d224ee08b6e32aa9ea8ea44a4e9244f3.tar.gz
rust-0e89f570d224ee08b6e32aa9ea8ea44a4e9244f3.zip
Added tests.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/diagnostics.rs4
-rw-r--r--src/librustc/ty/mod.rs4
-rw-r--r--src/librustc_typeck/astconv.rs42
-rw-r--r--src/librustc_typeck/check/wfcheck.rs4
-rw-r--r--src/librustc_typeck/collect.rs12
-rw-r--r--src/librustc_typeck/diagnostics.rs1
-rw-r--r--src/test/run-pass/issues/issue-24010.rs22
-rw-r--r--src/test/run-pass/traits/trait-alias-objects.rs (renamed from src/test/run-pass/traits/trait-alias-object-type.rs)5
-rw-r--r--src/test/ui/error-codes/E0191.rs3
-rw-r--r--src/test/ui/error-codes/E0719.rs17
-rw-r--r--src/test/ui/issue-51947.rs17
-rw-r--r--src/test/ui/issues/issue-51947.rs27
-rw-r--r--src/test/ui/traits/trait-alias-associated-type-rebound.rs17
13 files changed, 133 insertions, 42 deletions
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index 1d21a5cf79d..96590c1fc72 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -2134,7 +2134,7 @@ static X: u32 = 42;
 
 
 register_diagnostics! {
-//  E0006 // merged with E0005
+//  E0006, // merged with E0005
 //  E0101, // replaced with E0282
 //  E0102, // replaced with E0282
 //  E0134,
@@ -2183,9 +2183,7 @@ register_diagnostics! {
     E0657, // `impl Trait` can only capture lifetimes bound at the fn level
     E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax
     E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders
-
     E0697, // closures cannot be static
-
     E0707, // multiple elided lifetimes used in arguments of `async fn`
     E0708, // `async` non-`move` closures with arguments are not currently supported
     E0709, // multiple different lifetimes used in arguments of `async fn`
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index c18c55bcb5d..71d59750d6c 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1239,11 +1239,11 @@ pub type PolySubtypePredicate<'tcx> = ty::Binder<SubtypePredicate<'tcx>>;
 /// This kind of predicate has no *direct* correspondent in the
 /// syntax, but it roughly corresponds to the syntactic forms:
 ///
-/// 1. `T : TraitRef<..., Item=Type>`
+/// 1. `T: TraitRef<..., Item=Type>`
 /// 2. `<T as TraitRef<...>>::Item == Type` (NYI)
 ///
 /// In particular, form #1 is "desugared" to the combination of a
-/// normal trait predicate (`T : TraitRef<...>`) and one of these
+/// normal trait predicate (`T: TraitRef<...>`) and one of these
 /// predicates. Form #2 is a broader form in that it also permits
 /// equality between arbitrary types. Processing an instance of
 /// Form #2 eventually yields one of these `ProjectionPredicate`
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index daf04aa0db2..3aaa5810eab 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -831,7 +831,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
         let tcx = self.tcx();
 
         if !speculative {
-            // Given something like `U : SomeTrait<T=X>`, we want to produce a
+            // Given something like `U: SomeTrait<T = X>`, we want to produce a
             // predicate like `<U as SomeTrait>::T = X`. This is somewhat
             // subtle in the event that `T` is defined in a supertrait of
             // `SomeTrait`, because in that case we need to upcast.
@@ -839,7 +839,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
             // That is, consider this case:
             //
             // ```
-            // trait SubTrait : SuperTrait<int> { }
+            // trait SubTrait: SuperTrait<int> { }
             // trait SuperTrait<A> { type T; }
             //
             // ... B : SubTrait<T=foo> ...
@@ -879,6 +879,7 @@ 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.
@@ -886,10 +887,12 @@ 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 = traits::supertraits(tcx, trait_ref).filter(|r| {
+            let candidates = supertraits.filter(|r| {
                 self.trait_defines_associated_type_named(r.def_id(), binding.item_name)
             });
-            self.one_bound_for_assoc_type(candidates, &trait_ref.to_string(),
+            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)
         }?;
 
@@ -905,6 +908,7 @@ 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| {
@@ -921,6 +925,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
                 })
                 .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 {
@@ -1017,8 +1028,25 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
                 }));
         }
 
-        for (projection_bound, _) in &projection_bounds {
-            associated_types.remove(&projection_bound.projection_def_id());
+        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 item_def_id in associated_types {
@@ -1132,7 +1160,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
                                       span)
     }
 
-    // Checks that bounds contains exactly one element and reports appropriate
+    // Checks that `bounds` contains exactly one element and reports appropriate
     // errors otherwise.
     fn one_bound_for_assoc_type<I>(&self,
                                    mut bounds: I,
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 53f53657863..8574443190d 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -28,9 +28,9 @@ use errors::{DiagnosticBuilder, DiagnosticId};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir;
 
-/// Helper type of a temporary returned by .for_item(...).
+/// Helper type of a temporary returned by `.for_item(...)`.
 /// Necessary because we can't write the following bound:
-/// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(FnCtxt<'b, 'gcx, 'tcx>).
+/// `F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(FnCtxt<'b, 'gcx, 'tcx>)`.
 struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     inherited: super::InheritedBuilder<'a, 'gcx, 'tcx>,
     id: ast::NodeId,
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index be09cfce8ca..d5f5cbb562e 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1978,9 +1978,9 @@ pub enum SizedByDefault {
     No,
 }
 
-/// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
-/// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
-/// built-in trait (formerly known as kind): Send.
+/// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped `Ty`
+/// or a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
+/// built-in trait `Send`.
 pub fn compute_bounds<'gcx: 'tcx, 'tcx>(
     astconv: &dyn AstConv<'gcx, 'tcx>,
     param_ty: Ty<'tcx>,
@@ -1988,8 +1988,8 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(
     sized_by_default: SizedByDefault,
     span: Span,
 ) -> Bounds<'tcx> {
-    let mut region_bounds = vec![];
-    let mut trait_bounds = vec![];
+    let mut region_bounds = Vec::new();
+    let mut trait_bounds = Vec::new();
 
     for ast_bound in ast_bounds {
         match *ast_bound {
@@ -1999,7 +1999,7 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(
         }
     }
 
-    let mut projection_bounds = vec![];
+    let mut projection_bounds = Vec::new();
 
     let mut trait_bounds: Vec<_> = trait_bounds.iter().map(|&bound| {
         (astconv.instantiate_poly_trait_ref(bound, param_ty, &mut projection_bounds), bound.span)
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index c81aea2465b..a985c3e9fdf 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -4909,4 +4909,5 @@ register_diagnostics! {
     E0641, // cannot cast to/from a pointer with an unknown kind
     E0645, // trait aliases not finished
     E0698, // type inside generator must be known in this context
+    E0719, // duplicate values for associated type binding
 }
diff --git a/src/test/run-pass/issues/issue-24010.rs b/src/test/run-pass/issues/issue-24010.rs
new file mode 100644
index 00000000000..cce8bb84837
--- /dev/null
+++ b/src/test/run-pass/issues/issue-24010.rs
@@ -0,0 +1,22 @@
+// 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.
+
+trait Foo: Fn(i32) -> i32 + Send {}
+
+impl<T: ?Sized + Fn(i32) -> i32 + Send> Foo for T {}
+
+fn wants_foo(f: Box<Foo>) -> i32 {
+    f(42)
+}
+
+fn main() {
+    let f = Box::new(|x| x);
+    assert_eq!(wants_foo(f), 42);
+}
diff --git a/src/test/run-pass/traits/trait-alias-object-type.rs b/src/test/run-pass/traits/trait-alias-objects.rs
index 17e30922b2c..a5bb0cac251 100644
--- a/src/test/run-pass/traits/trait-alias-object-type.rs
+++ b/src/test/run-pass/traits/trait-alias-objects.rs
@@ -21,7 +21,6 @@ pub fn main() {
     let b = Box::new(456) as Box<dyn Foo>;
     assert!(*b == 456);
 
-    // FIXME(alexreg): associated type should be gotten from trait alias definition
-    // let c: &dyn I32Iterator = &vec![123].into_iter();
-    // assert_eq!(c.next(), Some(123));
+    let c: &mut dyn I32Iterator<Item = u32> = &mut vec![123].into_iter();
+    assert_eq!(c.next(), Some(123));
 }
diff --git a/src/test/ui/error-codes/E0191.rs b/src/test/ui/error-codes/E0191.rs
index 489ebb033f8..c35c7e10f5a 100644
--- a/src/test/ui/error-codes/E0191.rs
+++ b/src/test/ui/error-codes/E0191.rs
@@ -14,5 +14,4 @@ trait Trait {
 
 type Foo = Trait; //~ ERROR E0191
 
-fn main() {
-}
+fn main() {}
diff --git a/src/test/ui/error-codes/E0719.rs b/src/test/ui/error-codes/E0719.rs
new file mode 100644
index 00000000000..951041124bb
--- /dev/null
+++ b/src/test/ui/error-codes/E0719.rs
@@ -0,0 +1,17 @@
+// 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>;
+
+pub fn main() {
+    let _: &I32Iterator<Item = f32>; //~ ERROR E0719
+}
diff --git a/src/test/ui/issue-51947.rs b/src/test/ui/issue-51947.rs
deleted file mode 100644
index 7b79807e4d7..00000000000
--- a/src/test/ui/issue-51947.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// compile-pass
-
-#![crate_type = "lib"]
-#![feature(linkage)]
-
-// MergeFunctions will merge these via an anonymous internal
-// backing function, which must be named if ThinLTO buffers are used
-
-#[linkage = "weak"]
-pub fn fn1(a: u32, b: u32, c: u32) -> u32 {
-    a + b + c
-}
-
-#[linkage = "weak"]
-pub fn fn2(a: u32, b: u32, c: u32) -> u32 {
-    a + b + c
-}
diff --git a/src/test/ui/issues/issue-51947.rs b/src/test/ui/issues/issue-51947.rs
new file mode 100644
index 00000000000..3e0c3c002f6
--- /dev/null
+++ b/src/test/ui/issues/issue-51947.rs
@@ -0,0 +1,27 @@
+// 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
+
+#![crate_type = "lib"]
+#![feature(linkage)]
+
+// MergeFunctions will merge these via an anonymous internal
+// backing function, which must be named if ThinLTO buffers are used
+
+#[linkage = "weak"]
+pub fn fn1(a: u32, b: u32, c: u32) -> u32 {
+    a + b + c
+}
+
+#[linkage = "weak"]
+pub fn fn2(a: u32, b: u32, c: u32) -> u32 {
+    a + b + c
+}
diff --git a/src/test/ui/traits/trait-alias-associated-type-rebound.rs b/src/test/ui/traits/trait-alias-associated-type-rebound.rs
new file mode 100644
index 00000000000..32f707e192d
--- /dev/null
+++ b/src/test/ui/traits/trait-alias-associated-type-rebound.rs
@@ -0,0 +1,17 @@
+// 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>;
+trait U32Iterator = I32Iterator2<Item = i32>;
+
+pub fn main() {}