From 42a5a065dbfd5bac1195ab2ce9d348ac3cc0eb54 Mon Sep 17 00:00:00 2001 From: Christopher Date: Sun, 25 Sep 2016 16:24:23 -0500 Subject: [PATCH 01/26] Touch up formatting for variance README.md There were a few places that need extra indentation to register as a code block. --- src/librustc_typeck/variance/README.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/librustc_typeck/variance/README.md b/src/librustc_typeck/variance/README.md index 94d1ff91c37b5..ac785e4058bde 100644 --- a/src/librustc_typeck/variance/README.md +++ b/src/librustc_typeck/variance/README.md @@ -1,3 +1,5 @@ +## Variance of type and lifetime parameters + This file infers the variance of type and lifetime parameters. The algorithm is taken from Section 4 of the paper "Taming the Wildcards: Combining Definition- and Use-Site Variance" published in PLDI'11 and @@ -52,11 +54,11 @@ These indicate that (1) the variance of A must be at most covariant; variance of C must be at most covariant *and* contravariant. All of these results are based on a variance lattice defined as follows: - * Top (bivariant) - - + - o Bottom (invariant) + * Top (bivariant) + - + + o Bottom (invariant) -Based on this lattice, the solution V(A)=+, V(B)=-, V(C)=o is the +Based on this lattice, the solution `V(A)=+`, `V(B)=-`, `V(C)=o` is the optimal solution. Note that there is always a naive solution which just declares all variables to be invariant. @@ -68,11 +70,11 @@ take the form: V(X) <= Term Term := + | - | * | o | V(X) | Term x Term -Here the notation V(X) indicates the variance of a type/region +Here the notation `V(X)` indicates the variance of a type/region parameter `X` with respect to its defining class. `Term x Term` represents the "variance transform" as defined in the paper: - If the variance of a type variable `X` in type expression `E` is `V2` +> If the variance of a type variable `X` in type expression `E` is `V2` and the definition-site variance of the [corresponding] type parameter of a class `C` is `V1`, then the variance of `X` in the type expression `C` is `V3 = V1.xform(V2)`. @@ -267,7 +269,7 @@ expressions -- must be invariant with respect to all of their inputs. To see why this makes sense, consider what subtyping for a trait reference means: - <: + <: means that if I know that `T as Trait`, I also know that `U as Trait`. Moreover, if you think of it as dictionary passing style, @@ -291,9 +293,9 @@ impl Identity for T { type Out = T; ... } Now if I have `<&'static () as Identity>::Out`, this can be validly derived as `&'a ()` for any `'a`: - <&'a () as Identity> <: <&'static () as Identity> - if &'static () < : &'a () -- Identity is contravariant in Self - if 'static : 'a -- Subtyping rules for relations + <&'a () as Identity> <: <&'static () as Identity> + if &'static () < : &'a () -- Identity is contravariant in Self + if 'static : 'a -- Subtyping rules for relations This change otoh means that `<'static () as Identity>::Out` is always `&'static ()` (which might then be upcast to `'a ()`, From cb22364f3225293bd3e3f7d398cb81f3d1c5e1d7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 2 Oct 2016 15:45:06 +0200 Subject: [PATCH 02/26] Merge E0002 into E0004 --- src/librustc_const_eval/check_match.rs | 22 +++++++++++++------ .../compile-fail/{E0002.rs => E0004-2.rs} | 2 +- 2 files changed, 16 insertions(+), 8 deletions(-) rename src/test/compile-fail/{E0002.rs => E0004-2.rs} (94%) diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 5178ef65cf6a4..dd1f313f9af00 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -25,8 +25,10 @@ use rustc::middle::expr_use_visitor::{LoanCause, MutateMode}; use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization::{cmt}; use rustc::hir::pat_util::*; +use rustc::session::Session; use rustc::traits::Reveal; use rustc::ty::{self, Ty, TyCtxt}; +use rustc_errors::DiagnosticBuilder; use std::cmp::Ordering; use std::fmt; use std::iter::{FromIterator, IntoIterator, repeat}; @@ -163,6 +165,10 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { tcx.sess.abort_if_errors(); } +fn create_e0004<'a>(sess: &'a Session, sp: Span, error_message: String) -> DiagnosticBuilder<'a> { + struct_span_err!(sess, sp, E0004, "{}", &error_message) +} + fn check_expr(cx: &mut MatchCheckCtxt, ex: &hir::Expr) { intravisit::walk_expr(cx, ex); match ex.node { @@ -215,9 +221,10 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &hir::Expr) { if inlined_arms.is_empty() { if !pat_ty.is_uninhabited(cx.tcx) { // We know the type is inhabited, so this must be wrong - let mut err = struct_span_err!(cx.tcx.sess, ex.span, E0002, - "non-exhaustive patterns: type {} is non-empty", - pat_ty); + let mut err = create_e0004(cx.tcx.sess, ex.span, + format!("non-exhaustive patterns: type {} \ + is non-empty", + pat_ty)); span_help!(&mut err, ex.span, "Please ensure that all possible cases are being handled; \ possibly adding wildcards or more match arms."); @@ -438,10 +445,11 @@ fn check_exhaustive<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, 1 => format!("pattern {} not covered", joined_patterns), _ => format!("patterns {} not covered", joined_patterns) }; - struct_span_err!(cx.tcx.sess, sp, E0004, - "non-exhaustive patterns: {} not covered", - joined_patterns - ).span_label(sp, &label_text).emit(); + create_e0004(cx.tcx.sess, sp, + format!("non-exhaustive patterns: {} not covered", + joined_patterns)) + .span_label(sp, &label_text) + .emit(); }, } } diff --git a/src/test/compile-fail/E0002.rs b/src/test/compile-fail/E0004-2.rs similarity index 94% rename from src/test/compile-fail/E0002.rs rename to src/test/compile-fail/E0004-2.rs index 0e94c9595d82c..824b86cfa8312 100644 --- a/src/test/compile-fail/E0002.rs +++ b/src/test/compile-fail/E0004-2.rs @@ -11,5 +11,5 @@ fn main() { let x = Some(1); - match x { } //~ ERROR E0002 + match x { } //~ ERROR E0004 } From f320004a1b17d14f231410dc8238e425751539f0 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 3 Oct 2016 12:28:11 -0400 Subject: [PATCH 03/26] incr.comp.: Add test case for dependency graph of type aliases. --- src/test/compile-fail/dep-graph-type-alias.rs | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 src/test/compile-fail/dep-graph-type-alias.rs diff --git a/src/test/compile-fail/dep-graph-type-alias.rs b/src/test/compile-fail/dep-graph-type-alias.rs new file mode 100644 index 0000000000000..80cc9e71c7ab4 --- /dev/null +++ b/src/test/compile-fail/dep-graph-type-alias.rs @@ -0,0 +1,56 @@ +// 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. + + +// Test that changing what a `type` points to does not go unnoticed. + +// compile-flags: -Z query-dep-graph + +#![feature(rustc_attrs)] +#![allow(dead_code)] +#![allow(unused_variables)] + +fn main() { } + + +#[rustc_if_this_changed] +type TypeAlias = u32; + +#[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK +struct Struct { + x: TypeAlias, + y: u32 +} + +#[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK +enum Enum { + Variant1(TypeAlias), + Variant2(i32) +} + +#[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK +trait Trait { + fn method(&self, _: TypeAlias); +} + +struct SomeType; + +#[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK +impl SomeType { + fn method(&self, _: TypeAlias) {} +} + +#[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK +type TypeAlias2 = TypeAlias; + +#[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK +fn function(_: TypeAlias) { + +} From ae51ccfa771ffdfae63ad2a5a9deecf9712833d8 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 4 Oct 2016 16:23:01 +0300 Subject: [PATCH 04/26] SimplifyCfg: simplify the start block --- src/librustc_mir/transform/simplify_cfg.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc_mir/transform/simplify_cfg.rs b/src/librustc_mir/transform/simplify_cfg.rs index 8e1b7b44976f3..228fa46884130 100644 --- a/src/librustc_mir/transform/simplify_cfg.rs +++ b/src/librustc_mir/transform/simplify_cfg.rs @@ -50,6 +50,7 @@ impl<'a> SimplifyCfg<'a> { impl<'l, 'tcx> MirPass<'tcx> for SimplifyCfg<'l> { fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) { + debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, mir); CfgSimplifier::new(mir).simplify(); remove_dead_blocks(mir); @@ -78,6 +79,8 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> { // we can't use mir.predecessors() here because that counts // dead blocks, which we don't want to. + pred_count[START_BLOCK] = 1; + for (_, data) in traversal::preorder(mir) { if let Some(ref term) = data.terminator { for &tgt in term.successors().iter() { From 44ac0160cef4824082f738ce5d2b847b0b8f88ea Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 4 Oct 2016 16:27:27 +0300 Subject: [PATCH 05/26] SimplifyCfg: don't incref target when collapsing a goto with 1 pred --- src/librustc_mir/transform/simplify_cfg.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/transform/simplify_cfg.rs b/src/librustc_mir/transform/simplify_cfg.rs index 228fa46884130..ca8556496fa07 100644 --- a/src/librustc_mir/transform/simplify_cfg.rs +++ b/src/librustc_mir/transform/simplify_cfg.rs @@ -160,8 +160,16 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> { debug!("collapsing goto chain from {:?} to {:?}", *start, target); *changed |= *start != target; - self.pred_count[target] += 1; - self.pred_count[*start] -= 1; + + if self.pred_count[*start] == 1 { + // This is the last reference to *start, so the pred-count to + // to target is moved into the current block. + self.pred_count[*start] = 0; + } else { + self.pred_count[target] += 1; + self.pred_count[*start] -= 1; + } + *start = target; } From 29212ecdc9867fe90cca637374c1c73eb2e43e6b Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 4 Oct 2016 12:00:15 -0400 Subject: [PATCH 06/26] Assign internal linkage to autogenerated FnOnce::call_once() instances. --- src/librustc_trans/closure.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_trans/closure.rs b/src/librustc_trans/closure.rs index c0692e8085fc2..d506b47407d7d 100644 --- a/src/librustc_trans/closure.rs +++ b/src/librustc_trans/closure.rs @@ -257,7 +257,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( // Create the by-value helper. let function_name = method_instance.symbol_name(ccx.shared()); - let lloncefn = declare::declare_fn(ccx, &function_name, llonce_fn_ty); + let lloncefn = declare::define_internal_fn(ccx, &function_name, llonce_fn_ty); attributes::set_frame_pointer_elimination(ccx, lloncefn); let (block_arena, fcx): (TypedArena<_>, FunctionContext); From 457019967bd2be3ce20b71e6d0beb3897b0a10eb Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 4 Oct 2016 12:02:19 -0400 Subject: [PATCH 07/26] Add symbol hash to trans::partitioning debug output. --- src/librustc_trans/partitioning.rs | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index 65615e6b6440c..0f76d358e78f1 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -266,14 +266,14 @@ pub fn partition<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>, let mut initial_partitioning = place_root_translation_items(scx, trans_items); - debug_dump(tcx, "INITIAL PARTITONING:", initial_partitioning.codegen_units.iter()); + debug_dump(scx, "INITIAL PARTITONING:", initial_partitioning.codegen_units.iter()); // If the partitioning should produce a fixed count of codegen units, merge // until that count is reached. if let PartitioningStrategy::FixedUnitCount(count) = strategy { merge_codegen_units(&mut initial_partitioning, count, &tcx.crate_name[..]); - debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter()); + debug_dump(scx, "POST MERGING:", initial_partitioning.codegen_units.iter()); } // In the next step, we use the inlining map to determine which addtional @@ -283,7 +283,7 @@ pub fn partition<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>, let post_inlining = place_inlined_translation_items(initial_partitioning, inlining_map); - debug_dump(tcx, "POST INLINING:", post_inlining.0.iter()); + debug_dump(scx, "POST INLINING:", post_inlining.0.iter()); // Finally, sort by codegen unit name, so that we get deterministic results let mut result = post_inlining.0; @@ -551,7 +551,7 @@ fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString index)[..]) } -fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, +fn debug_dump<'a, 'b, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>, label: &str, cgus: I) where I: Iterator>, @@ -560,10 +560,21 @@ fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if cfg!(debug_assertions) { debug!("{}", label); for cgu in cgus { + let symbol_map = SymbolMap::build(scx, cgu.items + .iter() + .map(|(&trans_item, _)| trans_item)); debug!("CodegenUnit {}:", cgu.name); for (trans_item, linkage) in &cgu.items { - debug!(" - {} [{:?}]", trans_item.to_string(tcx), linkage); + let symbol_name = symbol_map.get_or_compute(scx, *trans_item); + let symbol_hash_start = symbol_name.rfind('h'); + let symbol_hash = symbol_hash_start.map(|i| &symbol_name[i ..]) + .unwrap_or(""); + + debug!(" - {} [{:?}] [{}]", + trans_item.to_string(scx.tcx()), + linkage, + symbol_hash); } debug!(""); From cd7a04cadcc046014bec5b9eea0abe06761f1e7f Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Tue, 4 Oct 2016 18:39:28 +0100 Subject: [PATCH 08/26] rustdoc: Fix missing *mut T impl `impl *mut T` is currently missing from https://doc.rust-lang.org/nightly/std/primitive.pointer.html and this adds it back. --- src/librustdoc/clean/inline.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 208a5d810922a..d39d093361692 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -301,8 +301,8 @@ pub fn build_impls<'a, 'tcx>(cx: &DocContext, tcx.lang_items.char_impl(), tcx.lang_items.str_impl(), tcx.lang_items.slice_impl(), - tcx.lang_items.slice_impl(), - tcx.lang_items.const_ptr_impl() + tcx.lang_items.const_ptr_impl(), + tcx.lang_items.mut_ptr_impl(), ]; for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) { From bfdf437f37c3cffc4f9ba01f248d2e08399b4280 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 4 Oct 2016 20:43:43 +0300 Subject: [PATCH 09/26] update tests --- src/test/mir-opt/deaggregator_test.rs | 4 ++-- src/test/mir-opt/deaggregator_test_enum.rs | 4 ++-- src/test/mir-opt/storage_ranges.rs | 4 ---- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/test/mir-opt/deaggregator_test.rs b/src/test/mir-opt/deaggregator_test.rs index 3304a66773ad2..f136d74fa517d 100644 --- a/src/test/mir-opt/deaggregator_test.rs +++ b/src/test/mir-opt/deaggregator_test.rs @@ -26,7 +26,7 @@ fn main() {} // _2 = _1; // _3 = _2; // _0 = Baz { x: _3, y: const F32(0), z: const false }; -// goto -> bb1; +// return; // } // END rustc.node13.Deaggregator.before.mir // START rustc.node13.Deaggregator.after.mir @@ -36,6 +36,6 @@ fn main() {} // (_0.0: usize) = _3; // (_0.1: f32) = const F32(0); // (_0.2: bool) = const false; -// goto -> bb1; +// return; // } // END rustc.node13.Deaggregator.after.mir diff --git a/src/test/mir-opt/deaggregator_test_enum.rs b/src/test/mir-opt/deaggregator_test_enum.rs index a6f12886f5527..25fa0e90835c6 100644 --- a/src/test/mir-opt/deaggregator_test_enum.rs +++ b/src/test/mir-opt/deaggregator_test_enum.rs @@ -31,7 +31,7 @@ fn main() { // _2 = _1; // _3 = _2; // _0 = Baz::Foo { x: _3 }; -// goto -> bb1; +// return; // } // END rustc.node10.Deaggregator.before.mir // START rustc.node10.Deaggregator.after.mir @@ -40,6 +40,6 @@ fn main() { // _3 = _2; // ((_0 as Foo).0: usize) = _3; // discriminant(_0) = 1; -// goto -> bb1; +// return; // } // END rustc.node10.Deaggregator.after.mir diff --git a/src/test/mir-opt/storage_ranges.rs b/src/test/mir-opt/storage_ranges.rs index 3885b233fd296..933bfa8df2ec2 100644 --- a/src/test/mir-opt/storage_ranges.rs +++ b/src/test/mir-opt/storage_ranges.rs @@ -38,10 +38,6 @@ fn main() { // _0 = (); // StorageDead(_6); // StorageDead(_1); -// goto -> bb1; -// } -// -// bb1: { // return; // } // END rustc.node4.TypeckMir.before.mir From 2d34ad04ef6a2a5b69da24ed6b7b2c9f38e4678f Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 4 Oct 2016 16:15:37 -0400 Subject: [PATCH 10/26] trans: Make sure that each FnOnce shim is only translated once. --- src/librustc_trans/closure.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/librustc_trans/closure.rs b/src/librustc_trans/closure.rs index d506b47407d7d..c87497384ad6a 100644 --- a/src/librustc_trans/closure.rs +++ b/src/librustc_trans/closure.rs @@ -217,6 +217,10 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( llreffn: ValueRef) -> ValueRef { + if let Some(&llfn) = ccx.instances().borrow().get(&method_instance) { + return llfn; + } + debug!("trans_fn_once_adapter_shim(closure_def_id={:?}, substs={:?}, llreffn={:?})", closure_def_id, substs, Value(llreffn)); @@ -312,5 +316,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( fcx.finish(bcx, DebugLoc::None); + ccx.instances().borrow_mut().insert(method_instance, lloncefn); + lloncefn } From 4922abfbd26c74a4bfb2d8ab5077eda7938be457 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Tue, 4 Oct 2016 15:41:26 -0500 Subject: [PATCH 11/26] Haiku: Fix IPv6 target_os check --- src/libstd/sys/common/net.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs index 18280e497db1d..609e43e1211bc 100644 --- a/src/libstd/sys/common/net.rs +++ b/src/libstd/sys/common/net.rs @@ -29,7 +29,7 @@ use sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP; #[cfg(not(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", target_os = "openbsd", target_os = "netbsd", - target_os = "solaris", taget_os = "haiku")))] + target_os = "solaris", target_os = "haiku")))] use sys::net::netc::IPV6_ADD_MEMBERSHIP; #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", From 7bbfac60e3cf502c34809a3572e108ca4dde2ef5 Mon Sep 17 00:00:00 2001 From: Eric Roshan-Eisner Date: Tue, 4 Oct 2016 14:33:16 -0700 Subject: [PATCH 12/26] update sip.rs for new intrinsics and defaults --- src/libcore/hash/sip.rs | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index bf138a45de866..fc74669635934 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -17,6 +17,9 @@ use ptr; /// An implementation of SipHash 1-3. /// +/// This is currently the default hashing function used by standard library +/// (eg. `collections::HashMap` uses it by default). +/// /// See: https://131002.net/siphash/ #[unstable(feature = "sip_hash_13", issue = "34767")] #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] @@ -39,9 +42,6 @@ pub struct SipHasher24 { /// /// See: https://131002.net/siphash/ /// -/// This is currently the default hashing function used by standard library -/// (eg. `collections::HashMap` uses it by default). -/// /// SipHash is a general-purpose hashing function: it runs at a good /// speed (competitive with Spooky and City) and permits strong _keyed_ /// hashing. This lets you key your hashtables from a strong RNG, such as @@ -117,23 +117,18 @@ unsafe fn load_u64_le(buf: &[u8], i: usize) -> u64 { data.to_le() } -macro_rules! rotl { - ($x:expr, $b:expr) => - (($x << $b) | ($x >> (64_i32.wrapping_sub($b)))) -} - macro_rules! compress { ($state:expr) => ({ compress!($state.v0, $state.v1, $state.v2, $state.v3) }); ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => ({ - $v0 = $v0.wrapping_add($v1); $v1 = rotl!($v1, 13); $v1 ^= $v0; - $v0 = rotl!($v0, 32); - $v2 = $v2.wrapping_add($v3); $v3 = rotl!($v3, 16); $v3 ^= $v2; - $v0 = $v0.wrapping_add($v3); $v3 = rotl!($v3, 21); $v3 ^= $v0; - $v2 = $v2.wrapping_add($v1); $v1 = rotl!($v1, 17); $v1 ^= $v2; - $v2 = rotl!($v2, 32); + $v0 = $v0.wrapping_add($v1); $v1 = $v1.rotate_left(13); $v1 ^= $v0; + $v0 = $v0.rotate_left(32); + $v2 = $v2.wrapping_add($v3); $v3 = $v3.rotate_left(16); $v3 ^= $v2; + $v0 = $v0.wrapping_add($v3); $v3 = $v3.rotate_left(21); $v3 ^= $v0; + $v2 = $v2.wrapping_add($v1); $v1 = $v1.rotate_left(17); $v1 ^= $v2; + $v2 = $v2.rotate_left(32); }); } From 335d393114da99c1716eb1dfb0af8c4efcb51b8a Mon Sep 17 00:00:00 2001 From: Nikhil Shagrithaya Date: Tue, 4 Oct 2016 17:30:22 +0000 Subject: [PATCH 13/26] Minor modifications in concurrency section of the Rust book --- src/doc/book/concurrency.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/book/concurrency.md b/src/doc/book/concurrency.md index a783650f8ea2d..41d8345b72094 100644 --- a/src/doc/book/concurrency.md +++ b/src/doc/book/concurrency.md @@ -4,7 +4,7 @@ Concurrency and parallelism are incredibly important topics in computer science, and are also a hot topic in industry today. Computers are gaining more and more cores, yet many programmers aren't prepared to fully utilize them. -Rust's memory safety features also apply to its concurrency story too. Even +Rust's memory safety features also apply to its concurrency story. Even concurrent Rust programs must be memory safe, having no data races. Rust's type system is up to the task, and gives you powerful ways to reason about concurrent code at compile time. @@ -281,8 +281,8 @@ And... still gives us an error. ``` `Arc` by default has immutable contents. It allows the _sharing_ of data -between threads, but shared mutable data is unsafe and when threads are -involved can cause data races! +between threads, but shared mutable data is unsafe—and when threads are +involved—can cause data races! Usually when we wish to make something in an immutable position mutable, we use From 51ef2b315b53717620674cb8b1c874de25c146a7 Mon Sep 17 00:00:00 2001 From: Nick Stevens Date: Tue, 4 Oct 2016 20:17:53 -0500 Subject: [PATCH 14/26] rustbuild: Fix bug preventing per-target musl-root In #36292, support was added to target musl libc for ARM targets using rustbuild. Specifically, that change allowed the addition of per-target "musl-root" options in the rustbuild config.toml so that multiple targets depending on musl could be built. However, that implementation contained a couple of omissions: the musl-root option was added to the config, but was never added to the TOML parsing, and therefore was not actually being loaded from config.toml. This commit rectifies that and allows successful building of musl-based ARM targets. --- src/bootstrap/compile.rs | 6 +++--- src/bootstrap/config.rs | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 16dbcae99fa1d..418c3a48ed348 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -90,16 +90,16 @@ pub fn std_link(build: &Build, add_to_sysroot(&out_dir, &libdir); if target.contains("musl") && !target.contains("mips") { - copy_musl_third_party_objects(build, &libdir); + copy_musl_third_party_objects(build, target, &libdir); } } /// Copies the crt(1,i,n).o startup objects /// /// Only required for musl targets that statically link to libc -fn copy_musl_third_party_objects(build: &Build, into: &Path) { +fn copy_musl_third_party_objects(build: &Build, target: &str, into: &Path) { for &obj in &["crt1.o", "crti.o", "crtn.o"] { - copy(&build.config.musl_root.as_ref().unwrap().join("lib").join(obj), &into.join(obj)); + copy(&build.musl_root(target).unwrap().join("lib").join(obj), &into.join(obj)); } } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index a8434c3efb358..69bd7a769910c 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -158,6 +158,7 @@ struct TomlTarget { cc: Option, cxx: Option, android_ndk: Option, + musl_root: Option, } impl Config { @@ -268,6 +269,7 @@ impl Config { } target.cxx = cfg.cxx.clone().map(PathBuf::from); target.cc = cfg.cc.clone().map(PathBuf::from); + target.musl_root = cfg.musl_root.clone().map(PathBuf::from); config.target_config.insert(triple.clone(), target); } From 7937f6ccdea38fd76a9ef98b41742d9318e25e4b Mon Sep 17 00:00:00 2001 From: Nick Stevens Date: Tue, 4 Oct 2016 20:22:51 -0500 Subject: [PATCH 15/26] rustbuild: Fix panic message when musl-root not set The previous panic message delivered when a musl target was specified but musl-root was not specified incorrectly instructed the user to add the musl-root key to the "build" section of config.toml. The key actually needs to be added to the "rust" section. --- src/bootstrap/sanity.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index c4e6399c2c36d..969cd70fd57eb 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -146,8 +146,8 @@ pub fn check(build: &mut Build) { } } None => { - panic!("when targeting MUSL either the build.musl-root \ - option or the target.$TARGET.musl-root one must \ + panic!("when targeting MUSL either the rust.musl-root \ + option or the target.$TARGET.musl-root option must \ be specified in config.toml") } } From 9081c003d32f0ae7cf5d5df394e92721ec559bcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Border=C3=A9?= Date: Mon, 3 Oct 2016 20:28:44 +0200 Subject: [PATCH 16/26] ICH - Add test cases for function interfaces --- .../incremental/hashes/function_interfaces.rs | 382 ++++++++++++++++++ 1 file changed, 382 insertions(+) create mode 100644 src/test/incremental/hashes/function_interfaces.rs diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs new file mode 100644 index 0000000000000..50f3729f1c652 --- /dev/null +++ b/src/test/incremental/hashes/function_interfaces.rs @@ -0,0 +1,382 @@ +// 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 tests the incremental compilation hash (ICH) implementation +// for function interfaces. + +// The general pattern followed here is: Change one thing between rev1 and rev2 +// and make sure that the hash has changed, then change nothing between rev2 and +// rev3 and make sure that the hash has not changed. + +// must-compile-successfully +// revisions: cfail1 cfail2 cfail3 +// compile-flags: -Z query-dep-graph + + +#![allow(warnings)] +#![feature(conservative_impl_trait)] +#![feature(intrinsics)] +#![feature(linkage)] +#![feature(rustc_attrs)] +#![crate_type="rlib"] + + +// Add Parameter --------------------------------------------------------------- + +#[cfg(cfail1)] +fn add_parameter() {} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_parameter(p: i32) {} + + +// Add Return Type ------------------------------------------------------------- + +#[cfg(cfail1)] +fn add_return_type() {} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_return_type() -> () {} + + +// Change Parameter Type ------------------------------------------------------- + +#[cfg(cfail1)] +fn type_of_parameter(p: i32) {} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn type_of_parameter(p: i64) {} + + +// Change Parameter Type Reference --------------------------------------------- + +#[cfg(cfail1)] +fn type_of_parameter_ref(p: &i32) {} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn type_of_parameter_ref(p: &mut i32) {} + + +// Change Parameter Order ------------------------------------------------------ + +#[cfg(cfail1)] +fn order_of_parameters(p1: i32, p2: i32) {} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn order_of_parameters(p2: i32, p1: i32) {} + + +// Unsafe ---------------------------------------------------------------------- + +#[cfg(cfail1)] +fn make_unsafe() {} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +unsafe fn make_unsafe() {} + + +// Extern ---------------------------------------------------------------------- + +#[cfg(cfail1)] +fn make_extern() {} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +extern fn make_extern() {} + + +// Extern C Extern Rust-Intrinsic ---------------------------------------------- + +#[cfg(cfail1)] +extern "C" fn make_intrinsic() {} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +extern "rust-intrinsic" fn make_intrinsic() {} + + +// Type Parameter -------------------------------------------------------------- + +#[cfg(cfail1)] +fn type_parameter() {} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn type_parameter() {} + + +// Lifetime Parameter ---------------------------------------------------------- + +#[cfg(cfail1)] +fn lifetime_parameter() {} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn lifetime_parameter<'a>() {} + + +// Trait Bound ----------------------------------------------------------------- + +#[cfg(cfail1)] +fn trait_bound() {} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn trait_bound() {} + + +// Builtin Bound --------------------------------------------------------------- + +#[cfg(cfail1)] +fn builtin_bound() {} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn builtin_bound() {} + + +// Lifetime Bound -------------------------------------------------------------- + +#[cfg(cfail1)] +fn lifetime_bound() {} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn lifetime_bound<'a, T: 'a>() {} + + +// Second Trait Bound ---------------------------------------------------------- + +#[cfg(cfail1)] +fn second_trait_bound() {} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn second_trait_bound() {} + + +// Second Builtin Bound -------------------------------------------------------- + +#[cfg(cfail1)] +fn second_builtin_bound() {} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn second_builtin_bound() {} + + +// Second Lifetime Bound ------------------------------------------------------- + +#[cfg(cfail1)] +fn second_lifetime_bound<'a, T: 'a>() {} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {} + + +// Inline ---------------------------------------------------------------------- + +#[cfg(cfail1)] +fn inline() {} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +#[inline] +fn inline() {} + + +// Inline Never ---------------------------------------------------------------- + +#[cfg(cfail1)] +fn inline_never() {} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +#[inline(never)] +fn inline_never() {} + + +// No Mangle ------------------------------------------------------------------- + +#[cfg(cfail1)] +fn no_mangle() {} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +#[no_mangle] +fn no_mangle() {} + + +// Linkage --------------------------------------------------------------------- + +#[cfg(cfail1)] +fn linkage() {} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +#[linkage] +fn linkage() {} + + +// Return Impl Trait ----------------------------------------------------------- + +#[cfg(cfail1)] +fn return_impl_trait() -> i32 { + 0 +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn return_impl_trait() -> impl Clone { + 0 +} + + +// Change Return Type Indirectly ----------------------------------------------- + +struct ReferencedType1; +struct ReferencedType2; + +mod change_return_type_indirectly { + #[cfg(cfail1)] + use super::ReferencedType1 as ReturnType; + #[cfg(not(cfail1))] + use super::ReferencedType2 as ReturnType; + + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + fn indirect_return_type() -> ReturnType { + ReturnType {} + } +} + + +// Change Parameter Type Indirectly -------------------------------------------- + +mod change_parameter_type_indirectly { + #[cfg(cfail1)] + use super::ReferencedType1 as ParameterType; + #[cfg(not(cfail1))] + use super::ReferencedType2 as ParameterType; + + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + fn indirect_parameter_type(p: ParameterType) {} +} + + +// Change Trait Bound Indirectly ----------------------------------------------- + +trait ReferencedTrait1 {} +trait ReferencedTrait2 {} + +mod change_trait_bound_indirectly { + #[cfg(cfail1)] + use super::ReferencedTrait1 as Trait; + #[cfg(not(cfail1))] + use super::ReferencedTrait2 as Trait; + + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + fn indirect_trait_bound(p: T) {} +} + + +// Change Trait Bound Indirectly In Where Clause ------------------------------- + +mod change_trait_bound_indirectly_in_where_clause { + #[cfg(cfail1)] + use super::ReferencedTrait1 as Trait; + #[cfg(not(cfail1))] + use super::ReferencedTrait2 as Trait; + + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + fn indirect_trait_bound_where(p: T) where T: Trait {} +} From e051eb32c2ed802a51d02c33cec6c8fe07516918 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Border=C3=A9?= Date: Tue, 4 Oct 2016 23:25:00 +0200 Subject: [PATCH 17/26] ICH - Include omitted elements in inc. comp. hash #36914 --- .../calculate_svh/svh_visitor.rs | 162 ++++++++++++++++-- 1 file changed, 146 insertions(+), 16 deletions(-) diff --git a/src/librustc_incremental/calculate_svh/svh_visitor.rs b/src/librustc_incremental/calculate_svh/svh_visitor.rs index 393f99b3eb832..603a7fc40eb4f 100644 --- a/src/librustc_incremental/calculate_svh/svh_visitor.rs +++ b/src/librustc_incremental/calculate_svh/svh_visitor.rs @@ -15,6 +15,11 @@ use self::SawExprComponent::*; use self::SawAbiComponent::*; +use self::SawItemComponent::*; +use self::SawPatComponent::*; +use self::SawTyComponent::*; +use self::SawTraitOrImplItemComponent::*; +use syntax::abi::Abi; use syntax::ast::{self, Name, NodeId}; use syntax::parse::token; use syntax_pos::{Span, NO_EXPANSION, COMMAND_LINE_EXPN, BytePos}; @@ -155,11 +160,11 @@ enum SawAbiComponent<'a> { SawMod, SawForeignItem, - SawItem, - SawTy, + SawItem(SawItemComponent), + SawTy(SawTyComponent), SawGenerics, - SawTraitItem, - SawImplItem, + SawTraitItem(SawTraitOrImplItemComponent), + SawImplItem(SawTraitOrImplItemComponent), SawStructField, SawVariant, SawPath(bool), @@ -167,7 +172,7 @@ enum SawAbiComponent<'a> { SawPathParameters, SawPathListItem, SawBlock, - SawPat, + SawPat(SawPatComponent), SawLocal, SawArm, SawExpr(SawExprComponent<'a>), @@ -198,6 +203,9 @@ enum SawAbiComponent<'a> { /// because the SVH is just a developer convenience; there is no /// guarantee of collision-freedom, hash collisions are just /// (hopefully) unlikely.) +/// +/// The xxxComponent enums and saw_xxx functions for Item, Pat, +/// Ty, TraitItem and ImplItem follow the same methodology. #[derive(Hash)] enum SawExprComponent<'a> { @@ -267,6 +275,134 @@ fn saw_expr<'a>(node: &'a Expr_) -> SawExprComponent<'a> { } } +#[derive(Hash)] +enum SawItemComponent { + SawItemExternCrate, + SawItemUse, + SawItemStatic(Mutability), + SawItemConst, + SawItemFn(Unsafety, Constness, Abi), + SawItemMod, + SawItemForeignMod, + SawItemTy, + SawItemEnum, + SawItemStruct, + SawItemUnion, + SawItemTrait(Unsafety), + SawItemDefaultImpl(Unsafety), + SawItemImpl(Unsafety, ImplPolarity) +} + +fn saw_item(node: &Item_) -> SawItemComponent { + match *node { + ItemExternCrate(..) => SawItemExternCrate, + ItemUse(..) => SawItemUse, + ItemStatic(_, mutability, _) => SawItemStatic(mutability), + ItemConst(..) =>SawItemConst, + ItemFn(_, unsafety, constness, abi, _, _) => SawItemFn(unsafety, constness, abi), + ItemMod(..) => SawItemMod, + ItemForeignMod(..) => SawItemForeignMod, + ItemTy(..) => SawItemTy, + ItemEnum(..) => SawItemEnum, + ItemStruct(..) => SawItemStruct, + ItemUnion(..) => SawItemUnion, + ItemTrait(unsafety, ..) => SawItemTrait(unsafety), + ItemDefaultImpl(unsafety, _) => SawItemDefaultImpl(unsafety), + ItemImpl(unsafety, implpolarity, ..) => SawItemImpl(unsafety, implpolarity) + } +} + +#[derive(Hash)] +enum SawPatComponent { + SawPatWild, + SawPatBinding(BindingMode), + SawPatStruct, + SawPatTupleStruct, + SawPatPath, + SawPatTuple, + SawPatBox, + SawPatRef(Mutability), + SawPatLit, + SawPatRange, + SawPathVec +} + +fn saw_pat(node: &PatKind) -> SawPatComponent { + match *node { + PatKind::Wild => SawPatWild, + PatKind::Binding(bindingmode, ..) => SawPatBinding(bindingmode), + PatKind::Struct(..) => SawPatStruct, + PatKind::TupleStruct(..) => SawPatTupleStruct, + PatKind::Path(..) => SawPatPath, + PatKind::Tuple(..) => SawPatTuple, + PatKind::Box(..) => SawPatBox, + PatKind::Ref(_, mutability) => SawPatRef(mutability), + PatKind::Lit(..) => SawPatLit, + PatKind::Range(..) => SawPatRange, + PatKind::Vec(..) => SawPathVec + } +} + +#[derive(Hash)] +enum SawTyComponent { + SawTyVec, + SawTyFixedLengthVec, + SawTyPtr(Mutability), + SawTyRptr(Mutability), + SawTyBareFn, + SawTyNever, + SawTyTup, + SawTyPath, + SawTyObjectSum, + SawTyPolyTraitRef, + SawTyImplTrait, + SawTyTypeof, + SawTyInfer +} + +fn saw_ty(node: &Ty_) -> SawTyComponent { + match *node { + TyVec(..) => SawTyVec, + TyFixedLengthVec(..) => SawTyFixedLengthVec, + TyPtr(ref mty) => SawTyPtr(mty.mutbl), + TyRptr(_, ref mty) => SawTyRptr(mty.mutbl), + TyBareFn(..) => SawTyBareFn, + TyNever => SawTyNever, + TyTup(..) => SawTyTup, + TyPath(..) => SawTyPath, + TyObjectSum(..) => SawTyObjectSum, + TyPolyTraitRef(..) => SawTyPolyTraitRef, + TyImplTrait(..) => SawTyImplTrait, + TyTypeof(..) => SawTyTypeof, + TyInfer => SawTyInfer + } +} + +#[derive(Hash)] +enum SawTraitOrImplItemComponent { + SawTraitOrImplItemConst, + SawTraitOrImplItemMethod(Unsafety, Constness, Abi), + SawTraitOrImplItemType +} + +fn saw_trait_item(ti: &TraitItem_) -> SawTraitOrImplItemComponent { + match *ti { + ConstTraitItem(..) => SawTraitOrImplItemConst, + MethodTraitItem(ref sig, _) => + SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi), + TypeTraitItem(..) => SawTraitOrImplItemType + } +} + +fn saw_impl_item(ii: &ImplItemKind) -> SawTraitOrImplItemComponent { + match *ii { + ImplItemKind::Const(..) => SawTraitOrImplItemConst, + ImplItemKind::Method(ref sig, _) => + SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi), + ImplItemKind::Type(..) => SawTraitOrImplItemType + } +} + #[derive(Clone, Copy, Hash, Eq, PartialEq)] enum SawSpanExpnKind { NoExpansion, @@ -383,10 +519,7 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has fn visit_item(&mut self, i: &'tcx Item) { debug!("visit_item: {:?} st={:?}", i, self.st); - - SawItem.hash(self.st); - // Hash the value of the discriminant of the Item variant. - self.hash_discriminant(&i.node); + SawItem(saw_item(&i.node)).hash(self.st); hash_span!(self, i.span); hash_attrs!(self, &i.attrs); visit::walk_item(self, i) @@ -399,7 +532,7 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has fn visit_ty(&mut self, t: &'tcx Ty) { debug!("visit_ty: st={:?}", self.st); - SawTy.hash(self.st); + SawTy(saw_ty(&t.node)).hash(self.st); hash_span!(self, t.span); visit::walk_ty(self, t) } @@ -412,8 +545,7 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has fn visit_trait_item(&mut self, ti: &'tcx TraitItem) { debug!("visit_trait_item: st={:?}", self.st); - SawTraitItem.hash(self.st); - self.hash_discriminant(&ti.node); + SawTraitItem(saw_trait_item(&ti.node)).hash(self.st); hash_span!(self, ti.span); hash_attrs!(self, &ti.attrs); visit::walk_trait_item(self, ti) @@ -421,8 +553,7 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has fn visit_impl_item(&mut self, ii: &'tcx ImplItem) { debug!("visit_impl_item: st={:?}", self.st); - SawImplItem.hash(self.st); - self.hash_discriminant(&ii.node); + SawImplItem(saw_impl_item(&ii.node)).hash(self.st); hash_span!(self, ii.span); hash_attrs!(self, &ii.attrs); visit::walk_impl_item(self, ii) @@ -452,8 +583,7 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has fn visit_pat(&mut self, p: &'tcx Pat) { debug!("visit_pat: st={:?}", self.st); - SawPat.hash(self.st); - self.hash_discriminant(&p.node); + SawPat(saw_pat(&p.node)).hash(self.st); hash_span!(self, p.span); visit::walk_pat(self, p) } From 14fe7ce9dc7fa9b4a1737d8abffa4a9cf0d76c0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Border=C3=A9?= Date: Wed, 5 Oct 2016 07:11:04 +0200 Subject: [PATCH 18/26] Adjustments due to naming changes in Ty_ and PatKind structs --- .../calculate_svh/svh_visitor.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc_incremental/calculate_svh/svh_visitor.rs b/src/librustc_incremental/calculate_svh/svh_visitor.rs index 603a7fc40eb4f..59226c83cea96 100644 --- a/src/librustc_incremental/calculate_svh/svh_visitor.rs +++ b/src/librustc_incremental/calculate_svh/svh_visitor.rs @@ -324,7 +324,7 @@ enum SawPatComponent { SawPatRef(Mutability), SawPatLit, SawPatRange, - SawPathVec + SawPatSlice } fn saw_pat(node: &PatKind) -> SawPatComponent { @@ -339,14 +339,14 @@ fn saw_pat(node: &PatKind) -> SawPatComponent { PatKind::Ref(_, mutability) => SawPatRef(mutability), PatKind::Lit(..) => SawPatLit, PatKind::Range(..) => SawPatRange, - PatKind::Vec(..) => SawPathVec + PatKind::Slice(..) => SawPatSlice } } #[derive(Hash)] enum SawTyComponent { - SawTyVec, - SawTyFixedLengthVec, + SawTySlice, + SawTyArray, SawTyPtr(Mutability), SawTyRptr(Mutability), SawTyBareFn, @@ -362,8 +362,8 @@ enum SawTyComponent { fn saw_ty(node: &Ty_) -> SawTyComponent { match *node { - TyVec(..) => SawTyVec, - TyFixedLengthVec(..) => SawTyFixedLengthVec, + TySlice(..) => SawTySlice, + TyArray(..) => SawTyArray, TyPtr(ref mty) => SawTyPtr(mty.mutbl), TyRptr(_, ref mty) => SawTyRptr(mty.mutbl), TyBareFn(..) => SawTyBareFn, From 6d54e0eb6be81bd1a880f44ed68a180275cfe329 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 4 Oct 2016 17:44:31 +0300 Subject: [PATCH 19/26] emit !nonnull metadata on loaded fat pointers when possible cc #36920 (in addition to LLVM PR30597, should fix the &&[i32] case) --- src/librustc_trans/base.rs | 43 +++++++++++++++++++++++++++---- src/librustc_trans/mir/block.rs | 4 +-- src/librustc_trans/mir/lvalue.rs | 14 ---------- src/librustc_trans/mir/mod.rs | 14 ++++++---- src/librustc_trans/mir/operand.rs | 20 +++++++------- src/librustc_trans/mir/rvalue.rs | 4 +-- 6 files changed, 60 insertions(+), 39 deletions(-) diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index d80ed5e27cc6d..2dde81bbaa319 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -183,6 +183,14 @@ pub fn get_dataptr(bcx: Block, fat_ptr: ValueRef) -> ValueRef { StructGEP(bcx, fat_ptr, abi::FAT_PTR_ADDR) } +pub fn get_meta_builder(b: &Builder, fat_ptr: ValueRef) -> ValueRef { + b.struct_gep(fat_ptr, abi::FAT_PTR_EXTRA) +} + +pub fn get_dataptr_builder(b: &Builder, fat_ptr: ValueRef) -> ValueRef { + b.struct_gep(fat_ptr, abi::FAT_PTR_ADDR) +} + fn require_alloc_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, info_ty: Ty<'tcx>, it: LangItem) -> DefId { match bcx.tcx().lang_items.require(it) { Ok(id) => id, @@ -708,11 +716,36 @@ pub fn store_fat_ptr<'blk, 'tcx>(cx: Block<'blk, 'tcx>, pub fn load_fat_ptr<'blk, 'tcx>(cx: Block<'blk, 'tcx>, src: ValueRef, - _ty: Ty<'tcx>) - -> (ValueRef, ValueRef) { - // FIXME: emit metadata - (Load(cx, get_dataptr(cx, src)), - Load(cx, get_meta(cx, src))) + ty: Ty<'tcx>) + -> (ValueRef, ValueRef) +{ + if cx.unreachable.get() { + // FIXME: remove me + return (Load(cx, get_dataptr(cx, src)), + Load(cx, get_meta(cx, src))); + } + + load_fat_ptr_builder(&B(cx), src, ty) +} + +pub fn load_fat_ptr_builder<'a, 'tcx>( + b: &Builder<'a, 'tcx>, + src: ValueRef, + t: Ty<'tcx>) + -> (ValueRef, ValueRef) +{ + + let ptr = get_dataptr_builder(b, src); + let ptr = if t.is_region_ptr() || t.is_unique() { + b.load_nonnull(ptr) + } else { + b.load(ptr) + }; + + // FIXME: emit metadata on `meta`. + let meta = b.load(get_meta_builder(b, src)); + + (ptr, meta) } pub fn from_immediate(bcx: Block, val: ValueRef) -> ValueRef { diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 9e2d947c5e563..9edb489decc73 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -35,7 +35,7 @@ use syntax::parse::token; use super::{MirContext, LocalRef}; use super::analyze::CleanupKind; use super::constant::Const; -use super::lvalue::{LvalueRef, load_fat_ptr}; +use super::lvalue::{LvalueRef}; use super::operand::OperandRef; use super::operand::OperandValue::*; @@ -703,7 +703,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { for (n, &ty) in arg_types.iter().enumerate() { let ptr = adt::trans_field_ptr_builder(bcx, tuple.ty, base, Disr(0), n); let val = if common::type_is_fat_ptr(bcx.tcx(), ty) { - let (lldata, llextra) = load_fat_ptr(bcx, ptr); + let (lldata, llextra) = base::load_fat_ptr_builder(bcx, ptr, ty); Pair(lldata, llextra) } else { // trans_argument will load this if it needs to diff --git a/src/librustc_trans/mir/lvalue.rs b/src/librustc_trans/mir/lvalue.rs index 7102bd81caf36..8e65eac2e8089 100644 --- a/src/librustc_trans/mir/lvalue.rs +++ b/src/librustc_trans/mir/lvalue.rs @@ -13,10 +13,8 @@ use rustc::ty::{self, Ty, TypeFoldable}; use rustc::mir::repr as mir; use rustc::mir::tcx::LvalueTy; use rustc_data_structures::indexed_vec::Idx; -use abi; use adt; use base; -use builder::Builder; use common::{self, BlockAndBuilder, CrateContext, C_uint, C_undef}; use consts; use machine; @@ -69,18 +67,6 @@ impl<'tcx> LvalueRef<'tcx> { } } -pub fn get_meta(b: &Builder, fat_ptr: ValueRef) -> ValueRef { - b.struct_gep(fat_ptr, abi::FAT_PTR_EXTRA) -} - -pub fn get_dataptr(b: &Builder, fat_ptr: ValueRef) -> ValueRef { - b.struct_gep(fat_ptr, abi::FAT_PTR_ADDR) -} - -pub fn load_fat_ptr(b: &Builder, fat_ptr: ValueRef) -> (ValueRef, ValueRef) { - (b.load(get_dataptr(b, fat_ptr)), b.load(get_meta(b, fat_ptr))) -} - impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { pub fn trans_lvalue(&mut self, bcx: &BlockAndBuilder<'bcx, 'tcx>, diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index fe71023ea34de..d5828f7c56c25 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -34,7 +34,7 @@ use rustc_data_structures::indexed_vec::{IndexVec, Idx}; pub use self::constant::trans_static_initializer; -use self::lvalue::{LvalueRef, get_dataptr, get_meta}; +use self::lvalue::{LvalueRef}; use rustc::mir::traversal; use self::operand::{OperandRef, OperandValue}; @@ -384,8 +384,10 @@ fn arg_local_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>, // they are the two sub-fields of a single aggregate field. let meta = &fcx.fn_ty.args[idx]; idx += 1; - arg.store_fn_arg(bcx, &mut llarg_idx, get_dataptr(bcx, dst)); - meta.store_fn_arg(bcx, &mut llarg_idx, get_meta(bcx, dst)); + arg.store_fn_arg(bcx, &mut llarg_idx, + base::get_dataptr_builder(bcx, dst)); + meta.store_fn_arg(bcx, &mut llarg_idx, + base::get_meta_builder(bcx, dst)); } else { arg.store_fn_arg(bcx, &mut llarg_idx, dst); } @@ -466,8 +468,10 @@ fn arg_local_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>, // so make an alloca to store them in. let meta = &fcx.fn_ty.args[idx]; idx += 1; - arg.store_fn_arg(bcx, &mut llarg_idx, get_dataptr(bcx, lltemp)); - meta.store_fn_arg(bcx, &mut llarg_idx, get_meta(bcx, lltemp)); + arg.store_fn_arg(bcx, &mut llarg_idx, + base::get_dataptr_builder(bcx, lltemp)); + meta.store_fn_arg(bcx, &mut llarg_idx, + base::get_meta_builder(bcx, lltemp)); } else { // otherwise, arg is passed by value, so make a // temporary and store it there diff --git a/src/librustc_trans/mir/operand.rs b/src/librustc_trans/mir/operand.rs index 4f1ec40398ca9..c9d83a3375258 100644 --- a/src/librustc_trans/mir/operand.rs +++ b/src/librustc_trans/mir/operand.rs @@ -143,20 +143,18 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { { debug!("trans_load: {:?} @ {:?}", Value(llval), ty); - let val = if common::type_is_imm_pair(bcx.ccx(), ty) { + let val = if common::type_is_fat_ptr(bcx.tcx(), ty) { + let (lldata, llextra) = base::load_fat_ptr_builder(bcx, llval, ty); + OperandValue::Pair(lldata, llextra) + } else if common::type_is_imm_pair(bcx.ccx(), ty) { + let [a_ty, b_ty] = common::type_pair_fields(bcx.ccx(), ty).unwrap(); let a_ptr = bcx.struct_gep(llval, 0); let b_ptr = bcx.struct_gep(llval, 1); - // This is None only for fat pointers, which don't - // need any special load-time behavior anyway. - let pair_fields = common::type_pair_fields(bcx.ccx(), ty); - let (a, b) = if let Some([a_ty, b_ty]) = pair_fields { - (base::load_ty_builder(bcx, a_ptr, a_ty), - base::load_ty_builder(bcx, b_ptr, b_ty)) - } else { - (bcx.load(a_ptr), bcx.load(b_ptr)) - }; - OperandValue::Pair(a, b) + OperandValue::Pair( + base::load_ty_builder(bcx, a_ptr, a_ty), + base::load_ty_builder(bcx, b_ptr, b_ty) + ) } else if common::type_is_immediate(bcx.ccx(), ty) { OperandValue::Immediate(base::load_ty_builder(bcx, llval, ty)) } else { diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index b643dcd9871b0..53538f9fc85fc 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -28,7 +28,7 @@ use Disr; use super::MirContext; use super::constant::const_scalar_checked_binop; use super::operand::{OperandRef, OperandValue}; -use super::lvalue::{LvalueRef, get_dataptr}; +use super::lvalue::{LvalueRef}; impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { pub fn trans_rvalue(&mut self, @@ -98,7 +98,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { let tr_elem = self.trans_operand(&bcx, elem); let size = count.value.as_u64(bcx.tcx().sess.target.uint_type); let size = C_uint(bcx.ccx(), size); - let base = get_dataptr(&bcx, dest.llval); + let base = base::get_dataptr_builder(&bcx, dest.llval); let bcx = bcx.map_block(|block| { tvec::slice_for_each(block, base, tr_elem.ty, size, |block, llslot| { self.store_operand_direct(block, llslot, tr_elem); From 923336627157eac4408b0851bf01ed20940f5582 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 4 Oct 2016 18:34:03 +0300 Subject: [PATCH 20/26] clean up misc. uses of get_dataptr/get_meta --- src/librustc_trans/base.rs | 127 +------------------------------ src/librustc_trans/mir/rvalue.rs | 91 +++++++++++++++++++--- 2 files changed, 82 insertions(+), 136 deletions(-) diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 2dde81bbaa319..5d6dd27108b82 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -255,124 +255,6 @@ pub fn bin_op_to_fcmp_predicate(op: hir::BinOp_) -> llvm::RealPredicate { } } -pub fn compare_fat_ptrs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - lhs_addr: ValueRef, - lhs_extra: ValueRef, - rhs_addr: ValueRef, - rhs_extra: ValueRef, - _t: Ty<'tcx>, - op: hir::BinOp_, - debug_loc: DebugLoc) - -> ValueRef { - match op { - hir::BiEq => { - let addr_eq = ICmp(bcx, llvm::IntEQ, lhs_addr, rhs_addr, debug_loc); - let extra_eq = ICmp(bcx, llvm::IntEQ, lhs_extra, rhs_extra, debug_loc); - And(bcx, addr_eq, extra_eq, debug_loc) - } - hir::BiNe => { - let addr_eq = ICmp(bcx, llvm::IntNE, lhs_addr, rhs_addr, debug_loc); - let extra_eq = ICmp(bcx, llvm::IntNE, lhs_extra, rhs_extra, debug_loc); - Or(bcx, addr_eq, extra_eq, debug_loc) - } - hir::BiLe | hir::BiLt | hir::BiGe | hir::BiGt => { - // a OP b ~ a.0 STRICT(OP) b.0 | (a.0 == b.0 && a.1 OP a.1) - let (op, strict_op) = match op { - hir::BiLt => (llvm::IntULT, llvm::IntULT), - hir::BiLe => (llvm::IntULE, llvm::IntULT), - hir::BiGt => (llvm::IntUGT, llvm::IntUGT), - hir::BiGe => (llvm::IntUGE, llvm::IntUGT), - _ => bug!(), - }; - - let addr_eq = ICmp(bcx, llvm::IntEQ, lhs_addr, rhs_addr, debug_loc); - let extra_op = ICmp(bcx, op, lhs_extra, rhs_extra, debug_loc); - let addr_eq_extra_op = And(bcx, addr_eq, extra_op, debug_loc); - - let addr_strict = ICmp(bcx, strict_op, lhs_addr, rhs_addr, debug_loc); - Or(bcx, addr_strict, addr_eq_extra_op, debug_loc) - } - _ => { - bug!("unexpected fat ptr binop"); - } - } -} - -pub fn compare_scalar_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - lhs: ValueRef, - rhs: ValueRef, - t: Ty<'tcx>, - op: hir::BinOp_, - debug_loc: DebugLoc) - -> ValueRef { - match t.sty { - ty::TyTuple(ref tys) if tys.is_empty() => { - // We don't need to do actual comparisons for nil. - // () == () holds but () < () does not. - match op { - hir::BiEq | hir::BiLe | hir::BiGe => return C_bool(bcx.ccx(), true), - hir::BiNe | hir::BiLt | hir::BiGt => return C_bool(bcx.ccx(), false), - // refinements would be nice - _ => bug!("compare_scalar_types: must be a comparison operator"), - } - } - ty::TyBool => { - // FIXME(#36856) -- using `from_immediate` forces these booleans into `i8`, - // which works around some LLVM bugs - ICmp(bcx, - bin_op_to_icmp_predicate(op, false), - from_immediate(bcx, lhs), - from_immediate(bcx, rhs), - debug_loc) - } - ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyUint(_) | ty::TyChar => { - ICmp(bcx, - bin_op_to_icmp_predicate(op, false), - lhs, - rhs, - debug_loc) - } - ty::TyRawPtr(mt) if common::type_is_sized(bcx.tcx(), mt.ty) => { - ICmp(bcx, - bin_op_to_icmp_predicate(op, false), - lhs, - rhs, - debug_loc) - } - ty::TyRawPtr(_) => { - let lhs_addr = Load(bcx, GEPi(bcx, lhs, &[0, abi::FAT_PTR_ADDR])); - let lhs_extra = Load(bcx, GEPi(bcx, lhs, &[0, abi::FAT_PTR_EXTRA])); - - let rhs_addr = Load(bcx, GEPi(bcx, rhs, &[0, abi::FAT_PTR_ADDR])); - let rhs_extra = Load(bcx, GEPi(bcx, rhs, &[0, abi::FAT_PTR_EXTRA])); - compare_fat_ptrs(bcx, - lhs_addr, - lhs_extra, - rhs_addr, - rhs_extra, - t, - op, - debug_loc) - } - ty::TyInt(_) => { - ICmp(bcx, - bin_op_to_icmp_predicate(op, true), - lhs, - rhs, - debug_loc) - } - ty::TyFloat(_) => { - FCmp(bcx, - bin_op_to_fcmp_predicate(op), - lhs, - rhs, - debug_loc) - } - // Should never get here, because t is scalar. - _ => bug!("non-scalar type passed to compare_scalar_types"), - } -} - pub fn compare_simd_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, lhs: ValueRef, rhs: ValueRef, @@ -693,12 +575,9 @@ pub fn store_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, dst: ValueRef, t debug!("store_ty: {:?} : {:?} <- {:?}", Value(dst), t, Value(v)); if common::type_is_fat_ptr(cx.tcx(), t) { - Store(cx, - ExtractValue(cx, v, abi::FAT_PTR_ADDR), - get_dataptr(cx, dst)); - Store(cx, - ExtractValue(cx, v, abi::FAT_PTR_EXTRA), - get_meta(cx, dst)); + let lladdr = ExtractValue(cx, v, abi::FAT_PTR_ADDR); + let llextra = ExtractValue(cx, v, abi::FAT_PTR_EXTRA); + store_fat_ptr(cx, lladdr, llextra, dst, t); } else { Store(cx, from_immediate(cx, v), dst); } diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 53538f9fc85fc..c30a9dfdd9646 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -20,6 +20,7 @@ use common::{self, val_ty, C_bool, C_null, C_uint, BlockAndBuilder, Result}; use debuginfo::DebugLoc; use adt; use machine; +use type_::Type; use type_of; use tvec; use value::Value; @@ -382,13 +383,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { match (lhs.val, rhs.val) { (OperandValue::Pair(lhs_addr, lhs_extra), OperandValue::Pair(rhs_addr, rhs_extra)) => { - bcx.with_block(|bcx| { - base::compare_fat_ptrs(bcx, - lhs_addr, lhs_extra, - rhs_addr, rhs_extra, - lhs.ty, op.to_hir_binop(), - debug_loc) - }) + self.trans_fat_ptr_binop(&bcx, op, + lhs_addr, lhs_extra, + rhs_addr, rhs_extra, + lhs.ty) } _ => bug!() } @@ -485,6 +483,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { input_ty: Ty<'tcx>) -> ValueRef { let is_float = input_ty.is_fp(); let is_signed = input_ty.is_signed(); + let is_nil = input_ty.is_nil(); + let is_bool = input_ty.is_bool(); match op { mir::BinOp::Add => if is_float { bcx.fadd(lhs, rhs) @@ -535,12 +535,79 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { DebugLoc::None) }) } - mir::BinOp::Eq | mir::BinOp::Lt | mir::BinOp::Gt | - mir::BinOp::Ne | mir::BinOp::Le | mir::BinOp::Ge => { - bcx.with_block(|bcx| { - base::compare_scalar_types(bcx, lhs, rhs, input_ty, - op.to_hir_binop(), DebugLoc::None) + mir::BinOp::Ne | mir::BinOp::Lt | mir::BinOp::Gt | + mir::BinOp::Eq | mir::BinOp::Le | mir::BinOp::Ge => if is_nil { + C_bool(bcx.ccx(), match op { + mir::BinOp::Ne | mir::BinOp::Lt | mir::BinOp::Gt => false, + mir::BinOp::Eq | mir::BinOp::Le | mir::BinOp::Ge => true, + _ => unreachable!() }) + } else if is_float { + bcx.fcmp( + base::bin_op_to_fcmp_predicate(op.to_hir_binop()), + lhs, rhs + ) + } else { + let (lhs, rhs) = if is_bool { + // FIXME(#36856) -- extend the bools into `i8` because + // LLVM's i1 comparisons are broken. + (bcx.zext(lhs, Type::i8(bcx.ccx())), + bcx.zext(rhs, Type::i8(bcx.ccx()))) + } else { + (lhs, rhs) + }; + + bcx.icmp( + base::bin_op_to_icmp_predicate(op.to_hir_binop(), is_signed), + lhs, rhs + ) + } + } + } + + pub fn trans_fat_ptr_binop(&mut self, + bcx: &BlockAndBuilder<'bcx, 'tcx>, + op: mir::BinOp, + lhs_addr: ValueRef, + lhs_extra: ValueRef, + rhs_addr: ValueRef, + rhs_extra: ValueRef, + _input_ty: Ty<'tcx>) + -> ValueRef { + match op { + mir::BinOp::Eq => { + bcx.and( + bcx.icmp(llvm::IntEQ, lhs_addr, rhs_addr), + bcx.icmp(llvm::IntEQ, lhs_extra, rhs_extra) + ) + } + mir::BinOp::Ne => { + bcx.or( + bcx.icmp(llvm::IntNE, lhs_addr, rhs_addr), + bcx.icmp(llvm::IntNE, lhs_extra, rhs_extra) + ) + } + mir::BinOp::Le | mir::BinOp::Lt | + mir::BinOp::Ge | mir::BinOp::Gt => { + // a OP b ~ a.0 STRICT(OP) b.0 | (a.0 == b.0 && a.1 OP a.1) + let (op, strict_op) = match op { + mir::BinOp::Lt => (llvm::IntULT, llvm::IntULT), + mir::BinOp::Le => (llvm::IntULE, llvm::IntULT), + mir::BinOp::Gt => (llvm::IntUGT, llvm::IntUGT), + mir::BinOp::Ge => (llvm::IntUGE, llvm::IntUGT), + _ => bug!(), + }; + + bcx.or( + bcx.icmp(strict_op, lhs_addr, rhs_addr), + bcx.and( + bcx.icmp(llvm::IntEQ, lhs_addr, rhs_addr), + bcx.icmp(op, lhs_extra, rhs_extra) + ) + ) + } + _ => { + bug!("unexpected fat ptr binop"); } } } From 45fe3a1a2ab2671bb9f726941eda6c2899eb6dff Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 4 Oct 2016 19:24:49 +0300 Subject: [PATCH 21/26] emit an assume that cast-from enums are in range Fixes #36955. --- src/librustc_trans/base.rs | 5 +++++ src/librustc_trans/mir/rvalue.rs | 23 ++++++++++++++++++++++- src/test/codegen/enum-bounds-check.rs | 24 ++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 src/test/codegen/enum-bounds-check.rs diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 5d6dd27108b82..e0e808f2dcca1 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -522,6 +522,11 @@ pub fn need_invoke(bcx: Block) -> bool { } } +pub fn call_assume<'a, 'tcx>(b: &Builder<'a, 'tcx>, val: ValueRef) { + let assume_intrinsic = b.ccx.get_intrinsic("llvm.assume"); + b.call(assume_intrinsic, &[val], None); +} + /// Helper for loading values from memory. Does the necessary conversion if the in-memory type /// differs from the type used for SSA values. Also handles various special cases where the type /// gives us better information about what we are loading. diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index c30a9dfdd9646..97aa475be68a7 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -11,12 +11,14 @@ use llvm::{self, ValueRef}; use rustc::ty::{self, Ty}; use rustc::ty::cast::{CastTy, IntTy}; +use rustc::ty::layout::Layout; use rustc::mir::repr as mir; use asm; use base; use callee::Callee; use common::{self, val_ty, C_bool, C_null, C_uint, BlockAndBuilder, Result}; +use common::{C_integral}; use debuginfo::DebugLoc; use adt; use machine; @@ -282,7 +284,26 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { } OperandValue::Pair(..) => bug!("Unexpected Pair operand") }; - (discr, adt::is_discr_signed(&l)) + let (signed, min, max) = match l { + &Layout::CEnum { signed, min, max, .. } => { + (signed, min, max) + } + _ => bug!("CEnum {:?} is not an enum", operand) + }; + + if max > min { + // We want `table[e as usize]` to not + // have bound checks, and this is the most + // convenient place to put the `assume`. + + base::call_assume(&bcx, bcx.icmp( + llvm::IntULE, + discr, + C_integral(common::val_ty(discr), max, false) + )) + } + + (discr, signed) } else { (operand.immediate(), operand.ty.is_signed()) }; diff --git a/src/test/codegen/enum-bounds-check.rs b/src/test/codegen/enum-bounds-check.rs new file mode 100644 index 0000000000000..4cfb5a752dfdc --- /dev/null +++ b/src/test/codegen/enum-bounds-check.rs @@ -0,0 +1,24 @@ +// 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. + +// compile-flags: -O + +#![crate_type = "lib"] + +pub enum Foo { + A, B +} + +// CHECK-LABEL: @lookup +#[no_mangle] +pub fn lookup(buf: &[u8; 2], f: Foo) -> u8 { + // CHECK-NOT: panic_bounds_check + buf[f as usize] +} From 8d06332a27b020f5252238946fa9dccc3843d52a Mon Sep 17 00:00:00 2001 From: Razican Date: Wed, 5 Oct 2016 13:18:45 +0200 Subject: [PATCH 22/26] Fixed small typo in `BufRead` comments `BufRead` comments, in the `Seek` trait implementation, was talking about allocating 8 *ebibytes*. It was a typo, the correct unit is *exbibytes*, since *ebibytes* don't even exist. The calculation is correct, though. --- src/libstd/io/buffered.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 21a0cc1fb3b13..93b2d34e27f92 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -231,7 +231,7 @@ impl Seek for BufReader { if let SeekFrom::Current(n) = pos { let remainder = (self.cap - self.pos) as i64; // it should be safe to assume that remainder fits within an i64 as the alternative - // means we managed to allocate 8 ebibytes and that's absurd. + // means we managed to allocate 8 exbibytes and that's absurd. // But it's not out of the realm of possibility for some weird underlying reader to // support seeking by i64::min_value() so we need to handle underflow when subtracting // remainder. From a4e9c392092b5a6d51296470c29f86aaaf255925 Mon Sep 17 00:00:00 2001 From: angelsl Date: Mon, 3 Oct 2016 23:37:30 +0800 Subject: [PATCH 23/26] Clarify last element in str.{r,}splitn documentation --- src/libcollections/str.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 96efe1a03e351..3b9af74b1e7ac 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -1053,10 +1053,10 @@ impl str { } /// An iterator over substrings of the given string slice, separated by a - /// pattern, restricted to returning at most `count` items. + /// pattern, restricted to returning at most `n` items. /// - /// The last element returned, if any, will contain the remainder of the - /// string slice. + /// If `n` substrings are returned, the last substring (the `n`th substring) + /// will contain the remainder of the string. /// /// The pattern can be a `&str`, [`char`], or a closure that determines the /// split. @@ -1098,16 +1098,16 @@ impl str { /// assert_eq!(v, ["abc", "defXghi"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P> { - core_str::StrExt::splitn(self, count, pat) + pub fn splitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> SplitN<'a, P> { + core_str::StrExt::splitn(self, n, pat) } /// An iterator over substrings of this string slice, separated by a /// pattern, starting from the end of the string, restricted to returning - /// at most `count` items. + /// at most `n` items. /// - /// The last element returned, if any, will contain the remainder of the - /// string slice. + /// If `n` substrings are returned, the last substring (the `n`th substring) + /// will contain the remainder of the string. /// /// The pattern can be a `&str`, [`char`], or a closure that /// determines the split. @@ -1145,10 +1145,10 @@ impl str { /// assert_eq!(v, ["ghi", "abc1def"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P> + pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> RSplitN<'a, P> where P::Searcher: ReverseSearcher<'a> { - core_str::StrExt::rsplitn(self, count, pat) + core_str::StrExt::rsplitn(self, n, pat) } /// An iterator over the matches of a pattern within the given string From 4b5a9a37066e3d879c061cdd58bd05ffe4554244 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Border=C3=A9?= Date: Wed, 5 Oct 2016 23:17:58 +0200 Subject: [PATCH 24/26] ICH: update saw_ty for TyBareFn; Update tests for functioninterfaces --- .../calculate_svh/svh_visitor.rs | 7 +++-- .../incremental/hashes/function_interfaces.rs | 28 +++++++++++++++---- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/librustc_incremental/calculate_svh/svh_visitor.rs b/src/librustc_incremental/calculate_svh/svh_visitor.rs index 59226c83cea96..9aa55dc582e60 100644 --- a/src/librustc_incremental/calculate_svh/svh_visitor.rs +++ b/src/librustc_incremental/calculate_svh/svh_visitor.rs @@ -349,7 +349,7 @@ enum SawTyComponent { SawTyArray, SawTyPtr(Mutability), SawTyRptr(Mutability), - SawTyBareFn, + SawTyBareFn(Unsafety, Abi), SawTyNever, SawTyTup, SawTyPath, @@ -366,7 +366,10 @@ fn saw_ty(node: &Ty_) -> SawTyComponent { TyArray(..) => SawTyArray, TyPtr(ref mty) => SawTyPtr(mty.mutbl), TyRptr(_, ref mty) => SawTyRptr(mty.mutbl), - TyBareFn(..) => SawTyBareFn, + TyBareFn(ref barefnty) => { + let ref fnty = *barefnty; + SawTyBareFn(fnty.unsafety, fnty.abi) + }, TyNever => SawTyNever, TyTup(..) => SawTyTup, TyPath(..) => SawTyPath, diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs index 50f3729f1c652..93d94cd1a19c4 100644 --- a/src/test/incremental/hashes/function_interfaces.rs +++ b/src/test/incremental/hashes/function_interfaces.rs @@ -84,14 +84,14 @@ fn type_of_parameter_ref(p: &mut i32) {} // Change Parameter Order ------------------------------------------------------ #[cfg(cfail1)] -fn order_of_parameters(p1: i32, p2: i32) {} +fn order_of_parameters(p1: i32, p2: i64) {} #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] -fn order_of_parameters(p2: i32, p1: i32) {} +fn order_of_parameters(p2: i64, p1: i32) {} // Unsafe ---------------------------------------------------------------------- @@ -188,7 +188,7 @@ fn builtin_bound() {} // Lifetime Bound -------------------------------------------------------------- #[cfg(cfail1)] -fn lifetime_bound() {} +fn lifetime_bound<'a, T>() {} #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -227,7 +227,7 @@ fn second_builtin_bound() {} // Second Lifetime Bound ------------------------------------------------------- #[cfg(cfail1)] -fn second_lifetime_bound<'a, T: 'a>() {} +fn second_lifetime_bound<'a, 'b, T: 'a>() {} #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -254,6 +254,7 @@ fn inline() {} // Inline Never ---------------------------------------------------------------- #[cfg(cfail1)] +#[inline(always)] fn inline_never() {} #[cfg(not(cfail1))] @@ -289,7 +290,7 @@ fn linkage() {} #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] -#[linkage] +#[linkage="weak_odr"] fn linkage() {} @@ -310,6 +311,23 @@ fn return_impl_trait() -> impl Clone { } +// Change Return Impl Trait ---------------------------------------------------- + +#[cfg(cfail1)] +fn change_return_impl_trait() -> impl Clone { + 0 +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_return_impl_trait() -> impl Copy { + 0 +} + + // Change Return Type Indirectly ----------------------------------------------- struct ReferencedType1; From 0e40dbb2f7f4e03bcb59ef9cb057b455cc672926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Border=C3=A9?= Date: Thu, 6 Oct 2016 08:10:52 +0200 Subject: [PATCH 25/26] ICH: Remove obsolete binding in saw_ty --- src/librustc_incremental/calculate_svh/svh_visitor.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/librustc_incremental/calculate_svh/svh_visitor.rs b/src/librustc_incremental/calculate_svh/svh_visitor.rs index 9aa55dc582e60..3df68ac583d46 100644 --- a/src/librustc_incremental/calculate_svh/svh_visitor.rs +++ b/src/librustc_incremental/calculate_svh/svh_visitor.rs @@ -366,10 +366,7 @@ fn saw_ty(node: &Ty_) -> SawTyComponent { TyArray(..) => SawTyArray, TyPtr(ref mty) => SawTyPtr(mty.mutbl), TyRptr(_, ref mty) => SawTyRptr(mty.mutbl), - TyBareFn(ref barefnty) => { - let ref fnty = *barefnty; - SawTyBareFn(fnty.unsafety, fnty.abi) - }, + TyBareFn(ref barefnty) => SawTyBareFn(barefnty.unsafety, barefnty.abi), TyNever => SawTyNever, TyTup(..) => SawTyTup, TyPath(..) => SawTyPath, From cb700e78ed24300e8609b1f8bd442ede4fae03d2 Mon Sep 17 00:00:00 2001 From: ParkHanbum Date: Thu, 29 Sep 2016 16:24:14 +0900 Subject: [PATCH 26/26] Add testcase for issue-32948 ref : https://github.com/rust-lang/rust/issue/32948 --- src/test/run-make/stable-symbol-names/Makefile | 14 +++++++++----- .../stable-symbol-names/stable-symbol-names1.rs | 14 ++++++++++++++ .../stable-symbol-names/stable-symbol-names2.rs | 6 ++++++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/test/run-make/stable-symbol-names/Makefile b/src/test/run-make/stable-symbol-names/Makefile index da96d1b1dcf58..c1b14440faab6 100644 --- a/src/test/run-make/stable-symbol-names/Makefile +++ b/src/test/run-make/stable-symbol-names/Makefile @@ -1,12 +1,16 @@ -include ../tools.mk -# This test case makes sure that monomorphizations of the same function with the -# same set of generic arguments will have the same symbol names when -# instantiated in different crates. +# The following command will: +# 1. dump the symbols of a library using `nm` +# 2. extract only those lines that we are interested in via `grep` +# 3. from those lines, extract just the symbol name via `sed` +# (symbol names always start with "_ZN" and end with "E") +# 4. sort those symbol names for deterministic comparison +# 5. write the result into a file dump-symbols = nm "$(TMPDIR)/lib$(1).rlib" \ - | grep "some_test_function" \ - | sed "s/^[0-9a-f]\{8,16\}/00000000/" \ + | grep -E "some_test_function|Bar|bar" \ + | sed "s/.*\(_ZN.*E\).*/\1/" \ | sort \ > "$(TMPDIR)/$(1).nm" diff --git a/src/test/run-make/stable-symbol-names/stable-symbol-names1.rs b/src/test/run-make/stable-symbol-names/stable-symbol-names1.rs index 7b2cd85711301..5c73ff0fab6d0 100644 --- a/src/test/run-make/stable-symbol-names/stable-symbol-names1.rs +++ b/src/test/run-make/stable-symbol-names/stable-symbol-names1.rs @@ -10,6 +10,20 @@ #![crate_type="rlib"] +pub trait Foo { + fn foo(); +} + +pub struct Bar; + +impl Foo for Bar { + fn foo() {} +} + +pub fn bar() { + Bar::foo::(); +} + pub fn some_test_function(t: T) -> T { t } diff --git a/src/test/run-make/stable-symbol-names/stable-symbol-names2.rs b/src/test/run-make/stable-symbol-names/stable-symbol-names2.rs index ff027d6b46ce5..097dce876affc 100644 --- a/src/test/run-make/stable-symbol-names/stable-symbol-names2.rs +++ b/src/test/run-make/stable-symbol-names/stable-symbol-names2.rs @@ -18,3 +18,9 @@ pub fn user() { let x = 2u64; stable_symbol_names1::some_test_function(&x); } + +pub fn trait_impl_test_function() { + use stable_symbol_names1::*; + Bar::foo::(); + bar(); +}