diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs index 1afeccdf8e3a9..3484a8b75dded 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>, 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 0000000000000..9131b609c4ce1 --- /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 or the MIT license +// , 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>> { + Box::new(0u32) +} + +pub fn bar(_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 0000000000000..0fb6ccc0dc8bd --- /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 or the MIT license +// , 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 { loop {} } + +struct Data { + data: T, + error: E, +} + +fn main() { + issue34796aux::bar(|()| { + Data::<(), std::io::Error> { + data: mk(), + error: mk(), + } + }) +}