about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-07-13 23:09:02 -0700
committerGitHub <noreply@github.com>2016-07-13 23:09:02 -0700
commit3c85f414e922b7bf427493211601c0c7bde3a286 (patch)
tree4d95acbdc10ca91e7d7fb00a8a093b4b9794357a /src
parent935bd763674ea3e5b79928bed08016291cc52901 (diff)
parent5ad507206fae81293cb07dfde5c94e6be3994160 (diff)
downloadrust-3c85f414e922b7bf427493211601c0c7bde3a286.tar.gz
rust-3c85f414e922b7bf427493211601c0c7bde3a286.zip
Auto merge of #34805 - michaelwoerister:stable-bounds-encoding, r=eddyb
tyencode: Make sure that projection bounds are handled in stable order.

Fixes #34796.

r? @alexcrichton
Diffstat (limited to 'src')
-rw-r--r--src/librustc_metadata/tyencode.rs9
-rw-r--r--src/test/run-pass/auxiliary/issue34796aux.rs30
-rw-r--r--src/test/run-pass/issue34796.rs36
3 files changed, 74 insertions, 1 deletions
diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs
index 1afeccdf8e3..3484a8b75dd 100644
--- a/src/librustc_metadata/tyencode.rs
+++ b/src/librustc_metadata/tyencode.rs
@@ -407,7 +407,14 @@ pub fn enc_existential_bounds<'a,'tcx>(w: &mut Cursor<Vec<u8>>,
 
     enc_region(w, cx, bs.region_bound);
 
-    for tp in &bs.projection_bounds {
+    // Encode projection_bounds in a stable order
+    let mut projection_bounds: Vec<_> = bs.projection_bounds
+                                          .iter()
+                                          .map(|b| (b.item_name().as_str(), b))
+                                          .collect();
+    projection_bounds.sort_by_key(|&(ref name, _)| name.clone());
+
+    for tp in projection_bounds.iter().map(|&(_, tp)| tp) {
         write!(w, "P");
         enc_projection_predicate(w, cx, &tp.0);
     }
diff --git a/src/test/run-pass/auxiliary/issue34796aux.rs b/src/test/run-pass/auxiliary/issue34796aux.rs
new file mode 100644
index 00000000000..9131b609c4c
--- /dev/null
+++ b/src/test/run-pass/auxiliary/issue34796aux.rs
@@ -0,0 +1,30 @@
+// Copyright 2016 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.
+
+#![crate_type = "lib"]
+pub trait Future {
+    type Item;
+    type Error;
+}
+
+impl Future for u32 {
+    type Item = ();
+    type Error = Box<()>;
+}
+
+fn foo() -> Box<Future<Item=(), Error=Box<()>>> {
+    Box::new(0u32)
+}
+
+pub fn bar<F, A, B>(_s: F)
+    where F: Fn(A) -> B,
+{
+    foo();
+}
diff --git a/src/test/run-pass/issue34796.rs b/src/test/run-pass/issue34796.rs
new file mode 100644
index 00000000000..0fb6ccc0dc8
--- /dev/null
+++ b/src/test/run-pass/issue34796.rs
@@ -0,0 +1,36 @@
+// Copyright 2016 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.
+
+// This test case exposes conditions where the encoding of a trait object type
+// with projection predicates would differ between this crate and the upstream
+// crate, because the predicates were encoded in different order within each
+// crate. This led to different symbol hashes of functions using these type,
+// which in turn led to linker errors because the two crates would not agree on
+// the symbol name.
+// The fix was to make the order in which predicates get encoded stable.
+
+// aux-build:issue34796aux.rs
+extern crate issue34796aux;
+
+fn mk<T>() -> T { loop {} }
+
+struct Data<T, E> {
+    data: T,
+    error: E,
+}
+
+fn main() {
+    issue34796aux::bar(|()| {
+        Data::<(), std::io::Error> {
+            data: mk(),
+            error: mk(),
+        }
+    })
+}