Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit ad19c32

Browse files
authoredOct 6, 2016
Auto merge of #37002 - jonathandturner:rollup, r=jonathandturner
Rollup of 15 pull requests - Successful merges: #36726, #36832, #36909, #36930, #36932, #36957, #36959, #36960, #36962, #36965, #36966, #36967, #36972, #36974, #36977 - Failed merges:
2 parents 46957f0 + 89aebdb commit ad19c32

File tree

31 files changed

+925
-267
lines changed

31 files changed

+925
-267
lines changed
 

‎src/bootstrap/compile.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,16 +90,16 @@ pub fn std_link(build: &Build,
9090
add_to_sysroot(&out_dir, &libdir);
9191

9292
if target.contains("musl") && !target.contains("mips") {
93-
copy_musl_third_party_objects(build, &libdir);
93+
copy_musl_third_party_objects(build, target, &libdir);
9494
}
9595
}
9696

9797
/// Copies the crt(1,i,n).o startup objects
9898
///
9999
/// Only required for musl targets that statically link to libc
100-
fn copy_musl_third_party_objects(build: &Build, into: &Path) {
100+
fn copy_musl_third_party_objects(build: &Build, target: &str, into: &Path) {
101101
for &obj in &["crt1.o", "crti.o", "crtn.o"] {
102-
copy(&build.config.musl_root.as_ref().unwrap().join("lib").join(obj), &into.join(obj));
102+
copy(&build.musl_root(target).unwrap().join("lib").join(obj), &into.join(obj));
103103
}
104104
}
105105

‎src/bootstrap/config.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ struct TomlTarget {
158158
cc: Option<String>,
159159
cxx: Option<String>,
160160
android_ndk: Option<String>,
161+
musl_root: Option<String>,
161162
}
162163

163164
impl Config {
@@ -268,6 +269,7 @@ impl Config {
268269
}
269270
target.cxx = cfg.cxx.clone().map(PathBuf::from);
270271
target.cc = cfg.cc.clone().map(PathBuf::from);
272+
target.musl_root = cfg.musl_root.clone().map(PathBuf::from);
271273

272274
config.target_config.insert(triple.clone(), target);
273275
}

‎src/bootstrap/sanity.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,8 @@ pub fn check(build: &mut Build) {
146146
}
147147
}
148148
None => {
149-
panic!("when targeting MUSL either the build.musl-root \
150-
option or the target.$TARGET.musl-root one must \
149+
panic!("when targeting MUSL either the rust.musl-root \
150+
option or the target.$TARGET.musl-root option must \
151151
be specified in config.toml")
152152
}
153153
}

‎src/doc/book/concurrency.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Concurrency and parallelism are incredibly important topics in computer
44
science, and are also a hot topic in industry today. Computers are gaining more
55
and more cores, yet many programmers aren't prepared to fully utilize them.
66

7-
Rust's memory safety features also apply to its concurrency story too. Even
7+
Rust's memory safety features also apply to its concurrency story. Even
88
concurrent Rust programs must be memory safe, having no data races. Rust's type
99
system is up to the task, and gives you powerful ways to reason about
1010
concurrent code at compile time.
@@ -281,8 +281,8 @@ And... still gives us an error.
281281
```
282282

283283
`Arc<T>` by default has immutable contents. It allows the _sharing_ of data
284-
between threads, but shared mutable data is unsafe and when threads are
285-
involved can cause data races!
284+
between threads, but shared mutable data is unsafeand when threads are
285+
involvedcan cause data races!
286286

287287

288288
Usually when we wish to make something in an immutable position mutable, we use

‎src/libcollections/str.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,10 +1053,10 @@ impl str {
10531053
}
10541054

10551055
/// An iterator over substrings of the given string slice, separated by a
1056-
/// pattern, restricted to returning at most `count` items.
1056+
/// pattern, restricted to returning at most `n` items.
10571057
///
1058-
/// The last element returned, if any, will contain the remainder of the
1059-
/// string slice.
1058+
/// If `n` substrings are returned, the last substring (the `n`th substring)
1059+
/// will contain the remainder of the string.
10601060
///
10611061
/// The pattern can be a `&str`, [`char`], or a closure that determines the
10621062
/// split.
@@ -1098,16 +1098,16 @@ impl str {
10981098
/// assert_eq!(v, ["abc", "defXghi"]);
10991099
/// ```
11001100
#[stable(feature = "rust1", since = "1.0.0")]
1101-
pub fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P> {
1102-
core_str::StrExt::splitn(self, count, pat)
1101+
pub fn splitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> SplitN<'a, P> {
1102+
core_str::StrExt::splitn(self, n, pat)
11031103
}
11041104

11051105
/// An iterator over substrings of this string slice, separated by a
11061106
/// pattern, starting from the end of the string, restricted to returning
1107-
/// at most `count` items.
1107+
/// at most `n` items.
11081108
///
1109-
/// The last element returned, if any, will contain the remainder of the
1110-
/// string slice.
1109+
/// If `n` substrings are returned, the last substring (the `n`th substring)
1110+
/// will contain the remainder of the string.
11111111
///
11121112
/// The pattern can be a `&str`, [`char`], or a closure that
11131113
/// determines the split.
@@ -1145,10 +1145,10 @@ impl str {
11451145
/// assert_eq!(v, ["ghi", "abc1def"]);
11461146
/// ```
11471147
#[stable(feature = "rust1", since = "1.0.0")]
1148-
pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P>
1148+
pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> RSplitN<'a, P>
11491149
where P::Searcher: ReverseSearcher<'a>
11501150
{
1151-
core_str::StrExt::rsplitn(self, count, pat)
1151+
core_str::StrExt::rsplitn(self, n, pat)
11521152
}
11531153

11541154
/// An iterator over the matches of a pattern within the given string

‎src/libcore/hash/sip.rs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ use ptr;
1717

1818
/// An implementation of SipHash 1-3.
1919
///
20+
/// This is currently the default hashing function used by standard library
21+
/// (eg. `collections::HashMap` uses it by default).
22+
///
2023
/// See: https://131002.net/siphash/
2124
#[unstable(feature = "sip_hash_13", issue = "34767")]
2225
#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")]
@@ -39,9 +42,6 @@ pub struct SipHasher24 {
3942
///
4043
/// See: https://131002.net/siphash/
4144
///
42-
/// This is currently the default hashing function used by standard library
43-
/// (eg. `collections::HashMap` uses it by default).
44-
///
4545
/// SipHash is a general-purpose hashing function: it runs at a good
4646
/// speed (competitive with Spooky and City) and permits strong _keyed_
4747
/// 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 {
117117
data.to_le()
118118
}
119119

120-
macro_rules! rotl {
121-
($x:expr, $b:expr) =>
122-
(($x << $b) | ($x >> (64_i32.wrapping_sub($b))))
123-
}
124-
125120
macro_rules! compress {
126121
($state:expr) => ({
127122
compress!($state.v0, $state.v1, $state.v2, $state.v3)
128123
});
129124
($v0:expr, $v1:expr, $v2:expr, $v3:expr) =>
130125
({
131-
$v0 = $v0.wrapping_add($v1); $v1 = rotl!($v1, 13); $v1 ^= $v0;
132-
$v0 = rotl!($v0, 32);
133-
$v2 = $v2.wrapping_add($v3); $v3 = rotl!($v3, 16); $v3 ^= $v2;
134-
$v0 = $v0.wrapping_add($v3); $v3 = rotl!($v3, 21); $v3 ^= $v0;
135-
$v2 = $v2.wrapping_add($v1); $v1 = rotl!($v1, 17); $v1 ^= $v2;
136-
$v2 = rotl!($v2, 32);
126+
$v0 = $v0.wrapping_add($v1); $v1 = $v1.rotate_left(13); $v1 ^= $v0;
127+
$v0 = $v0.rotate_left(32);
128+
$v2 = $v2.wrapping_add($v3); $v3 = $v3.rotate_left(16); $v3 ^= $v2;
129+
$v0 = $v0.wrapping_add($v3); $v3 = $v3.rotate_left(21); $v3 ^= $v0;
130+
$v2 = $v2.wrapping_add($v1); $v1 = $v1.rotate_left(17); $v1 ^= $v2;
131+
$v2 = $v2.rotate_left(32);
137132
});
138133
}
139134

‎src/librustc_const_eval/check_match.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ use rustc::middle::expr_use_visitor::{LoanCause, MutateMode};
2525
use rustc::middle::expr_use_visitor as euv;
2626
use rustc::middle::mem_categorization::{cmt};
2727
use rustc::hir::pat_util::*;
28+
use rustc::session::Session;
2829
use rustc::traits::Reveal;
2930
use rustc::ty::{self, Ty, TyCtxt};
31+
use rustc_errors::DiagnosticBuilder;
3032
use std::cmp::Ordering;
3133
use std::fmt;
3234
use std::iter::{FromIterator, IntoIterator, repeat};
@@ -163,6 +165,10 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
163165
tcx.sess.abort_if_errors();
164166
}
165167

168+
fn create_e0004<'a>(sess: &'a Session, sp: Span, error_message: String) -> DiagnosticBuilder<'a> {
169+
struct_span_err!(sess, sp, E0004, "{}", &error_message)
170+
}
171+
166172
fn check_expr(cx: &mut MatchCheckCtxt, ex: &hir::Expr) {
167173
intravisit::walk_expr(cx, ex);
168174
match ex.node {
@@ -215,9 +221,10 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &hir::Expr) {
215221
if inlined_arms.is_empty() {
216222
if !pat_ty.is_uninhabited(cx.tcx) {
217223
// We know the type is inhabited, so this must be wrong
218-
let mut err = struct_span_err!(cx.tcx.sess, ex.span, E0002,
219-
"non-exhaustive patterns: type {} is non-empty",
220-
pat_ty);
224+
let mut err = create_e0004(cx.tcx.sess, ex.span,
225+
format!("non-exhaustive patterns: type {} \
226+
is non-empty",
227+
pat_ty));
221228
span_help!(&mut err, ex.span,
222229
"Please ensure that all possible cases are being handled; \
223230
possibly adding wildcards or more match arms.");
@@ -438,10 +445,11 @@ fn check_exhaustive<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
438445
1 => format!("pattern {} not covered", joined_patterns),
439446
_ => format!("patterns {} not covered", joined_patterns)
440447
};
441-
struct_span_err!(cx.tcx.sess, sp, E0004,
442-
"non-exhaustive patterns: {} not covered",
443-
joined_patterns
444-
).span_label(sp, &label_text).emit();
448+
create_e0004(cx.tcx.sess, sp,
449+
format!("non-exhaustive patterns: {} not covered",
450+
joined_patterns))
451+
.span_label(sp, &label_text)
452+
.emit();
445453
},
446454
}
447455
}

‎src/librustc_incremental/calculate_svh/svh_visitor.rs

Lines changed: 146 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@
1515

1616
use self::SawExprComponent::*;
1717
use self::SawAbiComponent::*;
18+
use self::SawItemComponent::*;
19+
use self::SawPatComponent::*;
20+
use self::SawTyComponent::*;
21+
use self::SawTraitOrImplItemComponent::*;
22+
use syntax::abi::Abi;
1823
use syntax::ast::{self, Name, NodeId};
1924
use syntax::parse::token;
2025
use syntax_pos::{Span, NO_EXPANSION, COMMAND_LINE_EXPN, BytePos};
@@ -155,19 +160,19 @@ enum SawAbiComponent<'a> {
155160

156161
SawMod,
157162
SawForeignItem,
158-
SawItem,
159-
SawTy,
163+
SawItem(SawItemComponent),
164+
SawTy(SawTyComponent),
160165
SawGenerics,
161-
SawTraitItem,
162-
SawImplItem,
166+
SawTraitItem(SawTraitOrImplItemComponent),
167+
SawImplItem(SawTraitOrImplItemComponent),
163168
SawStructField,
164169
SawVariant,
165170
SawPath(bool),
166171
SawPathSegment,
167172
SawPathParameters,
168173
SawPathListItem,
169174
SawBlock,
170-
SawPat,
175+
SawPat(SawPatComponent),
171176
SawLocal,
172177
SawArm,
173178
SawExpr(SawExprComponent<'a>),
@@ -198,6 +203,9 @@ enum SawAbiComponent<'a> {
198203
/// because the SVH is just a developer convenience; there is no
199204
/// guarantee of collision-freedom, hash collisions are just
200205
/// (hopefully) unlikely.)
206+
///
207+
/// The xxxComponent enums and saw_xxx functions for Item, Pat,
208+
/// Ty, TraitItem and ImplItem follow the same methodology.
201209
#[derive(Hash)]
202210
enum SawExprComponent<'a> {
203211

@@ -267,6 +275,134 @@ fn saw_expr<'a>(node: &'a Expr_) -> SawExprComponent<'a> {
267275
}
268276
}
269277

