From 01c0723ef247fec4b85af203c7247b66e3817e1b Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Sat, 5 Mar 2016 14:51:24 -0500 Subject: [PATCH 1/5] add #[derive(Hash)] test for #21714 --- src/test/run-pass/deriving-hash.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/test/run-pass/deriving-hash.rs b/src/test/run-pass/deriving-hash.rs index a98cfa2393f..91bfc2f9201 100644 --- a/src/test/run-pass/deriving-hash.rs +++ b/src/test/run-pass/deriving-hash.rs @@ -12,6 +12,7 @@ #![feature(hash_default)] use std::hash::{Hash, SipHasher, Hasher}; +use std::mem::size_of; #[derive(Hash)] struct Person { @@ -24,12 +25,30 @@ struct Person { #[derive(Hash)] struct __H__H; #[derive(Hash)] enum Collision<__H> { __H { __H__H: __H } } +#[derive(Hash)] +enum E { A=1, B } + fn hash(t: &T) -> u64 { let mut s = SipHasher::new_with_keys(0, 0); t.hash(&mut s); s.finish() } +struct FakeHasher<'a>(&'a mut Vec); +impl<'a> Hasher for FakeHasher<'a> { + fn finish(&self) -> u64 { + unimplemented!() + } + + fn write(&mut self, bytes: &[u8]) { + self.0.extend(bytes); + } +} + +fn fake_hash(v: &mut Vec, e: E) { + e.hash(&mut FakeHasher(v)); +} + fn main() { let person1 = Person { id: 5, @@ -43,4 +62,11 @@ fn main() { }; assert_eq!(hash(&person1), hash(&person1)); assert!(hash(&person1) != hash(&person2)); + + // test #21714 + let mut va = vec![]; + let mut vb = vec![]; + fake_hash(&mut va, E::A); + fake_hash(&mut vb, E::B); + assert!(va != vb); } From c480b6a75df08cef48190e3c18eab26e99bae58c Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Mon, 7 Mar 2016 13:05:12 -0500 Subject: [PATCH 2/5] fix #21714 by using discriminant_value in #[derive(Hash)] This is the same approach taken in #24270, except that this should not be a breaking change because it only changes the output of hash functions, which nobody should be relying on. --- src/libsyntax_ext/deriving/hash.rs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/libsyntax_ext/deriving/hash.rs b/src/libsyntax_ext/deriving/hash.rs index ba38ebc8607..93686586489 100644 --- a/src/libsyntax_ext/deriving/hash.rs +++ b/src/libsyntax_ext/deriving/hash.rs @@ -12,7 +12,7 @@ use deriving; use deriving::generic::*; use deriving::generic::ty::*; -use syntax::ast::{MetaItem, Expr, Mutability}; +use syntax::ast::{self, MetaItem, Expr, Mutability}; use syntax::codemap::Span; use syntax::ext::base::{ExtCtxt, Annotatable}; use syntax::ext::build::AstBuilder; @@ -81,15 +81,18 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) let fields = match *substr.fields { Struct(_, ref fs) => fs, - EnumMatching(index, variant, ref fs) => { - // Determine the discriminant. We will feed this value to the byte - // iteration function. - let discriminant = match variant.node.disr_expr { - Some(ref d) => d.clone(), - None => cx.expr_usize(trait_span, index) - }; + EnumMatching(_, _, ref fs) => { + let path = cx.std_path(&["intrinsics", "discriminant_value"]); + let call = cx.expr_call_global( + trait_span, path, vec![cx.expr_self(trait_span)]); + let variant_value = cx.expr_block(P(ast::Block { + stmts: vec![], + expr: Some(call), + id: ast::DUMMY_NODE_ID, + rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated), + span: trait_span })); - stmts.push(call_hash(trait_span, discriminant)); + stmts.push(call_hash(trait_span, variant_value)); fs } From b20e748ad88daee81488c1033971eec6b139d291 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Tue, 22 Mar 2016 18:17:57 -0400 Subject: [PATCH 3/5] mk: point target LD_LIBRARY_PATH at current stage --- mk/main.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mk/main.mk b/mk/main.mk index 9df04a6d43e..10743ef2e25 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -493,7 +493,7 @@ endif LD_LIBRARY_PATH_ENV_HOSTDIR$(1)_T_$(2)_H_$(3) := \ $$(CURDIR)/$$(HLIB$(1)_H_$(3)):$$(CFG_LLVM_INST_DIR_$(3))/lib LD_LIBRARY_PATH_ENV_TARGETDIR$(1)_T_$(2)_H_$(3) := \ - $$(CURDIR)/$$(TLIB1_T_$(2)_H_$(CFG_BUILD)) + $$(CURDIR)/$$(TLIB$(1)_T_$(2)_H_$(CFG_BUILD)) HOST_RPATH_VAR$(1)_T_$(2)_H_$(3) := \ $$(LD_LIBRARY_PATH_ENV_NAME$(1)_T_$(2)_H_$(3))=$$(LD_LIBRARY_PATH_ENV_HOSTDIR$(1)_T_$(2)_H_$(3)):$$$$$$(LD_LIBRARY_PATH_ENV_NAME$(1)_T_$(2)_H_$(3)) From dd5972ee354c3b76c1d34df8eb0cbd5e9a6b48e7 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Tue, 22 Mar 2016 18:18:30 -0400 Subject: [PATCH 4/5] mk: add missing dep compiletest=>log --- mk/crates.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mk/crates.mk b/mk/crates.mk index ae40a8e7f70..05018d2a940 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -123,7 +123,7 @@ DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts \ test rustc_lint rustc_front -TOOL_DEPS_compiletest := test getopts +TOOL_DEPS_compiletest := test getopts log TOOL_DEPS_rustdoc := rustdoc TOOL_DEPS_rustc := rustc_driver TOOL_DEPS_rustbook := std rustdoc From 1e67d8a57099eb9d286b5a4adfa798c1b3d437b9 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Thu, 10 Mar 2016 00:31:19 -0500 Subject: [PATCH 5/5] deriving: factor out discriminant_value construction --- src/libsyntax_ext/deriving/generic/mod.rs | 38 +++++++---------------- src/libsyntax_ext/deriving/hash.rs | 15 +++------ src/libsyntax_ext/deriving/mod.rs | 17 ++++++++++ 3 files changed, 33 insertions(+), 37 deletions(-) diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 6dac2f5f9e5..7d452b14dae 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -209,6 +209,8 @@ use syntax::ptr::P; use self::ty::{LifetimeBounds, Path, Ptr, PtrTy, Self_, Ty}; +use deriving; + pub mod ty; pub struct TraitDef<'a> { @@ -381,22 +383,6 @@ fn find_type_parameters(ty: &ast::Ty, ty_param_names: &[ast::Name]) -> Vec P { - let path = cx.std_path(&["intrinsics", "unreachable"]); - let call = cx.expr_call_global( - sp, path, vec![]); - let unreachable = cx.expr_block(P(ast::Block { - stmts: vec![], - expr: Some(call), - id: ast::DUMMY_NODE_ID, - rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated), - span: sp })); - - unreachable -} - impl<'a> TraitDef<'a> { pub fn expand(&self, cx: &mut ExtCtxt, @@ -1279,15 +1265,11 @@ impl<'a> MethodDef<'a> { let mut first_ident = None; for (&ident, self_arg) in vi_idents.iter().zip(&self_args) { - let path = cx.std_path(&["intrinsics", "discriminant_value"]); - let call = cx.expr_call_global( - sp, path, vec![cx.expr_addr_of(sp, self_arg.clone())]); - let variant_value = cx.expr_block(P(ast::Block { - stmts: vec![], - expr: Some(call), - id: ast::DUMMY_NODE_ID, - rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated), - span: sp })); + let self_addr = cx.expr_addr_of(sp, self_arg.clone()); + let variant_value = deriving::call_intrinsic(cx, + sp, + "discriminant_value", + vec![self_addr]); let target_ty = cx.ty_ident(sp, cx.ident_of(target_type_name)); let variant_disr = cx.expr_cast(sp, variant_value, target_ty); @@ -1315,7 +1297,9 @@ impl<'a> MethodDef<'a> { //Since we know that all the arguments will match if we reach the match expression we //add the unreachable intrinsics as the result of the catch all which should help llvm //in optimizing it - match_arms.push(cx.arm(sp, vec![cx.pat_wild(sp)], expr_unreachable_intrinsic(cx, sp))); + match_arms.push(cx.arm(sp, + vec![cx.pat_wild(sp)], + deriving::call_intrinsic(cx, sp, "unreachable", vec![]))); // Final wrinkle: the self_args are expressions that deref // down to desired l-values, but we cannot actually deref @@ -1391,7 +1375,7 @@ impl<'a> MethodDef<'a> { // derive Debug on such a type could here generate code // that needs the feature gate enabled.) - expr_unreachable_intrinsic(cx, sp) + deriving::call_intrinsic(cx, sp, "unreachable", vec![]) } else { diff --git a/src/libsyntax_ext/deriving/hash.rs b/src/libsyntax_ext/deriving/hash.rs index 93686586489..c37ae116d37 100644 --- a/src/libsyntax_ext/deriving/hash.rs +++ b/src/libsyntax_ext/deriving/hash.rs @@ -12,7 +12,7 @@ use deriving; use deriving::generic::*; use deriving::generic::ty::*; -use syntax::ast::{self, MetaItem, Expr, Mutability}; +use syntax::ast::{MetaItem, Expr, Mutability}; use syntax::codemap::Span; use syntax::ext::base::{ExtCtxt, Annotatable}; use syntax::ext::build::AstBuilder; @@ -82,15 +82,10 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) let fields = match *substr.fields { Struct(_, ref fs) => fs, EnumMatching(_, _, ref fs) => { - let path = cx.std_path(&["intrinsics", "discriminant_value"]); - let call = cx.expr_call_global( - trait_span, path, vec![cx.expr_self(trait_span)]); - let variant_value = cx.expr_block(P(ast::Block { - stmts: vec![], - expr: Some(call), - id: ast::DUMMY_NODE_ID, - rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated), - span: trait_span })); + let variant_value = deriving::call_intrinsic(cx, + trait_span, + "discriminant_value", + vec![cx.expr_self(trait_span)]); stmts.push(call_hash(trait_span, variant_value)); diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index 1774167e830..92a141fb4ec 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -18,6 +18,7 @@ use syntax::ext::build::AstBuilder; use syntax::feature_gate; use syntax::codemap::Span; use syntax::parse::token::{intern, intern_and_get_ident}; +use syntax::ptr::P; macro_rules! pathvec { ($($x:ident)::+) => ( @@ -271,3 +272,19 @@ fn hygienic_type_parameter(item: &Annotatable, base: &str) -> String { typaram } +/// Constructs an expression that calls an intrinsic +fn call_intrinsic(cx: &ExtCtxt, + span: Span, + intrinsic: &str, + args: Vec>) -> P { + let path = cx.std_path(&["intrinsics", intrinsic]); + let call = cx.expr_call_global(span, path, args); + + cx.expr_block(P(ast::Block { + stmts: vec![], + expr: Some(call), + id: ast::DUMMY_NODE_ID, + rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated), + span: span })) +} +