278+
#[derive(Hash)]
279+
enum SawItemComponent {
280+
SawItemExternCrate,
281+
SawItemUse,
282+
SawItemStatic(Mutability),
283+
SawItemConst,
284+
SawItemFn(Unsafety, Constness, Abi),
285+
SawItemMod,
286+
SawItemForeignMod,
287+
SawItemTy,
288+
SawItemEnum,
289+
SawItemStruct,
290+
SawItemUnion,
291+
SawItemTrait(Unsafety),
292+
SawItemDefaultImpl(Unsafety),
293+
SawItemImpl(Unsafety, ImplPolarity)
294+
}
295+
296+
fn saw_item(node: &Item_) -> SawItemComponent {
297+
match *node {
298+
ItemExternCrate(..) => SawItemExternCrate,
299+
ItemUse(..) => SawItemUse,
300+
ItemStatic(_, mutability, _) => SawItemStatic(mutability),
301+
ItemConst(..) =>SawItemConst,
302+
ItemFn(_, unsafety, constness, abi, _, _) => SawItemFn(unsafety, constness, abi),
303+
ItemMod(..) => SawItemMod,
304+
ItemForeignMod(..) => SawItemForeignMod,
305+
ItemTy(..) => SawItemTy,
306+
ItemEnum(..) => SawItemEnum,
307+
ItemStruct(..) => SawItemStruct,
308+
ItemUnion(..) => SawItemUnion,
309+
ItemTrait(unsafety, ..) => SawItemTrait(unsafety),
310+
ItemDefaultImpl(unsafety, _) => SawItemDefaultImpl(unsafety),
311+
ItemImpl(unsafety, implpolarity, ..) => SawItemImpl(unsafety, implpolarity)
312+
}
313+
}
314+
315+
#[derive(Hash)]
316+
enum SawPatComponent {
317+
SawPatWild,
318+
SawPatBinding(BindingMode),
319+
SawPatStruct,
320+
SawPatTupleStruct,
321+
SawPatPath,
322+
SawPatTuple,
323+
SawPatBox,
324+
SawPatRef(Mutability),
325+
SawPatLit,
326+
SawPatRange,
327+
SawPatSlice
328+
}
329+
330+
fn saw_pat(node: &PatKind) -> SawPatComponent {
331+
match *node {
332+
PatKind::Wild => SawPatWild,
333+
PatKind::Binding(bindingmode, ..) => SawPatBinding(bindingmode),
334+
PatKind::Struct(..) => SawPatStruct,
335+
PatKind::TupleStruct(..) => SawPatTupleStruct,
336+
PatKind::Path(..) => SawPatPath,
337+
PatKind::Tuple(..) => SawPatTuple,
338+
PatKind::Box(..) => SawPatBox,
339+
PatKind::Ref(_, mutability) => SawPatRef(mutability),
340+
PatKind::Lit(..) => SawPatLit,
341+
PatKind::Range(..) => SawPatRange,
342+
PatKind::Slice(..) => SawPatSlice
343+
}
344+
}
345+
346+
#[derive(Hash)]
347+
enum SawTyComponent {
348+
SawTySlice,
349+
SawTyArray,
350+
SawTyPtr(Mutability),
351+
SawTyRptr(Mutability),
352+
SawTyBareFn(Unsafety, Abi),
353+
SawTyNever,
354+
SawTyTup,
355+
SawTyPath,
356+
SawTyObjectSum,
357+
SawTyPolyTraitRef,
358+
SawTyImplTrait,
359+
SawTyTypeof,
360+
SawTyInfer
361+
}
362+
363+
fn saw_ty(node: &Ty_) -> SawTyComponent {
364+
match *node {
365+
TySlice(..) => SawTySlice,
366+
TyArray(..) => SawTyArray,
367+
TyPtr(ref mty) => SawTyPtr(mty.mutbl),
368+
TyRptr(_, ref mty) => SawTyRptr(mty.mutbl),
369+
TyBareFn(ref barefnty) => SawTyBareFn(barefnty.unsafety, barefnty.abi),
370+
TyNever => SawTyNever,
371+
TyTup(..) => SawTyTup,
372+
TyPath(..) => SawTyPath,
373+
TyObjectSum(..) => SawTyObjectSum,
374+
TyPolyTraitRef(..) => SawTyPolyTraitRef,
375+
TyImplTrait(..) => SawTyImplTrait,
376+
TyTypeof(..) => SawTyTypeof,
377+
TyInfer => SawTyInfer
378+
}
379+
}
380+
381+
#[derive(Hash)]
382+
enum SawTraitOrImplItemComponent {
383+
SawTraitOrImplItemConst,
384+
SawTraitOrImplItemMethod(Unsafety, Constness, Abi),
385+
SawTraitOrImplItemType
386+
}
387+
388+
fn saw_trait_item(ti: &TraitItem_) -> SawTraitOrImplItemComponent {
389+
match *ti {
390+
ConstTraitItem(..) => SawTraitOrImplItemConst,
391+
MethodTraitItem(ref sig, _) =>
392+
SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi),
393+
TypeTraitItem(..) => SawTraitOrImplItemType
394+
}
395+
}
396+
397+
fn saw_impl_item(ii: &ImplItemKind) -> SawTraitOrImplItemComponent {
398+
match *ii {
399+
ImplItemKind::Const(..) => SawTraitOrImplItemConst,
400+
ImplItemKind::Method(ref sig, _) =>
401+
SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi),
402+
ImplItemKind::Type(..) => SawTraitOrImplItemType
403+
}
404+
}
405+
270406
#[derive(Clone, Copy, Hash, Eq, PartialEq)]
271407
enum SawSpanExpnKind {
272408
NoExpansion,
@@ -383,10 +519,7 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has
383519

384520
fn visit_item(&mut self, i: &'tcx Item) {
385521
debug!("visit_item: {:?} st={:?}", i, self.st);
386-
387-
SawItem.hash(self.st);
388-
// Hash the value of the discriminant of the Item variant.
389-
self.hash_discriminant(&i.node);
522+
SawItem(saw_item(&i.node)).hash(self.st);
390523
hash_span!(self, i.span);
391524
hash_attrs!(self, &i.attrs);
392525
visit::walk_item(self, i)
@@ -399,7 +532,7 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has
399532

400533
fn visit_ty(&mut self, t: &'tcx Ty) {
401534
debug!("visit_ty: st={:?}", self.st);
402-
SawTy.hash(self.st);
535+
SawTy(saw_ty(&t.node)).hash(self.st);
403536
hash_span!(self, t.span);
404537
visit::walk_ty(self, t)
405538
}
@@ -412,17 +545,15 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has
412545

413546
fn visit_trait_item(&mut self, ti: &'tcx TraitItem) {
414547
debug!("visit_trait_item: st={:?}", self.st);
415-
SawTraitItem.hash(self.st);
416-
self.hash_discriminant(&ti.node);
548+
SawTraitItem(saw_trait_item(&ti.node)).hash(self.st);
417549
hash_span!(self, ti.span);
418550
hash_attrs!(self, &ti.attrs);
419551
visit::walk_trait_item(self, ti)
420552
}
421553

422554
fn visit_impl_item(&mut self, ii: &'tcx ImplItem) {
423555
debug!("visit_impl_item: st={:?}", self.st);
424-
SawImplItem.hash(self.st);
425-
self.hash_discriminant(&ii.node);
556+
SawImplItem(saw_impl_item(&ii.node)).hash(self.st);
426557
hash_span!(self, ii.span);
427558
hash_attrs!(self, &ii.attrs);
428559
visit::walk_impl_item(self, ii)
@@ -452,8 +583,7 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has
452583

453584
fn visit_pat(&mut self, p: &'tcx Pat) {
454585
debug!("visit_pat: st={:?}", self.st);
455-
SawPat.hash(self.st);
456-
self.hash_discriminant(&p.node);
586+
SawPat(saw_pat(&p.node)).hash(self.st);
457587
hash_span!(self, p.span);
458588
visit::walk_pat(self, p)
459589
}

‎src/librustc_mir/transform/simplify_cfg.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ impl<'a> SimplifyCfg<'a> {
5050

5151
impl<'l, 'tcx> MirPass<'tcx> for SimplifyCfg<'l> {
5252
fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) {
53+
debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, mir);
5354
CfgSimplifier::new(mir).simplify();
5455
remove_dead_blocks(mir);
5556

@@ -78,6 +79,8 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
7879

7980
// we can't use mir.predecessors() here because that counts
8081
// dead blocks, which we don't want to.
82+
pred_count[START_BLOCK] = 1;
83+
8184
for (_, data) in traversal::preorder(mir) {
8285
if let Some(ref term) = data.terminator {
8386
for &tgt in term.successors().iter() {
@@ -157,8 +160,16 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
157160
debug!("collapsing goto chain from {:?} to {:?}", *start, target);
158161

159162
*changed |= *start != target;
160-
self.pred_count[target] += 1;
161-
self.pred_count[*start] -= 1;
163+
164+
if self.pred_count[*start] == 1 {
165+
// This is the last reference to *start, so the pred-count to
166+
// to target is moved into the current block.
167+
self.pred_count[*start] = 0;
168+
} else {
169+
self.pred_count[target] += 1;
170+
self.pred_count[*start] -= 1;
171+
}
172+
162173
*start = target;
163174
}
164175

‎src/librustc_trans/base.rs

Lines changed: 46 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,14 @@ pub fn get_dataptr(bcx: Block, fat_ptr: ValueRef) -> ValueRef {
183183
StructGEP(bcx, fat_ptr, abi::FAT_PTR_ADDR)
184184
}
185185

186+
pub fn get_meta_builder(b: &Builder, fat_ptr: ValueRef) -> ValueRef {
187+
b.struct_gep(fat_ptr, abi::FAT_PTR_EXTRA)
188+
}
189+
190+
pub fn get_dataptr_builder(b: &Builder, fat_ptr: ValueRef) -> ValueRef {
191+
b.struct_gep(fat_ptr, abi::FAT_PTR_ADDR)
192+
}
193+
186194
fn require_alloc_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, info_ty: Ty<'tcx>, it: LangItem) -> DefId {
187195
match bcx.tcx().lang_items.require(it) {
188196
Ok(id) => id,
@@ -247,124 +255,6 @@ pub fn bin_op_to_fcmp_predicate(op: hir::BinOp_) -> llvm::RealPredicate {
247255
}
248256
}
249257

250-
pub fn compare_fat_ptrs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
251-
lhs_addr: ValueRef,
252-
lhs_extra: ValueRef,
253-
rhs_addr: ValueRef,
254-
rhs_extra: ValueRef,
255-
_t: Ty<'tcx>,
256-
op: hir::BinOp_,
257-
debug_loc: DebugLoc)
258-
-> ValueRef {
259-
match op {
260-
hir::BiEq => {
261-
let addr_eq = ICmp(bcx, llvm::IntEQ, lhs_addr, rhs_addr, debug_loc);
262-
let extra_eq = ICmp(bcx, llvm::IntEQ, lhs_extra, rhs_extra, debug_loc);
263-
And(bcx, addr_eq, extra_eq, debug_loc)
264-
}
265-
hir::BiNe => {
266-
let addr_eq = ICmp(bcx, llvm::IntNE, lhs_addr, rhs_addr, debug_loc);
267-
let extra_eq = ICmp(bcx, llvm::IntNE, lhs_extra, rhs_extra, debug_loc);
268-
Or(bcx, addr_eq, extra_eq, debug_loc)
269-
}
270-
hir::BiLe | hir::BiLt | hir::BiGe | hir::BiGt => {
271-
// a OP b ~ a.0 STRICT(OP) b.0 | (a.0 == b.0 && a.1 OP a.1)
272-
let (op, strict_op) = match op {
273-
hir::BiLt => (llvm::IntULT, llvm::IntULT),
274-
hir::BiLe => (llvm::IntULE, llvm::IntULT),
275-
hir::BiGt => (llvm::IntUGT, llvm::IntUGT),
276-
hir::BiGe => (llvm::IntUGE, llvm::IntUGT),
277-
_ => bug!(),
278-
};
279-
280-
let addr_eq = ICmp(bcx, llvm::IntEQ, lhs_addr, rhs_addr, debug_loc);
281-
let extra_op = ICmp(bcx, op, lhs_extra, rhs_extra, debug_loc);
282-
let addr_eq_extra_op = And(bcx, addr_eq, extra_op, debug_loc);
283-
284-
let addr_strict = ICmp(bcx, strict_op, lhs_addr, rhs_addr, debug_loc);
285-
Or(bcx, addr_strict, addr_eq_extra_op, debug_loc)
286-
}
287-
_ => {
288-
bug!("unexpected fat ptr binop");
289-
}
290-
}
291-
}
292-
293-
pub fn compare_scalar_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
294-
lhs: ValueRef,
295-
rhs: ValueRef,
296-
t: Ty<'tcx>,
297-
op: hir::BinOp_,
298-
debug_loc: DebugLoc)
299-
-> ValueRef {
300-
match t.sty {
301-
ty::TyTuple(ref tys) if tys.is_empty() => {
302-
// We don't need to do actual comparisons for nil.
303-
// () == () holds but () < () does not.
304-
match op {
305-
hir::BiEq | hir::BiLe | hir::BiGe => return C_bool(bcx.ccx(), true),
306-
hir::BiNe | hir::BiLt | hir::BiGt => return C_bool(bcx.ccx(), false),
307-
// refinements would be nice
308-
_ => bug!("compare_scalar_types: must be a comparison operator"),
309-
}
310-
}
311-
ty::TyBool => {
312-
// FIXME(#36856) -- using `from_immediate` forces these booleans into `i8`,
313-
// which works around some LLVM bugs
314-
ICmp(bcx,
315-
bin_op_to_icmp_predicate(op, false),
316-
from_immediate(bcx, lhs),
317-
from_immediate(bcx, rhs),
318-
debug_loc)
319-
}
320-
ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyUint(_) | ty::TyChar => {
321-
ICmp(bcx,
322-
bin_op_to_icmp_predicate(op, false),
323-
lhs,
324-
rhs,
325-
debug_loc)
326-
}
327-
ty::TyRawPtr(mt) if common::type_is_sized(bcx.tcx(), mt.ty) => {
328-
ICmp(bcx,
329-
bin_op_to_icmp_predicate(op, false),
330-
lhs,
331-
rhs,
332-
debug_loc)
333-
}
334-
ty::TyRawPtr(_) => {
335-
let lhs_addr = Load(bcx, GEPi(bcx, lhs, &[0, abi::FAT_PTR_ADDR]));
336-
let lhs_extra = Load(bcx, GEPi(bcx, lhs, &[0, abi::FAT_PTR_EXTRA]));
337-
338-
let rhs_addr = Load(bcx, GEPi(bcx, rhs, &[0, abi::FAT_PTR_ADDR]));
339-
let rhs_extra = Load(bcx, GEPi(bcx, rhs, &[0, abi::FAT_PTR_EXTRA]));
340-
compare_fat_ptrs(bcx,
341-
lhs_addr,
342-
lhs_extra,
343-
rhs_addr,
344-
rhs_extra,
345-
t,
346-
op,
347-
debug_loc)
348-
}
349-
ty::TyInt(_) => {
350-
ICmp(bcx,
351-
bin_op_to_icmp_predicate(op, true),
352-
lhs,
353-
rhs,
354-
debug_loc)
355-
}
356-
ty::TyFloat(_) => {
357-
FCmp(bcx,
358-
bin_op_to_fcmp_predicate(op),
359-
lhs,
360-
rhs,
361-
debug_loc)
362-
}
363-
// Should never get here, because t is scalar.
364-
_ => bug!("non-scalar type passed to compare_scalar_types"),
365-
}
366-
}
367-
368258
pub fn compare_simd_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
369259
lhs: ValueRef,
370260
rhs: ValueRef,
@@ -632,6 +522,11 @@ pub fn need_invoke(bcx: Block) -> bool {
632522
}
633523
}
634524

525+
pub fn call_assume<'a, 'tcx>(b: &Builder<'a, 'tcx>, val: ValueRef) {
526+
let assume_intrinsic = b.ccx.get_intrinsic("llvm.assume");
527+
b.call(assume_intrinsic, &[val], None);
528+
}
529+
635530
/// Helper for loading values from memory. Does the necessary conversion if the in-memory type
636531
/// differs from the type used for SSA values. Also handles various special cases where the type
637532
/// gives us better information about what we are loading.
@@ -685,12 +580,9 @@ pub fn store_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, dst: ValueRef, t
685580
debug!("store_ty: {:?} : {:?} <- {:?}", Value(dst), t, Value(v));
686581

687582
if common::type_is_fat_ptr(cx.tcx(), t) {
688-
Store(cx,
689-
ExtractValue(cx, v, abi::FAT_PTR_ADDR),
690-
get_dataptr(cx, dst));
691-
Store(cx,
692-
ExtractValue(cx, v, abi::FAT_PTR_EXTRA),
693-
get_meta(cx, dst));
583+
let lladdr = ExtractValue(cx, v, abi::FAT_PTR_ADDR);
584+
let llextra = ExtractValue(cx, v, abi::FAT_PTR_EXTRA);
585+
store_fat_ptr(cx, lladdr, llextra, dst, t);
694586
} else {
695587
Store(cx, from_immediate(cx, v), dst);
696588
}
@@ -708,11 +600,36 @@ pub fn store_fat_ptr<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
708600

709601
pub fn load_fat_ptr<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
710602
src: ValueRef,
711-
_ty: Ty<'tcx>)
712-
-> (ValueRef, ValueRef) {
713-
// FIXME: emit metadata
714-
(Load(cx, get_dataptr(cx, src)),
715-
Load(cx, get_meta(cx, src)))
603+
ty: Ty<'tcx>)
604+
-> (ValueRef, ValueRef)
605+
{
606+
if cx.unreachable.get() {
607+
// FIXME: remove me
608+
return (Load(cx, get_dataptr(cx, src)),
609+
Load(cx, get_meta(cx, src)));
610+
}
611+
612+
load_fat_ptr_builder(&B(cx), src, ty)
613+
}
614+
615+
pub fn load_fat_ptr_builder<'a, 'tcx>(
616+
b: &Builder<'a, 'tcx>,
617+
src: ValueRef,
618+
t: Ty<'tcx>)
619+
-> (ValueRef, ValueRef)
620+
{
621+
622+
let ptr = get_dataptr_builder(b, src);
623+
let ptr = if t.is_region_ptr() || t.is_unique() {
624+
b.load_nonnull(ptr)
625+
} else {
626+
b.load(ptr)
627+
};
628+
629+
// FIXME: emit metadata on `meta`.
630+
let meta = b.load(get_meta_builder(b, src));
631+
632+
(ptr, meta)
716633
}
717634

718635
pub fn from_immediate(bcx: Block, val: ValueRef) -> ValueRef {

‎src/librustc_trans/closure.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,10 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
217217
llreffn: ValueRef)
218218
-> ValueRef
219219
{
220+
if let Some(&llfn) = ccx.instances().borrow().get(&method_instance) {
221+
return llfn;
222+
}
223+
220224
debug!("trans_fn_once_adapter_shim(closure_def_id={:?}, substs={:?}, llreffn={:?})",
221225
closure_def_id, substs, Value(llreffn));
222226

@@ -257,7 +261,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
257261

258262
// Create the by-value helper.
259263
let function_name = method_instance.symbol_name(ccx.shared());
260-
let lloncefn = declare::declare_fn(ccx, &function_name, llonce_fn_ty);
264+
let lloncefn = declare::define_internal_fn(ccx, &function_name, llonce_fn_ty);
261265
attributes::set_frame_pointer_elimination(ccx, lloncefn);
262266

263267
let (block_arena, fcx): (TypedArena<_>, FunctionContext);
@@ -312,5 +316,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
312316

313317
fcx.finish(bcx, DebugLoc::None);
314318

319+
ccx.instances().borrow_mut().insert(method_instance, lloncefn);
320+
315321
lloncefn
316322
}

‎src/librustc_trans/mir/block.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use syntax::parse::token;
3535
use super::{MirContext, LocalRef};
3636
use super::analyze::CleanupKind;
3737
use super::constant::Const;
38-
use super::lvalue::{LvalueRef, load_fat_ptr};
38+
use super::lvalue::{LvalueRef};
3939
use super::operand::OperandRef;
4040
use super::operand::OperandValue::*;
4141

@@ -703,7 +703,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
703703
for (n, &ty) in arg_types.iter().enumerate() {
704704
let ptr = adt::trans_field_ptr_builder(bcx, tuple.ty, base, Disr(0), n);
705705
let val = if common::type_is_fat_ptr(bcx.tcx(), ty) {
706-
let (lldata, llextra) = load_fat_ptr(bcx, ptr);
706+
let (lldata, llextra) = base::load_fat_ptr_builder(bcx, ptr, ty);
707707
Pair(lldata, llextra)
708708
} else {
709709
// trans_argument will load this if it needs to

‎src/librustc_trans/mir/lvalue.rs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,8 @@ use rustc::ty::{self, Ty, TypeFoldable};
1313
use rustc::mir::repr as mir;
1414
use rustc::mir::tcx::LvalueTy;
1515
use rustc_data_structures::indexed_vec::Idx;
16-
use abi;
1716
use adt;
1817
use base;
19-
use builder::Builder;
2018
use common::{self, BlockAndBuilder, CrateContext, C_uint, C_undef};
2119
use consts;
2220
use machine;
@@ -69,18 +67,6 @@ impl<'tcx> LvalueRef<'tcx> {
6967
}
7068
}
7169

72-
pub fn get_meta(b: &Builder, fat_ptr: ValueRef) -> ValueRef {
73-
b.struct_gep(fat_ptr, abi::FAT_PTR_EXTRA)
74-
}
75-
76-
pub fn get_dataptr(b: &Builder, fat_ptr: ValueRef) -> ValueRef {
77-
b.struct_gep(fat_ptr, abi::FAT_PTR_ADDR)
78-
}
79-
80-
pub fn load_fat_ptr(b: &Builder, fat_ptr: ValueRef) -> (ValueRef, ValueRef) {
81-
(b.load(get_dataptr(b, fat_ptr)), b.load(get_meta(b, fat_ptr)))
82-
}
83-
8470
impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
8571
pub fn trans_lvalue(&mut self,
8672
bcx: &BlockAndBuilder<'bcx, 'tcx>,

‎src/librustc_trans/mir/mod.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use rustc_data_structures::indexed_vec::{IndexVec, Idx};
3434

3535
pub use self::constant::trans_static_initializer;
3636

37-
use self::lvalue::{LvalueRef, get_dataptr, get_meta};
37+
use self::lvalue::{LvalueRef};
3838
use rustc::mir::traversal;
3939

4040
use self::operand::{OperandRef, OperandValue};
@@ -384,8 +384,10 @@ fn arg_local_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
384384
// they are the two sub-fields of a single aggregate field.
385385
let meta = &fcx.fn_ty.args[idx];
386386
idx += 1;
387-
arg.store_fn_arg(bcx, &mut llarg_idx, get_dataptr(bcx, dst));
388-
meta.store_fn_arg(bcx, &mut llarg_idx, get_meta(bcx, dst));
387+
arg.store_fn_arg(bcx, &mut llarg_idx,
388+
base::get_dataptr_builder(bcx, dst));
389+
meta.store_fn_arg(bcx, &mut llarg_idx,
390+
base::get_meta_builder(bcx, dst));
389391
} else {
390392
arg.store_fn_arg(bcx, &mut llarg_idx, dst);
391393
}
@@ -466,8 +468,10 @@ fn arg_local_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
466468
// so make an alloca to store them in.
467469
let meta = &fcx.fn_ty.args[idx];
468470
idx += 1;
469-
arg.store_fn_arg(bcx, &mut llarg_idx, get_dataptr(bcx, lltemp));
470-
meta.store_fn_arg(bcx, &mut llarg_idx, get_meta(bcx, lltemp));
471+
arg.store_fn_arg(bcx, &mut llarg_idx,
472+
base::get_dataptr_builder(bcx, lltemp));
473+
meta.store_fn_arg(bcx, &mut llarg_idx,
474+
base::get_meta_builder(bcx, lltemp));
471475
} else {
472476
// otherwise, arg is passed by value, so make a
473477
// temporary and store it there

‎src/librustc_trans/mir/operand.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -143,20 +143,18 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
143143
{
144144
debug!("trans_load: {:?} @ {:?}", Value(llval), ty);
145145

146-
let val = if common::type_is_imm_pair(bcx.ccx(), ty) {
146+
let val = if common::type_is_fat_ptr(bcx.tcx(), ty) {
147+
let (lldata, llextra) = base::load_fat_ptr_builder(bcx, llval, ty);
148+
OperandValue::Pair(lldata, llextra)
149+
} else if common::type_is_imm_pair(bcx.ccx(), ty) {
150+
let [a_ty, b_ty] = common::type_pair_fields(bcx.ccx(), ty).unwrap();
147151
let a_ptr = bcx.struct_gep(llval, 0);
148152
let b_ptr = bcx.struct_gep(llval, 1);
149153

150-
// This is None only for fat pointers, which don't
151-
// need any special load-time behavior anyway.
152-
let pair_fields = common::type_pair_fields(bcx.ccx(), ty);
153-
let (a, b) = if let Some([a_ty, b_ty]) = pair_fields {
154-
(base::load_ty_builder(bcx, a_ptr, a_ty),
155-
base::load_ty_builder(bcx, b_ptr, b_ty))
156-
} else {
157-
(bcx.load(a_ptr), bcx.load(b_ptr))
158-
};
159-
OperandValue::Pair(a, b)
154+
OperandValue::Pair(
155+
base::load_ty_builder(bcx, a_ptr, a_ty),
156+
base::load_ty_builder(bcx, b_ptr, b_ty)
157+
)
160158
} else if common::type_is_immediate(bcx.ccx(), ty) {
161159
OperandValue::Immediate(base::load_ty_builder(bcx, llval, ty))
162160
} else {

‎src/librustc_trans/mir/rvalue.rs

Lines changed: 103 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,18 @@
1111
use llvm::{self, ValueRef};
1212
use rustc::ty::{self, Ty};
1313
use rustc::ty::cast::{CastTy, IntTy};
14+
use rustc::ty::layout::Layout;
1415
use rustc::mir::repr as mir;
1516

1617
use asm;
1718
use base;
1819
use callee::Callee;
1920
use common::{self, val_ty, C_bool, C_null, C_uint, BlockAndBuilder, Result};
21+
use common::{C_integral};
2022
use debuginfo::DebugLoc;
2123
use adt;
2224
use machine;
25+
use type_::Type;
2326
use type_of;
2427
use tvec;
2528
use value::Value;
@@ -28,7 +31,7 @@ use Disr;
2831
use super::MirContext;
2932
use super::constant::const_scalar_checked_binop;
3033
use super::operand::{OperandRef, OperandValue};
31-
use super::lvalue::{LvalueRef, get_dataptr};
34+
use super::lvalue::{LvalueRef};
3235

3336
impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
3437
pub fn trans_rvalue(&mut self,
@@ -98,7 +101,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
98101
let tr_elem = self.trans_operand(&bcx, elem);
99102
let size = count.value.as_u64(bcx.tcx().sess.target.uint_type);
100103
let size = C_uint(bcx.ccx(), size);
101-
let base = get_dataptr(&bcx, dest.llval);
104+
let base = base::get_dataptr_builder(&bcx, dest.llval);
102105
let bcx = bcx.map_block(|block| {
103106
tvec::slice_for_each(block, base, tr_elem.ty, size, |block, llslot| {
104107
self.store_operand_direct(block, llslot, tr_elem);
@@ -281,7 +284,26 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
281284
}
282285
OperandValue::Pair(..) => bug!("Unexpected Pair operand")
283286
};
284-
(discr, adt::is_discr_signed(&l))
287+
let (signed, min, max) = match l {
288+
&Layout::CEnum { signed, min, max, .. } => {
289+
(signed, min, max)
290+
}
291+
_ => bug!("CEnum {:?} is not an enum", operand)
292+
};
293+
294+
if max > min {
295+
// We want `table[e as usize]` to not
296+
// have bound checks, and this is the most
297+
// convenient place to put the `assume`.
298+
299+
base::call_assume(&bcx, bcx.icmp(
300+
llvm::IntULE,
301+
discr,
302+
C_integral(common::val_ty(discr), max, false)
303+
))
304+
}
305+
306+
(discr, signed)
285307
} else {
286308
(operand.immediate(), operand.ty.is_signed())
287309
};
@@ -382,13 +404,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
382404
match (lhs.val, rhs.val) {
383405
(OperandValue::Pair(lhs_addr, lhs_extra),
384406
OperandValue::Pair(rhs_addr, rhs_extra)) => {
385-
bcx.with_block(|bcx| {
386-
base::compare_fat_ptrs(bcx,
387-
lhs_addr, lhs_extra,
388-
rhs_addr, rhs_extra,
389-
lhs.ty, op.to_hir_binop(),
390-
debug_loc)
391-
})
407+
self.trans_fat_ptr_binop(&bcx, op,
408+
lhs_addr, lhs_extra,
409+
rhs_addr, rhs_extra,
410+
lhs.ty)
392411
}
393412
_ => bug!()
394413
}
@@ -485,6 +504,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
485504
input_ty: Ty<'tcx>) -> ValueRef {
486505
let is_float = input_ty.is_fp();
487506
let is_signed = input_ty.is_signed();
507+
let is_nil = input_ty.is_nil();
508+
let is_bool = input_ty.is_bool();
488509
match op {
489510
mir::BinOp::Add => if is_float {
490511
bcx.fadd(lhs, rhs)
@@ -535,12 +556,79 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
535556
DebugLoc::None)
536557
})
537558
}
538-
mir::BinOp::Eq | mir::BinOp::Lt | mir::BinOp::Gt |
539-
mir::BinOp::Ne | mir::BinOp::Le | mir::BinOp::Ge => {
540-
bcx.with_block(|bcx| {
541-
base::compare_scalar_types(bcx, lhs, rhs, input_ty,
542-
op.to_hir_binop(), DebugLoc::None)
559+
mir::BinOp::Ne | mir::BinOp::Lt | mir::BinOp::Gt |
560+
mir::BinOp::Eq | mir::BinOp::Le | mir::BinOp::Ge => if is_nil {
561+
C_bool(bcx.ccx(), match op {
562+
mir::BinOp::Ne | mir::BinOp::Lt | mir::BinOp::Gt => false,
563+
mir::BinOp::Eq | mir::BinOp::Le | mir::BinOp::Ge => true,
564+
_ => unreachable!()
543565
})
566+
} else if is_float {
567+
bcx.fcmp(
568+
base::bin_op_to_fcmp_predicate(op.to_hir_binop()),
569+
lhs, rhs
570+
)
571+
} else {
572+
let (lhs, rhs) = if is_bool {
573+
// FIXME(#36856) -- extend the bools into `i8` because
574+
// LLVM's i1 comparisons are broken.
575+
(bcx.zext(lhs, Type::i8(bcx.ccx())),
576+
bcx.zext(rhs, Type::i8(bcx.ccx())))
577+
} else {
578+
(lhs, rhs)
579+
};
580+
581+
bcx.icmp(
582+
base::bin_op_to_icmp_predicate(op.to_hir_binop(), is_signed),
583+
lhs, rhs
584+
)
585+
}
586+
}
587+
}
588+
589+
pub fn trans_fat_ptr_binop(&mut self,
590+
bcx: &BlockAndBuilder<'bcx, 'tcx>,
591+
op: mir::BinOp,
592+
lhs_addr: ValueRef,
593+
lhs_extra: ValueRef,
594+
rhs_addr: ValueRef,
595+
rhs_extra: ValueRef,
596+
_input_ty: Ty<'tcx>)
597+
-> ValueRef {
598+
match op {
599+
mir::BinOp::Eq => {
600+
bcx.and(
601+
bcx.icmp(llvm::IntEQ, lhs_addr, rhs_addr),
602+
bcx.icmp(llvm::IntEQ, lhs_extra, rhs_extra)
603+
)
604+
}
605+
mir::BinOp::Ne => {
606+
bcx.or(
607+
bcx.icmp(llvm::IntNE, lhs_addr, rhs_addr),
608+
bcx.icmp(llvm::IntNE, lhs_extra, rhs_extra)
609+
)
610+
}
611+
mir::BinOp::Le | mir::BinOp::Lt |
612+
mir::BinOp::Ge | mir::BinOp::Gt => {
613+
// a OP b ~ a.0 STRICT(OP) b.0 | (a.0 == b.0 && a.1 OP a.1)
614+
let (op, strict_op) = match op {
615+
mir::BinOp::Lt => (llvm::IntULT, llvm::IntULT),
616+
mir::BinOp::Le => (llvm::IntULE, llvm::IntULT),
617+
mir::BinOp::Gt => (llvm::IntUGT, llvm::IntUGT),
618+
mir::BinOp::Ge => (llvm::IntUGE, llvm::IntUGT),
619+
_ => bug!(),
620+
};
621+
622+
bcx.or(
623+
bcx.icmp(strict_op, lhs_addr, rhs_addr),
624+
bcx.and(
625+
bcx.icmp(llvm::IntEQ, lhs_addr, rhs_addr),
626+
bcx.icmp(op, lhs_extra, rhs_extra)
627+
)
628+
)
629+
}
630+
_ => {
631+
bug!("unexpected fat ptr binop");
544632
}
545633
}
546634
}

‎src/librustc_trans/partitioning.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -267,14 +267,14 @@ pub fn partition<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>,
267267
let mut initial_partitioning = place_root_translation_items(scx,
268268
trans_items);
269269

270-
debug_dump(tcx, "INITIAL PARTITONING:", initial_partitioning.codegen_units.iter());
270+
debug_dump(scx, "INITIAL PARTITONING:", initial_partitioning.codegen_units.iter());
271271

272272
// If the partitioning should produce a fixed count of codegen units, merge
273273
// until that count is reached.
274274
if let PartitioningStrategy::FixedUnitCount(count) = strategy {
275275
merge_codegen_units(&mut initial_partitioning, count, &tcx.crate_name[..]);
276276

277-
debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter());
277+
debug_dump(scx, "POST MERGING:", initial_partitioning.codegen_units.iter());
278278
}
279279

280280
// In the next step, we use the inlining map to determine which addtional
@@ -284,7 +284,7 @@ pub fn partition<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>,
284284
let post_inlining = place_inlined_translation_items(initial_partitioning,
285285
inlining_map);
286286

287-
debug_dump(tcx, "POST INLINING:", post_inlining.0.iter());
287+
debug_dump(scx, "POST INLINING:", post_inlining.0.iter());
288288

289289
// Finally, sort by codegen unit name, so that we get deterministic results
290290
let mut result = post_inlining.0;
@@ -552,7 +552,7 @@ fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString
552552
index)[..])
553553
}
554554

555-
fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
555+
fn debug_dump<'a, 'b, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>,
556556
label: &str,
557557
cgus: I)
558558
where I: Iterator<Item=&'b CodegenUnit<'tcx>>,
@@ -561,10 +561,21 @@ fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
561561
if cfg!(debug_assertions) {
562562
debug!("{}", label);
563563
for cgu in cgus {
564+
let symbol_map = SymbolMap::build(scx, cgu.items
565+
.iter()
566+
.map(|(&trans_item, _)| trans_item));
564567
debug!("CodegenUnit {}:", cgu.name);
565568

566569
for (trans_item, linkage) in &cgu.items {
567-
debug!(" - {} [{:?}]", trans_item.to_string(tcx), linkage);
570+
let symbol_name = symbol_map.get_or_compute(scx, *trans_item);
571+
let symbol_hash_start = symbol_name.rfind('h');
572+
let symbol_hash = symbol_hash_start.map(|i| &symbol_name[i ..])
573+
.unwrap_or("<no hash>");
574+
575+
debug!(" - {} [{:?}] [{}]",
576+
trans_item.to_string(scx.tcx()),
577+
linkage,
578+
symbol_hash);
568579
}
569580

570581
debug!("");

‎src/librustc_typeck/variance/README.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
## Variance of type and lifetime parameters
2+
13
This file infers the variance of type and lifetime parameters. The
24
algorithm is taken from Section 4 of the paper "Taming the Wildcards:
35
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;
5254
variance of C must be at most covariant *and* contravariant. All of these
5355
results are based on a variance lattice defined as follows:
5456

55-
* Top (bivariant)
56-
- +
57-
o Bottom (invariant)
57+
* Top (bivariant)
58+
- +
59+
o Bottom (invariant)
5860

59-
Based on this lattice, the solution V(A)=+, V(B)=-, V(C)=o is the
61+
Based on this lattice, the solution `V(A)=+`, `V(B)=-`, `V(C)=o` is the
6062
optimal solution. Note that there is always a naive solution which
6163
just declares all variables to be invariant.
6264

@@ -68,11 +70,11 @@ take the form:
6870
V(X) <= Term
6971
Term := + | - | * | o | V(X) | Term x Term
7072

71-
Here the notation V(X) indicates the variance of a type/region
73+
Here the notation `V(X)` indicates the variance of a type/region
7274
parameter `X` with respect to its defining class. `Term x Term`
7375
represents the "variance transform" as defined in the paper:
7476

75-
If the variance of a type variable `X` in type expression `E` is `V2`
77+
> If the variance of a type variable `X` in type expression `E` is `V2`
7678
and the definition-site variance of the [corresponding] type parameter
7779
of a class `C` is `V1`, then the variance of `X` in the type expression
7880
`C<E>` is `V3 = V1.xform(V2)`.
@@ -267,7 +269,7 @@ expressions -- must be invariant with respect to all of their
267269
inputs. To see why this makes sense, consider what subtyping for a
268270
trait reference means:
269271

270-
<T as Trait> <: <U as Trait>
272+
<T as Trait> <: <U as Trait>
271273

272274
means that if I know that `T as Trait`, I also know that `U as
273275
Trait`. Moreover, if you think of it as dictionary passing style,
@@ -291,9 +293,9 @@ impl<T> Identity for T { type Out = T; ... }
291293
Now if I have `<&'static () as Identity>::Out`, this can be
292294
validly derived as `&'a ()` for any `'a`:
293295

294-
<&'a () as Identity> <: <&'static () as Identity>
295-
if &'static () < : &'a () -- Identity is contravariant in Self
296-
if 'static : 'a -- Subtyping rules for relations
296+
<&'a () as Identity> <: <&'static () as Identity>
297+
if &'static () < : &'a () -- Identity is contravariant in Self
298+
if 'static : 'a -- Subtyping rules for relations
297299

298300
This change otoh means that `<'static () as Identity>::Out` is
299301
always `&'static ()` (which might then be upcast to `'a ()`,

‎src/librustdoc/clean/inline.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,8 @@ pub fn build_impls<'a, 'tcx>(cx: &DocContext,
301301
tcx.lang_items.char_impl(),
302302
tcx.lang_items.str_impl(),
303303
tcx.lang_items.slice_impl(),
304-
tcx.lang_items.slice_impl(),
305-
tcx.lang_items.const_ptr_impl()
304+
tcx.lang_items.const_ptr_impl(),
305+
tcx.lang_items.mut_ptr_impl(),
306306
];
307307

308308
for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) {

‎src/libstd/io/buffered.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ impl<R: Seek> Seek for BufReader<R> {
231231
if let SeekFrom::Current(n) = pos {
232232
let remainder = (self.cap - self.pos) as i64;
233233
// it should be safe to assume that remainder fits within an i64 as the alternative
234-
// means we managed to allocate 8 ebibytes and that's absurd.
234+
// means we managed to allocate 8 exbibytes and that's absurd.
235235
// But it's not out of the realm of possibility for some weird underlying reader to
236236
// support seeking by i64::min_value() so we need to handle underflow when subtracting
237237
// remainder.

‎src/libstd/sys/common/net.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
2929
#[cfg(not(any(target_os = "dragonfly", target_os = "freebsd",
3030
target_os = "ios", target_os = "macos",
3131
target_os = "openbsd", target_os = "netbsd",
32-
target_os = "solaris", taget_os = "haiku")))]
32+
target_os = "solaris", target_os = "haiku")))]
3333
use sys::net::netc::IPV6_ADD_MEMBERSHIP;
3434
#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
3535
target_os = "ios", target_os = "macos",

‎src/test/codegen/enum-bounds-check.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: -O
12+
13+
#![crate_type = "lib"]
14+
15+
pub enum Foo {
16+
A, B
17+
}
18+
19+
// CHECK-LABEL: @lookup
20+
#[no_mangle]
21+
pub fn lookup(buf: &[u8; 2], f: Foo) -> u8 {
22+
// CHECK-NOT: panic_bounds_check
23+
buf[f as usize]
24+
}

‎src/test/compile-fail/E0002.rs renamed to ‎src/test/compile-fail/E0004-2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@
1111
fn main() {
1212
let x = Some(1);
1313

14-
match x { } //~ ERROR E0002
14+
match x { } //~ ERROR E0004
1515
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
12+
// Test that changing what a `type` points to does not go unnoticed.
13+
14+
// compile-flags: -Z query-dep-graph
15+
16+
#![feature(rustc_attrs)]
17+
#![allow(dead_code)]
18+
#![allow(unused_variables)]
19+
20+
fn main() { }
21+
22+
23+
#[rustc_if_this_changed]
24+
type TypeAlias = u32;
25+
26+
#[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK
27+
struct Struct {
28+
x: TypeAlias,
29+
y: u32
30+
}
31+
32+
#[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK
33+
enum Enum {
34+
Variant1(TypeAlias),
35+
Variant2(i32)
36+
}
37+
38+
#[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK
39+
trait Trait {
40+
fn method(&self, _: TypeAlias);
41+
}
42+
43+
struct SomeType;
44+
45+
#[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK
46+
impl SomeType {
47+
fn method(&self, _: TypeAlias) {}
48+
}
49+
50+
#[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK
51+
type TypeAlias2 = TypeAlias;
52+
53+
#[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK
54+
fn function(_: TypeAlias) {
55+
56+
}

‎src/test/incremental/hashes/function_interfaces.rs

Lines changed: 400 additions & 0 deletions
Large diffs are not rendered by default.

‎src/test/mir-opt/deaggregator_test.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ fn main() {}
2626
// _2 = _1;
2727
// _3 = _2;
2828
// _0 = Baz { x: _3, y: const F32(0), z: const false };
29-
// goto -> bb1;
29+
// return;
3030
// }
3131
// END rustc.node13.Deaggregator.before.mir
3232
// START rustc.node13.Deaggregator.after.mir
@@ -36,6 +36,6 @@ fn main() {}
3636
// (_0.0: usize) = _3;
3737
// (_0.1: f32) = const F32(0);
3838
// (_0.2: bool) = const false;
39-
// goto -> bb1;
39+
// return;
4040
// }
4141
// END rustc.node13.Deaggregator.after.mir

‎src/test/mir-opt/deaggregator_test_enum.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ fn main() {
3131
// _2 = _1;
3232
// _3 = _2;
3333
// _0 = Baz::Foo { x: _3 };
34-
// goto -> bb1;
34+
// return;
3535
// }
3636
// END rustc.node10.Deaggregator.before.mir
3737
// START rustc.node10.Deaggregator.after.mir
@@ -40,6 +40,6 @@ fn main() {
4040
// _3 = _2;
4141
// ((_0 as Foo).0: usize) = _3;
4242
// discriminant(_0) = 1;
43-
// goto -> bb1;
43+
// return;
4444
// }
4545
// END rustc.node10.Deaggregator.after.mir

‎src/test/mir-opt/storage_ranges.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,6 @@ fn main() {
3838
// _0 = ();
3939
// StorageDead(_6);
4040
// StorageDead(_1);
41-
// goto -> bb1;
42-
// }
43-
//
44-
// bb1: {
4541
// return;
4642
// }
4743
// END rustc.node4.TypeckMir.before.mir

‎src/test/run-make/stable-symbol-names/Makefile

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
-include ../tools.mk
22

3-
# This test case makes sure that monomorphizations of the same function with the
4-
# same set of generic arguments will have the same symbol names when
5-
# instantiated in different crates.
3+
# The following command will:
4+
# 1. dump the symbols of a library using `nm`
5+
# 2. extract only those lines that we are interested in via `grep`
6+
# 3. from those lines, extract just the symbol name via `sed`
7+
# (symbol names always start with "_ZN" and end with "E")
8+
# 4. sort those symbol names for deterministic comparison
9+
# 5. write the result into a file
610

711
dump-symbols = nm "$(TMPDIR)/lib$(1).rlib" \
8-
| grep "some_test_function" \
9-
| sed "s/^[0-9a-f]\{8,16\}/00000000/" \
12+
| grep -E "some_test_function|Bar|bar" \
13+
| sed "s/.*\(_ZN.*E\).*/\1/" \
1014
| sort \
1115
> "$(TMPDIR)/$(1).nm"
1216

‎src/test/run-make/stable-symbol-names/stable-symbol-names1.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,20 @@
1010

1111
#![crate_type="rlib"]
1212

13+
pub trait Foo {
14+
fn foo<T>();
15+
}
16+
17+
pub struct Bar;
18+
19+
impl Foo for Bar {
20+
fn foo<T>() {}
21+
}
22+
23+
pub fn bar() {
24+
Bar::foo::<Bar>();
25+
}
26+
1327
pub fn some_test_function<T>(t: T) -> T {
1428
t
1529
}

‎src/test/run-make/stable-symbol-names/stable-symbol-names2.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,9 @@ pub fn user() {
1818
let x = 2u64;
1919
stable_symbol_names1::some_test_function(&x);
2020
}
21+
22+
pub fn trait_impl_test_function() {
23+
use stable_symbol_names1::*;
24+
Bar::foo::<Bar>();
25+
bar();
26+
}

0 commit comments

Comments
 (0)
Please sign in to comment.